1 /***************************************************************************
2 * Copyright (C) 2010~2010 by CSSlayer *
3 * wengxt@gmail.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 <dlfcn.h>
22 #include <libintl.h>
23 #include <pthread.h>
24 #include <regex.h>
25
26 #include "fcitx-utils/utarray.h"
27 #include "frontend.h"
28 #include "addon.h"
29 #include "ime-internal.h"
30 #include "fcitx-config/xdg.h"
31 #include "fcitx-utils/log.h"
32 #include "ui.h"
33 #include "hook.h"
34 #include "hook-internal.h"
35 #include "instance.h"
36 #include "instance-internal.h"
37 #include "addon-internal.h"
38 #include "config.h"
39
40 static void FcitxInstanceCleanUpIC(FcitxInstance* instance);
41 static void NewICData(FcitxInstance* instance, FcitxInputContext* ic);
42 static void FreeICData(FcitxInstance* instance, FcitxInputContext* ic);
43 static void FillICData(FcitxInstance* instance, FcitxInputContext* ic);
44 static boolean AppPreeditBlacklisted(
45 FcitxInstance* instance, FcitxInputContext* ic);
46
FillICData(FcitxInstance * instance,FcitxInputContext * ic)47 void FillICData(FcitxInstance* instance, FcitxInputContext* ic)
48 {
49 FcitxInputContext2* ic2 = (FcitxInputContext2*) ic;
50 unsigned int i = utarray_len(ic2->data);
51 for (;i < utarray_len(&instance->icdata);i++) {
52 FcitxICDataInfo *info =
53 (FcitxICDataInfo*)_utarray_eltptr(&instance->icdata, i);
54 void *data = NULL;
55 if (info->allocCallback)
56 data = info->allocCallback(info->arg);
57 utarray_push_back(ic2->data, &data);
58 }
59 }
60
61
NewICData(FcitxInstance * instance,FcitxInputContext * ic)62 void NewICData(FcitxInstance* instance, FcitxInputContext* ic)
63 {
64 FcitxInputContext2* ic2 = (FcitxInputContext2*) ic;
65 utarray_new(ic2->data, fcitx_ptr_icd);
66 FillICData(instance, ic);
67 }
68
FreeICData(FcitxInstance * instance,FcitxInputContext * ic)69 void FreeICData(FcitxInstance* instance, FcitxInputContext* ic)
70 {
71 FcitxInputContext2* ic2 = (FcitxInputContext2*) ic;
72 unsigned int i = 0;
73 for (;i < utarray_len(ic2->data);i++) {
74 void** data = (void**)_utarray_eltptr(ic2->data, i);
75 FcitxICDataInfo* info =
76 (FcitxICDataInfo*)_utarray_eltptr(&instance->icdata, i);
77 if (info->freeCallback) {
78 info->freeCallback(info->arg, *data);
79 }
80 }
81 utarray_free(ic2->data);
82 fcitx_utils_free(ic2->prgname);
83 }
84
85 FCITX_EXPORT_API void*
FcitxInstanceGetICData(FcitxInstance * instance,FcitxInputContext * ic,int icdataid)86 FcitxInstanceGetICData(FcitxInstance *instance, FcitxInputContext *ic,
87 int icdataid)
88 {
89 FCITX_UNUSED(instance);
90 if (!ic)
91 return NULL;
92
93 FcitxInputContext2* ic2 = (FcitxInputContext2*)ic;
94 void **data = fcitx_array_eltptr(ic2->data, icdataid);
95 if (!data)
96 return NULL;
97 return *data;
98 }
99
100 static
FcitxInstanceSetICDataInternal(struct _FcitxInstance * instance,FcitxInputContext * ic,int icdataid,void * newdata,boolean copy)101 void FcitxInstanceSetICDataInternal(struct _FcitxInstance* instance, FcitxInputContext* ic, int icdataid, void* newdata, boolean copy)
102 {
103 FcitxInputContext2* ic2 = (FcitxInputContext2*) ic;
104 FcitxICDataInfo *info = fcitx_array_eltptr(&instance->icdata, icdataid);
105 void **data = fcitx_array_eltptr(ic2->data, icdataid);
106 if (!data || !info)
107 return;
108 if (copy) {
109 if (info->copyCallback) {
110 *data = info->copyCallback(info->arg, *data, newdata);
111 }
112 }
113 else
114 *data = newdata;
115 }
116
117 FCITX_EXPORT_API
FcitxInstanceSetICData(struct _FcitxInstance * instance,FcitxInputContext * ic,int icdataid,void * newdata)118 void FcitxInstanceSetICData(struct _FcitxInstance* instance, FcitxInputContext* ic, int icdataid, void* newdata)
119 {
120 if (!ic)
121 return;
122 switch (instance->config->shareState) {
123 case ShareState_All:
124 case ShareState_PerProgram: {
125 FcitxInputContext *rec = instance->ic_list;
126 while (rec != NULL) {
127 boolean flag = false;
128 if (instance->config->shareState == ShareState_All)
129 flag = true;
130 else {
131 flag = FcitxInstanceCheckICFromSameApplication(instance, rec, ic);
132 }
133
134 if (flag)
135 FcitxInstanceSetICDataInternal(instance, rec, icdataid, newdata, (rec != ic));
136 rec = rec->next;
137 }
138 }
139 break;
140 case ShareState_None:
141 FcitxInstanceSetICDataInternal(instance, ic, icdataid, newdata, false);
142 break;
143 }
144 }
145
146 FCITX_EXPORT_API
FcitxFrontendsInit(UT_array * frontends)147 void FcitxFrontendsInit(UT_array* frontends)
148 {
149 utarray_init(frontends, fcitx_ptr_icd);
150 }
151
152 FCITX_EXPORT_API FcitxInputContext*
FcitxInstanceCreateIC(FcitxInstance * instance,int frontendid,void * priv)153 FcitxInstanceCreateIC(FcitxInstance* instance, int frontendid, void * priv)
154 {
155 /* clean up invalid ic here */
156 FcitxInstanceCleanUpIC(instance);
157 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid);
158 if (pfrontend == NULL)
159 return NULL;
160 FcitxFrontend* frontend = (*pfrontend)->frontend;
161
162 FcitxInputContext *rec;
163 if (instance->free_list != NULL) {
164 rec = instance->free_list;
165 instance->free_list = instance->free_list->next;
166 } else
167 rec = malloc(sizeof(FcitxInputContext2));
168
169 memset(rec, 0, sizeof(FcitxInputContext2));
170 rec->frontendid = frontendid;
171 rec->offset_x = -1;
172 rec->offset_y = -1;
173 ((FcitxInputContext2*)rec)->prgname = NULL;
174 ((FcitxInputContext2*)rec)->mayUsePreedit = Tri_Unknown;
175
176 NewICData(instance, rec);
177 switch (instance->config->shareState) {
178 case ShareState_All:
179 rec->state = instance->globalState;
180 break;
181 case ShareState_None:
182 case ShareState_PerProgram:
183 rec->state = instance->config->defaultIMState;
184 break;
185 default:
186 break;
187 }
188
189 frontend->CreateIC((*pfrontend)->addonInstance, rec, priv);
190
191 rec->next = instance->ic_list;
192 instance->ic_list = rec;
193 return rec;
194 }
195
196 FCITX_EXPORT_API
FcitxInstanceAllocDataForIC(FcitxInstance * instance,FcitxICDataAllocCallback allocCallback,FcitxICDataCopyCallback copyCallback,FcitxICDataFreeCallback freeCallback,void * arg)197 int FcitxInstanceAllocDataForIC(FcitxInstance* instance,
198 FcitxICDataAllocCallback allocCallback,
199 FcitxICDataCopyCallback copyCallback,
200 FcitxICDataFreeCallback freeCallback, void* arg)
201 {
202 FcitxICDataInfo info;
203 info.allocCallback = allocCallback;
204 info.copyCallback = copyCallback;
205 info.freeCallback = freeCallback;
206 info.arg = arg;
207
208 utarray_push_back(&instance->icdata, &info);
209 FcitxInputContext *rec = instance->ic_list;
210 while (rec) {
211 FillICData(instance, rec);
212 rec = rec->next;
213 }
214 return utarray_len(&instance->icdata) - 1;
215 }
216
FcitxInstanceCleanUpIC(FcitxInstance * instance)217 void FcitxInstanceCleanUpIC(FcitxInstance* instance)
218 {
219 FcitxInputContext *rec = instance->ic_list, *last = NULL, *todel;
220
221 while (rec) {
222 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance,
223 rec->frontendid);
224 FcitxFrontend *frontend = (*pfrontend)->frontend;
225 pid_t pid = 0;
226 if (frontend->GetPid)
227 pid = frontend->GetPid((*pfrontend)->addonInstance, rec);
228 if (pid && !fcitx_utils_pid_exists(pid)) {
229 if (last != NULL)
230 last->next = rec->next;
231 else
232 instance->ic_list = rec->next;
233 todel = rec;
234 rec = rec->next;
235 todel->next = instance->free_list;
236 instance->free_list = todel;
237 frontend->DestroyIC((*pfrontend)->addonInstance, todel);
238 FreeICData(instance, todel);
239
240 if (todel == instance->lastIC) {
241 FcitxInstanceSetLastIC(instance, NULL);
242 }
243
244 if (todel == instance->CurrentIC) {
245 instance->CurrentIC = NULL;
246 FcitxUICloseInputWindow(instance);
247 FcitxUIOnInputUnFocus(instance);
248 FcitxInstanceSetCurrentIC(instance, NULL);
249 }
250 }
251 else {
252 last = rec;
253 rec = rec->next;
254 }
255 }
256 }
257
258 FCITX_EXPORT_API
FcitxInstanceFindIC(FcitxInstance * instance,int frontendid,void * filter)259 FcitxInputContext* FcitxInstanceFindIC(FcitxInstance* instance, int frontendid, void *filter)
260 {
261 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid);
262 if (pfrontend == NULL)
263 return NULL;
264 FcitxFrontend* frontend = (*pfrontend)->frontend;
265 FcitxInputContext *rec = instance->ic_list;
266 while (rec != NULL) {
267 if (rec->frontendid == frontendid && frontend->CheckIC((*pfrontend)->addonInstance, rec, filter))
268 return rec;
269 rec = rec->next;
270 }
271 return NULL;
272 }
273
274 FCITX_EXPORT_API
FcitxInstanceSetICStateFromSameApplication(FcitxInstance * instance,int frontendid,FcitxInputContext * ic)275 void FcitxInstanceSetICStateFromSameApplication(FcitxInstance* instance, int frontendid, FcitxInputContext *ic)
276 {
277 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid);
278 if (pfrontend == NULL)
279 return;
280 FcitxFrontend* frontend = (*pfrontend)->frontend;
281 if (!frontend->CheckICFromSameApplication)
282 return;
283 FcitxInputContext *rec = instance->ic_list;
284 while (rec != NULL) {
285 if (rec->frontendid == frontendid && frontend->CheckICFromSameApplication((*pfrontend)->addonInstance, rec, ic)) {
286 ic->state = rec->state;
287 break;
288 }
289 rec = rec->next;
290 }
291 }
292
293 FCITX_EXPORT_API
FcitxInstanceDestroyIC(FcitxInstance * instance,int frontendid,void * filter)294 void FcitxInstanceDestroyIC(FcitxInstance* instance, int frontendid, void* filter)
295 {
296 FcitxInputContext *rec, *last;
297 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid);
298 if (pfrontend == NULL)
299 return;
300 FcitxFrontend* frontend = (*pfrontend)->frontend;
301
302 last = NULL;
303
304 for (rec = instance->ic_list; rec != NULL; last = rec, rec = rec->next) {
305 if (rec->frontendid == frontendid && frontend->CheckIC((*pfrontend)->addonInstance, rec, filter)) {
306 if (last != NULL)
307 last->next = rec->next;
308 else
309 instance->ic_list = rec->next;
310
311 rec->next = instance->free_list;
312 instance->free_list = rec;
313
314 if (rec == instance->lastIC) {
315 FcitxInstanceSetLastIC(instance, NULL);
316 }
317
318 if (rec == FcitxInstanceGetCurrentIC(instance)) {
319 FcitxUICloseInputWindow(instance);
320 FcitxUIOnInputUnFocus(instance);
321 FcitxInstanceSetCurrentIC(instance, NULL);
322 }
323
324 frontend->DestroyIC((*pfrontend)->addonInstance, rec);
325 FreeICData(instance, rec);
326 return;
327 }
328 }
329
330 return;
331 }
332
333 FCITX_EXPORT_API
FcitxInstanceGetCurrentState(FcitxInstance * instance)334 FcitxContextState FcitxInstanceGetCurrentState(FcitxInstance* instance)
335 {
336 if (instance->CurrentIC)
337 return instance->CurrentIC->state;
338 else
339 return IS_CLOSED;
340 }
341
342 FCITX_EXPORT_API
FcitxInstanceGetCurrentStatev2(FcitxInstance * instance)343 FcitxContextState FcitxInstanceGetCurrentStatev2(FcitxInstance* instance)
344 {
345 if (instance->CurrentIC) {
346 if (instance->CurrentIC->state == IS_INACTIVE)
347 return IS_ACTIVE;
348 return instance->CurrentIC->state;
349 }
350 else
351 return IS_CLOSED;
352 }
353
354 FCITX_EXPORT_API
FcitxInstanceGetCurrentCapacity(FcitxInstance * instance)355 FcitxCapacityFlags FcitxInstanceGetCurrentCapacity(FcitxInstance* instance)
356 {
357 if (instance->CurrentIC)
358 return instance->CurrentIC->contextCaps;
359 else
360 return CAPACITY_NONE;
361 }
362
363 FCITX_EXPORT_API
FcitxInstanceCommitString(FcitxInstance * instance,FcitxInputContext * ic,const char * str)364 void FcitxInstanceCommitString(FcitxInstance* instance, FcitxInputContext* ic, const char* str)
365 {
366 if (str == NULL)
367 return ;
368
369 if (ic == NULL)
370 return;
371
372 char *pstr = FcitxInstanceProcessCommitFilter(instance, str);
373 if (pstr != NULL)
374 str = pstr;
375
376 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
377 if (pfrontend == NULL)
378 return;
379 FcitxFrontend* frontend = (*pfrontend)->frontend;
380 frontend->CommitString((*pfrontend)->addonInstance, ic, str);
381
382 FcitxInputState* input = instance->input;
383 fcitx_utf8_strncpy(input->strLastCommit, str, MAX_USER_INPUT);
384 input->strLastCommit[MAX_USER_INPUT] = '\0';
385 instance->iHZInputed += (int)(fcitx_utf8_strlen(str));
386
387 if (pstr)
388 free(pstr);
389 }
390
391 FCITX_EXPORT_API
FcitxInstanceGetSurroundingText(FcitxInstance * instance,FcitxInputContext * ic,char ** str,unsigned int * cursor,unsigned int * anchor)392 boolean FcitxInstanceGetSurroundingText(FcitxInstance* instance, FcitxInputContext* ic, char** str, unsigned int* cursor, unsigned int* anchor)
393 {
394 if (ic == NULL)
395 return false;
396
397 if (!(ic->contextCaps & CAPACITY_SURROUNDING_TEXT))
398 return false;
399 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
400 if (pfrontend == NULL)
401 return false;
402
403 FcitxFrontend* frontend = (*pfrontend)->frontend;
404 if (frontend->GetSurroundingPreedit) {
405 return frontend->GetSurroundingPreedit((*pfrontend)->addonInstance, ic, str, cursor, anchor);
406 }
407 return false;
408 }
409
410 FCITX_EXPORT_API
FcitxInstanceDeleteSurroundingText(FcitxInstance * instance,FcitxInputContext * ic,int offset,unsigned int size)411 void FcitxInstanceDeleteSurroundingText(FcitxInstance* instance, FcitxInputContext* ic, int offset, unsigned int size)
412 {
413 if (ic == NULL)
414 return;
415 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
416 if (pfrontend == NULL)
417 return;
418
419 FcitxFrontend* frontend = (*pfrontend)->frontend;
420 if (frontend->DeleteSurroundingText) {
421 frontend->DeleteSurroundingText((*pfrontend)->addonInstance, ic, offset, size);
422 }
423 }
424
425 FCITX_EXPORT_API
FcitxInstanceUpdatePreedit(FcitxInstance * instance,FcitxInputContext * ic)426 void FcitxInstanceUpdatePreedit(FcitxInstance* instance, FcitxInputContext* ic)
427 {
428 if (!instance->profile->bUsePreedit)
429 return;
430
431 if (ic == NULL)
432 return;
433
434 if (AppPreeditBlacklisted(instance, ic))
435 return;
436
437 if (!(ic->contextCaps & CAPACITY_PREEDIT))
438 return;
439 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
440 if (pfrontend == NULL)
441 return;
442 FcitxFrontend* frontend = (*pfrontend)->frontend;
443 frontend->UpdatePreedit((*pfrontend)->addonInstance, ic);
444 }
445
446 FCITX_EXPORT_API
FcitxInstanceUpdateClientSideUI(FcitxInstance * instance,FcitxInputContext * ic)447 void FcitxInstanceUpdateClientSideUI(FcitxInstance* instance, FcitxInputContext* ic)
448 {
449 if (ic == NULL)
450 return;
451
452 if (!(ic->contextCaps & CAPACITY_CLIENT_SIDE_UI))
453 return;
454 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
455 if (pfrontend == NULL)
456 return;
457 FcitxFrontend* frontend = (*pfrontend)->frontend;
458 if (frontend->UpdateClientSideUI)
459 frontend->UpdateClientSideUI((*pfrontend)->addonInstance, ic);
460 }
461
462 FCITX_EXPORT_API
FcitxInstanceSetWindowOffset(FcitxInstance * instance,FcitxInputContext * ic,int x,int y)463 void FcitxInstanceSetWindowOffset(FcitxInstance* instance, FcitxInputContext *ic, int x, int y)
464 {
465 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
466 if (pfrontend == NULL)
467 return;
468 FcitxFrontend* frontend = (*pfrontend)->frontend;
469 if (frontend->SetWindowOffset)
470 frontend->SetWindowOffset((*pfrontend)->addonInstance, ic, x, y);
471 }
472
473 FCITX_EXPORT_API
FcitxInstanceGetWindowPosition(FcitxInstance * instance,FcitxInputContext * ic,int * x,int * y)474 void FcitxInstanceGetWindowPosition(FcitxInstance* instance, FcitxInputContext* ic, int* x, int* y)
475 {
476 if (ic == NULL)
477 return;
478
479 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
480 if (pfrontend == NULL)
481 return;
482 FcitxFrontend* frontend = (*pfrontend)->frontend;
483 int rx, ry, rw, rh;
484 if (frontend->GetWindowRect) {
485 frontend->GetWindowRect((*pfrontend)->addonInstance, ic,
486 &rx, &ry, &rw, &rh);
487 *x = rx;
488 *y = ry + rh;
489 }
490 }
491
492 FCITX_EXPORT_API
FcitxInstanceGetWindowRect(FcitxInstance * instance,FcitxInputContext * ic,int * x,int * y,int * w,int * h)493 void FcitxInstanceGetWindowRect(FcitxInstance* instance, FcitxInputContext* ic, int* x, int* y, int* w, int* h)
494 {
495 if (ic == NULL)
496 return;
497
498 FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid);
499 if (pfrontend == NULL)
500 return;
501 FcitxFrontend* frontend = (*pfrontend)->frontend;
502 if (frontend->GetWindowRect) {
503 frontend->GetWindowRect((*pfrontend)->addonInstance, ic, x, y, w, h);
504 }
505 }
506
507 FCITX_EXPORT_API
FcitxInstanceLoadFrontend(FcitxInstance * instance)508 boolean FcitxInstanceLoadFrontend(FcitxInstance* instance)
509 {
510 UT_array* addons = &instance->addons;
511 UT_array* frontends = &instance->frontends;
512 FcitxAddon *addon;
513 int frontendindex = 0;
514 utarray_clear(frontends);
515 for (addon = (FcitxAddon *) utarray_front(addons);
516 addon != NULL;
517 addon = (FcitxAddon *) utarray_next(addons, addon)) {
518 if (addon->bEnabled && addon->category == AC_FRONTEND) {
519 char *modulePath;
520 switch (addon->type) {
521 case AT_SHAREDLIBRARY: {
522 FILE *fp = FcitxXDGGetLibFile(addon->library, "r", &modulePath);
523 void *handle;
524 FcitxFrontend* frontend;
525 if (!fp)
526 break;
527 fclose(fp);
528 handle = dlopen(modulePath, RTLD_NOW | RTLD_NODELETE | (addon->loadLocal ? RTLD_LOCAL : RTLD_GLOBAL));
529 if (!handle) {
530 FcitxLog(ERROR, _("Frontend: open %s fail %s") , modulePath , dlerror());
531 break;
532 }
533
534 if (!FcitxCheckABIVersion(handle, addon->name)) {
535 FcitxLog(ERROR, "%s ABI Version Error", addon->name);
536 dlclose(handle);
537 break;
538 }
539
540 frontend = FcitxGetSymbol(handle, addon->name, "frontend");
541 if (!frontend || !frontend->Create) {
542 FcitxLog(ERROR, _("Frontend: bad frontend"));
543 dlclose(handle);
544 break;
545 }
546 if ((addon->addonInstance = frontend->Create(instance, frontendindex)) == NULL) {
547 dlclose(handle);
548 break;
549 }
550 if (instance->loadingFatalError)
551 return false;
552 addon->frontend = frontend;
553 frontendindex ++;
554 utarray_push_back(frontends, &addon);
555 }
556 break;
557 default:
558 break;
559 }
560 free(modulePath);
561 }
562 }
563
564 if (utarray_len(&instance->frontends) <= 0) {
565 FcitxLog(ERROR, _("No available frontend"));
566 return false;
567 }
568 return true;
569 }
570
571 FCITX_EXPORT_API
FcitxInstanceICSupportPreedit(FcitxInstance * instance,FcitxInputContext * ic)572 boolean FcitxInstanceICSupportPreedit(FcitxInstance* instance, FcitxInputContext* ic)
573 {
574 if (!ic || ((ic->contextCaps & CAPACITY_PREEDIT) == 0
575 || !instance->profile->bUsePreedit
576 || AppPreeditBlacklisted(instance, ic)))
577 return false;
578 return true;
579 }
580
AppPreeditBlacklisted(FcitxInstance * instance,FcitxInputContext * ic)581 static boolean AppPreeditBlacklisted(
582 FcitxInstance* instance, FcitxInputContext* ic)
583 {
584 FcitxInputContext2* ic2 = (FcitxInputContext2*) ic;
585 if (ic2->mayUsePreedit != Tri_Unknown)
586 return ic2->mayUsePreedit;
587
588 ic2->mayUsePreedit = false;
589
590 const char* prgname = ic2->prgname;
591 if (!prgname)
592 return false;
593
594 utarray_foreach(re, instance->no_preedit_app_list, regex_t*) {
595 if (regexec(*re, prgname, 0, NULL, 0) == 0) {
596 /* matched */
597 ic2->mayUsePreedit = true;
598 return true;
599 }
600 }
601
602 return false;
603 }
604
605 // kate: indent-mode cstyle; space-indent on; indent-width 0;
606