1 /***************************************************************************
2 * Copyright (C) 2002~2005 by Yuking *
3 * yuking_net@sohu.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20 #include "config.h"
21
22
23 #include "table.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <libintl.h>
29 #include <errno.h>
30
31 #include "fcitx/fcitx.h"
32 #include "fcitx/keys.h"
33 #include "fcitx/ui.h"
34 #include "fcitx/profile.h"
35 #include "fcitx-utils/log.h"
36 #include "fcitx/module.h"
37 #include "fcitx/frontend.h"
38 #include "fcitx/candidate.h"
39 #include "fcitx/context.h"
40 #include "fcitx-config/xdg.h"
41 #include "fcitx-utils/utarray.h"
42 #include "fcitx-utils/utils.h"
43 #include "im/pinyin/fcitx-pinyin.h"
44 #include "module/punc/fcitx-punc.h"
45 #include "module/pinyin-enhance/fcitx-pinyin-enhance.h"
46
47 #define MAX_TABLE_INPUT 50
48
49 static void TableMetaDataFree(TableMetaData *table);
50 typedef struct {
51 ADJUSTORDER order;
52 int simpleLevel;
53 } TableCandWordSortContext;
54
55 static void *TableCreate(FcitxInstance* instance);
56 static int TableCandCmp(const void* a, const void* b, void* arg);
57 static INPUT_RETURN_VALUE TableKeyBlocker(void* arg, FcitxKeySym sym, unsigned int state);
58 static INPUT_RETURN_VALUE Table_PYGetCandWord(void *arg,
59 FcitxCandidateWord *candidateWord);
60
61 FCITX_DEFINE_PLUGIN(fcitx_table, ime2, FcitxIMClass2) = {
62 TableCreate,
63 NULL,
64 ReloadTableConfig,
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL
70 };
71
72 static boolean LoadTableConfig(TableConfig* config);
73 static void SaveTableConfig(TableConfig* config);
74
GetTableMod(TableMetaData * table)75 static inline unsigned int GetTableMod(TableMetaData* table)
76 {
77 static unsigned int cmodtable[] = {
78 FcitxKeyState_None, FcitxKeyState_Alt,
79 FcitxKeyState_Ctrl, FcitxKeyState_Shift
80 };
81 if (fcitx_unlikely(table->chooseModifier >= _CM_COUNT))
82 table->chooseModifier = _CM_COUNT - 1;
83
84 return cmodtable[table->chooseModifier];
85 }
86
LoadTableConfig(TableConfig * config)87 boolean LoadTableConfig(TableConfig* config)
88 {
89 FcitxConfigFileDesc* configDesc = GetTableGlobalConfigDesc();
90 if (configDesc == NULL)
91 return false;
92
93 FILE *fp;
94 fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-table.config", "r", NULL);
95 if (!fp) {
96 if (errno == ENOENT)
97 SaveTableConfig(config);
98 }
99
100 FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, configDesc);
101
102 TableConfigConfigBind(config, cfile, configDesc);
103 FcitxConfigBindSync((FcitxGenericConfig*)config);
104
105 if (fp)
106 fclose(fp);
107
108 return true;
109 }
110
SaveTableConfig(TableConfig * config)111 void SaveTableConfig(TableConfig *config)
112 {
113 FCITX_UNUSED(config);
114 }
115
TableCreate(FcitxInstance * instance)116 void *TableCreate(FcitxInstance* instance)
117 {
118 FcitxTableState *tbl = fcitx_utils_malloc0(sizeof(FcitxTableState));
119 tbl->owner = instance;
120 if (!LoadTableConfig(&tbl->config)) {
121 free(tbl);
122 return NULL;
123 }
124 LoadTableInfo(tbl);
125
126
127 return tbl;
128 }
129
SaveTableIM(void * arg)130 void SaveTableIM(void *arg)
131 {
132 TableMetaData* table = (TableMetaData*) arg;
133
134 if (!table->tableDict)
135 return;
136 if (table->tableDict && table->tableDict->iTableChanged)
137 SaveTableDict(table);
138 }
139
TableMetaDataGetName(TableMetaData * table)140 static inline char* TableMetaDataGetName(TableMetaData* table)
141 {
142 return (strlen(table->uniqueName) == 0) ?
143 table->strIconName : table->uniqueName;
144 }
145
TableMetaDataInsert(TableMetaData ** tableSet,TableMetaData * table)146 static inline void TableMetaDataInsert(TableMetaData** tableSet, TableMetaData* table)
147 {
148 char* name = TableMetaDataGetName(table);
149 HASH_ADD_KEYPTR(hh, *tableSet, name, strlen(name), table);
150 }
151
TableMetaDataFind(TableMetaData * table,const char * name)152 static inline TableMetaData* TableMetaDataFind(TableMetaData* table, const char* name)
153 {
154 TableMetaData* result = NULL;
155 HASH_FIND_STR(table, name, result);
156 return result;
157 }
158
TableMetaDataUnlink(TableMetaData ** tableSet,TableMetaData * table)159 static inline void TableMetaDataUnlink(TableMetaData** tableSet, TableMetaData* table)
160 {
161 HASH_DEL(*tableSet, table);
162 }
163
TableMetaDataRemove(TableMetaData ** tableSet,TableMetaData * table)164 static inline void TableMetaDataRemove(TableMetaData** tableSet, TableMetaData* table)
165 {
166 HASH_DEL(*tableSet, table);
167 TableMetaDataFree(table);
168 }
169
TableMetaDataRegister(FcitxTableState * tbl,TableMetaData * table)170 static inline void TableMetaDataRegister(FcitxTableState* tbl, TableMetaData* table)
171 {
172 table->status = TABLE_REGISTERED;
173 FcitxInstanceRegisterIM(
174 tbl->owner,
175 table,
176 TableMetaDataGetName(table),
177 table->strName,
178 table->strIconName,
179 TableInit,
180 TableResetStatus,
181 DoTableInput,
182 TableGetCandWords,
183 TablePhraseTips,
184 SaveTableIM,
185 NULL,
186 TableKeyBlocker,
187 table->iPriority,
188 table->langCode
189 );
190 }
191
TableConfigStealTableName(FcitxConfigFile * cfile)192 static inline char* TableConfigStealTableName(FcitxConfigFile* cfile)
193 {
194 FcitxConfigOption* option = FcitxConfigFileGetOption(cfile, "CodeTable",
195 "UniqueName");
196 if (option && strlen(option->rawValue))
197 return option->rawValue;
198
199 option = FcitxConfigFileGetOption(cfile, "CodeTable", "IconName");
200 if (option)
201 return option->rawValue;
202 return NULL;
203 }
204
205 /*
206 * Read table configuration
207 * and returns whether table im is really changed.
208 */
LoadTableInfo(FcitxTableState * tbl)209 boolean LoadTableInfo(FcitxTableState *tbl)
210 {
211 FcitxStringHashSet* sset = NULL;
212 tbl->bTablePhraseTips = false;
213 if (tbl->curLoadedTable) {
214 FreeTableDict(tbl->curLoadedTable);
215 tbl->curLoadedTable = NULL;
216 }
217
218 sset = FcitxXDGGetFiles("table", NULL, ".conf");
219
220 {
221 TableMetaData* titer = tbl->tables;
222 while(titer)
223 {
224 titer->status = TABLE_PENDING;
225 titer = titer->hh.next;
226 }
227 }
228
229 boolean imchanged = false;
230 HASH_FOREACH(string, sset, FcitxStringHashSet) {
231 // FcitxLog(INFO, _("Load Table Config File:%s"), string->name);
232 FILE* fp = FcitxXDGGetFileWithPrefix("table", string->name, "r", NULL);
233 if (!fp) {
234 continue;
235 }
236 FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, GetTableConfigDesc());
237 fclose(fp);
238 if (!cfile) {
239 continue;
240 }
241 char *tableName = TableConfigStealTableName(cfile);
242 boolean needunregister = true;
243 if (!tableName) {
244 continue;
245 }
246 TableMetaData* t = TableMetaDataFind(tbl->tables, tableName);
247 if (!t) {
248 t = fcitx_utils_new(TableMetaData);
249 needunregister = false;
250 } else {
251 TableMetaDataUnlink(&tbl->tables, t);
252 }
253 TableMetaDataConfigBind(t, cfile, GetTableConfigDesc());
254 FcitxConfigBindSync((FcitxGenericConfig*)t);
255 if (t->bEnabled) {
256 t->confName = strdup(string->name);
257 t->owner = tbl;
258 TableMetaDataInsert(&tbl->tables, t);
259 if (needunregister)
260 t->status = TABLE_REGISTERED;
261 else
262 t->status = TABLE_NEW;
263 } else {
264 if (needunregister) {
265 FcitxInstanceUnregisterIM(tbl->owner,
266 TableMetaDataGetName(t));
267 imchanged = true;
268 }
269 TableMetaDataFree(t);
270 }
271 }
272 fcitx_utils_free_string_hash_set(sset);
273
274 TableMetaData* titer = tbl->tables;
275 while (titer) {
276 /*
277 * if it's this case, the configuration file may already gone
278 * thus let's remove it
279 */
280 if (titer->status == TABLE_PENDING) {
281 TableMetaData* cur = titer;
282 FcitxInstanceUnregisterIM(tbl->owner, TableMetaDataGetName(cur));
283 TableMetaDataRemove(&tbl->tables, cur);
284 imchanged = true;
285 } else {
286 if (titer->status != TABLE_REGISTERED) {
287 // FcitxLog(INFO, "register %s", TableMetaDataGetName(titer));
288 TableMetaDataRegister(tbl, titer);
289 imchanged = true;
290 }
291 titer = titer->hh.next;
292 }
293 }
294
295 tbl->iTableCount = HASH_COUNT(tbl->tables);
296 return imchanged;
297 }
298
299 CONFIG_DESC_DEFINE(GetTableConfigDesc, "table.desc")
300 CONFIG_DESC_DEFINE(GetTableGlobalConfigDesc, "fcitx-table.desc")
301
TableInit(void * arg)302 boolean TableInit(void *arg)
303 {
304 TableMetaData* table = (TableMetaData*) arg;
305 FcitxTableState *tbl = table->owner;
306 boolean flag = true;
307 FcitxInstanceSetContext(tbl->owner, CONTEXT_IM_KEYBOARD_LAYOUT, table->kbdlayout);
308 FcitxInstanceSetContext(tbl->owner, CONTEXT_SHOW_REMIND_STATUS, &flag);
309 if (table->bUseAlternativePageKey) {
310 FcitxInstanceSetContext(tbl->owner, CONTEXT_ALTERNATIVE_PREVPAGE_KEY,
311 table->hkAlternativePrevPage);
312 FcitxInstanceSetContext(tbl->owner, CONTEXT_ALTERNATIVE_NEXTPAGE_KEY,
313 table->hkAlternativeNextPage);
314 }
315 FcitxAddon* pyaddon = FcitxPinyinGetAddon(tbl->owner);
316 tbl->pyaddon = pyaddon;
317 tbl->PYBaseOrder = AD_FREQ;
318
319 FcitxPinyinReset(tbl->owner);
320 return true;
321 }
322
TableResetStatus(void * arg)323 void TableResetStatus(void* arg)
324 {
325 TableMetaData* table = (TableMetaData*) arg;
326 FcitxTableState *tbl = table->owner;
327 FcitxInputState *input = FcitxInstanceGetInputState(tbl->owner);
328 tbl->bIsTableAddPhrase = false;
329 tbl->bIsTableDelPhrase = false;
330 tbl->bIsTableClearFreq = false;
331 tbl->bIsTableAdjustOrder = false;
332 FcitxInputStateSetIsDoInputOnly(input, false);
333 //bSingleHZMode = false;
334 }
335
TableCheckNoMatch(TableMetaData * table,const char * code)336 boolean TableCheckNoMatch(TableMetaData* table, const char* code)
337 {
338 FcitxInstance *instance = table->owner->owner;
339 FcitxInputState *input = FcitxInstanceGetInputState(instance);
340 FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
341 if (!table->bTableExactMatch) {
342 return FcitxCandidateWordGetListSize(candList) == 0;
343 } else {
344 return (FcitxCandidateWordGetListSize(candList) == 0) &&
345 TableFindFirstMatchCode(table, code, false, false) == -1;
346 }
347 }
348
DoTableInput(void * arg,FcitxKeySym sym,unsigned int state)349 INPUT_RETURN_VALUE DoTableInput(void* arg, FcitxKeySym sym, unsigned int state)
350 {
351 TableMetaData* table = (TableMetaData*) arg;
352 FcitxTableState *tbl = table->owner;
353 INPUT_RETURN_VALUE retVal;
354 FcitxInstance *instance = tbl->owner;
355 FcitxInputState *input = FcitxInstanceGetInputState(instance);
356 FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(instance);
357 char* strCodeInput = FcitxInputStateGetRawInputBuffer(input);
358 FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
359 char *output_str = FcitxInputStateGetOutputString(input);
360
361 FcitxCandidateWordSetChooseAndModifier(candList, table->strChoose,
362 GetTableMod(table));
363 if (table->bUseAlternativeCandidateWordNumber) {
364 FcitxCandidateWordSetPageSize(candList, table->iCandidateWordNumber);
365 } else {
366 FcitxCandidateWordSetPageSize(candList, config->iMaxCandWord);
367 }
368
369 if (table != tbl->curLoadedTable && tbl->curLoadedTable) {
370 FreeTableDict(tbl->curLoadedTable);
371 tbl->curLoadedTable = NULL;
372 }
373
374 if (tbl->curLoadedTable == NULL) {
375 if (!LoadTableDict(table)) {
376 FcitxInstanceUnregisterIM(instance, TableMetaDataGetName(table));
377 FcitxInstanceUpdateIMList(instance);
378 return IRV_DONOT_PROCESS;
379 }
380 tbl->curLoadedTable = table;
381 }
382
383 if (FcitxHotkeyIsHotKeyModifierCombine(sym, state))
384 return IRV_TO_PROCESS;
385
386 if (tbl->bTablePhraseTips) {
387 if (FcitxHotkeyIsHotKey(sym, state, FCITX_CTRL_DELETE)) {
388 tbl->bTablePhraseTips = false;
389 TableDelPhraseByHZ(table->tableDict, FcitxMessagesGetMessageString(FcitxInputStateGetAuxUp(input), 1));
390 return IRV_CLEAN;
391 } else if (state == FcitxKeyState_None && (sym != FcitxKey_Control_L && sym != FcitxKey_Control_R && sym != FcitxKey_Shift_L && sym != FcitxKey_Shift_R)) {
392 FcitxInstanceCleanInputWindow(instance);
393 tbl->bTablePhraseTips = false;
394 FcitxUICloseInputWindow(instance);
395 }
396 }
397
398 retVal = IRV_DO_NOTHING;
399 if (state == FcitxKeyState_None &&
400 (IsInputKey(table->tableDict, sym)
401 || IsEndKey(table, sym)
402 || (table->bUseMatchingKey && sym == table->cMatchingKey)
403 || (table->bUsePY && sym == table->cPinyin)
404 || (strCodeInput[0] == table->cPinyin && table->bUsePY && sym == FcitxKey_apostrophe)
405 )
406 ) {
407 if (FcitxInputStateGetIsInRemind(input))
408 FcitxCandidateWordReset(candList);
409 FcitxInputStateSetIsInRemind(input, false);
410
411 /* it's not in special state */
412 if (!tbl->bIsTableAddPhrase && !tbl->bIsTableDelPhrase &&
413 !tbl->bIsTableAdjustOrder && !tbl->bIsTableClearFreq) {
414 size_t raw_size = FcitxInputStateGetRawInputBufferSize(input);
415 if (FcitxHotkeyCheckChooseKeyAndModifier(sym, state,
416 table->strChoose,
417 GetTableMod(table)) >= 0) {
418 size_t len1 = strlen(strCodeInput);
419 size_t len = len1 > raw_size ? raw_size : len1;
420 char buf[len + 2];
421 memcpy(buf, strCodeInput, len);
422 buf[len] = (char)sym;
423 buf[len + 1] = '\0';
424 if (TableFindFirstMatchCode(table, buf, false, false) == -1)
425 return IRV_TO_PROCESS;
426 }
427
428 /* check we use Pinyin or Not */
429 if (strCodeInput[0] == table->cPinyin && table->bUsePY) {
430 if (raw_size != (MAX_PY_LENGTH * 5 + 1)) {
431 strCodeInput[raw_size] = (char) sym;
432 raw_size++;
433 strCodeInput[raw_size] = '\0';
434 FcitxInputStateSetRawInputBufferSize(input, raw_size);
435 retVal = IRV_DISPLAY_CANDWORDS;
436 } else {
437 retVal = IRV_DO_NOTHING;
438 }
439 } else {
440 /* length is not too large */
441 if (((raw_size < table->tableDict->iCodeLength) ||
442 (table->tableDict->bHasPinyin &&
443 raw_size < table->tableDict->iPYCodeLength) ||
444 (((TableCheckNoMatch(table, FcitxInputStateGetRawInputBuffer(input)) &&
445 table->bNoMatchDontCommit) || !table->bUseAutoSend) &&
446 raw_size >= table->tableDict->iCodeLength)) &&
447 raw_size <= MAX_TABLE_INPUT) {
448 strCodeInput[raw_size] = (char)sym;
449 raw_size++;
450 strCodeInput[raw_size] = '\0';
451 FcitxInputStateSetRawInputBufferSize(input, raw_size);
452
453 if (raw_size == 1 && strCodeInput[0] == table->cPinyin &&
454 table->bUsePY) {
455 retVal = IRV_DISPLAY_LAST;
456 } else {
457 char *strTemp = NULL;
458 char *strLastFirstCand;
459 CANDTYPE lastFirstCandType;
460
461 strLastFirstCand = (char *)NULL;
462 lastFirstCandType = CT_AUTOPHRASE;
463 if (FcitxCandidateWordPageCount(candList) != 0) {
464 // to realize auto-sending HZ to client
465 FcitxCandidateWord *candWord = NULL;
466 candWord = FcitxCandidateWordGetCurrentWindow(candList);
467 if (candWord->owner == table) {
468 TABLECANDWORD* tableCandWord = candWord->priv;
469 lastFirstCandType = tableCandWord->flag;
470 INPUT_RETURN_VALUE ret = _TableGetCandWord(table, tableCandWord, false);
471 if (ret & IRV_FLAG_PENDING_COMMIT_STRING)
472 strLastFirstCand = output_str;
473 }
474 }
475
476 retVal = TableGetCandWords(table);
477 int key = FcitxInputStateGetRawInputBuffer(input)[0];
478 if (!table->bIgnorePunc
479 || (table->bIgnorePunc
480 && table->ignorePuncList
481 && (!table->ignorePuncList[0] || strchr(table->ignorePuncList, key)))) {
482 FcitxPuncGetPunc2(instance, &key, &strTemp, NULL);
483 }
484 if (IsEndKey(table, sym)) {
485 if (raw_size == 1)
486 return IRV_TO_PROCESS;
487
488 if (FcitxCandidateWordPageCount(candList) == 0) {
489 FcitxInputStateSetRawInputBufferSize(input, 0);
490 return IRV_CLEAN;
491 }
492
493 if (FcitxCandidateWordGetCurrentWindowSize(candList) == 1) {
494 retVal = FcitxCandidateWordChooseByIndex(candList, 0);
495 return retVal;
496 }
497
498 return IRV_DISPLAY_CANDWORDS;
499 } else if (table->bUseAutoSend
500 && table->iTableAutoSendToClientWhenNone
501 && (!(retVal & IRV_FLAG_PENDING_COMMIT_STRING))
502 && (raw_size >= (table->iTableAutoSendToClientWhenNone + 1))
503 && TableCheckNoMatch(table, FcitxInputStateGetRawInputBuffer(input))) {
504 if (strLastFirstCand && (lastFirstCandType != CT_AUTOPHRASE)) {
505 FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance), strLastFirstCand);
506 } else if (table->bSendRawPreedit) {
507 strCodeInput[raw_size - 1] = '\0';
508 FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance), strCodeInput);
509 }
510 retVal = IRV_DISPLAY_CANDWORDS;
511 FcitxInputStateSetRawInputBufferSize(input, 1);
512 strCodeInput[0] = sym;
513 strCodeInput[1] = '\0';
514 } else if ((raw_size == 1) && strTemp &&
515 FcitxCandidateWordPageCount(candList) == 0) {
516 /**
517 * 如果第一个字母是标点,并且没有候选字/词
518 * 则当做标点处理──适用于二笔这样的输入
519 **/
520 FcitxInstanceCleanInputWindow(instance);
521 FcitxInputStateGetRawInputBuffer(input)[0] = '\0';
522 FcitxInputStateSetRawInputBufferSize(input, 0);
523 TableResetStatus(table);
524 return IRV_TO_PROCESS;
525 }
526 }
527 } else {
528 if (table->bUseAutoSend && table->iTableAutoSendToClient) {
529 retVal = IRV_DISPLAY_CANDWORDS;
530 if (FcitxCandidateWordPageCount(candList)) {
531 FcitxCandidateWord* candWord = FcitxCandidateWordGetCurrentWindow(candList);
532 if (candWord->owner == table) {
533 TABLECANDWORD* tableCandWord = candWord->priv;
534 if (tableCandWord->flag != CT_AUTOPHRASE) {
535 INPUT_RETURN_VALUE ret = TableGetCandWord(table, candWord);
536 if (ret & IRV_FLAG_PENDING_COMMIT_STRING) {
537 FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance), output_str);
538 }
539 }
540 }
541 } else if (table->bSendRawPreedit) {
542 FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance), strCodeInput);
543 }
544
545 FcitxInputStateSetRawInputBufferSize(input, 1);
546 strCodeInput[0] = sym;
547 strCodeInput[1] = '\0';
548 FcitxInputStateSetIsInRemind(input, false);
549
550 } else
551 retVal = IRV_DO_NOTHING;
552 }
553 }
554 }
555 } else {
556 FcitxMessages *msg_up = FcitxInputStateGetAuxUp(input);
557 FcitxMessages *msg_down = FcitxInputStateGetAuxDown(input);
558 if (tbl->bIsTableAddPhrase) {
559 if (FcitxHotkeyIsHotKey(sym, state, FCITX_LEFT)) {
560 if (tbl->iTableNewPhraseHZCount < table->tableDict->iHZLastInputCount && tbl->iTableNewPhraseHZCount < PHRASE_MAX_LENGTH) {
561 tbl->iTableNewPhraseHZCount++;
562 TableCreateNewPhrase(table);
563 }
564 } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_RIGHT)) {
565 if (tbl->iTableNewPhraseHZCount > 2) {
566 tbl->iTableNewPhraseHZCount--;
567 TableCreateNewPhrase(table);
568 }
569 } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_ENTER)) {
570 if (strcmp("????", FcitxMessagesGetMessageString(msg_down, 0)))
571 TableInsertPhrase(table->tableDict, FcitxMessagesGetMessageString(msg_down, 1), FcitxMessagesGetMessageString(msg_down, 0));
572 tbl->bIsTableAddPhrase = false;
573 FcitxInputStateSetIsDoInputOnly(input, false);
574 return IRV_CLEAN;
575 } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_ESCAPE)) {
576 tbl->bIsTableAddPhrase = false;
577 FcitxInputStateSetIsDoInputOnly(input, false);
578 return IRV_CLEAN;
579 } else {
580 return IRV_DO_NOTHING;
581 }
582 return IRV_DISPLAY_MESSAGE;
583 }
584 if (FcitxHotkeyIsHotKey(sym, state, tbl->config.hkTableAddPhrase)) {
585 if (!tbl->bIsTableAddPhrase) {
586 if (table->tableDict->iHZLastInputCount < 2 || !table->tableDict->bRule) //词组最少为两个汉字
587 return IRV_DO_NOTHING;
588
589 tbl->bTablePhraseTips = false;
590 tbl->iTableNewPhraseHZCount = 2;
591 tbl->bIsTableAddPhrase = true;
592 FcitxInputStateSetIsDoInputOnly(input, true);
593 FcitxInputStateSetShowCursor(input, false);
594
595 FcitxInstanceCleanInputWindow(instance);
596 FcitxMessagesAddMessageStringsAtLast(msg_up, MSG_TIPS, _("Left/Right to choose selected character, Press Enter to confirm, Press Escape to Cancel"));
597
598 FcitxMessagesAddMessageStringsAtLast(msg_down,
599 MSG_FIRSTCAND, "");
600 FcitxMessagesAddMessageStringsAtLast(msg_down, MSG_CODE, "");
601 TableCreateNewPhrase(table);
602 retVal = IRV_DISPLAY_MESSAGE;
603 } else
604 retVal = IRV_TO_PROCESS;
605
606 return retVal;
607 } else if (FcitxHotkeyIsHotKey(sym, state, tbl->config.hkLookupPinyin) && tbl->pyaddon) {
608 char strPY[128];
609
610 //如果刚刚输入的是个词组,刚不查拼音
611 if (fcitx_utf8_strlen(output_str) != 1)
612 return IRV_DO_NOTHING;
613
614 FcitxInputStateSetRawInputBufferSize(input, 0);
615
616 FcitxInstanceCleanInputWindow(instance);
617 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input),
618 MSG_INPUT, output_str);
619
620 FcitxMessagesAddMessageStringsAtLast(
621 FcitxInputStateGetAuxDown(input), MSG_CODE, _("Pinyin: "));
622 const int8_t *py_list;
623 if ((py_list = FcitxPinyinEnhanceFindPy(tbl->owner, output_str))
624 && *py_list) {
625 int8_t i;
626 int offset = 0;
627 for (i = 0;i < *py_list && offset + 16 < sizeof(strPY);i++) {
628 int len;
629 const int8_t *py;
630 if (i > 0) {
631 memcpy(strPY + offset, ", ", 2);
632 offset += 2;
633 }
634 py = pinyin_enhance_pylist_get(py_list, i);
635 FcitxPinyinEnhancePyToString(tbl->owner, strPY + offset,
636 py, &len);
637 offset += len;
638 }
639 } else {
640 FcitxPinyinLoadBaseDict(tbl->owner);
641 FcitxPinyinGetPyByHZ(tbl->owner, output_str, strPY);
642 }
643 FcitxMessagesAddMessageStringsAtLast(
644 FcitxInputStateGetAuxDown(input), MSG_TIPS,
645 (strPY[0]) ? strPY : _("Cannot found Pinyin"));
646 FcitxInputStateSetShowCursor(input, false);
647
648 return IRV_DISPLAY_MESSAGE;
649 }
650
651 if (!FcitxInputStateGetRawInputBufferSize(input) && !FcitxInputStateGetIsInRemind(input))
652 return IRV_TO_PROCESS;
653
654 if (FcitxHotkeyIsHotKey(sym, state, FCITX_ESCAPE)) {
655 if (tbl->bIsTableDelPhrase || tbl->bIsTableAdjustOrder || tbl->bIsTableClearFreq) {
656 TableResetStatus(table);
657 FcitxInstanceCleanInputWindowUp(instance);
658 FcitxMessagesAddMessageStringsAtLast(
659 FcitxInputStateGetPreedit(input), MSG_INPUT,
660 FcitxInputStateGetRawInputBuffer(input));
661 FcitxMessagesAddMessageStringsAtLast(
662 FcitxInputStateGetClientPreedit(input),
663 MSG_INPUT | MSG_DONOT_COMMIT_WHEN_UNFOCUS,
664 FcitxInputStateGetRawInputBuffer(input));
665 retVal = IRV_DISPLAY_CANDWORDS;
666 } else
667 return IRV_CLEAN;
668 } else if (FcitxHotkeyCheckChooseKey(sym, state, table->strChoose) >= 0) {
669 int iKey;
670 iKey = FcitxHotkeyCheckChooseKey(sym, state, table->strChoose);
671
672 if (FcitxCandidateWordPageCount(candList) == 0)
673 return IRV_TO_PROCESS;
674
675 if (FcitxCandidateWordGetByIndex(candList, iKey) == NULL)
676 return IRV_DO_NOTHING;
677 else {
678 FcitxCandidateWord* candWord = FcitxCandidateWordGetByIndex(candList, iKey);
679 if (candWord->owner == table && tbl->bIsTableDelPhrase) {
680 TableDelPhraseByIndex(table, candWord->priv);
681 tbl->bIsTableDelPhrase = false;
682 FcitxInputStateSetIsDoInputOnly(input, false);
683 retVal = IRV_DISPLAY_CANDWORDS;
684 } else if (candWord->owner == table && tbl->bIsTableAdjustOrder) {
685 TableAdjustOrderByIndex(table, candWord->priv);
686 tbl->bIsTableAdjustOrder = false;
687 FcitxInputStateSetIsDoInputOnly(input, false);
688 retVal = IRV_DISPLAY_CANDWORDS;
689 } else if (candWord->owner == table && tbl->bIsTableClearFreq) {
690 TableClearFreqByIndex(table, candWord->priv);
691 tbl->bIsTableClearFreq = false;
692 FcitxInputStateSetIsDoInputOnly(input, false);
693 retVal = IRV_DISPLAY_CANDWORDS;
694 }
695 else
696 return IRV_TO_PROCESS;
697 }
698 } else if (!tbl->bIsTableDelPhrase && !tbl->bIsTableAdjustOrder && !tbl->bIsTableClearFreq) {
699 if (FcitxHotkeyIsHotKey(sym, state, tbl->config.hkTableAdjustOrder)) {
700 if (FcitxCandidateWordGetListSize(candList) < 2 || FcitxInputStateGetIsInRemind(input))
701 return IRV_DO_NOTHING;
702
703 tbl->bIsTableAdjustOrder = true;
704 FcitxInstanceCleanInputWindowUp(instance);
705 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input), MSG_TIPS, _("Choose the phrase to be put in the front, Press Escape to Cancel"));
706 retVal = IRV_DISPLAY_MESSAGE;
707 } else if (FcitxHotkeyIsHotKey(sym, state, tbl->config.hkTableDelPhrase)) {
708 if (!FcitxCandidateWordPageCount(candList) || FcitxInputStateGetIsInRemind(input))
709 return IRV_DO_NOTHING;
710
711 tbl->bIsTableDelPhrase = true;
712 FcitxInstanceCleanInputWindowUp(instance);
713 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input), MSG_TIPS, _("Choose the phrase to be deleted, Press Escape to Cancel"));
714 retVal = IRV_DISPLAY_MESSAGE;
715 } else if (FcitxHotkeyIsHotKey(sym, state, tbl->config.hkTableClearFreq)) {
716 if (!FcitxCandidateWordPageCount(candList) || FcitxInputStateGetIsInRemind(input))
717 return IRV_DO_NOTHING;
718
719 tbl->bIsTableClearFreq = true;
720 FcitxInstanceCleanInputWindowUp(instance);
721 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input), MSG_TIPS, _("Choose the phrase to clear typing history, Press Escape to Cancel"));
722 retVal = IRV_DISPLAY_MESSAGE;
723 } else if (FcitxHotkeyIsHotKey(sym, state, FCITX_BACKSPACE)) {
724 if (!FcitxInputStateGetRawInputBufferSize(input)) {
725 FcitxInputStateSetIsInRemind(input, false);
726 return IRV_DONOT_PROCESS_CLEAN;
727 }
728
729 FcitxInputStateSetRawInputBufferSize(input, FcitxInputStateGetRawInputBufferSize(input) - 1);
730 strCodeInput[FcitxInputStateGetRawInputBufferSize(input)] = '\0';
731
732 if (FcitxInputStateGetRawInputBufferSize(input) == 1 && strCodeInput[0] == table->cPinyin && table->bUsePY) {
733 FcitxCandidateWordReset(candList);
734 retVal = IRV_DISPLAY_LAST;
735 } else if (FcitxInputStateGetRawInputBufferSize(input))
736 retVal = IRV_DISPLAY_CANDWORDS;
737 else
738 retVal = IRV_CLEAN;
739 } else if (FcitxHotkeyIsHotKey(sym, state, table->hkCommitKey)) {
740 if (FcitxInputStateGetRawInputBufferSize(input) == 1 && strCodeInput[0] == table->cPinyin && table->bUsePY)
741 retVal = IRV_COMMIT_STRING;
742 else {
743 if (FcitxCandidateWordPageCount(candList) == 0 && table->bCommitKeyCommitWhenNoMatch) {
744 FcitxInstanceCommitString(instance, FcitxInstanceGetCurrentIC(instance), FcitxInputStateGetRawInputBuffer(input));
745 FcitxInputStateSetRawInputBufferSize(input, 0);
746 FcitxInputStateGetRawInputBuffer(input)[0] = '\0';
747 FcitxInputStateSetIsInRemind(input, false);
748 FcitxInstanceCleanInputWindow(instance);
749 FcitxUIUpdateInputWindow(instance);
750 retVal = IRV_DO_NOTHING;
751 }
752 else {
753 retVal = FcitxCandidateWordChooseByIndex(candList, 0);
754 if (retVal == IRV_TO_PROCESS)
755 retVal = IRV_DO_NOTHING;
756 }
757 }
758 } else {
759 return IRV_TO_PROCESS;
760 }
761 }
762 }
763
764 if (!FcitxInputStateGetIsInRemind(input)) {
765 if (tbl->bIsTableDelPhrase || tbl->bIsTableAdjustOrder || tbl->bIsTableClearFreq)
766 FcitxInputStateSetIsDoInputOnly(input, true);
767 }
768
769 if (tbl->bIsTableDelPhrase || tbl->bIsTableAdjustOrder || tbl->bIsTableClearFreq || FcitxInputStateGetIsInRemind(input))
770 FcitxInputStateSetShowCursor(input, false);
771 else {
772 FcitxInputStateSetShowCursor(input, true);
773 FcitxInputStateSetCursorPos(input, strlen(FcitxInputStateGetRawInputBuffer(input)));
774 FcitxInputStateSetClientCursorPos(input, 0);
775 }
776
777 return retVal;
778 }
779
TableGetCandWord(void * arg,FcitxCandidateWord * candWord)780 INPUT_RETURN_VALUE TableGetCandWord(void* arg, FcitxCandidateWord* candWord)
781 {
782 TableMetaData* table = (TableMetaData*) arg;
783 FcitxTableState *tbl = table->owner;
784 FcitxInputState* input = FcitxInstanceGetInputState(tbl->owner);
785 TABLECANDWORD* tableCandWord = candWord->priv;
786
787 INPUT_RETURN_VALUE retVal = _TableGetCandWord(table, tableCandWord, true);
788 if (retVal & IRV_FLAG_PENDING_COMMIT_STRING) {
789 if (table->bAutoPhrase && (fcitx_utf8_strlen(FcitxInputStateGetOutputString(input)) == 1 || (fcitx_utf8_strlen(FcitxInputStateGetOutputString(input)) > 1 && table->bAutoPhrasePhrase)))
790 UpdateHZLastInput(table, FcitxInputStateGetOutputString(input));
791
792 if (tbl->pCurCandRecord)
793 TableUpdateHitFrequency(table, tbl->pCurCandRecord);
794 }
795
796 return retVal;
797 }
798
799 /*
800 * 第二个参数表示是否进入联想模式,实现自动上屏功能时,不能使用联想模式
801 */
_TableGetCandWord(TableMetaData * table,TABLECANDWORD * tableCandWord,boolean _bRemind)802 INPUT_RETURN_VALUE _TableGetCandWord(TableMetaData* table, TABLECANDWORD* tableCandWord, boolean _bRemind)
803 {
804 char *pCandWord = NULL;
805 FcitxTableState* tbl = table->owner;
806 FcitxInstance *instance = tbl->owner;
807 FcitxInputState *input = FcitxInstanceGetInputState(instance);
808 FcitxProfile *profile = FcitxInstanceGetProfile(instance);
809
810 if (tableCandWord->flag == CT_FH)
811 return TableGetFHCandWord(table, tableCandWord);
812
813 FcitxInputStateSetIsInRemind(input, false);
814
815 if (tableCandWord->flag == CT_NORMAL)
816 tbl->pCurCandRecord = tableCandWord->candWord.record;
817 else
818 tbl->pCurCandRecord = (RECORD *)NULL;
819
820 if (table->tableDict->iTableChanged >= TABLE_AUTO_SAVE_AFTER)
821 SaveTableDict(table);
822
823 switch (tableCandWord->flag) {
824 case CT_NORMAL:
825 pCandWord = tableCandWord->candWord.record->strHZ;
826 break;
827 case CT_AUTOPHRASE:
828 if (table->iSaveAutoPhraseAfter) {
829 /* 当_bRemind为false时,不应该计算自动组词的频度,因此此时实际并没有选择这个词 */
830 if (table->iSaveAutoPhraseAfter >= tableCandWord->candWord.autoPhrase->iSelected && _bRemind)
831 tableCandWord->candWord.autoPhrase->iSelected++;
832 if (table->iSaveAutoPhraseAfter == tableCandWord->candWord.autoPhrase->iSelected) //保存自动词组
833 TableInsertPhrase(table->tableDict, tableCandWord->candWord.autoPhrase->strCode, tableCandWord->candWord.autoPhrase->strHZ);
834 }
835 pCandWord = tableCandWord->candWord.autoPhrase->strHZ;
836 break;
837 case CT_FH:
838 pCandWord = table->tableDict->fh[tableCandWord->candWord.iFHIndex].strFH;
839 break;
840 case CT_REMIND: {
841 strcpy(tbl->strTableRemindSource, tableCandWord->candWord.record->strHZ + strlen(tbl->strTableRemindSource));
842 strcpy(FcitxInputStateGetOutputString(input), tbl->strTableRemindSource);
843 INPUT_RETURN_VALUE retVal = TableGetRemindCandWords(table);
844 if (retVal == IRV_DISPLAY_CANDWORDS)
845 return IRV_COMMIT_STRING_REMIND;
846 else
847 return IRV_COMMIT_STRING;
848 }
849 }
850
851 if (profile->bUseRemind && _bRemind) {
852 strcpy(tbl->strTableRemindSource, pCandWord);
853 strcpy(FcitxInputStateGetOutputString(input), pCandWord);
854 INPUT_RETURN_VALUE retVal = TableGetRemindCandWords(table);
855 if (retVal == IRV_DISPLAY_CANDWORDS)
856 return IRV_COMMIT_STRING_REMIND;
857 } else {
858 if (table->bPromptTableCode) {
859 RECORD *temp;
860
861 FcitxInstanceCleanInputWindow(instance);
862 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input), MSG_INPUT, FcitxInputStateGetRawInputBuffer(input));
863
864 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxDown(input), MSG_TIPS, pCandWord);
865 temp = table->tableDict->tableSingleHZ[CalHZIndex(pCandWord)];
866 if (temp) {
867 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxDown(input), MSG_CODE, temp->strCode);
868 }
869 } else {
870 FcitxInstanceCleanInputWindow(instance);
871 }
872 }
873
874 if (fcitx_utf8_strlen(pCandWord) == 1)
875 FcitxInputStateSetLastIsSingleChar(input, 1);
876 else
877 FcitxInputStateSetLastIsSingleChar(input, 0);
878
879 strcpy(FcitxInputStateGetOutputString(input), pCandWord);
880 return IRV_COMMIT_STRING;
881 }
882
TableGetPinyinCandWords(TableMetaData * table)883 INPUT_RETURN_VALUE TableGetPinyinCandWords(TableMetaData* table)
884 {
885 FcitxTableState* tbl = table->owner;
886 FcitxInstance *instance = tbl->owner;
887
888 if (!tbl->pyaddon)
889 return IRV_DISPLAY_CANDWORDS;
890
891 FcitxInputState *input = FcitxInstanceGetInputState(instance);
892
893 strcpy(FcitxPinyinGetFindString(tbl->owner),
894 FcitxInputStateGetRawInputBuffer(input) + 1);
895
896 FcitxKeySym dummy1 = FcitxKey_None;
897 unsigned int dummy2 = 0;
898 FcitxPinyinDoInput(tbl->owner, &dummy1, &dummy2);
899 FcitxPinyinGetCandwords(tbl->owner);
900
901 FcitxInputStateGetRawInputBuffer(input)[0] = table->cPinyin;
902 FcitxInputStateGetRawInputBuffer(input)[1] = '\0';
903
904 strcat(FcitxInputStateGetRawInputBuffer(input),
905 FcitxPinyinGetFindString(tbl->owner));
906 FcitxInputStateSetRawInputBufferSize(input, strlen(FcitxInputStateGetRawInputBuffer(input)));
907
908 FcitxInstanceCleanInputWindowUp(instance);
909 FcitxMessagesAddMessageStringsAtLast(
910 FcitxInputStateGetPreedit(input), MSG_INPUT,
911 FcitxInputStateGetRawInputBuffer(input));
912 FcitxMessagesAddMessageStringsAtLast(
913 FcitxInputStateGetClientPreedit(input),
914 MSG_INPUT | MSG_DONOT_COMMIT_WHEN_UNFOCUS,
915 FcitxInputStateGetRawInputBuffer(input));
916 FcitxInputStateSetCursorPos(input, FcitxInputStateGetRawInputBufferSize(input));
917 FcitxInputStateSetClientCursorPos(input, 0);
918
919 //下面将拼音的候选字表转换为码表输入法的样式
920 FcitxCandidateWord* candWord;
921 for (candWord = FcitxCandidateWordGetFirst(FcitxInputStateGetCandidateList(input));
922 candWord != NULL;
923 candWord = FcitxCandidateWordGetNext(FcitxInputStateGetCandidateList(input), candWord)) {
924 char* pstr;
925 if (fcitx_utf8_strlen(candWord->strWord) == 1) {
926 RECORD* recTemp = table->tableDict->tableSingleHZ[CalHZIndex(candWord->strWord)];
927 if (!recTemp)
928 pstr = (char *) NULL;
929 else
930 pstr = recTemp->strCode;
931
932 } else
933 pstr = (char *) NULL;
934
935 if (pstr) {
936 candWord->strExtra = strdup(pstr);
937 candWord->extraType = MSG_CODE;
938 }
939 tbl->pygetcandword = candWord->callback;
940 candWord->callback = Table_PYGetCandWord;
941 candWord->owner = table;
942 }
943
944 return IRV_DISPLAY_CANDWORDS;
945 }
946
TableGetCandWords(void * arg)947 INPUT_RETURN_VALUE TableGetCandWords(void* arg)
948 {
949 TableMetaData* table = (TableMetaData*) arg;
950 FcitxTableState *tbl = table->owner;
951 int i;
952 RECORD *recTemp;
953 FcitxInstance *instance = tbl->owner;
954 FcitxInputState *input = FcitxInstanceGetInputState(instance);
955 FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
956 FcitxCandidateWordSetLayoutHint(candList, table->layoutHint);
957
958 if (FcitxInputStateGetRawInputBuffer(input)[0] == '\0')
959 return IRV_TO_PROCESS;
960
961 if (FcitxInputStateGetIsInRemind(input))
962 return TableGetRemindCandWords(table);
963
964 if (!strcmp(FcitxInputStateGetRawInputBuffer(input), table->strSymbol))
965 return TableGetFHCandWords(table);
966
967 if (FcitxInputStateGetRawInputBuffer(input)[0] == table->cPinyin && table->bUsePY && tbl->pyaddon)
968 return TableGetPinyinCandWords(table);
969
970 if (TableFindFirstMatchCode(table, FcitxInputStateGetRawInputBuffer(input), table->bTableExactMatch, true) == -1 && !table->tableDict->iAutoPhrase) {
971 if (FcitxInputStateGetRawInputBufferSize(input)) {
972 FcitxMessagesSetMessageCount(FcitxInputStateGetPreedit(input), 0);
973 FcitxMessagesSetMessageCount(FcitxInputStateGetClientPreedit(input), 0);
974 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetPreedit(input), MSG_INPUT, FcitxInputStateGetRawInputBuffer(input));
975 FcitxMessageType type = MSG_INPUT;
976 if (!table->bSendRawPreedit)
977 type |= MSG_DONOT_COMMIT_WHEN_UNFOCUS;
978 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetClientPreedit(input), type, FcitxInputStateGetRawInputBuffer(input));
979 FcitxInputStateSetCursorPos(input, strlen(FcitxInputStateGetRawInputBuffer(input)));
980 FcitxInputStateSetClientCursorPos(input, 0);
981 }
982 //Not Found
983 return IRV_DISPLAY_CANDWORDS;
984 }
985
986 TableCandWordSortContext context;
987 context.order = table->tableOrder;
988 context.simpleLevel = table->iSimpleLevel;
989 UT_array candTemp;
990 utarray_init(&candTemp, fcitx_ptr_icd);
991
992 while (table->tableDict->currentRecord && table->tableDict->currentRecord != table->tableDict->recordHead) {
993 if (table->tableDict->currentRecord->type != RECORDTYPE_CONSTRUCT &&
994 table->tableDict->currentRecord->type != RECORDTYPE_PROMPT &&
995 !TableCompareCode(table, FcitxInputStateGetRawInputBuffer(input), table->tableDict->currentRecord->strCode, table->bTableExactMatch)) {
996 TABLECANDWORD* tableCandWord = fcitx_utils_malloc0(sizeof(TABLECANDWORD));
997 TableAddCandWord(table->tableDict->currentRecord, tableCandWord);
998 utarray_push_back(&candTemp, &tableCandWord);
999 }
1000 table->tableDict->currentRecord = table->tableDict->currentRecord->next;
1001 }
1002
1003 /* seems AD_NO will go back to n^2, really effect performance */
1004 if (table->tableOrder != AD_NO)
1005 utarray_msort_r(&candTemp, TableCandCmp, &context);
1006
1007 TABLECANDWORD** pcand = NULL;
1008 for (pcand = (TABLECANDWORD**) utarray_front(&candTemp);
1009 pcand != NULL;
1010 pcand = (TABLECANDWORD**) utarray_next(&candTemp, pcand)) {
1011 TABLECANDWORD* tableCandWord = *pcand;
1012 FcitxCandidateWord candWord;
1013 candWord.callback = TableGetCandWord;
1014 candWord.owner = table;
1015 candWord.priv = tableCandWord;
1016 candWord.strWord = strdup(tableCandWord->candWord.record->strHZ);
1017 candWord.strExtra = NULL;
1018 candWord.wordType = MSG_OTHER;
1019
1020 const char* pstr = NULL;
1021 if ((tableCandWord->flag == CT_NORMAL) && (tableCandWord->candWord.record->type == RECORDTYPE_PINYIN)) {
1022 if (fcitx_utf8_strlen(tableCandWord->candWord.record->strHZ) == 1) {
1023 recTemp = table->tableDict->tableSingleHZ[CalHZIndex(tableCandWord->candWord.record->strHZ)];
1024 if (!recTemp)
1025 pstr = (char *) NULL;
1026 else
1027 pstr = recTemp->strCode;
1028 } else
1029 pstr = (char *) NULL;
1030 } else if (HasMatchingKey(table, FcitxInputStateGetRawInputBuffer(input)))
1031 pstr = (tableCandWord->flag == CT_NORMAL) ? tableCandWord->candWord.record->strCode : tableCandWord->candWord.autoPhrase->strCode;
1032 else
1033 pstr = ((tableCandWord->flag == CT_NORMAL) ? tableCandWord->candWord.record->strCode : tableCandWord->candWord.autoPhrase->strCode) + FcitxInputStateGetRawInputBufferSize(input);
1034
1035 if (pstr) {
1036 if (table->customPrompt) {
1037 size_t codelen = strlen(pstr);
1038 int i = 0;
1039 int totallen = 0;
1040 for (i = 0; i < codelen; i ++) {
1041 RECORD* rec = table->tableDict->promptCode[(uint8_t) pstr[i]];
1042 if (rec) {
1043 totallen += strlen(rec->strHZ);
1044 } else
1045 totallen += 1;
1046 }
1047
1048 candWord.strExtra = fcitx_utils_malloc0(sizeof(char) * (totallen + 1 + 3));
1049 if (codelen)
1050 strcpy(candWord.strExtra, "\xef\xbd\x9e");
1051 for (i = 0; i < codelen; i ++) {
1052 RECORD* rec = table->tableDict->promptCode[(uint8_t) pstr[i]];
1053 if (rec) {
1054 strcat(candWord.strExtra, rec->strHZ);
1055 } else {
1056 char temp[2] = {pstr[i], '\0'};
1057 strcat(candWord.strExtra, temp);
1058 }
1059 }
1060 }
1061 else {
1062 candWord.strExtra = strdup(pstr);
1063 }
1064 candWord.extraType = MSG_CODE;
1065 }
1066
1067 FcitxCandidateWordAppend(candList, &candWord);
1068 }
1069 utarray_clear(&candTemp);
1070
1071 if (table->tableDict->bRule && table->bAutoPhrase && FcitxInputStateGetRawInputBufferSize(input) == table->tableDict->iCodeLength) {
1072 for (i = table->tableDict->iAutoPhrase - 1; i >= 0; i--) {
1073 if (!TableCompareCode(table, FcitxInputStateGetRawInputBuffer(input), table->tableDict->autoPhrase[i].strCode, table->bTableExactMatch)) {
1074 if (TableHasPhrase(table->tableDict, table->tableDict->autoPhrase[i].strCode, table->tableDict->autoPhrase[i].strHZ)) {
1075 TABLECANDWORD* tableCandWord = fcitx_utils_malloc0(sizeof(TABLECANDWORD));
1076 TableAddAutoCandWord(table, i, tableCandWord);
1077 utarray_push_back(&candTemp, &tableCandWord);
1078 }
1079 }
1080 }
1081 }
1082
1083 for (pcand = (TABLECANDWORD**) utarray_front(&candTemp);
1084 pcand != NULL;
1085 pcand = (TABLECANDWORD**) utarray_next(&candTemp, pcand)) {
1086 TABLECANDWORD* tableCandWord = *pcand;
1087 FcitxCandidateWord candWord;
1088 candWord.callback = TableGetCandWord;
1089 candWord.owner = table;
1090 candWord.priv = tableCandWord;
1091 candWord.strWord = strdup(tableCandWord->candWord.autoPhrase->strHZ);
1092 candWord.strExtra = NULL;
1093 candWord.wordType = MSG_USERPHR;
1094
1095 FcitxCandidateWordAppend(candList, &candWord);
1096 }
1097
1098 utarray_done(&candTemp);
1099
1100 INPUT_RETURN_VALUE retVal = IRV_DISPLAY_CANDWORDS;
1101
1102 if (table->bUseAutoSend && table->iTableAutoSendToClient && (FcitxInputStateGetRawInputBufferSize(input) >= table->iTableAutoSendToClient)) {
1103 if (FcitxCandidateWordGetCurrentWindowSize(candList) == 1) { //如果只有一个候选词,则送到客户程序中
1104 FcitxCandidateWord* candWord = FcitxCandidateWordGetCurrentWindow(candList);
1105 if (candWord->owner == table) {
1106 TABLECANDWORD* tableCandWord = candWord->priv;
1107 if (tableCandWord->flag != CT_AUTOPHRASE || (tableCandWord->flag == CT_AUTOPHRASE && !table->iSaveAutoPhraseAfter))
1108 if (!(tableCandWord->flag == CT_NORMAL && tableCandWord->candWord.record->type == RECORDTYPE_PINYIN))
1109 retVal = FcitxCandidateWordChooseByIndex(candList, 0);
1110 }
1111 }
1112 }
1113
1114 if (FcitxInputStateGetRawInputBufferSize(input)) {
1115 FcitxMessagesSetMessageCount(FcitxInputStateGetPreedit(input), 0);
1116 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetPreedit(input), MSG_INPUT, FcitxInputStateGetRawInputBuffer(input));
1117 FcitxInputStateSetCursorPos(input, strlen(FcitxInputStateGetRawInputBuffer(input)));
1118 FcitxCandidateWord* candWord = NULL;
1119 if (table->bFirstCandidateAsPreedit && (candWord = FcitxCandidateWordGetFirst(candList))) {
1120 FcitxMessagesSetMessageCount(FcitxInputStateGetClientPreedit(input), 0);
1121 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetClientPreedit(input), MSG_INPUT, candWord->strWord);
1122 FcitxInputStateSetClientCursorPos(input, 0);
1123 }
1124 else {
1125 FcitxMessagesSetMessageCount(FcitxInputStateGetClientPreedit(input), 0);
1126 FcitxMessageType type = MSG_INPUT;
1127 if (!table->bSendRawPreedit)
1128 type |= MSG_DONOT_COMMIT_WHEN_UNFOCUS;
1129 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetClientPreedit(input), type, FcitxInputStateGetRawInputBuffer(input));
1130 FcitxInputStateSetClientCursorPos(input, 0);
1131 }
1132 }
1133
1134 return retVal;
1135 }
1136
TableAddAutoCandWord(TableMetaData * table,short which,TABLECANDWORD * tableCandWord)1137 void TableAddAutoCandWord(TableMetaData* table, short which, TABLECANDWORD* tableCandWord)
1138 {
1139 tableCandWord->flag = CT_AUTOPHRASE;
1140 tableCandWord->candWord.autoPhrase = &table->tableDict->autoPhrase[which];
1141 }
1142
TableAddCandWord(RECORD * record,TABLECANDWORD * tableCandWord)1143 void TableAddCandWord(RECORD * record, TABLECANDWORD* tableCandWord)
1144 {
1145 tableCandWord->flag = CT_NORMAL;
1146 tableCandWord->candWord.record = record;
1147 }
1148
TableClearFreqByIndex(TableMetaData * table,TABLECANDWORD * tableCandWord)1149 void TableClearFreqByIndex(TableMetaData* table, TABLECANDWORD* tableCandWord)
1150 {
1151 RECORD *recTemp;
1152
1153 recTemp = tableCandWord->candWord.record;
1154 recTemp->iHit = 0;
1155
1156 table->tableDict->iTableChanged++;
1157 }
1158
1159 /*
1160 * 根据序号调整词组顺序,序号从1开始
1161 * 将指定的字/词调整到同样编码的最前面
1162 */
TableAdjustOrderByIndex(TableMetaData * table,TABLECANDWORD * tableCandWord)1163 void TableAdjustOrderByIndex(TableMetaData* table, TABLECANDWORD* tableCandWord)
1164 {
1165 RECORD *recTemp;
1166 int iTemp;
1167
1168 recTemp = tableCandWord->candWord.record;
1169 while (!strcmp(recTemp->strCode, recTemp->prev->strCode))
1170 recTemp = recTemp->prev;
1171 if (recTemp == tableCandWord->candWord.record) //说明已经是第一个
1172 return;
1173
1174 //将指定的字/词放到recTemp前
1175 tableCandWord->candWord.record->prev->next = tableCandWord->candWord.record->next;
1176 tableCandWord->candWord.record->next->prev = tableCandWord->candWord.record->prev;
1177 recTemp->prev->next = tableCandWord->candWord.record;
1178 tableCandWord->candWord.record->prev = recTemp->prev;
1179 recTemp->prev = tableCandWord->candWord.record;
1180 tableCandWord->candWord.record->next = recTemp;
1181
1182 table->tableDict->iTableChanged++;
1183
1184 //需要的话,更新索引
1185 if (tableCandWord->candWord.record->strCode[1] == '\0') {
1186 size_t tmp_len = strlen(table->tableDict->strInputCode);
1187 for (iTemp = 0; iTemp < tmp_len; iTemp++) {
1188 if (table->tableDict->recordIndex[iTemp].cCode ==
1189 tableCandWord->candWord.record->strCode[0]) {
1190 table->tableDict->recordIndex[iTemp].record = tableCandWord->candWord.record;
1191 break;
1192 }
1193 }
1194 }
1195 }
1196
1197 /*
1198 * 根据序号删除词组,序号从1开始
1199 */
TableDelPhraseByIndex(TableMetaData * table,TABLECANDWORD * tableCandWord)1200 void TableDelPhraseByIndex(TableMetaData* table, TABLECANDWORD* tableCandWord)
1201 {
1202 if (tableCandWord->flag != CT_NORMAL)
1203 return;
1204
1205 if (fcitx_utf8_strlen(tableCandWord->candWord.record->strHZ) <= 1)
1206 return;
1207
1208 TableDelPhrase(table->tableDict, tableCandWord->candWord.record);
1209 }
1210
TableCreateNewPhrase(TableMetaData * table)1211 void TableCreateNewPhrase(TableMetaData* table)
1212 {
1213 int i;
1214 FcitxTableState* tbl = table->owner;
1215 FcitxInstance *instance = tbl->owner;
1216 FcitxInputState* input = FcitxInstanceGetInputState(instance);
1217 FcitxMessages *msg_down = FcitxInputStateGetAuxDown(input);
1218
1219 FcitxMessagesSetMessageTextStrings(msg_down, 0, "");
1220 for (i = tbl->iTableNewPhraseHZCount; i > 0; i--)
1221 FcitxMessagesMessageConcat(msg_down, 0, table->tableDict->hzLastInput[table->tableDict->iHZLastInputCount - i].strHZ);
1222
1223 boolean bCanntFindCode = TableCreatePhraseCode(table->tableDict, FcitxMessagesGetMessageString(msg_down, 0));
1224
1225 if (!bCanntFindCode) {
1226 FcitxMessagesSetMessageCount(msg_down, 2);
1227 FcitxMessagesSetMessageTextStrings(msg_down, 1,
1228 table->tableDict->strNewPhraseCode);
1229 } else {
1230 FcitxMessagesSetMessageCount(msg_down, 1);
1231 FcitxMessagesSetMessageTextStrings(msg_down, 0, "????");
1232 }
1233
1234 }
1235
1236 /*
1237 * 获取联想候选字列表
1238 */
TableGetRemindCandWords(TableMetaData * table)1239 INPUT_RETURN_VALUE TableGetRemindCandWords(TableMetaData* table)
1240 {
1241 FcitxTableState* tbl = table->owner;
1242 int iLength;
1243 RECORD *tableRemind = NULL;
1244 FcitxGlobalConfig *config = FcitxInstanceGetGlobalConfig(tbl->owner);
1245 FcitxInstance *instance = tbl->owner;
1246 FcitxInputState *input = FcitxInstanceGetInputState(instance);
1247 boolean bDisablePagingInRemind = config->bDisablePagingInRemind;
1248 FcitxCandidateWordList *cand_list = FcitxInputStateGetCandidateList(input);
1249
1250 if (!tbl->strTableRemindSource[0])
1251 return IRV_TO_PROCESS;
1252
1253 FcitxInputStateGetRawInputBuffer(input)[0] = '\0';
1254 FcitxInputStateSetRawInputBufferSize(input, 0);
1255 FcitxCandidateWordReset(cand_list);
1256
1257 iLength = fcitx_utf8_strlen(tbl->strTableRemindSource);
1258 tableRemind = table->tableDict->recordHead->next;
1259
1260 while (tableRemind != table->tableDict->recordHead) {
1261 if (bDisablePagingInRemind &&
1262 FcitxCandidateWordGetListSize(cand_list) >=
1263 FcitxCandidateWordGetPageSize(cand_list))
1264 break;
1265
1266 if (((iLength + 1) == fcitx_utf8_strlen(tableRemind->strHZ))) {
1267 if (!fcitx_utf8_strncmp(tableRemind->strHZ,
1268 tbl->strTableRemindSource, iLength) &&
1269 fcitx_utf8_get_nth_char(tableRemind->strHZ, iLength)) {
1270 TABLECANDWORD *tableCandWord = fcitx_utils_new(TABLECANDWORD);
1271 TableAddRemindCandWord(tableRemind, tableCandWord);
1272 FcitxCandidateWord candWord;
1273 candWord.callback = TableGetCandWord;
1274 candWord.owner = table;
1275 candWord.priv = tableCandWord;
1276 candWord.strExtra = NULL;
1277 candWord.strWord = strdup(tableCandWord->candWord.record->strHZ + strlen(tbl->strTableRemindSource));
1278 candWord.wordType = MSG_OTHER;
1279 FcitxCandidateWordAppend(cand_list, &candWord);
1280 }
1281 }
1282 tableRemind = tableRemind->next;
1283 }
1284
1285 FcitxInstanceCleanInputWindowUp(instance);
1286 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input),
1287 MSG_TIPS, _("Remind:"));
1288 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetAuxUp(input),
1289 MSG_INPUT, tbl->strTableRemindSource);
1290 int count = FcitxCandidateWordPageCount(cand_list);
1291 FcitxInputStateSetIsInRemind(input, count);
1292 if (count) {
1293 return IRV_DISPLAY_CANDWORDS;
1294 } else {
1295 return IRV_CLEAN;
1296 }
1297 }
1298
TableAddRemindCandWord(RECORD * record,TABLECANDWORD * tableCandWord)1299 void TableAddRemindCandWord(RECORD * record, TABLECANDWORD* tableCandWord)
1300 {
1301 tableCandWord->flag = CT_REMIND;
1302 tableCandWord->candWord.record = record;
1303 }
1304
TableGetRemindCandWord(void * arg,TABLECANDWORD * tableCandWord)1305 INPUT_RETURN_VALUE TableGetRemindCandWord(void* arg, TABLECANDWORD* tableCandWord)
1306 {
1307 TableMetaData* table = (TableMetaData*) arg;
1308 FcitxTableState* tbl = table->owner;
1309 FcitxInstance *instance = tbl->owner;
1310 FcitxInputState *input = FcitxInstanceGetInputState(instance);
1311
1312 tableCandWord->candWord.record->iHit++;
1313 strcpy(tbl->strTableRemindSource, tableCandWord->candWord.record->strHZ + strlen(tbl->strTableRemindSource));
1314 TableGetRemindCandWords(table);
1315
1316 strcpy(FcitxInputStateGetOutputString(input), tbl->strTableRemindSource);
1317 return IRV_COMMIT_STRING_REMIND;
1318 }
1319
TableGetFHCandWords(TableMetaData * table)1320 INPUT_RETURN_VALUE TableGetFHCandWords(TableMetaData* table)
1321 {
1322 int i;
1323 FcitxTableState* tbl = table->owner;
1324 FcitxInstance *instance = tbl->owner;
1325 FcitxInputState *input = FcitxInstanceGetInputState(instance);
1326
1327 FcitxInstanceCleanInputWindowUp(instance);
1328 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetPreedit(input), MSG_INPUT, FcitxInputStateGetRawInputBuffer(input));
1329 FcitxMessagesAddMessageStringsAtLast(FcitxInputStateGetClientPreedit(input), MSG_INPUT | MSG_DONOT_COMMIT_WHEN_UNFOCUS, FcitxInputStateGetRawInputBuffer(input));
1330 FcitxInputStateSetCursorPos(input, FcitxInputStateGetRawInputBufferSize(input));
1331 FcitxInputStateSetClientCursorPos(input, 0);
1332
1333 if (!table->tableDict->iFH)
1334 return IRV_DISPLAY_MESSAGE;
1335
1336 for (i = 0; i < table->tableDict->iFH; i++) {
1337 TABLECANDWORD* tableCandWord = fcitx_utils_malloc0(sizeof(TABLECANDWORD));
1338 tableCandWord->flag = CT_FH;
1339 tableCandWord->candWord.iFHIndex = i;
1340 FcitxCandidateWord candWord;
1341 candWord.callback = TableGetCandWord;
1342 candWord.owner = table;
1343 candWord.priv = tableCandWord;
1344 candWord.strExtra = NULL;
1345 candWord.strWord = strdup(table->tableDict->fh[i].strFH);
1346 candWord.wordType = MSG_OTHER;
1347 FcitxCandidateWordAppend(FcitxInputStateGetCandidateList(input), &candWord);
1348 }
1349 return IRV_DISPLAY_CANDWORDS;
1350 }
1351
TableGetFHCandWord(TableMetaData * table,TABLECANDWORD * tableCandWord)1352 INPUT_RETURN_VALUE TableGetFHCandWord(TableMetaData* table, TABLECANDWORD* tableCandWord)
1353 {
1354 FcitxTableState* tbl = table->owner;
1355 FcitxInstance *instance = tbl->owner;
1356 FcitxInputState *input = FcitxInstanceGetInputState(instance);
1357
1358 strcpy(FcitxInputStateGetOutputString(input), table->tableDict->fh[tableCandWord->candWord.iFHIndex].strFH);
1359 return IRV_COMMIT_STRING;
1360 }
1361
TablePhraseTips(void * arg)1362 boolean TablePhraseTips(void *arg)
1363 {
1364 TableMetaData* table = (TableMetaData*) arg;
1365 FcitxTableState *tbl = table->owner;
1366 RECORD *recTemp = NULL;
1367 char strTemp[PHRASE_MAX_LENGTH * UTF8_MAX_LENGTH + 1] = "", *ps;
1368 short i, j;
1369 FcitxInstance *instance = tbl->owner;
1370 FcitxInputState *input = FcitxInstanceGetInputState(instance);
1371
1372 if (!table->tableDict->recordHead)
1373 return false;
1374
1375 //如果最近输入了一个词组,这个工作就不需要了
1376 if (FcitxInputStateGetLastIsSingleChar(input) != 1)
1377 return false;
1378
1379 j = (table->tableDict->iHZLastInputCount > PHRASE_MAX_LENGTH) ? table->tableDict->iHZLastInputCount - PHRASE_MAX_LENGTH : 0;
1380 for (i = j; i < table->tableDict->iHZLastInputCount; i++)
1381 strcat(strTemp, table->tableDict->hzLastInput[i].strHZ);
1382 //如果只有一个汉字,这个工作也不需要了
1383 if (fcitx_utf8_strlen(strTemp) < 2)
1384 return false;
1385
1386 //首先要判断是不是已经在词库中
1387 ps = strTemp;
1388 FcitxMessages *msg_up = FcitxInputStateGetAuxUp(input);
1389 FcitxMessages *msg_down = FcitxInputStateGetAuxDown(input);
1390 for (i = 0; i < (table->tableDict->iHZLastInputCount - j - 1); i++) {
1391 recTemp = TableFindPhrase(table->tableDict, ps);
1392 if (recTemp) {
1393 FcitxInstanceCleanInputWindow(instance);
1394 FcitxMessagesAddMessageStringsAtLast(
1395 msg_up, MSG_TIPS, _("Phrase is already in Dict "));
1396 FcitxMessagesAddMessageStringsAtLast(msg_up, MSG_INPUT, ps);
1397
1398 FcitxMessagesAddMessageStringsAtLast(msg_down, MSG_FIRSTCAND,
1399 _("Code is "));
1400 FcitxMessagesAddMessageStringsAtLast(msg_down, MSG_CODE,
1401 recTemp->strCode);
1402 FcitxMessagesAddMessageStringsAtLast(msg_down, MSG_TIPS,
1403 _(" Ctrl+Delete To Delete"));
1404 tbl->bTablePhraseTips = true;
1405 FcitxInputStateSetShowCursor(input, false);
1406
1407 return true;
1408 }
1409 ps = ps + fcitx_utf8_char_len(ps);
1410 }
1411
1412 return false;
1413 }
1414
UpdateHZLastInput(TableMetaData * table,const char * str)1415 void UpdateHZLastInput(TableMetaData* table, const char *str)
1416 {
1417 unsigned int i, j;
1418 unsigned int str_len = fcitx_utf8_strlen(str);
1419 TableDict *const tableDict = table->tableDict;
1420 SINGLE_HZ *const hzLastInput = tableDict->hzLastInput;
1421
1422 for (i = 0;i < str_len;i++) {
1423 if (tableDict->iHZLastInputCount < PHRASE_MAX_LENGTH) {
1424 tableDict->iHZLastInputCount++;
1425 } else {
1426 for (j = 0;j < (tableDict->iHZLastInputCount - 1);j++) {
1427 strncpy(hzLastInput[j].strHZ, hzLastInput[j + 1].strHZ,
1428 fcitx_utf8_char_len(hzLastInput[j + 1].strHZ));
1429 }
1430 }
1431 unsigned int char_len = fcitx_utf8_char_len(str);
1432 strncpy(hzLastInput[tableDict->iHZLastInputCount - 1].strHZ,
1433 str, char_len);
1434 hzLastInput[tableDict->iHZLastInputCount - 1].strHZ[char_len] = '\0';
1435 str += char_len;
1436 }
1437
1438 if (tableDict->bRule && table->bAutoPhrase) {
1439 TableCreateAutoPhrase(table, (char)(str_len));
1440 }
1441 }
1442
TableMetaDataFree(TableMetaData * table)1443 void TableMetaDataFree(TableMetaData *table)
1444 {
1445 if (!table)
1446 return;
1447 FcitxConfigFree(&table->config);
1448 fcitx_utils_free(table->confName);
1449 free(table);
1450 }
1451
TableCandCmp(const void * a,const void * b,void * arg)1452 int TableCandCmp(const void* a, const void* b, void *arg)
1453 {
1454 TABLECANDWORD* canda = *(TABLECANDWORD**)a;
1455 TABLECANDWORD* candb = *(TABLECANDWORD**)b;
1456 TableCandWordSortContext* context = arg;
1457
1458 if (context->simpleLevel > 0) {
1459 size_t lengthA = strlen(canda->candWord.record->strCode);
1460 size_t lengthB = strlen(candb->candWord.record->strCode);
1461
1462 if (lengthA <= context->simpleLevel && lengthB <= context->simpleLevel) {
1463 /* we use msort which is stable, so it doesn't matter */
1464 return 0;
1465 }
1466 if (lengthA > context->simpleLevel && lengthB <= context->simpleLevel) {
1467 return 1;
1468 }
1469 if (lengthA <= context->simpleLevel && lengthB > context->simpleLevel) {
1470 return -1;
1471 }
1472 }
1473
1474 switch (context->order) {
1475 case AD_NO:
1476 /* actually this is dead code, since AD_NO doesn't sort at all */
1477 return 0;
1478 case AD_FAST: {
1479 int result = strcmp(canda->candWord.record->strCode,
1480 candb->candWord.record->strCode);
1481 if (result != 0)
1482 return result;
1483 return candb->candWord.record->iIndex - canda->candWord.record->iIndex;
1484 }
1485 case AD_FREQ: {
1486 int result = strcmp(canda->candWord.record->strCode,
1487 candb->candWord.record->strCode);
1488 if (result != 0)
1489 return result;
1490 return candb->candWord.record->iHit - canda->candWord.record->iHit;
1491 }
1492 }
1493 return 0;
1494 }
1495
TableKeyBlocker(void * arg,FcitxKeySym sym,unsigned int state)1496 INPUT_RETURN_VALUE TableKeyBlocker(void* arg, FcitxKeySym sym, unsigned int state)
1497 {
1498 TableMetaData *table = arg;
1499 FcitxInstance *instance = table->owner->owner;
1500 FcitxInputState *input = FcitxInstanceGetInputState(instance);
1501
1502 do {
1503 if (!table->bCommitAndPassByInvalidKey)
1504 break;
1505 if (!FcitxHotkeyIsHotKeySimple(sym, state))
1506 break;
1507 FcitxCandidateWordList *cand_list;
1508 cand_list = FcitxInputStateGetCandidateList(input);
1509 if (FcitxCandidateWordPageCount(cand_list)) {
1510 FcitxCandidateWord *candWord;
1511 candWord = FcitxCandidateWordGetCurrentWindow(cand_list);
1512 if (candWord->owner != table)
1513 break;
1514 TABLECANDWORD* tableCandWord = candWord->priv;
1515 if (tableCandWord->flag == CT_AUTOPHRASE)
1516 break;
1517 INPUT_RETURN_VALUE ret = TableGetCandWord(table, candWord);
1518 if (!(ret & IRV_FLAG_PENDING_COMMIT_STRING))
1519 break;
1520 FcitxInstanceCommitString(
1521 instance, FcitxInstanceGetCurrentIC(instance),
1522 FcitxInputStateGetOutputString(input));
1523 } else if (table->bSendRawPreedit) {
1524 FcitxInstanceCommitString(
1525 instance, FcitxInstanceGetCurrentIC(instance),
1526 FcitxInputStateGetRawInputBuffer(input));
1527 }
1528 FcitxInputStateSetRawInputBufferSize(input, 0);
1529 FcitxInputStateGetRawInputBuffer(input)[0] = '\0';
1530 FcitxInputStateSetIsInRemind(input, false);
1531 FcitxInstanceCleanInputWindow(instance);
1532 FcitxUIUpdateInputWindow(instance);
1533 return IRV_FLAG_FORWARD_KEY;
1534 } while (0);
1535 return FcitxStandardKeyBlocker(input, sym, state);
1536 }
1537
ReloadTableConfig(void * arg)1538 void ReloadTableConfig(void* arg)
1539 {
1540 FcitxTableState* tbl = arg;
1541 LoadTableConfig(&tbl->config);
1542 if (LoadTableInfo(tbl))
1543 FcitxInstanceUpdateIMList(tbl->owner);
1544 }
1545
1546 INPUT_RETURN_VALUE
Table_PYGetCandWord(void * arg,FcitxCandidateWord * candidateWord)1547 Table_PYGetCandWord(void* arg, FcitxCandidateWord* candidateWord)
1548 {
1549 TableMetaData* table = arg;
1550 FcitxTableState* tbl = table->owner;
1551 INPUT_RETURN_VALUE retVal = tbl->pygetcandword(tbl->pyaddon->addonInstance,
1552 candidateWord);
1553 FcitxPinyinReset(tbl->owner);
1554 FcitxInputState *state = FcitxInstanceGetInputState(tbl->owner);
1555 if (!(retVal & IRV_FLAG_PENDING_COMMIT_STRING)) {
1556 strcpy(FcitxInputStateGetOutputString(state), candidateWord->strWord);
1557 }
1558
1559 return IRV_COMMIT_STRING | IRV_FLAG_RESET_INPUT;
1560 }
1561
1562 // kate: indent-mode cstyle; space-indent on; indent-width 0;
1563