/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include	"memory_debug.h"
#include	"lc_encode.h"
#include	"tr_html.h"

XLISP_ENV * html_env;

XL_SEXP *
tr_html_sexp(TR_HTML_INFO *,XL_SEXP *);

void
init_tr_html()
{
	html_env = new_env(0);
	set_env(gblisp_top_env1,l_string(std_cm,"___HTML"),
		get_env(html_env));
	init_html_font(html_env);
	init_html_br(html_env);
	init_html_center(html_env);
	init_html_a(html_env);
}


void
tr_push_attr_stack(TR_HTML_INFO * info)
{
TR_HTML_ATTR_STACK * s;
	s = d_alloc(sizeof(*s));
	if ( info->d.attr_stack ) {
		memcpy(s,info->d.attr_stack,sizeof(*s));
		s->next = info->d.attr_stack;
		s->attr = _tr_copy_attr(info->d.attr_stack->attr);
		info->d.attr_stack = s;
	}
	else {
		s->next = 0;
		s->attr = 0;
		info->d.attr_stack = s;
	}
}

void
tr_pop_attr_stack(TR_HTML_INFO * info)
{
TR_HTML_ATTR_STACK * s;
	if ( info->d.attr_stack ) {
		s = info->d.attr_stack;
		info->d.attr_stack = s->next;
		_tr_free_attr(s->attr);
		d_f_ree(s);
	}
}

TR_HTML_INFO *
tr_get_html_info(XLISP_ENV * env)
{
XL_SEXP * p;
	p = eval(env,n_get_symbol("___html_info"));
	return p->ptr.ptr;
}


void
tr_html_string_data(TR_HTML_INFO * inf,L_CHAR * str,int len)
{
	if ( len < 0 )
		len = l_strlen(str);
	inf->d.p = tr_insert_string(
		inf->d.sq,
		inf->d.p,
		len,
		inf->d.attr_stack->ws,
		inf->d.attr_stack->attr,
		0,
		inf->d.attr_stack->size,
		str);
	inf->d.last_output = str[len-1];
}

XL_SEXP *
tr_html_pair_symbol(TR_HTML_INFO * inf,XL_SEXP * s)
{
	return eval(inf->d.env,s);
}

XL_SEXP *
tr_html_pair_non_symbol(TR_HTML_INFO * inf,XL_SEXP * s)
{
XL_SEXP * ret;
	for ( ; get_type(s) == XLT_PAIR ; s = cdr(s) ) {
		ret = tr_html_sexp(inf,car(s));
		if ( get_type(ret) == XLT_ERROR )
			return ret;
	}
	return ret;
}


XL_SEXP *
tr_html_pair(TR_HTML_INFO * inf,XL_SEXP * s)
{
XL_SEXP * cmd;
	cmd = car(s);
	if ( get_type(cmd) != XLT_SYMBOL )
		return tr_html_pair_non_symbol(inf,s);
	else	return tr_html_pair_symbol(inf,s);
}


XL_SEXP *
tr_html_integer(TR_HTML_INFO * inf,XL_SEXP * s)
{
char * buf;
int len;
	if ( s->integer.unit ) {
		len = l_strlen(s->integer.unit)*5;
		buf = d_alloc(50 + len);
		sprintf(buf, I64_FORMAT "%s",s->integer.data,
			n_string(std_cm,s->integer.unit));
	}
	else {
		buf = d_alloc(50);
		sprintf(buf,I64_FORMAT,s->integer.data);
	}
	tr_html_string_data(inf,l_string(std_cm,buf),-1);
	d_f_ree(buf);
	return 0;
}

XL_SEXP *
tr_html_float(TR_HTML_INFO * inf,XL_SEXP * s)
{
char * buf;
int len;
	if ( s->floating.unit ) {
		len = l_strlen(s->floating.unit)*5;
		buf = d_alloc(100 + len);
		sprintf(buf,"%f%s",s->floating.data,
			n_string(std_cm,s->floating.unit));
	}
	else {
		buf = d_alloc(100);
		sprintf(buf,"%f",s->floating.data);
	}
	tr_html_string_data(inf,l_string(std_cm,buf),-1);
	d_f_ree(buf);
	return 0;
}

XL_SEXP *
tr_html_string(TR_HTML_INFO * inf,XL_SEXP * s)
{
	tr_html_string_data(inf,s->string.data,-1);
	return 0;
}


XL_SEXP *
tr_html_sexp(TR_HTML_INFO * info,XL_SEXP * s)
{
	switch ( get_type(s) ) {
	case XLT_NULL:
		return 0;
	case XLT_PAIR:
		return tr_html_pair(info,s);
	case XLT_INTEGER:
		return tr_html_integer(info,s);
	case XLT_FLOAT:
		return tr_html_float(info,s);
	case XLT_STRING:
		return tr_html_string(info,s);
	default:
		return 0;
	}
}

void
tr_html_roll_paper(TR_HTML_INFO * info,XL_SEXP * s)
{

	tr_new_box(info->d.sq,0,&info->attr);
	tr_html_sexp(info,s);
}


void
tr_html_cut_paper(TR_HTML_INFO * info,XL_SEXP * s)
{
	er_panic("not support");
}


void
tr_html(TR_HTML_INFO
 * info,XL_SEXP * s,int pri)
{


	memset(&info->d,0,sizeof(info->d));

	gc_push(0,0,"tr_html");

	info->d.env = new_env(info->base_env);
	set_env(info->d.env,l_string(std_cm,"___html_info"),get_ptr(info,0));
	tr_push_attr_stack(info);
	info->d.attr_stack->ws = info->default_ws;
	info->d.attr_stack->size = info->default_size;
	info->d.sq = tr_new_sequence(info->box_op,pri,info->sq_work);

	tr_html_roll_paper(info,s);

	gc_pop(0,0);
}

void
tr_close_html(TR_HTML_INFO * info)
{
	tr_close_sequence(info->d.sq);
}

