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
21 #include <stdio.h>
22 #include <limits.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <libintl.h>
26
27 #include "punc.h"
28 #include "fcitx/module.h"
29 #include "fcitx/fcitx.h"
30 #include "fcitx/hook.h"
31 #include "fcitx/ime.h"
32 #include "fcitx/keys.h"
33 #include "fcitx/frontend.h"
34 #include "fcitx/instance.h"
35 #include "fcitx/candidate.h"
36 #include "fcitx/context.h"
37 #include "fcitx-config/xdg.h"
38 #include "fcitx-utils/log.h"
39 #include "fcitx-utils/utils.h"
40 #include "fcitx-utils/bitset.h"
41 #include "module/freedesktop-notify/fcitx-freedesktop-notify.h"
42
43 /**
44 * @file punc.c
45 * Trans full width punc for Fcitx
46 */
47
48 #define PUNC_DICT_FILENAME "punc.mb"
49 #define MAX_PUNC_NO 2
50 #define MAX_PUNC_LENGTH 2
51
52 struct _FcitxPuncState;
53 typedef struct _WidePunc {
54 char ASCII;
55 char strWidePunc[MAX_PUNC_NO][MAX_PUNC_LENGTH * UTF8_MAX_LENGTH + 1];
56 unsigned iCount: 2;
57 } WidePunc;
58
59 typedef struct _PuncWhich {
60 FcitxBitSet* bitset;
61 WidePunc* lastPunc;
62 } PuncWhich;
63
64 typedef struct _FcitxPunc {
65 char* langCode;
66 WidePunc* curPunc;
67
68 UT_hash_handle hh;
69 } FcitxPunc;
70
71 static boolean LoadPuncDict(struct _FcitxPuncState* puncState);
72 static FcitxPunc* LoadPuncFile(const char* filename);
73 static char *GetPunc(struct _FcitxPuncState* puncState, int iKey);
74 static void FreePunc(struct _FcitxPuncState* puncState);
75 static void* PuncCreate(FcitxInstance* instance);
76 static boolean PuncPreFilter(void* arg, FcitxKeySym sym, unsigned int state, INPUT_RETURN_VALUE* retVal);
77 static boolean ProcessPunc(void* arg, FcitxKeySym sym, unsigned int state, INPUT_RETURN_VALUE* retVal);
78 static void TogglePuncState(void *arg);
79 static boolean GetPuncState(void *arg);
80 static void ReloadPunc(void *arg);
81 static INPUT_RETURN_VALUE TogglePuncStateWithHotkey(void *arg);
82 static void ResetPunc(void *arg);
83 static void ResetPuncWhichStatus(void* arg);
84 static boolean IsHotKeyPunc(FcitxKeySym sym, unsigned int state);
85 static void PuncLanguageChanged(void* arg, const void* value);
86
87 static void* PuncWhichAlloc(void* arg);
88 static void* PuncWhichCopy(void* arg, void* data, void* src);
89 static void PuncWhichFree(void* arg, void* data);
90
91 DECLARE_ADDFUNCTIONS(Punc)
92
93 typedef struct _FcitxPuncState {
94 char cLastIsAutoConvert;
95 boolean bLastIsNumber;
96 FcitxInstance* owner;
97 FcitxPunc* puncSet;
98 WidePunc* curPunc;
99 int slot;
100 } FcitxPuncState;
101
102 FCITX_DEFINE_PLUGIN(fcitx_punc, module, FcitxModule) = {
103 PuncCreate,
104 NULL,
105 NULL,
106 NULL,
107 ReloadPunc
108 };
109
PuncCreate(FcitxInstance * instance)110 void* PuncCreate(FcitxInstance* instance)
111 {
112 FcitxPuncState* puncState = fcitx_utils_malloc0(sizeof(FcitxPuncState));
113 puncState->owner = instance;
114 LoadPuncDict(puncState);
115 FcitxKeyFilterHook hk;
116 hk.arg = puncState;
117 hk.func = ProcessPunc;
118
119 FcitxInstanceRegisterPostInputFilter(instance, hk);
120
121 hk.func = PuncPreFilter;
122 FcitxInstanceRegisterPreInputFilter(instance, hk);
123
124 puncState->cLastIsAutoConvert = '\0';
125 puncState->bLastIsNumber = false;
126
127 FcitxHotkeyHook hotkey;
128 hotkey.hotkey = FcitxInstanceGetGlobalConfig(instance)->hkPunc;
129 hotkey.hotkeyhandle = TogglePuncStateWithHotkey;
130 hotkey.arg = puncState;
131 FcitxInstanceRegisterHotkeyFilter(instance, hotkey);
132
133 FcitxIMEventHook hook;
134 hook.arg = puncState;
135 hook.func = ResetPunc;
136
137 FcitxInstanceRegisterResetInputHook(instance, hook);
138
139 hook.func = ResetPuncWhichStatus;
140
141 FcitxInstanceRegisterInputUnFocusHook(instance, hook);
142
143 FcitxInstanceWatchContext(instance, CONTEXT_IM_LANGUAGE,
144 PuncLanguageChanged, puncState);
145
146 FcitxProfile* profile = FcitxInstanceGetProfile(instance);
147 FcitxUIRegisterStatus(instance, puncState, "punc",
148 profile->bUseWidePunc ? _("Full width punct") :
149 _("Latin punct"),
150 _("Toggle Full Width Punctuation"), TogglePuncState,
151 GetPuncState);
152
153 puncState->slot = FcitxInstanceAllocDataForIC(instance, PuncWhichAlloc,
154 PuncWhichCopy, PuncWhichFree,
155 puncState);
156
157 FcitxInstanceRegisterWatchableContext(instance, CONTEXT_DISABLE_PUNC, FCT_Boolean, FCF_ResetOnInputMethodChange);
158
159 FcitxPuncAddFunctions(instance);
160 return puncState;
161 }
162
PuncWhichAlloc(void * arg)163 void* PuncWhichAlloc(void *arg)
164 {
165 FcitxPunc *puncState = arg;
166 PuncWhich *which = fcitx_utils_new(PuncWhich);
167 which->lastPunc = puncState->curPunc;
168 which->bitset = fcitx_bitset_new(256);
169 return which;
170 }
171
PuncWhichCopy(void * arg,void * data,void * src)172 void* PuncWhichCopy(void* arg, void* data, void* src)
173 {
174 FCITX_UNUSED(arg);
175 PuncWhich *which = data;
176 PuncWhich *whichsrc = src;
177 which->lastPunc = whichsrc->lastPunc;
178 memcpy(which->bitset, whichsrc->bitset, fcitx_bitset_size(256));
179 return data;
180 }
181
PuncWhichFree(void * arg,void * data)182 void PuncWhichFree(void* arg, void* data)
183 {
184 FCITX_UNUSED(arg);
185 PuncWhich *which = data;
186 free(which->bitset);
187 free(data);
188 }
189
PuncLanguageChanged(void * arg,const void * value)190 void PuncLanguageChanged(void* arg, const void* value)
191 {
192 FcitxPuncState* puncState = (FcitxPuncState*) arg;
193 const char* lang = (const char*) value;
194 FcitxPunc* punc = NULL;
195 if (lang) {
196 HASH_FIND_STR(puncState->puncSet, lang, punc);
197 if (punc)
198 puncState->curPunc = punc->curPunc;
199 else
200 puncState->curPunc = NULL;
201 } else
202 puncState->curPunc = NULL;
203
204 FcitxUISetStatusVisable (puncState->owner, "punc", puncState->curPunc != NULL) ;
205 }
206
207 static void
PuncGetPunc2(FcitxPuncState * puncState,int key,char ** p1,char ** p2)208 PuncGetPunc2(FcitxPuncState *puncState, int key, char **p1, char **p2)
209 {
210 int iIndex = 0;
211 WidePunc *curPunc = puncState->curPunc;
212
213 if (!curPunc)
214 return;
215
216 while (curPunc[iIndex].ASCII) {
217 if (curPunc[iIndex].ASCII == key) {
218 if (p1)
219 *p1 = curPunc[iIndex].strWidePunc[0];
220 if (curPunc[iIndex].iCount > 1 && p2)
221 *p2 = curPunc[iIndex].strWidePunc[1];
222 break;
223 }
224 iIndex++;
225 }
226 }
227
ResetPunc(void * arg)228 void ResetPunc(void* arg)
229 {
230 FcitxPuncState* puncState = (FcitxPuncState*) arg;
231 puncState->bLastIsNumber = false;
232 puncState->cLastIsAutoConvert = '\0';
233 }
234
ResetPuncWhichStatus(void * arg)235 void ResetPuncWhichStatus(void* arg)
236 {
237 FcitxPuncState* puncState = (FcitxPuncState*) arg;
238 WidePunc *curPunc = puncState->curPunc;
239
240 if (!curPunc)
241 return;
242
243 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(puncState->owner);
244 if (!ic)
245 return;
246 PuncWhich* puncWhich = FcitxInstanceGetICData(puncState->owner, ic, puncState->slot);
247 fcitx_bitset_clear(puncWhich->bitset);
248 }
249
PuncPreFilter(void * arg,FcitxKeySym sym,unsigned int state,INPUT_RETURN_VALUE * retVal)250 boolean PuncPreFilter(void* arg, FcitxKeySym sym, unsigned int state,
251 INPUT_RETURN_VALUE* retVal)
252 {
253 FCITX_UNUSED(retVal);
254 FcitxPuncState *puncState = (FcitxPuncState*)arg;
255 boolean disablePunc = FcitxInstanceGetContextBoolean(
256 puncState->owner, CONTEXT_DISABLE_PUNC);
257 if (disablePunc)
258 return false;
259
260 if (FcitxHotkeyIsHotKeySimple(sym, state) &&
261 !FcitxHotkeyIsHotKeyDigit(sym, state) && !IsHotKeyPunc(sym, state))
262 puncState->bLastIsNumber = false;
263 return false;
264 }
265
ProcessPunc(void * arg,FcitxKeySym sym,unsigned int state,INPUT_RETURN_VALUE * retVal)266 boolean ProcessPunc(void* arg, FcitxKeySym sym, unsigned int state, INPUT_RETURN_VALUE* retVal)
267 {
268 FcitxPuncState* puncState = (FcitxPuncState*) arg;
269 FcitxInstance* instance = puncState->owner;
270 FcitxInputState* input = FcitxInstanceGetInputState(puncState->owner);
271 FcitxProfile* profile = FcitxInstanceGetProfile(instance);
272 FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(instance);
273
274 char *pPunc = NULL;
275
276 if (*retVal != IRV_TO_PROCESS)
277 return false;
278
279 boolean disablePunc = FcitxInstanceGetContextBoolean(
280 puncState->owner, CONTEXT_DISABLE_PUNC);
281 if (disablePunc)
282 return false;
283
284 FcitxCandidateWordList *candList = FcitxInputStateGetCandidateList(input);
285 if (FcitxCandidateWordGetListSize(candList) != 0) {
286 if (FcitxCandidateWordGetHasGoneToNextPage(candList) &&
287 FcitxHotkeyIsHotKey(sym, state,
288 FcitxConfigPrevPageKey(instance, config))) {
289 return false;
290 }
291 /*
292 * comparing with upper case, if paging is occupied,
293 * punc will not let next page pass
294 */
295 if (FcitxHotkeyIsHotKey(sym, state,
296 FcitxConfigNextPageKey(instance, config))) {
297 return false;
298 }
299 }
300
301 FcitxKeySym origsym = sym;
302 sym = FcitxHotkeyPadToMain(sym);
303 if (profile->bUseWidePunc) {
304 if (puncState->bLastIsNumber && config->bEngPuncAfterNumber
305 && (FcitxHotkeyIsHotKey(origsym, state, FCITX_PERIOD)
306 || FcitxHotkeyIsHotKey(origsym, state, FCITX_SEMICOLON)
307 || FcitxHotkeyIsHotKey(origsym, state, FCITX_COMMA))) {
308 puncState->cLastIsAutoConvert = origsym;
309 puncState->bLastIsNumber = false;
310 *retVal = IRV_DONOT_PROCESS;
311 return true;
312 }
313 if (FcitxHotkeyIsHotKeySimple(sym, state))
314 pPunc = GetPunc(puncState, origsym);
315 }
316
317 /*
318 * 在有候选词未输入的情况下,选择第一个候选词并输入标点
319 */
320 if (IsHotKeyPunc(sym, state)) {
321 FcitxInputStateGetOutputString(input)[0] = '\0';
322 INPUT_RETURN_VALUE ret = IRV_TO_PROCESS;
323 if (!FcitxInputStateGetIsInRemind(input))
324 ret = FcitxCandidateWordChooseByTotalIndex(FcitxInputStateGetCandidateList(input), 0);
325
326 /* if there is nothing to commit */
327 if (ret == IRV_TO_PROCESS) {
328 if (pPunc) {
329 strcat(FcitxInputStateGetOutputString(input), pPunc);
330 *retVal = IRV_PUNC;
331 FcitxInstanceCleanInputWindow(instance);
332 return true;
333 } else
334 return false;
335 } else {
336 if (pPunc)
337 strcat(FcitxInputStateGetOutputString(input), pPunc);
338 else {
339 char buf[2] = { sym, 0 };
340 strcat(FcitxInputStateGetOutputString(input), buf);
341 }
342
343 FcitxInstanceCleanInputWindow(instance);
344 *retVal = IRV_PUNC;
345 return true;
346 }
347
348 return false;
349 }
350
351 if (profile->bUseWidePunc) {
352 if (FcitxHotkeyIsHotKey(sym, state, FCITX_BACKSPACE)
353 && puncState->cLastIsAutoConvert) {
354 char *pPunc;
355
356 FcitxInstanceForwardKey(puncState->owner, FcitxInstanceGetCurrentIC(instance), FCITX_PRESS_KEY, sym, state);
357 pPunc = GetPunc(puncState, puncState->cLastIsAutoConvert);
358 if (pPunc)
359 FcitxInstanceCommitString(puncState->owner, FcitxInstanceGetCurrentIC(instance), pPunc);
360
361 puncState->cLastIsAutoConvert = 0;
362 *retVal = IRV_DO_NOTHING;
363 return true;
364 } else if (FcitxHotkeyIsHotKeyDigit(sym, state)) {
365 puncState->bLastIsNumber = true;
366 } else {
367 puncState->bLastIsNumber = false;
368 }
369 }
370 puncState->cLastIsAutoConvert = 0;
371 return false;
372 }
373
374 /**
375 * 加载标点词典
376 * @param void
377 * @return void
378 * @note 文件中数据的格式为: 对应的英文符号 中文标点 <中文标点>
379 * 加载标点词典。标点词典定义了一组标点转换,如输入‘.’就直接转换成‘。’
380 */
LoadPuncDict(FcitxPuncState * puncState)381 boolean LoadPuncDict(FcitxPuncState* puncState)
382 {
383 FcitxStringHashSet* puncfiles = FcitxXDGGetFiles("data", PUNC_DICT_FILENAME "." , NULL);
384 FcitxStringHashSet *curpuncfile = puncfiles;
385 FcitxPunc* punc;
386 while (curpuncfile) {
387 punc = LoadPuncFile(curpuncfile->name);
388 if (punc)
389 HASH_ADD_KEYPTR(hh, puncState->puncSet, punc->langCode, strlen(punc->langCode), punc);
390 curpuncfile = curpuncfile->hh.next;
391 }
392
393 fcitx_utils_free_string_hash_set(puncfiles);
394 return true;
395 }
396
LoadPuncFile(const char * filename)397 FcitxPunc* LoadPuncFile(const char* filename)
398 {
399 FILE *fpDict; // 词典文件指针
400 int iRecordNo;
401 char strText[4 + MAX_PUNC_LENGTH * UTF8_MAX_LENGTH];
402 char *pstr; // 临时指针
403 int i;
404 fpDict = FcitxXDGGetFileWithPrefix("data", filename, "r", NULL);
405
406 if (strlen(filename) < strlen(PUNC_DICT_FILENAME))
407 return NULL;
408
409 if (!fpDict) {
410 FcitxLog(WARNING, _("Can't open punc file."));
411 return NULL;
412 }
413
414 /* 计算词典里面有多少的数据
415 * 这个函数非常简单,就是计算该文件有多少行(包含空行)。
416 * 因为空行,在下面会略去,所以,这儿存在内存的浪费现象。
417 * 没有一个空行就是浪费sizeof (WidePunc)字节内存*/
418 iRecordNo = fcitx_utils_calculate_record_number(fpDict);
419 // 申请空间,用来存放这些数据。这儿没有检查是否申请到内存,严格说有小隐患
420 WidePunc* punc = (WidePunc *) fcitx_utils_malloc0(sizeof(WidePunc) * (iRecordNo + 1));
421
422 iRecordNo = 0;
423
424 // 下面这个循环,就是一行一行的读入词典文件的数据。并将其放入到curPunc里面去。
425 for (;;) {
426 if (!fgets(strText, (MAX_PUNC_LENGTH * UTF8_MAX_LENGTH + 3), fpDict))
427 break;
428 i = strlen(strText) - 1;
429
430 // 先找到最后一个字符
431 while ((strText[i] == '\n') || (strText[i] == ' ')) {
432 if (!i)
433 break;
434 i--;
435 }
436
437 // 如果找到,进行出入。当是空行时,肯定找不到。所以,也就略过了空行的处理
438 if (i) {
439 strText[i + 1] = '\0'; // 在字符串的最后加个封口
440 pstr = strText; // 将pstr指向第一个非空字符
441 while (*pstr == ' ')
442 pstr++;
443 punc[iRecordNo].ASCII = *pstr++; // 这个就是中文符号所对应的ASCII码值
444 while (*pstr == ' ') // 然后,将pstr指向下一个非空字符
445 pstr++;
446
447 punc[iRecordNo].iCount = 0; // 该符号有几个转化,比如英文"就可以转换成“和”
448 // 依次将该ASCII码所对应的符号放入到结构中
449 while (*pstr) {
450 i = 0;
451 // 因为中文符号都是多字节(这里读取并不像其他地方是固定两个,所以没有问题)的,所以,要一直往后读,知道空格或者字符串的末尾
452 while (*pstr != ' ' && *pstr) {
453 punc[iRecordNo].strWidePunc[punc[iRecordNo].iCount][i] = *pstr;
454 i++;
455 pstr++;
456 }
457
458 // 每个中文符号用'\0'隔开
459 punc[iRecordNo].strWidePunc[punc[iRecordNo].iCount][i] = '\0';
460 while (*pstr == ' ')
461 pstr++;
462 punc[iRecordNo].iCount++;
463 }
464
465 iRecordNo++;
466 }
467 }
468
469 punc[iRecordNo].ASCII = '\0';
470 fclose(fpDict);
471
472 FcitxPunc* p = fcitx_utils_malloc0(sizeof(FcitxPunc));
473 p->langCode = "";
474
475 const char* langcode = filename + strlen(PUNC_DICT_FILENAME);
476 if (*langcode == '\0')
477 p->langCode = strdup("C");
478 else
479 p->langCode = strdup(langcode + 1);
480
481 p->curPunc = punc;
482
483 return p;
484 }
485
FreePunc(FcitxPuncState * puncState)486 void FreePunc(FcitxPuncState* puncState)
487 {
488 puncState->curPunc = NULL;
489 FcitxPunc* cur;
490 while (puncState->puncSet) {
491 cur = puncState->puncSet;
492 HASH_DEL(puncState->puncSet, cur);
493 free(cur->langCode);
494 free(cur->curPunc);
495 free(cur);
496 }
497 }
498
GetPuncWhich(FcitxPuncState * puncState,WidePunc * punc)499 static inline int GetPuncWhich(FcitxPuncState* puncState, WidePunc* punc)
500 {
501 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(puncState->owner);
502 if (!ic)
503 return 0;
504 PuncWhich* puncWhich = FcitxInstanceGetICData(puncState->owner, ic, puncState->slot);
505 if (puncWhich->lastPunc != puncState->curPunc) {
506 fcitx_bitset_clear(puncWhich->bitset);
507 puncWhich->lastPunc = puncState->curPunc;
508 }
509 int result = fcitx_bitset_isset(puncWhich->bitset, punc->ASCII) ? 1 : 0;
510 if (result >= punc->iCount)
511 result = 0;
512 return result;
513 }
514
SetPuncWhich(FcitxPuncState * puncState,WidePunc * punc)515 static inline void SetPuncWhich(FcitxPuncState* puncState, WidePunc* punc)
516 {
517 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(puncState->owner);
518 if (!ic)
519 return;
520 PuncWhich* puncWhich = FcitxInstanceGetICData(puncState->owner, ic, puncState->slot);
521 FcitxBitSet* bitset = puncWhich->bitset;
522 if (punc->iCount == 1)
523 fcitx_bitset_unset(bitset, punc->ASCII);
524 else {
525 if (fcitx_bitset_isset(bitset, punc->ASCII))
526 fcitx_bitset_unset(bitset, punc->ASCII);
527 else
528 fcitx_bitset_set(bitset, punc->ASCII);
529 }
530 }
531
532 /*
533 * 根据字符得到相应的标点符号
534 * 如果该字符不在标点符号集中,则返回NULL
535 */
536 static char*
GetPunc(FcitxPuncState * puncState,int iKey)537 GetPunc(FcitxPuncState *puncState, int iKey)
538 {
539 int iIndex = 0;
540 char *pPunc;
541 WidePunc *curPunc = puncState->curPunc;
542
543 if (!curPunc)
544 return NULL;
545
546 while (curPunc[iIndex].ASCII) {
547 if (curPunc[iIndex].ASCII == iKey) {
548 pPunc = curPunc[iIndex].strWidePunc[GetPuncWhich(puncState,
549 &curPunc[iIndex])];
550 SetPuncWhich(puncState, &curPunc[iIndex]);
551 return pPunc;
552 }
553 iIndex++;
554 }
555
556 return NULL;
557 }
558
TogglePuncState(void * arg)559 void TogglePuncState(void* arg)
560 {
561 FcitxPuncState* puncState = (FcitxPuncState*)arg;
562 FcitxInstance* instance = puncState->owner;
563 FcitxProfile* profile = FcitxInstanceGetProfile(instance);
564 profile->bUseWidePunc = !profile->bUseWidePunc;
565
566 FcitxUISetStatusString(puncState->owner, "punc",
567 profile->bUseWidePunc ? _("Full width punct") :
568 _("Latin punct"),
569 _("Toggle Full Width Punctuation"));
570 FcitxProfileSave(profile);
571 }
572
TogglePuncStateWithHotkey(void * arg)573 INPUT_RETURN_VALUE TogglePuncStateWithHotkey(void* arg)
574 {
575 FcitxPuncState *puncState = (FcitxPuncState*)arg;
576 FcitxInstance *instance = puncState->owner;
577 FcitxProfile *profile = FcitxInstanceGetProfile(instance);
578
579 FcitxUIStatus *status = FcitxUIGetStatusByName(instance, "punc");
580 if (status->visible){
581 FcitxUIUpdateStatus(instance, "punc");
582 FcitxFreeDesktopNotifyShowAddonTip(
583 instance, "fcitx-punc-toggle",
584 profile->bUseWidePunc ? "fcitx-punc-active" : "fcitx-punc-inactive",
585 _("Punctuation Support"),
586 profile->bUseWidePunc ? _("Full width punctuations are used.") :
587 _("Latin punctuations are used."));
588 return IRV_DO_NOTHING;
589 } else {
590 return IRV_TO_PROCESS;
591 }
592 }
593
GetPuncState(void * arg)594 boolean GetPuncState(void* arg)
595 {
596 FcitxPuncState* puncState = (FcitxPuncState*) arg;
597 FcitxInstance* instance = puncState->owner;
598 FcitxProfile* profile = FcitxInstanceGetProfile(instance);
599 return profile->bUseWidePunc;
600 }
601
ReloadPunc(void * arg)602 void ReloadPunc(void* arg)
603 {
604 FcitxPuncState* puncState = (FcitxPuncState*) arg;
605 FreePunc(puncState);
606 LoadPuncDict(puncState);
607
608 PuncLanguageChanged(puncState, FcitxInstanceGetContextString(puncState->owner, CONTEXT_IM_LANGUAGE));
609 }
610
IsHotKeyPunc(FcitxKeySym sym,unsigned int state)611 boolean IsHotKeyPunc(FcitxKeySym sym, unsigned int state)
612 {
613 if (FcitxHotkeyIsHotKeySimple(sym, state)
614 && !FcitxHotkeyIsHotKeyDigit(sym, state)
615 && !FcitxHotkeyIsHotKeyLAZ(sym, state)
616 && !FcitxHotkeyIsHotKeyUAZ(sym, state)
617 && !FcitxHotkeyIsHotKey(sym, state, FCITX_SPACE))
618 return true;
619
620 return false;
621 }
622 #include "fcitx-punc-addfunctions.h"
623