/*************************************************************************** * Copyright (C) 2002~2005 by Yuking * * yuking_net@sohu.com * * * * 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif //======================================== #include "table.h" #include "punc.h" #include #include #include #include #include #include /* #ifdef HAVE_MACHINE_ENDIAN_H #include #endif */ #include #include "tools.h" #include "InputWindow.h" #include "py.h" #include "pyParser.h" #include "ui.h" #ifdef _USE_XFT #include #include #endif TABLE *table; INT8 iTableIMIndex = 0; INT8 iTableCount; Bool bTableDictLoaded = False; //Loads tables only if needed RECORD *currentRecord = NULL, *recordHead = NULL; RECORD *tableSingleHZ[SINGLE_HZ_COUNT]; //Records the single characters in table to speed auto phrase TABLECANDWORD tableCandWord[MAX_CAND_WORD]; RECORD_INDEX *recordIndex = NULL; AUTOPHRASE *autoPhrase = NULL; AUTOPHRASE *insertPoint = NULL; uint iAutoPhrase = 0; uint iTableCandDisplayed; uint iTableTotalCandCount; INT16 iTableOrderChanged = 0; char strTableLegendSource[PHRASE_MAX_LENGTH * 2 + 1] = "\0"; FH *fh; int iFH = 0; unsigned int iTableIndex = 0; Bool bIsTableDelPhrase = False; HOTKEYS hkTableDelPhrase[HOT_KEY_COUNT] = { CTRL_7, 0 }; Bool bIsTableAdjustOrder = False; HOTKEYS hkTableAdjustOrder[HOT_KEY_COUNT] = { CTRL_6, 0 }; Bool bIsTableAddPhrase = False; HOTKEYS hkTableAddPhrase[HOT_KEY_COUNT] = { CTRL_8, 0 }; HOTKEYS hkGetPY[HOT_KEY_COUNT] = { CTRL_ALT_E, 0 }; INT8 iTableChanged = 0; INT8 iTableNewPhraseHZCount; Bool bCanntFindCode; //Records if new phrase has corresponding code - should be always false char *strNewPhraseCode; SINGLE_HZ hzLastInput[PHRASE_MAX_LENGTH]; //Records last HZ input INT16 iHZLastInputCount = 0; Bool bTablePhraseTips = False; ADJUSTORDER PYBaseOrder; extern char strPYAuto[]; extern Display *dpy; extern Window inputWindow; #ifdef _USE_XFT extern XftFont *xftFont; extern XftFont *xftFontEn; #else extern XFontSet fontSet; #endif extern char strCodeInput[]; extern Bool bIsDoInputOnly; extern int iCandPageCount; extern int iCurrentCandPage; extern int iCandWordCount; extern int iLegendCandWordCount; extern int iLegendCandPageCount; extern int iCurrentLegendCandPage; extern int iCodeInputCount; extern int iMaxCandWord; extern char strStringGet[]; extern MESSAGE messageUp[]; extern uint uMessageUp; extern MESSAGE messageDown[]; extern uint uMessageDown; extern Bool bPointAfterNumber; extern INT8 iIMIndex; extern Bool bUseLegend; extern Bool bIsInLegend; extern INT8 lastIsSingleHZ; extern Bool bDisablePagingInLegend; extern Bool bShowCursor; extern Bool bAutoHideInputWindow; extern ADJUSTORDER baseOrder; extern Bool bSP; extern Bool bPYBaseDictLoaded; extern uint iFixedInputWindowWidth; //---------------------------------------- extern PYFA *PYFAList; extern PYCandWord PYCandWords[]; //extern Bool bSingleHZMode; extern char strFindString[]; extern ParsePYStruct findMap; //---------------------------------------- /* * 读取码表输入法的名称和文件路径 */ void LoadTableInfo (void) { FILE *fp; char strPath[PATH_MAX]; int i; char *pstr; FreeTableIM (); if (table) free (table); iTableCount = 0; strcpy (strPath, (char *) getenv ("HOME")); strcat (strPath, "/.fcitx/"); strcat (strPath, TABLE_CONFIG_FILENAME); if (access (strPath, 0)) { strcpy (strPath, PKGDATADIR "/data/"); strcat (strPath, TABLE_CONFIG_FILENAME); } fp = fopen (strPath, "rt"); if (!fp) return; //首先来看看有多少个码表 while (1) { if (!fgets (strPath, PATH_MAX, fp)) break; i = strlen (strPath) - 1; while (strPath[i] == ' ' || strPath[i] == '\n') strPath[i--] = '\0'; pstr = strPath; if (*pstr == ' ') pstr++; if (pstr[0] == '#') continue; if (strstr (pstr, "[码表]")) iTableCount++; } table = (TABLE *) malloc (sizeof (TABLE) * iTableCount); for (iTableIMIndex = 0; iTableIMIndex < iTableCount; iTableIMIndex++) { table[iTableIMIndex].strInputCode = NULL; table[iTableIMIndex].strName[0] = '\0'; table[iTableIMIndex].strPath[0] = '\0'; table[iTableIMIndex].strSymbolFile[0] = '\0'; table[iTableIMIndex].tableOrder = AD_NO; table[iTableIMIndex].bUsePY = True; table[iTableIMIndex].cPinyin = '\0'; table[iTableIMIndex].bTableAutoSendToClient = True; table[iTableIMIndex].rule = NULL; table[iTableIMIndex].bUseMatchingKey = False; table[iTableIMIndex].cMatchingKey = '\0'; table[iTableIMIndex].bTableExactMatch = False; table[iTableIMIndex].bAutoPhrase = True; table[iTableIMIndex].bAutoPhrasePhrase = True; table[iTableIMIndex].iSaveAutoPhraseAfter = 0; table[iTableIMIndex].iAutoPhrase = 4; table[iTableIMIndex].bPromptTableCode = True; table[iTableIMIndex].strSymbol[0] = '\0'; } iTableIMIndex = -1; //读取其它属性的默认值 if (iTableCount) { rewind (fp); while (1) { if (!fgets (strPath, PATH_MAX, fp)) break; i = strlen (strPath) - 1; while (strPath[i] == ' ' || strPath[i] == '\n') strPath[i--] = '\0'; pstr = strPath; if (*pstr == ' ') pstr++; if (pstr[0] == '#') continue; if (!strcmp (pstr, "[码表]")) { if (iTableIMIndex != -1) { if (table[iTableIMIndex].strName[0] == '\0' || table[iTableIMIndex].strPath[0] == '\0') { iTableCount = 0; free (table); fprintf (stderr, "The config file of No.%d table errors!\n", iTableIMIndex); return; } } iTableIMIndex++; } else if (!strncmp (pstr, "名称=", 5)) { pstr += 5; strcpy (table[iTableIMIndex].strName, pstr); } else if (!strncmp (pstr, "码表=", 5)) { pstr += 5; strcpy (table[iTableIMIndex].strPath, pstr); } else if (!strncmp (pstr, "调频=", 5)) { pstr += 5; table[iTableIMIndex].tableOrder = (ADJUSTORDER) atoi (pstr); } else if (!strncmp (pstr, "拼音=", 5)) { pstr += 5; table[iTableIMIndex].bUsePY = atoi (pstr); } else if (!strncmp (pstr, "拼音键=", 7)) { pstr += 7; while (*pstr == ' ') pstr++; table[iTableIMIndex].cPinyin = *pstr; } else if (!strncmp (pstr, "自动上屏=", 9)) { pstr += 9; table[iTableIMIndex].bTableAutoSendToClient = atoi (pstr); } else if (!strncmp (pstr, "模糊=", 5)) { pstr += 5; table[iTableIMIndex].bUseMatchingKey = atoi (pstr); } else if (!strncmp (pstr, "模糊键=", 7)) { pstr += 7; while (*pstr == ' ') pstr++; table[iTableIMIndex].cMatchingKey = *pstr; } else if (!strncmp (pstr, "精确匹配=", 9)) { pstr += 9; table[iTableIMIndex].bTableExactMatch = atoi (pstr); } else if (!strncmp (pstr, "自动词组=", 9)) { pstr += 9; table[iTableIMIndex].bAutoPhrase = atoi (pstr); } else if (!strncmp (pstr, "自动词组长度=", 13)) { pstr += 13; table[iTableIMIndex].iAutoPhrase = atoi (pstr); } else if (!strncmp (pstr, "词组参与自动造词=", 17)) { pstr += 17; table[iTableIMIndex].bAutoPhrasePhrase = atoi (pstr); } else if (!strncmp (pstr, "保存自动词组=", 13)) { pstr += 13; table[iTableIMIndex].iSaveAutoPhraseAfter = atoi (pstr); } else if (!strncmp (pstr, "提示编码=", 9)) { pstr += 9; table[iTableIMIndex].bPromptTableCode = atoi (pstr); } else if (!strncmp (pstr, "符号=", 5)) { pstr += 5; strcpy (table[iTableIMIndex].strSymbol, pstr); } else if (!strncmp (pstr, "符号文件=", 9)) { pstr += 9; strcpy (table[iTableIMIndex].strSymbolFile, pstr); } } } fclose (fp); } Bool LoadTableDict (void) { char strCode[MAX_CODE_LENGTH + 1]; char strHZ[PHRASE_MAX_LENGTH * 2 + 1]; FILE *fpDict; RECORD *recTemp; char strPath[PATH_MAX]; unsigned int i = 0; unsigned int iTemp, iTempCount; char cChar = 0; //首先,来看看我们该调入哪个码表 for (i = 0; i < iTableCount; i++) { if (table[i].iIMIndex == iIMIndex) iTableIMIndex = i; } //读入码表 strcpy (strPath, (char *) getenv ("HOME")); strcat (strPath, "/.fcitx/"); strcat (strPath, table[iTableIMIndex].strPath); if (access (strPath, 0)) { strcpy (strPath, PKGDATADIR "/data/"); strcat (strPath, table[iTableIMIndex].strPath); } fpDict = fopen (strPath, "rb"); if (!fpDict) { fprintf (stderr, "Cannot load table file: %s\n", strPath); return False; } //先读取码表的信息 fread (&iTemp, sizeof (unsigned int), 1, fpDict); table[iTableIMIndex].strInputCode = (char *) malloc (sizeof (char) * (iTemp + 1)); fread (table[iTableIMIndex].strInputCode, sizeof (char), iTemp + 1, fpDict); /* * 建立索引 */ recordIndex = (RECORD_INDEX *) malloc (strlen (table[iTableIMIndex].strInputCode) * sizeof (RECORD_INDEX)); for (iTemp = 0; iTemp < strlen (table[iTableIMIndex].strInputCode); iTemp++) { recordIndex[iTemp].cCode = table[iTableIMIndex].strInputCode[iTemp]; recordIndex[iTemp].record = NULL; } /* ********************************************************************** */ fread (&(table[iTableIMIndex].iCodeLength), sizeof (unsigned char), 1, fpDict); fread (&iTemp, sizeof (unsigned int), 1, fpDict); table[iTableIMIndex].strIgnoreChars = (char *) malloc (sizeof (char) * (iTemp + 1)); fread (table[iTableIMIndex].strIgnoreChars, sizeof (char), iTemp + 1, fpDict); fread (&(table[iTableIMIndex].bRule), sizeof (unsigned char), 1, fpDict); if (table[iTableIMIndex].bRule) { //表示有组词规则 table[iTableIMIndex].rule = (RULE *) malloc (sizeof (RULE) * (table[iTableIMIndex].iCodeLength - 1)); for (i = 0; i < table[iTableIMIndex].iCodeLength - 1; i++) { fread (&(table[iTableIMIndex].rule[i].iFlag), sizeof (unsigned char), 1, fpDict); fread (&(table[iTableIMIndex].rule[i].iWords), sizeof (unsigned char), 1, fpDict); table[iTableIMIndex].rule[i].rule = (RULE_RULE *) malloc (sizeof (RULE_RULE) * table[iTableIMIndex].iCodeLength); for (iTemp = 0; iTemp < table[iTableIMIndex].iCodeLength; iTemp++) { fread (&(table[iTableIMIndex].rule[i].rule[iTemp].iFlag), sizeof (unsigned char), 1, fpDict); fread (&(table[iTableIMIndex].rule[i].rule[iTemp].iWhich), sizeof (unsigned char), 1, fpDict); fread (&(table[iTableIMIndex].rule[i].rule[iTemp].iIndex), sizeof (unsigned char), 1, fpDict); } } } recordHead = (RECORD *) malloc (sizeof (RECORD)); currentRecord = recordHead; fread (&(table[iTableIMIndex].iRecordCount), sizeof (unsigned int), 1, fpDict); for (i = 0; i < SINGLE_HZ_COUNT; i++) tableSingleHZ[i] = (RECORD *) NULL; for (i = 0; i < table[iTableIMIndex].iRecordCount; i++) { fread (strCode, sizeof (char), table[iTableIMIndex].iCodeLength + 1, fpDict); fread (&iTemp, sizeof (unsigned int), 1, fpDict); fread (strHZ, sizeof (char), iTemp, fpDict); recTemp = (RECORD *) malloc (sizeof (RECORD)); recTemp->strCode = (char *) malloc (sizeof (char) * (table[iTableIMIndex].iCodeLength + 1)); strcpy (recTemp->strCode, strCode); recTemp->strHZ = (char *) malloc (sizeof (char) * iTemp); strcpy (recTemp->strHZ, strHZ); recTemp->flag = 0; fread (&(recTemp->iHit), sizeof (unsigned int), 1, fpDict); fread (&(recTemp->iIndex), sizeof (unsigned int), 1, fpDict); if (recTemp->iIndex > iTableIndex) iTableIndex = recTemp->iIndex; /* 建立索引 */ if (cChar != recTemp->strCode[0]) { cChar = recTemp->strCode[0]; iTemp = 0; while (cChar != recordIndex[iTemp].cCode) iTemp++; recordIndex[iTemp].record = recTemp; } /* **************************************************************** */ /** 为单字生成一个表 */ if (strlen (recTemp->strHZ) == 2 && !IsIgnoreChar (strCode[0])) { iTemp = CalHZIndex (recTemp->strHZ); if (tableSingleHZ[iTemp]) { if (strlen (strCode) > strlen (tableSingleHZ[iTemp]->strCode)) tableSingleHZ[iTemp] = recTemp; } else tableSingleHZ[iTemp] = recTemp; } currentRecord->next = recTemp; recTemp->prev = currentRecord; currentRecord = recTemp; } currentRecord->next = recordHead; recordHead->prev = currentRecord; fclose (fpDict); //读取相应的特殊符号表 strcpy (strPath, (char *) getenv ("HOME")); strcat (strPath, "/.fcitx/"); strcat (strPath, table[iTableIMIndex].strSymbolFile); if (access (strPath, 0)) { strcpy (strPath, PKGDATADIR "/data/"); strcat (strPath, table[iTableIMIndex].strSymbolFile); fpDict = fopen (strPath, "rt"); } fpDict = fopen (strPath, "rt"); if (fpDict) { iFH = CalculateRecordNumber (fpDict); fh = (FH *) malloc (sizeof (FH) * iFH); for (i = 0; i < iFH; i++) { if (EOF == fscanf (fpDict, "%s\n", fh[i].strFH)) break; } iFH = i; fclose (fpDict); } strNewPhraseCode = (char *) malloc (sizeof (char) * (table[iTableIMIndex].iCodeLength + 1)); strNewPhraseCode[table[iTableIMIndex].iCodeLength] = '\0'; bTableDictLoaded = True; //为自动词组分配空间 autoPhrase = (AUTOPHRASE *) malloc (sizeof (AUTOPHRASE) * AUTO_PHRASE_COUNT); //读取上次保存的自动词组信息 strcpy (strPath, (char *) getenv ("HOME")); strcat (strPath, "/.fcitx/"); strcat (strPath, table[iTableIMIndex].strName); strcat (strPath, "_LastAutoPhrase.tmp"); fpDict = fopen (strPath, "rb"); i = 0; if (fpDict) { fread (&iAutoPhrase, sizeof (unsigned int), 1, fpDict); for (; i < iAutoPhrase; i++) { autoPhrase[i].strCode = (char *) malloc (sizeof (char) * (table[iTableIMIndex].iCodeLength + 1)); autoPhrase[i].strHZ = (char *) malloc (sizeof (char) * (PHRASE_MAX_LENGTH * 2 + 1)); fread (autoPhrase[i].strCode, table[iTableIMIndex].iCodeLength + 1, 1, fpDict); fread (autoPhrase[i].strHZ, PHRASE_MAX_LENGTH * 2 + 1, 1, fpDict); fread (&iTempCount, sizeof (unsigned int), 1, fpDict); autoPhrase[i].iSelected = iTempCount; if (i == AUTO_PHRASE_COUNT - 1) autoPhrase[i].next = &autoPhrase[0]; else autoPhrase[i].next = &autoPhrase[i + 1]; } fclose (fpDict); } for (; i < AUTO_PHRASE_COUNT; i++) { autoPhrase[i].strCode = (char *) malloc (sizeof (char) * (table[iTableIMIndex].iCodeLength + 1)); autoPhrase[i].strHZ = (char *) malloc (sizeof (char) * (PHRASE_MAX_LENGTH * 2 + 1)); autoPhrase[i].iSelected = 0; if (i == AUTO_PHRASE_COUNT - 1) autoPhrase[i].next = &autoPhrase[0]; else autoPhrase[i].next = &autoPhrase[i + 1]; } if (i == AUTO_PHRASE_COUNT) insertPoint = &autoPhrase[0]; else insertPoint = &autoPhrase[i - 1]; /* * 然后初始化码表输入法 TableInit(); */ /* * 呵呵,借用一下这儿来为一个词库文件生成五笔编码 */ /* FILE *temp1,*temp2; char str[100]; temp1=fopen("phrase.txt","rt"); temp2=fopen("table.txt","wt"); while (!feof(temp1)) { fscanf(temp1,"%s\n",str); TableCreatePhraseCode(str); printf("\nProcessing %s ... ",str); if ( !bCanntFindCode ) fprintf(temp2,"%s %s\n", strNewPhraseCode,str); else puts("ERROR!"); } printf("\nCreate table.txt ok!\n"); fclose(temp2); fclose(temp1); */ /* ********************************************** */ return True; } void TableInit (void) { bSP = False; PYBaseOrder = baseOrder; strPYAuto[0] = '\0'; } /* * 释放当前码表所占用的内存 * 目的是切换码表时使占用的内存减少 */ void FreeTableIM (void) { RECORD *recTemp, *recNext; INT16 i; if (!recordHead) return; if (iTableChanged || iTableOrderChanged) SaveTableDict (); //释放码表 recTemp = recordHead->next; while (recTemp != recordHead) { recNext = recTemp->next; free (recTemp->strCode); free (recTemp->strHZ); free (recTemp); recTemp = recNext; } free (recordHead); recordHead = NULL; if (iFH) { free (fh); iFH = 0; } free (table[iTableIMIndex].strInputCode); free (table[iTableIMIndex].strIgnoreChars); table[iTableIMIndex].iRecordCount = 0; bTableDictLoaded = False; free (strNewPhraseCode); //释放组词规则的空间 if (table[iTableIMIndex].rule) { for (i = 0; i < table[iTableIMIndex].iCodeLength - 1; i++) free (table[iTableIMIndex].rule[i].rule); free (table[iTableIMIndex].rule); table[iTableIMIndex].rule = NULL; } //释放索引的空间 if (recordIndex) { free (recordIndex); recordIndex = NULL; } //释放自动词组的空间 for (i = 0; i < AUTO_PHRASE_COUNT; i++) { free (autoPhrase[i].strCode); free (autoPhrase[i].strHZ); } free (autoPhrase); baseOrder = PYBaseOrder; } void TableResetStatus (void) { bIsTableAddPhrase = False; bIsTableDelPhrase = False; bIsTableAdjustOrder = False; bIsDoInputOnly = False; //bSingleHZMode = False; } void SaveTableDict (void) { RECORD *recTemp; char strPath[PATH_MAX]; char strPathTemp[PATH_MAX]; FILE *fpDict; unsigned int iTemp; unsigned int i; //先将码表保存在一个临时文件中,如果保存成功,再将该临时文件改名是码表名──这样可以防止码表文件被破坏 strcpy (strPathTemp, (char *) getenv ("HOME")); strcat (strPathTemp, "/.fcitx/"); if (access (strPathTemp, 0)) mkdir (strPathTemp, S_IRWXU); strcat (strPathTemp, TEMP_FILE); fpDict = fopen (strPathTemp, "wb"); if (!fpDict) { fprintf (stderr, "Cannot create table file: %s\n", strPathTemp); return; } iTemp = strlen (table[iTableIMIndex].strInputCode); fwrite (&iTemp, sizeof (unsigned int), 1, fpDict); fwrite (table[iTableIMIndex].strInputCode, sizeof (char), iTemp + 1, fpDict); fwrite (&(table[iTableIMIndex].iCodeLength), sizeof (INT8), 1, fpDict); iTemp = strlen (table[iTableIMIndex].strIgnoreChars); fwrite (&iTemp, sizeof (unsigned int), 1, fpDict); fwrite (table[iTableIMIndex].strIgnoreChars, sizeof (char), iTemp + 1, fpDict); fwrite (&(table[iTableIMIndex].bRule), sizeof (unsigned char), 1, fpDict); if (table[iTableIMIndex].bRule) { //表示有组词规则 for (i = 0; i < table[iTableIMIndex].iCodeLength - 1; i++) { fwrite (&(table[iTableIMIndex].rule[i].iFlag), sizeof (unsigned char), 1, fpDict); fwrite (&(table[iTableIMIndex].rule[i].iWords), sizeof (unsigned char), 1, fpDict); for (iTemp = 0; iTemp < table[iTableIMIndex].iCodeLength; iTemp++) { fwrite (&(table[iTableIMIndex].rule[i].rule[iTemp].iFlag), sizeof (unsigned char), 1, fpDict); fwrite (&(table[iTableIMIndex].rule[i].rule[iTemp].iWhich), sizeof (unsigned char), 1, fpDict); fwrite (&(table[iTableIMIndex].rule[i].rule[iTemp].iIndex), sizeof (unsigned char), 1, fpDict); } } } fwrite (&(table[iTableIMIndex].iRecordCount), sizeof (unsigned int), 1, fpDict); recTemp = recordHead->next; while (recTemp != recordHead) { fwrite (recTemp->strCode, sizeof (char), table[iTableIMIndex].iCodeLength + 1, fpDict); iTemp = strlen (recTemp->strHZ) + 1; fwrite (&iTemp, sizeof (unsigned int), 1, fpDict); fwrite (recTemp->strHZ, sizeof (char), iTemp, fpDict); fwrite (&(recTemp->iHit), sizeof (unsigned int), 1, fpDict); fwrite (&(recTemp->iIndex), sizeof (unsigned int), 1, fpDict); recTemp = recTemp->next; } fclose (fpDict); strcpy (strPath, (char *) getenv ("HOME")); strcat (strPath, "/.fcitx/"); strcat (strPath, table[iTableIMIndex].strPath); if (access (strPath, 0)) unlink (strPath); rename (strPathTemp, strPath); iTableOrderChanged = 0; iTableChanged = 0; //保存上次的自动词组信息 strcpy (strPathTemp, (char *) getenv ("HOME")); strcat (strPathTemp, "/.fcitx/"); strcat (strPathTemp, TEMP_FILE); fpDict = fopen (strPathTemp, "wb"); if (fpDict) { fwrite (&iAutoPhrase, sizeof (int), 1, fpDict); for (i = 0; i < iAutoPhrase; i++) { fwrite (autoPhrase[i].strCode, table[iTableIMIndex].iCodeLength + 1, 1, fpDict); fwrite (autoPhrase[i].strHZ, PHRASE_MAX_LENGTH * 2 + 1, 1, fpDict); iTemp = autoPhrase[i].iSelected; fwrite (&iTemp, sizeof (unsigned int), 1, fpDict); } fclose (fpDict); } strcpy (strPath, (char *) getenv ("HOME")); strcat (strPath, "/.fcitx/"); strcat (strPath, table[iTableIMIndex].strName); strcat (strPath, "_LastAutoPhrase.tmp"); if (access (strPath, 0)) unlink (strPath); rename (strPathTemp, strPath); } Bool IsInputKey (int iKey) { char *p; p = table[iTableIMIndex].strInputCode; if (!p) return False; while (*p) { if (iKey == *p) return True; p++; } return False; } Bool IsIgnoreChar (char cChar) { char *p; p = table[iTableIMIndex].strIgnoreChars; while (*p) { if (cChar == *p) return True; p++; } return False; } INPUT_RETURN_VALUE DoTableInput (int iKey) { INPUT_RETURN_VALUE retVal; if (!bTableDictLoaded) LoadTableDict (); if (bTablePhraseTips) { if (iKey == CTRL_DELETE) { bTablePhraseTips = False; TableDelPhraseByHZ (messageUp[1].strMsg); return IRV_DONOT_PROCESS_CLEAN; } else if (iKey != LCTRL && iKey != RCTRL && iKey != LSHIFT && iKey != RSHIFT) { uMessageUp = uMessageDown = 0; bTablePhraseTips = False; if (bAutoHideInputWindow) XUnmapWindow (dpy, inputWindow); else DisplayInputWindow (); } } retVal = IRV_DO_NOTHING; if (IsInputKey (iKey) || iKey == table[iTableIMIndex].cMatchingKey || iKey == table[iTableIMIndex].cPinyin) { bIsInLegend = False; if (!bIsTableAddPhrase && !bIsTableDelPhrase && !bIsTableAdjustOrder) { if (strCodeInput[0] == table[iTableIMIndex].cPinyin && table[iTableIMIndex].bUsePY) { if (iCodeInputCount != (MAX_PY_LENGTH * 5 + 1)) { strCodeInput[iCodeInputCount++] = (char) iKey; strCodeInput[iCodeInputCount] = '\0'; retVal = TableGetCandWords (SM_FIRST); } else retVal = IRV_DO_NOTHING; } else { if (iCodeInputCount < table[iTableIMIndex].iCodeLength) { strCodeInput[iCodeInputCount++] = (char) iKey; strCodeInput[iCodeInputCount] = '\0'; if (iCodeInputCount == 1 && strCodeInput[0] == table[iTableIMIndex].cPinyin && table[iTableIMIndex].bUsePY) { iCandWordCount = 0; retVal = IRV_DISPLAY_LAST; } else { char *strTemp; retVal = TableGetCandWords (SM_FIRST); strTemp = GetPunc (strCodeInput[0]); if (table[iTableIMIndex].bTableAutoSendToClient && (iCodeInputCount == table[iTableIMIndex].iCodeLength)) { if (iCandWordCount == 1 && (tableCandWord[0].flag != CT_AUTOPHRASE || (tableCandWord[0].flag == CT_AUTOPHRASE && !table[iTableIMIndex].iSaveAutoPhraseAfter))) { //如果只有一个候选词,则送到客户程序中 strcpy (strStringGet, TableGetCandWord (0)); iCandWordCount = 0; if (bIsInLegend) retVal = IRV_GET_LEGEND; else retVal = IRV_GET_CANDWORDS; } } else if ((iCodeInputCount == 1) && strTemp && !iCandWordCount) { //如果第一个字母是标点,并且没有候选字/词,则当做标点处理──适用于二笔这样的输入法 strcpy (strStringGet, strTemp); retVal = IRV_PUNC; } } } else { if (table[iTableIMIndex].bTableAutoSendToClient) { if (iCandWordCount) { if (tableCandWord[0].flag != CT_AUTOPHRASE) { strcpy (strStringGet, TableGetCandWord (0)); retVal = IRV_GET_CANDWORDS_NEXT; } else retVal = IRV_DISPLAY_CANDWORDS; } else retVal = IRV_DISPLAY_CANDWORDS; iCodeInputCount = 1; strCodeInput[0] = iKey; strCodeInput[1] = '\0'; bIsInLegend = False; TableGetCandWords (SM_FIRST); } else retVal = IRV_DO_NOTHING; } } } } else { if (bIsTableAddPhrase) { switch (iKey) { case LEFT: if (iTableNewPhraseHZCount < iHZLastInputCount && iTableNewPhraseHZCount < PHRASE_MAX_LENGTH) { iTableNewPhraseHZCount++; TableCreateNewPhrase (); } break; case RIGHT: if (iTableNewPhraseHZCount > 2) { iTableNewPhraseHZCount--; TableCreateNewPhrase (); } break; case ENTER: if (!bCanntFindCode) TableInsertPhrase (messageDown[1].strMsg, messageDown[0].strMsg); case ESC: bIsTableAddPhrase = False; bIsDoInputOnly = False; return IRV_CLEAN; default: return IRV_DO_NOTHING; } return IRV_DISPLAY_MESSAGE; } if (IsHotKey (iKey, hkTableAddPhrase)) { if (!bIsTableAddPhrase) { if (iHZLastInputCount < 2 || !table[iTableIMIndex].bRule) //词组最少为两个汉字 return IRV_DO_NOTHING; iTableNewPhraseHZCount = 2; bIsTableAddPhrase = True; bIsDoInputOnly = True; bShowCursor = False; uMessageUp = 1; strcpy (messageUp[0].strMsg, "左/右键增加/减少,ENTER确定,ESC取消"); messageUp[0].type = MSG_TIPS; uMessageDown = 2; messageDown[0].type = MSG_FIRSTCAND; messageDown[1].type = MSG_CODE; TableCreateNewPhrase (); DisplayInputWindow (); retVal = IRV_DISPLAY_MESSAGE; } else retVal = IRV_TO_PROCESS; return retVal; } else if (IsHotKey (iKey, hkGetPY)) { char strPY[100]; //如果拼音单字字库没有读入,则读入它 if (!bPYBaseDictLoaded) LoadPYBaseDict (); //如果刚刚输入的是个词组,刚不查拼音 if (strlen (strStringGet) != 2) return IRV_DO_NOTHING; iCodeInputCount = 0; uMessageUp = 1; strcpy (messageUp[0].strMsg, strStringGet); messageUp[0].type = MSG_INPUT; uMessageDown = 2; strcpy (messageDown[0].strMsg, "读音:"); messageDown[0].type = MSG_CODE; PYGetPYByHZ (strStringGet, strPY); strcpy (messageDown[1].strMsg, (strPY[0]) ? strPY : "无法查到该字读音"); messageDown[1].type = MSG_TIPS; bShowCursor = False; return IRV_DISPLAY_MESSAGE; } if (!iCodeInputCount && !bIsInLegend) return IRV_TO_PROCESS; if (iKey == ESC) { if (bIsTableDelPhrase || bIsTableAdjustOrder) { TableResetStatus (); retVal = IRV_DISPLAY_CANDWORDS; } else return IRV_CLEAN; } else if (iKey >= '0' && iKey <= '9') { iKey -= '0'; if (iKey == 0) iKey = 10; if (!bIsInLegend) { if (!iCandWordCount) return IRV_TO_PROCESS; if (iKey > iCandWordCount) return IRV_DO_NOTHING; else { if (bIsTableDelPhrase) { TableDelPhraseByIndex (iKey); retVal = TableGetCandWords (SM_FIRST); } else if (bIsTableAdjustOrder) { TableAdjustOrderByIndex (iKey); retVal = TableGetCandWords (SM_FIRST); } else { //如果是拼音,进入快速调整字频方式 if (strcmp (strCodeInput, table[iTableIMIndex].strSymbol) && strCodeInput[0] == table[iTableIMIndex].cPinyin && table[iTableIMIndex].bUsePY) PYGetCandWord (iKey - 1); strcpy (strStringGet, TableGetCandWord (iKey - 1)); if (bIsInLegend) retVal = IRV_GET_LEGEND; else retVal = IRV_GET_CANDWORDS; } } } else { strcpy (strStringGet, TableGetLegendCandWord (iKey - 1)); retVal = IRV_GET_LEGEND; } } else if (!bIsTableDelPhrase && !bIsTableAdjustOrder) { if (IsHotKey (iKey, hkTableAdjustOrder)) { if ((iTableCandDisplayed == iCandWordCount && iCandWordCount < 2) || bIsInLegend) return IRV_DO_NOTHING; bIsTableAdjustOrder = True; uMessageUp = 1; strcpy (messageUp[0].strMsg, "选择需要提前的词组序号,ESC取消"); messageUp[0].type = MSG_TIPS; retVal = IRV_DISPLAY_MESSAGE; } else if (IsHotKey (iKey, hkTableDelPhrase)) { if (!iCandWordCount || bIsInLegend) return IRV_DO_NOTHING; bIsTableDelPhrase = True; uMessageUp = 1; strcpy (messageUp[0].strMsg, "选择需要删除的词组序号,ESC取消"); messageUp[0].type = MSG_TIPS; retVal = IRV_DISPLAY_MESSAGE; } else if (iKey == (XK_BackSpace & 0x00FF) || iKey == CTRL_H) { if (!iCodeInputCount) { bIsInLegend = False; return IRV_DONOT_PROCESS_CLEAN; } iCodeInputCount--; strCodeInput[iCodeInputCount] = '\0'; if (iCodeInputCount == 1 && strCodeInput[0] == table[iTableIMIndex].cPinyin) { iCandWordCount = 0; retVal = IRV_DISPLAY_LAST; } else if (iCodeInputCount) retVal = TableGetCandWords (SM_FIRST); else retVal = IRV_CLEAN; } else if (iKey == ' ') { if (!bIsInLegend) { if (!(table[iTableIMIndex].bUsePY && iCodeInputCount == 1 && strCodeInput[0] == table[iTableIMIndex].cPinyin)) { if (strcmp (strCodeInput, table[iTableIMIndex].strSymbol) && strCodeInput[0] == table[iTableIMIndex].cPinyin && table[iTableIMIndex].bUsePY) PYGetCandWord (0); if (!iCandWordCount) { iCodeInputCount = 0; return IRV_CLEAN; } strcpy (strStringGet, TableGetCandWord (0)); } else uMessageDown = 0; if (bIsInLegend) retVal = IRV_GET_LEGEND; else retVal = IRV_GET_CANDWORDS; } else { strcpy (strStringGet, TableGetLegendCandWord (0)); retVal = IRV_GET_LEGEND; } } else return IRV_TO_PROCESS; } } if (!bIsInLegend) { if (!bIsTableDelPhrase && !bIsTableAdjustOrder) { if (iCodeInputCount) { uMessageUp = 1; strcpy (messageUp[0].strMsg, strCodeInput); messageUp[0].type = MSG_INPUT; } else uMessageUp = 0; } else bIsDoInputOnly = True; } if (bIsTableDelPhrase || bIsTableAdjustOrder || bIsInLegend) bShowCursor = False; else bShowCursor = True; return retVal; } char *TableGetCandWord (int iIndex) { char *pCandWord = NULL; if (!strcmp (strCodeInput, table[iTableIMIndex].strSymbol)) return TableGetFHCandWord (iIndex); bIsInLegend = False; if (!iCandWordCount) return NULL; if (iIndex > (iCandWordCount - 1)) iIndex = iCandWordCount - 1; if (tableCandWord[iIndex].flag == CT_NORMAL) { tableCandWord[iIndex].candWord.record->iHit++; tableCandWord[iIndex].candWord.record->iIndex = ++iTableIndex; } iTableOrderChanged++; if (iTableOrderChanged == TABLE_AUTO_SAVE_AFTER) SaveTableDict (); switch (tableCandWord[iIndex].flag) { case CT_NORMAL: pCandWord = tableCandWord[iIndex].candWord.record->strHZ; break; case CT_AUTOPHRASE: if (table[iTableIMIndex].iSaveAutoPhraseAfter) { if (table[iTableIMIndex].iSaveAutoPhraseAfter >= tableCandWord[iIndex].candWord.autoPhrase->iSelected) tableCandWord[iIndex].candWord.autoPhrase->iSelected++; if (table[iTableIMIndex].iSaveAutoPhraseAfter == tableCandWord[iIndex].candWord.autoPhrase->iSelected) //保存自动词组 TableInsertPhrase (tableCandWord[iIndex].candWord.autoPhrase->strCode, tableCandWord[iIndex].candWord.autoPhrase->strHZ); } pCandWord = tableCandWord[iIndex].candWord.autoPhrase->strHZ; break; case CT_PYPHRASE: pCandWord = tableCandWord[iIndex].candWord.strPYPhrase; break; default: ; } if (bUseLegend) { strcpy (strTableLegendSource, pCandWord); TableGetLegendCandWords (SM_FIRST); } else { if (table[iTableIMIndex].bPromptTableCode) { RECORD *temp; uMessageUp = 1; strcpy (messageUp[0].strMsg, strCodeInput); messageUp[0].type = MSG_INPUT; strcpy (messageDown[0].strMsg, pCandWord); messageDown[0].type = MSG_TIPS; temp = tableSingleHZ[CalHZIndex (pCandWord)]; if (temp) { strcpy (messageDown[1].strMsg, temp->strCode); messageDown[1].type = MSG_CODE; uMessageDown = 2; } else uMessageDown = 1; } else { uMessageDown = 0; uMessageUp = 0; iCodeInputCount = 0; } } if (strlen (pCandWord) == 2) lastIsSingleHZ = 1; else lastIsSingleHZ = 0; if (strlen (pCandWord) == 2 || (strlen (pCandWord) > 2 && table[iTableIMIndex].bAutoPhrasePhrase)) UpdateHZLastInput (pCandWord); return pCandWord; } INPUT_RETURN_VALUE TableGetPinyinCandWords (SEARCH_MODE mode) { int i; if (mode == SM_FIRST) { strcpy (strFindString, strCodeInput + 1); DoPYInput (-1); strCodeInput[0] = table[iTableIMIndex].cPinyin; strCodeInput[1] = '\0'; strcat (strCodeInput, strFindString); iCodeInputCount = strlen (strCodeInput); } else PYGetCandWords (mode); //下面将拼音的候选字表转换为码表输入法的样式 for (i = 0; i < iCandWordCount; i++) { tableCandWord[i].flag = CT_PYPHRASE; PYGetCandText (i, tableCandWord[i].candWord.strPYPhrase); } return IRV_DISPLAY_CANDWORDS; } INPUT_RETURN_VALUE TableGetCandWords (SEARCH_MODE mode) { int i, iTemp; char strTemp[3], *pstr; RECORD *recTemp; if (bIsInLegend) return TableGetLegendCandWords (mode); if (!strcmp (strCodeInput, table[iTableIMIndex].strSymbol)) return TableGetFHCandWords (mode); if (strCodeInput[0] == table[iTableIMIndex].cPinyin && table[iTableIMIndex].bUsePY) TableGetPinyinCandWords (mode); else { if (mode == SM_FIRST) { iCandWordCount = 0; iTableCandDisplayed = 0; iTableTotalCandCount = 0; iCurrentCandPage = 0; iCandPageCount = 0; TableResetFlags (); if (TableFindFirstMatchCode () == -1 && !iAutoPhrase) { uMessageDown = 0; return IRV_DISPLAY_CANDWORDS; //Not Found } } else { if (!iCandWordCount) return IRV_TO_PROCESS; if (mode == SM_NEXT) { if (iTableCandDisplayed >= iTableTotalCandCount) return IRV_TO_PROCESS; } else { if (iTableCandDisplayed == iCandWordCount) return IRV_TO_PROCESS; iTableCandDisplayed -= iCandWordCount; TableSetCandWordsFlag (iCandWordCount, False); } TableFindFirstMatchCode (); } iCandWordCount = 0; if (mode == SM_PREV && table[iTableIMIndex].bRule && table[iTableIMIndex].bAutoPhrase && iCodeInputCount == table[iTableIMIndex].iCodeLength) { for (i = iAutoPhrase - 1; i >= 0; i--) { if (!TableCompareCode (strCodeInput, autoPhrase[i].strCode) && autoPhrase[i].flag) { if (TableHasPhrase (autoPhrase[i].strCode, autoPhrase[i].strHZ)) TableAddAutoCandWord (i, mode); } } } if (iCandWordCount < iMaxCandWord) { while (currentRecord && currentRecord != recordHead) { if ((mode == SM_PREV) ^ (!currentRecord->flag)) { if (!TableCompareCode (strCodeInput, currentRecord->strCode) && CheckHZCharset (currentRecord->strHZ)) { if (mode == SM_FIRST) iTableTotalCandCount++; TableAddCandWord (currentRecord, mode); } } currentRecord = currentRecord->next; } } if (table[iTableIMIndex].bRule && table[iTableIMIndex].bAutoPhrase && mode != SM_PREV && iCodeInputCount == table[iTableIMIndex].iCodeLength) { for (i = iAutoPhrase - 1; i >= 0; i--) { if (!TableCompareCode (strCodeInput, autoPhrase[i].strCode) && !autoPhrase[i].flag) { if (TableHasPhrase (autoPhrase[i].strCode, autoPhrase[i].strHZ)) { if (mode == SM_FIRST) iTableTotalCandCount++; TableAddAutoCandWord (i, mode); } } } } TableSetCandWordsFlag (iCandWordCount, True); if (mode != SM_PREV) iTableCandDisplayed += iCandWordCount; //由于iCurrentCandPage和iCandPageCount用来指示是否显示上/下翻页图标,因此,此处需要设置一下 iCurrentCandPage = (iTableCandDisplayed == iCandWordCount) ? 0 : 1; iCandPageCount = (iTableCandDisplayed >= iTableTotalCandCount) ? 1 : 2; if (iCandWordCount == iTableTotalCandCount) iCandPageCount = 0; /* **************************************************** */ } if (bPointAfterNumber) { strTemp[1] = '.'; strTemp[2] = '\0'; } else strTemp[1] = '\0'; /* 如果用户设置了固定输入条宽度,就在此进行处理 */ if (iFixedInputWindowWidth && !(strCodeInput[0] == table[iTableIMIndex].cPinyin && table[iTableIMIndex].bUsePY)) { uint iWidth = 2 * INPUTWND_START_POS_DOWN + 1; if (mode == SM_PREV) { for (i = (iCandWordCount - 1); i >= 0; i--) { strTemp[0] = i + 1 + '0'; if (i == 9) strTemp[0] = '0'; if (HasMatchingKey ()) pstr = (tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strCode : tableCandWord[i].candWord.autoPhrase->strCode; /*else if (tableCandWord[i].flag==CT_PYPHRASE) { if (strlen(tableCandWord[i].candWord.strPYPhrase)==2){ recTemp = tableSingleHZ[CalHZIndex (tableCandWord[i].candWord.strPYPhrase)]; if (!recTemp) pstr=(char *)NULL; else pstr=recTemp->strCode; } else pstr=(char *)NULL; } */ else pstr = ((tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strCode : tableCandWord[i].candWord.autoPhrase->strCode) + iCodeInputCount; #ifdef _USE_XFT if (pstr) iWidth += StringWidth (pstr, xftFontEn); iWidth += StringWidth (strTemp, xftFontEn); switch (tableCandWord[i].flag) { case CT_NORMAL: iWidth += StringWidth (tableCandWord[i].candWord.record->strHZ, xftFont); break; case CT_AUTOPHRASE: iWidth += StringWidth (tableCandWord[i].candWord.autoPhrase->strHZ, xftFont); /* case CT_PYPHRASE: iWidth += StringWidth (tableCandWord[i].candWord.strPhrase, xftFont); */ default: ; } iWidth += StringWidth (" ", xftFontEn); #else if (pstr) iWidth += StringWidth (pstr, fontSet); iWidth += StringWidth (strTemp, fontSet); switch (tableCandWord[i].flag) { case CT_NORMAL: iWidth += StringWidth (tableCandWord[i].candWord.record->strHZ, fontSet); break; case CT_AUTOPHRASE: iWidth += StringWidth (tableCandWord[i].candWord.autoPhrase->strHZ, fontSet); /*case CT_PYPHRASE: iWidth += StringWidth (tableCandWord[i].candWord.strPhrase, fontSet); */ default: ; } iWidth += StringWidth (" ", fontSet); #endif if (iWidth > iFixedInputWindowWidth) { if (i == 0) { #ifdef _USE_XFT iWidth -= StringWidth (" ", xftFontEn); #else iWidth -= StringWidth (" ", fontSet); #endif if (iWidth > iFixedInputWindowWidth) i = 1; } else i++; break; } } if (i < 0) i = 0; for (iWidth = 0; iWidth < i; iWidth++) { if (tableCandWord[iWidth].flag == CT_NORMAL) tableCandWord[iWidth].candWord.record->flag = True; else tableCandWord[iWidth].candWord.autoPhrase->flag = True; } for (iWidth = 0; iWidth < (iCandWordCount - i); iWidth++) { tableCandWord[iWidth].flag = tableCandWord[iWidth + i].flag; if (tableCandWord[iWidth].flag == CT_NORMAL) tableCandWord[iWidth].candWord.record = tableCandWord[iWidth + i].candWord.record; else tableCandWord[iWidth].candWord.autoPhrase = tableCandWord[iWidth + i].candWord.autoPhrase; } iCandWordCount -= i; } else { //如果是向后翻,需要从前往后计算长度 iTemp = iCandWordCount; for (i = 0; i < iCandWordCount; i++) { strTemp[0] = i + 1 + '0'; if (i == 9) strTemp[0] = '0'; if (HasMatchingKey ()) pstr = (tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strCode : tableCandWord[i].candWord.autoPhrase->strCode; else pstr = ((tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strCode : tableCandWord[i].candWord.autoPhrase->strCode) + iCodeInputCount; #ifdef _USE_XFT iWidth += StringWidth (pstr, xftFontEn); iWidth += StringWidth (strTemp, xftFontEn); iWidth += StringWidth ((tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strHZ : tableCandWord[i].candWord.autoPhrase->strHZ, xftFont); iWidth += StringWidth (" ", xftFontEn); #else iWidth += StringWidth (pstr, fontSet); iWidth += StringWidth (strTemp, fontSet); iWidth += StringWidth ((tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strHZ : tableCandWord[i].candWord.autoPhrase->strHZ, fontSet); iWidth += StringWidth (" ", fontSet); #endif if (iWidth > iFixedInputWindowWidth) { if (i == (iCandWordCount - 1)) { #ifdef _USE_XFT iWidth -= StringWidth (" ", xftFontEn); #else iWidth -= StringWidth (" ", fontSet); #endif if (iWidth <= iFixedInputWindowWidth) i = iCandWordCount; } break; } } for (iWidth = i; iWidth < iCandWordCount; iWidth++) { if (tableCandWord[iWidth].flag == CT_NORMAL) tableCandWord[iWidth].candWord.record->flag = False; else tableCandWord[iWidth].candWord.autoPhrase->flag = False; } iCandWordCount = i; iTableCandDisplayed -= iTemp - i; } } uMessageDown = 0; for (i = 0; i < iCandWordCount; i++) { strTemp[0] = i + 1 + '0'; if (i == 9) strTemp[0] = '0'; strcpy (messageDown[uMessageDown].strMsg, strTemp); messageDown[uMessageDown++].type = MSG_INDEX; switch (tableCandWord[i].flag) { case CT_NORMAL: strcpy (messageDown[uMessageDown].strMsg, tableCandWord[i].candWord.record->strHZ); break; case CT_AUTOPHRASE: strcpy (messageDown[uMessageDown].strMsg, tableCandWord[i].candWord.autoPhrase->strHZ); break; case CT_PYPHRASE: strcpy (messageDown[uMessageDown].strMsg, tableCandWord[i].candWord.strPYPhrase); break; default: ; } if (tableCandWord[i].flag == CT_AUTOPHRASE) messageDown[uMessageDown++].type = MSG_TIPS; else messageDown[uMessageDown++].type = ((i == 0) ? MSG_FIRSTCAND : MSG_OTHER); if (tableCandWord[i].flag == CT_PYPHRASE) { if (strlen (tableCandWord[i].candWord.strPYPhrase) == 2) { recTemp = tableSingleHZ[CalHZIndex (tableCandWord[i].candWord.strPYPhrase)]; if (!recTemp) pstr = (char *) NULL; else pstr = recTemp->strCode; } else pstr = (char *) NULL; } else if (HasMatchingKey ()) pstr = (tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strCode : tableCandWord[i].candWord.autoPhrase->strCode; else pstr = ((tableCandWord[i].flag == CT_NORMAL) ? tableCandWord[i].candWord.record->strCode : tableCandWord[i].candWord.autoPhrase->strCode) + iCodeInputCount; if (pstr) strcpy (messageDown[uMessageDown].strMsg, pstr); else messageDown[uMessageDown].strMsg[0] = '\0'; if (i != (iCandWordCount - 1)) { strcat (messageDown[uMessageDown].strMsg, " "); } messageDown[uMessageDown++].type = MSG_CODE; } return IRV_DISPLAY_CANDWORDS; } void TableAddAutoCandWord (INT16 which, SEARCH_MODE mode) { int i, j; if (mode == SM_PREV) { if (iCandWordCount == iMaxCandWord) { i = iCandWordCount - 1; for (j = 0; j < iCandWordCount - 1; j++) tableCandWord[j].candWord.autoPhrase = tableCandWord[j + 1].candWord.autoPhrase; } else i = iCandWordCount++; tableCandWord[i].flag = CT_AUTOPHRASE; tableCandWord[i].candWord.autoPhrase = &autoPhrase[which]; } else { if (iCandWordCount == iMaxCandWord) return; tableCandWord[iCandWordCount].flag = CT_AUTOPHRASE; tableCandWord[iCandWordCount++].candWord.autoPhrase = &autoPhrase[which]; } } void TableAddCandWord (RECORD * record, SEARCH_MODE mode) { int i = 0, j; switch (table[iTableIMIndex].tableOrder) { case AD_NO: if (mode == SM_PREV) { if (iCandWordCount == iMaxCandWord) i = iCandWordCount - 1; else { for (i = 0; i < iCandWordCount; i++) { if (tableCandWord[i].flag != CT_NORMAL) break; } } } else { if (iCandWordCount == iMaxCandWord) return; tableCandWord[iCandWordCount].flag = CT_NORMAL; tableCandWord[iCandWordCount++].candWord.record = record; return; } break; case AD_FREQ: if (mode == SM_PREV) { for (i = iCandWordCount - 1; i >= 0; i--) { if (tableCandWord[i].flag == CT_NORMAL) { if (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) < 0 || (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) == 0 && tableCandWord[i].candWord.record->iHit >= record->iHit)) break; } } if (iCandWordCount == iMaxCandWord) { if (i < 0) return; } else i++; } else { for (; i < iCandWordCount; i++) { if (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) > 0 || (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) == 0 && tableCandWord[i].candWord.record->iHit < record->iHit)) break; } if (i == iMaxCandWord) return; } break; case AD_FAST: if (mode == SM_PREV) { for (i = iCandWordCount - 1; i >= 0; i--) { if (tableCandWord[i].flag == CT_NORMAL) { if (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) < 0 || (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) == 0 && tableCandWord[i].candWord.record->iIndex >= record->iIndex)) break; } } if (iCandWordCount == iMaxCandWord) { if (i < 0) return; } else i++; } else { for (i = 0; i < iCandWordCount; i++) { if (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) > 0 || (strcmp (tableCandWord[i].candWord.record->strCode, record->strCode) == 0 && tableCandWord[i].candWord.record->iIndex < record->iIndex)) break; } if (i == iMaxCandWord) return; } break; } if (mode == SM_PREV) { if (iCandWordCount == iMaxCandWord) { for (j = 0; j < i; j++) { tableCandWord[j].flag = tableCandWord[j + 1].flag; if (tableCandWord[j].flag == CT_NORMAL) tableCandWord[j].candWord.record = tableCandWord[j + 1].candWord.record; else tableCandWord[j].candWord.autoPhrase = tableCandWord[j + 1].candWord.autoPhrase; } } else { for (j = iCandWordCount; j > i; j--) { tableCandWord[j].flag = tableCandWord[j - 1].flag; if (tableCandWord[j].flag == CT_NORMAL) tableCandWord[j].candWord.record = tableCandWord[j - 1].candWord.record; else tableCandWord[j].candWord.autoPhrase = tableCandWord[j - 1].candWord.autoPhrase; } } } else { j = iCandWordCount; if (iCandWordCount == iMaxCandWord) j--; for (; j > i; j--) { tableCandWord[j].flag = tableCandWord[j - 1].flag; if (tableCandWord[j].flag == CT_NORMAL) tableCandWord[j].candWord.record = tableCandWord[j - 1].candWord.record; else tableCandWord[j].candWord.autoPhrase = tableCandWord[j - 1].candWord.autoPhrase; } } tableCandWord[i].flag = CT_NORMAL; tableCandWord[i].candWord.record = record; if (iCandWordCount != iMaxCandWord) iCandWordCount++; } void TableResetFlags (void) { RECORD *record = recordHead->next; INT16 i; while (record != recordHead) { record->flag = False; record = record->next; } for (i = 0; i < iAutoPhrase; i++) autoPhrase[i].flag = False; } void TableSetCandWordsFlag (int iCount, Bool flag) { int i; for (i = 0; i < iCount; i++) { if (tableCandWord[i].flag == CT_NORMAL) tableCandWord[i].candWord.record->flag = flag; else tableCandWord[i].candWord.autoPhrase->flag = flag; } } Bool HasMatchingKey (void) { char *str; str = strCodeInput; while (*str) { if (*str++ == table[iTableIMIndex].cMatchingKey) return True; } return False; } int TableCompareCode (char *strUser, char *strDict) { int i; for (i = 0; i < strlen (strUser); i++) { if (!strDict[i]) return strUser[i]; if (strUser[i] != table[iTableIMIndex].cMatchingKey || !table[iTableIMIndex].bUseMatchingKey) { if (strUser[i] != strDict[i]) return (strUser[i] - strDict[i]); } } if (table[iTableIMIndex].bTableExactMatch) { if (strlen (strUser) != strlen (strDict)) return -999; //随意的一个值 } return 0; } int TableFindFirstMatchCode (void) { int i = 0; if (!recordHead) return -1; if (table[iTableIMIndex].bUseMatchingKey && (strCodeInput[0] == table[iTableIMIndex].cMatchingKey)) i = 0; else { while (strCodeInput[0] != recordIndex[i].cCode) i++; } currentRecord = recordIndex[i].record; if (!currentRecord) return -1; while (currentRecord != recordHead) { if (!TableCompareCode (strCodeInput, currentRecord->strCode)) { if (CheckHZCharset (currentRecord->strHZ)) return i; } currentRecord = currentRecord->next; i++; } return -1; //Not found } /* * 反查编码 * bMode=True表示用于组词,此时不查一、二级简码。但如果只有二级简码时返回二级简码,不查一级简码 */ /*RECORD *TableFindCode (char *strHZ, Bool bMode) { RECORD *recShort = NULL; //记录二级简码的位置 int i; for (i = 0; i < iSingleHZCount; i++) { if (!strcmp (tableSingleHZ[i]->strHZ, strHZ) && !IsIgnoreChar (tableSingleHZ[i]->strCode[0])) { if (!bMode) return tableSingleHZ[i]; if (strlen (tableSingleHZ[i]->strCode) == 2) recShort = tableSingleHZ[i]; else if (strlen (tableSingleHZ[i]->strCode) > 2) return tableSingleHZ[i]; } } return recShort; }*/ /* * 根据序号调整词组顺序,序号从1开始 * 将指定的字/词调整到同样编码的最前面 */ void TableAdjustOrderByIndex (int iIndex) { RECORD *recTemp; int iTemp; if (tableCandWord[iIndex - 1].flag != CT_NORMAL) return; recTemp = tableCandWord[iIndex - 1].candWord.record; while (!strcmp (recTemp->strCode, recTemp->prev->strCode)) recTemp = recTemp->prev; if (recTemp == tableCandWord[iIndex - 1].candWord.record) //说明已经是第一个 return; //将指定的字/词放到recTemp前 tableCandWord[iIndex - 1].candWord.record->prev->next = tableCandWord[iIndex - 1].candWord.record->next; tableCandWord[iIndex - 1].candWord.record->next->prev = tableCandWord[iIndex - 1].candWord.record->prev; recTemp->prev->next = tableCandWord[iIndex - 1].candWord.record; tableCandWord[iIndex - 1].candWord.record->prev = recTemp->prev; recTemp->prev = tableCandWord[iIndex - 1].candWord.record; tableCandWord[iIndex - 1].candWord.record->next = recTemp; iTableChanged++; //需要的话,更新索引 if (tableCandWord[iIndex - 1].candWord.record->strCode[1] == '\0') { for (iTemp = 0; iTemp < strlen (table[iTableIMIndex].strInputCode); iTemp++) { if (recordIndex[iTemp].cCode == tableCandWord[iIndex - 1].candWord.record->strCode[0]) { recordIndex[iTemp].record = tableCandWord[iIndex - 1].candWord.record; break; } } } if (iTableChanged == 5) SaveTableDict (); } /* * 根据序号删除词组,序号从1开始 */ void TableDelPhraseByIndex (int iIndex) { if (tableCandWord[iIndex - 1].flag != CT_NORMAL) return; if (strlen (tableCandWord[iIndex - 1].candWord.record->strHZ) <= 2) return; TableDelPhrase (tableCandWord[iIndex - 1].candWord.record); } /* * 根据字串删除词组 */ void TableDelPhraseByHZ (char *strHZ) { RECORD *recTemp; recTemp = TableFindPhrase (strHZ); if (recTemp) TableDelPhrase (recTemp); } void TableDelPhrase (RECORD * record) { record->prev->next = record->next; record->next->prev = record->prev; free (record->strCode); free (record->strHZ); free (record); table[iTableIMIndex].iRecordCount--; SaveTableDict (); } /* *判断某个词组是不是已经在词库中,有返回NULL,无返回插入点 */ RECORD *TableHasPhrase (char *strCode, char *strHZ) { RECORD *recTemp; int i; i = 0; while (strCode[0] != recordIndex[i].cCode) i++; recTemp = recordIndex[i].record; while (recTemp != recordHead) { if (strcmp (recTemp->strCode, strCode) > 0) break; else if (!strcmp (recTemp->strCode, strCode)) { if (!strcmp (recTemp->strHZ, strHZ)) //该词组已经在词库中 return NULL; } recTemp = recTemp->next; } return recTemp; } /* *根据字串判断词库中是否有某个字/词 */ RECORD *TableFindPhrase (char *strHZ) { RECORD *recTemp; char strTemp[3]; int i; //首先,先查找第一个汉字的编码 strTemp[0] = strHZ[0]; strTemp[1] = strHZ[1]; strTemp[2] = '\0'; recTemp = tableSingleHZ[CalHZIndex (strTemp)]; if (!recTemp) return (RECORD *) NULL; //然后根据该编码找到检索的起始点 i = 0; while (recTemp->strCode[0] != recordIndex[i].cCode) i++; recTemp = recordIndex[i].record; while (recTemp != recordHead) { if (recTemp->strCode[0] != recordIndex[i].cCode) break; if (!strcmp (recTemp->strHZ, strHZ)) return recTemp; recTemp = recTemp->next; } return (RECORD *) NULL; } void TableInsertPhrase (char *strCode, char *strHZ) { RECORD *insertPoint, *dictNew; insertPoint = TableHasPhrase (strCode, strHZ); if (!insertPoint) return; dictNew = (RECORD *) malloc (sizeof (RECORD)); dictNew->strCode = (char *) malloc (sizeof (char) * (table[iTableIMIndex].iCodeLength + 1)); strcpy (dictNew->strCode, strCode); dictNew->strHZ = (char *) malloc (sizeof (char) * (strlen (strHZ) + 1)); strcpy (dictNew->strHZ, strHZ); dictNew->iHit = 0; dictNew->iIndex = iTableIndex; dictNew->prev = insertPoint->prev; insertPoint->prev->next = dictNew; insertPoint->prev = dictNew; dictNew->next = insertPoint; table[iTableIMIndex].iRecordCount++; SaveTableDict (); } void TableCreateNewPhrase (void) { int i; messageDown[0].strMsg[0] = '\0'; for (i = iTableNewPhraseHZCount; i > 0; i--) strcat (messageDown[0].strMsg, hzLastInput[iHZLastInputCount - i].strHZ); TableCreatePhraseCode (messageDown[0].strMsg); if (!bCanntFindCode) strcpy (messageDown[1].strMsg, strNewPhraseCode); else strcpy (messageDown[1].strMsg, "????"); } void TableCreatePhraseCode (char *strHZ) { unsigned char i; unsigned char i1, i2; int iLen; char strTemp[3]; RECORD *recTemp; strTemp[2] = '\0'; bCanntFindCode = False; iLen = strlen (strHZ) / 2; if (iLen >= table[iTableIMIndex].iCodeLength) { i2 = table[iTableIMIndex].iCodeLength; i1 = 1; } else { i2 = iLen; i1 = 0; } for (i = 0; i < table[iTableIMIndex].iCodeLength - 1; i++) { if (table[iTableIMIndex].rule[i].iWords == i2 && table[iTableIMIndex].rule[i].iFlag == i1) break; } for (i1 = 0; i1 < table[iTableIMIndex].iCodeLength; i1++) { if (table[iTableIMIndex].rule[i].rule[i1].iFlag) { strTemp[0] = strHZ[(table[iTableIMIndex].rule[i].rule[i1].iWhich - 1) * 2]; strTemp[1] = strHZ[(table[iTableIMIndex].rule[i].rule[i1].iWhich - 1) * 2 + 1]; } else { strTemp[0] = strHZ[(iLen - table[iTableIMIndex].rule[i].rule[i1].iWhich) * 2]; strTemp[1] = strHZ[(iLen - table[iTableIMIndex].rule[i].rule[i1].iWhich) * 2 + 1]; } recTemp = tableSingleHZ[CalHZIndex (strTemp)]; if (!recTemp) { bCanntFindCode = True; break; } strNewPhraseCode[i1] = recTemp->strCode[table[iTableIMIndex].rule[i].rule[i1].iIndex - 1]; } } /* * 获取联想候选字列表 */ INPUT_RETURN_VALUE TableGetLegendCandWords (SEARCH_MODE mode) { char strTemp[3]; int iLength; int i; RECORD *tableLegend = NULL; unsigned int iTableTotalLengendCandCount = 0; if (!strTableLegendSource[0]) return IRV_TO_PROCESS; iLength = strlen (strTableLegendSource); if (mode == SM_FIRST) { iCurrentLegendCandPage = 0; iLegendCandPageCount = 0; TableResetFlags (); } else { if (!iLegendCandPageCount) return IRV_TO_PROCESS; if (mode == SM_NEXT) { if (iCurrentLegendCandPage == iLegendCandPageCount) return IRV_DO_NOTHING; iCurrentLegendCandPage++; } else { if (!iCurrentLegendCandPage) return IRV_DO_NOTHING; TableSetCandWordsFlag (iLegendCandWordCount, False); iCurrentLegendCandPage--; } } iLegendCandWordCount = 0; tableLegend = recordHead->next; while (tableLegend != recordHead) { if (((mode == SM_PREV) ^ (!tableLegend->flag)) && ((iLength + 2) == strlen (tableLegend->strHZ))) { if (!strncmp (tableLegend->strHZ, strTableLegendSource, iLength) && tableLegend->strHZ[iLength] && CheckHZCharset (tableLegend->strHZ)) { if (mode == SM_FIRST) iTableTotalLengendCandCount++; TableAddLegendCandWord (tableLegend, mode); } } tableLegend = tableLegend->next; } TableSetCandWordsFlag (iLegendCandWordCount, True); if (mode == SM_FIRST && bDisablePagingInLegend) iLegendCandPageCount = iTableTotalLengendCandCount / iMaxCandWord - ((iTableTotalLengendCandCount % iMaxCandWord) ? 0 : 1); uMessageUp = 2; strcpy (messageUp[0].strMsg, "联想:"); messageUp[0].type = MSG_TIPS; strcpy (messageUp[1].strMsg, strTableLegendSource); messageUp[1].type = MSG_INPUT; if (bPointAfterNumber) { strTemp[1] = '.'; strTemp[2] = '\0'; } else strTemp[1] = '\0'; uMessageDown = 0; for (i = 0; i < iLegendCandWordCount; i++) { if (i == 9) strTemp[0] = '0'; else strTemp[0] = i + 1 + '0'; strcpy (messageDown[uMessageDown].strMsg, strTemp); messageDown[uMessageDown++].type = MSG_INDEX; strcpy (messageDown[uMessageDown].strMsg, tableCandWord[i].candWord.record->strHZ + strlen (strTableLegendSource)); if (i != (iLegendCandWordCount - 1)) { strcat (messageDown[uMessageDown].strMsg, " "); } messageDown[uMessageDown++].type = ((i == 0) ? MSG_FIRSTCAND : MSG_OTHER); } bIsInLegend = (iLegendCandWordCount != 0); return IRV_DISPLAY_CANDWORDS; } void TableAddLegendCandWord (RECORD * record, SEARCH_MODE mode) { int i, j; if (mode == SM_PREV) { for (i = iLegendCandWordCount - 1; i >= 0; i--) { if (tableCandWord[i].candWord.record->iHit >= record->iHit) break; } if (iLegendCandWordCount == iMaxCandWord) { if (i < 0) return; } else i++; } else { for (i = 0; i < iLegendCandWordCount; i++) { if (tableCandWord[i].candWord.record->iHit < record->iHit) break; } if (i == iMaxCandWord) return; } if (mode == SM_PREV) { if (iLegendCandWordCount == iMaxCandWord) { for (j = 0; j < i; j++) tableCandWord[j].candWord.record = tableCandWord[j + 1].candWord.record; } else { for (j = iLegendCandWordCount; j > i; j--) tableCandWord[j].candWord.record = tableCandWord[j - 1].candWord.record; } } else { j = iLegendCandWordCount; if (iLegendCandWordCount == iMaxCandWord) j--; for (; j > i; j--) tableCandWord[j].candWord.record = tableCandWord[j - 1].candWord.record; } tableCandWord[i].flag = CT_NORMAL; tableCandWord[i].candWord.record = record; if (iLegendCandWordCount != iMaxCandWord) iLegendCandWordCount++; } char *TableGetLegendCandWord (int iIndex) { if (iLegendCandWordCount) { if (iIndex > (iLegendCandWordCount - 1)) iIndex = iLegendCandWordCount - 1; tableCandWord[iIndex].candWord.record->iHit++; strcpy (strTableLegendSource, tableCandWord[iIndex].candWord.record->strHZ + strlen (strTableLegendSource)); TableGetLegendCandWords (SM_FIRST); return strTableLegendSource; } return NULL; } INPUT_RETURN_VALUE TableGetFHCandWords (SEARCH_MODE mode) { char strTemp[3]; int i; if (!iFH) return IRV_DISPLAY_MESSAGE; if (bPointAfterNumber) { strTemp[1] = '.'; strTemp[2] = '\0'; } else strTemp[1] = '\0'; uMessageDown = 0; if (mode == SM_FIRST) { iCandPageCount = iFH / iMaxCandWord - ((iFH % iMaxCandWord) ? 0 : 1); iCurrentCandPage = 0; } else { if (!iCandPageCount) return IRV_TO_PROCESS; if (mode == SM_NEXT) { if (iCurrentCandPage == iCandPageCount) return IRV_DO_NOTHING; iCurrentCandPage++; } else { if (!iCurrentCandPage) return IRV_DO_NOTHING; iCurrentCandPage--; } } for (i = 0; i < iMaxCandWord; i++) { strTemp[0] = i + 1 + '0'; if (i == 9) strTemp[0] = '0'; strcpy (messageDown[uMessageDown].strMsg, strTemp); messageDown[uMessageDown++].type = MSG_INDEX; strcpy (messageDown[uMessageDown].strMsg, fh[iCurrentCandPage * iMaxCandWord + i].strFH); if (i != (iMaxCandWord - 1)) { strcat (messageDown[uMessageDown].strMsg, " "); } messageDown[uMessageDown++].type = ((i == 0) ? MSG_FIRSTCAND : MSG_OTHER); if ((iCurrentCandPage * iMaxCandWord + i) >= (iFH - 1)) { i++; break; } } iCandWordCount = i; return IRV_DISPLAY_CANDWORDS; } char *TableGetFHCandWord (int iIndex) { uMessageDown = 0; if (iCandWordCount) { if (iIndex > (iCandWordCount - 1)) iIndex = iCandWordCount - 1; return fh[iCurrentCandPage * iMaxCandWord + iIndex].strFH; } return NULL; } Bool TablePhraseTips (void) { RECORD *recTemp = NULL; char strTemp[PHRASE_MAX_LENGTH * 2 + 1] = "\0"; INT16 i, j; if (!recordHead) return False; //如果最近输入了一个词组,这个工作就不需要了 if (lastIsSingleHZ != 1) return False; j = (iHZLastInputCount > PHRASE_MAX_LENGTH) ? iHZLastInputCount - PHRASE_MAX_LENGTH : 0; for (i = j; i < iHZLastInputCount; i++) strcat (strTemp, hzLastInput[i].strHZ); //如果只有一个汉字,这个工作也不需要了 if (strlen (strTemp) < 4) return False; //首先要判断是不是已经在词库中 for (i = 0; i < (iHZLastInputCount - j - 1); i++) { recTemp = TableFindPhrase (strTemp + i * 2); if (recTemp) { strcpy (messageUp[0].strMsg, "词库中有词组 "); messageUp[0].type = MSG_TIPS; strcpy (messageUp[1].strMsg, strTemp + i * 2); messageUp[1].type = MSG_INPUT; uMessageUp = 2; strcpy (messageDown[0].strMsg, "编码为 "); messageDown[0].type = MSG_FIRSTCAND; strcpy (messageDown[1].strMsg, recTemp->strCode); messageDown[1].type = MSG_CODE; strcpy (messageDown[2].strMsg, " ^DEL删除"); messageDown[2].type = MSG_TIPS; uMessageDown = 3; bTablePhraseTips = True; bShowCursor = False; return True; } } return False; } void TableCreateAutoPhrase (INT8 iCount) { char strHZ[table[iTableIMIndex].iAutoPhrase * 2 + 1]; INT16 i, j, k; /* * 为了提高效率,此处只重新生成新录入字构成的词组 */ j = iHZLastInputCount - table[iTableIMIndex].iAutoPhrase - iCount; if (j < 0) j = 0; for (; j < iHZLastInputCount - 1; j++) { for (i = table[iTableIMIndex].iAutoPhrase; i >= 2; i--) { if ((j + i - 1) > iHZLastInputCount) continue; strcpy (strHZ, hzLastInput[j].strHZ); for (k = 1; k < i; k++) strcat (strHZ, hzLastInput[j + k].strHZ); //再去掉重复的词组 for (k = 0; k < iAutoPhrase; k++) { if (!strcmp (autoPhrase[k].strHZ, strHZ)) goto _next; } TableCreatePhraseCode (strHZ); if (iAutoPhrase != AUTO_PHRASE_COUNT) { autoPhrase[iAutoPhrase].flag = False; strcpy (autoPhrase[iAutoPhrase].strCode, strNewPhraseCode); strcpy (autoPhrase[iAutoPhrase].strHZ, strHZ); autoPhrase[iAutoPhrase].iSelected = 0; iAutoPhrase++; } else { insertPoint->flag = False; strcpy (insertPoint->strCode, strNewPhraseCode); strcpy (insertPoint->strHZ, strHZ); insertPoint->iSelected = 0; insertPoint = insertPoint->next; } _next: continue; } } /* for (i=0;i