aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/modules/immodules/xim/ecore_imf_xim.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/ecore/src/modules/immodules/xim/ecore_imf_xim.c1499
1 files changed, 0 insertions, 1499 deletions
diff --git a/libraries/ecore/src/modules/immodules/xim/ecore_imf_xim.c b/libraries/ecore/src/modules/immodules/xim/ecore_imf_xim.c
deleted file mode 100644
index 01a3576..0000000
--- a/libraries/ecore/src/modules/immodules/xim/ecore_imf_xim.c
+++ /dev/null
@@ -1,1499 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Eina.h>
6#include <Ecore.h>
7#include <Ecore_Input.h>
8#include <Ecore_IMF.h>
9#include <Ecore_X.h>
10#include <X11/Xlib.h>
11#include <X11/Xlocale.h>
12#include <X11/Xutil.h>
13#include <X11/keysym.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <langinfo.h>
18#include <assert.h>
19
20#define CLAMP(x, low, high) (x > high) ? high : (x < low) ? low : x
21#define _(x) x
22
23#ifdef ENABLE_XIM
24static Eina_List *open_ims = NULL;
25#endif
26
27#define FEEDBACK_MASK (XIMReverse | XIMUnderline | XIMHighlight)
28
29typedef struct _XIM_Im_Info XIM_Im_Info;
30struct _XIM_Im_Info
31{
32 Ecore_X_Window win;
33 char *locale;
34 XIM im;
35 Eina_List *ics;
36 Eina_Bool reconnecting;
37 XIMStyles *xim_styles;
38 Eina_Bool supports_string_conversion : 1;
39 Eina_Bool supports_cursor : 1;
40};
41
42typedef struct _Ecore_IMF_Context_Data Ecore_IMF_Context_Data;
43struct _Ecore_IMF_Context_Data
44{
45 Ecore_X_Window win;
46 long mask;
47 XIC ic; /* Input context for composed characters */
48 char *locale;
49 XIM_Im_Info *im_info;
50 int preedit_length;
51 int preedit_cursor;
52 Eina_Unicode *preedit_chars;
53 Eina_Bool use_preedit;
54 Eina_Bool finalizing;
55 Eina_Bool has_focus;
56 Eina_Bool in_toplevel;
57 XIMFeedback *feedbacks;
58
59 XIMCallback preedit_start_cb;
60 XIMCallback preedit_done_cb;
61 XIMCallback preedit_draw_cb;
62 XIMCallback preedit_caret_cb;
63};
64
65/* prototype */
66Ecore_IMF_Context_Data *imf_context_data_new();
67void imf_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data);
68
69#ifdef ENABLE_XIM
70static void add_feedback_attr(Eina_List **attrs,
71 const char *str,
72 XIMFeedback feedback,
73 int start_pos,
74 int end_pos);
75
76static void reinitialize_ic(Ecore_IMF_Context *ctx);
77static void reinitialize_all_ics(XIM_Im_Info *info);
78static void set_ic_client_window(Ecore_IMF_Context *ctx,
79 Ecore_X_Window window);
80static int preedit_start_callback(XIC xic,
81 XPointer client_data,
82 XPointer call_data);
83static void preedit_done_callback(XIC xic,
84 XPointer client_data,
85 XPointer call_data);
86static int xim_text_to_utf8(Ecore_IMF_Context *ctx,
87 XIMText *xim_text,
88 char **text);
89static void preedit_draw_callback(XIC xic,
90 XPointer client_data,
91 XIMPreeditDrawCallbackStruct *call_data);
92static void preedit_caret_callback(XIC xic,
93 XPointer client_data,
94 XIMPreeditCaretCallbackStruct *call_data);
95static XVaNestedList preedit_callback_set(Ecore_IMF_Context *ctx);
96static XIC get_ic(Ecore_IMF_Context *ctx);
97static XIM_Im_Info *get_im(Ecore_X_Window window,
98 char *locale);
99static void xim_info_try_im(XIM_Im_Info *info);
100static void xim_info_display_closed(Ecore_X_Display *display,
101 int is_error,
102 XIM_Im_Info *info);
103static void xim_instantiate_callback(Display *display,
104 XPointer client_data,
105 XPointer call_data);
106static void setup_im(XIM_Im_Info *info);
107static void xim_destroy_callback(XIM xim,
108 XPointer client_data,
109 XPointer call_data);
110#endif
111
112#ifdef ENABLE_XIM
113static unsigned int
114utf8_offset_to_index(const char *str, int offset)
115{
116 int index = 0;
117 int i;
118 for (i = 0; i < offset; i++)
119 {
120 eina_unicode_utf8_get_next(str, &index);
121 }
122
123 return index;
124}
125
126#endif
127
128static void
129_ecore_imf_context_xim_add(Ecore_IMF_Context *ctx)
130{
131 EINA_LOG_DBG("in");
132#ifdef ENABLE_XIM
133 Ecore_IMF_Context_Data *imf_context_data = NULL;
134
135 imf_context_data = imf_context_data_new();
136 if (!imf_context_data) return;
137
138 imf_context_data->use_preedit = EINA_TRUE;
139 imf_context_data->finalizing = EINA_FALSE;
140 imf_context_data->has_focus = EINA_FALSE;
141 imf_context_data->in_toplevel = EINA_FALSE;
142
143 ecore_imf_context_data_set(ctx, imf_context_data);
144#else
145 (void)ctx;
146#endif
147}
148
149static void
150_ecore_imf_context_xim_del(Ecore_IMF_Context *ctx)
151{
152 EINA_LOG_DBG("in");
153#ifdef ENABLE_XIM
154 Ecore_IMF_Context_Data *imf_context_data;
155 imf_context_data = ecore_imf_context_data_get(ctx);
156
157 imf_context_data->finalizing = EINA_TRUE;
158 if (imf_context_data->im_info && !imf_context_data->im_info->ics->next)
159 {
160 if (imf_context_data->im_info->reconnecting == EINA_TRUE)
161 {
162 Ecore_X_Display *dsp;
163 dsp = ecore_x_display_get();
164 XUnregisterIMInstantiateCallback(dsp,
165 NULL, NULL, NULL,
166 xim_instantiate_callback,
167 (XPointer)imf_context_data->im_info);
168 }
169 else if (imf_context_data->im_info->im)
170 {
171 XIMCallback im_destroy_callback;
172 im_destroy_callback.client_data = NULL;
173 im_destroy_callback.callback = NULL;
174 XSetIMValues(imf_context_data->im_info->im,
175 XNDestroyCallback, &im_destroy_callback,
176 NULL);
177 }
178 }
179
180 set_ic_client_window(ctx, 0);
181
182 imf_context_data_destroy(imf_context_data);
183#else
184 (void)ctx;
185#endif
186}
187
188static void
189_ecore_imf_context_xim_client_window_set(Ecore_IMF_Context *ctx,
190 void *window)
191{
192 EINA_LOG_DBG("in");
193#ifdef ENABLE_XIM
194 set_ic_client_window(ctx, (Ecore_X_Window)((Ecore_Window)window));
195#else
196 (void)ctx;
197 (void)window;
198#endif
199}
200
201static void
202_ecore_imf_context_xim_preedit_string_get(Ecore_IMF_Context *ctx,
203 char **str,
204 int *cursor_pos)
205{
206 EINA_LOG_DBG("in");
207#ifdef ENABLE_XIM
208 Ecore_IMF_Context_Data *imf_context_data;
209 char *utf8;
210 int len;
211 imf_context_data = ecore_imf_context_data_get(ctx);
212 if (imf_context_data->preedit_chars)
213 {
214 utf8 = eina_unicode_unicode_to_utf8(imf_context_data->preedit_chars,
215 &len);
216 if (str)
217 *str = utf8;
218 else
219 free(utf8);
220 }
221 else
222 {
223 if (str)
224 *str = NULL;
225 if (cursor_pos)
226 *cursor_pos = 0;
227 }
228
229 if (cursor_pos)
230 *cursor_pos = imf_context_data->preedit_cursor;
231#else
232 (void)ctx;
233 if (str)
234 *str = NULL;
235 if (cursor_pos)
236 *cursor_pos = 0;
237#endif
238}
239
240static void
241_ecore_imf_context_xim_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
242 char **str,
243 Eina_List **attrs,
244 int *cursor_pos)
245{
246 EINA_LOG_DBG("in");
247
248#ifdef ENABLE_XIM
249 Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
250
251 _ecore_imf_context_xim_preedit_string_get(ctx, str, cursor_pos);
252
253 if (!attrs) return;
254 if (!imf_context_data || !imf_context_data->feedbacks) return;
255
256 int i = 0;
257 XIMFeedback last_feedback = 0;
258 int start = -1;
259
260 for (i = 0; i < imf_context_data->preedit_length; i++)
261 {
262 XIMFeedback new_feedback = imf_context_data->feedbacks[i] & FEEDBACK_MASK;
263
264 if (new_feedback != last_feedback)
265 {
266 if (start >= 0)
267 add_feedback_attr(attrs, *str, last_feedback, start, i);
268
269 last_feedback = new_feedback;
270 start = i;
271 }
272 }
273
274 if (start >= 0)
275 add_feedback_attr(attrs, *str, last_feedback, start, i);
276#else
277 (void)ctx;
278 if (str)
279 *str = NULL;
280 if (attrs)
281 *attrs = NULL;
282 if (cursor_pos)
283 *cursor_pos = 0;
284#endif
285}
286
287static void
288_ecore_imf_context_xim_focus_in(Ecore_IMF_Context *ctx)
289{
290 EINA_LOG_DBG("in");
291#ifdef ENABLE_XIM
292 XIC ic;
293 Ecore_IMF_Context_Data *imf_context_data;
294 imf_context_data = ecore_imf_context_data_get(ctx);
295 ic = imf_context_data->ic;
296 imf_context_data->has_focus = EINA_TRUE;
297
298 if (ecore_imf_context_input_panel_enabled_get(ctx))
299 ecore_imf_context_input_panel_show(ctx);
300
301 if (ic)
302 {
303 char *str;
304
305#ifdef X_HAVE_UTF8_STRING
306 if ((str = Xutf8ResetIC(ic)))
307#else
308 if ((str = XmbResetIC(ic)))
309#endif
310 XFree(str);
311
312 XSetICFocus(ic);
313 }
314#else
315 (void)ctx;
316#endif
317}
318
319static void
320_ecore_imf_context_xim_focus_out(Ecore_IMF_Context *ctx)
321{
322 EINA_LOG_DBG("%s in", __FUNCTION__);
323#ifdef ENABLE_XIM
324 XIC ic;
325 Ecore_IMF_Context_Data *imf_context_data;
326 imf_context_data = ecore_imf_context_data_get(ctx);
327 if (imf_context_data->has_focus == EINA_TRUE)
328 {
329 imf_context_data->has_focus = EINA_FALSE;
330 ic = imf_context_data->ic;
331 if (ic)
332 XUnsetICFocus(ic);
333
334 if (ecore_imf_context_input_panel_enabled_get(ctx))
335 ecore_imf_context_input_panel_hide(ctx);
336 }
337#else
338 (void)ctx;
339#endif
340}
341
342static void
343_ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx)
344{
345 EINA_LOG_DBG("%s in", __FUNCTION__);
346#ifdef ENABLE_XIM
347 XIC ic;
348 Ecore_IMF_Context_Data *imf_context_data;
349 char *result;
350
351 /* restore conversion state after resetting ic later */
352 XIMPreeditState preedit_state = XIMPreeditUnKnown;
353 XVaNestedList preedit_attr;
354 Eina_Bool have_preedit_state = EINA_FALSE;
355
356 imf_context_data = ecore_imf_context_data_get(ctx);
357 ic = imf_context_data->ic;
358 if (!ic)
359 return;
360
361 if (imf_context_data->preedit_length == 0)
362 return;
363
364 preedit_attr = XVaCreateNestedList(0,
365 XNPreeditState, &preedit_state,
366 NULL);
367 if (!XGetICValues(ic,
368 XNPreeditAttributes, preedit_attr,
369 NULL))
370 have_preedit_state = EINA_TRUE;
371
372 XFree(preedit_attr);
373
374 result = XmbResetIC(ic);
375
376 preedit_attr = XVaCreateNestedList(0,
377 XNPreeditState, preedit_state,
378 NULL);
379 if (have_preedit_state)
380 XSetICValues(ic,
381 XNPreeditAttributes, preedit_attr,
382 NULL);
383
384 XFree(preedit_attr);
385
386 if (imf_context_data->feedbacks)
387 {
388 free(imf_context_data->feedbacks);
389 imf_context_data->feedbacks = NULL;
390 }
391
392 if (imf_context_data->preedit_length)
393 {
394 imf_context_data->preedit_length = 0;
395 free(imf_context_data->preedit_chars);
396 imf_context_data->preedit_chars = NULL;
397
398 ecore_imf_context_preedit_changed_event_add(ctx);
399 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
400 }
401
402 if (result)
403 {
404 char *result_utf8 = strdup(result);
405 if (result_utf8)
406 {
407 ecore_imf_context_commit_event_add(ctx, result_utf8);
408 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, result_utf8);
409 free(result_utf8);
410 }
411 }
412
413 XFree(result);
414#else
415 (void)ctx;
416#endif
417}
418
419static void
420_ecore_imf_context_xim_use_preedit_set(Ecore_IMF_Context *ctx,
421 Eina_Bool use_preedit)
422{
423 EINA_LOG_DBG("in");
424#ifdef ENABLE_XIM
425 Ecore_IMF_Context_Data *imf_context_data;
426 imf_context_data = ecore_imf_context_data_get(ctx);
427
428 use_preedit = use_preedit != EINA_FALSE;
429
430 if (imf_context_data->use_preedit != use_preedit)
431 {
432 imf_context_data->use_preedit = use_preedit;
433 reinitialize_ic(ctx);
434 }
435#else
436 (void)ctx;
437 (void)use_preedit;
438#endif
439}
440
441#ifdef ENABLE_XIM
442static void
443add_feedback_attr(Eina_List **attrs,
444 const char *str,
445 XIMFeedback feedback,
446 int start_pos,
447 int end_pos)
448{
449 Ecore_IMF_Preedit_Attr *attr = NULL;
450
451 unsigned int start_index = utf8_offset_to_index(str, start_pos);
452 unsigned int end_index = utf8_offset_to_index(str, end_pos);
453
454 if (feedback & FEEDBACK_MASK)
455 {
456 attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
457 attr->start_index = start_index;
458 attr->end_index = end_index;
459 *attrs = eina_list_append(*attrs, (void *)attr);
460 }
461
462 if (feedback & XIMUnderline)
463 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
464
465 if (feedback & XIMReverse)
466 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
467
468 if (feedback & XIMHighlight)
469 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
470}
471
472#endif
473
474static void
475_ecore_imf_context_xim_cursor_location_set(Ecore_IMF_Context *ctx,
476 int x, int y, int w, int h)
477{
478 EINA_LOG_DBG("%s in", __FUNCTION__);
479
480#ifdef ENABLE_XIM
481 Ecore_IMF_Context_Data *imf_context_data;
482 XIC ic;
483 XVaNestedList preedit_attr;
484 XPoint spot;
485
486 imf_context_data = ecore_imf_context_data_get(ctx);
487 ic = imf_context_data->ic;
488 if (!ic)
489 return;
490
491 spot.x = x;
492 spot.y = y + h;
493
494 preedit_attr = XVaCreateNestedList(0,
495 XNSpotLocation, &spot,
496 NULL);
497 XSetICValues(ic,
498 XNPreeditAttributes, preedit_attr,
499 NULL);
500
501 XFree(preedit_attr);
502#else
503 (void)ctx;
504 (void)x;
505 (void)y;
506 (void)h;
507#endif
508 (void)(w); // yes w is unused, but only a bi-product of the algorithm
509}
510
511static void
512_ecore_imf_context_xim_input_panel_show(Ecore_IMF_Context *ctx)
513{
514 EINA_LOG_DBG("%s in", __FUNCTION__);
515
516#ifdef ENABLE_XIM
517 Ecore_IMF_Context_Data *imf_context_data;
518 imf_context_data = ecore_imf_context_data_get(ctx);
519
520 ecore_x_e_virtual_keyboard_state_set
521 (imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
522#else
523 (void)ctx;
524#endif
525}
526
527static void
528_ecore_imf_context_xim_input_panel_hide(Ecore_IMF_Context *ctx)
529{
530 EINA_LOG_DBG("%s in", __FUNCTION__);
531
532#ifdef ENABLE_XIM
533 Ecore_IMF_Context_Data *imf_context_data;
534 imf_context_data = ecore_imf_context_data_get(ctx);
535
536 ecore_x_e_virtual_keyboard_state_set
537 (imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
538#else
539 (void)ctx;
540#endif
541}
542
543#ifdef ENABLE_XIM
544static unsigned int
545_ecore_x_event_reverse_modifiers(unsigned int state)
546{
547 unsigned int modifiers = 0;
548
549 /**< "Control" is pressed */
550 if (state & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
551 modifiers |= ControlMask;
552
553 /**< "Alt" is pressed */
554 if (state & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
555 modifiers |= Mod1Mask;
556
557 /**< "Shift" is pressed */
558 if (state & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
559 modifiers |= ShiftMask;
560
561 /**< "Win" (between "Ctrl" and "A */
562 if (state & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
563 modifiers |= Mod5Mask;
564
565 return modifiers;
566}
567
568static unsigned int
569_ecore_x_event_reverse_locks(unsigned int state)
570{
571 unsigned int locks = 0;
572
573 /**< "Num" lock is active */
574 if (state & ECORE_IMF_KEYBOARD_LOCK_NUM)
575 locks |= Mod3Mask;
576
577 if (state & ECORE_IMF_KEYBOARD_LOCK_CAPS)
578 locks |= LockMask;
579
580#if 0 /* FIXME: add mask. */
581 if (state & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
582 ;
583#endif
584
585 return locks;
586}
587
588static KeyCode
589_keycode_get(Ecore_X_Display *dsp,
590 const char *keyname)
591{
592 KeyCode keycode;
593
594 // EINA_LOG_DBG("keyname:%s keysym:%lu", keyname, XStringToKeysym(keyname));
595 if (strcmp(keyname, "Keycode-0") == 0)
596 {
597 keycode = 0;
598 }
599 else {
600 keycode = XKeysymToKeycode(dsp, XStringToKeysym(keyname));
601 }
602
603 return keycode;
604}
605
606#endif
607
608static Eina_Bool
609_ecore_imf_context_xim_filter_event(Ecore_IMF_Context *ctx,
610 Ecore_IMF_Event_Type type,
611 Ecore_IMF_Event *event)
612{
613 EINA_LOG_DBG("%s in", __FUNCTION__);
614#ifdef ENABLE_XIM
615 Ecore_IMF_Context_Data *imf_context_data;
616 XIC ic;
617
618 Ecore_X_Display *dsp;
619 Ecore_X_Window win;
620
621 int val;
622 char compose_buffer[256];
623 KeySym sym;
624 char *compose = NULL;
625 char *tmp = NULL;
626 Eina_Bool result = EINA_FALSE;
627
628 imf_context_data = ecore_imf_context_data_get(ctx);
629 ic = imf_context_data->ic;
630 if (!ic)
631 {
632 ic = get_ic(ctx);
633 }
634
635 if (type == ECORE_IMF_EVENT_KEY_DOWN)
636 {
637 XKeyPressedEvent xev;
638 Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
639 EINA_LOG_DBG("ECORE_IMF_EVENT_KEY_DOWN");
640
641 dsp = ecore_x_display_get();
642 win = imf_context_data->win;
643
644 xev.type = KeyPress;
645 xev.serial = 0; /* hope it doesn't matter */
646 xev.send_event = 0;
647 xev.display = dsp;
648 xev.window = win;
649 xev.root = ecore_x_window_root_get(win);
650 xev.subwindow = win;
651 xev.time = ev->timestamp;
652 xev.x = xev.x_root = 0;
653 xev.y = xev.y_root = 0;
654 xev.state = 0;
655 xev.state |= _ecore_x_event_reverse_modifiers(ev->modifiers);
656 xev.state |= _ecore_x_event_reverse_locks(ev->locks);
657 xev.keycode = _keycode_get(dsp, ev->keyname);
658 xev.same_screen = True;
659
660 if (ic)
661 {
662 Status mbstatus;
663#ifdef X_HAVE_UTF8_STRING
664 val = Xutf8LookupString(ic,
665 &xev,
666 compose_buffer,
667 sizeof(compose_buffer) - 1,
668 &sym,
669 &mbstatus);
670#else /* ifdef X_HAVE_UTF8_STRING */
671 val = XmbLookupString(ic,
672 &xev,
673 compose_buffer,
674 sizeof(compose_buffer) - 1,
675 &sym,
676 &mbstatus);
677#endif /* ifdef X_HAVE_UTF8_STRING */
678 if (mbstatus == XBufferOverflow)
679 {
680 tmp = malloc(sizeof (char) * (val + 1));
681 if (!tmp)
682 {
683 return EINA_FALSE;
684 }
685
686 compose = tmp;
687
688#ifdef X_HAVE_UTF8_STRING
689 val = Xutf8LookupString(ic,
690 (XKeyEvent *)&xev,
691 tmp,
692 val,
693 &sym,
694 &mbstatus);
695#else /* ifdef X_HAVE_UTF8_STRING */
696 val = XmbLookupString(ic,
697 (XKeyEvent *)&xev,
698 tmp,
699 val,
700 &sym,
701 &mbstatus);
702#endif /* ifdef X_HAVE_UTF8_STRING */
703 if (val > 0)
704 {
705 tmp[val] = '\0';
706#ifndef X_HAVE_UTF8_STRING
707 compose = eina_str_convert(nl_langinfo(CODESET),
708 "UTF-8", tmp);
709 free(tmp);
710 tmp = compose;
711#endif /* ifndef X_HAVE_UTF8_STRING */
712 }
713 else
714 compose = NULL;
715 }
716 else if (val > 0)
717 {
718 compose_buffer[val] = '\0';
719#ifdef X_HAVE_UTF8_STRING
720 compose = strdup(compose_buffer);
721#else /* ifdef X_HAVE_UTF8_STRING */
722 compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8",
723 compose_buffer);
724#endif /* ifdef X_HAVE_UTF8_STRING */
725 }
726 }
727 else {
728 XComposeStatus status;
729 val = XLookupString(&xev,
730 compose_buffer,
731 sizeof(compose_buffer),
732 &sym,
733 &status);
734 if (val > 0)
735 {
736 compose_buffer[val] = '\0';
737 compose = eina_str_convert(nl_langinfo(CODESET),
738 "UTF-8", compose_buffer);
739 }
740 }
741
742 if (compose)
743 {
744 Eina_Unicode *unicode;
745 int len;
746 unicode = eina_unicode_utf8_to_unicode(compose, &len);
747 if (!unicode) abort();
748 if (unicode[0] >= 0x20 && unicode[0] != 0x7f)
749 {
750 ecore_imf_context_commit_event_add(ctx, compose);
751 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, compose);
752 result = EINA_TRUE;
753 }
754 free(compose);
755 free(unicode);
756 }
757 }
758
759 return result;
760#else
761 (void)ctx;
762 (void)type;
763 (void)event;
764 return EINA_FALSE;
765#endif
766}
767
768static const Ecore_IMF_Context_Info xim_info = {
769 .id = "xim",
770 .description = _("X input method"),
771 .default_locales = "ko:ja:th:zh",
772 .canvas_type = "evas",
773 .canvas_required = 1,
774};
775
776static Ecore_IMF_Context_Class xim_class = {
777 .add = _ecore_imf_context_xim_add,
778 .del = _ecore_imf_context_xim_del,
779 .client_window_set = _ecore_imf_context_xim_client_window_set,
780 .client_canvas_set = NULL,
781 .show = _ecore_imf_context_xim_input_panel_show,
782 .hide = _ecore_imf_context_xim_input_panel_hide,
783 .preedit_string_get = _ecore_imf_context_xim_preedit_string_get,
784 .focus_in = _ecore_imf_context_xim_focus_in,
785 .focus_out = _ecore_imf_context_xim_focus_out,
786 .reset = _ecore_imf_context_xim_reset,
787 .cursor_position_set = NULL,
788 .use_preedit_set = _ecore_imf_context_xim_use_preedit_set,
789 .input_mode_set = NULL,
790 .filter_event = _ecore_imf_context_xim_filter_event,
791 .preedit_string_with_attributes_get = _ecore_imf_context_xim_preedit_string_with_attributes_get,
792 .prediction_allow_set = NULL,
793 .autocapital_type_set = NULL,
794 .control_panel_show = NULL,
795 .control_panel_hide = NULL,
796 .input_panel_layout_set = NULL,
797 .input_panel_layout_get = NULL,
798 .input_panel_language_set = NULL,
799 .input_panel_language_get = NULL,
800 .cursor_location_set = _ecore_imf_context_xim_cursor_location_set,
801 .input_panel_imdata_set = NULL,
802 .input_panel_imdata_get = NULL,
803 .input_panel_return_key_type_set = NULL,
804 .input_panel_return_key_disabled_set = NULL,
805 .input_panel_caps_lock_mode_set = NULL
806};
807
808static Ecore_IMF_Context *
809xim_imf_module_create(void)
810{
811 EINA_LOG_DBG("%s in", __FUNCTION__);
812 Ecore_IMF_Context *ctx = NULL;
813
814 ctx = ecore_imf_context_new(&xim_class);
815 if (!ctx)
816 goto error;
817
818 return ctx;
819
820error:
821 free(ctx);
822 return NULL;
823}
824
825static Ecore_IMF_Context *
826xim_imf_module_exit(void)
827{
828 return NULL;
829}
830
831Eina_Bool
832ecore_imf_xim_init(void)
833{
834 EINA_LOG_DBG("%s in", __FUNCTION__);
835 eina_init();
836 ecore_x_init(NULL);
837 ecore_imf_module_register(&xim_info,
838 xim_imf_module_create,
839 xim_imf_module_exit);
840
841 return EINA_TRUE;
842}
843
844void
845ecore_imf_xim_shutdown(void)
846{
847#ifdef ENABLE_XIM
848 while (open_ims) {
849 XIM_Im_Info *info = open_ims->data;
850 Ecore_X_Display *display = ecore_x_display_get();
851
852 xim_info_display_closed(display, EINA_FALSE, info);
853 }
854#endif
855
856 ecore_x_shutdown();
857 eina_shutdown();
858}
859
860EINA_MODULE_INIT(ecore_imf_xim_init);
861EINA_MODULE_SHUTDOWN(ecore_imf_xim_shutdown);
862
863#ifdef ENABLE_XIM
864/*
865 * internal functions
866 */
867Ecore_IMF_Context_Data *
868imf_context_data_new()
869{
870 Ecore_IMF_Context_Data *imf_context_data = NULL;
871 char *locale;
872
873 locale = setlocale(LC_CTYPE, "");
874 if (!locale) return NULL;
875
876 if (!XSupportsLocale()) return NULL;
877
878 imf_context_data = calloc(1, sizeof(Ecore_IMF_Context_Data));
879 if (!imf_context_data) return NULL;
880
881 imf_context_data->locale = strdup(locale);
882 if (!imf_context_data->locale) goto error;
883
884 return imf_context_data;
885error:
886 imf_context_data_destroy(imf_context_data);
887 return NULL;
888}
889
890void
891imf_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data)
892{
893 if (!imf_context_data)
894 return;
895
896 if (imf_context_data->ic)
897 XDestroyIC(imf_context_data->ic);
898
899 free(imf_context_data->preedit_chars);
900
901 if (imf_context_data->feedbacks)
902 {
903 free(imf_context_data->feedbacks);
904 imf_context_data->feedbacks = NULL;
905 }
906
907 free(imf_context_data->locale);
908 free(imf_context_data);
909}
910
911static int
912preedit_start_callback(XIC xic __UNUSED__,
913 XPointer client_data,
914 XPointer call_data __UNUSED__)
915{
916 EINA_LOG_DBG("in");
917 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
918 Ecore_IMF_Context_Data *imf_context_data;
919 imf_context_data = ecore_imf_context_data_get(ctx);
920
921 if (imf_context_data->finalizing == EINA_FALSE)
922 {
923 ecore_imf_context_preedit_start_event_add(ctx);
924 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
925 }
926 return -1;
927}
928
929static void
930preedit_done_callback(XIC xic __UNUSED__,
931 XPointer client_data,
932 XPointer call_data __UNUSED__)
933{
934 EINA_LOG_DBG("in");
935 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
936 Ecore_IMF_Context_Data *imf_context_data;
937 imf_context_data = ecore_imf_context_data_get(ctx);
938
939 if (imf_context_data->preedit_length)
940 {
941 imf_context_data->preedit_length = 0;
942 free(imf_context_data->preedit_chars);
943 imf_context_data->preedit_chars = NULL;
944 ecore_imf_context_preedit_changed_event_add(ctx);
945 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
946 }
947
948 if (imf_context_data->finalizing == EINA_FALSE)
949 {
950 ecore_imf_context_preedit_end_event_add(ctx);
951 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
952 }
953}
954
955/* FIXME */
956static int
957xim_text_to_utf8(Ecore_IMF_Context *ctx __UNUSED__,
958 XIMText *xim_text,
959 char **text)
960{
961 int text_length = 0;
962 char *result = NULL;
963
964 if (xim_text && xim_text->string.multi_byte)
965 {
966 if (xim_text->encoding_is_wchar)
967 {
968 EINA_LOG_WARN("Wide character return from Xlib not currently supported");
969 *text = NULL;
970 return 0;
971 }
972
973 /* XXX Convert to UTF-8 */
974 result = strdup(xim_text->string.multi_byte);
975 if (result)
976 {
977 text_length = eina_unicode_utf8_get_len(result);
978 if (text_length != xim_text->length)
979 {
980 EINA_LOG_WARN("Size mismatch when converting text from input method: supplied length = %d\n, result length = %d", xim_text->length, text_length);
981 }
982 }
983 else {
984 EINA_LOG_WARN("Error converting text from IM to UCS-4");
985 *text = NULL;
986 return 0;
987 }
988
989 *text = result;
990 return text_length;
991 }
992 else {
993 *text = NULL;
994 return 0;
995 }
996}
997
998static void
999preedit_draw_callback(XIC xic __UNUSED__,
1000 XPointer client_data,
1001 XIMPreeditDrawCallbackStruct *call_data)
1002{
1003 EINA_LOG_DBG("in");
1004 Eina_Bool ret = EINA_FALSE;
1005 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
1006 Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
1007 XIMText *t = call_data->text;
1008 char *tmp;
1009 Eina_Unicode *new_text = NULL;
1010 Eina_UStrbuf *preedit_bufs = NULL;
1011 int new_text_length;
1012 int i = 0;
1013
1014 preedit_bufs = eina_ustrbuf_new();
1015 if (imf_context_data->preedit_chars)
1016 {
1017 ret = eina_ustrbuf_append(preedit_bufs, imf_context_data->preedit_chars);
1018 if (ret == EINA_FALSE) goto done;
1019 }
1020
1021 new_text_length = xim_text_to_utf8(ctx, t, &tmp);
1022 if (tmp)
1023 {
1024 int tmp_len;
1025 new_text = eina_unicode_utf8_to_unicode((const char *)tmp, &tmp_len);
1026 free(tmp);
1027 }
1028
1029 if (t == NULL)
1030 {
1031 /* delete string */
1032 ret = eina_ustrbuf_remove(preedit_bufs,
1033 call_data->chg_first, call_data->chg_length);
1034 }
1035 else if (call_data->chg_length == 0)
1036 {
1037 /* insert string */
1038 ret = eina_ustrbuf_insert(preedit_bufs, new_text, call_data->chg_first);
1039 }
1040 else if (call_data->chg_length > 0)
1041 {
1042 /* replace string */
1043 ret = eina_ustrbuf_remove(preedit_bufs,
1044 call_data->chg_first, call_data->chg_length);
1045 if (ret == EINA_FALSE) goto done;
1046
1047 ret = eina_ustrbuf_insert_n(preedit_bufs, new_text,
1048 new_text_length, call_data->chg_first);
1049 if (ret == EINA_FALSE) goto done;
1050 }
1051 else {
1052 ret = EINA_FALSE;
1053 }
1054
1055done:
1056 if (ret == EINA_TRUE)
1057 {
1058 free(imf_context_data->preedit_chars);
1059 imf_context_data->preedit_chars =
1060 eina_ustrbuf_string_steal(preedit_bufs);
1061 imf_context_data->preedit_length =
1062 eina_unicode_strlen(imf_context_data->preedit_chars);
1063
1064 if (imf_context_data->feedbacks)
1065 {
1066 free(imf_context_data->feedbacks);
1067 imf_context_data->feedbacks = NULL;
1068 }
1069
1070 if (imf_context_data->preedit_length > 0)
1071 {
1072 imf_context_data->feedbacks = calloc(imf_context_data->preedit_length, sizeof(XIMFeedback));
1073
1074 for (i = 0; i < imf_context_data->preedit_length; i++)
1075 imf_context_data->feedbacks[i] = t->feedback[i];
1076 }
1077
1078 ecore_imf_context_preedit_changed_event_add(ctx);
1079 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1080 }
1081
1082 free(new_text);
1083 eina_ustrbuf_free(preedit_bufs);
1084}
1085
1086static void
1087preedit_caret_callback(XIC xic __UNUSED__,
1088 XPointer client_data,
1089 XIMPreeditCaretCallbackStruct *call_data)
1090{
1091 EINA_LOG_DBG("in");
1092 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
1093 Ecore_IMF_Context_Data *imf_context_data;
1094 imf_context_data = ecore_imf_context_data_get(ctx);
1095
1096 if (call_data->direction == XIMAbsolutePosition)
1097 {
1098 // printf("call_data->position:%d\n", call_data->position);
1099 imf_context_data->preedit_cursor = call_data->position;
1100 if (imf_context_data->finalizing == EINA_FALSE)
1101 {
1102 ecore_imf_context_preedit_changed_event_add(ctx);
1103 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1104 }
1105 }
1106}
1107
1108static XVaNestedList
1109preedit_callback_set(Ecore_IMF_Context *ctx)
1110{
1111 Ecore_IMF_Context_Data *imf_context_data;
1112 imf_context_data = ecore_imf_context_data_get(ctx);
1113
1114 imf_context_data->preedit_start_cb.client_data = (XPointer)ctx;
1115 imf_context_data->preedit_start_cb.callback = (XIMProc)preedit_start_callback;
1116
1117 imf_context_data->preedit_done_cb.client_data = (XPointer)ctx;
1118 imf_context_data->preedit_done_cb.callback = (XIMProc)preedit_done_callback;
1119
1120 imf_context_data->preedit_draw_cb.client_data = (XPointer)ctx;
1121 imf_context_data->preedit_draw_cb.callback = (XIMProc)preedit_draw_callback;
1122
1123 imf_context_data->preedit_caret_cb.client_data = (XPointer)ctx;
1124 imf_context_data->preedit_caret_cb.callback = (XIMProc)preedit_caret_callback;
1125
1126 return XVaCreateNestedList(0,
1127 XNPreeditStartCallback,
1128 &imf_context_data->preedit_start_cb,
1129 XNPreeditDoneCallback,
1130 &imf_context_data->preedit_done_cb,
1131 XNPreeditDrawCallback,
1132 &imf_context_data->preedit_draw_cb,
1133 XNPreeditCaretCallback,
1134 &imf_context_data->preedit_caret_cb,
1135 NULL);
1136}
1137
1138static XIC
1139get_ic(Ecore_IMF_Context *ctx)
1140{
1141 Ecore_IMF_Context_Data *imf_context_data;
1142 XIC ic;
1143 imf_context_data = ecore_imf_context_data_get(ctx);
1144 ic = imf_context_data->ic;
1145 if (!ic)
1146 {
1147 XIM_Im_Info *im_info = imf_context_data->im_info;
1148 XVaNestedList preedit_attr = NULL;
1149 XIMStyle im_style = 0;
1150 XPoint spot = { 0, 0 };
1151 char *name = NULL;
1152
1153 if (!im_info)
1154 {
1155 EINA_LOG_WARN("Doesn't open XIM.");
1156 return NULL;
1157 }
1158
1159 // supported styles
1160#if 0
1161 int i;
1162 if (im_info->xim_styles)
1163 {
1164 for (i = 0; i < im_info->xim_styles->count_styles; i++)
1165 {
1166 printf("%i: ", i);
1167 if (im_info->xim_styles->supported_styles[i] & XIMPreeditCallbacks)
1168 printf("XIMPreeditCallbacks | ");
1169 if (im_info->xim_styles->supported_styles[i] & XIMPreeditPosition)
1170 printf("XIMPreeditPosition | ");
1171 if (im_info->xim_styles->supported_styles[i] & XIMPreeditArea)
1172 printf("XIMPreeditArea | ");
1173 if (im_info->xim_styles->supported_styles[i] & XIMPreeditNothing)
1174 printf("XIMPreeditNothing | ");
1175 if (im_info->xim_styles->supported_styles[i] & XIMPreeditNone)
1176 printf("XIMPreeditNone | ");
1177 if (im_info->xim_styles->supported_styles[i] & XIMStatusArea)
1178 printf("XIMStatusArea | ");
1179 if (im_info->xim_styles->supported_styles[i] & XIMStatusCallbacks)
1180 printf("XIMStatusCallbacks | ");
1181 if (im_info->xim_styles->supported_styles[i] & XIMStatusNothing)
1182 printf("XIMStatusNothing | ");
1183 if (im_info->xim_styles->supported_styles[i] & XIMStatusNone)
1184 printf("XIMStatusNone | ");
1185 printf("\n");
1186 }
1187 }
1188#endif
1189 // "OverTheSpot" = XIMPreeditPosition | XIMStatusNothing
1190 // "OffTheSpot" = XIMPreeditArea | XIMStatusArea
1191 // "Root" = XIMPreeditNothing | XIMStatusNothing
1192
1193 if (imf_context_data->use_preedit == EINA_TRUE)
1194 {
1195 if (im_info->supports_cursor)
1196 {
1197 // kinput2 DOES do this...
1198 XFontSet fs;
1199 char **missing_charset_list;
1200 int missing_charset_count;
1201 char *def_string;
1202
1203 im_style |= XIMPreeditPosition;
1204 im_style |= XIMStatusNothing;
1205 fs = XCreateFontSet(ecore_x_display_get(),
1206 "fixed",
1207 &missing_charset_list,
1208 &missing_charset_count,
1209 &def_string);
1210 preedit_attr = XVaCreateNestedList(0,
1211 XNSpotLocation, &spot,
1212 XNFontSet, fs,
1213 NULL);
1214 }
1215 else
1216 {
1217 im_style |= XIMPreeditCallbacks;
1218 im_style |= XIMStatusNothing;
1219 preedit_attr = preedit_callback_set(ctx);
1220 }
1221 name = XNPreeditAttributes;
1222 }
1223 else
1224 {
1225 im_style |= XIMPreeditNothing;
1226 im_style |= XIMStatusNothing;
1227 }
1228
1229 if (im_info->im)
1230 {
1231 ic = XCreateIC(im_info->im,
1232 XNInputStyle, im_style,
1233 XNClientWindow, imf_context_data->win,
1234 name, preedit_attr, NULL);
1235 }
1236 XFree(preedit_attr);
1237 if (ic)
1238 {
1239 unsigned long mask = 0xaaaaaaaa;
1240 XGetICValues(ic,
1241 XNFilterEvents, &mask,
1242 NULL);
1243 imf_context_data->mask = mask;
1244 ecore_x_event_mask_set(imf_context_data->win, mask);
1245 }
1246
1247 imf_context_data->ic = ic;
1248 if (ic && imf_context_data->has_focus == EINA_TRUE)
1249 XSetICFocus(ic);
1250 }
1251
1252 return ic;
1253}
1254
1255static void
1256reinitialize_ic(Ecore_IMF_Context *ctx)
1257{
1258 Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
1259 XIC ic = imf_context_data->ic;
1260 if (ic)
1261 {
1262 XDestroyIC(ic);
1263 imf_context_data->ic = NULL;
1264 if (imf_context_data->preedit_length)
1265 {
1266 imf_context_data->preedit_length = 0;
1267 free(imf_context_data->preedit_chars);
1268 imf_context_data->preedit_chars = NULL;
1269 ecore_imf_context_preedit_changed_event_add(ctx);
1270 ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1271 }
1272 }
1273}
1274
1275static void
1276reinitialize_all_ics(XIM_Im_Info *info)
1277{
1278 Eina_List *tmp_list;
1279 Ecore_IMF_Context *ctx;
1280
1281 EINA_LIST_FOREACH (info->ics, tmp_list, ctx)
1282 reinitialize_ic(ctx);
1283}
1284
1285static void
1286set_ic_client_window(Ecore_IMF_Context *ctx,
1287 Ecore_X_Window window)
1288{
1289 EINA_LOG_DBG("in");
1290 Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
1291 Ecore_X_Window old_win;
1292
1293 /* reinitialize IC */
1294 reinitialize_ic(ctx);
1295
1296 old_win = imf_context_data->win;
1297 EINA_LOG_DBG("old_win:%d window:%d ", old_win, window);
1298 if (old_win != 0 && old_win != window) /* XXX how do check window... */
1299 {
1300 XIM_Im_Info *info;
1301 info = imf_context_data->im_info;
1302 info->ics = eina_list_remove(info->ics, imf_context_data);
1303 imf_context_data->im_info = NULL;
1304 }
1305
1306 imf_context_data->win = window;
1307
1308 if (window) /* XXX */
1309 {
1310 XIM_Im_Info *info = NULL;
1311 info = get_im(window, imf_context_data->locale);
1312 imf_context_data->im_info = info;
1313 imf_context_data->im_info->ics =
1314 eina_list_prepend(imf_context_data->im_info->ics,
1315 imf_context_data);
1316 }
1317}
1318
1319static XIM_Im_Info *
1320get_im(Ecore_X_Window window,
1321 char *locale)
1322{
1323 EINA_LOG_DBG("in");
1324
1325 Eina_List *l;
1326 XIM_Im_Info *im_info = NULL;
1327 XIM_Im_Info *info = NULL;
1328 EINA_LIST_FOREACH (open_ims, l, im_info) {
1329 if (strcmp(im_info->locale, locale) == 0)
1330 {
1331 if (im_info->im)
1332 {
1333 return im_info;
1334 }
1335 else {
1336 info = im_info;
1337 break;
1338 }
1339 }
1340 }
1341
1342 if (!info)
1343 {
1344 info = calloc(1, sizeof(XIM_Im_Info));
1345 if (!info) return NULL;
1346 open_ims = eina_list_prepend(open_ims, info);
1347 info->win = window;
1348 info->locale = strdup(locale);
1349 info->reconnecting = EINA_FALSE;
1350 }
1351
1352 xim_info_try_im(info);
1353 return info;
1354}
1355
1356/* initialize info->im */
1357static void
1358xim_info_try_im(XIM_Im_Info *info)
1359{
1360 Ecore_X_Display *dsp;
1361
1362 assert(info->im == NULL);
1363 if (info->reconnecting == EINA_TRUE)
1364 return;
1365
1366 if (XSupportsLocale())
1367 {
1368 if (!XSetLocaleModifiers(""))
1369 EINA_LOG_WARN("Unable to set locale modifiers with XSetLocaleModifiers()");
1370 dsp = ecore_x_display_get();
1371 info->im = XOpenIM(dsp, NULL, NULL, NULL);
1372 if (!info->im)
1373 {
1374 XRegisterIMInstantiateCallback(dsp,
1375 NULL, NULL, NULL,
1376 xim_instantiate_callback,
1377 (XPointer)info);
1378 info->reconnecting = EINA_TRUE;
1379 return;
1380 }
1381 setup_im(info);
1382 }
1383}
1384
1385static void
1386xim_info_display_closed(Ecore_X_Display *display __UNUSED__,
1387 int is_error __UNUSED__,
1388 XIM_Im_Info *info)
1389{
1390 Eina_List *ics, *tmp_list;
1391 Ecore_IMF_Context *ctx;
1392
1393 open_ims = eina_list_remove(open_ims, info);
1394
1395 ics = info->ics;
1396 info->ics = NULL;
1397
1398 EINA_LIST_FOREACH (ics, tmp_list, ctx)
1399 set_ic_client_window(ctx, 0);
1400
1401 EINA_LIST_FREE (ics, ctx) {
1402 Ecore_IMF_Context_Data *imf_context_data;
1403 imf_context_data = ecore_imf_context_data_get(ctx);
1404 imf_context_data_destroy(imf_context_data);
1405 }
1406
1407 free(info->locale);
1408
1409 if (info->im)
1410 XCloseIM(info->im);
1411
1412 free(info);
1413}
1414
1415static void
1416xim_instantiate_callback(Display *display,
1417 XPointer client_data,
1418 XPointer call_data __UNUSED__)
1419{
1420 XIM_Im_Info *info = (XIM_Im_Info *)client_data;
1421 XIM im = NULL;
1422
1423 im = XOpenIM(display, NULL, NULL, NULL);
1424
1425 if (!im)
1426 {
1427 fprintf(stderr, "Failed to connect to IM\n");
1428 return;
1429 }
1430
1431 info->im = im;
1432 setup_im(info);
1433
1434 XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL,
1435 xim_instantiate_callback,
1436 (XPointer)info);
1437 info->reconnecting = EINA_FALSE;
1438}
1439
1440static void
1441setup_im(XIM_Im_Info *info)
1442{
1443 XIMValuesList *ic_values = NULL;
1444 XIMCallback im_destroy_callback;
1445
1446 if (!info->im)
1447 return;
1448
1449 im_destroy_callback.client_data = (XPointer)info;
1450 im_destroy_callback.callback = (XIMProc)xim_destroy_callback;
1451 XSetIMValues(info->im,
1452 XNDestroyCallback, &im_destroy_callback,
1453 NULL);
1454
1455 XGetIMValues(info->im,
1456 XNQueryInputStyle, &info->xim_styles,
1457 XNQueryICValuesList, &ic_values,
1458 NULL);
1459
1460 if (ic_values)
1461 {
1462 int i;
1463
1464 for (i = 0; i < ic_values->count_values; i++)
1465 {
1466 if (!strcmp(ic_values->supported_values[i],
1467 XNStringConversionCallback))
1468 info->supports_string_conversion = EINA_TRUE;
1469 if (!strcmp(ic_values->supported_values[i],
1470 XNCursor))
1471 info->supports_cursor = EINA_TRUE;
1472 }
1473#if 0
1474 printf("values........\n");
1475 for (i = 0; i < ic_values->count_values; i++)
1476 printf("%s\n", ic_values->supported_values[i]);
1477 printf("styles........\n");
1478 for (i = 0; i < info->xim_styles->count_styles; i++)
1479 printf("%lx\n", info->xim_styles->supported_styles[i]);
1480#endif
1481 XFree(ic_values);
1482 }
1483}
1484
1485static void
1486xim_destroy_callback(XIM xim __UNUSED__,
1487 XPointer client_data,
1488 XPointer call_data __UNUSED__)
1489{
1490 XIM_Im_Info *info = (XIM_Im_Info *)client_data;
1491 info->im = NULL;
1492
1493 reinitialize_all_ics(info);
1494 xim_info_try_im(info);
1495
1496 return;
1497}
1498
1499#endif /* ENABLE_XIM */