1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/inmethod.c,v 1.14 2011/06/14 02:32:18 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_INMETHOD_C_
22 
23 #include "tgifdefs.h"
24 
25 #ifndef _NO_XCIN
26 #include "cli_xcin.e"
27 #endif /* ~_NO_XCIN */
28 #ifndef _NO_CHINPUT
29 #include "chinput.e"
30 #endif /* ~_NO_CHINPUT */
31 #ifndef _NO_KINPUT
32 #include "convkinput.e"
33 #endif /* ~_NO_KINPUT */
34 #ifndef _NO_XIM
35 #include "convxim.e"
36 #endif /* ~_NO_XIM */
37 #ifndef _NO_TGTWB5
38 #include "tgtwb5.e"
39 #endif /* ~_NO_TGTWB5 */
40 
41 #include "dialog.e"
42 #include "inmethod.e"
43 #include "msg.e"
44 #include "util.e"
45 #include "setup.e"
46 #include "strtbl.e"
47 #include "tidget.e"
48 
49 #ifndef _NO_DL_SUPPORT
50 #define CLOSE_DL(handle) dlclose(handle)
51 #define OPEN_DL(path,flag) dlopen((path),(flag))
52 #define GET_DL_SYM(handle,symbol) dlsym((handle),(symbol))
53 #ifndef RTLD_NOW
54 #define OPEN_DL_MODE 1
55 #else /* RTLD_NOW */
56 #define OPEN_DL_MODE (RTLD_NOW|RTLD_GLOBAL)
57 #endif /* ~RTLD_NOW */
58 #else /* _NO_DL_SUPPORT */
59 #define CLOSE_DL(handle)
60 #define OPEN_DL(path,flag) NULL
61 #define GET_DL_SYM(handle,symbol) NULL
62 #define OPEN_DL_MODE 0
63 #endif /* ~_NO_DL_SUPPORT */
64 
65 int gnInputMethod=TGIM_NONE; /* one of TGIM_* */
66 int gnOverTheSpot=FALSE;
67 
68 int cmdLineHasInputMethod=FALSE;
69 int cmdLineDoubleByteInputMethod=FALSE;
70 char cmdLineInputMethod[MAXSTRING];
71 
72 static int gnInputMethodIndex=INVALID;
73 static int gnSingleOrDoubleByteInputMethod=0;
74 
75 typedef void (CleanUpFunc)ARGS_DECL((Display *dpy, Window win));
76 typedef int (InitFunc)ARGS_DECL((Display *dpy, Window win, char *arg));
77 typedef int (FocusInFunc)ARGS_DECL((Display *dpy, Window win));
78 typedef int (FocusOutFunc)ARGS_DECL((Display *dpy, Window win));
79 typedef int (SendKeyFunc)ARGS_DECL((Display *dpy, Window win,
80                                     XKeyEvent *key_ev, char *buf));
81 typedef int (ConvPropertyFunc)ARGS_DECL((Display *dpy, Window win,
82                                          XPropertyEvent *prop_ev,
83                                          char **ppsz_buf));
84 typedef int (ExpectCMFunc)ARGS_DECL((Display *dpy, Window win));
85 typedef int (HandleCMFunc)ARGS_DECL((Display *dpy, Window win,
86                                      XClientMessageEvent *cm_ev,
87                                      XKeyEvent *key_ev, char *buf));
88 typedef int (ActivateOnCntrlSpaceFunc)ARGS_DECL((Display *dpy, Window win));
89 typedef int (HandleCntrlSpaceFunc)ARGS_DECL((Display *dpy, Window win));
90 typedef int (DeactivateOnCreateTextFunc)ARGS_DECL((Display *dpy, Window win));
91 typedef int (HandleCreateTextFunc)ARGS_DECL((Display *dpy, Window win));
92 typedef int (TellCursorPosFunc)ARGS_DECL((Display *dpy, Window win,
93                                           int cur_x, int cur_y));
94 typedef int (ExpectNextEventFunc)ARGS_DECL((Display *dpy, Window win));
95 typedef int (HandleNextEventFunc)ARGS_DECL((Display *dpy, Window win,
96                                             XEvent *ev));
97 typedef int (HandleNewCurTextFunc)ARGS_DECL((Display *dpy, Window win));
98 typedef int (ExpectLookupStringFunc)ARGS_DECL((Display *dpy, Window win));
99 typedef int (HandleLookupStringFunc)ARGS_DECL((Display *dpy, Window win,
100                                                XKeyEvent *key_ev, char *psz_buf,
101                                                int buf_size, KeySym *p_key_sym,
102                                                int *pn_has_ch));
103 
104 typedef struct tagIMInfo {
105    char *pszName;
106    int nInputMethod;
107    int nSingleDouble;
108    CleanUpFunc *pCleanUpFunc;
109    InitFunc *pInitFunc;
110    FocusInFunc *pFocusInFunc;
111    FocusOutFunc *pFocusOutFunc;
112    SendKeyFunc *pSendKeyFunc;
113    ConvPropertyFunc *pConvPropertyFunc;
114    ExpectCMFunc *pExpectCMFunc;
115    HandleCMFunc *pHandleCMFunc;
116    ActivateOnCntrlSpaceFunc *pActivateOnCntrlSpaceFunc;
117    HandleCntrlSpaceFunc *pHandleCntrlSpaceFunc;
118    DeactivateOnCreateTextFunc *pDeactivateOnCreateTextFunc;
119    HandleCreateTextFunc *pHandleCreateTextFunc;
120    TellCursorPosFunc *pTellCursorPosFunc;
121    ExpectNextEventFunc *pExpectNextEventFunc;
122    HandleNextEventFunc *pHandleNextEventFunc;
123    HandleNewCurTextFunc *pHandleNewCurTextFunc;
124    ExpectLookupStringFunc *pExpectLookupStringFunc;
125    HandleLookupStringFunc *pHandleLookupStringFunc;
126 } IMInfo;
127 
128 static IMInfo *gpIMInfo=NULL;
129 
130 /* --------------------- xcin Routines --------------------- */
131 
132 #ifndef _NO_XCIN
133 static
XcinInit(dpy,win,arg)134 int XcinInit(dpy, win, arg)
135    Display *dpy;
136    Window win;
137    char *arg;
138 {
139    return TRUE;
140 }
141 
142 static
XcinFocusIn(dpy,win)143 int XcinFocusIn(dpy, win)
144    Display *dpy;
145    Window win;
146 {
147    Tg_send_FocusIn(dpy, win);
148    return TRUE;
149 }
150 
151 static
XcinFocusOut(dpy,win)152 int XcinFocusOut(dpy, win)
153    Display *dpy;
154    Window win;
155 {
156    Tg_send_FocusOut(dpy, win);
157    return TRUE;
158 }
159 
160 static
XcinSendKey(dpy,win,key_ev,buf)161 int XcinSendKey(dpy, win, key_ev, buf)
162    Display *dpy;
163    Window win;
164    XKeyEvent *key_ev;
165    char *buf;
166 {
167    return Tg_send_key(dpy, win, key_ev, buf);
168 }
169 
170 static
XcinExpectCM(dpy,win)171 int XcinExpectCM(dpy, win)
172    Display *dpy;
173    Window win;
174 {
175    return FALSE;
176 }
177 #endif /* ~_NO_XCIN */
178 
179 /* --------------------- chinput Routines --------------------- */
180 
181 #ifndef _NO_CHINPUT
182 static
ChinputInit(dpy,win,arg)183 int ChinputInit(dpy, win, arg)
184    Display *dpy;
185    Window win;
186    char *arg;
187 {
188    return (Tg_HZclientInit(dpy)==0);
189 }
190 
191 static
ChinputFocusIn(dpy,win)192 int ChinputFocusIn(dpy, win)
193    Display *dpy;
194    Window win;
195 {
196    return TRUE;
197 }
198 
199 static
ChinputFocusOut(dpy,win)200 int ChinputFocusOut(dpy, win)
201    Display *dpy;
202    Window win;
203 {
204    return TRUE;
205 }
206 
207 static
ChinputSendKey(dpy,win,key_ev,buf)208 int ChinputSendKey(dpy, win, key_ev, buf)
209    Display *dpy;
210    Window win;
211    XKeyEvent *key_ev;
212    char *buf;
213 {
214    Tg_HZsendKey(dpy, win, key_ev);
215    *buf = '\0';
216    return TRUE;
217 }
218 
219 static
ChinputExpectCM(dpy,win)220 int ChinputExpectCM(dpy, win)
221    Display *dpy;
222    Window win;
223 {
224    return TRUE;
225 }
226 
227 static
ChinputHandleCM(dpy,win,cm_ev,key_ev,buf)228 int ChinputHandleCM(dpy, win, cm_ev, key_ev, buf)
229    Display *dpy;
230    Window win;
231    XClientMessageEvent *cm_ev;
232    XKeyEvent *key_ev;
233    char *buf;
234 {
235    return Tg_HZhandleCM(cm_ev, key_ev, buf);
236 }
237 #endif /* ~_NO_CHINPUT */
238 
239 /* --------------------- kinput Routines --------------------- */
240 
241 #ifndef _NO_KINPUT
242 static
KinputCleanUp(dpy,win)243 void KinputCleanUp(dpy, win)
244    Display *dpy;
245    Window win;
246 {
247    imProtocol = IM_NONE;
248 }
249 
250 static
KinputInit(dpy,win,arg)251 int KinputInit(dpy, win, arg)
252    Display *dpy;
253    Window win;
254    char *arg;
255 {
256    char *c_ptr=NULL;
257 
258    copyAndPasteJIS = FALSE;
259    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "CopyAndPasteJIS")) != NULL &&
260          UtilStrICmp(c_ptr, "true") == 0) {
261       copyAndPasteJIS = TRUE;
262    }
263    gnOverTheSpot = FALSE;
264    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "PreeditType")) != NULL &&
265          UtilStrICmp(c_ptr, "overthespot") == 0) {
266       gnOverTheSpot = TRUE;
267    }
268    KinputSetConvOverSpot(gnOverTheSpot);
269 
270    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "ConvSelection")) != NULL) {
271       UtilTrimBlanks(c_ptr);
272       strncpy(kinputConvSelName, c_ptr, MAXSTRING-1);
273       kinputConvSelName[MAXSTRING-1] = '\0';
274    }
275 
276    imProtocol = IM_KINPUT;
277    return TRUE;
278 }
279 
280 static
KinputFocusIn(dpy,win)281 int KinputFocusIn(dpy, win)
282    Display *dpy;
283    Window win;
284 {
285    return TRUE;
286 }
287 
288 static
KinputFocusOut(dpy,win)289 int KinputFocusOut(dpy, win)
290    Display *dpy;
291    Window win;
292 {
293    return TRUE;
294 }
295 
296 static
KinputSendKey(dpy,win,key_ev,buf)297 int KinputSendKey(dpy, win, key_ev, buf)
298    Display *dpy;
299    Window win;
300    XKeyEvent *key_ev;
301    char *buf;
302 {
303    return FALSE;
304 }
305 
306 static
KinputConvProperty(dpy,win,prop_ev,ppsz_buf)307 int KinputConvProperty(dpy, win, prop_ev, ppsz_buf)
308    Display *dpy;
309    Window win;
310    XPropertyEvent *prop_ev;
311    char **ppsz_buf;
312 {
313    char *c_ptr=KinputCheckConvProperty(dpy, win, prop_ev);
314 
315    if (c_ptr != NULL && ppsz_buf != NULL) {
316       *ppsz_buf = c_ptr;
317       return TRUE;
318    }
319    return FALSE;
320 }
321 
322 static
KinputExpectCM(dpy,win)323 int KinputExpectCM(dpy, win)
324    Display *dpy;
325    Window win;
326 {
327    return (win == drawWindow ||
328          (TidgetHasFocus() && win == TidgetGetFocusWindow()));
329 }
330 
331 static
KinputHandleCM(dpy,win,cm_ev,key_ev,buf)332 int KinputHandleCM(dpy, win, cm_ev, key_ev, buf)
333    Display *dpy;
334    Window win;
335    XClientMessageEvent *cm_ev;
336    XKeyEvent *key_ev;
337    char *buf;
338 {
339    KinputCheckClientMessage(dpy, win, cm_ev);
340    return FALSE;
341 }
342 
343 static
KinputActiveOnCntrlSpace(dpy,win)344 int KinputActiveOnCntrlSpace(dpy, win)
345    Display *dpy;
346    Window win;
347 {
348    return (win == drawWindow ||
349          (TidgetHasFocus() && win == TidgetGetFocusWindow()));
350 }
351 
352 static
KinputHandleCntrlSpace(dpy,win)353 int KinputHandleCntrlSpace(dpy, win)
354    Display *dpy;
355    Window win;
356 {
357    KinputBeginConversion(dpy, win);
358    return TRUE;
359 }
360 
361 static
KinputDeactiveOnCreateText(dpy,win)362 int KinputDeactiveOnCreateText(dpy, win)
363    Display *dpy;
364    Window win;
365 {
366    return TRUE;
367 }
368 
369 static
KinputHandleCreateText(dpy,win)370 int KinputHandleCreateText(dpy, win)
371    Display *dpy;
372    Window win;
373 {
374    KinputEndConversion(dpy, win);
375    return TRUE;
376 }
377 
378 static
KinputTellCursorPos(dpy,win,cur_x,cur_y)379 int KinputTellCursorPos(dpy, win, cur_x, cur_y)
380    Display *dpy;
381    Window win;
382    int cur_x, cur_y;
383 {
384    KinputTellCursorPosition(dpy, win, cur_x, cur_y);
385    return TRUE;
386 }
387 #endif /* ~_NO_KINPUT */
388 
389 /* --------------------- xim Routines --------------------- */
390 
391 #ifndef _NO_XIM
392 static
XimCleanUp(dpy,win)393 void XimCleanUp(dpy, win)
394    Display *dpy;
395    Window win;
396 {
397    XIMCleanUp();
398 }
399 
400 static
XimInit(dpy,win,arg)401 int XimInit(dpy, win, arg)
402    Display *dpy;
403    Window win;
404    char *arg;
405 {
406    char *c_ptr=NULL;
407    XIMInit();
408    gnOverTheSpot = FALSE;
409    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "PreeditType")) != NULL &&
410          UtilStrICmp(c_ptr, "overthespot") == 0) {
411       gnOverTheSpot = TRUE;
412    }
413    XIMSetConvOverSpot(gnOverTheSpot);
414    return TRUE;
415 }
416 
417 static
XimFocusIn(dpy,win)418 int XimFocusIn(dpy, win)
419    Display *dpy;
420    Window win;
421 {
422    XIMSetICFocus(dpy, win);
423    return TRUE;
424 }
425 
426 static
XimFocusOut(dpy,win)427 int XimFocusOut(dpy, win)
428    Display *dpy;
429    Window win;
430 {
431    XIMUnsetICFocus(win);
432    return TRUE;
433 }
434 
435 static
XimDeactiveOnCreateText(dpy,win)436 int XimDeactiveOnCreateText(dpy, win)
437    Display *dpy;
438    Window win;
439 {
440    return TRUE;
441 }
442 
443 static
XimHandleCreateText(dpy,win)444 int XimHandleCreateText(dpy, win)
445    Display *dpy;
446    Window win;
447 {
448    XIMUnsetICFocus(win);
449    return TRUE;
450 }
451 
452 static
XimExpectNextEvent(dpy,win)453 int XimExpectNextEvent(dpy, win)
454    Display *dpy;
455    Window win;
456 {
457    return (win == drawWindow ||
458          (TidgetHasFocus() && win == TidgetGetFocusWindow()));
459 }
460 
461 static
XimHandleNextEvent(dpy,win,ev)462 int XimHandleNextEvent(dpy, win, ev)
463    Display *dpy;
464    Window win;
465    XEvent *ev;
466 {
467    XIMNextEvent(dpy, win, ev);
468    return TRUE;
469 }
470 
471 static
XimHandleNewCurText(dpy,win)472 int XimHandleNewCurText(dpy, win)
473    Display *dpy;
474    Window win;
475 {
476    XIMSetICFocus(dpy, win);
477    return TRUE;
478 }
479 
480 static
XimExpectLookupString(dpy,win)481 int XimExpectLookupString(dpy, win)
482    Display *dpy;
483    Window win;
484 {
485    return (win == drawWindow ||
486          (TidgetHasFocus() && win == TidgetGetFocusWindow()));
487 }
488 
489 static XIMStatus c_stat;
490 
491 static
XimHandleLookupString(dpy,win,key_ev,psz_buf,buf_size,p_key_sym,pn_has_ch)492 int XimHandleLookupString(dpy, win, key_ev, psz_buf, buf_size, p_key_sym,
493       pn_has_ch)
494    Display *dpy;
495    Window win;
496    XKeyEvent *key_ev;
497    char *psz_buf;
498    int buf_size;
499    KeySym *p_key_sym;
500    int *pn_has_ch;
501 {
502    *pn_has_ch = XIMLookupString(key_ev, psz_buf, buf_size, p_key_sym, &c_stat);
503    return TRUE;
504 }
505 
506 static
XimTellCursorPos(dpy,win,cur_x,cur_y)507 int XimTellCursorPos(dpy, win, cur_x, cur_y)
508    Display *dpy;
509    Window win;
510    int cur_x, cur_y;
511 {
512    XIMTellCursorPosition(dpy, win, cur_x, cur_y);
513    return TRUE;
514 }
515 #endif /* ~_NO_XIM */
516 
517 /* --------------------- tgtwb5 Routines --------------------- */
518 
519 #ifndef _NO_TGTWB5
520 static
Tgtwb5CleanUp(dpy,win)521 void Tgtwb5CleanUp(dpy, win)
522    Display *dpy;
523    Window win;
524 {
525    Tgtwb5_CleanUp(dpy, win);
526 }
527 
528 static
Tgtwb5Init(dpy,win,arg)529 int Tgtwb5Init(dpy, win, arg)
530    Display *dpy;
531    Window win;
532    char *arg;
533 {
534    return Tgtwb5_Init(dpy, win, arg);
535 }
536 
537 static
Tgtwb5SendKey(dpy,win,key_ev,buf)538 int Tgtwb5SendKey(dpy, win, key_ev, buf)
539    Display *dpy;
540    Window win;
541    XKeyEvent *key_ev;
542    char *buf;
543 {
544    return Tgtwb5_SendKey(dpy, win, key_ev, buf);
545 }
546 
547 static
Tgtwb5ExpectCM(dpy,win)548 int Tgtwb5ExpectCM(dpy, win)
549    Display *dpy;
550    Window win;
551 {
552    return FALSE;
553 }
554 
555 static
Tgtwb5ActiveOnCntrlSpace(dpy,win)556 int Tgtwb5ActiveOnCntrlSpace(dpy, win)
557    Display *dpy;
558    Window win;
559 {
560    return (win == drawWindow ||
561          (TidgetHasFocus() && win == TidgetGetFocusWindow()));
562 }
563 
564 static
Tgtwb5HandleCntrlSpace(dpy,win)565 int Tgtwb5HandleCntrlSpace(dpy, win)
566    Display *dpy;
567    Window win;
568 {
569    return Tgtwb5_HandleCntrlSpace(dpy, win);
570 }
571 
572 static
Tgtwb5DeactiveOnCreateText(dpy,win)573 int Tgtwb5DeactiveOnCreateText(dpy, win)
574    Display *dpy;
575    Window win;
576 {
577    return TRUE;
578 }
579 
580 static
Tgtwb5HandleCreateText(dpy,win)581 int Tgtwb5HandleCreateText(dpy, win)
582    Display *dpy;
583    Window win;
584 {
585    Tgtwb5_HandleCreateText(dpy, win);
586    return TRUE;
587 }
588 #endif /* ~_NO_XCIN */
589 
590 /* --------------------- Global Routines --------------------- */
591 
592 static struct tagIMInfo gstIMInfo[] = {
593 #ifndef _NO_XCIN
594    { "xcin", TGIM_XCIN, TGIM_DBIM,
595      NULL, XcinInit, XcinFocusIn, XcinFocusOut,
596      XcinSendKey, NULL, XcinExpectCM, NULL,
597      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
598    },
599 #endif /* ~_NO_XCIN */
600 #ifndef _NO_CHINPUT
601    { "chinput", TGIM_CHINPUT, TGIM_DBIM,
602      NULL, ChinputInit, ChinputFocusIn, ChinputFocusOut,
603      ChinputSendKey, NULL, ChinputExpectCM, ChinputHandleCM,
604      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
605    },
606 #endif /* ~_NO_CHINPUT */
607 #ifndef _NO_KINPUT
608    { "kinput2", TGIM_KINPUT, TGIM_DBIM,
609      KinputCleanUp, KinputInit, KinputFocusIn, KinputFocusOut,
610      KinputSendKey, KinputConvProperty, KinputExpectCM, KinputHandleCM,
611      KinputActiveOnCntrlSpace, KinputHandleCntrlSpace,
612      KinputDeactiveOnCreateText, KinputHandleCreateText,
613      KinputTellCursorPos, NULL, NULL, NULL, NULL, NULL
614    },
615 #endif /* ~_NO_KINPUT */
616 #ifndef _NO_XIM
617    { "xim", TGIM_XIM, (TGIM_DBIM|TGIM_SBIM),
618      XimCleanUp, XimInit, XimFocusIn, XimFocusOut,
619      NULL, NULL, NULL, NULL, NULL, NULL,
620      XimDeactiveOnCreateText, XimHandleCreateText,
621      XimTellCursorPos, XimExpectNextEvent, XimHandleNextEvent,
622      XimHandleNewCurText, XimExpectLookupString, XimHandleLookupString
623    },
624 #endif /* ~_NO_XIM */
625 #ifndef _NO_TGTWB5
626    { "tgtwb5/tgchgb", TGIM_TGTWB5, TGIM_DBIM,
627      Tgtwb5CleanUp, Tgtwb5Init, NULL, NULL,
628      Tgtwb5SendKey, NULL, Tgtwb5ExpectCM, NULL,
629      Tgtwb5ActiveOnCntrlSpace, Tgtwb5HandleCntrlSpace,
630      Tgtwb5DeactiveOnCreateText, Tgtwb5HandleCreateText,
631      NULL, NULL, NULL, NULL, NULL, NULL
632    },
633 #endif /* ~_NO_TGTWB5 */
634    { NULL, TGIM_NONE, 0, NULL, NULL, NULL, NULL,
635      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
636      NULL, NULL, NULL, NULL, NULL
637    }
638 };
639 
640 static void *gpLibIdnHandle=NULL;
641 static Tgim_stringprep_convert_Func *gpfn_stringprep_convert=NULL;
642 
643 static
CleanUpTgim_stringprep_convert()644 void CleanUpTgim_stringprep_convert()
645 {
646    if (gpLibIdnHandle != NULL) {
647       gpfn_stringprep_convert = NULL;
648       CLOSE_DL(gpLibIdnHandle);
649       gpLibIdnHandle = NULL;
650    }
651 }
652 
653 static
InitTgim_stringprep_convert()654 void InitTgim_stringprep_convert()
655 {
656 #if (!defined(_NO_IDNLIB) || defined(HAVE_LIBZ))
657    gpLibIdnHandle = OPEN_DL("libidn.so", OPEN_DL_MODE);
658    if (gpLibIdnHandle != NULL) {
659       gpfn_stringprep_convert =
660             (Tgim_stringprep_convert_Func*)GET_DL_SYM(gpLibIdnHandle,
661             "stringprep_convert");
662       if (gpfn_stringprep_convert == NULL) {
663          CLOSE_DL(gpLibIdnHandle);
664          gpLibIdnHandle = NULL;
665       }
666    }
667 #endif /* (!defined(_NO_IDNLIB) || defined(HAVE_LIBZ)) */
668 }
669 
Tgim_has_stringprep_convert()670 int Tgim_has_stringprep_convert()
671 {
672 #if (!defined(_NO_IDNLIB) || defined(HAVE_LIBZ))
673    if (gpLibIdnHandle != NULL && gpfn_stringprep_convert != NULL) {
674       return TRUE;
675    }
676 #endif /* (!defined(_NO_IDNLIB) || defined(HAVE_LIBZ)) */
677    return FALSE;
678 }
679 
Tgim_stringprep_convert(const char * str,const char * to_codeset,const char * from_codeset)680 char *Tgim_stringprep_convert(const char *str, const char *to_codeset,
681       const char *from_codeset)
682 {
683 #if (!defined(_NO_IDNLIB) || defined(HAVE_LIBZ))
684    if (gpLibIdnHandle != NULL && gpfn_stringprep_convert != NULL) {
685        return (gpfn_stringprep_convert)(str, to_codeset, from_codeset);
686    }
687 #endif /* (!defined(_NO_IDNLIB) || defined(HAVE_LIBZ)) */
688    return NULL;
689 }
690 
CleanUpInputMethods()691 void CleanUpInputMethods()
692 {
693    CleanUpTgim_stringprep_convert();
694    if (gnInputMethodIndex != INVALID &&
695          gstIMInfo[gnInputMethodIndex].pCleanUpFunc != NULL) {
696       (gstIMInfo[gnInputMethodIndex].pCleanUpFunc)(mainDisplay, mainWindow);
697    }
698    gnInputMethodIndex = INVALID;
699    cmdLineHasInputMethod = FALSE;
700    cmdLineDoubleByteInputMethod = FALSE;
701    *cmdLineInputMethod = '\0';
702    gpIMInfo = NULL;
703    gnSingleOrDoubleByteInputMethod = 0;
704 }
705 
InitInputMethods()706 int InitInputMethods()
707 {
708    char *psz=NULL, single_double=0;
709 
710    gnInputMethod = gnInputMethodIndex = INVALID;
711    if (cmdLineHasInputMethod) {
712       UtilTrimBlanks(cmdLineInputMethod);
713       psz = cmdLineInputMethod;
714       single_double = (cmdLineDoubleByteInputMethod ? TGIM_DBIM : TGIM_SBIM);
715    } else {
716       psz = XGetDefault(mainDisplay, TOOL_NAME, "DoubleByteInputMethod");
717       if (psz == NULL) {
718          psz = XGetDefault(mainDisplay, TOOL_NAME, "SingleByteInputMethod");
719          single_double = TGIM_SBIM;
720       } else {
721          if (XGetDefault(mainDisplay, TOOL_NAME, "SingleByteInputMethod") !=
722                NULL) {
723             sprintf(gszMsgBox, TgLoadString(STID_TWO_XDEF_ONE_IGNORED),
724                   TOOL_NAME, "DoubleByteInputMethod", TOOL_NAME,
725                   "SingleByteInputMethod", TOOL_NAME, "SingleByteInputMethod");
726             Msg(gszMsgBox);
727             fprintf(stderr, "%s\n", gszMsgBox);
728          }
729          single_double = TGIM_DBIM;
730       }
731    }
732    gnSingleOrDoubleByteInputMethod = single_double;
733 
734    if (psz != NULL) {
735       IMInfo *pIMInfo=gstIMInfo;
736       char *psz_comma=strchr(psz, ',');
737       int i=0;
738 
739       if (psz_comma != NULL) *psz_comma = '\0';
740       for ( ; pIMInfo->pszName != NULL; pIMInfo++, i++) {
741          char *psz_slash=strchr(pIMInfo->pszName,'/');
742 
743          if (psz_slash == NULL) {
744             if (UtilStrICmp(psz, pIMInfo->pszName) == 0 &&
745                   (single_double & pIMInfo->nSingleDouble) == single_double) {
746                gnInputMethod = pIMInfo->nInputMethod;
747                gnInputMethodIndex = i;
748                gpIMInfo = pIMInfo;
749                if (gstIMInfo[gnInputMethodIndex].pInitFunc != NULL) {
750                   if (psz_comma == NULL) {
751                      if (!((gstIMInfo[gnInputMethodIndex].pInitFunc)(mainDisplay,
752                            mainWindow, NULL))) {
753                         /* may not be a problem */
754                      }
755                   } else {
756                      if (!((gstIMInfo[gnInputMethodIndex].pInitFunc)(mainDisplay,
757                            mainWindow, &psz_comma[1]))) {
758                         /* may not be a problem */
759                      }
760                   }
761                }
762                break;
763             }
764          } else {
765             char *psz_dup=UtilStrDup(pIMInfo->pszName), *psz_cur=NULL;
766             int done=FALSE;
767 
768             if (psz_dup == NULL) FailAllocMessage();
769             psz_cur = psz_dup;
770             psz_slash = strchr(psz_cur, '/');
771             while (!done) {
772                if (psz_slash != NULL) *psz_slash = '\0';
773                if (UtilStrICmp(psz, psz_cur) == 0 &&
774                      (single_double & pIMInfo->nSingleDouble) == single_double) {
775                   gnInputMethod = pIMInfo->nInputMethod;
776                   gnInputMethodIndex = i;
777                   gpIMInfo = pIMInfo;
778                   if (gstIMInfo[gnInputMethodIndex].pInitFunc != NULL) {
779                      if (psz_comma == NULL) {
780                         if (!((gstIMInfo[gnInputMethodIndex].pInitFunc)(mainDisplay,
781                               mainWindow, NULL))) {
782                            /* may not be a problem */
783                         }
784                      } else {
785                         if (!((gstIMInfo[gnInputMethodIndex].pInitFunc)(mainDisplay,
786                               mainWindow, &psz_comma[1]))) {
787                            /* may not be a problem */
788                         }
789                      }
790                   }
791                   done = TRUE;
792                }
793                if (psz_slash != NULL) {
794                   *psz_slash++ = '/';
795                   psz_cur = psz_slash;
796                   psz_slash = strchr(psz_cur, '/');
797                } else {
798                   break;
799                }
800             }
801             UtilFree(psz_dup);
802             if (done) {
803                break;
804             }
805          }
806       }
807       if (psz_comma != NULL) *psz_comma++ = ',';
808 
809       if (gnInputMethod == INVALID) {
810          if (single_double == TGIM_DBIM) {
811             fprintf(stderr, TgLoadString(STID_DBIM_UNSUPPORTED), psz);
812          } else {
813             fprintf(stderr, TgLoadString(STID_SBIM_UNSUPPORTED), psz);
814          }
815          fprintf(stderr, "\n");
816       }
817    }
818    if (gnSingleOrDoubleByteInputMethod == TGIM_SBIM &&
819          gnInputMethod != INVALID) {
820       InitTgim_stringprep_convert();
821    }
822    return TRUE;
823 }
824 
ResetInputMethod()825 int ResetInputMethod()
826 {
827    int rc=FALSE;
828 
829    if (gpIMInfo == NULL) return FALSE;
830 
831    sprintf(gszMsgBox, TgLoadString(STID_OK_TO_RESET_GIVEN_IM),
832          gpIMInfo->pszName);
833    if (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB) != MB_ID_YES) {
834       return FALSE;
835    }
836    CleanUpInputMethods();
837    rc = InitInputMethods();
838 
839    sprintf(gszMsgBox, TgLoadString(STID_GIVEN_IM_RESETED), gpIMInfo->pszName);
840    Msg(gszMsgBox);
841 
842    return rc;
843 }
844 
InputMethodTypeMatched(double_byte)845 int InputMethodTypeMatched(double_byte)
846    int double_byte;
847 {
848    if (gnInputMethodIndex == INVALID || gpIMInfo == NULL) return FALSE;
849 
850    if (double_byte) {
851       return (gnSingleOrDoubleByteInputMethod == TGIM_DBIM &&
852             (gpIMInfo->nSingleDouble & TGIM_DBIM) == TGIM_DBIM);
853    } else {
854       return (gnSingleOrDoubleByteInputMethod == TGIM_SBIM &&
855             (gpIMInfo->nSingleDouble & TGIM_SBIM) == TGIM_SBIM);
856    }
857 }
858 
tgIMFocusIn(dpy,win)859 int tgIMFocusIn(dpy, win)
860    Display *dpy;
861    Window win;
862 {
863    if (gnInputMethodIndex == INVALID ||
864          gstIMInfo[gnInputMethodIndex].pFocusInFunc == NULL) {
865       return FALSE;
866    }
867    return ((gstIMInfo[gnInputMethodIndex].pFocusInFunc)(dpy, win));
868 }
869 
tgIMFocusOut(dpy,win)870 int tgIMFocusOut(dpy, win)
871    Display *dpy;
872    Window win;
873 {
874    if (gnInputMethodIndex == INVALID ||
875          gstIMInfo[gnInputMethodIndex].pFocusOutFunc == NULL) {
876       return FALSE;
877    }
878    return ((gstIMInfo[gnInputMethodIndex].pFocusOutFunc)(dpy, win));
879 }
880 
tgIMTranslateKeyEvent(dpy,win,key_ev,buf)881 int tgIMTranslateKeyEvent(dpy, win, key_ev, buf)
882    Display *dpy;
883    Window win;
884    XKeyEvent *key_ev;
885    char *buf;
886 {
887    if (gnInputMethodIndex == INVALID ||
888          gstIMInfo[gnInputMethodIndex].pSendKeyFunc == NULL) {
889       return FALSE;
890    }
891    return ((gstIMInfo[gnInputMethodIndex].pSendKeyFunc)(dpy, win, key_ev, buf));
892 }
893 
tgIMConvertProperty(dpy,win,prop_ev,ppsz_buf)894 int tgIMConvertProperty(dpy, win, prop_ev, ppsz_buf)
895    Display *dpy;
896    Window win;
897    XPropertyEvent *prop_ev;
898    char **ppsz_buf;
899 {
900    if (gnInputMethodIndex == INVALID ||
901          gstIMInfo[gnInputMethodIndex].pConvPropertyFunc == NULL) {
902       return FALSE;
903    }
904    return ((gstIMInfo[gnInputMethodIndex].pConvPropertyFunc)(dpy, win, prop_ev,
905          ppsz_buf));
906 }
907 
tgIMExpectClientMessage(dpy,win)908 int tgIMExpectClientMessage(dpy, win)
909    Display *dpy;
910    Window win;
911 {
912    if (gnInputMethodIndex == INVALID ||
913          gstIMInfo[gnInputMethodIndex].pExpectCMFunc == NULL) {
914       return FALSE;
915    }
916    return ((gstIMInfo[gnInputMethodIndex].pExpectCMFunc)(dpy, win));
917 }
918 
tgIMHandleClientMessage(dpy,win,cm_ev,key_ev,buf)919 int tgIMHandleClientMessage(dpy, win, cm_ev, key_ev, buf)
920    Display *dpy;
921    Window win;
922    XClientMessageEvent *cm_ev;
923    XKeyEvent *key_ev;
924    char *buf;
925 {
926    if (gnInputMethodIndex == INVALID ||
927          gstIMInfo[gnInputMethodIndex].pHandleCMFunc == NULL) {
928       return FALSE;
929    }
930    return ((gstIMInfo[gnInputMethodIndex].pHandleCMFunc)(dpy, win, cm_ev,
931          key_ev, buf));
932 }
933 
tgIMActiveOnCntrlSpace(dpy,win)934 int tgIMActiveOnCntrlSpace(dpy, win)
935    Display *dpy;
936    Window win;
937 {
938    if (gnInputMethodIndex == INVALID ||
939          gstIMInfo[gnInputMethodIndex].pActivateOnCntrlSpaceFunc == NULL) {
940       return FALSE;
941    }
942    return ((gstIMInfo[gnInputMethodIndex].pActivateOnCntrlSpaceFunc)(dpy, win));
943 }
944 
tgIMHandleCntrlSpace(dpy,win)945 int tgIMHandleCntrlSpace(dpy, win)
946    Display *dpy;
947    Window win;
948 {
949    if (gnInputMethodIndex == INVALID ||
950          gstIMInfo[gnInputMethodIndex].pHandleCntrlSpaceFunc == NULL) {
951       return FALSE;
952    }
953    return ((gstIMInfo[gnInputMethodIndex].pHandleCntrlSpaceFunc)(dpy, win));
954 }
955 
tgIMDeactiveOnCreateText(dpy,win)956 int tgIMDeactiveOnCreateText(dpy, win)
957    Display *dpy;
958    Window win;
959 {
960    if (gnInputMethodIndex == INVALID ||
961          gstIMInfo[gnInputMethodIndex].pDeactivateOnCreateTextFunc == NULL) {
962       return FALSE;
963    }
964    return ((gstIMInfo[gnInputMethodIndex].pDeactivateOnCreateTextFunc)(dpy,
965          win));
966 }
967 
tgIMHandleCreateText(dpy,win)968 int tgIMHandleCreateText(dpy, win)
969    Display *dpy;
970    Window win;
971 {
972    if (gnInputMethodIndex == INVALID ||
973          gstIMInfo[gnInputMethodIndex].pHandleCreateTextFunc == NULL) {
974       return FALSE;
975    }
976    return ((gstIMInfo[gnInputMethodIndex].pHandleCreateTextFunc)(dpy, win));
977 }
978 
tgIMTellCursorPosition(dpy,win,cur_x,cur_y)979 int tgIMTellCursorPosition(dpy, win, cur_x, cur_y)
980    Display *dpy;
981    Window win;
982    int cur_x, cur_y;
983 {
984    if (gnInputMethodIndex == INVALID ||
985          gstIMInfo[gnInputMethodIndex].pTellCursorPosFunc == NULL) {
986       return FALSE;
987    }
988    return ((gstIMInfo[gnInputMethodIndex].pTellCursorPosFunc)(dpy, win,
989          cur_x, cur_y));
990 }
991 
tgIMExpectNextEvent(dpy,win)992 int tgIMExpectNextEvent(dpy, win)
993    Display *dpy;
994    Window win;
995 {
996    if (gnInputMethodIndex == INVALID ||
997          gstIMInfo[gnInputMethodIndex].pExpectNextEventFunc == NULL) {
998       return FALSE;
999    }
1000    return ((gstIMInfo[gnInputMethodIndex].pExpectNextEventFunc)(dpy, win));
1001 }
1002 
tgIMHandleNextEvent(dpy,win,ev)1003 int tgIMHandleNextEvent(dpy, win, ev)
1004    Display *dpy;
1005    Window win;
1006    XEvent *ev;
1007 {
1008    if (gnInputMethodIndex == INVALID ||
1009          gstIMInfo[gnInputMethodIndex].pHandleNextEventFunc == NULL) {
1010       return FALSE;
1011    }
1012    return ((gstIMInfo[gnInputMethodIndex].pHandleNextEventFunc)(dpy, win, ev));
1013 }
1014 
tgIMHandleNewCurText(dpy,win)1015 int tgIMHandleNewCurText(dpy, win)
1016    Display *dpy;
1017    Window win;
1018 {
1019    if (gnInputMethodIndex == INVALID ||
1020          gstIMInfo[gnInputMethodIndex].pHandleNewCurTextFunc == NULL) {
1021       return FALSE;
1022    }
1023    return ((gstIMInfo[gnInputMethodIndex].pHandleNewCurTextFunc)(dpy, win));
1024 }
1025 
tgIMExpectLookupString(dpy,win)1026 int tgIMExpectLookupString(dpy, win)
1027    Display *dpy;
1028    Window win;
1029 {
1030    if (gnInputMethodIndex == INVALID ||
1031          gstIMInfo[gnInputMethodIndex].pExpectLookupStringFunc == NULL) {
1032       return FALSE;
1033    }
1034    return ((gstIMInfo[gnInputMethodIndex].pExpectLookupStringFunc)(dpy, win));
1035 }
1036 
tgIMHandleLookupString(dpy,win,key_ev,psz_buf,buf_size,p_key_sym,pn_has_ch)1037 int tgIMHandleLookupString(dpy, win, key_ev, psz_buf, buf_size, p_key_sym,
1038       pn_has_ch)
1039    Display *dpy;
1040    Window win;
1041    XKeyEvent *key_ev;
1042    char *psz_buf;
1043    int buf_size;
1044    KeySym *p_key_sym;
1045    int *pn_has_ch;
1046 {
1047    if (gnInputMethodIndex == INVALID ||
1048          gstIMInfo[gnInputMethodIndex].pHandleLookupStringFunc == NULL) {
1049       return FALSE;
1050    }
1051    return ((gstIMInfo[gnInputMethodIndex].pHandleLookupStringFunc)(dpy, win,
1052          key_ev, psz_buf, buf_size, p_key_sym, pn_has_ch));
1053 }
1054 
1055