Files
MiniGUI/obsolete/ime/hzinput.c

1841 lines
49 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT NOTICE
//
// The following open source license statement does not apply to any
// entity in the Exception List published by FMSoft.
//
// For more information, please visit:
//
// https://www.fmsoft.cn/exception-list
//
//////////////////////////////////////////////////////////////////////////////
/*
* This file is part of MiniGUI, a mature cross-platform windowing
* and Graphics User Interface (GUI) support system for embedded systems
* and smart IoT devices.
*
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
* Copyright (C) 1998~2002, WEI Yongming
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Or,
*
* As this program is a library, any link to this program must follow
* GNU General Public License version 3 (GPLv3). If you cannot accept
* GPLv3, you need to be licensed from FMSoft.
*
* If you have got a commercial license of this program, please use it
* under the terms and conditions of the commercial license.
*
* For more information about the commercial license, please refer to
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
*/
/*
** $Id: hzinput.c 8944 2007-12-29 08:29:16Z xwyan $
**
** hzinput.c: The GB2312 IME window.
**
** Orignally by KANG Xiaoning, some code from cce by He Rui.
**
** Copyright (C) 1998, 1999 He Rui (herui@cs.duke.edu)
** Copyright (C) 1999 Kang Xiaoning.
** Copyright (C) 2000 Zheng Xiang.
** Copyright (C) 2000, 2001, 2002 Wei Yongming.
** Copyright (C) 2003 ~ 2007 Feynman Software.
**
** Current maintainer: Wei Yongming
** Create date: 1999/04/01
**
** Used abbreviations:
** ime: input method
** punc: punctuate mark
**
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** 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. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
** Modify records:
**
** Who When Where For What
**-----------------------------------------------------------------------------
** WEI Yongming 1999/06/14 Tsinghua Message dispatching
** GONG Xiaorui 1999/07/01 HongShiFang Soft keyboard
** WEI Yongming 1999/07/17 Tsinghua Add some local functions
** WEI Yongming 1999/08/24 Tsinghua Remove soft keyboard.
** WEI Yongming 1999/08/29 Tsinghua Handle some special keys.
** Wei Yongming 1999/09/01 Tsinghua Translat punc marks.
** Wei Yongming 1999/09/01 Tsinghua Translat punc marks.
** Wei Yongming 2000/11/06 BluePoint Merge pinyin module by Zheng Xiang.
**
** TODO:
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "endianrw.h"
#include "misc.h"
#include "hzinput.h"
#include "pinyin.h"
/************ private functions *******************/
static BOOL hz_input_init(void);
static void hz_input_done(void);
static void unload_input_table(int i);
static BOOL hz_filter(unsigned char key, LPARAM lParam);
static int toggle_input_method(void);
static void toggle_half_full(void);
static void set_active_input_method(int);
static void refresh_input_method_area(HWND hwnd, HDC hDC);
static void DispSelection(HDC hDC);
static void FindMatchKey(void);
static void FillMatchChars(int j);
static void FillAssociateChars(int index);
static void FindAssociateKey(int index);
static hz_input_table* IntCode_Init(void);
static void IntCode_FindMatchKey(void);
static void IntCode_FillMatchChars(int index);
static void intcode_hz_filter(unsigned char key,LPARAM lParam);
/***************************************************************************
* variable defines *
***************************************************************************/
#define VERSION_STRING "Chinese Input"
static BOOL bTwoLines;
static char ime_tab_path [MAX_PATH + 1];
static const unsigned char fullchar[] =
" !”#$%&’()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ〔\〕^□"
" ";
#define CPUNCTYPE_1TO1 0
#define CPUNCTYPE_1TO2 1
#define CPUNCTYPE_CYCLE 2
#define CTRLBTN_WIDTH 16
#define CTRLBTN_HEIGHT 16
typedef struct PuncMark
{
unsigned char epunc;
int type;
int currone; // only for cycle
unsigned char* cpunc;
}PUNCMARK;
static PUNCMARK puncmark[] =
{
{'`', 0, 0, "·"},
{'~', 0, 0, ""},
{'!', 0, 0, ""},
{'@', 0, 0, ""},
{'#', 0, 0, ""},
{'$', 0, 0, ""},
{'%', 0, 0, ""},
{'^', CPUNCTYPE_1TO2, 0, "……"},
{'&', 0, 0, "§"},
{'*', 0, 0, "×"},
{'_', CPUNCTYPE_1TO2, 0, "——"},
{'(', CPUNCTYPE_CYCLE, 0, ""},
{')', CPUNCTYPE_CYCLE, 0, ""},
{'{', CPUNCTYPE_CYCLE, 0, "《》"},
{'}', CPUNCTYPE_CYCLE, 0, "〈〉"},
{'[', CPUNCTYPE_CYCLE, 0, "〖〗"},
{']', CPUNCTYPE_CYCLE, 0, "【】"},
{'\\', 0, 0, "÷"},
{'|', 0, 0, ""},
{';', 0, 0, ""},
{':', 0, 0, ""},
{'\'', CPUNCTYPE_CYCLE, 0, ""},
{'\"', CPUNCTYPE_CYCLE, 0, "“”"},
{',', 0, 0, ""},
{'.', 0, 0, ""},
{'<', CPUNCTYPE_CYCLE, 0, "「」"},
{'>', CPUNCTYPE_CYCLE, 0, "『』"},
{'?', 0, 0, ""},
{'/', 0, 0, ""}
};
static int IsOpened; /* 1 for opened, 0 for closed */
static int IsHanziInput; /* 0 for ascii, 1 for hanzi input */
static int IsFullChar; /* 0 for half char, 1 for full char */
static int IsFullPunc; /* 0 for half punctuate marks, 1 for full marks */
static int CurIME;
static int nIMENr; /* effetive IME method number */
static HWND sg_hTargetWnd = 0; // target window of ime.
static hz_input_table *input_table[NR_INPUTMETHOD],*cur_table = NULL;
static char seltab[16][MAX_PHRASE_LENGTH];
static int CurSelNum=0; /* Current Total Selection Number */
static unsigned long InpKey[MAX_INPUT_LENGTH],save_InpKey[MAX_INPUT_LENGTH];
/* Input key buffer */
static int InputCount,InputMatch, StartKey,EndKey;
static int save_StartKey,save_EndKey, save_MultiPageMode,
save_NextPageIndex, save_CurrentPageIndex;
static int NextPageIndex,CurrentPageIndex,MultiPageMode;
/* When enter MultiPageMode:
StartKey .... CurrentPageIndex .... NextPageIndex .... EndKey
*/
static unsigned long val1, val2,key1,key2;
static int IsAssociateMode;
static int CharIndex[15]; // starting index of matched char/phrases
static const BITMAP* sg_bmpIME; // the bmp of the IME control button
static int UseAssociateMode = 0;
/* 6 bit a key mask */
static const unsigned long mask[]=
{
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x3F000000, 0x3FFC0000, 0x3FFFF000, 0x3FFFFFC0, 0x3FFFFFFF, 0x3FFFFFFF,
0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF
};
/***************************************************************************
* some local functions *
***************************************************************************/
static hz_input_table* load_input_method(char *filename)
{
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
int i;
#endif
int nread;
FILE *fd;
char phrase_filename[100],assoc_filename[100];
hz_input_table *table;
table = calloc (1, sizeof(hz_input_table));
if (table == NULL)
return NULL;
fd = fopen(filename, "rb");
if (fd == NULL) {
free (table);
return NULL;
}
nread = fread(table, sizeof(hz_input_table),1,fd);
if (nread != 1) {
goto fail;
}
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
table->TotalKey = ArchSwap32(table->TotalKey);
table->MaxPress = ArchSwap32(table->MaxPress);
table->MaxDupSel= ArchSwap32(table->MaxDupSel);
table->TotalChar= ArchSwap32(table->TotalChar);
table->PhraseNum= ArchSwap32(table->PhraseNum);
for (i = 0; i < 64; i++) {
table->KeyIndex [i] = ArchSwap16(table->KeyIndex[i]);
}
#endif
if( strcmp(MAGIC_NUMBER, table->magic_number) ) {
goto fail;
}
table->item = (ITEM *)malloc (sizeof(ITEM) * table->TotalChar);
if ( table->item == NULL ) {
goto fail;
}
if (fread (table->item, sizeof(ITEM), table->TotalChar, fd) < table->TotalChar)
goto fail;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
for (i = 0; i < table->TotalChar; i++) {
table->item[i].key1 = ArchSwap32(table->item[i].key1);
table->item[i].key2 = ArchSwap32(table->item[i].key2);
table->item[i].frequency = ArchSwap16(table->item[i].frequency);
}
#endif
fclose (fd);
if (table->PhraseNum > 0) {
strcpy( phrase_filename, filename );
strcat( phrase_filename, ".phr" );
strcpy( assoc_filename, filename );
strcat( assoc_filename, ".lx");
table->PhraseFile = fopen( phrase_filename, "rb" );
table->AssocFile = fopen( assoc_filename, "rb");
if (table->PhraseFile == NULL || table->AssocFile == NULL) {
printf("Load Phrase/Assoc File error!\n");
free(table->item);
free(table);
return NULL;
}
}
else {
table->PhraseFile = table->AssocFile = NULL;
}
return table;
fail:
free (table->item);
free (table);
fclose (fd);
return NULL;
}
static void free_input_method(hz_input_table *table)
{
free(table->item);
free(table);
}
static void ClrIn(void)
{
memset(InpKey, 0, sizeof( InpKey));
memset( seltab, 0, sizeof( seltab));
MultiPageMode = NextPageIndex = CurrentPageIndex = 0;
CurSelNum = InputCount = InputMatch = 0;
IsAssociateMode = 0; /* lian xiang */
}
static void FindAssociateKey(int index)
{
FILE *fp = cur_table->AssocFile;
int ofs[2],offset;
if (index < 0xB0A1)
{
StartKey = EndKey = 0;
return; /* no match */
}
offset = (index / 256 - 0xB0) * 94 + index % 256 - 0xA1;
fseek(fp, offset * sizeof(int), SEEK_SET);
fread(ofs,sizeof(int),2,fp);
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
ofs[0] = ArchSwap32(ofs[0]);
ofs[1] = ArchSwap32(ofs[1]);
#endif
StartKey = 72 * 94 + 1 + ofs[0];
EndKey = 72 * 94 + 1 + ofs[1];
}
static void load_phrase( int phrno, char *tt )
{
FILE *fp = cur_table->PhraseFile;
int ofs[2], len;
fseek( fp, ( phrno + 1 ) << 2, SEEK_SET );
fread( ofs, sizeof(int), 2, fp );
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
ofs[0] = ArchSwap32(ofs[0]);
ofs[1] = ArchSwap32(ofs[1]);
#endif
len = ofs[1] - ofs[0];
if ( len > 128 || len <= 0 ) {
strcpy( tt, "error" );
return;
}
ofs[0] += ( cur_table->PhraseNum + 1 ) << 2;
/* Add the index area length */
fseek( fp, ofs[0], SEEK_SET );
fread( tt, 1, len, fp );
tt[len] = 0;
}
static void putstr (unsigned char *p ,LPARAM lParam)
{
int index,len = strlen(p);
__mg_ime_writemsg(p, len, lParam, TRUE);
if (InputCount <= InputMatch) /* All Match */
{
index = (int)p[len-2] * 256 + p[len-1];
ClrIn();
if (UseAssociateMode)
{
FindAssociateKey(index);
CurrentPageIndex = StartKey;
MultiPageMode = 0;
FillAssociateChars(StartKey);
if (CurSelNum > 0)
{
IsAssociateMode = 1;
}
}
}
else
{
int nCount = InputCount - InputMatch,nMatch = InputMatch,i;
MultiPageMode = NextPageIndex = CurrentPageIndex = 0;
InputCount = InputMatch = 0;
for(i = 0; i < nCount; i++)
save_InpKey[i] = InpKey[nMatch+i];
memset(InpKey, 0, sizeof(InpKey));
for(i = 1; i <= nCount; i++) /* feed the additional keys */
{
InpKey[InputCount] = save_InpKey[InputCount];
InputCount++;
if (InputCount <= InputMatch+1)
{
FindMatchKey();
MultiPageMode = 0;
CurrentPageIndex = StartKey;
FillMatchChars(StartKey);
}
}
if (InputMatch == 0) /* left key has no match, delete */
{
ClrIn();
return;
}
}
}
static int epunc2cpunc (unsigned char epunc, unsigned char* cpunc)
{
int i;
for (i = 0; i < 29; i++) {
if (puncmark [i].epunc == epunc) {
switch (puncmark [i].type)
{
case CPUNCTYPE_1TO1:
memcpy (cpunc, puncmark [i].cpunc, 2);
return 2;
case CPUNCTYPE_1TO2:
memcpy (cpunc, puncmark [i].cpunc, 4);
return 4;
case CPUNCTYPE_CYCLE:
memcpy (cpunc, puncmark[i].cpunc + puncmark[i].currone, 2);
if (puncmark[i].currone == 0)
puncmark[i].currone = 2;
else
puncmark[i].currone = 0;
return 2;
default:
return 0;
}
}
}
return 0;
}
/* After add/delete a char, search the matched char/phrase, update the
StartKey/EndKey key, save the related keys at first, if no match
is found, we may restore its original value
*/
static void FindMatchKey(void)
{
save_StartKey = StartKey;
save_EndKey = EndKey;
save_MultiPageMode = MultiPageMode;
save_NextPageIndex = NextPageIndex;
save_CurrentPageIndex = CurrentPageIndex;
val1 = InpKey[4] | (InpKey[3]<<6) | (InpKey[2]<<12) | (InpKey[1]<<18) |
(InpKey[0]<<24);
val2 = InpKey[9] | (InpKey[8]<<6) | (InpKey[7]<<12) | (InpKey[6]<<18) |
(InpKey[5]<<24);
if (InputCount == 1)
StartKey = cur_table->KeyIndex[InpKey[0]];
else
StartKey = CharIndex[InputCount-1];
EndKey = cur_table->KeyIndex[InpKey[0]+1];
for (; StartKey < EndKey; StartKey++)
{
key1 = (cur_table->item[StartKey].key1 & mask[InputCount+5]);
key2 = (cur_table->item[StartKey].key2 & mask[InputCount]);
if (key1 > val1) break;
if (key1 < val1) continue;
if (key2 < val2) continue;
break;
}
CharIndex[InputCount] = StartKey;
}
/* Find the matched chars/phrases and fill it into SelTab
The starting checked index is j
The Selection Line 1xxx 2xxx, 80-20=60 60/2=30 chinese chars only
0-9 Selection can contain only 30 chinese chars
*/
static void FillAssociateChars(int index)
{
unsigned char str[25];
int PhraseNo, CurLen = 0;
CurSelNum = 0;
while( CurSelNum < cur_table->MaxDupSel && index < EndKey &&
CurLen < MAX_SEL_LENGTH)
{
fseek( cur_table->AssocFile, index << 2, SEEK_SET );
fread( &PhraseNo, sizeof(int), 1, cur_table->AssocFile );
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
PhraseNo = ArchSwap32(PhraseNo);
#endif
load_phrase( PhraseNo, str );
strcpy(seltab[CurSelNum],str+2);
CurLen += strlen(seltab[CurSelNum++]);
index++;
}
/* check if more than one page */
if ( index < EndKey && CurSelNum == cur_table->MaxDupSel )
{
/* has another matched key, so enter MultiPageMode, has more pages */
NextPageIndex = index;
MultiPageMode = 1;
}
else if (MultiPageMode)
{
NextPageIndex = StartKey; /* rotate selection */
}
else MultiPageMode = 0;
}
static void FillMatchChars(int j)
{
int SelNum = 0, CurLen = 0;
//bzero( seltab, sizeof( seltab ) );
while( ( cur_table->item[j].key1 & mask[InputCount+5] ) == val1 &&
( cur_table->item[j].key2 & mask[InputCount] ) == val2 &&
SelNum < cur_table->MaxDupSel && j < EndKey &&
CurLen < MAX_SEL_LENGTH)
{
unsigned short ch = cur_table->item[j].ch;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
ch = ArchSwap16 (ch);
#endif
if (ch < 0xA1A1)
load_phrase (ch, seltab[SelNum]);
else
{
memcpy (&seltab[SelNum], &(cur_table->item[j].ch), 2);
seltab [SelNum][2] = '\0';
}
CurLen += strlen(seltab[SelNum++]);
j++;
}
if (SelNum == 0) /* some match found */
{
StartKey = save_StartKey;
EndKey = save_EndKey;
MultiPageMode = save_MultiPageMode;
NextPageIndex = save_NextPageIndex;
CurrentPageIndex = save_CurrentPageIndex;
return; /* keep the original selection */
}
CurSelNum = SelNum;
for(SelNum = CurSelNum; SelNum < 16; SelNum++)
seltab[SelNum][0] = '\0'; /* zero out the unused area */
InputMatch = InputCount; /* until now we have some matches */
/* check if more than one page */
if ( j < EndKey && (cur_table->item[j].key1 & mask[InputCount+5]) == val1 &&
( cur_table->item[j].key2 & mask[InputCount] ) == val2 &&
CurSelNum == cur_table->MaxDupSel )
{
/* has another matched key, so enter MultiPageMode, has more pages */
NextPageIndex = j;
MultiPageMode = 1;
}
else if (MultiPageMode)
{
NextPageIndex = StartKey; /* rotate selection */
}
else MultiPageMode = 0;
}
/* return value: Has output? */
static BOOL hz_filter(unsigned char key, LPARAM lParam)
{
int inkey = 0,vv;
char *is_sel_key = (char*)0;
if (IsHanziInput) {
unsigned char cc [2];
if (IsFullPunc) {
unsigned char cpunc[4];
int len;
len = epunc2cpunc (key, cpunc);
if (len != 0) {
__mg_ime_writemsg(cpunc, len, lParam, TRUE);
ClrIn();
return TRUE;
}
}
if (IsFullChar && key >= ' ' && key <= 127) {
key = (key - ' ') << 1;
cc[0] = (unsigned char)(fullchar[key]);
cc[1] = (unsigned char)(fullchar[key+1]);
__mg_ime_writemsg(cc, 2, lParam, TRUE);
return FALSE;
}
}
else {
__mg_ime_outchar (key, lParam);
return FALSE;
}
if (CurIME == 0) {
intcode_hz_filter(key, lParam);
return TRUE;
}
#ifdef _IME_GB2312_PINYIN
if (CurIME == 1) {
Pinyin_HZFilter (&Pinyin_Module, key, lParam);
return TRUE;
}
#endif
switch ( key ) {
case '\010': /* BackSpace Ctrl+H */
case '\177': /* BackSpace */
if ( InputCount > 0 )
{
InpKey[--InputCount]=0;
if (InputCount == 0)
{
ClrIn();
}
else if (InputCount < InputMatch)
{
FindMatchKey();
MultiPageMode = 0;
CurrentPageIndex = StartKey;
FillMatchChars(StartKey);
}
}
else __mg_ime_outchar(key,lParam);
break;
case '\033': /* ESCAPE */
if (InputCount > 0)
{
ClrIn();
}
else __mg_ime_outchar(key,lParam);
break;
case '-':
if ( MultiPageMode )
{
if ( CurrentPageIndex > StartKey)
CurrentPageIndex = CurrentPageIndex - cur_table->MaxDupSel;
else CurrentPageIndex = StartKey;
if (IsAssociateMode)
FillAssociateChars(CurrentPageIndex);
else FillMatchChars(CurrentPageIndex);
}
else __mg_ime_outchar(key,lParam);
break;
case '=':
if ( MultiPageMode )
{
CurrentPageIndex = NextPageIndex;
if (IsAssociateMode)
FillAssociateChars(CurrentPageIndex);
else FillMatchChars(CurrentPageIndex);
}
else __mg_ime_outchar(key,lParam);
break;
case ' ':
if ( CurSelNum == 0 )
__mg_ime_outchar(key,lParam);
if ( seltab[0][0] )
putstr(seltab[0],lParam);
break;
default:
inkey = cur_table->KeyMap[key];
is_sel_key = strchr( cur_table->selkey, key);
vv = is_sel_key - cur_table->selkey;
/* selkey index, strchr may return NULL */
/* if a key is simultaneously inkey & is_sel_key, then selkey first?*/
if ( (!inkey && !is_sel_key) ||
(!inkey && is_sel_key && (CurSelNum == 0 || seltab[vv][0] == 0)) )
{
IsAssociateMode = 0;
ClrIn();
__mg_ime_outchar(key,lParam);
break;
}
if (is_sel_key && CurSelNum > 0 && seltab[vv][0])
{
putstr(seltab[vv],lParam);
break;
}
/* now it must be inkey? */
IsAssociateMode = 0;
if ( inkey >= 1 && InputCount < MAX_INPUT_LENGTH )
InpKey[InputCount++] = inkey;
if (InputCount <= InputMatch+1)
{
FindMatchKey();
CurrentPageIndex = StartKey;
MultiPageMode = 0;
FillMatchChars(StartKey);
if (InputCount >= cur_table->MaxPress && CurSelNum == 1 &&
cur_table->last_full)
{
// left only one selection
putstr(seltab[0],lParam);
}
}
break;
} /* switch */
return TRUE;
}
static void DispSelection(HDC hDC)
{
int i, pos = 1;
char str[100];
char minibuf[2];
minibuf[1]=0;
str[0]=0;
if (MultiPageMode && CurrentPageIndex != StartKey)
{
strcat(str,"< ");
pos += 2;
}
for( i = 0; i < CurSelNum; i++ )
{
if ( !seltab[i][0] ) {
if (CurIME == 0 && i == 0)
continue;
else
break;
}
minibuf[0]= input_table[CurIME]->selkey[i];
strcat(str,minibuf);
strcat(str,seltab[i]);
strcat(str," ");
}
if ( MultiPageMode && NextPageIndex != StartKey)
{
strcat (str,"> ");
}
if (bTwoLines)
TextOut (hDC, 2, 18, str);
else
TextOut (hDC, 150, 2, str);
}
static void unload_input_table(int i)
{
if (((i >= 0) && (i < 10)) && input_table[i])
{
if (i == CurIME)
{
if (IsHanziInput)
toggle_input_method();
CurIME = 0;
}
if (input_table[i]->PhraseFile)
fclose(input_table[i]->PhraseFile);
if (input_table[i]->AssocFile)
fclose(input_table[i]->AssocFile);
free_input_method(input_table[i]);
input_table[i] = NULL;
}
}
static int toggle_input_method(void)
{
if (input_table[CurIME] || CurIME == 1)
{
IsHanziInput ^= 1;
cur_table = input_table[CurIME];
ClrIn();
}
return IsHanziInput;
}
static void toggle_half_full(void)
{
IsFullChar ^= 1;
ClrIn();
}
static void toggle_punc (void)
{
IsFullPunc ^= 1;
ClrIn();
}
static BOOL hz_input_init(void)
{
char szFileName[MAX_PATH + 1];
char szKey[10];
char szValue[MAX_NAME + 1];
int number;
int i;
if( GetMgEtcValue ("imeinfo", "imetabpath",
ime_tab_path, MAX_PATH) < 0 ) {
fprintf (stderr, "IME: Get imetab file path error!\n");
return FALSE;
}
IsOpened = 1;
IsHanziInput = 1; // default is hanzi input
IsFullChar = 0;
IsFullPunc = 0;
CurIME = 0;
input_table[0] = IntCode_Init();
if (input_table[0] == NULL)
return FALSE;
#ifdef _IME_GB2312_PINYIN
if (!InitPinyinInput (ime_tab_path, &Pinyin_Module)) {
fprintf (stderr, "IME: Init Pinyin module failure!\n");
unload_input_table (0);
return FALSE;
}
nIMENr = 2;
#else
nIMENr = 1;
#endif
if ((sg_bmpIME = GetSystemBitmap (HWND_DESKTOP, SYSBMP_IMECTRLBTN))
== NULL) {
fprintf (stderr, "IME: Load the control button failure!\n");
return FALSE;
}
if( GetMgEtcValue ("imeinfo", "imenumber",
szValue, 10) < 0 )
goto error;
number = atoi (szValue);
if(number <= 0)
goto error;
number = (number < NR_INPUTMETHOD) ? number : NR_INPUTMETHOD;
for (i = 0; i < number; i++) {
sprintf(szKey, "ime%d", i);
if( GetMgEtcValue ("imeinfo",
szKey, szValue, MAX_NAME) < 0 )
goto error;
#ifdef _DEBUG
fprintf (stderr, "IME: Loading Input Method %d: %s\n",i, szValue);
#endif
strcpy(szFileName, ime_tab_path);
strcat(szFileName, szValue);
strcat(szFileName, ".tab");
input_table [i + nIMENr] = load_input_method(szFileName);
if (!input_table [i + nIMENr])
goto error;
}
nIMENr += number;
if (nIMENr > 1)
CurIME = 1;
cur_table = input_table [CurIME];
return TRUE;
error:
#ifdef _IME_GB2312_PINYIN
for (i = 0; i < nIMENr; i++) {
if (i != 1)
unload_input_table (i);
}
PinyinInputCleanup (ime_tab_path, &Pinyin_Module);
#else
for (i = 0; i < nIMENr; i++)
unload_input_table (i);
#endif
return FALSE;
}
static void hz_input_done(void)
{
int i;
for (i = 0; i < NR_INPUTMETHOD; i++)
if (input_table[i]) {
if (input_table[i]->PhraseFile)
fclose(input_table[i]->PhraseFile);
if (input_table[i]->AssocFile)
fclose(input_table[i]->AssocFile);
free_input_method(input_table[i]);
}
#ifdef _IME_GB2312_PINYIN
PinyinInputCleanup (ime_tab_path, &Pinyin_Module);
#endif
}
static void set_active_input_method(int active)
{
#if _IME_GB2312_PINYIN
if (input_table[active] || active == 1)
#else
if (input_table[active])
#endif
{
CurIME = active;
cur_table = input_table[active];
ClrIn();
#if _IME_GB2312_PINYIN
if (CurIME == 1 || CurIME == 0)
#else
if (CurIME == 0)
#endif
UseAssociateMode = 0;
else
UseAssociateMode = 1;
}
}
static void refresh_input_method_area(HWND hwnd, HDC hDC)
{
RECT rc;
char str[100];
int i;
char minibuf[2];
WINDOWINFO *info;
GetClientRect (hwnd, &rc);
FillBoxWithBitmapPart (hDC, rc.right - 4 - 32, 2,
CTRLBTN_WIDTH, CTRLBTN_HEIGHT,
0, 0,
sg_bmpIME,
0, (IsFullChar*CTRLBTN_HEIGHT));
FillBoxWithBitmapPart (hDC, rc.right - 4 - 16, 2,
CTRLBTN_WIDTH, CTRLBTN_HEIGHT,
0, 0,
sg_bmpIME,
CTRLBTN_WIDTH, (IsFullPunc*CTRLBTN_HEIGHT));
if (!IsHanziInput) {
rc.left += 2;
rc.top += 2;
info = (WINDOWINFO*)GetWindowInfo (hwnd);
info->we_rdr->disabled_text_out (hwnd, hDC, "【 En 】", &rc, DT_SINGLELINE);
}
#ifdef _IME_GB2312_PINYIN
else if (CurIME != 1)
#else
else
#endif
{
minibuf[1] = 0;
strcpy (str, input_table[CurIME]->cname);
for( i = 0; i <= MAX_INPUT_LENGTH ; i++)
{
if (i < InputCount)
minibuf[0] = input_table[CurIME]->KeyName[InpKey[i]];
else
minibuf[0]=' ';
if (i == InputMatch && InputCount > InputMatch && i != 0)
strcat (str,"-");
strcat (str,minibuf);
}
TextOut (hDC, 2, 2, str);
DispSelection (hDC);
}
#ifdef _IME_GB2312_PINYIN
else
RefreshPYInputArea (&Pinyin_Module, hDC, bTwoLines);
#endif
}
/*************************************************************************
* Internal Code Input Method *
*************************************************************************/
static hz_input_table *IntCode_Init(void)
{
hz_input_table *table;
int i,index;
UseAssociateMode = 1; /* force to no associate */
table = malloc(sizeof(hz_input_table));
if (table == NULL)
{
#ifdef _DEBUG
fprintf(stderr, "IME: load_input_method");
#endif
return NULL;
}
/* reset to zero. */
memset (table, 0, sizeof (hz_input_table));
strcpy(table->magic_number,MAGIC_NUMBER);
strcpy(table->ename, "IntCode");
strcpy(table->cname, "【内码】");
strcpy(table->selkey, "0123456789abcdef");
table->last_full = 1;
for(i = 0; i < 128; i++)
{
table->KeyMap[i] = 0;
if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'f'))
{
if (i >= '0' && i <= '9')
index = i - '0';
else index = i -'a' + 10;
table->KeyMap[i] = index;
table->KeyName[index] = toupper(i);
}
}
return table;
}
/* StartKey <= index < EndKey is valid */
static void IntCode_FindMatchKey(void)
{
unsigned long Key = (InpKey[0] << 12) | (InpKey[1] << 8);
switch(InputCount)
{
case 0:
case 1:
StartKey = EndKey = 0; /* not display selection */
break;
case 2:
StartKey = Key + 0xA1;
EndKey = Key + 0xFF; /* A1-A9,B0-F7 A1-FE */
break;
case 3:
StartKey = Key + (InpKey[2] << 4);
if (InpKey[2] == 10) StartKey++; /* A1 */
EndKey = StartKey + 0x10;
if (InpKey[2] == 15) EndKey--; /* FE */
break;
}
}
/* ABCD AB then C=a..f, Sel=0-9 begin display selection
ABC then D=0-f, Sel=0-f
*/
static void IntCode_FillMatchChars(int index)
{
int MaxSel,i;
CurSelNum = 0;
if (InputCount < 2) return;
if (InputCount == 2) MaxSel = 10; else MaxSel = 16;
if (index % 256 == 0xA1 && InputCount == 3)
{
seltab[0][0] = '\0';
CurSelNum++;
}
while( CurSelNum < MaxSel && index < EndKey)
{
seltab[CurSelNum][0] = index / 256;
seltab[CurSelNum][1] = index % 256;
seltab[CurSelNum][2] = '\0';
CurSelNum++;
index++;
}
for(i = CurSelNum; i < 16; i++)
seltab[i][0] = '\0'; /* zero out the unused area */
InputMatch = InputCount;
/* check if more than one page */
if ( index < EndKey && CurSelNum == MaxSel && MaxSel == 10)
{
/* has another matched key, so enter MultiPageMode, has more pages */
NextPageIndex = index;
MultiPageMode = 1;
}
else if (MultiPageMode)
{
NextPageIndex = StartKey; /* rotate selection */
}
else MultiPageMode = 0;
}
static void intcode_hz_filter(unsigned char key,LPARAM lParam)
{
int inkey = 0;
switch ( key )
{
case '\010': /* BackSpace Ctrl+H */
case '\177': /* BackSpace */
if ( InputCount > 0 )
{
InpKey[--InputCount]=0;
if (InputCount == 0)
{
ClrIn();
}
else if (InputCount >= 2)
{
IntCode_FindMatchKey();
MultiPageMode = 0;
CurrentPageIndex = StartKey;
IntCode_FillMatchChars(StartKey);
}
}
else __mg_ime_outchar(key,lParam);
break;
case '\033': /* ESCAPE */
if (InputCount > 0)
{
ClrIn();
}
else __mg_ime_outchar(key,lParam);
break;
case '-':
if ( MultiPageMode )
{
if ( CurrentPageIndex > StartKey)
CurrentPageIndex = CurrentPageIndex - 10;
else CurrentPageIndex = StartKey;
IntCode_FillMatchChars(CurrentPageIndex);
}
else __mg_ime_outchar(key,lParam);
break;
case '=':
if ( MultiPageMode )
{
CurrentPageIndex = NextPageIndex;
IntCode_FillMatchChars(CurrentPageIndex);
}
else __mg_ime_outchar(key,lParam);
break;
case ' ':
if ( CurSelNum == 0 )
__mg_ime_outchar(key,lParam);
if ( seltab[0][0] )
putstr(seltab[0],lParam);
break;
default:
inkey = cur_table->KeyMap[key];
switch(InputCount)
{
case 0: /* A-F */
case 1: /* 0-F */
case 2: /* A-F */
if (inkey >=0 && !(InputCount != 1 && inkey < 10) &&
!(InputCount == 1 &&
( (InpKey[0]==10 && inkey>9) || //A1-A9
(InpKey[0]==10 && inkey==0) ||
(InpKey[0]==15 && inkey>7)) ) ) //B0-F7
{
InpKey[InputCount++] = inkey;
if (InputCount >=2)
{
IntCode_FindMatchKey();
MultiPageMode = 0;
CurrentPageIndex = StartKey;
IntCode_FillMatchChars(StartKey);
}
}
else if (InputCount == 2 && inkey >= 0 && inkey < CurSelNum &&
seltab[inkey][0])
{
putstr(seltab[inkey],lParam);
}
else /* not select key or input key */
{
ClrIn();
__mg_ime_outchar(key,lParam);
return;
}
break;
case 3: /* output char */
if (inkey >=1 && !(InpKey[2] == 10 && inkey == 0) &&
!(InpKey[2] == 15 && inkey == 15))
{
seltab[0][0] = (InpKey[0] << 4) | InpKey[1];
seltab[0][1] = (InpKey[2] << 4) | inkey ;
seltab[0][2] = '\0';
putstr(seltab[0],lParam);
}
else
{
ClrIn();
__mg_ime_outchar(key,lParam);
return;
}
break;
}
} /* switch */
}
/*************** below are interface to other modules **************/
/* use these functions in other modules only */
/* set current active input method */
/* this function sets the active input method to ime */
/* ime value can be: 0 for internal code */
/* 1 for pinyin */
/* 2 for wubi */
static void imeSetStatus(int iStatusCode, int Value)
{
switch (iStatusCode) {
case IS_ENABLE:
if (Value && !IsHanziInput)
toggle_input_method ();
else if (!Value && IsHanziInput)
toggle_input_method ();
break;
case IS_FULLCHAR:
if (Value && !IsFullChar)
toggle_half_full ();
else if (!Value && IsFullChar)
toggle_half_full ();
break;
case IS_FULLPUNC:
if (Value && !IsFullPunc)
toggle_punc ();
else if (!Value && IsFullPunc)
toggle_punc ();
break;
case IS_METHOD:
if (Value < 0) {
Value = (CurIME + 1) % nIMENr;
set_active_input_method (Value);
}
else {
if (Value >= nIMENr)
Value = nIMENr - 1;
if (Value != CurIME)
set_active_input_method (Value);
else
return;
}
break;
default:
break;
}
}
static int imeGetStatus(int iStatusCode)
{
switch (iStatusCode) {
case IS_ENABLE:
return IsHanziInput;
break;
case IS_FULLCHAR:
return IsFullChar;
break;
case IS_FULLPUNC:
return IsFullPunc;
break;
case IS_METHOD:
return CurIME;
break;
default:
break;
}
return 0;
}
static inline BOOL imeIsSpecialChar (int chr)
{
if (chr == '\t' || chr == '\n' || chr == '\r')
return TRUE;
return FALSE;
}
static inline BOOL imeIsSpecialKey (int scancode)
{
if (scancode == SCANCODE_TAB
|| scancode == SCANCODE_ENTER
|| scancode > SCANCODE_F1)
return TRUE;
return FALSE;
}
static inline BOOL imeIsEffectiveIME (void)
{
return IsHanziInput || IsFullChar || IsFullPunc;
}
static int clean_left_ctrl = 1;
/*************************************************************************
* extern function *
*************************************************************************/
void __mg_ime_writemsg (BYTE *buffer, int len, LPARAM lParam, BOOL bDByte)
{
WORD wDByte;
int i;
if (bDByte) {
for (i=0; i<len; i+=2) {
wDByte = MAKEWORD16 (buffer[i], buffer[i+1]);
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, MSG_CHAR, wDByte, 0);
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
else
Send2ActiveWindow (mgTopmostLayer, MSG_CHAR, wDByte, 0);
#endif
}
}
else {
for (i=0; i<len; i++) {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, MSG_CHAR, buffer[i], 0);
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
else
Send2ActiveWindow (mgTopmostLayer, MSG_CHAR, buffer[i], 0);
#endif
}
}
}
void __mg_ime_outchar (unsigned char c, LPARAM lParam)
{
int scancode = 0;
switch (c) {
case '\010':
case '\177': /* BackSpace */
scancode = SCANCODE_BACKSPACE;
break;
case '\033':
scancode = SCANCODE_ESCAPE;
break;
case '\t':
scancode = SCANCODE_TAB;
break;
}
if (scancode) {
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
if (!sg_hTargetWnd) {
Send2ActiveWindow (mgTopmostLayer, MSG_KEYDOWN, scancode, (LPARAM)KS_IMEPOST);
Send2ActiveWindow (mgTopmostLayer, MSG_KEYUP, scancode, (LPARAM)KS_IMEPOST);
return;
}
#endif
PostMessage (sg_hTargetWnd, MSG_KEYDOWN, scancode, (LPARAM)KS_IMEPOST);
PostMessage (sg_hTargetWnd, MSG_KEYUP, scancode, (LPARAM)KS_IMEPOST);
}
else
__mg_ime_writemsg (&c, 1, lParam, FALSE);
}
/* this is the ime window proc */
int GBIMEWinProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
static BOOL fCaptured = FALSE;
static int oldx, oldy;
int x, y;
int maxx, maxy;
RECT rcWindow;
RECT *prcExpect, *prcResult;
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
if (message == MSG_KEYDOWN || message == MSG_KEYUP) {
if (wParam < SCANCODE_KEYPAD7 || wParam > SCANCODE_KEYPADPERIOD)
{
if (IsOpened && IsHanziInput) {
MSG Msg = {hWnd, message, wParam, lParam};
TranslateMessage (&Msg);
}
}
}
else if (message == MSG_SYSKEYDOWN) {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, message, wParam, lParam);
else
Send2ActiveWindow (mgTopmostLayer, MSG_KEYDOWN, wParam, lParam);
}
else if (message == MSG_SYSKEYUP) {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, message, wParam, lParam);
else
Send2ActiveWindow (mgTopmostLayer, MSG_KEYUP, wParam, lParam);
}
#endif
switch (message) {
case MSG_NCCREATE:
if (hz_input_init())
/* Register before show the window. */
SendMessage (HWND_DESKTOP, MSG_IME_REGISTER, (WPARAM)hWnd, 0);
else
return -1;
break;
case MSG_IME_OPEN:
if (!IsOpened) {
ShowWindow(hWnd, SW_SHOW);
IsOpened = 1;
}
break;
case MSG_IME_CLOSE:
if (IsOpened) {
ShowWindow(hWnd, SW_HIDE);
IsOpened = 0;
}
break;
case MSG_IME_SETSTATUS:
imeSetStatus ((int)wParam, (int)lParam);
break;
case MSG_IME_GETSTATUS:
return imeGetStatus ((int)wParam);
break;
case MSG_IME_SETTARGET:
if (sg_hTargetWnd != hWnd)
sg_hTargetWnd = (HWND)wParam;
break;
case MSG_IME_GETTARGET:
return (int)sg_hTargetWnd;
break;
case MSG_SETFOCUS:
case MSG_KILLFOCUS:
return 0;
case MSG_CHAR:
if (IsOpened && !imeIsSpecialChar (wParam)) {
if (hz_filter ((BYTE)wParam, lParam))
InvalidateRect (hWnd, NULL, TRUE);
}
return 0;
case MSG_KEYDOWN:
if (wParam != SCANCODE_LEFTCONTROL)
clean_left_ctrl = 0;
else
clean_left_ctrl = 1;
if (IsOpened) {
if (wParam == SCANCODE_SPACE && (lParam & KS_CTRL)) {
toggle_half_full ();
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
else if (wParam == SCANCODE_PERIOD && (lParam & KS_CTRL)) {
toggle_punc ();
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
else if ((wParam == SCANCODE_LEFTSHIFT) && (lParam & KS_CTRL)) {
imeSetStatus (IS_METHOD, -1);
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
#ifndef _LITE_VERSION
if (sg_hTargetWnd && imeIsEffectiveIME () && imeIsSpecialKey (wParam))
PostMessage (sg_hTargetWnd, MSG_KEYDOWN, wParam, lParam);
#else
if (!IsHanziInput || (imeIsEffectiveIME () && imeIsSpecialKey (wParam))) {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, MSG_KEYDOWN, wParam, lParam);
#ifndef _STAND_ALONE
else
Send2ActiveWindow (mgTopmostLayer, MSG_KEYDOWN, wParam, lParam);
#endif
}
#endif
}
#ifdef _LITE_VERSION
else {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, MSG_KEYDOWN, wParam, lParam);
#ifndef _STAND_ALONE
else
Send2ActiveWindow (mgTopmostLayer, MSG_KEYDOWN, wParam, lParam);
#endif
}
#endif
return 0;
case MSG_KEYUP:
if (IsOpened) {
if (wParam == SCANCODE_LEFTCONTROL && clean_left_ctrl ) {
toggle_input_method ();
InvalidateRect (hWnd, NULL, TRUE);
}
#ifndef _LITE_VERSION
if (sg_hTargetWnd && imeIsEffectiveIME () && imeIsSpecialKey (wParam))
PostMessage (sg_hTargetWnd, MSG_KEYUP, wParam, lParam);
#else
if (!IsHanziInput || (imeIsEffectiveIME () && imeIsSpecialKey (wParam))) {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, MSG_KEYUP, wParam, lParam);
#ifndef _STAND_ALONE
else
Send2ActiveWindow (mgTopmostLayer, MSG_KEYUP, wParam, lParam);
#endif
}
#endif
}
#ifdef _LITE_VERSION
else {
if (sg_hTargetWnd)
PostMessage (sg_hTargetWnd, MSG_KEYUP, wParam, lParam);
#ifndef _STAND_ALONE
else
Send2ActiveWindow (mgTopmostLayer, MSG_KEYUP, wParam, lParam);
#endif
}
#endif
return 0;
case MSG_PAINT:
hdc = BeginPaint (hWnd);
SetBkColor (hdc,
GetWindowElementPixelEx (hWnd, hdc, WE_MAINC_THREED_BODY));
refresh_input_method_area (hWnd, hdc);
EndPaint (hWnd, hdc);
return 0;
case MSG_LBUTTONDOWN:
{
RECT rc;
int zwidth = GetSysCCharWidth();
int zheight = GetSysCharHeight();
GetClientRect (hWnd, &rc);
oldx = LOWORD (lParam);
oldy = HIWORD (lParam);
if (IsHanziInput && oldx > 0 && oldx < 4*zwidth && oldy > 2 && oldy < zheight+2){
imeSetStatus (IS_METHOD, -1);
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
if (oldx > rc.right - 4 - 32 && oldx < rc.right - 4 - 16 && oldy > 2 && oldy < 16+2){
toggle_half_full ();
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
if (oldx > rc.right - 4 - 16 && oldx < rc.right - 4 && oldy > 2 && oldy < 16+2){
toggle_punc ();
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
SetCapture (hWnd);
ClientToScreen (hWnd, &oldx, &oldy);
fCaptured = TRUE;
}
break;
case MSG_LBUTTONUP:
ReleaseCapture ();
fCaptured = FALSE;
break;
case MSG_MOUSEMOVE:
if (fCaptured) {
GetWindowRect (hWnd, &rcWindow);
x = LOSWORD (lParam);
y = HISWORD (lParam);
OffsetRect (&rcWindow, x - oldx, y - oldy);
MoveWindow (hWnd, rcWindow.left, rcWindow.top,
RECTW (rcWindow), RECTH (rcWindow), TRUE);
oldx = x;
oldy = y;
}
break;
case MSG_SIZECHANGING:
prcExpect = (PRECT)wParam;
prcResult = (PRECT)lParam;
*prcResult = *prcExpect;
if (prcExpect->left < 0) {
prcResult->left = 0;
prcResult->right = RECTWP (prcExpect);
}
if (prcExpect->top < 0) {
prcResult->top = 0;
prcResult->bottom = RECTHP (prcExpect);
}
maxx = GetGDCapability (HDC_SCREEN, GDCAP_HPIXEL);
maxy = GetGDCapability (HDC_SCREEN, GDCAP_VPIXEL);
if (prcExpect->right > maxx) {
prcResult->right = maxx;
prcResult->left = maxx - RECTWP (prcExpect);
}
#if 0
if (prcExpect->bottom > (maxy-80)) {
prcResult->bottom = maxy-78;
prcResult->top = (maxy-78) - RECTHP (prcExpect);
}
#else
if (prcExpect->bottom > maxy) {
prcResult->bottom = maxy;
prcResult->top = maxy - RECTHP (prcExpect);
}
#endif
return 0;
case MSG_CLOSE:
SendMessage (HWND_DESKTOP, MSG_IME_UNREGISTER, (WPARAM)hWnd, 0);
hz_input_done ();
DestroyMainWindow (hWnd);
#ifndef _LITE_VERSION
PostQuitMessage (hWnd);
#endif
return 0;
}
return DefaultMainWinProc(hWnd, message, wParam, lParam);
}
static void InitIMEWinCreateInfo (PMAINWINCREATE pCreateInfo)
{
pCreateInfo->dwStyle = WS_ABSSCRPOS | WS_BORDER | WS_VISIBLE;
pCreateInfo->dwExStyle = WS_EX_TOPMOST;
pCreateInfo->spCaption = "The IME Window" ;
pCreateInfo->hMenu = 0;
pCreateInfo->hCursor = GetSystemCursor(0);
pCreateInfo->hIcon = 0;
pCreateInfo->MainWindowProc = GBIMEWinProc;
pCreateInfo->lx = GetGDCapability (HDC_SCREEN, GDCAP_MAXX) - 400;
pCreateInfo->ty = GetGDCapability (HDC_SCREEN, GDCAP_MAXY) - 80;
pCreateInfo->rx = GetGDCapability (HDC_SCREEN, GDCAP_MAXX);
pCreateInfo->by = GetGDCapability (HDC_SCREEN, GDCAP_MAXY) - 40;
pCreateInfo->iBkColor =
GetWindowElementPixelEx (HWND_NULL, HDC_SCREEN, WE_MAINC_THREED_BODY);
pCreateInfo->dwAddData = 0;
pCreateInfo->hHosting = 0;
}
#ifdef _LITE_VERSION
HWND GBIMEWindowEx (HWND hosting, int lx, int ty, int rx, int by, BOOL two_lines)
{
MAINWINCREATE CreateInfo;
HWND hMainWnd;
#ifndef _STAND_ALONE
if (!mgIsServer)
return HWND_INVALID;
#endif
InitIMEWinCreateInfo (&CreateInfo);
CreateInfo.hHosting = hosting;
if (lx != 0 || ty != 0 || rx != 0 || by != 0) {
CreateInfo.lx = lx;
CreateInfo.ty = ty;
CreateInfo.rx = rx;
CreateInfo.by = by;
bTwoLines = two_lines;
}
else
bTwoLines = TRUE;
hMainWnd = CreateMainWindow(&CreateInfo);
if (hMainWnd == HWND_INVALID)
return HWND_INVALID;
ShowWindow (hMainWnd, SW_SHOWNORMAL);
return hMainWnd;
}
#else
typedef struct ime_info
{
sem_t wait;
HWND hwnd;
} IME_INFO;
static void* start_gb_ime (void* data)
{
MSG Msg;
MAINWINCREATE CreateInfo;
IME_INFO* ime_info = (IME_INFO*) data;
HWND ime_hwnd;
InitIMEWinCreateInfo (&CreateInfo);
bTwoLines = TRUE;
ime_hwnd = ime_info->hwnd = CreateMainWindow (&CreateInfo);
sem_post (&ime_info->wait);
if (ime_hwnd == HWND_INVALID)
return NULL;
while (GetMessage (&Msg, ime_hwnd) ) {
if (Msg.message == MSG_KEYDOWN || Msg.message == MSG_KEYUP) {
if (IsOpened && IsHanziInput)
TranslateMessage (&Msg);
else if (sg_hTargetWnd) {
PostMessage (sg_hTargetWnd,
Msg.message, Msg.wParam, Msg.lParam | KS_IMEPOST);
}
}
DispatchMessage(&Msg);
}
MainWindowThreadCleanup (ime_hwnd);
return NULL;
}
static pthread_t imethread;
/* the argument of 'hosting' is ignored. */
HWND GBIMEWindow (HWND hosting)
{
IME_INFO ime_info;
pthread_attr_t new_attr;
sem_init (&ime_info.wait, 0, 0);
pthread_attr_init (&new_attr);
pthread_attr_setdetachstate (&new_attr, PTHREAD_CREATE_DETACHED);
pthread_create (&imethread, &new_attr, start_gb_ime, &ime_info);
pthread_attr_destroy (&new_attr);
sem_wait (&ime_info.wait);
sem_destroy (&ime_info.wait);
return ime_info.hwnd;
}
#endif