1 /*
2 * Author: Yoichiro Ueno (ueno@cs.titech.ac.jp)
3 *
4 * Copyright (C) 1991, 1992, Yoichiro Ueno.
5 *
6 * Permission to use, copy, modify, and distribute this software and
7 * its documentation for any purpose is hereby granted by the Author without
8 * fee, provided that the above copyright notice appear in all copies and
9 * that both the copyright notice and this permission notice appear in
10 * supporting documentation, and that the name of the Author not be used
11 * in advertising or publicity pertaining to distribution of the software
12 * without specific, written prior permission. The Author makes no
13 * representations about the suitability of this software for any purpose.
14 * It is provided "as is" without express or implied warranty.
15 *
16 * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 *
24 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/convxim.c,v 1.5 2009/08/07 03:41:16 william Exp $
25 */
26 #ifndef _NO_XIM
27
28 #define _INCLUDE_FROM_CONVXIM_C_
29
30 #include "tgifdefs.h"
31
32 #include "convkinput.e"
33 #include "convxim.e"
34 #include "dialog.e"
35 #include "font.e"
36 #include "list.e"
37 #include "miniline.e"
38 #include "msg.e"
39 #include "setup.e"
40 #include "strtbl.e"
41 #include "util.e"
42
43 #ifndef _NO_XIMP
44 #define DEFAULT_MODIFIERS ""
45 #define DEFAULT_LANG "ja_JP.EUC"
46 #else /* _NO_XIMP */
47 #define DEFAULT_MODIFIERS "@im=_XWNMO"
48 #define DEFAULT_LANG "ja_JP.ujis"
49 #endif /* ~_NO_XIMP */
50
51 typedef struct tagXICInfo {
52 XIC ic;
53 Window win;
54 } XICInfo;
55
56 static CVList gXICInfoList;
57
58 char ximConvModifiers[MAXSTRING] = DEFAULT_MODIFIERS;
59 char ximConvLang[MAXSTRING] = DEFAULT_LANG;
60
61 static char *locale = NULL;
62 static char *modifiers = NULL;
63 static XIM im = NULL;
64 static XIC ic = NULL;
65
66 typedef void (MYIOErrHandler)ARGS_DECL((void));
67
68 static MYIOErrHandler *oldhandler = NULL;
69 static Bool _XIMErrorFlag = False;
70 static Bool overthespot = False;
71
72 static Bool modscim = False;
73 static int pre_x = 0;
74 static int pre_y = 0;
75
76 #ifndef _NO_XIMP
_XipSetIOErrorHandler(new_handler)77 static MYIOErrHandler *_XipSetIOErrorHandler(new_handler)
78 MYIOErrHandler *new_handler;
79 {
80 return NULL;
81 }
82 #else /* _NO_XIMP */
83 extern void (*_XipSetIOErrorHandler())();
84 #endif /* ~_NO_XIMP */
85
86 /* --------------------- Utility Functions --------------------- */
87
88 static
FindXIC(win)89 CVListElem *FindXIC(win)
90 Window win;
91 {
92 CVListElem *pElem=NULL;
93
94 for (pElem=ListFirst(&gXICInfoList); pElem != NULL;
95 pElem=ListNext(&gXICInfoList, pElem)) {
96 XICInfo *pxi=(XICInfo*)(pElem->obj);
97
98 if (pxi->win == win) {
99 return pElem;
100 }
101 }
102 return NULL;
103 }
104
105 static
DeleteXICInfo(pElem)106 void DeleteXICInfo(pElem)
107 CVListElem *pElem;
108 {
109 XICInfo *pxi=(XICInfo*)(pElem->obj);
110
111 if (pxi->ic != NULL) XDestroyIC(pxi->ic);
112
113 ListUnlink(&gXICInfoList, pElem);
114 free(pElem);
115 }
116
117 /* --------------------- Exported Functions --------------------- */
118
119 static
_XIMIOError()120 void _XIMIOError()
121 {
122 _XIMErrorFlag = True;
123 }
124
125 static
XIMClose(win)126 void XIMClose(win)
127 Window win;
128 {
129 CVListElem *pElem=FindXIC(win);
130
131 if (pElem != NULL) {
132 DeleteXICInfo(pElem);
133 }
134 }
135
136 #define ROOT 1
137 #define OVERTHESPOT 2
138 static int style_type=ROOT;
139 XFontSet XIMfs;
140 XFontSetExtents * fs_ext=NULL;
141 char** missing_list=NULL;
142 int missing_count=0;
143 char* def_string=NULL;
144 char* XIMFontSetStr="-misc-fixed-medium-r-normal--14-*";
145
146 static
XIMSetLocale()147 void XIMSetLocale()
148 {
149 #ifndef _NO_LOCALE_SUPPORT
150 char buf[80], *c_ptr=NULL;
151
152 c_ptr = (char*)getenv("LC_ALL");
153 if (c_ptr != NULL) {
154 UtilStrCpyN(ximConvLang, sizeof(ximConvLang), c_ptr);
155 } else {
156 c_ptr = (char*)getenv("LANG");
157 if (c_ptr != NULL) {
158 UtilStrCpyN(ximConvLang, sizeof(ximConvLang), c_ptr);
159 } else if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "Lang")) !=
160 NULL) {
161 UtilTrimBlanks(c_ptr);
162 UtilStrCpyN(ximConvLang, sizeof(ximConvLang), c_ptr);
163 }
164 }
165 locale = setlocale(LC_ALL, ximConvLang);
166 sprintf(buf, TgLoadString(STID_LOCALE_IS),
167 locale==NULL ? TgLoadCachedString(CSTID_PARANED_NULL) : locale);
168 Msg(buf);
169
170 c_ptr = (char*)getenv("LC_CTYPE");
171 if (c_ptr != NULL) {
172 UtilStrCpyN(buf, sizeof(buf), c_ptr);
173 locale = setlocale(LC_CTYPE, buf);
174 #ifdef _TGIF_DBG /* debug, do not translate */
175 sprintf(buf, "LC_CTYPE is '%s'.", locale==NULL ? "null" : locale);
176 Msg(buf);
177 #endif /* _TGIF_DBG */
178 }
179 setlocale(LC_NUMERIC, "C");
180 #endif /* ~_NO_LOCALE_SUPPORT */
181 }
182
XIMSetICFocus(dpy,win)183 void XIMSetICFocus(dpy, win)
184 Display *dpy;
185 Window win;
186 {
187 char buf[80];
188 XIMStyles * styles=NULL;
189 Bool style_flag;
190 int style_attr=0;
191 int i;
192 XPoint spot;
193 XRectangle s_rect;
194 XVaNestedList preedit_attr, status_attr;
195 CVListElem *pElem=NULL;
196
197 if(oldhandler == NULL)
198 oldhandler = _XipSetIOErrorHandler(_XIMIOError);
199
200 if(locale == NULL) {
201 XIMSetLocale();
202 }
203 if(modifiers == NULL) {
204 char *c_ptr=(char*)getenv("XMODIFIERS");
205
206 if (c_ptr != NULL) {
207 UtilStrCpyN(ximConvModifiers, sizeof(ximConvModifiers), c_ptr);
208 } else {
209 if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "Modifiers")) !=
210 NULL) {
211 UtilTrimBlanks(c_ptr);
212 UtilStrCpyN(ximConvModifiers, sizeof(ximConvModifiers), c_ptr);
213 }
214 }
215 modifiers = XSetLocaleModifiers(ximConvModifiers);
216 sprintf(buf, TgLoadString(STID_MODIFIER_IS),
217 modifiers==NULL ? TgLoadCachedString(CSTID_PARANED_NULL) :
218 modifiers);
219 Msg(buf);
220 }
221
222 for (i = 0; i <= (int)strlen(modifiers) - 4 ; i++) {
223 if (strncmp((char *)&modifiers[i], "SCIM", 4) == 0 ||
224 strncmp((char *)&modifiers[i], "scim", 4) == 0) {
225 modscim = True;
226 break;
227 }
228 }
229
230 if(im == NULL) {
231 im = XOpenIM(mainDisplay, NULL, NULL, NULL);
232 if(im == NULL) {
233 MsgBox(TgLoadString(STID_CANNOT_OPEN_XIM), TOOL_NAME, INFO_MB);
234 return;
235 }
236 }
237 pElem = FindXIC(win);
238 if (pElem != NULL) {
239 XICInfo *pxi=(XICInfo*)(pElem->obj);
240
241 ic = pxi->ic;
242 } else {
243 XICInfo *pxi=(XICInfo*)malloc(sizeof(XICInfo));
244
245 if (pxi == NULL) FailAllocMessage();
246 memset(pxi, 0, sizeof(XICInfo));
247 if (!ListAppend(&gXICInfoList, pxi)) {
248 }
249 pxi->win = win;
250
251 XGetIMValues(im,
252 XNQueryInputStyle, &styles,
253 NULL, NULL);
254 style_flag = False;
255 if (overthespot) {
256 for(i = 0; i < (int)(styles->count_styles); i ++){
257 if((styles->supported_styles[i] ==
258 (XIMPreeditPosition | XIMStatusArea)) ||
259 (styles->supported_styles[i] ==
260 (XIMPreeditPosition | XIMStatusNothing))){
261 style_flag = True;
262 style_type = OVERTHESPOT;
263 style_attr = styles->supported_styles[i];
264 Msg(TgLoadString(STID_OVERTHESPOT_CONV));
265 }
266 }
267 }else{
268 for(i = 0; i < (int)(styles->count_styles); i ++){
269 if(styles->supported_styles[i] ==
270 (XIMPreeditNothing | XIMStatusNothing)){
271 style_flag = True;
272 style_type = ROOT;
273 Msg(TgLoadString(STID_ROOT_CONV));
274 }
275 }
276 }
277 if(!style_flag) {
278 sprintf(gszMsgBox, TgLoadString(STID_IM_NOT_SUPPORT_GIVEN_STYLE),
279 (overthespot ? "OverTheSpot" : "Root"));
280 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
281 XCloseIM(im);
282 im = NULL;
283 return;
284 }
285 switch (style_type){
286 case ROOT:
287 ic = XCreateIC(im,
288 XNInputStyle , XIMPreeditNothing | XIMStatusNothing,
289 XNClientWindow, win,
290 XNFocusWindow, win,
291 NULL, NULL);
292 break;
293 case OVERTHESPOT:
294 XIMfs=XCreateFontSet(dpy, XIMFontSetStr,
295 &missing_list, &missing_count, &def_string);
296 fs_ext=XExtentsOfFontSet(XIMfs);
297 spot.x=0; spot.y=fs_ext->max_logical_extent.height;
298 s_rect.x=0; s_rect.y=fs_ext->max_logical_extent.height;
299 s_rect.width=640; s_rect.height=fs_ext->max_logical_extent.height;
300 preedit_attr=XVaCreateNestedList(0,
301 XNSpotLocation, &spot,
302 XNFontSet, XIMfs,
303 NULL);
304 status_attr=XVaCreateNestedList(0,
305 XNArea, &s_rect,
306 XNFontSet, XIMfs,
307 NULL);
308 ic = XCreateIC(im,
309 XNInputStyle , style_attr,
310 XNClientWindow, win,
311 XNFocusWindow, win,
312 XNPreeditAttributes, preedit_attr,
313 XNStatusAttributes, status_attr,
314 NULL, NULL);
315 XFree(preedit_attr);
316 XFree(status_attr);
317 break;
318 }
319 if(ic == NULL) {
320 fprintf(stderr, "%s\n",
321 TgLoadString(STID_FAIL_TO_CREATE_INPUTCONTEXT));
322 XCloseIM(im);
323 im = NULL;
324 return;
325 }
326 pxi->ic = ic;
327 Msg(TgLoadString(STID_OPEN_XIM));
328 }
329 XSetICFocus(ic);
330
331 if(_XIMErrorFlag) {
332 XIMClose(win);
333 Msg(TgLoadString(STID_CLOSE_XIM));
334 }
335 }
336
XIMNextEvent(dpy,win,xev_p)337 void XIMNextEvent(dpy, win, xev_p)
338 Display * dpy;
339 Window win;
340 XEvent * xev_p;
341 {
342 Bool filter_status;
343
344 do {
345 XNextEvent(dpy, xev_p);
346
347 /*
348 * The 2nd argument has been changed from win to None
349 * according to Ambrose Li's investigation. See his
350 * e-mail on "Sun, 09 Mar 2003 19:09:38 EST".
351 */
352 filter_status = XFilterEvent(xev_p, None);
353
354 if(_XIMErrorFlag) {
355 XIMClose(win);
356 Msg(TgLoadString(STID_CLOSE_XIM));
357 }
358 } while(filter_status == True);
359 }
360
XIMLookupString(key_ev,buf,buf_len,key_sym_p,c_stat_p)361 int XIMLookupString(key_ev, buf, buf_len, key_sym_p, c_stat_p)
362 XKeyEvent * key_ev;
363 char * buf;
364 int buf_len;
365 KeySym * key_sym_p;
366 XIMStatus * c_stat_p;
367 {
368 int has_ch=0;
369
370 if(im && ic) {
371 c_stat_p->valid = MB_STATUS;
372 has_ch = XmbLookupString (ic, key_ev, buf, buf_len, key_sym_p, &c_stat_p->mb_status);
373 /*
374 * switch (c_stat_p->mb_status) {
375 * case XLookupKeySym:
376 * case XLookupBoth:
377 * {
378 * unsigned int key_sym=(unsigned int)(*key_sym_p);
379 *
380 * if (key_sym < 0x100) {
381 * has_ch = 1;
382 * *buf = (char)(unsigned char)(key_sym & 0x0ff);
383 * buf[1] = '\0';
384 * }
385 * }
386 * break;
387 * default: break;
388 * }
389 */
390 }
391 else {
392 c_stat_p->valid = COMPOSE_STATUS;
393 has_ch = XLookupString (key_ev, buf, buf_len, key_sym_p, &c_stat_p->status);
394 }
395 return has_ch;
396 }
397
XIMUnsetICFocus(win)398 void XIMUnsetICFocus(win)
399 Window win;
400 {
401 CVListElem *pElem=FindXIC(win);
402
403 if (pElem != NULL) {
404 XICInfo *pxi=(XICInfo*)(pElem->obj);
405
406 ic = pxi->ic;
407 }
408 if(im && ic) {
409 XUnsetICFocus(ic);
410 }
411 }
412
XIMSetConvOverSpot(gnOverTheSpot)413 void XIMSetConvOverSpot(gnOverTheSpot)
414 Bool gnOverTheSpot;
415 {
416 overthespot=gnOverTheSpot;
417 }
418
XIMTellCursorPosition(dpy,win,x,y)419 void XIMTellCursorPosition(dpy, win, x, y)
420 Display* dpy;
421 Window win;
422 int x;
423 int y;
424 {
425 XPoint spot;
426 XRectangle s_rect;
427 XVaNestedList preedit_attr,status_attr;
428 char szAttemptedFontName[MAXSTRING+1];
429 CVListElem *pElem=FindXIC(win);
430
431 if (pElem != NULL) {
432 XICInfo *pxi=(XICInfo*)(pElem->obj);
433
434 ic = pxi->ic;
435 }
436 if (im == NULL || ic == NULL || !overthespot) return;
437
438 if (x == pre_x && y == pre_y) return;
439 pre_x = x; pre_y = y;
440
441 if (XIMfs) XFreeFontSet(dpy, XIMfs);
442 GetCurFontInfoStr(szAttemptedFontName, sizeof(szAttemptedFontName));
443 XIMfs=XCreateFontSet(dpy, szAttemptedFontName,
444 &missing_list, &missing_count, &def_string);
445 fs_ext=XExtentsOfFontSet(XIMfs);
446 spot.x=textCurX; spot.y=textCurBaselineY;
447 s_rect.x=textCurX; s_rect.y=textCurBaselineY+3;
448 /*s_rect.width=200; s_rect.height=fs_ext->max_logical_extent.height;*/
449 s_rect.width=50; s_rect.height=16;
450
451 preedit_attr=XVaCreateNestedList(0,
452 XNSpotLocation, &spot,
453 XNFontSet, XIMfs,
454 NULL);
455 status_attr=XVaCreateNestedList(0,
456 XNArea, &s_rect,
457 NULL);
458 XSetICValues(ic,
459 XNPreeditAttributes, preedit_attr,
460 XNStatusAttributes, status_attr,
461 NULL);
462 XFree(preedit_attr);
463 XFree(status_attr);
464 if (!modscim) {
465 XSetICFocus(ic);
466 }
467 }
468
XIMCleanUp()469 void XIMCleanUp()
470 {
471 CVListElem *pElem=NULL;
472
473 for (pElem=ListFirst(&gXICInfoList); pElem != NULL;
474 pElem=ListNext(&gXICInfoList, pElem)) {
475 XICInfo *pxi=(XICInfo*)(pElem->obj);
476
477 if (pxi->ic != NULL) XDestroyIC(pxi->ic);
478 free(pxi);
479 }
480 ListUnlinkAll(&gXICInfoList);
481
482 if(im != NULL) {
483 XCloseIM(im);
484 }
485 im = NULL;
486 ic = NULL;
487 _XIMErrorFlag = False;
488 }
489
XIMInit()490 int XIMInit()
491 {
492 im = NULL;
493 ic = NULL;
494 _XIMErrorFlag = False;
495 CVListInit(&gXICInfoList);
496
497 return TRUE;
498 }
499
500 #endif /* ~_NO_XIM */
501
502