📄 uiime_cj.c
字号:
#include "uiIme_cj.h"
#include "uiCJ_Tbl.res"
#include "uisw_kbd.h"
/***********************************************************************
*
* Internal Constants
*
***********************************************************************/
#define CHANGJIE_TABLE_SIZE 13060
#define CHANGJIE_KEY_NUMBER 52 // 仓颉键盘按键个数(不含选字区及功能键)
#define CHANGJIE_KEY_INDEX_ADDRESS 44
#define CHANGJIE_KEY_INDEX_SYMBOL 45
#define CHANGJIE_KEY_INDEX_SPACE 46 // 空白键的索引
#define CHANGJIE_KEY_INDEX_BACKSPACE 10 // back space
static WORD ChangJieKey[CHANGJIE_KEY_NUMBER];/* = {
// 1 2 3 4 5 6 7 8 9 0
0xa2b0, 0xa2b1,0xa2b2,0xa2b3,0xa2b4,0xa2b5,0xa2b6,0xa2b7,0xa2b8, 0xa2af,KEY_BACKSPACE,
//手 田 水 口 廿 卜 山 戈 人 心 =
17, 23, 5, 18, 20, 25, 21, 9, 15, 16, 0xa1d7,
//日 尸 木 火 土 竹 十 大 中 ? Tab
1, 19, 4, 6, 7, 8, 10, 11, 12, 0xa153, KEY_TAB,
//重 难 金 女 月 弓 一 ; : ! ENTER
26, 24, 3, 22, 2, 14, 13, 0xa146, 0xa147, 0xa154, KEY_ENTER,
// 址 符 space 、 , . 。 DEL
0x0020, 0x0020, 0x0020, 0xa142, 0xa141, 0xa145, 0xa143, KEY_DELETE
};
*/
/*
static WORD ChangJieCodeMap[27] = {
// 日 月 金 木 水 火 土 竹 戈 十
0x0020, 0xa4e9, 0xa4eb, 0xaaf7, 0xa4ec, 0xa4f4, 0xa4f5, 0xa467, 0xa6cb, 0xa4e0, 0xa451,
// 大 中 一 弓 人 心 手 口 尸 廿 山
0xa46a, 0xa4a4, 0xa440, 0xa47d, 0xa448, 0xa4df, 0xa4e2, 0xa466, 0xa472, 0xa4dc, 0xa473,
// 女 田 难 卜 重
0xa46b, 0xa5d0, 0xc3f8, 0xa452, 0xadab
};
*/
#ifdef __WIN32__
static WORD ChangJieCodeMap[27] = {
// 日 月 金 木 水 火 土 竹 戈 十
0x0020, 0xe9a4, 0xeba4, 0xf7aa, 0xeca4, 0xf4a4, 0xf5a4, 0x67a4, 0xcba6, 0xe0a4, 0x51a4,
// 大 中 一 弓 人 心 手 口 尸 廿 山
0x6aa4, 0xa4a4, 0x40a4, 0x7da4, 0x48a4, 0xdfa4, 0xe2a4, 0x66a4, 0x72a4, 0xdca4, 0x73a4,
// 女 田 难 卜 重
0x6ba4, 0xd0a5, 0xf8c3, 0x52a4, 0xabad
};
#else
static WORD ChangJieCodeMap[27] = {
// 日 月 金 木 水 火 土 竹 戈 十
0x2000, 0xa4e9, 0xa4eb, 0xaaf7, 0xa4ec, 0xa4f4, 0xa4f5, 0xa467, 0xa6cb, 0xa4e0, 0xa451,
// 大 中 一 弓 人 心 手 口 尸 廿 山
0xa46a, 0xa4a4, 0xa440, 0xa47d, 0xa448, 0xa4df, 0xa4e2, 0xa466, 0xa472, 0xa4dc, 0xa473,
// 女 田 难 卜 重
0xa46b, 0xa5d0, 0xc3f8, 0xa452, 0xadab
};
#endif
//static char ImeCjStrAddress[] = "县市乡镇路街段巷弄号楼";
//static char ImeCjStrSymbol[] = "!:;、。,·? "‘'“”『』※《》";
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
//BOOL ImeLookupCJ(char key, char *buffer, IMM_CANDIDATE* pCdd);
static BOOL CjKeyIsCJCode(char key);
//static void CjPushCJKeyToCmp(char key, IMM_COMPOSITION* pCmp);
static void CjConvertCJCode(IMM_COMPOSITION* pCmp, IMM_CANDIDATE* pCdd);
/***********************************************
* wbStr: code of wb *
* offset: offset of candidate word *
* return: total count of candidate word *
************************************************/
//DLL_EXP(int) guiIme_cj(char *cjStr, DWORD *offset)
int guiIme_cj(char *cjStr, unsigned short *pBig5Code)
{
//static void CjConvertCJCode(IMM_COMPOSITION* pCmp, IMM_CANDIDATE* pCdd)
// union for the calculate compressed code
union
{
DWORD dwordData;
BYTE byteData[4];
} CompressedCode;
BYTE *TableEntry = (unsigned char *)ChangJieTable;
BYTE code[2] = {0, 0}, Big5Code[2];
BYTE len;
int i, foundCnt=0;
// BOOL bMatch = FALSE;
if((cjStr[0])==0)
return 0;
len = strlen(cjStr);
// calculate the compressed code using key index in key buffer
CompressedCode.dwordData = 0;
for(i = 0; i < 5; i++)
{
CompressedCode.dwordData *= 27;
//if (i < pCmp->count)
//CompressedCode.dwordData += pCmp->buff[i];
if (i<len)
CompressedCode.dwordData += cjStr[i];
}
// scan the table to find the matches
for(i = 0; i < CHANGJIE_TABLE_SIZE; i++)
{
#ifdef __WIN32__
if(TableEntry[0] == CompressedCode.byteData[0] && TableEntry[1] == CompressedCode.byteData[1] && TableEntry[2] == CompressedCode.byteData[2])
{
#else
if(TableEntry[0] == CompressedCode.byteData[3] && TableEntry[1] == CompressedCode.byteData[2] && TableEntry[2] == CompressedCode.byteData[1])
{
#endif
WORD TableIndex = i;
code[0] = 0xa4;
if(TableIndex >= 0x1519)
{
code[0] = 0xc9;
TableIndex -= 0x1519;
}
code[0] += (BYTE)(TableIndex / 0x9d);
code[1] = (BYTE)(TableIndex % 0x9d);
if(code[1] < 0x3f)
code[1] += 0x40;
else
code[1] += 0xa1 - 0x3f;
// add the character to candidate
//bMatch = TRUE;
//ImmAddCddByPCH((char *)&code[0]);
/*#ifndef __WIN32__
Big5Code[0] = code[1];
Big5Code[1] = code[0];
#else
*/
Big5Code[0] = code[0];
Big5Code[1] = code[1];
//#endif
pBig5Code[foundCnt] = *(unsigned short*)Big5Code;
foundCnt++;
}
TableEntry += 3;
}
pBig5Code[foundCnt] = 0;
return foundCnt;
}
void ConvertNumberToCode(char *numStr, unsigned short *codeStr)
{
int i, len, number;
len = strlen(numStr);
for(i=0; i<len; i++)
{
number = numStr[i];
codeStr[i] = ChangJieCodeMap[number] ;
}
codeStr[i] = 0;
}
/******************************************************************
* offset: offset of candidate word, get from guiIme_py() *
* totalCount: total count of candidate word, get form guiIme_py() *
* startPos: start position of word to read *
* toReadCount: number of word to read *
* pWordText: buffer of word *
* return: actual number of word read *
*******************************************************************/
/*int guiGetCandidate_cj(DWORD offset, unsigned short totalCount, unsigned short startPos, unsigned short toReadCount, unsigned short *pWordText)
{
unsigned short *pWord;
int readCount, i;
if(!offset)
return 0;
if(startPos>totalCount)
return 0;
pWord = (unsigned short *)(offset+2*startPos);
readCount = (totalCount>startPos+toReadCount)?toReadCount:(totalCount-startPos);
for(i=0; i<readCount; i++)
pWordText[i] = pWord[i];
pWordText[readCount] = 0x0000;
return readCount;
}
*/
int KeyIsCJCode(unsigned short key)
{
if(key>25)
return 0;
return 1;
}
/***********************************************************************
*
* FUNCTION: ImmAddCddByPCH
*
* DESCRIPTION: interface for IME to put *Chinese* character into cdd buffer
*
* PARAMETERS: pch - the pointer to character buffer that stores
* the candidate chinese character
*
* RETURNED: TRUE, if the character is successfully put
* FALSE, if the buffer is full
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
*
***********************************************************************/
static IMM_OBJ ImmObj;
BOOL ImmAddCddByPCH(char* pch)
{
// if the buffer is full, then return
if (ImmObj.cdd.count >= MAX_CANDIDATE_COUNT)
return FALSE;
// add the character & increase count flag
ImmObj.cdd.buff[ImmObj.cdd.count].b.h = pch[0];
ImmObj.cdd.buff[ImmObj.cdd.count].b.l = pch[1];
ImmObj.cdd.count++;
return TRUE;
}
/***********************************************************************
*
* FUNCTION: CjConvertCJCode
*
* DESCRIPTION: convert the cj codes in composition into chinese characters
* and put them in candidate
*
* PARAMETERS: pCmp - pointer to composition
* pCdd - pointer to candidate
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
*
***********************************************************************/
static void CjConvertCJCode(IMM_COMPOSITION* pCmp, IMM_CANDIDATE* pCdd)
{
// union for the calculate compressed code
union
{
DWORD dwordData;
BYTE byteData[4];
} CompressedCode;
BYTE *TableEntry = (unsigned char *)ChangJieTable;
BYTE Big5Code[2] = {0, 0};
int i;
BOOL bMatch = FALSE;
// if there isn't key in the buffer, then return
if (pCmp->count == 0)
return;
// calculate the compressed code using key index in key buffer
CompressedCode.dwordData = 0;
for(i = 0; i < 5; i++)
{
CompressedCode.dwordData *= 27;
if (i < pCmp->count)
CompressedCode.dwordData += pCmp->buff[i];
}
// scan the table to find the matches
for(i = 0; i < CHANGJIE_TABLE_SIZE; i++)
{
#ifdef __WIN32__
if(TableEntry[0] == CompressedCode.byteData[0] && TableEntry[1] == CompressedCode.byteData[1] && TableEntry[2] == CompressedCode.byteData[2])
{
#else
if(TableEntry[0] == CompressedCode.byteData[3] && TableEntry[1] == CompressedCode.byteData[2] && TableEntry[2] == CompressedCode.byteData[1])
{
#endif
WORD TableIndex = i;
Big5Code[0] = 0xa4;
if(TableIndex >= 0x1519)
{
Big5Code[0] = 0xc9;
TableIndex -= 0x1519;
}
Big5Code[0] += (BYTE)(TableIndex / 0x9d);
Big5Code[1] = (BYTE)(TableIndex % 0x9d);
if(Big5Code[1] < 0x3f)
Big5Code[1] += 0x40;
else
Big5Code[1] += 0xa1 - 0x3f;
// add the character to candidate
bMatch = TRUE;
ImmAddCddByPCH((char *)&Big5Code[0]);
}
TableEntry += 3;
}
// if there is no matching
if (!bMatch)
{
//ImmClearCandidate();
//ImmClearComposition();
}
}
/***********************************************************************
*
* FUNCTION: CjKeyIsCJCode
*
* DESCRIPTION: if specify key is the key that represent a CJ code
*
* PARAMETERS: key - specify the key
*
* RETURNED: TRUE, if given key is a CJ code key
* FALSE, if not
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
*
***********************************************************************/
static BOOL CjKeyIsCJCode(char key)
{
if (key <= 10)
return FALSE;
if (key == CHANGJIE_KEY_INDEX_BACKSPACE)
return FALSE;
if (key == 31 || key == 32)
return FALSE;
if (key >= 40 && key <= 45)
return FALSE;
if (key >= 47 && key <= 51)
return FALSE;
return TRUE;
}
/***********************************************************************
*
* FUNCTION: CjPushCJKeyToCmp
*
* DESCRIPTION: add cj code into composition
*
* PARAMETERS: key - the pressed key
* pCmp - pointer to composition
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
*
***********************************************************************/
/*static void CjPushCJKeyToCmp(char key, IMM_COMPOSITION* pCmp)
{
// if the cmp buffer is full, return
if (pCmp->count >= 5)
return;
pCmp->buff[pCmp->count] = ChangJieKey[key];
pCmp->count++;
}*/ // by zhang xue ping
/***********************************************************************
*
* FUNCTION: ImmAddCddByWord
*
* DESCRIPTION: interface for IME to put character into cdd buffer
*
* PARAMETERS: w - a WORD that stores the candidate chinese character
*
* RETURNED: TRUE, if the character is successfully put
* FALSE, if the buffer is full
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
*
***********************************************************************/
BOOL ImmAddCddByWord(WORD w)
{
// if the buffer is full, then return
if (ImmObj.cdd.count >= MAX_CANDIDATE_COUNT)
return FALSE;
// add the character & increase count flag
ImmObj.cdd.buff[ImmObj.cdd.count].w = w;
ImmObj.cdd.count++;
return TRUE;
}
/***********************************************************************
*
* FUNCTION: ImeLookupCJ
*
* DESCRIPTION: ChangJei IME's lookup function, responsible for converting
* the composition string into candidate characters.
*
* PARAMETERS: key - the newly pressed key
* pCmp - pointer to composition
* pCdd - pointer to candidate
*
* RETURNED: TRUE, if keyboard need repaint
* FALSE, if keyboard need not repaint
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
*
***********************************************************************/
/*
BOOL ImeLookupCJ(char key, char *buffer, IMM_CANDIDATE* pCdd)
{
IMM_COMPOSITION* pCmp;
unsigned char len;
char ch[3];
ch[2] = 0;
len = strlen(buffer);
pCmp->count = len;
strcpy(pCmp->buff, buffer);
// 0. if key index is invalid, do nothing
if (key == -1)
return FALSE;
// 1. "space", lookup the table to convert the cj code to big-5 code
if (key == CHANGJIE_KEY_INDEX_SPACE)
{
if (pCmp->count == 0)
ImmAddCddByPCH(" ");
else
CjConvertCJCode(pCmp, pCdd);
}
// 2. "backspace"
else if (key == CHANGJIE_KEY_INDEX_BACKSPACE)
{
//CjRemoveCJCode(pCmp, pCdd);
}
// 3. "address" & "symbol"
else if (key == CHANGJIE_KEY_INDEX_ADDRESS || key == CHANGJIE_KEY_INDEX_SYMBOL)
{
//CjKeyAddrSymbol(key);
}
// 4. else add the key into cmp window
else if (CjKeyIsCJCode(key))
{
CjPushCJKeyToCmp(key, pCmp);
// if up to 5 cj code, then convert
if (pCmp->count == 5)
CjConvertCJCode(pCmp, pCdd);
} else {
ImmAddCddByWord(ChangJieKey[key]);
}
return FALSE;
}
*/ // by zhang xue ping
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -