/**********************************************************************
 
	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	"utils.h"
#include	"long_char.h"
#include	"lc_encode.h"
#include	"text_render.h"
#include	"tr_lang.h"


TR_ERROR
make_en_render(TR_SEQUENCE * ,TR_CHAR_INFO *);
void
setup_en_render(TR_LANG * lang,int type,void * work);
void *
get_en_render(TR_LANG *,void *);
void
free_en_work(void *);

TR_LANG en_render = {
	"en",
	VSD_H_L2R,0,
	setup_en_render,
	get_en_render,
	free_en_work,
	make_en_render,
	0
};

void
free_en_work(void * _w)
{
EN_WORK * w;
	w = _w;
	if ( w->delim )
		d_f_ree(w->delim);
	if ( w->space )
		d_f_ree(w->space);
	d_f_ree(w);
}


void *
get_en_render(TR_LANG * lang,void * w)
{
EN_WORK * wp;
EN_WORK * out;
	if ( w )
		out = w;
	else	out = d_calloc(sizeof(*out),1);
	wp = lang->work;
	*out = *wp;
	if ( wp->delim )
		out->delim = ll_copy_str(wp->delim);
	else	out->delim = 0;
	if ( wp->space )
		out->space = ll_copy_str(
				wp->space);
	else	out->space = 0;
	return out;
}

void
setup_en_render(TR_LANG * lang,int type,void * work)
{
EN_WORK * w, * wp;
	switch ( type ) {
	case TRT_INIT_BIN:
		w = (EN_WORK*)work;
		if ( lang->work )
			free_en_work(lang->work);
		lang->work = d_alloc(sizeof(*w));
		wp = lang->work;
		memset(wp,0,sizeof(*wp));
		if ( w == 0 )
			break;
		wp->space = ll_copy_str(w->space);
		wp->delim = ll_copy_str(w->delim);
		break;
	default:
		er_panic("setup_en_render(1)");
	}
}

int
in_table(L_CHAR ch,L_CHAR * list)
{
	if ( list == 0 )
		return -1;
	for ( ; *list ; list ++ )
		if ( cmp_l_code(ch,*list) == 0 )
			return 0;
	return -1;
}

TR_ERROR
make_en_render(TR_SEQUENCE * sq,TR_CHAR_INFO * ci)
{
TR_ERROR e;
TR_PTR p;
TR_CHAR_ELEMENT * el;
int start,space;
EN_WORK * wp;
TR_PTR_STACK *pos_stack;
TR_CHAR_INFO target;
TR_LL_CTL	ctl;
	start = 1;
	space = 0;
	ci->lang_line->dir = VSD_H_L2R;
	pos_stack = 0;
	_tr_push_ptr_stack(&pos_stack,ci->p);
	(*sq->box_op->start_lang_line_op)(sq,ci);
	for ( p = ci->p ; ; ) {
		e.code = TRE_OK;
		e.subcode = TRE_OK_NONE;
		if ( p.buf == 0 )
			break;
		if ( p.ptr >= p.buf->buf_len )
			break;
		_tr_get_char_info(&target,sq,p);
		if ( _tr_lang_area_cmp_ci(sq,ci,&target) )
			break;
		el = &p.buf->element_buf[p.ptr];
		if ( start ) {
			space = 0;
			wp = ci->lang->work;
			if ( in_table(el->ch,wp->space) == 0 )
				goto next;
		}
		if ( in_table(el->ch,wp->space) == 0 || 
				in_table(el->ch,wp->delim) == 0 )
			space = 1;
		else	space = 0;
		ctl.h.cmd = LLC_WEIGHT;
		ctl.w.weight = TRW_RABER;
		if ( space == 1 )
			e = (*sq->box_op->lang_line_ctl)(sq,ci,&ctl);
		else {
			e.code = TRE_OK;
			e.subcode = TRE_OK_NONE;
		}
		if ( e.code == TRE_OK )
			e = (*sq->box_op->put_box_line)(sq,ci,p,el);
	ctl_err:
		switch ( e.code ) {
		case TRE_INSERT_CHAR:
		/* insert_char: */
			for ( ; ; ) {
				p = _tr_pop_ptr_stack(&pos_stack);
				e = (*sq->box_op->pop_box_line)(sq,ci,p);
				if ( e.code == TRE_OK )
					break;
			}
			e.subcode = TRE_OK_NEW_LINE;
			goto end;
		case TRE_INSERT_LINE:
			p = ci->p;
			goto end;
		case TRE_OK:
			if ( space )
				_tr_push_ptr_stack(&pos_stack,p);
			break;
		}
		if ( space == 1 ) {
			e = (*sq->box_op->lang_line_ctl)(sq,ci,&ctl);
			if ( e.code != TRE_OK )
				goto ctl_err;
		}
	next:
		start = 0;
		p = tr_ptr_next(p);
	}
end:
	ci->lang_line->end = p;
	e = _tr_stop_lang_line_op(e,sq,ci);
	_tr_free_ptr_stack(&pos_stack);
	return e;
}

