/**********************************************************************
 
	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.

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

#ifndef ___TEXT_RENDER_H___
#define ___TEXT_RENDER_H___

#include	"graph.h"
#include	"long_char.h"
#include	"avt.h"
#include	"utils.h"

#define TR_RING_INIT(n)	\
	n->next = n->prev = n;
#define TR_RING_INSERT(b,n) \
	n->prev = b;		\
	n->next = b->next;	\
	n->prev->next = n;	\
	n->next->prev = n;
#define TR_RING_DELETE(n) \
	n->prev->next = n->next;	\
	n->next->prev = n->prev;

#define CTL_CODE(ch)	(	\
		(ch) == '\r' &&	\
		(ch) == '\n'	\
	)

/* dirty flags */

#define TRF_DIRTY_INS_DEL_CHAR		0x00000001
#define TRF_DIRTY_CHANGE_METRIC		0x00000002
#define TRF_DIRTY_LINE_PIXELS		0x00000004
#define TRF_DIRTY_DOC_DIR_PIXELS	0x00000008

typedef struct tr_error {
	int		code;
#define TRE_OK			0
#define TRE_INSERT_CHAR		(-1)
#define TRE_INSERT_LINE		(-2)
	int		subcode;
	/* ok subcode */
#define TRE_OK_NONE		0
#define TRE_OK_NEW_LINE		1
} TR_ERROR;

typedef struct tr_ptr {
	struct tr_char_buf *	buf;
	int			ptr;
} TR_PTR;

typedef struct tr_llc_header {
	int		cmd;
#define LLC_WEIGHT	1
#define LLC_RETURN_CODE	2
} TR_LLC_HEADER;

typedef struct tr_llc_weight {
	TR_LLC_HEADER	h;
	int		weight;
#define TRW_ZERO	0
#define TRW_DONTCARE	1
#define TRW_RABER	2
} TR_LLC_WEIGHT;

typedef struct tr_llc_return_code {
	TR_LLC_HEADER	h;
	L_CHAR		ch;
	int		dir;
} TR_LLC_RETURN_CODE;

typedef union tr_ll_ctl {
	TR_LLC_HEADER		h;
	TR_LLC_WEIGHT		w;
	TR_LLC_RETURN_CODE	rc;
} TR_LL_CTL;

typedef struct tr_attr_header {
	union tr_attr *		next;
	unsigned short		type;
#define TRAT_LINE_ATTR		1
#define TRAT_ORNAMENT		2
#define TRAT_REFERENCE		3
#define TRAT_COLOR		4
#define TRAT_MAX		5
} TR_ATTR_HEADER;

typedef struct tra_ornament {
	TR_ATTR_HEADER		h;
	unsigned short		flags;
} TRA_ORNAMENT;

typedef struct tra_referenece {
	TR_ATTR_HEADER		h;
	short			id;
} TRA_REFERENECE;


typedef struct tr_line_attr {
	char			flags;
#define TRLF_ALIGN		0x01
#define TRLF_DEFAULT_DIR	0x02
#define TRLF_PITCH		0x04
#define TRLF_ALL		0x07
	char			align;
#define TRT_CENTER		1
#define TRT_CAPITA_BASIS_ALL	2
#define TRT_LINE_START		3
#define TRT_LINE_END		4
#define TRT_CAPITA_BASIS	5
	short			default_dir;
	short			pitch;
} TR_LINE_ATTR;

typedef struct tra_line_attr {
	TR_ATTR_HEADER		h;
	TR_LINE_ATTR		attr;
} TRA_LINE_ATTR;

typedef struct tra_color {
	TR_ATTR_HEADER		h;
	int			color;
} TRA_COLOR;

typedef struct tra_short_data {
	TR_ATTR_HEADER		h;
	short			data;
} TRA_SHORT_DATA;

typedef struct tra_int_data {
	TR_ATTR_HEADER		h;
	int			data;
} TRA_INT_DATA;

typedef union tr_attr {
	TR_ATTR_HEADER		h;

	TRA_SHORT_DATA		sd;
	TRA_INT_DATA		id;

	TRA_ORNAMENT		o;
	TRA_REFERENECE		r;
	TRA_LINE_ATTR		la;
	TRA_COLOR		c;
} TR_ATTR;

typedef struct tr_attr_table {
	int		size;
	TR_ATTR *	(*copy)(struct tr_attr_table *,TR_ATTR*);
	void		(*free)(TR_ATTR*);
	int		(*cmp)(TR_ATTR*,TR_ATTR*);
} TR_ATTR_TABLE;



typedef struct tr_ptr_stack {
	struct tr_ptr_stack * 	next;
	TR_PTR			p;
} TR_PTR_STACK;

typedef struct tr_l_char_tbl2 {
	L_CHAR		from;
	L_CHAR		to;
	struct tr_lang * lang;
} TR_L_CHAR_TBL2;

typedef struct tr_l_char_tbl2_header {
	TR_L_CHAR_TBL2 *		tbl;
	struct tr_l_char_tbl2_header *	inheritance;
} TR_L_CHAR_TBL2_HEADER;

typedef struct tr_l_char_tbl {
	L_CHAR			ch;
	L_CHAR			mask;
	struct tr_lang *	lang;
	TR_L_CHAR_TBL2_HEADER *	tbl;
} TR_L_CHAR_TBL;


typedef struct tr_lc_tbl2_cache {
	TR_L_CHAR_TBL2 *		body;
	struct tr_lc_tbl2_cache *	next;
	struct tr_lc_tbl2_cache *	prev;
} TR_LC_TBL2_CACHE;

typedef struct tr_lc_tbl_cache {
	TR_L_CHAR_TBL *			body;
	struct tr_lc_tbl_cache *	next;
	struct tr_lc_tbl_cache *	prev;
	TR_LC_TBL2_CACHE *		cache;
} TR_LC_TBL_CACHE;

typedef struct tr_metric {
	I_RECT			size;
	short			desent;
	short			asent;
	I_POINT			end;
} TR_METRIC;

typedef struct tr_char_metric {
	TR_METRIC		metric;
	short			px_start;
} TR_CHAR_METRIC;


typedef struct tr_char_element {
	L_CHAR			ch;
	union {
		int				type;
				// if type == -1 -> obj
		struct {
			int			size;
			LC_WRITING_STYLE *	ws;
		}	ws;
		struct {
			int			type;
			void *			obj;
		}	obj;
	} d;
	TR_ATTR *		attr;
} TR_CHAR_ELEMENT;

typedef struct tr_char_buf {
	struct tr_char_buf *	next;
	struct tr_char_buf *	prev;

	int			seq;
	int			buf_len;
	TR_CHAR_ELEMENT *	element_buf;
	struct tr_lang_line *	lang_line;
} TR_CHAR_BUF;

typedef struct tr_element {
	struct tr_element *	next;
	struct tr_element *	prev;
	struct tr_element *	ll_next;
	TR_METRIC		metric;
	short			cr;
	void *			work;
} TR_ELEMENT;

typedef struct tr_lang_line {
	struct tr_lang_line *	box_next;
//	int			no;
	TR_PTR			start;
	TR_PTR			end;
	int			dir;

	TR_ELEMENT *		element_list;
	struct tr_box_line *	box_line;
	struct tr_lang_area *	lang_area;
	struct tr_lang_line *	area_next;
} TR_LANG_LINE;

typedef struct tr_box_line {
	struct tr_box_line *	next;
	struct tr_box *		box;
	TR_LINE_ATTR		attr;
	short			height;
	short			base_offset;

	short			assent;
	short			desent;
	int			doc_start_offset;
	int			pixels;
	TR_LANG_LINE *		lang_list;
	TR_ELEMENT *		el_head;

	void *			work;
} TR_BOX_LINE;

typedef struct tr_box_attr {
	TR_LINE_ATTR		default_lattr;
	int			max_line_pixels;
		/* = -1 : not fix */
	int			max_doc_dir_pixels;
		/* max_pixels = -1 : not fix */
} TR_BOX_ATTR;

typedef struct tr_box {
	struct tr_box *		next;
	struct tr_box *		prev;

	int			seq;
	struct tr_sequence *	sequence;
	int			dirty_flags;
	void *			work;
	int			start_px_offset;
	struct tr_box_line *	line_list;
	TR_BOX_ATTR		attr;

	struct tr_box *		dirty_next;
} TR_BOX;

typedef struct tr_lang_area {
	struct tr_lang *	op;
	struct tr_lang_area *	next;
	struct tr_lang_area *	prev;
	TR_LANG_LINE *		line_list;
	int			dir;
} TR_LANG_AREA;


typedef struct tr_unmapping_char {
	struct tr_unmapping_char *	next;
	TR_PTR				p;
	int				ok_subcode;
} TR_UNMAPPING_CHAR;

typedef struct tr_dirty {
	TR_UNMAPPING_CHAR	umc;
	TR_BOX *		box;
} TR_DIRTY;

typedef struct tr_reference {
	short			id;
	L_CHAR *		data;
} TR_REFERENCE;


typedef struct trl_context {
	struct trl_lang_list *	used;
} TRL_CONTEXT;


typedef struct tr_sequence {
	struct tr_box_op *	box_op;
	int			lock;
	char * 			lock_file;
	int			lock_line;
	int			thread;
	int			pri;
	TR_BOX *		box_ring;
	TR_CHAR_BUF *		char_buf_ring;
	TR_LANG_AREA *		lang_area_ring;
	TR_UNMAPPING_CHAR *	unmapping_char;
	TR_BOX *		dirty_box;

	short			ref_id;
	AVT_NODE  *		ref;

	struct trl_context	lang_ctx;

	void *			work;

	void *			callback_arg;
	void			(*callback)(
			struct tr_sequence * sq,void *);

	WAITSYNC_SERVER		waitsync;
	struct tr_sequence *	next;
} TR_SEQUENCE;

typedef struct tr_char_info {
	TR_PTR			p;
	struct tr_lang *	lang;
	TR_LANG_LINE *		lang_line;
	TR_LANG_AREA *		lang_area;
	TR_BOX_LINE *		box_line;
	TR_BOX *		box;
} TR_CHAR_INFO;

typedef struct tr_lang_area_info {
	TR_PTR			start_char;
	TR_PTR			end_char;
	TR_LANG_LINE *		start_lang_line;
	TR_LANG_LINE *		end_lang_line;
	TR_BOX_LINE *		start_box_line;
	TR_BOX_LINE *		end_box_line;
	TR_BOX *		start_box;
	TR_BOX *		end_box;

	TR_BOX_LINE *		phys_start_box_line;
	TR_BOX_LINE *		phys_end_box_line;
	TR_BOX *		phys_start_box;
	TR_BOX *		phys_end_box;
} TR_LANG_AREA_INFO;

#define TRF_WHERE_TOP	0
#define TRF_WHERE_LAST	1
#define TRF_WHERE_NEXT	2
#define TRF_WHERE_PREV	3


typedef struct tr_lang {
	char			lang[4];
	short			dir_flags;
	short			sub_dir_flags;
	void	(*setup_lang)(struct tr_lang *,int,void *);
	void *	(*get_setup)(struct tr_lang *,void *);
#define TRT_INIT_BIN	1
#define TRT_INIT_SEXP	2
	void	(*free_work)(void *);
	TR_ERROR (*make_lang_line)(
		struct tr_sequence *,
		struct tr_char_info *);
	void *			work;
	struct tr_lang *	next;
} TR_LANG;


typedef struct trl_lang_list {
	struct trl_lang_list *	next;
	TR_LANG *		lang;
	int			ref;
} TRL_LANG_LIST;


typedef struct tr_obj_op {
	void *	(*copy_obj)(void*);
	struct tr_metric
		(*get_obj_metric)(void*,int dir);
	void	(*free_obj)(void*);
	void	(*gc_obj)(void*);
} TR_OBJ_OP;


typedef struct tr_box_op {
	int	(*new_sequence)(struct tr_sequence *,void *);

	void	(*init_thread)(struct tr_sequence*);
	void	(*exit_thread)(struct tr_sequence*);

	void	(*unmapping_element)(struct tr_element *);

	void	(*new_box_line)(struct tr_sequence *,struct tr_box_line*);
	void	(*free_box_line)(struct tr_sequence *,struct tr_box_line*);
	void	(*new_box)(struct tr_sequence *,struct tr_box*);
	void	(*free_box)(struct tr_sequence *,struct tr_box*);

	void	(*start_lang_line_op)(
			struct tr_sequence *,
			struct tr_char_info *);
	TR_ERROR (*_stop_lang_line_op)(
			struct tr_sequence *,
			struct tr_char_info *);
	TR_ERROR (*put_box_line)(
			struct tr_sequence * sq,
			struct tr_char_info *,
			TR_PTR,
			struct tr_char_element * el);
	TR_ERROR (*pop_box_line)(
			struct tr_sequence * sq,
			struct tr_char_info *,
			TR_PTR);
	TR_ERROR (*lang_line_ctl)(
			struct tr_sequence * sq,
			struct tr_char_info *,
			TR_LL_CTL *);
	void	(*gc_tr)(TR_SEQUENCE*);

	void	(*waitsync)(TR_SEQUENCE *,WAITSYNC_CLIENT*,int);

	struct {
		short a;short b;
	} dummy;
	TR_OBJ_OP *	obj_op;
} TR_BOX_OP;


TR_SEQUENCE *
tr_new_sequence(TR_BOX_OP * op,int pri,void * work);
TR_BOX *
tr_new_box(TR_SEQUENCE *,TR_BOX *,TR_BOX_ATTR*);

TR_PTR
tr_insert_string(
	TR_SEQUENCE * sq,
	TR_PTR p_ptr,
	int len,
	LC_WRITING_STYLE * ws,
	TR_ATTR	* attr,
	void *obj,
	int size,
	L_CHAR * str);
TR_PTR
tr_delete_string(
	TR_SEQUENCE * sq,
	TR_PTR ptr,
	int len);

TR_PTR tr_ptr_next(TR_PTR);
TR_PTR tr_ptr_prev(TR_PTR);
TR_LANG_LINE *
_tr_next_lang_line(TR_LANG_LINE *);
TR_LANG_LINE *
_tr_prev_lang_line(TR_LANG_LINE *);
void
_tr_push_ptr_stack(TR_PTR_STACK ** st,TR_PTR p);
TR_PTR
_tr_pop_ptr_stack(TR_PTR_STACK ** st);
void
_tr_free_ptr_stack(TR_PTR_STACK ** st);
TR_ERROR
_tr_stop_lang_line_op(TR_ERROR,TR_SEQUENCE *,TR_CHAR_INFO *);
TR_ATTR *
_tr_copy_attr(TR_ATTR *);
void
_tr_free_attr(TR_ATTR *);
void
_tr_set_attr_int_data(TR_ATTR **,int,int);
void
_tr_set_attr_reference(TR_SEQUENCE *sq,TR_ATTR ** ap,L_CHAR * ref);
TR_ERROR
_tr_new_element(TR_ELEMENT ** ,TR_SEQUENCE * sq,TR_LANG_LINE * ll);
void
_tr_acc_line_attr(TR_LINE_ATTR * a,TR_ATTR * attr);
void
_tr_set_line_attr(TR_LINE_ATTR * la,TR_ATTR ** ap);
void
_tr_set_default_lattr(TR_LINE_ATTR * a);
TR_ATTR *
_tr_get_attr(TR_ATTR * a,int type);
void
tr_wait_stable_sequence(TR_SEQUENCE * sq);
int
_tr_lang_area_cmp_ci(TR_SEQUENCE * sq,TR_CHAR_INFO * ci1,TR_CHAR_INFO * ci2);
void
_tr_copy_line_attr(TR_LINE_ATTR * a1,TR_LINE_ATTR * a2);
int
_tr_cmp_attr(TR_ATTR * a,TR_ATTR * b);
void
_tr_destroy_lang_line(TR_SEQUENCE * sq,TR_LANG_LINE * ll);
void
_tr_destroy_element(TR_SEQUENCE * sq,TR_LANG_LINE * ll,TR_ELEMENT * el);
int
tr_ptr_cmp(TR_PTR a,TR_PTR b);



void _xx_tr_check_error(TR_ERROR,char *,int);
#define _tr_check_error(er)	\
	_xx_tr_check_error(er,__FILE__,__LINE__)
int tr_copyout(TR_SEQUENCE * sq,TR_PTR,L_CHAR *,int);
void tr_close_sequence(TR_SEQUENCE * sq);
void tr_ptr_regulation(TR_SEQUENCE * sq,TR_PTR *);
void tr_set_callback(TR_SEQUENCE * sq,
	void (*func)(TR_SEQUENCE*,void*),
	void * arg);
TR_LANG *
trl_get_lang(TRL_CONTEXT * ctx,L_CHAR ch);
void
trl_insert_table(L_CHAR from ,L_CHAR to,TR_LANG * lang,int convert_flag);
void xx_tr_lock(TR_SEQUENCE*,char*,int);
#define tr_lock(sq)	xx_tr_lock(sq,__FILE__,__LINE__)
void tr_unlock(TR_SEQUENCE*);

void tr_waitsync(TR_SEQUENCE *,WAITSYNC_CLIENT *,int);


void tr_system_lock();
void tr_system_unlock();

void gc_lock_text_render();
void gc_unlock_text_render();
void gc_text_render();
void init_text_render();


void waitsync_test(TR_SEQUENCE * sq,char * msg);
TR_LANG * _tr_search_lang_from_abb(char * abb);
int _tr_insert_lang(TR_LANG * lang);
void init_lang(TR_LANG * lang);
void _tr_rw_lock();
void _tr_rw_unlock();
void tr_rw_lock();
void tr_rw_unlock();
void gc_tr_obj(TR_SEQUENCE * sq,void (*gc_obj)(void*));
int _tr_lock(TR_SEQUENCE * sq,char *,int);
void _tr_unlock(TR_SEQUENCE * sq);
void _tr_sleep_sq_position(TR_SEQUENCE * sq);
void _tr_wakeup_sq_position(TR_SEQUENCE * sq);
TR_LANG * _tr_search_lang(L_CHAR ch,TRL_CONTEXT * ctx);
int _tr_ptr_regulation(TR_PTR * p);
TR_CHAR_BUF * _tr_new_char_buf(TR_CHAR_BUF * cb);
void _tr_set_char_buf_lang_line(TR_LANG_LINE * ll);
int _tr_get_attr_short_data(TR_ATTR * a,int type);
void _tr_set_attr_short_data(TR_ATTR ** ap,int type,short data);
int _tr_get_attr_int_data(TR_ATTR * a,int type);
int tr_ref_cmp(TR_REFERENCE * r1,TR_REFERENCE * r2);
void _wakeup_sequence(TR_SEQUENCE * sq);
void _insert_unmapping_char(TR_SEQUENCE * sq,TR_PTR ptr,int ok_subcode);
TR_UNMAPPING_CHAR _get_unmapping_char(TR_SEQUENCE * sq);
void _tr_disable_unmapping_char(TR_SEQUENCE * sq,TR_PTR p);
void _dirty_box(TR_SEQUENCE * sq,TR_BOX* b,int flags);
TR_BOX * _get_dirty_box(TR_SEQUENCE * sq);
int _get_dirty(TR_SEQUENCE * sq,TR_DIRTY * d);
int get_dirty(TR_SEQUENCE * sq,TR_DIRTY * d);
TR_BOX * _tr_new_box(TR_SEQUENCE * sq,TR_BOX * b,TR_BOX_ATTR * attr);
void _tr_insert_lang_line_mapping(TR_PTR ptr,int len);
void _tr_insert_lang_line_mapping_new_cb(TR_PTR ptr,int len);
TR_PTR _tr_insert_string(
	TR_SEQUENCE * sq,
	TR_PTR p_ptr,
	int len,
	LC_WRITING_STYLE * ws,
	TR_ATTR	* attr,
	void *obj,
	int size,
	L_CHAR * str);
void _tr_delete_lang_line_mapping1(TR_SEQUENCE * sq,TR_PTR p);
void _tr_delete_lang_line_mapping2(TR_SEQUENCE * sq,TR_PTR p1,TR_PTR p2,int len);
void _tr_cut_char_buf1(TR_SEQUENCE * sq,TR_PTR ptr,int len);
void _tr_cut_char_buf2(TR_SEQUENCE * sq,TR_PTR p);
void _tr_destroy_char_buf(TR_SEQUENCE * sq,TR_CHAR_BUF * cb);
TR_PTR _tr_delete_string(
	TR_SEQUENCE * sq,
	TR_PTR ptr,
	int len);
void _tr_destroy_lang_line_list(TR_SEQUENCE * sq,TR_LANG_LINE * ll);
void _tr_destroy_box_line(TR_SEQUENCE * sq,TR_BOX_LINE * bl);
void _tr_destroy_box_line_list(TR_SEQUENCE * sq,TR_BOX_LINE * bl);
void _tr_destroy_box(TR_SEQUENCE * sq,TR_BOX * b);
TR_PTR _tr_box_line_last_ptr(TR_BOX_LINE* bl);
TR_PTR _tr_box_line_first_ptr(TR_BOX_LINE * bl);
TR_PTR _tr_box_last_ptr(TR_BOX * b);
TR_PTR _tr_box_first_ptr(TR_BOX * b);
int _tr_get_doc_dir_pixels(TR_SEQUENCE * sq,TR_BOX * b);
void _tr_box_doc_dir_pixels(TR_SEQUENCE * sq,TR_BOX * b);
void _tr_dirty_box(TR_SEQUENCE * sq,TR_BOX * b);
void tr_dirty_box(TR_SEQUENCE * sq,TR_BOX * b);
int _tr_get_char_info(TR_CHAR_INFO * ci,TR_SEQUENCE * sq,TR_PTR ptr);
void _tr_set_bl_offset(TR_BOX * b,TR_BOX_LINE * st);
void _tr_setup_bl_offset(TR_BOX * b,TR_BOX_LINE * bl);
TR_BOX_LINE * _tr_new_box_line(TR_SEQUENCE * sq,TR_BOX * b,
		TR_BOX_LINE * bl,int where,int height);
int _tr_lang_area_check(TR_LANG_AREA * a,TR_LANG_LINE * ll);
TR_LANG_LINE * _tr_new_lang_line(
	TR_SEQUENCE * sq,
	TR_BOX_LINE * bl,
	TR_LANG_AREA * a,
	TR_LANG_LINE * ll,
	int where);
TR_LANG_AREA * _tr_new_lang_area(
	TR_SEQUENCE * sq,
	TR_LANG * lang,
	TR_LANG_AREA * prev);
void _tr_get_lang_area_info(TR_LANG_AREA_INFO *lai,TR_LANG_AREA *a);
int _tr_lang_area_cmp_ptr(TR_SEQUENCE * sq,TR_PTR p1,TR_PTR p2);
int _tr_box_line_adjust(TR_SEQUENCE * sq,TR_BOX_LINE * b1,TR_BOX_LINE * b2);
void _tr_lang_area_proc(TR_SEQUENCE * sq,TR_CHAR_INFO * ci);
void _tr_unmapping_char_proc(TR_SEQUENCE * sq,TR_UNMAPPING_CHAR * umc);
void tr_unmapping_char_proc(TR_SEQUENCE * sq,TR_UNMAPPING_CHAR * umc);
TR_LANG_LINE * _tr_element_prev_lang_line(TR_LANG_LINE * ll);
TR_LANG_LINE * _tr_element_next_lang_line(TR_LANG_LINE * ll);
TR_ELEMENT * _tr_forward(TR_LANG_LINE * ll,TR_LANG_LINE * ll_next);
TR_ELEMENT * _tr_last_el(TR_LANG_LINE * ll);
TR_ELEMENT * _tr_reverse(TR_LANG_LINE * ll,TR_LANG_LINE * ll_prev);
void _tr_wait_stable_sequence(TR_SEQUENCE * sq);
void _tr_waitsync(TR_SEQUENCE * sq,WAITSYNC_CLIENT * c,int);
void _trl_free_langs(TRL_LANG_LIST * ll);
int _tr_copyout(TR_PTR p,L_CHAR * str,int len);
void _tr_set_callback(TR_SEQUENCE * sq,
	void (*func)(TR_SEQUENCE*,void*),
	void * arg);

#endif



