/**********************************************************************
 
	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	<stdlib.h>
#include	<stdio.h>
#include	"v.h"
#include	"memory_debug.h"

int
v_get_text_minrect_8(
	VRECT * r,
	VOBJECT * obj,
	VPOINT * st,
	VFONT * vf,
	char * str,
	int len)
{
XFontStruct * fs;
int dir,ascent,descent;
XCharStruct cs;
int width;

	fs = XLoadQueryFont(obj->header.win->d->d,
		vf->fontname);
	XSetFont(obj->header.win->d->d,
		obj->header.win->gc,
		fs->fid);
	XTextExtents(fs,
		str,
		len,
		&dir,
		&ascent,
		&descent,
		&cs);
	switch ( dir ) {
	case FontRightToLeft:
		r->br.x = obj->vtext.st_x-cs.lbearing;
		r->tl.x = obj->vtext.st_x-cs.rbearing;
		break;
	case FontLeftToRight:
		r->tl.x = obj->vtext.st_x+cs.lbearing;
		r->br.x = obj->vtext.st_x+cs.rbearing;
		break;
	}
	r->tl.y = st->y-ascent;
	r->br.y = st->y+descent;
	width = XTextWidth(vf->fs,str,len);
	st->x += width;
	return 0;
}

void
v_draw_text_one_font_8(
	VRECT * r,
	VOBJECT * obj,
	VPOINT * st,
	char * str,
	int len,
	VFONT * work)
{
int fid;

	fid = XLoadFont(obj->header.win->d->d,work->fontname);
	XSetFont(obj->header.win->d->d,
		obj->header.win->gc,
		fid);
	if ( obj->vtext.background & C_NULL ) {
		XSetForeground(
			obj->header.win->d->d,
			obj->header.win->gc,
			GB2MCOLOR_D(obj->header.win->d,
				obj->vtext.color));
		XDrawString(
			obj->header.win->d->d,
			obj->header.win->w,
			obj->header.win->gc,
			st->x,
			st->y,
			str,
			len);
	}
	else {
		XSetForeground(
			obj->header.win->d->d,
			obj->header.win->gc,
			GB2MCOLOR_D(obj->header.win->d,
				obj->vtext.color));
		XSetBackground(
			obj->header.win->d->d,
			obj->header.win->gc,
			GB2MCOLOR_D(obj->header.win->d,
				obj->vtext.background));

		XDrawImageString(
			obj->header.win->d->d,
			obj->header.win->w,
			obj->header.win->gc,
			st->x,
			st->y,
			str,
			len);
	}
	v_get_text_minrect_8(r,obj,st,work,str,len);
}

int
v_get_text_minrect_16(
	VRECT * r,
	VOBJECT * obj,
	VPOINT * st,
	VFONT * vf,
	XChar2b * str,
	int len)
{
XFontStruct * fs;
int dir,ascent,descent;
XCharStruct cs;
int width;

	fs = XLoadQueryFont(obj->header.win->d->d,
		vf->fontname);
	XSetFont(obj->header.win->d->d,
		obj->header.win->gc,
		fs->fid);
	XTextExtents16(fs,
		str,
		len,
		&dir,
		&ascent,
		&descent,
		&cs);
	switch ( dir ) {
	case FontRightToLeft:
		r->br.x = obj->vtext.st_x-cs.lbearing;
		r->tl.x = obj->vtext.st_x-cs.rbearing;
		break;
	case FontLeftToRight:
		r->tl.x = obj->vtext.st_x+cs.lbearing;
		r->br.x = obj->vtext.st_x+cs.rbearing;
		break;
	}
	r->tl.y = st->y-ascent;
	r->br.y = st->y+descent;
	width = XTextWidth16(vf->fs,str,len);
	st->x += width;
	return 0;
}

void
v_draw_text_one_font_16(
	VRECT * r,
	VOBJECT * obj,
	VPOINT * st,
	XChar2b * str,
	int len,
	VFONT * work)
{
int fid;
	fid = XLoadFont(obj->header.win->d->d,work->fontname);
	XSetFont(obj->header.win->d->d,
		obj->header.win->gc,
		fid);
	if ( obj->vtext.background & C_NULL ) {
		XSetForeground(
			obj->header.win->d->d,
			obj->header.win->gc,
			GB2MCOLOR_D(obj->header.win->d,
				obj->vtext.color));
		XDrawString16(
			obj->header.win->d->d,
			obj->header.win->w,
			obj->header.win->gc,
			st->x,
			st->y,
			str,
			len);
	}
	else {
		XSetForeground(
			obj->header.win->d->d,
			obj->header.win->gc,
			GB2MCOLOR_D(obj->header.win->d,
				obj->vtext.color));
		XSetBackground(
			obj->header.win->d->d,
			obj->header.win->gc,
			GB2MCOLOR_D(obj->header.win->d,
				obj->vtext.background));

		XDrawImageString16(
			obj->header.win->d->d,
			obj->header.win->w,
			obj->header.win->gc,
			st->x,
			st->y,
			str,
			len);
	}
	v_get_text_minrect_16(r,obj,st,work,str,len);
}


char *
convert_8(L_CHAR * str,int len)
{
char * ret;
int i;
	ret = d_alloc(len);
	for ( i = 0; i < len ; i ++ )
		ret[i] = str[i];
	return ret;
}

char *
convert_7(L_CHAR * str,int len)
{
char * ret;
int i;
	ret = d_alloc(len);
	for ( i = 0; i < len ; i ++ )
		ret[i] = str[i]&0x7f;
	return ret;
}

XChar2b *
convert_16(L_CHAR * str,int len)
{
XChar2b * ret;
int i;
	ret = d_alloc(len*sizeof(XChar2b));
	for ( i = 0 ; i < len ; i ++ ) {
		ret[i].byte1 = (str[i]>>8)&0xff;
		ret[i].byte2 = str[i]&0xff;
	}
	return ret;
}


void
v_draw_text_one_font(
	VRECT * r,
	VOBJECT * obj,
	VPOINT * st,
	L_CHAR * str,
	int len,
	VFONT * vf,
	L_CHAR mask)
{
char * str8;
XChar2b * str16;
	if ( vf->fs->min_byte1 == 0 && vf->fs->max_byte1 == 0 ) {
		if ( mask == LCZM_7b_TYPE ) {
			str8 = convert_7(str,len);
			v_draw_text_one_font_8(r,obj,st,str8,len,vf);
			d_f_ree(str8);
		}
		else {
			str8 = convert_8(str,len);
			v_draw_text_one_font_8(r,obj,st,str8,len,vf);
			d_f_ree(str8);
		}
	}
	else {
		str16 = convert_16(str,len);
		v_draw_text_one_font_16(r,obj,st,str16,len,vf);
		d_f_ree(str16);
	}
}

void
v_draw_text(VOBJECT * obj)
{
int i,j;
L_CHAR unknown;
int f;
WRITABLE_CODE_TABLE * t;
int write_len;
int len;
L_CHAR * str;
VPOINT st;
VRECT rct,r;
	len = obj->vtext.length;
	str = obj->vtext.data;
	unknown = '?';
	f = 0;
	st.x = obj->vtext.st_x;
	st.y = obj->vtext.st_y;
	obj->vtext.minrect.tl.x = obj->vtext.minrect.tl.y = 0;
	obj->vtext.minrect.br.x = obj->vtext.minrect.br.y = -1;
	for ( i = 0 ; i < len ; ) {
		t = get_wct(obj->header.win->d->font_work,str[i]);
		if ( t ) {
			for ( j = i ; j < len &&
				(str[j]&t->mask) == t->lcz ; j ++ );
			v_draw_text_one_font(
				&r,
				obj,
				&st,
				&str[i],
				j-i,
				t->work,
				t->mask);
			i = j;
		}
		else {
			v_draw_text_one_font(
				&r,
				obj,
				&st,
				&unknown,
				1,
				&obj->header.win->d->iso8859_1,
				LCZM_1B_TYPE);
			i ++;
		}
		marge_vrect(&obj->vtext.minrect,&r);
	}
}

typedef struct v_set_text_s {
	VERROR * err;
	VOBJECT * obj;
	unsigned long color;
	unsigned long background;
	L_CHAR * data;
	int	length;
} V_SET_TEXT_S;

int
_v_redraw_text(VOBJECT*args)
{

	v_draw_text(args);
	return 0;
}

void v_redraw_text(VTEXT * vt)
{
	ms_do(_v_redraw_text,(void*)vt,"v_redraw_text");
}

void
v_text_handler(
	VOBJECT *	obj,
	int		cmd)
{
	switch ( cmd ) {
	case VE_REDRAW:
		v_redraw_text(&obj->vtext);
		break;
	case VE_BUTTON:
		break;
	default:
		fprintf(stderr,"v_text::unsupport cmd %i\n",cmd);
	}
}

typedef struct v_create_text {
	VOBJECT *	ret;
	VERROR *	err;

	VWINDOW *	win;
	unsigned long	color;
	unsigned long	background;
	int		size;
	int		dir;
	int		st_x;
	int 		st_y;
	L_CHAR *	data;
	int		length;
} V_CREATE_TEXT_S;


int
_v_create_text(V_CREATE_TEXT_S * v)
{
VOBJECT * obj;
int fid;
VWINDOW *	win;
unsigned long	color;
unsigned long	background;
int		st_x;
int 		st_y;
char *		fname;
L_CHAR *	data;
int		length;


	win = v->win;
	color = v->color;
	background = v->background;
	st_x = v->st_x;
	st_y = v->st_y;
	data = v->data;
	length = v->length;

	obj = d_alloc(sizeof(VTEXT));
	obj->vtext.st_x = st_x;
	obj->vtext.st_y = st_y;
	obj->vtext.data = d_alloc(length*sizeof(L_CHAR));
	memcpy(obj->vtext.data,data,length*sizeof(L_CHAR));
	obj->vtext.length = length;
	obj->vtext.color = color;
	obj->vtext.background = background;
	obj->vtext.size = v->size;
	obj->vtext.dir = v->dir;
	obj->header.type = VT_TEXT;
	obj->header.handler = v_text_handler;
	obj->header.win = win;
	obj->header.next = win->obj_list;
	win->obj_list = obj;
	v->err->err1 = E_OK;

	v_draw_text(obj);
	XFlush(obj->header.win->d->d);
	v->ret = obj;
	return 0;
}

VOBJECT *
v_create_text(VERROR * err,
	VWINDOW *	win,
	unsigned long	color,
	unsigned long	background,
	int		size,
	int		dir,
	int		st_x,
	int 		st_y,
	L_CHAR *	data,
	int		length)
{
V_CREATE_TEXT_S v;
	v.err = err;
	v.win = win;
	v.color = color;
	v.background = background;
	v.size = size;
	v.dir = dir;
	v.st_x = st_x;
	v.st_y = st_y;
	v.data = data;
	v.length = length;
	v.ret = 0;
	ms_do(_v_create_text,&v,"v_create_text");
	return v.ret;
}


int
_v_set_text(void * args)
{
V_SET_TEXT_S *pvst = (V_SET_TEXT_S*)args;
VERROR * err = pvst->err;
VOBJECT * obj = pvst->obj;
unsigned long color = pvst->color;
unsigned long background = pvst->background;
L_CHAR *data = pvst->data;
int	length = pvst->length;
char * fname;
int i;
/*
printf("##### start v_set_text(threadID:=%d)\n",get_tid());fflush(stdout);
*/
	fname = obj->header.win->d->iso8859_1.fontname; 
	if ( !(color & C_NULL) ) {
		obj->vtext.color = color;
	}
	if ( !(background & C_NULL) ) {
		obj->vtext.background = background;
	}
	if ( obj->header.type != VT_TEXT ) {
		err->err1 = E_PARAM;
		err->err2 = 0;
	}

	if ( data ) {
		d_f_ree(obj->vtext.data);
		obj->vtext.data = d_alloc(length*sizeof(L_CHAR));
		memcpy(obj->vtext.data,data,length*sizeof(L_CHAR));
		obj->vtext.length = length;
	}


	v_draw_text(obj);
/*
printf("end Draw\n");fflush(stdout);
*/
	XFlush(obj->header.win->d->d);
	err->err1 = E_OK;
/*
printf("end v_set_text\n");fflush(stdout);
*/
	return 0;
}


int 
v_set_text(VERROR * err,
	VOBJECT * obj,
	unsigned long color,
	unsigned long background,
	L_CHAR *data,
	int	length)
{
V_SET_TEXT_S vst;

	vst.obj = obj;
	vst.color = color;
	vst.background = background;
	vst.length = length;	
	vst.data = data;
	vst.err = err;

	ms_do(_v_set_text, (void *)&vst, "v_set_text");

	return 0;
}

typedef struct _v_move_text_s {
	int		x;
	int		y;
	VOBJECT *	obj;
} _V_MOVE_TEXT_S;

int
_v_move_text(_V_MOVE_TEXT_S * t)
{
	t->obj->vtext.st_x = t->x;
	t->obj->vtext.st_y = t->y;
	v_draw_text(t->obj);
	return 0;
}

void
v_move_text(VOBJECT * obj,int x,int y)
{
_V_MOVE_TEXT_S v;
	v.x = x;
	v.y = y;
	v.obj = obj;
	ms_do(_v_move_text,&v,"v_move_text");
}

typedef struct v_text_minrect_s {
	VRECT *		r;
	VOBJECT *	obj;
} V_TEXT_MINRECT_S;


int
_v_text_minrect(void *args)
{
XFontStruct * fs;
int dir,ascent,descent;
XCharStruct cs;

V_TEXT_MINRECT_S *vtm = (V_TEXT_MINRECT_S*)args;
VRECT* r = vtm->r;
VOBJECT *obj = vtm->obj;


	*vtm->r = obj->vtext.minrect;

	return 0;
}

int 
v_text_minrect(VRECT * r,VOBJECT * obj)
{

V_TEXT_MINRECT_S vtm;
	vtm.r = r;
	vtm.obj = obj;
	
	ms_do(_v_text_minrect,(void*)&vtm,"v_text_minrect");
	
	return 0;
}



