/**********************************************************************
 
	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 ___LONG_CHAR_H___
#define ___LONG_CHAR_H___

#include	"graph.h"

#define LCZM_4BYTE	0x80000000
#define LCZ_4BYTE	0x00000000
#define LCZM_4B_TYPE	0x80000000

#define LCZM_3BYTE	0xc0000000
#define LCZ_3BYTE	0x80000000
#define LCZM_3B_TYPE	0xff000000
#define LCZM_3B_CODE	0x00ffffff

#define	LCZM_2BYTE	0xe0000000
#define LCZ_2BYTE	0xc0000000
#define LCZM_2B_TYPE	0xffff0000
#define LCZM_2B_CODE	0x0000ffff

#define LCZM_1BYTE	0xf0000000
#define LCZ_1BYTE	0xe0000000
#define LCZM_1B_TYPE	0xffffff00
#define LCZM_1B_CODE	0x000000ff

#define LCZM_7BIT	0xf0000000
#define LCZ_7BIT	0xf0000000
#define LCZM_7b_TYPE	0xffffff80
#define LCZM_7b_CODE	0x0000007f

#define LCZM_ALL	0xffffffff


#define _L_CHAR	unsigned long
typedef _L_CHAR L_CHAR;

#define LC_MIN	0x00000000
#define LC_MAX	0xffffffff


#define LC_NAME_SIZE	32

typedef struct code_abb {
	struct code_abb *	next;
	char		name[LC_NAME_SIZE];
	struct code_method *	cm;
	L_CHAR			lccode;
} CODE_ABB;

typedef struct cm_dummy {
	short		d0;
	short		d1;
} CM_DUMMY;


typedef struct lcz_set {
	L_CHAR		lcz;
	L_CHAR		mask;
} LCZ_SET;


typedef struct code_method {
	char		name[LC_NAME_SIZE];
	L_CHAR		lccode;
	LCZ_SET *	main_code;
	int		max_ret;
	int		close_max;
	CM_DUMMY	dummy;
	void *		(*open)();
	int		(*close)(unsigned char *,void *);
	int		(*to_internal)(
				L_CHAR * ret,
				void * work,
				unsigned char ch
					);
	int		(*to_external)(
				unsigned char * ret,
				void * work,
				L_CHAR ch
					);
	struct code_method *	next;
} CODE_METHOD;


typedef struct lc_combination {
	L_CHAR		node;
	L_CHAR *	leaf;
} LC_COMBINATION;

typedef struct lc_cn {
	L_CHAR		lcz;
	L_CHAR		cn;
	int		max;
} LC_CN;


typedef struct lc_description_table {
	L_CHAR			lcz;
	L_CHAR			mask;
	L_CHAR			lcc;
	L_CHAR			(*int2ex)(L_CHAR);
	L_CHAR			(*ex2int)(L_CHAR);
	char *			name;
} LC_DESCRIPTION_TABLE;

typedef struct lc_font_size_list {
	struct lc_font_size_list *	next;
	int				size;
	L_CHAR				from;
	L_CHAR				to;
} LC_FONT_SIZE_LIST;

typedef struct lc_font_work {
	void *				work;
	struct lc_font_engine *		fe;
} LC_FONT_WORK;

typedef struct lc_font {
	struct lc_font *		next;
	L_CHAR *			fontname;
	L_CHAR				lcz[2];
	L_CHAR				mask[2];
	LC_FONT_SIZE_LIST *		list;
	LC_FONT_WORK *			fw_list;
	int				fw_len;
	struct lc_font_engine_type *	fe_type;
} LC_FONT;


typedef struct lcf_set {
	L_CHAR			ch;
	LC_FONT *		font;
	int			size;
} LCF_SET;

typedef struct lc_string_pic {
	I_RECT		r;
	short		width;
	short		dir;
#define VSD_V_R2L	1
#define VSD_V_L2R	2
#define VSD_H_L2R	4
#define VSD_H_R2L	8

#define VSD_V		(VSD_V_R2L|VSD_V_L2R)
#define VSD_H		(VSD_H_R2L|VSD_H_L2R)
#define VSD_FORWARD	(VSD_V|VSD_H_L2R)
#define VSD_REVERSE	VSD_H_R2L
#define VSD_ALL		(VSD_V|VSD_H)
	unsigned char *	pic;
} LC_STRING_PIC;



typedef struct lc_font_engine {
	struct lc_font_engine *		next;
	char *				name;
	struct lc_font_engine_type *	type;
	void *				work;
} LC_FONT_ENGINE;

typedef struct lc_font_engine_type {
	char	type[32];
	int	(*fe_new)(LC_FONT *,LC_FONT_ENGINE *);
	void	(*fe_get_pic)(
			LC_STRING_PIC * sp,
			int dir,
			LCF_SET * str,
			int len);
	int	(*fe_coverage)(
			LC_FONT *,int,L_CHAR);
	CM_DUMMY	d;
	struct lc_font_engine *	next;
} LC_FONT_ENGINE_TYPE;

typedef struct lc_table {
	struct lc_table *	next;
	int			flags;
#define LCTF_NO_CHECK	0x00000001
	struct lc_table *	relate;
	int			ref;
	int			size;
	LCF_SET *		tbl;
} LC_TABLE;

typedef struct writable_code_table {
	struct writable_code_table *	next;
	L_CHAR				lcz;
	L_CHAR				mask;
	LC_TABLE *			lc_tbl;
} WRITABLE_CODE_TABLE;


typedef struct wct {
	struct wct *			next;
	WRITABLE_CODE_TABLE *		list;
	int				size;
} WCT;

typedef struct font_pri {
	LC_FONT *		font;
	int			method;
#define FST_JUST		0
#define FST_NEARLY		1
#define FST_SMALL		2
#define FST_LARGE		3
} FONT_PRI;

typedef struct font_pri_name {
	L_CHAR *		font;
	L_CHAR			lcz[2];
	L_CHAR			mask[2];
	int			method;
} FONT_PRI_NAME;

typedef struct lc_ws_cond {
	int				cond;
#define WSC_ANY			1
#define WSC_FE_LIST		2
#define WSC_FET_LIST		4
#define WSC_PIC_REQUIRED	8
	LC_FONT_ENGINE **		fe;
	LC_FONT_ENGINE_TYPE **		fet;
} LC_WS_COND;

typedef struct lc_cond_writing_style {
	struct lc_cond_writing_style *	next;
	WCT *				wct;
	LC_WS_COND			c;
	FONT_PRI *			un_fonts;
	FONT_PRI *			ja_fonts;
	FONT_PRI *			tw_fonts;
	FONT_PRI *			cn_fonts;
	FONT_PRI *			kr_fonts;

} LC_COND_WRITING_STYLE;

typedef struct lc_cond_writing_style_list {
	struct lc_cond_writing_style_list *	next;
	struct lc_ws_children_list *		ws_cl;
	LC_COND_WRITING_STYLE *			cws;
	struct lc_cond_writing_style_list *	stack_next;
} LC_COND_WRITING_STYLE_LIST;


typedef struct lc_cws {
	LC_COND_WRITING_STYLE_LIST *	list;
	struct lc_writing_style *	top;
	LC_COND_WRITING_STYLE_LIST *	stack;
	LC_WS_COND			cond;
} LC_CWS;

typedef struct lc_writing_style {
	struct lc_writing_style *	next;
	L_CHAR *			stylename;
	LC_COND_WRITING_STYLE *		cws_list;

	FONT_PRI_NAME *			un_fonts_n;
	FONT_PRI_NAME *			ja_fonts_n;
	FONT_PRI_NAME *			tw_fonts_n;
	FONT_PRI_NAME *			cn_fonts_n;
	FONT_PRI_NAME *			kr_fonts_n;

	struct lc_ws_children_list *	children;
	struct lc_ws_children_list *	self_children_list;
} LC_WRITING_STYLE;

typedef struct lc_ws_children_list {
	struct lc_ws_children_list *	next;
	LC_WRITING_STYLE *		ws;
} LC_WS_CHILDREN_LIST;

typedef struct unicode_x {
	L_CHAR	unicode;
	L_CHAR	local;
} UNICODE_X;

typedef struct code_entry {
	L_CHAR			code;
	struct code_entry *	co;
} CODE_ENTRY;

typedef struct code_table_header {
	struct code_table_header *	next;
	L_CHAR				lcz;
	L_CHAR				mask;
	int				len;
	struct code_entry *		tbl;
} CODE_TABLE_HEADER;

extern CODE_METHOD * std_cm;

L_CHAR * _l_string_1(CODE_METHOD *,char*);
L_CHAR * _l_string_2(CODE_METHOD *,char*);

#define l_string(cm,str)	\
	((#str)[0] == '\"' ? _l_string_2(cm,str) : _l_string_1(cm,str))


char * n_string(CODE_METHOD *,L_CHAR *);
int l_strcmp(L_CHAR*,L_CHAR*);
int l_strlen(L_CHAR *);
void l_strcpy(L_CHAR * d,L_CHAR * s);
CODE_METHOD * get_default_cm();
CODE_METHOD * search_cm(char *);
CODE_METHOD * search_cm_by_lccode(L_CHAR);
CODE_METHOD * search_cm_by_main_code(L_CHAR);
L_CHAR search_lccode(char * name);
L_CHAR get_lc_mask(L_CHAR code);
void insert_code_list(CODE_METHOD *);
void insert_code_abb(char * name,L_CHAR,CODE_METHOD *);

L_CHAR * wct_conv(WCT*,L_CHAR *);
WCT * new_wct();
WRITABLE_CODE_TABLE * set_wct(WCT* wct,L_CHAR lcz,L_CHAR mask,
			WRITABLE_CODE_TABLE * alias,
			void * work);
WRITABLE_CODE_TABLE * get_wct(WCT* wct,L_CHAR ch);
void
set_convert(WCT * w,
	L_CHAR from,L_CHAR mask,
	L_CHAR to,
	int flag);
#define SC_ALL		0
#define SC_IF_NOTEXIST	1
int wct_check(WCT *,L_CHAR);
void
copy_wct(
	WRITABLE_CODE_TABLE * dest,
	WRITABLE_CODE_TABLE * src,
	int mode);



extern CODE_METHOD sjis_cm,jis_cm,euc_cm,int_cm;
extern CODE_METHOD utf8_cm,ucs4_cm,utf16_cm;
extern CODE_METHOD ascii_cm;

/* latin domain font bitmap */
#define LCB_ISO8859_1		1
#define LCB_ISO8859_2		2
#define LCB_ISO8859_3		4
#define LCB_ISO8859_4		8
#define LCB_ISO8859_5		0x10
#define LCB_ISO8859_6		0x20
#define LCB_ISO8859_7		0x40
#define LCB_ISO8859_8		0x80
#define LCB_ISO8859_9		0x100
#define LCB_ISO8859_10		0x200
#define LCB_ISO8859_11		0x400
#define LCB_ISO8859_12		0x800
#define LCB_ISO8859_13		0x1000
#define LCB_ISO8859_14		0x2000
#define LCB_ISO8859_15		0x4000

#define LCB_UNICODE_v1_1	0x80000000
#define LCB_UNICODE_v2_0	0x40000000
#define LCB_UNICODE_v3_0	0x20000000

/* jp domain font bitmap */

#define LCB_JISX0201		1
#define LCB_JISX0208_1978	2
#define LCB_JISX0208_1983	4
#define LCB_JISX0208_1990	8
#define LCB_JISX0212_1990	0x10
#define LCB_NICHIBUN		0x20
#define LCB_KONJAKU		0x40
#define LCB_UNICODE_v1_1_JP	0x80000000
#define LCB_UNICODE_v2_0_JP	0x40000000
#define LCB_UNICODE_v3_0_JP	0x20000000

void wct_unicode(WCT * w);
void wct_jp(WCT * w,int bitmap);
void wct_latin(WCT * w,int bitmap);

CODE_TABLE_HEADER *
get_code_table_by_lcz(L_CHAR lcz);
CODE_TABLE_HEADER *
get_code_table_by_char(L_CHAR a);
int
set_correspond(L_CHAR a,L_CHAR b);
L_CHAR
code_convert(L_CHAR from,L_CHAR lcz);
L_CHAR
code_convert_set(L_CHAR fron,LCZ_SET *,LCZ_SET * );
int
cmp_l_code(L_CHAR,L_CHAR);

LC_FONT_SIZE_LIST *
_get_lc_font_size_list(LC_FONT *,int,int);
LC_FONT_SIZE_LIST *
get_lc_font_size_list(LC_FONT *,int,int);
LC_FONT_WORK *
get_font_work(LC_FONT * f,LC_FONT_ENGINE * fe);
LC_FONT * _lc_new_font(L_CHAR *,L_CHAR*,L_CHAR*);
LC_FONT * lc_new_font(L_CHAR *,L_CHAR*,L_CHAR*);
int
check_font_and_cond(LC_WS_COND * cond,LC_FONT * f);
int
check_font_name_and_cond(LC_WS_COND * cond,L_CHAR * fontname);

LC_WRITING_STYLE * new_ws(L_CHAR *,
	FONT_PRI_NAME *,
	FONT_PRI_NAME *,
	FONT_PRI_NAME *,
	FONT_PRI_NAME *,
	FONT_PRI_NAME *);
LC_WRITING_STYLE * get_ws(L_CHAR *);
int set_ws_child(LC_WRITING_STYLE *,LC_WRITING_STYLE *);
LC_CWS get_cws(LC_WRITING_STYLE *,LC_WS_COND *);
FONT_PRI_NAME *
copy_font_pri_name(FONT_PRI_NAME * f);

#define CBF_SRC_COMBINE	0x00000001
#define CBF_SRC_PLANE	0x00000000
#define CBF_DST_COMBINE	0x00000010
#define CBF_DST_PLANE	0x00000000
#define CBF_ERR_KEEP	0x00000100

L_CHAR *
combine(L_CHAR *,int length);
L_CHAR *
uncombine(L_CHAR *,int length);
LCF_SET *
combine_lcf(LCF_SET *,int length);
LCF_SET *
uncombine_lcf(LCF_SET *,int length);
LCF_SET *
ws_convert(
	LC_WRITING_STYLE * ws,LC_WS_COND * cond,
	int size,L_CHAR * str,int len,int flags);
L_CHAR * copy_out_lcf_set(LCF_SET *,int len,int flags);

L_CHAR *
code_convert_with_combine(L_CHAR * str_input,int length,
	LCZ_SET * set,int flags);
char *
code_convert_str(char * str,CODE_METHOD * from,CODE_METHOD * to,int flags);
char *
code_convert_lc2str(L_CHAR * target,CODE_METHOD * to,int flags);

void
insert_lc_font_size_list(LC_FONT * f,LC_FONT_SIZE_LIST * sl);

LC_FONT *
lc_select_font(
	int * ret_size,
	L_CHAR * str,
	int length,
	LC_WRITING_STYLE * ws,
	int size,
	LC_WS_COND * cond,
	int flags);
void insert_font_engine(LC_FONT_ENGINE * );
LCF_SET *
str2lcf(L_CHAR * str,int len,LC_FONT * f,int size);
L_CHAR * get_all_l_char(int * sizep,L_CHAR a);
void font2lcz(LCZ_SET * lset,LC_FONT * f);
CODE_METHOD * get_encoding(L_CHAR*);
void init_longchar();
void print_code_table_header_prototype(CODE_TABLE_HEADER * ct);
void print_code_table();

void _insert_lc_font_size_list(LC_FONT * f,LC_FONT_SIZE_LIST * sl);
int insert_font_work(LC_FONT * f,LC_FONT_ENGINE * fe,void * work);
void _insert_font_engine(LC_FONT_ENGINE * fe);
void _delete_font_engine(LC_FONT_ENGINE * fe);
void delete_font_engine(LC_FONT_ENGINE * fe);
LC_FONT * _search_wfont(L_CHAR * fontname);
LC_FONT * search_wfont(L_CHAR * fontname);
LC_FONT_ENGINE_TYPE * _search_fe_type(char * en);
void _insert_lc_font_size_list(LC_FONT * f,LC_FONT_SIZE_LIST * sl);
int insert_font_work(LC_FONT * f,LC_FONT_ENGINE * fe,void * work);
void init_wct();
WRITABLE_CODE_TABLE * _search_w(WCT * t,L_CHAR lcz);
void _write_char_w(
	WRITABLE_CODE_TABLE * w,
	L_CHAR ch,
	LC_FONT * f,
	int f_size,
	L_CHAR after);
int _search_ws_font(LCF_SET * sp,FONT_PRI * fp,L_CHAR ch,int size);
void _wct_setup_char(FONT_PRI * fp,WRITABLE_CODE_TABLE * w,L_CHAR ch,int size);
FONT_PRI * fitting_font_pri(LC_COND_WRITING_STYLE * cws,L_CHAR lcz);
FONT_PRI * merge_fp_list(FONT_PRI * fp,FONT_PRI * fp2);
WRITABLE_CODE_TABLE *
_wct_setup(LC_COND_WRITING_STYLE * cws,L_CHAR ch_input,int f_size);
int _wct_check_scalable_fonts(WCT * t);
WCT * _get_wct(LC_COND_WRITING_STYLE * cws,int size);
LC_COND_WRITING_STYLE_LIST *
copy_cws(LC_COND_WRITING_STYLE_LIST * l);
void cws_stack_push(LC_CWS * cws,LC_WS_CHILDREN_LIST * ws_cl);
void cws_stack_pop(LC_CWS * cws);
void cws_stack_move(LC_CWS * cws);
void check_str(L_CHAR * str,int len);
LCF_SET * _ws_convert(
	LC_WRITING_STYLE * ws,
	LC_WS_COND * cond,
	int size,
	L_CHAR * str_input,
	int length,
	int flags);
int fpn_len(FONT_PRI_NAME * n);
void get_font_pri(FONT_PRI ** fp,FONT_PRI_NAME * fpn,LC_WS_COND * cond);
int _lc_cmp_ws_cond(LC_WS_COND * c1,LC_WS_COND * c2);
void _lc_free_ws_cond(LC_WS_COND * c);
LC_WRITING_STYLE * _new_ws(
	L_CHAR * stylename,
	FONT_PRI_NAME * un,
	FONT_PRI_NAME * ja,
	FONT_PRI_NAME * tw,
	FONT_PRI_NAME * cn,
	FONT_PRI_NAME * kr
	);
LC_WRITING_STYLE * _get_ws(L_CHAR * stylename);
int _set_ws_child(LC_WRITING_STYLE * ws1,LC_WRITING_STYLE * ws2);
void _gc_lc_table();
LC_COMBINATION * cb_mutch(int * mlen,L_CHAR * str,int maxlen);
LC_CN * cn_mutch(L_CHAR node);
LC_COMBINATION * cb_mutch_node(L_CHAR node);
LC_FONT * __lc_select_font(
	int * ret_size,
	L_CHAR * str,
	int	length,
	LC_WRITING_STYLE * ws,
	int	size,
	LC_WS_COND * cond,
	int flags,

	int * fp_ws_count);
LC_FONT * _lc_select_font(
	int * ret_size,
	L_CHAR * str,
	int	length,
	LC_WRITING_STYLE * ws,
	int	size,
	LC_WS_COND * cond,
	int flags);

LCF_SET __wct_convert(LC_COND_WRITING_STYLE * cws,WCT * wct,L_CHAR ch,int size);
LCF_SET _wct_convert(LC_CWS * cws,L_CHAR ch,int size);
FONT_PRI * cws_fitting_font_pri(LC_CWS * cws,L_CHAR lcz,int * fp_ws_count);
void _lc_copy_ws_cond(LC_WS_COND * dest,LC_WS_COND * src);
int col_code_entry(CODE_ENTRY * ce1,CODE_ENTRY * ce2);
void marge_code_entry(CODE_ENTRY * e1,CODE_ENTRY * e2);


#endif
