/*
Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions: The above copyright notice and this
permission notice shall be included in all copies or substantial
portions of the Software.


THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.


Except as contained in this notice, the names of The Open Group and/or
Sun Microsystems, Inc. shall not be used in advertising or otherwise to
promote the sale, use or other dealings in this Software without prior
written authorization from The Open Group and/or Sun Microsystems,
Inc., as applicable.


X Window System is a trademark of The Open Group

OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
logo, LBX, X Window System, and Xinerama are trademarks of the Open
Group. All other trademarks and registered trademarks mentioned herein
are the property of their respective owners. No right, title or
interest in or to any trademark, service mark, logo or trade name of
Sun Microsystems, Inc. or its licensors is granted.

*/

#include <stdio.h>
#include <locale.h>

#include "encode.h"
#include "KeyboardConfig.h"
#include "hzinput.h"

#define MAX_LINE_LEN 		256

#define DEFAULT_KEYBOARD_CONFIG_FILE	"keyboard.cfg"
#define DEFAULT_KEYBOARD_LAYOUT_FILE	"common/keyboard_layout.txt"

#define LABEL_STR		"LABEL"
#define TYPE_STR		"TYPE"
#define ENCODE_STR		"ENCODE"
#define STRING_TYPE_STR		"COMMIT_AS_STRING"
#define KEY_TYPE_STR		"COMMIT_AS_KEY"
#define LIST_BEGIN_STR		"LIST_BEGIN"
#define LIST_END_STR		"LIST_END"

/* Used by KeyboardAux */
int 			gKeyboardNum = 0;
VirtualKeyboard  	*gVKB[MAX_KEYBOARD_NUM + 1];

/* Used by PaletteAux to create Keyboard List menu */
int 			gVKB_Name_Num = 0;
char 			*gVKB_Name_List[MAX_KEYBOARD_NUM + 2];

/* Used for IME Keyboard */
VirtualKeyboard		*gIMEVKB[MAX_ENGINE_NUM];
char 			*gIMEVKB_Name_List[MAX_ENGINE_NUM];

static int  nLocaleID;

static char *Close_String_CN = "关闭";
static char *Close_String_TW = "關閉";

static char *Keyboard_String_CN = "键盘";
static char *Keyboard_String_TW = "鍵盤";

static char *Keyboard_String = NULL;
static char *CloseKeyboard_String = NULL;

int read_keyboard_config_file(char *path_name, char *file_name);
int read_keyboard_layout_file(char *path_name, char *file_name);
void set_ctrlkey_label(VirtualKeyboard *pVKB);
void set_basekey_label(VirtualKeyboard *pVKB, char *line);
void set_keyboard_encode(VirtualKeyboard *pVKB, char *encode_name);
void set_keyboard_label(VirtualKeyboard *pVKB, char *cname);
int get_pc_keyboard_item(char *sLocaleName);
VirtualKeyboard *KeyboardItem_Malloc();
int KeyboardItem_Free(VirtualKeyboard *pVKB);
void Keyboards_Print();

void get_keyboard_line(FILE *fd, char *line)
{
	int line_ptr;
	char line_buf[256], *ptr;

	line_ptr = 0;
	line[0] = '\0';

	/* get line with no space */
 	while(fgets(line_buf, 255, fd) != NULL) {
		ptr = line_buf;

		/* skip space keys */
		while(*ptr && isspace(*ptr)) ptr++;

		/* if is space line, get new line */
		if (*ptr == '\n' || *ptr == '\0')
			continue;

		while(*ptr != '\n' && *ptr != '\0' && line_ptr < MAX_LINE_LEN) 
			line[line_ptr++] = *ptr++;

		/* trim right space */
		while (isspace(line[line_ptr-1])) line_ptr--;
		line[line_ptr] = '\0';

		/* if the line end with '\', then continue read the next line */
		if (line[line_ptr-1] == '\\') {
			line_ptr--;
			line[line_ptr] = '\0';
			continue;
		}

		break;
	}
}

/*  
For keyboard.cfg 

format as follow:

[zh_CN.EUC]
zh_CN.EUC/keyboard_layout.txt
common/keyboard_layout.txt

[zh_CN.GBK]
zh_CN.GBK/keyboard_layout1.txt
zh_CN.GBK/keyboard_layout2.txt
common/keyboard_layout.txt

base directory:  /usr/lib/im/locale/<locale>/

*/
int read_keyboard_config_file(char *path_name, char *file_name)
{
	char	line[MAX_LINE_LEN], sFileName[256];
	char 	*ptr, *locale_str;
	FILE 	*fd;
	int 	locale_flag = ENCODE_ERROR;
	int 	have_matched = 0;
	int 	len;

	sprintf(sFileName, "%s/%s", path_name, file_name);
	DEBUG_printf("File Name:%s\n", sFileName);
	fd = fopen(sFileName, "r");
	if (!fd) {
		DEBUG_printf("Can not open the file:%s\n", sFileName);
		return(-1);
	}

	do {
		get_keyboard_line(fd, line);

		if (line[0] == '\0') break;
		if (line[0] == '#') continue;

		len = strlen(line);
		if (line[0] == '[' && line[len-1] == ']') {

			if (have_matched == 1) break;

			/* Check the previous item is a formal item */
			/* get english name of the item */
			ptr = line + 1;
			while(isspace(*ptr)) ptr++;
			locale_str = ptr;
			
			ptr = line + len - 2;
			while(isspace(*ptr)) ptr--;
			*(ptr+1) = '\0';

			DEBUG_printf("read_config_file: locale_name:%s\n", locale_str);
			if (*locale_str) {
				locale_flag = get_encodeid_from_locale(locale_str);
			}
			continue;
		}

		if (locale_flag == ENCODE_ERROR || locale_flag != nLocaleID) continue;

		have_matched = 1;

		/* read the layout file, in line[], contain the config file name. */
		read_keyboard_layout_file(path_name, line);
		
	} while (1);

	fclose(fd);

	/* if no entry for the locale, read the default layout file. */
	if (have_matched == 0)
		return(-1);

	return(0);
}

/* 
For keyboard_layout.txt

Format as follow:

[ english name ]
LABEL	chinese name
TYPE  	COMMIT_AS_STRING/COMMIT_AS_KEY
ENCODE  UTF-8
LIST_BEGIN
a   	lower_str	upper_str
LIST_END

*/
int read_keyboard_layout_file(char *path_name, char *file_name)
{
	char	line[MAX_LINE_LEN], sFileName[256];
	char 	*ptr, *ename_str;
	FILE 	*fd;
	int 	i, len, need_alloc_new_item;
	int 	list_begin = 0;
	VirtualKeyboard *pVKB;

	sprintf(sFileName, "%s/%s", path_name, file_name);
	DEBUG_printf("File Name:%s\n", sFileName);
	fd = fopen(sFileName, "r");
	if (!fd) {
		DEBUG_printf("Can not open the file:%s\n", sFileName);
		return(-1);
	}

	do {
		if (gKeyboardNum >= MAX_KEYBOARD_NUM) break;

		get_keyboard_line(fd, line);

		if (line[0] == '\0') break;
		if (line[0] == '#') continue;

		len = strlen(line);
		if (line[0] == '[' && line[len-1] == ']') {
			list_begin = 0;

			/* Check the previous item is a formal item */
			need_alloc_new_item = 1;
			if (gKeyboardNum > 0) {
				pVKB = gVKB[gKeyboardNum-1];
				if (pVKB != NULL) {
					if (pVKB->cname == NULL)
						need_alloc_new_item = 0;
				}
			}

			if (need_alloc_new_item == 1) {
				pVKB = (VirtualKeyboard *)KeyboardItem_Malloc();
				if (pVKB == NULL) {
					DEBUG_printf("No memory \n");
					break;
				}

				gVKB[gKeyboardNum] = pVKB;
				gKeyboardNum ++;
			}
			
			/* get english name of the item */
			ptr = line + 1;
			while(isspace(*ptr)) ptr++;
			ename_str = ptr;
			
			ptr = line + len - 2;
			while(isspace(*ptr)) ptr--;
			*(ptr+1) = '\0';

			DEBUG_printf("ename_str:%s###\n", ename_str);
			if (*ename_str) {
				if (pVKB->ename) free((char *)pVKB->ename);
				pVKB->ename = (char *)strdup(ename_str);
			}

			continue;
		}
		
		if (!(strncasecmp(line, LABEL_STR, strlen(LABEL_STR)))) {
			ptr = line + strlen(LABEL_STR);
			while(*ptr && isspace(*ptr)) ptr++;
			if (*ptr) {
				if (pVKB->cname) free((char *)pVKB->cname);
				set_keyboard_label(pVKB, ptr);
				DEBUG_printf("cname:%s\n", pVKB->cname);
			}
			continue;
		}

		if (!(strncasecmp(line, ENCODE_STR, strlen(ENCODE_STR)))) {
			ptr = line + strlen(ENCODE_STR);
			while(*ptr && isspace(*ptr)) ptr++;
			if (*ptr) {
				set_keyboard_encode(pVKB, ptr);
				DEBUG_printf("encode:%s\n", ptr);
			}
			continue;
		}

		if (!(strncasecmp(line, TYPE_STR, strlen(TYPE_STR)))) {
			ptr = line + strlen(TYPE_STR);
			while(*ptr && isspace(*ptr)) ptr++;
			if (*ptr) {
				DEBUG_printf("TYPE: %s\n", ptr);
				if (!(strncasecmp(ptr, KEY_TYPE_STR, strlen(KEY_TYPE_STR)))) {
					pVKB->type = KEYBOARD_KEY_TYPE;
				} else {
					pVKB->type = KEYBOARD_STRING_TYPE;
				}
			}
			continue;
		}

		if (!(strncasecmp(line, LIST_BEGIN_STR, strlen(LIST_BEGIN_STR)))) {
			list_begin = 1;
			continue;
		}

		if (!(strncasecmp(line, LIST_END_STR, strlen(LIST_END_STR)))) {
			list_begin = 0;
			continue;
		}

		if (list_begin == 1) {
			set_basekey_label(pVKB, line);
		}

	} while (1);

	fclose(fd);
	return(0);
}

void set_ctrlkey_label(VirtualKeyboard *pVKB)
{
	if (pVKB == NULL) return;

	pVKB->ctrlkey[VK_BackSpace].label_str = BACKSPACE_KEY_LABEL;
	pVKB->ctrlkey[VK_Tab].label_str = TAB_KEY_LABEL;
	pVKB->ctrlkey[VK_Caps_Lock].label_str = CAPS_KEY_LABEL;
	pVKB->ctrlkey[VK_Enter].label_str = ENTER_KEY_LABEL;
	pVKB->ctrlkey[VK_Shift_L].label_str = SHIFT_KEY_LABEL;
	pVKB->ctrlkey[VK_Control_L].label_str = CTRL_KEY_LABEL;
	pVKB->ctrlkey[VK_Alt_L].label_str = ALT_KEY_LABEL;
	pVKB->ctrlkey[VK_space].label_str = SPACE_KEY_LABEL;
	pVKB->ctrlkey[VK_escape].label_str = ESCAPE_KEY_LABEL;
}

void set_basekey_label(VirtualKeyboard *pVKB, char *line)
{
	char ch, i, index;
	char *ptr, *lower_str, *upper_str, *label_str;
	
	if (!line || !*line) return;

	ch = tolower(line[0]);

	label_str = KEYLIST_LOWER;
	index = 0;
	for (i=0; i< strlen(label_str); i++) {
		if (ch == *(label_str + i)) {
			index = i;
			break;
		}
	}
	
	/* skip spaces */
	ptr = line + 1;
	while (*ptr && isspace(*ptr)) ptr++;
	lower_str = ptr;

	/* skip to space */
	while (*ptr && !isspace(*ptr)) ptr++;
	if (*ptr) {
		*ptr = '\0';
		ptr++;
	}

	while (*ptr && isspace(*ptr)) ptr++;
	upper_str = ptr;

	while (*ptr && !isspace(*ptr)) ptr++;
	*ptr = '\0';

	if (pVKB->encode != ENCODE_UTF8) {
		if (*lower_str) pVKB->basekey[index].lower_str = (char *)strdup(lower_str);
		if (*upper_str) pVKB->basekey[index].upper_str = (char *)strdup(upper_str);
	} else {
		char buffer[256], *tmp_buf;
		int ilen, olen, ret;

		tmp_buf = buffer;
		ilen = strlen(lower_str);
		olen = 256;
		memset(buffer, 0, olen);
		ret = Convert_UTF8_To_Native(nLocaleID, lower_str, ilen, &tmp_buf, &olen);
		if (ret == 0)
			pVKB->basekey[index].lower_str = (char *)strdup(buffer);
		else 
			pVKB->basekey[index].lower_str = (char *)strdup(lower_str);

		ilen = strlen(upper_str);
		memset(buffer, 0, olen);
		ret = Convert_UTF8_To_Native(nLocaleID, upper_str, ilen, &tmp_buf, &olen);
		if (ret == 0)
			pVKB->basekey[index].upper_str = (char *)strdup(buffer);
		else 
			pVKB->basekey[index].upper_str = (char *)strdup(upper_str);


	}
}

void set_keyboard_label(VirtualKeyboard *pVKB, char *cname)
{
	if (!cname || !*cname) return;

	if (pVKB->encode != ENCODE_UTF8) {
		pVKB->cname = (char *)strdup(cname);
	} else {
		char buffer[256], *tmp_buf;
		int ilen, olen, ret;

		tmp_buf = buffer;
		ilen = strlen(cname);
		olen = 256;
		memset(buffer, 0, olen);
		ret = Convert_UTF8_To_Native(nLocaleID, cname, ilen, &tmp_buf, &olen);
		if (ret == 0)
			pVKB->cname = (char *)strdup(buffer);
		else 
			pVKB->cname = (char *)strdup(cname);
	}
}

void set_keyboard_encode(VirtualKeyboard *pVKB, char *encode_name)
{

	if (!encode_name || !*encode_name) return;
	pVKB->encode = get_encodeid_from_name(encode_name);
}

int get_pc_keyboard_item(char *sLocaleName)
{
	VirtualKeyboard *pVKB;
	char str[2], label_str[128], *tmp_str;
	int i, lang_id;

	/* add PC Keyboard Item */
	pVKB = (VirtualKeyboard *)KeyboardItem_Malloc();
	if (pVKB == NULL) {
		DEBUG_printf("No memory \n");
		return;
	}

	pVKB->ename = (char *)strdup("pc keyboard");
	pVKB->type  = KEYBOARD_KEY_TYPE;
	pVKB->encode = ENCODE_UTF8;

	lang_id = get_langid_from_locale(sLocaleName);
	if (lang_id == LANG_ZH_TW || lang_id == LANG_ZH_HK)
		sprintf(label_str, "PC %s", Keyboard_String_TW);
	else 
		sprintf(label_str, "PC %s", Keyboard_String_CN);

	set_keyboard_label(pVKB, label_str);

	for (i=0; i<MAX_BASEKEY_NUM; i++) {
		tmp_str = KEYLIST_LOWER;
		str[0] = *(tmp_str + i);
		str[1] = 0;
		pVKB->basekey[i].lower_str = (char *)strdup(str);

		tmp_str = KEYLIST_UPPER;
		str[0] = *(tmp_str + i);
		str[1] = 0;
		pVKB->basekey[i].upper_str = (char *)strdup(str);

	}
		
	gVKB[gKeyboardNum] = pVKB;
	gKeyboardNum ++;
}

/* Add VKB List for KeyboardAux */
VirtualKeyboard *KeyboardItem_Malloc()
{
	VirtualKeyboard *pVKB;
	int i;

	pVKB = (VirtualKeyboard *)calloc(1, sizeof(VirtualKeyboard));
	if (pVKB == NULL) return(NULL);

	pVKB->ename = NULL;
	pVKB->cname = NULL;
	pVKB->type  = KEYBOARD_STRING_TYPE;
	pVKB->encode = ENCODE_ERROR;

	set_ctrlkey_label(pVKB);

	for (i=0; i<MAX_BASEKEY_NUM; i++) {
		pVKB->basekey[i].lower_str = NULL;
		pVKB->basekey[i].upper_str = NULL;
	}

	return(pVKB);
}


int KeyboardItem_Free(VirtualKeyboard *pVKB)
{
	int i;

	if (pVKB == NULL) return;

	if (pVKB->ename) free(pVKB->ename);
	if (pVKB->cname) free(pVKB->cname);

	for (i=0; i<MAX_BASEKEY_NUM; i++) {
		if (pVKB->basekey[i].lower_str) free(pVKB->basekey[i].lower_str);
		if (pVKB->basekey[i].upper_str) free(pVKB->basekey[i].upper_str);
	}

	free((char *)pVKB);
}

int Keyboards_Init()
{
	int i, ret;
	char *sLocaleName, *lang_name, path_name[64];

	gKeyboardNum = 0;
	for (i=0; i<MAX_KEYBOARD_NUM + 1; i++)
		gVKB[i] = NULL;

	for (i=0; i<MAX_ENGINE_NUM; i++) 
		gIMEVKB[i] = NULL;

	sLocaleName = setlocale(LC_CTYPE, NULL);
	nLocaleID = get_encodeid_from_locale(sLocaleName);

	lang_name = (char *)get_langname_from_locale(sLocaleName);
	sprintf(path_name, "/usr/lib/im/locale/%s", lang_name);

	DEBUG_printf("path_name:%s\n", path_name);

	get_pc_keyboard_item(sLocaleName);

	ret = read_keyboard_config_file(path_name, DEFAULT_KEYBOARD_CONFIG_FILE);

	/* if not ready */
	if (ret == -1) 
		read_keyboard_layout_file(path_name, DEFAULT_KEYBOARD_LAYOUT_FILE);
/*
	Keyboards_Print();
*/
}

int Keyboards_Done()
{
	int i, j;

	for (i=0; i<gKeyboardNum; i++) {
		KeyboardItem_Free(gVKB[i]);
		gVKB[i] = NULL;
	}

	for (i=0; i<MAX_ENGINE_NUM; i++) {
		KeyboardItem_Free(gIMEVKB[i]);
		gIMEVKB[i] = NULL;
	}
}

void Keyboards_Print()
{
	VirtualKeyboard *pVKB;
	int i, j;
	char ch, *label_str;

	label_str = KEYLIST_LOWER;
	for (i=0; i<gKeyboardNum; i++) {
		DEBUG_printf("\n\nKeyboard No %d\n", i);
		pVKB = gVKB[i];
		if (pVKB == NULL) continue;

		if (pVKB->ename) DEBUG_printf("ename:%s#\n", pVKB->ename);
		if (pVKB->cname) DEBUG_printf("cname:%s#\n", pVKB->cname);

		for (j=0; j<MAX_BASEKEY_NUM; j++) {
			if (pVKB->basekey[j].lower_str)  {
				DEBUG_printf("%c:#%s#       ", *(label_str + j), pVKB->basekey[j].lower_str);
				if (pVKB->basekey[j].upper_str) 
					DEBUG_printf("#%s#", pVKB->basekey[j].upper_str);
				DEBUG_printf("\n");
			}
		}
	}
}

/* Create VKB Name List for PaletteAux to create menu */
int VKB_Name_List_Init()
{
	int i, lang_id;
	int ilen, olen, ret;
	char buffer[256], *label_str, *tmp_buf;
	char *sLocaleName, *Close_String;

	gVKB_Name_Num = 0;
	for (i=0; i<MAX_KEYBOARD_NUM + 2; i++)
		gVKB_Name_List[i] = NULL;

	for (i=0; i<MAX_ENGINE_NUM; i++)
		gIMEVKB_Name_List[i] = NULL;

	sLocaleName = setlocale(LC_CTYPE, NULL);
	lang_id = get_langid_from_locale(sLocaleName);
	nLocaleID = get_encodeid_from_locale(sLocaleName);

	if (lang_id == LANG_ZH_TW || lang_id == LANG_ZH_HK)
		label_str = Close_String_TW;
	else 
		label_str = Close_String_CN;

	ilen = strlen(label_str);
	olen = 256;
	memset(buffer, 0, olen);
	tmp_buf = buffer;
	ret = Convert_UTF8_To_Native(nLocaleID, label_str, ilen, &tmp_buf, &olen);
	if (ret == 0)
		Close_String = (char *) strdup(buffer);
	else 
		Close_String = (char *) strdup(label_str);

	if (lang_id == LANG_ZH_TW || lang_id == LANG_ZH_HK)
		label_str = Keyboard_String_TW;
	else 
		label_str = Keyboard_String_CN;

	ilen = strlen(label_str);
	olen = 256;
	memset(buffer, 0, olen);
	tmp_buf = buffer;
	ret = Convert_UTF8_To_Native(nLocaleID, label_str, ilen, &tmp_buf, &olen);
	if (ret == 0)
		Keyboard_String = (char *)strdup(buffer);
	else 
		Keyboard_String = (char *)strdup(label_str);

	/* form "Close Keyboard" */
	if (Close_String && Keyboard_String) {
		sprintf(buffer, "%s%s", Close_String, Keyboard_String);
	} else {
		sprintf(buffer, "%s %s", "Close", "Keyboard");
	}
	CloseKeyboard_String = (char *)strdup(buffer);
	if (Close_String) free((char *)Close_String);

	Keyboards_Init();

	for (i=0; i<gKeyboardNum; i++) {
		gVKB_Name_List[i] = (char *)strdup(gVKB[i]->cname);
	}
 	gVKB_Name_Num = gKeyboardNum;
	
	Keyboards_Done();
}

int VKB_Name_List_Done()
{
	int i;

	for (i=0; i<gKeyboardNum; i++) {
		if (gVKB_Name_List[i])
			free((char *)gVKB_Name_List[i]);
		gVKB_Name_List[i] = NULL;
	}

	for (i=0; i<MAX_ENGINE_NUM; i++) {
		if (gIMEVKB_Name_List[i] != NULL)
			free((char *)gIMEVKB_Name_List[i]);
		gIMEVKB_Name_List[i] = NULL;
	}

	if (Keyboard_String)
		free((char *)Keyboard_String);
	if (CloseKeyboard_String)
		free((char *)CloseKeyboard_String);

	gVKB_Name_Num = 0;
}

int VKB_Name_List_Create(int engine_id)
{
 	gVKB_Name_Num = gKeyboardNum;

	if (engine_id >= 0 && engine_id < MAX_ENGINE_NUM) {
		if (gIMEVKB_Name_List[engine_id]) {
			gVKB_Name_List[gVKB_Name_Num] = gIMEVKB_Name_List[engine_id];
			gVKB_Name_Num ++;
		}
	}

	gVKB_Name_List[gVKB_Name_Num] = CloseKeyboard_String;
	gVKB_Name_Num ++;
}

int IMEVKB_Name_List_Add(int engine_id, char *sIMEName)
{
	char tmp_name[128];

	if (engine_id < 0 || engine_id >= MAX_ENGINE_NUM) return;

	if (Keyboard_String)
		sprintf(tmp_name, "%s%s", sIMEName, Keyboard_String);
	else
		sprintf(tmp_name, "%s %s", sIMEName, "Keyboard");

	gIMEVKB_Name_List[engine_id] = (char *)strdup(tmp_name);
}

int IMEVKB_Check_If_Exist(int engine_id)
{
	if (engine_id < 0 || engine_id >= MAX_ENGINE_NUM) return;

	if (gIMEVKB_Name_List[engine_id] != NULL)
		return(1);
	else
		return(0);
}

int IMEVKB_Keymap_Add(int engine_id, char **keymap_buf)
{
	VirtualKeyboard *pVKB;
	char ch, str[2], label_str[128], *tmp_str;
	int i;

	if (engine_id < 0 || engine_id >= MAX_ENGINE_NUM) return;

	if (gIMEVKB[engine_id])
		KeyboardItem_Free(gIMEVKB[engine_id]);

	/* add IME Keyboard Item */
	pVKB = (VirtualKeyboard *)KeyboardItem_Malloc();
	if (pVKB == NULL) {
		DEBUG_printf("No memory \n");
		return;
	}

	pVKB->ename = (char *)strdup("ime keyboard");
	pVKB->cname = (char *)strdup("ime keyboard");
	pVKB->type  = KEYBOARD_KEY_TYPE;
	pVKB->encode = ENCODE_ERROR;

	for (i=0; i<MAX_BASEKEY_NUM; i++) {
		tmp_str = KEYLIST_LOWER;
		ch = *(tmp_str + i) - 0x20;
		tmp_str = keymap_buf[ch];
		if (*tmp_str) {
/*
			DEBUG_printf("keymap[%c]: %s\n", ch + 0x20, tmp_str);
*/
			pVKB->basekey[i].lower_str = (char *)strdup(tmp_str);
		} else {
			tmp_str = KEYLIST_LOWER;
			str[0] = *(tmp_str + i);
			str[1] = 0;
			pVKB->basekey[i].lower_str = (char *)strdup(str);
		}

		tmp_str = KEYLIST_UPPER;
		str[0] = *(tmp_str + i);
		str[1] = 0;
		pVKB->basekey[i].upper_str = (char *)strdup(str);
	}
		
	gIMEVKB[engine_id] = pVKB;
}

