/*
###
### This file is part of
###
###                        TurboLinux  ZWinPro
###
###                 Copyright (C) 1999-2000 TurboLinux, Inc. 
###                        All Rights Reserved
### Distributed under the terms of the GNU General Public License (GPL)
###
###
### Authors:     TurboLinux Chinese Development Team:
###              Justin Yu   <justiny@turbolinux.com.cn>
###              Sean Chen   <seanc@turbolinux.com.cn>
###              Daniel Fang <danf@turbolinux.com.cn>
### WWW:         http://www.turbolinux.com.cn/ZWinPro/
### FTP:         ftp://ftp.turbolinux.com.cn/pub/ZWinPro/
###
*/

/*
 * Copyright 1997 by Yu Mingjian.          All Rights Reserved
 * Distributed under the terms of the GNU General Public License (GPL)
 *
 * Permission to retain, use, modify, copy, and distribute Chinput1.0
 * in source or binary and its documentation (hereafter, the Software)
 * for noncommercial purpose is hereby granted to you without a fee,
 * provided that this entire copyright and permission notice appear in
 * all such copies, that no charge be associated with such copies,
 * that distribution of derivative works (including value-added
 * distributions such as with additional input dictionaries or fonts)
 * include clarification that such added or derived parts are not from
 * the original Software, and that the names of the author(s) not be
 * used to endorse or promote such works. The author(s) of the software
 * makes no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 * THE AUTHOR(S) OF THE SOFTWARE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
 * IN NO EVENT SHALL THE AUTHOR(S) OF THE SOFTWARE BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author: Yu Mingjian, Institute of High Energy Physics, Academia Sinica
 * 
 */

//Root style is basic style for all applications. it is an inputbar
//with two rows: one row is for status and preedit, another is for
//candidate from lists
// +-----------------------------------------------+-----------------+
// | [status] [input method name]: preedit         |[corner] [power] |
// +-----------------------------------------------+-----------------+
// | 1. xx 2. xx ..........                   >    |[punct]  [browse]|
// +-----------------------------------------------+-----------------+

#include "all.h"

static void chinput_root_ba_draw_window (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC dimgc = HZServer.dimGC;
	GC lightgc = HZServer.lightGC;
	GC ledgc  = HZServer.ledGC;
	GC panelgc = HZServer.panelGC;
	int ledx1 = HZServer.hzBwin.ledx1;
	int ledy1 = HZServer.hzBwin.ledy1;
	int ledx2 = HZServer.hzBwin.ledx2;
	int ledy2 = HZServer.hzBwin.ledy2;
	int q_x1 = HZServer.hzBwin.q_x1;
	int q_y1 = HZServer.hzBwin.q_y1;
	int q_x2 = HZServer.hzBwin.q_x2;
	int q_y2 = HZServer.hzBwin.q_y2;
	int p_x1 = HZServer.hzBwin.p_x1;
	int p_y1 = HZServer.hzBwin.p_y1;
	int p_x2 = HZServer.hzBwin.p_x2;
	int p_y2 = HZServer.hzBwin.p_y2;
	int offset = HZServer.hzBwin.offset;

        /* draw led */
	XFillRectangle (dpy, win, ledgc, ledx1, ledy1,
			ledx2-ledx1, ledy2-ledy1);
	if (!HZServer.hzBwin.flag) 
		chinput_util_draw_btn (dpy, win,dimgc,lightgc,
				ledx1, ledy1, ledx2, ledy2, False);
	else
		chinput_util_draw_btn (dpy, win,dimgc,lightgc,
			ledx1, ledy1, ledx2, ledy2, True);

	chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc,
			HZServer.hzBwin.btnx1, HZServer.hzBwin.btny1,
			HZServer.hzBwin.btnx2, HZServer.hzBwin.btny2,
			HZServer.hzBwin.btnx3, HZServer.hzBwin.btny3,
			HZServer.hzKwin.onflag);

	/* draw buttons */
	chinput_util_draw_btn (dpy, win, dimgc, lightgc, q_x1, q_y1,q_x2,q_y2, True);
	if (flag_corner)
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "È«", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "È«", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥þ", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥þ", 2);
	}
	else
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "°ë", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "°ë", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥b", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥b", 2);
	}

	chinput_util_draw_btn (dpy, win, dimgc, lightgc, p_x1, p_y1, p_x2, p_y2, True);
	if (flag_punct)
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "£ï", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "£ï", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¢÷", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¢÷", 2);
	}
	else
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, " .", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, " .", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¡O", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¡O", 2);
	}
}

// Pls check the meaning of lock.
void chinput_root_unlock_window (void)
{
	/* server's absolute request */
	HZServer.lockw = None;
	chinput_alloc_color ("#00ff00",  "#000000", "#000000");
	XSetForeground (display,HZServer.ledGC,foreground_pixel);
	chinput_root_ba_draw_window ();
}

void chinput_root_lock_window (void)
{
	/* server's absolute request */
	chinput_alloc_color ("#ff0000",  "#000000", "#000000");
	XSetForeground (display,HZServer.ledGC,foreground_pixel);
	HZServer.hzBwin.flag = True;
	chinput_root_ba_draw_window ();
}

void chinput_root_draw_input_area (char *buf, int len)
{
	char tbuf[256];

	if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
		sprintf(tbuf, "%s: %s", chinputime[cur_inputmethod].namegb, buf);
	else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
		sprintf(tbuf, "%s: %s", chinputime[cur_inputmethod].namegb, buf);
	else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
		sprintf(tbuf, "%s: %s", chinputime[cur_inputmethod].namebig5, buf);
	else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
		sprintf(tbuf, "%s: %s", chinputime[cur_inputmethod].namebig5, buf);
#ifdef  IMLIB
	chinput_util_draw_str(window1, HZServer.normalGC, 20, HZServer.f_height+4, tbuf, strlen(tbuf));
#else
	chinput_util_draw_str(window1, HZServer.normalGC, 4, HZServer.f_height+4, tbuf, strlen(tbuf));
#endif
}

void chinput_root_draw_candidate_area (char *buf, int len)
{
	chinput_util_draw_str(window1, HZServer.normalGC, 4,
			HZServer.f_height * 2 + 11, buf, len);
}

void chinput_root_draw_panel (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	int width = HZServer.hzIwin.width;
	int height = HZServer.hzIwin.height;

	GC dimgc = HZServer.dimGC;
	GC lightgc = HZServer.lightGC;
	GC panelgc = HZServer.panelGC;

	/* fill background */
	XFillRectangle(dpy, win, panelgc, 0, 0, width, height);

	/* draw 3D separator line in the input window */
	XDrawLine(dpy, win, dimgc, 0, height/2, width, height/2);
	XDrawLine(dpy, win, lightgc, 0, height/2+1, width, height/2+1);

	/* draw 3D border */
	XDrawLine(dpy, win, lightgc, 0, 0, width-1, 0);
	XDrawLine(dpy, win, lightgc, 0, 1, width-1, 1);
	XDrawLine(dpy, win, lightgc, 0, 0, 0, height-1);
	XDrawLine(dpy, win, lightgc, 1, 0, 1, height-1);
	XDrawLine(dpy, win, dimgc, 0, height-1, width-1, height-1);
	XDrawLine(dpy, win, dimgc, 0, height-2, width-1, height-2);
	XDrawLine(dpy, win, dimgc, width-1, 0, width-1, height-1);
	XDrawLine(dpy, win, dimgc, width-2, 0, width-2, height-1);
#ifdef IMLIB
	Imlib_paste_image(icon_id, im_chinput, win, 4, 6, 16, 16);
#endif
}

void chinput_root_ba_draw_panel (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC  lightgc = HZServer.lightGC;
	GC  dimgc = HZServer.dimGC;
	GC  panelgc = HZServer.panelGC;

	int width = HZServer.hzIwin.width;
	int height = HZServer.hzIwin.height;
	int bwidth = HZServer.hzBwin.width;
	int bheight = HZServer.hzBwin.height;

	XFillRectangle(dpy, win, panelgc, width, 0, bwidth+2, bheight+2);

	/* draw 3D border */
	XDrawLine(dpy, win, lightgc, width, 0, width+bwidth-1, 0);
	XDrawLine(dpy, win, lightgc, width, 1, width+bwidth-1, 1);
	XDrawLine(dpy, win, lightgc, width, 0, width, height-1);
	XDrawLine(dpy, win, lightgc, width+1, 0, width+1, height-1);
	XDrawLine(dpy, win, dimgc, width, height-1, width+bwidth-1, height-1);
	XDrawLine(dpy, win, dimgc, width, height-2, width+bwidth-1, height-2);
	XDrawLine(dpy, win, dimgc, width+bwidth-1, 0, width+bwidth-1, height-1);
	XDrawLine(dpy, win, dimgc, width+bwidth-2, 0, width+bwidth-2, height-1);
}

void chinput_root_ka_draw_panel (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC  dimgc = HZServer.dimGC;
	GC  lightgc = HZServer.lightGC;
	GC  panelgc = HZServer.panelGC;
	int width = HZServer.hzIwin.width;
	int height = HZServer.hzIwin.height;
	int bwidth = HZServer.hzBwin.width;
	int kheight = HZServer.hzKwin.height;

	int twidth = width + bwidth;
	int theight = height +
			((HZServer.hzKwin.onflag) ? kheight : 0);

	if (!(HZServer.hzKwin.onflag))
		return;

	XFillRectangle(dpy, win, panelgc, 0, height, twidth, kheight);

	/* draw 3D border */
	XDrawLine(dpy, win, lightgc, 0, height, twidth-1, height);
	XDrawLine(dpy, win, lightgc, 0, height+1, twidth-1, height+1);
	XDrawLine(dpy, win, lightgc, 0, 0, 0, theight-1);
	XDrawLine(dpy, win, lightgc, 1, 0, 1, theight-1);
	XDrawLine(dpy, win, dimgc, 0, theight-1, twidth-1, theight-1);
	XDrawLine(dpy, win, dimgc, 0, theight-2, twidth-1, theight-2);
	XDrawLine(dpy, win, dimgc, twidth-1, 0, twidth-1, theight-1);
	XDrawLine(dpy, win, dimgc, twidth-2, 0, twidth-2, theight-1);

	chinput_root_ka_draw_button();
}

extern Boolean flag_corner;
extern Boolean flag_punct;
extern int flag_font;		// 16: 1;  24: 2;

void chinput_root_ka_draw_window (void)
{
	int i, j, step;
	int x1, y1, x2, y2;
	unsigned char str[3];

	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC dimgc = HZServer.dimGC;
	GC lightgc = HZServer.lightGC;
step = 20;

	/* draw first set of chars */
	for (i=0; i<=12; i++)
	{
		x1 = HZServer.hzKwin.offx1;
		y1 = i*step + HZServer.hzKwin.offy1 + HZServer.hzIwin.height;
		x2 = HZServer.hzKwin.offx1 + step * 16;
		y2 = y1;
		XDrawLine (dpy, win, dimgc, x1, y1-1, x2, y2-1);
		XDrawLine (dpy, win, lightgc, x1, y1, x2, y2);
	}
	for (j=0; j<=16; j++)
	{
		x1 = j*step + HZServer.hzKwin.offx1;
		y1 = HZServer.hzKwin.offy1 + HZServer.hzIwin.height;
		x2 = x1;
		y2 = HZServer.hzKwin.offy1 + HZServer.hzIwin.height + step * 12;
		XDrawLine (dpy, win, dimgc, x1-1, y1, x2-1, y2);
		XDrawLine (dpy, win, lightgc, x1, y1, x2, y2);
	}
	/* draw hanzi */
	for (i=0; i<12; i++)//four lines
	{
		for (j=0; j<16; j++)
		{
			x1 = j*step + HZServer.hzKwin.offx1 + 2;
			y1 = i*step + HZServer.hzKwin.offy1 + HZServer.hzIwin.height +
					HZServer.f_height;
			str[0] = (unsigned char)(HZServer.hzKwin.cur);
			str[1] = (unsigned char)(HZServer.hzKwin.second_start+i*16 + j);
			str[2] = '\0';
		chinput_util_draw_str(win, HZServer.normalGC, x1, y1, str, 2);
		}
	}
}

void chinput_root_ka_draw_button (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC dimgc = HZServer.dimGC;
	GC lightgc = HZServer.lightGC;

	chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc,
	HZServer.hzKwin.prevx1, HZServer.hzKwin.prevy1,
			HZServer.hzKwin.prevx2, HZServer.hzKwin.prevy2,
			HZServer.hzKwin.prevx3, HZServer.hzKwin.prevy3, True);
	chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc,
	HZServer.hzKwin.nextx1, HZServer.hzKwin.nexty1,
			HZServer.hzKwin.nextx2, HZServer.hzKwin.nexty2,
			HZServer.hzKwin.nextx3, HZServer.hzKwin.nexty3, True);
}

void chinput_root_proc_key (XEvent report)
{
	char buf[HZSERVER_BUFFER_SIZE];
	int  bufsize = HZSERVER_BUFFER_SIZE;
	KeySym keysym;
	XComposeStatus compose;
	int charcount;
// no key please 
	charcount = XLookupString((XKeyEvent *)&report, buf,
			bufsize, &keysym, &compose);

	switch (keysym)
	{
		case XK_F1:
		case XK_F12:
			break;
		case XK_F2:
			break;
		case XK_F3:
			break;
		case XK_F4:
			break;
		case XK_F5:
			break;
		case XK_F6:
			break;
		case XK_F7:
			break;
		case XK_F8:
			break;
		case XK_F9:
			break;
		case XK_F10:
			break;
		case XK_F11:
			break;
		case XK_space:
			break;
		default:
			break;
	}
}

// QJ == full corner/ half corner??
void chinput_root_proc_2byte (XEvent report)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC dimgc = HZServer.dimGC;
	GC lightgc = HZServer.lightGC;
	GC panelgc = HZServer.panelGC;
	int q_x1 = HZServer.hzBwin.q_x1;
	int q_y1 = HZServer.hzBwin.q_y1;
	int q_x2 = HZServer.hzBwin.q_x2;
	int q_y2 = HZServer.hzBwin.q_y2;
	int offset = HZServer.hzBwin.offset;

	chinput_util_draw_btn(dpy, win, dimgc, lightgc, q_x1, q_y1, q_x2, q_y2, False);
	chinput_util_wait_btn_release();
	chinput_util_draw_btn(dpy, win, dimgc, lightgc, q_x1, q_y1, q_x2, q_y2, True);
	if (chinput_util_in_box(butx, buty, q_x1, q_y1, q_x2, q_y2))
		flag_corner = (flag_corner == True ? False : True);
	// redraw label
	if (flag_corner)
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "È«", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "È«", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥þ", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥þ", 2);
	}
	else
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "°ë", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "°ë", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥b", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥b", 2);
	}
	// Alert Docking
}

void chinput_root_corner_flush (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC   panelgc = HZServer.panelGC;
	int     q_x1 = HZServer.hzBwin.q_x1;
	int     q_y1 = HZServer.hzBwin.q_y1;
	int     q_x2 = HZServer.hzBwin.q_x2;
	int     q_y2 = HZServer.hzBwin.q_y2;
	int     offset = HZServer.hzBwin.offset;
	if (flag_corner)
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "È«", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "È«", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥þ", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥þ", 2);
	}
	else
	{
		if(HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "°ë", 2);
		else if(HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "°ë", 2);
		else if(HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥b", 2);
		else if(HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label(dpy, win, panelgc,
					q_x1, q_y1, q_x2, q_y2, offset, "¥b", 2);
	}
}

void chinput_root_proc_punct (XEvent report)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC   panelgc = HZServer.panelGC;
	int     p_x1 = HZServer.hzBwin.p_x1;
	int     p_y1 = HZServer.hzBwin.p_y1;
	int     p_x2 = HZServer.hzBwin.p_x2;
	int     p_y2 = HZServer.hzBwin.p_y2;
	int     offset = HZServer.hzBwin.offset;

	chinput_util_draw_btn (HZServer.display, HZServer.window1, HZServer.dimGC,
	HZServer.lightGC, p_x1, p_y1, p_x2, p_y2, False);
	chinput_util_wait_btn_release ();
	chinput_util_draw_btn (HZServer.display, HZServer.window1, HZServer.dimGC,
			HZServer.lightGC, p_x1, p_y1, p_x2, p_y2, True);
	if (chinput_util_in_box (butx, buty,  p_x1, p_y1, p_x2, p_y2))
		flag_punct = (flag_punct == True ? False : True);
	// redraw label
	if (flag_punct)
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "£ï", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "£ï", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¢÷", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¢÷", 2);
	}
	else
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, " .", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, " .", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¡O", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¡O", 2);
	}
	// Alert Docking ?
}

void chinput_root_punct_flush (void)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC   panelgc = HZServer.panelGC;
	int     p_x1 = HZServer.hzBwin.p_x1;
	int     p_y1 = HZServer.hzBwin.p_y1;
	int     p_x2 = HZServer.hzBwin.p_x2;
	int     p_y2 = HZServer.hzBwin.p_y2;
	int     offset = HZServer.hzBwin.offset;

// redraw label
	if (flag_punct)
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "£ï", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "£ï", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¢÷", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¢÷", 2);
	}
	else
	{
		if (HZServer.encoding == HZSERVER_ENCODING_GB2312)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, " .", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_GB18030)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, " .", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¡O", 2);
		else if (HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS)
			chinput_util_draw_btn_label (dpy, win, panelgc,
					p_x1, p_y1, p_x2, p_y2, offset, "¡O", 2);
	}
}

#if 0
static void chinput_root_proc_lock (int lock)
{
	flag_lock = lock;
}
#endif

void chinput_root_proc_pop_kwindow (void)
{
	if (HZServer.hzKwin.onflag)
	{
		HZServer.hzKwin.onflag = False;
		XResizeWindow (display, window1,
				HZServer.hzIwin.width + HZServer.hzBwin.width,
				HZServer.hzIwin.height);
	}
	else
	{	/* pop up keyboard window */
		HZServer.hzKwin.onflag = True;
		/* draw the window */
		XResizeWindow (display, window1, 
				HZServer.hzIwin.width + HZServer.hzBwin.width,
				HZServer.hzIwin.height + HZServer.hzKwin.height);
	}
	chinput_root_ba_draw_panel ();
	chinput_root_ba_draw_window ();
	chinput_root_ka_draw_panel ();
	chinput_root_ka_draw_window ();
}

void chinput_root_proc_kwindow (int x0, int y0)
{
	int i, j, k;
	int x1, y1, x2, y2;
	//int step = ((HZServer.f_width == 16) ? 20 : 28);
	int step = 20;
	unsigned char str[3];
	XClientMessageEvent event;
	char *s = event.data.b;

	/* get the hanzi at pointer position */
	if (chinput_util_in_box (x0, y0, HZServer.hzKwin.offx1,
			HZServer.hzKwin.offy1 + HZServer.hzIwin.height,
			HZServer.hzKwin.offx1 + step * 16,
			HZServer.hzKwin.offy1 + HZServer.hzIwin.height + step * 12))
	{
		/* computate the right cell */
		i =  (y0 - HZServer.hzIwin.height - HZServer.hzKwin.offy1) / step;
		j =  (x0 - HZServer.hzKwin.offx1) / step;
		x1 = j*step + HZServer.hzKwin.offx1;
		y1 =  (i-1)*step + HZServer.hzKwin.offy1 + HZServer.hzIwin.height +
				HZServer.f_height + 4;
		x2 = x1 + step;
		y2 = y1 + step;

		/* sunken it */
		chinput_util_draw_btn (HZServer.display, HZServer.window1, HZServer.dimGC,
				HZServer.lightGC, x1, y1, x2, y2, False);
		chinput_util_wait_btn_release ();
		chinput_util_draw_btn (HZServer.display, HZServer.window1, HZServer.dimGC,
				HZServer.lightGC, x1, y1, x2, y2, True);

		if (!chinput_util_in_box (butx, buty, x1, y1, x2, y2))
			return;
		k = HZServer.hzKwin.second_start + i * 16 + j;
		str[0] = (unsigned char)(HZServer.hzKwin.cur);
		str[1] = (unsigned char)k;

		if ((k > HZServer.hzKwin.second_end &&
				k < HZServer.hzKwin.second_start2)||
				(k > HZServer.hzKwin.second_end2))
			return;
	}

	str[2] = '\0';
	if (0)
	{
		event.type=ClientMessage;
		event.window=window1;
		event.message_type=hz_output_atom;
		event.format=32;
		event.data.b[0] = 2;
		strncpy (s+1, (char *)str, 2);
		if (HZServer.lockw != None)
			XSendEvent (display, HZServer.lockw, False, 0, (XEvent *)&event);
		else
			XSendEvent (display, InputFocus, True, 0, (XEvent *)&event);
	}

	//XIM forward
	chinput_xim_forward_string (str, 2);
}

void chinput_root_proc_change_kwindow (int x0, int y0)
{
	Display *dpy = HZServer.display;
	Window  win  = HZServer.window1;
	GC dimgc = HZServer.dimGC;
	GC lightgc = HZServer.lightGC;
	int prevx1 = HZServer.hzKwin.prevx1;
	int prevy1 = HZServer.hzKwin.prevy1;
	int prevx2 = HZServer.hzKwin.prevx2;
	int prevy2 = HZServer.hzKwin.prevy2;
	int prevx3 = HZServer.hzKwin.prevx3;
	int prevy3 = HZServer.hzKwin.prevy3;
	int nextx1 = HZServer.hzKwin.nextx1;
	int nexty1 = HZServer.hzKwin.nexty1;
	int nextx2 = HZServer.hzKwin.nextx2;
	int nexty2 = HZServer.hzKwin.nexty2;
	int nextx3 = HZServer.hzKwin.nextx3;
	int nexty3 = HZServer.hzKwin.nexty3;

	if (chinput_util_in_box (x0, y0, nextx3, nexty3, nextx1, nexty2))
	{
		chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc, 
				nextx1, nexty1, nextx2, nexty2, nextx3, nexty3, False);
		/* wait for button release */
		chinput_util_wait_btn_release ();
		chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc,
				nextx1, nexty1, nextx2, nexty2, nextx3, nexty3, True);
		if (!chinput_util_in_box (butx, buty, nextx3, nexty3, nextx1, nexty2))
			return;
		if (HZServer.hzKwin.cur < HZServer.hzKwin.first_end){
			if ( (HZServer.encoding == HZSERVER_ENCODING_BIG5) ||
					(HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS) )
				HZServer.hzKwin.cur ++ ;
			else
				HZServer.hzKwin.cur += 2 ;
		}
		else
		{
			XBell (dpy, 100);
			return;
		}
		chinput_root_ka_draw_panel ();
		chinput_root_ka_draw_window ();
	}
	else
	{
		chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc,
				prevx1, prevy1, prevx2, prevy2, prevx3, prevy3, False);
		/* wait for button release */
		chinput_util_wait_btn_release ();
		chinput_util_draw_tri_btn (dpy, win, dimgc, lightgc,
				prevx1, prevy1, prevx2, prevy2, prevx3, prevy3, True);

		if (!chinput_util_in_box (butx, buty, prevx2, prevy3, prevx1, prevy1))
			return;
		if (HZServer.hzKwin.cur > HZServer.hzKwin.first_start)
		{
			if ( (HZServer.encoding == HZSERVER_ENCODING_BIG5) ||
					(HZServer.encoding == HZSERVER_ENCODING_BIG5HKSCS) )
				HZServer.hzKwin.cur -- ;
			else
				HZServer.hzKwin.cur -= 2;
        	}
		else
		{
			XBell (dpy, 100);
				return;	
		}
		chinput_root_ka_draw_panel ();
		chinput_root_ka_draw_window ();
	}
}

void chinput_root_proc_close_window (XEvent report)
{
	int ledx1 = HZServer.hzBwin.ledx1;
	int ledy1 = HZServer.hzBwin.ledy1;
	int ledx2 = HZServer.hzBwin.ledx2;
	int ledy2 = HZServer.hzBwin.ledy2;

	HZServer.hzBwin.flag = False;
	chinput_root_ba_draw_window ();

	chinput_util_wait_btn_release ();

	if (chinput_util_in_box (butx, buty, ledx1, ledy1, ledx2, ledy2))
	{
		/* shift + leftbutton , lock focusin window */
		if (report.xbutton.state & ShiftMask)
		{
			// Focus window
			Window fw;
			// Revert to return
			int rv;
			XGetInputFocus (display, &fw, &rv);

			/* we'd better not lock ourselves */
			if (fw != window1)
			{
				HZServer.lockw = fw;
				chinput_root_lock_window ();
			}
			else
			{
				HZServer.hzBwin.flag = True;
				chinput_root_ba_draw_window ();
			}
			return;
		}
		/* the first time force close the lock window */
		else if (HZServer.lockw != None)
		{
			chinput_root_unlock_window ();
			HZServer.hzBwin.flag = True;
			chinput_root_ba_draw_window ();
			return;
		}
		chinput_util_exit ();
	}
	else
	{
		HZServer.hzBwin.flag = True;
		chinput_root_ba_draw_window ();
	}
}

/* there is a bug in this routine, i.e., I didnot reset the buffer
   of input area */
void chinput_root_resize_window (int count)
{
	int twidth, theight;
	int ht;

	if (dmode != HZSERVER_DMODE_ROOT)
		return;

	if ((HZServer.hzIwin.cols >= HZSERVER_MAXCOLS && count > 0) ||
			(HZServer.hzIwin.cols <= HZSERVER_MINCOLS && count < 0 ))
		return;
	HZServer.hzIwin.cols = count;

	HZServer.hzIwin.width = HZServer.hzIwin.cols *
			HZServer.f_width / 2 + 20;

	twidth = HZServer.hzIwin.width + HZServer.hzBwin.width;
	theight = HZServer.hzIwin.height + ((HZServer.hzKwin.onflag) ?
			HZServer.hzKwin.height : 0);
	ht = HZServer.hzIwin.height + HZServer.hzKwin.height;

	HZServer.hzBwin.ledx1 = twidth - 25;
	HZServer.hzBwin.ledy1 = 5;
	HZServer.hzBwin.ledx2 = twidth - 5;
	HZServer.hzBwin.ledy2 = 11;

	HZServer.hzBwin.btnx1 = twidth - 23;
	HZServer.hzBwin.btny1 = HZServer.hzIwin.height - 10;
	HZServer.hzBwin.btnx2 = twidth - 7;
	HZServer.hzBwin.btny2 = HZServer.hzIwin.height - 10;
	HZServer.hzBwin.btnx3 = twidth - 15;
	HZServer.hzBwin.btny3 = HZServer.hzIwin.height - 3;

	HZServer.hzBwin.q_x1 = HZServer.hzBwin.ledx1 - 26;
	HZServer.hzBwin.q_y1 = HZServer.hzBwin.ledy1;
	HZServer.hzBwin.q_x2 = HZServer.hzBwin.q_x1 + 19;
	HZServer.hzBwin.q_y2 = HZServer.hzBwin.q_y1 + 19;

	HZServer.hzBwin.p_x1 = HZServer.hzBwin.q_x1;
	HZServer.hzBwin.p_y1 = HZServer.hzBwin.q_y1 + 22;
	HZServer.hzBwin.p_x2 = HZServer.hzBwin.p_x1 + 19;
	HZServer.hzBwin.p_y2 = HZServer.hzBwin.p_y1 + 19;
	HZServer.hzBwin.offset = 16;

	HZServer.hzKwin.prevx2 = twidth - 50;
	HZServer.hzKwin.prevy2 = ht - 20;
	HZServer.hzKwin.prevx3 = twidth - 40;
	HZServer.hzKwin.prevy3 = ht - 30;
	HZServer.hzKwin.prevx1 = twidth - 40;
	HZServer.hzKwin.prevy1 = ht - 10;
	HZServer.hzKwin.nextx1 = twidth - 10;
	HZServer.hzKwin.nexty1 = ht - 20;
	HZServer.hzKwin.nextx3 = twidth - 20;
	HZServer.hzKwin.nexty3 = ht - 30;
	HZServer.hzKwin.nextx2 = twidth - 20;
	HZServer.hzKwin.nexty2 = ht - 10;

	XResizeWindow(display, window1, twidth, theight);
	chinput_root_input_flush();
}

void chinput_root_input_flush (void)
{
	char mbuf[256];
	if (flag_refresh)
		return;
	bzero (mbuf, 256);
	if (flag_english)
		strcpy (mbuf, input_buf);
	else
		IMM_GetInputDisplay(chinput_imm, mbuf, sizeof (mbuf));
	chinput_root_draw_input_area (mbuf, strlen(mbuf));
}

void chinput_root_candidate_flush (void)
{
	char mbuf[256];
	if (flag_refresh)
		return;
	bzero(mbuf, 256);
	IMM_GetSelectDisplay (chinput_imm, mbuf, sizeof (mbuf));
	if (strlen(mbuf) == 0)
		flag_found = 0;
	else
		flag_found = 1;
	chinput_root_draw_candidate_area (mbuf, strlen (mbuf));
}

void chinput_root_panel_flush (void)
{
	//main area
	chinput_root_draw_panel ();

	//button area
	chinput_root_ba_draw_panel ();
	chinput_root_ba_draw_window ();

	//keyboard area
	chinput_root_ka_draw_panel ();
	chinput_root_ka_draw_window ();
}

//flushing contents contains three part
//1. the panel itself
//2. the input buffer
//3. the candidate buffer
void chinput_root_flush (void)
{
	chinput_root_panel_flush ();
	chinput_root_input_flush ();
	chinput_root_candidate_flush ();
}

