5d455bd6dd43cda0bdbe86b8165fc1d6598dcf1d
[platform/core/uifw/isf.git] / ism / extras / efl_immodule / isf_imf_context.cpp
1 /*
2  * ISF(Input Service Framework)
3  *
4  * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
5  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6  *
7  * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Haifeng Deng <haifeng.deng@samsung.com>
8  *
9  * This library is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU Lesser General Public License as published by the
11  * Free Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
15  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this library; if not, write to the Free Software Foundation, Inc., 51
21  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24
25 #define Uses_SCIM_BACKEND
26 #define Uses_SCIM_IMENGINE_MODULE
27 #define Uses_SCIM_HELPER_MODULE
28 #define Uses_SCIM_HOTKEY
29 #define Uses_SCIM_PANEL_CLIENT
30
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <sys/time.h>
34 #include <sys/times.h>
35 #include <pthread.h>
36 #include <langinfo.h>
37
38 #include <Evas.h>
39 #include <Ecore_Evas.h>
40 #include <Ecore_X.h>
41 #include <X11/XKBlib.h>
42 #include <X11/keysym.h>
43 #include <X11/Xutil.h>
44 #include <glib.h>
45 #include <utilX.h>
46 #include <vconf.h>
47 #include <vconf-keys.h>
48 #include <notification.h>
49
50 #include "scim_private.h"
51 #include "scim.h"
52 #include "isf_imf_context.h"
53 #include "isf_imf_control_ui.h"
54
55 #ifndef CODESET
56 # define CODESET "INVALID"
57 #endif
58
59 #define ENABLE_BACKKEY 1
60
61 using namespace scim;
62
63 struct _EcoreIMFContextISFImpl {
64     EcoreIMFContextISF      *parent;
65     IMEngineInstancePointer  si;
66     Ecore_X_Window           client_window;
67     Evas                    *client_canvas;
68     Ecore_IMF_Input_Mode     input_mode;
69     WideString               preedit_string;
70     AttributeList            preedit_attrlist;
71     Ecore_IMF_Autocapital_Type autocapital_type;
72     void                    *imdata;
73     int                      imdata_size;
74     int                      preedit_caret;
75     int                      cursor_x;
76     int                      cursor_y;
77     int                      cursor_top_y;
78     int                      cursor_pos;
79     bool                     use_preedit;
80     bool                     is_on;
81     bool                     shared_si;
82     bool                     preedit_started;
83     bool                     preedit_updating;
84     bool                     need_commit_preedit;
85     bool                     uppercase;
86     bool                     prediction_allow;
87
88     EcoreIMFContextISFImpl  *next;
89 };
90
91 /* Input Context handling functions. */
92 static EcoreIMFContextISFImpl *new_ic_impl              (EcoreIMFContextISF     *parent);
93 static void                    delete_ic_impl           (EcoreIMFContextISFImpl *impl);
94 static void                    delete_all_ic_impl       (void);
95
96 static EcoreIMFContextISF     *find_ic                  (int                     id);
97
98
99 /* private functions */
100 static void     panel_slot_reload_config                (int                     context);
101 static void     panel_slot_exit                         (int                     context);
102 static void     panel_slot_update_candidate_item_layout (int                     context,
103                                                          const std::vector<uint32> &row_items);
104 static void     panel_slot_update_lookup_table_page_size(int                     context,
105                                                          int                     page_size);
106 static void     panel_slot_lookup_table_page_up         (int                     context);
107 static void     panel_slot_lookup_table_page_down       (int                     context);
108 static void     panel_slot_trigger_property             (int                     context,
109                                                          const String           &property);
110 static void     panel_slot_process_helper_event         (int                     context,
111                                                          const String           &target_uuid,
112                                                          const String           &helper_uuid,
113                                                          const Transaction      &trans);
114 static void     panel_slot_move_preedit_caret           (int                     context,
115                                                          int                     caret_pos);
116 static void     panel_slot_update_preedit_caret         (int                     context,
117                                                          int                     caret);
118 static void     panel_slot_select_aux                   (int                     context,
119                                                          int                     aux_index);
120 static void     panel_slot_select_candidate             (int                     context,
121                                                          int                     cand_index);
122 static void     panel_slot_process_key_event            (int                     context,
123                                                          const KeyEvent         &key);
124 static void     panel_slot_commit_string                (int                     context,
125                                                          const WideString       &wstr);
126 static void     panel_slot_forward_key_event            (int                     context,
127                                                          const KeyEvent         &key);
128 static void     panel_slot_request_help                 (int                     context);
129 static void     panel_slot_request_factory_menu         (int                     context);
130 static void     panel_slot_change_factory               (int                     context,
131                                                          const String           &uuid);
132 static void     panel_slot_reset_keyboard_ise           (int                     context);
133 static void     panel_slot_update_keyboard_ise          (int                     context);
134 static void     panel_slot_show_preedit_string          (int                     context);
135 static void     panel_slot_hide_preedit_string          (int                     context);
136 static void     panel_slot_update_preedit_string        (int                     context,
137                                                          const WideString       &str,
138                                                          const AttributeList    &attrs);
139 static void     panel_slot_get_surrounding_text         (int                     context,
140                                                          int                     maxlen_before,
141                                                          int                     maxlen_after);
142 static void     panel_slot_delete_surrounding_text      (int                     context,
143                                                          int                     offset,
144                                                          int                     len);
145
146 static void     panel_req_focus_in                      (EcoreIMFContextISF     *ic);
147 static void     panel_req_update_factory_info           (EcoreIMFContextISF     *ic);
148 static void     panel_req_update_spot_location          (EcoreIMFContextISF     *ic);
149 static void     panel_req_update_cursor_position        (EcoreIMFContextISF     *ic, int cursor_pos);
150 static void     panel_req_show_help                     (EcoreIMFContextISF     *ic);
151 static void     panel_req_show_factory_menu             (EcoreIMFContextISF     *ic);
152
153 /* Panel iochannel handler*/
154 static bool     panel_initialize                        (void);
155 static void     panel_finalize                          (void);
156 static Eina_Bool panel_iochannel_handler                (void                   *data,
157                                                          Ecore_Fd_Handler       *fd_handler);
158
159 /* utility functions */
160 static bool     filter_hotkeys                          (EcoreIMFContextISF     *ic,
161                                                          const KeyEvent         &key);
162 static void     turn_on_ic                              (EcoreIMFContextISF     *ic);
163 static void     turn_off_ic                             (EcoreIMFContextISF     *ic);
164 static void     set_ic_capabilities                     (EcoreIMFContextISF     *ic);
165
166 static void     initialize                              (void);
167 static void     finalize                                (void);
168
169 static void     open_next_factory                       (EcoreIMFContextISF     *ic);
170 static void     open_previous_factory                   (EcoreIMFContextISF     *ic);
171 static void     open_specific_factory                   (EcoreIMFContextISF     *ic,
172                                                          const String           &uuid);
173 static void     initialize_modifier_bits                (Display *display);
174 static unsigned int scim_x11_keymask_scim_to_x11        (Display *display, uint16 scimkeymask);
175 static XKeyEvent createKeyEvent                         (bool press, int keycode, int modifiers, bool fake);
176 static void     send_x_key_event                        (const KeyEvent &key, bool fake);
177
178 static void     attach_instance                         (const IMEngineInstancePointer &si);
179
180 /* slot functions */
181 static void     slot_show_preedit_string                (IMEngineInstanceBase   *si);
182 static void     slot_show_aux_string                    (IMEngineInstanceBase   *si);
183 static void     slot_show_lookup_table                  (IMEngineInstanceBase   *si);
184
185 static void     slot_hide_preedit_string                (IMEngineInstanceBase   *si);
186 static void     slot_hide_aux_string                    (IMEngineInstanceBase   *si);
187 static void     slot_hide_lookup_table                  (IMEngineInstanceBase   *si);
188
189 static void     slot_update_preedit_caret               (IMEngineInstanceBase   *si,
190                                                          int                     caret);
191 static void     slot_update_preedit_string              (IMEngineInstanceBase   *si,
192                                                          const WideString       &str,
193                                                          const AttributeList    &attrs);
194 static void     slot_update_aux_string                  (IMEngineInstanceBase   *si,
195                                                          const WideString       &str,
196                                                          const AttributeList    &attrs);
197 static void     slot_commit_string                      (IMEngineInstanceBase   *si,
198                                                          const WideString       &str);
199 static void     slot_forward_key_event                  (IMEngineInstanceBase   *si,
200                                                          const KeyEvent         &key);
201 static void     slot_update_lookup_table                (IMEngineInstanceBase   *si,
202                                                          const LookupTable      &table);
203
204 static void     slot_register_properties                (IMEngineInstanceBase   *si,
205                                                          const PropertyList     &properties);
206 static void     slot_update_property                    (IMEngineInstanceBase   *si,
207                                                          const Property         &property);
208 static void     slot_beep                               (IMEngineInstanceBase   *si);
209 static void     slot_start_helper                       (IMEngineInstanceBase   *si,
210                                                          const String           &helper_uuid);
211 static void     slot_stop_helper                        (IMEngineInstanceBase   *si,
212                                                          const String           &helper_uuid);
213 static void     slot_send_helper_event                  (IMEngineInstanceBase   *si,
214                                                          const String           &helper_uuid,
215                                                          const Transaction      &trans);
216 static bool     slot_get_surrounding_text               (IMEngineInstanceBase   *si,
217                                                          WideString             &text,
218                                                          int                    &cursor,
219                                                          int                     maxlen_before,
220                                                          int                     maxlen_after);
221 static bool     slot_delete_surrounding_text            (IMEngineInstanceBase   *si,
222                                                          int                     offset,
223                                                          int                     len);
224
225 static void     slot_expand_candidate                   (IMEngineInstanceBase   *si);
226 static void     slot_contract_candidate                 (IMEngineInstanceBase   *si);
227
228 static void     slot_set_candidate_style                (IMEngineInstanceBase   *si,
229                                                          ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line,
230                                                          ISF_CANDIDATE_MODE_T    mode);
231
232 static void     reload_config_callback                  (const ConfigPointer    &config);
233
234 static void     fallback_commit_string_cb               (IMEngineInstanceBase   *si,
235                                                          const WideString       &str);
236 static void     _display_input_language                 (EcoreIMFContextISF *ic);
237
238 /* Local variables declaration */
239 static String                                           _language;
240 static EcoreIMFContextISFImpl                          *_used_ic_impl_list          = 0;
241 static EcoreIMFContextISFImpl                          *_free_ic_impl_list          = 0;
242 static EcoreIMFContextISF                              *_ic_list                    = 0;
243
244 static KeyboardLayout                                   _keyboard_layout            = SCIM_KEYBOARD_Default;
245 static int                                              _valid_key_mask             = SCIM_KEY_AllMasks;
246
247 static FrontEndHotkeyMatcher                            _frontend_hotkey_matcher;
248 static IMEngineHotkeyMatcher                            _imengine_hotkey_matcher;
249
250 static IMEngineInstancePointer                          _default_instance;
251
252 static ConfigModule                                    *_config_module              = 0;
253 static ConfigPointer                                    _config;
254 static BackEndPointer                                   _backend;
255
256 static EcoreIMFContextISF                              *_focused_ic                 = 0;
257
258 static bool                                             _scim_initialized           = false;
259
260 static int                                              _instance_count             = 0;
261 static int                                              _context_count              = 0;
262
263 static IMEngineFactoryPointer                           _fallback_factory;
264 static IMEngineInstancePointer                          _fallback_instance;
265 static PanelClient                                      _panel_client;
266 static int                                              _panel_client_id            = 0;
267
268 static Ecore_Fd_Handler                                *_panel_iochannel_read_handler = 0;
269 static Ecore_Fd_Handler                                *_panel_iochannel_err_handler  = 0;
270
271 static Ecore_X_Window                                   _client_window              = 0;
272 static Ecore_Event_Handler                             *_key_down_handler           = 0;
273 static Ecore_Event_Handler                             *_key_up_handler             = 0;
274
275 static bool                                             _on_the_spot                = true;
276 static bool                                             _shared_input_method        = false;
277 static double                                           space_key_time              = 0.0;
278
279 static Eina_Bool                                        autoperiod_allow            = EINA_FALSE;
280 static Eina_Bool                                        autocap_allow               = EINA_FALSE;
281 static Eina_Bool                                        desktop_mode                = EINA_FALSE;
282
283 static Display *__current_display      = 0;
284 static int      __current_alt_mask     = Mod1Mask;
285 static int      __current_meta_mask    = 0;
286 static int      __current_super_mask   = 0;
287 static int      __current_hyper_mask   = 0;
288 static int      __current_numlock_mask = Mod2Mask;
289
290 extern Ecore_IMF_Context *input_panel_ctx;
291
292 // A hack to shutdown the immodule cleanly even if im_module_exit () is not called when exiting.
293 class FinalizeHandler
294 {
295 public:
296     FinalizeHandler () {
297         SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler ()\n";
298     }
299     ~FinalizeHandler () {
300         SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler ()\n";
301         finalize ();
302     }
303 };
304
305 static FinalizeHandler                                  _finalize_handler;
306
307 EAPI ConfigPointer isf_imf_context_get_config (void)
308 {
309     return _config;
310 }
311
312 EAPI EcoreIMFContextISF *
313 get_focused_ic ()
314 {
315     return _focused_ic;
316 }
317
318 EAPI int
319 get_panel_client_id (void)
320 {
321     return _panel_client_id;
322 }
323
324 EAPI Eina_Bool
325 get_desktop_mode ()
326 {
327     return desktop_mode;
328 }
329
330 static unsigned int
331 get_time (void)
332 {
333     unsigned int tint;
334     struct timeval tv;
335     struct timezone tz;           /* is not used since ages */
336     gettimeofday (&tv, &tz);
337     tint = tv.tv_sec * 1000;
338     tint = tint / 1000 * 1000;
339     tint = tint + tv.tv_usec / 1000;
340     return tint;
341 }
342
343 /* Function Implementations */
344 static EcoreIMFContextISFImpl *
345 new_ic_impl (EcoreIMFContextISF *parent)
346 {
347     EcoreIMFContextISFImpl *impl = NULL;
348
349     if (_free_ic_impl_list != NULL) {
350         impl = _free_ic_impl_list;
351         _free_ic_impl_list = _free_ic_impl_list->next;
352     } else {
353         impl = new EcoreIMFContextISFImpl;
354         if (impl == NULL)
355             return NULL;
356     }
357
358     impl->uppercase = false;
359     impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
360     impl->next = _used_ic_impl_list;
361     _used_ic_impl_list = impl;
362
363     impl->parent = parent;
364     impl->imdata = NULL;
365     impl->imdata_size = 0;
366
367     return impl;
368 }
369
370 static void
371 delete_ic_impl (EcoreIMFContextISFImpl *impl)
372 {
373     EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
374
375     for (; rec != 0; last = rec, rec = rec->next) {
376         if (rec == impl) {
377             if (last != 0)
378                 last->next = rec->next;
379             else
380                 _used_ic_impl_list = rec->next;
381
382             rec->next = _free_ic_impl_list;
383             _free_ic_impl_list = rec;
384
385             if (rec->imdata) {
386                 free (rec->imdata);
387                 rec->imdata = NULL;
388             }
389
390             rec->imdata_size = 0;
391             rec->parent = 0;
392             rec->si.reset ();
393             rec->client_window = 0;
394             rec->preedit_string = WideString ();
395             rec->preedit_attrlist.clear ();
396
397             return;
398         }
399     }
400 }
401
402 static void
403 delete_all_ic_impl (void)
404 {
405     EcoreIMFContextISFImpl *it = _used_ic_impl_list;
406
407     while (it != 0) {
408         _used_ic_impl_list = it->next;
409         delete it;
410         it = _used_ic_impl_list;
411     }
412
413     it = _free_ic_impl_list;
414     while (it != 0) {
415         _free_ic_impl_list = it->next;
416         delete it;
417         it = _free_ic_impl_list;
418     }
419 }
420
421 static EcoreIMFContextISF *
422 find_ic (int id)
423 {
424     EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
425
426     while (rec != 0) {
427         if (rec->parent && rec->parent->id == id)
428             return rec->parent;
429         rec = rec->next;
430     }
431
432     return 0;
433 }
434
435 static Eina_Bool
436 _key_down_cb (void *data, int type, void *event)
437 {
438     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
439
440     Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event;
441     if (!ev || !_focused_ic || !_focused_ic->ctx) return ECORE_CALLBACK_RENEW;
442
443     if (!strcmp (ev->keyname, KEY_END) &&
444         ecore_imf_context_input_panel_state_get (_focused_ic->ctx) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
445         LOGD ("END key is pressed\n");
446         return ECORE_CALLBACK_CANCEL;
447     }
448
449     return ECORE_CALLBACK_RENEW;
450 }
451
452 static Eina_Bool
453 _key_up_cb (void *data, int type, void *event)
454 {
455     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
456
457     Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event;
458     if (!ev || !_focused_ic || !_focused_ic->ctx) return ECORE_CALLBACK_RENEW;
459
460     if (!strcmp (ev->keyname, KEY_END) &&
461         ecore_imf_context_input_panel_state_get (_focused_ic->ctx) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
462         LOGD ("END key is released\n");
463         isf_imf_context_input_panel_instant_hide (_focused_ic->ctx);
464         return ECORE_CALLBACK_CANCEL;
465     }
466
467     return ECORE_CALLBACK_RENEW;
468 }
469
470 static void
471 _check_desktop_mode (Ecore_X_Window win)
472 {
473     char *profile = ecore_x_e_window_profile_get (win);
474     if (profile && (strcmp (profile, "desktop") == 0)) {
475         desktop_mode = EINA_TRUE;
476     } else {
477         desktop_mode = EINA_FALSE;
478     }
479
480     if (profile)
481         free (profile);
482 }
483
484 static Eina_Bool
485 _x_prop_change (void *data, int type, void *event)
486 {
487     Ecore_X_Event_Window_Property *e = (Ecore_X_Event_Window_Property *)event;
488     Ecore_X_Window xwin = (Ecore_X_Window)data;
489
490     if (e->win != xwin) return ECORE_CALLBACK_PASS_ON;
491
492     if (e->atom == ECORE_X_ATOM_E_PROFILE) {
493         _check_desktop_mode (e->win);
494     }
495
496     return ECORE_CALLBACK_PASS_ON;
497 }
498
499 EAPI int
500 register_key_handler ()
501 {
502     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
503
504 #ifdef ENABLE_BACKKEY
505     if (!_key_down_handler)
506         _key_down_handler = ecore_event_handler_add (ECORE_EVENT_KEY_DOWN, _key_down_cb, NULL);
507
508     if (!_key_up_handler)
509         _key_up_handler = ecore_event_handler_add (ECORE_EVENT_KEY_UP, _key_up_cb, NULL);
510 #endif
511
512     return EXIT_SUCCESS;
513 }
514
515 EAPI int
516 unregister_key_handler ()
517 {
518     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
519
520     if (_key_down_handler) {
521         ecore_event_handler_del (_key_down_handler);
522         _key_down_handler = NULL;
523     }
524
525     if (_key_up_handler) {
526         ecore_event_handler_del (_key_up_handler);
527         _key_up_handler = NULL;
528     }
529
530     return EXIT_SUCCESS;
531 }
532
533 static void
534 set_prediction_allow (IMEngineInstancePointer si, bool prediction)
535 {
536     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
537
538     if (si)
539         si->set_prediction_allow (prediction);
540 }
541
542 static void
543 autoperiod_insert (Ecore_IMF_Context *ctx)
544 {
545     char *plain_str = NULL;
546     char *markup_str = NULL;
547     int cursor_pos = 0;
548     Eina_Unicode *ustr = NULL;
549     Ecore_IMF_Event_Delete_Surrounding ev;
550
551     if (!ctx) return;
552
553     Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
554     if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
555         return;
556
557     if (autoperiod_allow == EINA_FALSE)
558         return;
559
560     if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
561         goto done;
562
563     ecore_imf_context_surrounding_get (ctx, &markup_str, &cursor_pos);
564     if (!markup_str) goto done;
565
566     // Convert into plain string
567     plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
568     if (!plain_str) goto done;
569
570     // Convert string from UTF-8 to unicode
571     ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
572     if (!ustr) goto done;
573
574     if (cursor_pos < 2) goto done;
575
576     if (((ustr[cursor_pos-2] != ':') && (ustr[cursor_pos-2] != ';') &&
577         (ustr[cursor_pos-2] != '.') && (ustr[cursor_pos-2] != ',') &&
578         (ustr[cursor_pos-2] != '?') && (ustr[cursor_pos-2] != '!') &&
579         (ustr[cursor_pos-2] != ' ')) && ((ustr[cursor_pos-1] == ' ') || (ustr[cursor_pos-1] == '\240'))) {
580         ev.ctx = ctx;
581         ev.n_chars = 1;
582         ev.offset = -1;
583         ecore_imf_context_delete_surrounding_event_add (ctx, -1, 1);
584         ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
585
586         ecore_imf_context_commit_event_add (ctx, ".");
587         ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)".");
588      }
589
590 done:
591     if (markup_str) free (markup_str);
592     if (plain_str) free (plain_str);
593     if (ustr) free (ustr);
594     space_key_time = ecore_time_get ();
595 }
596
597 static Eina_Bool
598 analyze_surrounding_text (Ecore_IMF_Context *ctx)
599 {
600     char *plain_str = NULL;
601     char *markup_str = NULL;
602     const char *puncs[] = {". ", ".\302\240", "! ", "!\302\240", "? ", "?\302\240", "¿ ", "¿\302\240", "¡ ", "¡\302\240" };
603     Eina_Bool ret = EINA_FALSE;
604     int cursor_pos = 0;
605     int i = 0;
606     Eina_Unicode *tail = NULL;
607     Eina_Unicode *ustr = NULL;
608     const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
609     Eina_Unicode *uni_puncs[punc_num];
610     EcoreIMFContextISF *context_scim;
611
612     if (!ctx) return EINA_FALSE;
613     context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
614     if (!context_scim || !context_scim->impl) return EINA_FALSE;
615
616     switch (context_scim->impl->autocapital_type) {
617         case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
618             return EINA_FALSE;
619         case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
620             return EINA_TRUE;
621         default:
622             break;
623     }
624
625     if (context_scim->impl->cursor_pos == 0)
626         return EINA_TRUE;
627
628     for (i = 0; i < punc_num; i++) {
629         uni_puncs[i] = eina_unicode_utf8_to_unicode (puncs[i], NULL);
630     }
631
632     ecore_imf_context_surrounding_get (ctx, &markup_str, &cursor_pos);
633     if (!markup_str) goto done;
634
635     if (cursor_pos == 0) {
636         ret = EINA_TRUE;
637         goto done;
638     }
639
640     // Convert into plain string
641     plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
642     if (!plain_str) goto done;
643
644     // Convert string from UTF-8 to unicode
645     ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
646     if (!ustr) goto done;
647
648     if (cursor_pos >= 1) {
649         if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
650             if (ustr[cursor_pos-1] == ' ' || ustr[cursor_pos-1] == '\302\240') {
651                 ret = EINA_TRUE;
652                 goto done;
653             }
654         }
655
656         // Check paragraph separator <PS> and carriage return  <br>
657         if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
658             ret = EINA_TRUE;
659             goto done;
660         }
661     }
662
663     // check punctuation
664     if (cursor_pos >= 2) {
665         tail = eina_unicode_strndup (ustr+cursor_pos-2, 2);
666
667         if (tail) {
668             for (i = 0; i < punc_num; i++) {
669                 if (!eina_unicode_strcmp (tail, uni_puncs[i])) {
670                     ret = EINA_TRUE;
671                     break;
672                 }
673             }
674             free (tail);
675             tail = NULL;
676         }
677     }
678
679 done:
680     if (ustr) free (ustr);
681     if (markup_str) free (markup_str);
682     if (plain_str) free (plain_str);
683
684     for (i = 0; i < punc_num; i++) {
685         if (uni_puncs[i]) free (uni_puncs[i]);
686     }
687
688     return ret;
689 }
690
691 EAPI Eina_Bool
692 caps_mode_check (Ecore_IMF_Context *ctx, Eina_Bool force, Eina_Bool noti)
693 {
694     Eina_Bool uppercase;
695     EcoreIMFContextISF *context_scim;
696
697     if (!ctx) return EINA_FALSE;
698     context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
699
700     Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
701     if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
702         return EINA_FALSE;
703
704     // Check autocapital type
705     if (!context_scim || !context_scim->impl)
706         return EINA_FALSE;
707
708     if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
709         uppercase = EINA_TRUE;
710     } else {
711         if (autocap_allow == EINA_FALSE)
712             return EINA_FALSE;
713
714         if (analyze_surrounding_text (ctx)) {
715             uppercase = EINA_TRUE;
716         } else {
717             uppercase = EINA_FALSE;
718         }
719     }
720
721     if (force) {
722         context_scim->impl->uppercase = uppercase;
723         if (noti)
724             isf_imf_context_input_panel_caps_mode_set (ctx, uppercase);
725     } else {
726         if (context_scim->impl->uppercase != uppercase) {
727             context_scim->impl->uppercase = uppercase;
728             if (noti)
729                 isf_imf_context_input_panel_caps_mode_set (ctx, uppercase);
730         }
731     }
732
733     return uppercase;
734 }
735
736 static void
737 window_to_screen_geometry_get (Ecore_X_Window client_win, int *x, int *y)
738 {
739     Ecore_X_Window root_window, win;
740     int win_x, win_y;
741     int sum_x = 0, sum_y = 0;
742
743     root_window = ecore_x_window_root_get (client_win);
744     win = client_win;
745
746     while (root_window != win) {
747         ecore_x_window_geometry_get (win, &win_x, &win_y, NULL, NULL);
748         sum_x += win_x;
749         sum_y += win_y;
750         win = ecore_x_window_parent_get (win);
751     }
752
753     if (x)
754         *x = sum_x;
755     if (y)
756         *y = sum_y;
757 }
758
759 static void
760 evas_focus_out_cb (void *data, Evas *e, void *event_info)
761 {
762     Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
763
764     if (!ctx) return;
765
766     LOGD ("ctx : %p\n", ctx);
767
768     if (input_panel_ctx == ctx && _scim_initialized) {
769         isf_imf_context_input_panel_instant_hide (ctx);
770     }
771 }
772
773 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
774 {
775     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
776
777     autoperiod_allow = vconf_keynode_get_bool (key);
778 }
779
780 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
781 {
782     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
783
784     autocap_allow = vconf_keynode_get_bool (key);
785 }
786
787 EAPI void context_scim_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
788 {
789     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
790
791     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
792
793     if (data && context_scim->impl->imdata)
794         memcpy (data, context_scim->impl->imdata, context_scim->impl->imdata_size);
795
796     *length = context_scim->impl->imdata_size;
797 }
798
799 /* Public functions */
800 /**
801  * isf_imf_context_new
802  *
803  * This function will be called by Ecore IMF.
804  * Create a instance of type EcoreIMFContextISF.
805  *
806  * Return value: A pointer to the newly created EcoreIMFContextISF instance
807  */
808 EAPI EcoreIMFContextISF *
809 isf_imf_context_new (void)
810 {
811     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
812
813     int val;
814
815     EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
816     if (context_scim == NULL) {
817         std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
818         return NULL;
819     }
820
821     if (_context_count == 0) {
822         _context_count = getpid () % 50000;
823     }
824     context_scim->id = _context_count++;
825
826     if (!_scim_initialized) {
827         initialize ();
828         _scim_initialized = true;
829         isf_imf_input_panel_init ();
830
831         /* get autoperiod allow vconf value */
832         if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
833             if (val == EINA_TRUE)
834                 autoperiod_allow = EINA_TRUE;
835         }
836
837         vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
838
839         /* get autocapital allow vconf value */
840         if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
841             if (val == EINA_TRUE)
842                 autocap_allow = EINA_TRUE;
843         }
844
845         vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
846     }
847
848     return context_scim;
849 }
850
851 /**
852  * isf_imf_context_shutdown
853  *
854  * It will be called when the scim im module is unloaded by ecore. It will do some
855  * cleanup job.
856  */
857 EAPI void
858 isf_imf_context_shutdown (void)
859 {
860     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
861
862     if (_scim_initialized) {
863         _scim_initialized = false;
864
865         LOGD ("immodule shutdown\n");
866
867         vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
868         vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
869
870         isf_imf_input_panel_shutdown ();
871         finalize ();
872     }
873 }
874
875 EAPI void
876 isf_imf_context_add (Ecore_IMF_Context *ctx)
877 {
878     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
879
880     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
881
882     if (!context_scim) return;
883
884     context_scim->impl = NULL;
885
886     if (_backend.null ())
887         return;
888
889     IMEngineInstancePointer si;
890
891     // Use the default instance if "shared input method" mode is enabled.
892     if (_shared_input_method && !_default_instance.null ()) {
893         si = _default_instance;
894         SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
895     }
896
897     // Not in "shared input method" mode, or no default instance, create an instance.
898     if (si.null ()) {
899         IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
900         if (factory.null ()) return;
901         si = factory->create_instance ("UTF-8", _instance_count++);
902         if (si.null ()) return;
903         attach_instance (si);
904         SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
905     }
906
907     // If "shared input method" mode is enabled, and there is no default instance,
908     // then store this instance as default one.
909     if (_shared_input_method && _default_instance.null ()) {
910         SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
911         _default_instance = si;
912     }
913
914     context_scim->ctx                       = ctx;
915     context_scim->impl                      = new_ic_impl (context_scim);
916     if (context_scim->impl == NULL) {
917         std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
918         return;
919     }
920
921     context_scim->impl->si                  = si;
922     context_scim->impl->client_window       = 0;
923     context_scim->impl->client_canvas       = NULL;
924     context_scim->impl->preedit_caret       = 0;
925     context_scim->impl->cursor_x            = 0;
926     context_scim->impl->cursor_y            = 0;
927     context_scim->impl->cursor_pos          = -1;
928     context_scim->impl->cursor_top_y        = 0;
929     context_scim->impl->is_on               = true;
930     context_scim->impl->shared_si           = _shared_input_method;
931     context_scim->impl->use_preedit         = _on_the_spot;
932     context_scim->impl->preedit_started     = false;
933     context_scim->impl->preedit_updating    = false;
934     context_scim->impl->need_commit_preedit = false;
935     context_scim->impl->prediction_allow    = true;
936
937     if (!_ic_list)
938         context_scim->next = NULL;
939     else
940         context_scim->next = _ic_list;
941     _ic_list = context_scim;
942
943     if (_shared_input_method)
944         context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
945
946     _panel_client.prepare (context_scim->id);
947     _panel_client.register_input_context (context_scim->id, si->get_factory_uuid ());
948     set_ic_capabilities (context_scim);
949     _panel_client.send ();
950
951     SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
952 }
953
954 EAPI void
955 isf_imf_context_del (Ecore_IMF_Context *ctx)
956 {
957     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
958
959     if (!_ic_list) return;
960
961     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
962     Ecore_IMF_Input_Panel_State input_panel_state = ecore_imf_context_input_panel_state_get (ctx);
963
964     if (context_scim) {
965         if (context_scim->id != _ic_list->id) {
966             EcoreIMFContextISF * pre = _ic_list;
967             EcoreIMFContextISF * cur = _ic_list->next;
968             while (cur != NULL) {
969                 if (cur->id == context_scim->id) {
970                     pre->next = cur->next;
971                     break;
972                 }
973                 pre = cur;
974                 cur = cur->next;
975             }
976         } else {
977             _ic_list = _ic_list->next;
978         }
979     }
980
981     if (context_scim && context_scim->impl) {
982         _panel_client.prepare (context_scim->id);
983
984         if (context_scim == _focused_ic)
985             context_scim->impl->si->focus_out ();
986
987         if (context_scim->impl->client_canvas)
988             evas_event_callback_del_full (context_scim->impl->client_canvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, evas_focus_out_cb, ctx);
989
990         if (input_panel_ctx == ctx && _scim_initialized) {
991             LOGD ("ctx : %p\n", ctx);
992             if (input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
993                 input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
994                 ecore_imf_context_input_panel_hide (ctx);
995                 input_panel_event_callback_call (ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
996             }
997         }
998
999         // Delete the instance.
1000         // FIXME:
1001         // In case the instance send out some helper event,
1002         // and this context has been focused out,
1003         // we need set the focused_ic to this context temporary.
1004         EcoreIMFContextISF *old_focused = _focused_ic;
1005         _focused_ic = context_scim;
1006         context_scim->impl->si.reset ();
1007         _focused_ic = old_focused;
1008
1009         if (context_scim == _focused_ic) {
1010             _panel_client.turn_off (context_scim->id);
1011             _panel_client.focus_out (context_scim->id);
1012         }
1013
1014         _panel_client.remove_input_context (context_scim->id);
1015         _panel_client.send ();
1016
1017         if (context_scim->impl->client_window)
1018             isf_imf_context_client_window_set (ctx, NULL);
1019
1020         if (context_scim->impl) {
1021             delete_ic_impl (context_scim->impl);
1022             context_scim->impl = 0;
1023         }
1024     }
1025
1026     isf_imf_context_input_panel_event_callback_clear (ctx);
1027
1028     if (context_scim == _focused_ic)
1029         _focused_ic = 0;
1030
1031     if (context_scim) {
1032         delete context_scim;
1033         context_scim = 0;
1034     }
1035 }
1036
1037 /**
1038  * isf_imf_context_client_canvas_set
1039  * @ctx: a #Ecore_IMF_Context
1040  * @canvas: the client canvas
1041  *
1042  * This function will be called by Ecore IMF.
1043  *
1044  * Set the client canvas for the Input Method Context; this is the canvas
1045  * in which the input appears.
1046  *
1047  * The canvas type can be determined by using the context canvas type.
1048  * Actually only canvas with type "evas" (Evas *) is supported. This canvas
1049  * may be used in order to correctly position status windows, and may also
1050  * be used for purposes internal to the Input Method Context.
1051  */
1052 EAPI void
1053 isf_imf_context_client_canvas_set (Ecore_IMF_Context *ctx, void *canvas)
1054 {
1055     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1056
1057     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1058
1059     if (context_scim && context_scim->impl && context_scim->impl->client_canvas != (Evas*) canvas) {
1060         context_scim->impl->client_canvas = (Evas*)canvas;
1061
1062         LOGD ("ctx : %p, canvas : %p\n", ctx, canvas);
1063
1064         evas_event_callback_add (context_scim->impl->client_canvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, evas_focus_out_cb, ctx);
1065     }
1066 }
1067
1068 /**
1069  * isf_imf_context_client_window_set
1070  * @ctx: a #Ecore_IMF_Context
1071  * @window: the client window
1072  *
1073  * This function will be called by Ecore IMF.
1074  *
1075  * Set the client window for the Input Method Context; this is the Ecore_X_Window
1076  * when using X11, Ecore_Win32_Window when using Win32, etc.
1077  *
1078  * This window is used in order to correctly position status windows,
1079  * and may also be used for purposes internal to the Input Method Context.
1080  */
1081 EAPI void
1082 isf_imf_context_client_window_set (Ecore_IMF_Context *ctx, void *window)
1083 {
1084     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1085
1086     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1087
1088     if (context_scim && context_scim->impl && context_scim->impl->client_window != (Ecore_X_Window)((Ecore_Window)window)) {
1089         context_scim->impl->client_window = (Ecore_X_Window)((Ecore_Window)window);
1090
1091         LOGD ("ctx : %p, client X win ID : %#x\n", ctx, context_scim->impl->client_window);
1092
1093         if ((context_scim->impl->client_window != 0) &&
1094                 (context_scim->impl->client_window != _client_window)) {
1095             _client_window = context_scim->impl->client_window;
1096
1097             _check_desktop_mode (_client_window);
1098
1099             ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, _x_prop_change, window);
1100         }
1101     }
1102 }
1103
1104 /**
1105  * isf_imf_context_focus_in
1106  * @ctx: a #Ecore_IMF_Context
1107  *
1108  * This function will be called by Ecore IMF.
1109  *
1110  * Notify the Input Method Context that the widget to which its correspond has gained focus.
1111  */
1112 EAPI void
1113 isf_imf_context_focus_in (Ecore_IMF_Context *ctx)
1114 {
1115     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1116
1117     if (!context_scim)
1118         return;
1119
1120     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1121
1122     if (_focused_ic) {
1123         if (_focused_ic == context_scim) {
1124             SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1125             return;
1126         }
1127         SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1128         if (_focused_ic->ctx)
1129             isf_imf_context_focus_out (_focused_ic->ctx);
1130     }
1131
1132     bool need_cap   = false;
1133     bool need_reset = false;
1134     bool need_reg   = false;
1135
1136     if (context_scim && context_scim->impl) {
1137         _focused_ic = context_scim;
1138         isf_imf_context_control_focus_in (ctx);
1139
1140         _panel_client.prepare (context_scim->id);
1141
1142         // Handle the "Shared Input Method" mode.
1143         if (_shared_input_method) {
1144             SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
1145             IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1146             if (!factory.null ()) {
1147                 if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
1148                     _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
1149                     attach_instance (_default_instance);
1150                     SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
1151                 }
1152
1153                 context_scim->impl->shared_si = true;
1154                 context_scim->impl->si = _default_instance;
1155
1156                 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1157                 context_scim->impl->preedit_string.clear ();
1158                 context_scim->impl->preedit_attrlist.clear ();
1159                 context_scim->impl->preedit_caret = 0;
1160                 context_scim->impl->preedit_started = false;
1161                 need_cap = true;
1162                 need_reset = true;
1163                 need_reg = true;
1164             }
1165         } else if (context_scim->impl->shared_si) {
1166             SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
1167             IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1168             if (!factory.null ()) {
1169                 context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
1170                 context_scim->impl->preedit_string.clear ();
1171                 context_scim->impl->preedit_attrlist.clear ();
1172                 context_scim->impl->preedit_caret = 0;
1173                 context_scim->impl->preedit_started = false;
1174                 attach_instance (context_scim->impl->si);
1175                 need_cap = true;
1176                 need_reg = true;
1177                 context_scim->impl->shared_si = false;
1178                 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
1179             }
1180         }
1181
1182         context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
1183
1184         if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
1185         if (need_cap) set_ic_capabilities (context_scim);
1186
1187         panel_req_focus_in (context_scim);
1188 //        panel_req_update_spot_location (context_scim);
1189 //        panel_req_update_factory_info (context_scim);
1190
1191         if (need_reset) context_scim->impl->si->reset ();
1192         if (context_scim->impl->is_on) {
1193             _panel_client.turn_on (context_scim->id);
1194 //            _panel_client.hide_preedit_string (context_scim->id);
1195 //            _panel_client.hide_aux_string (context_scim->id);
1196 //            _panel_client.hide_lookup_table (context_scim->id);
1197             context_scim->impl->si->focus_in ();
1198             context_scim->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ctx));
1199             set_prediction_allow (context_scim->impl->si, context_scim->impl->prediction_allow);
1200             if (context_scim->impl->imdata)
1201                 context_scim->impl->si->set_imdata ((const char *)context_scim->impl->imdata, context_scim->impl->imdata_size);
1202         } else {
1203             _panel_client.turn_off (context_scim->id);
1204         }
1205
1206         _panel_client.send ();
1207     }
1208
1209     LOGD ("ctx : %p\n", ctx);
1210
1211     if (ecore_imf_context_input_panel_enabled_get (ctx))
1212         ecore_imf_context_input_panel_show (ctx);
1213     else
1214         LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
1215 }
1216
1217 /**
1218  * isf_imf_context_focus_out
1219  * @ctx: a #Ecore_IMF_Context
1220  *
1221  * This function will be called by Ecore IMF.
1222  *
1223  * Notify the Input Method Context that the widget to which its correspond has lost focus.
1224  */
1225 EAPI void
1226 isf_imf_context_focus_out (Ecore_IMF_Context *ctx)
1227 {
1228     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1229     Eina_Bool lock_scr;
1230
1231     if (!context_scim) return;
1232
1233     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1234
1235     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1236
1237         WideString wstr = context_scim->impl->preedit_string;
1238
1239         LOGD ("ctx : %p\n", ctx);
1240
1241         if (ecore_imf_context_input_panel_enabled_get (ctx))
1242             ecore_imf_context_input_panel_hide (ctx);
1243
1244         if (context_scim->impl->need_commit_preedit) {
1245             panel_slot_hide_preedit_string (context_scim->id);
1246
1247             if (wstr.length ()) {
1248                 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1249                 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1250             }
1251             _panel_client.prepare (context_scim->id);
1252             _panel_client.reset_input_context (context_scim->id);
1253             _panel_client.send ();
1254         }
1255
1256         lock_scr = check_focus_out_by_lockscreen (ctx);
1257
1258         if (!lock_scr)
1259             _panel_client.prepare (context_scim->id);
1260
1261         context_scim->impl->si->focus_out ();
1262         context_scim->impl->si->reset ();
1263
1264         if (!lock_scr) {
1265 //          if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1266             _panel_client.focus_out (context_scim->id);
1267             _panel_client.send ();
1268         }
1269         _focused_ic = 0;
1270     }
1271 }
1272
1273 /**
1274  * isf_imf_context_reset
1275  * @ctx: a #Ecore_IMF_Context
1276  *
1277  * This function will be called by Ecore IMF.
1278  *
1279  * Notify the Input Method Context that a change such as a change in cursor
1280  * position has been made. This will typically cause the Input Method Context
1281  * to clear the preedit state.
1282  */
1283 EAPI void
1284 isf_imf_context_reset (Ecore_IMF_Context *ctx)
1285 {
1286     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1287
1288     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1289
1290     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1291         WideString wstr = context_scim->impl->preedit_string;
1292
1293         _panel_client.prepare (context_scim->id);
1294         context_scim->impl->si->reset ();
1295         _panel_client.reset_input_context (context_scim->id);
1296         _panel_client.send ();
1297
1298         if (context_scim->impl->need_commit_preedit) {
1299             panel_slot_hide_preedit_string (context_scim->id);
1300
1301             if (wstr.length ()) {
1302                 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1303                 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1304             }
1305         }
1306     }
1307 }
1308
1309 /**
1310  * isf_imf_context_cursor_position_set
1311  * @ctx: a #Ecore_IMF_Context
1312  * @cursor_pos: New cursor position in characters.
1313  *
1314  * This function will be called by Ecore IMF.
1315  *
1316  * Notify the Input Method Context that a change in the cursor position has been made.
1317  */
1318 EAPI void
1319 isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos)
1320 {
1321     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1322
1323     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1324
1325     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1326         if (context_scim->impl->cursor_pos != cursor_pos) {
1327             LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
1328             context_scim->impl->cursor_pos = cursor_pos;
1329
1330             caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1331
1332             if (context_scim->impl->preedit_updating)
1333                 return;
1334             _panel_client.prepare (context_scim->id);
1335             context_scim->impl->si->update_cursor_position (cursor_pos);
1336             panel_req_update_cursor_position (context_scim, cursor_pos);
1337             _panel_client.send ();
1338         }
1339     }
1340 }
1341
1342 /**
1343  * isf_imf_context_cursor_location_set
1344  * @ctx: a #Ecore_IMF_Context
1345  * @x: x position of New cursor.
1346  * @y: y position of New cursor.
1347  * @w: the width of New cursor.
1348  * @h: the height of New cursor.
1349  *
1350  * This function will be called by Ecore IMF.
1351  *
1352  * Notify the Input Method Context that a change in the cursor location has been made.
1353  */
1354 EAPI void
1355 isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
1356 {
1357     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1358
1359     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1360     Ecore_Evas *ee;
1361     int canvas_x, canvas_y;
1362     int new_cursor_x, new_cursor_y;
1363
1364     if (cw == 0 && ch == 0)
1365         return;
1366
1367     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1368         if (context_scim->impl->client_canvas) {
1369             ee = ecore_evas_ecore_evas_get (context_scim->impl->client_canvas);
1370             if (!ee) return;
1371
1372             ecore_evas_geometry_get (ee, &canvas_x, &canvas_y, NULL, NULL);
1373         }
1374         else {
1375             if (context_scim->impl->client_window)
1376                 window_to_screen_geometry_get (context_scim->impl->client_window, &canvas_x, &canvas_y);
1377             else
1378                 return;
1379         }
1380
1381         new_cursor_x = canvas_x + cx;
1382         new_cursor_y = canvas_y + cy + ch;
1383
1384         // Don't update spot location while updating preedit string.
1385         if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
1386             return;
1387
1388         if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y) {
1389             context_scim->impl->cursor_x     = new_cursor_x;
1390             context_scim->impl->cursor_y     = new_cursor_y;
1391             context_scim->impl->cursor_top_y = canvas_y + cy;
1392             _panel_client.prepare (context_scim->id);
1393             panel_req_update_spot_location (context_scim);
1394             _panel_client.send ();
1395             SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
1396         }
1397     }
1398 }
1399
1400 /**
1401  * isf_imf_context_input_mode_set
1402  * @ctx: a #Ecore_IMF_Context
1403  * @input_mode: the input mode
1404  *
1405  * This function will be called by Ecore IMF.
1406  *
1407  * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
1408  * is in Ecore_IMF.h.
1409  */
1410 EAPI void
1411 isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
1412 {
1413     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1414
1415     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1416     if (context_scim && context_scim->impl) {
1417         context_scim->impl->input_mode = input_mode;
1418     }
1419 }
1420
1421 /**
1422  * isf_imf_context_preedit_string_get
1423  * @ctx: a #Ecore_IMF_Context
1424  * @str: the preedit string
1425  * @cursor_pos: the cursor position
1426  *
1427  * This function will be called by Ecore IMF.
1428  *
1429  * To get the preedit string of the input method.
1430  */
1431 EAPI void
1432 isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
1433 {
1434     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1435
1436     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1437
1438     if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1439         String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1440
1441         if (str) {
1442             if (mbs.length ())
1443                 *str = strdup (mbs.c_str ());
1444             else
1445                 *str = strdup ("");
1446         }
1447
1448         if (cursor_pos) {
1449             *cursor_pos = context_scim->impl->preedit_caret;
1450         }
1451     } else {
1452         if (str)
1453             *str = strdup ("");
1454
1455         if (cursor_pos)
1456             *cursor_pos = 0;
1457     }
1458 }
1459
1460 EAPI void
1461 isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
1462 {
1463     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1464
1465     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1466
1467     if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1468         String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1469
1470         if (str) {
1471             if (mbs.length ())
1472                 *str = strdup (mbs.c_str ());
1473             else
1474                 *str = strdup ("");
1475         }
1476
1477         if (cursor_pos) {
1478             *cursor_pos = context_scim->impl->preedit_caret;
1479         }
1480
1481         if (attrs) {
1482             if (mbs.length ()) {
1483                 int start_index, end_index;
1484                 int wlen = context_scim->impl->preedit_string.length ();
1485                 Ecore_IMF_Preedit_Attr *attr = NULL;
1486                 AttributeList::const_iterator i;
1487                 bool *attrs_flag = new bool [mbs.length ()];
1488                 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1489                 for (i = context_scim->impl->preedit_attrlist.begin ();
1490                     i != context_scim->impl->preedit_attrlist.end (); ++i) {
1491                     start_index = i->get_start ();
1492                     end_index = i->get_end ();
1493                     if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1494                         start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1495                         end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1496                         if (i->get_type () == SCIM_ATTR_DECORATE) {
1497                             attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof (Ecore_IMF_Preedit_Attr));
1498                             if (attr == NULL)
1499                                 continue;
1500                             attr->start_index = start_index;
1501                             attr->end_index = end_index;
1502
1503                             if (i->get_value () == SCIM_ATTR_DECORATE_UNDERLINE) {
1504                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1505                                 *attrs = eina_list_append (*attrs, (void *)attr);
1506                             } else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE) {
1507                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1508                                 *attrs = eina_list_append (*attrs, (void *)attr);
1509                             } else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
1510                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1511                                 *attrs = eina_list_append (*attrs, (void *)attr);
1512                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR1) {
1513                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
1514                                 *attrs = eina_list_append (*attrs, (void *)attr);
1515                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR2) {
1516                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
1517                                 *attrs = eina_list_append (*attrs, (void *)attr);
1518                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR3) {
1519                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
1520                                 *attrs = eina_list_append (*attrs, (void *)attr);
1521                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR4) {
1522                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
1523                                 *attrs = eina_list_append (*attrs, (void *)attr);
1524                             } else {
1525                                 free (attr);
1526                             }
1527                             switch(i->get_value())
1528                             {
1529                                 case SCIM_ATTR_DECORATE_UNDERLINE:
1530                                 case SCIM_ATTR_DECORATE_REVERSE:
1531                                 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1532                                 case SCIM_ATTR_DECORATE_BGCOLOR1:
1533                                 case SCIM_ATTR_DECORATE_BGCOLOR2:
1534                                 case SCIM_ATTR_DECORATE_BGCOLOR3:
1535                                 case SCIM_ATTR_DECORATE_BGCOLOR4:
1536                                     // Record which character has attribute.
1537                                     for (int pos = start_index; pos < end_index; ++pos)
1538                                         attrs_flag [pos] = 1;
1539                                     break;
1540                                 default:
1541                                     break;
1542                             }
1543                         } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1544                             SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1545                         } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1546                             SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1547                         }
1548                     }
1549                 }
1550                 // Add underline for all characters which don't have attribute.
1551                 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1552                     if (!attrs_flag [pos]) {
1553                         int begin_pos = pos;
1554                         while (pos < mbs.length () && !attrs_flag [pos])
1555                             ++pos;
1556                         // use REVERSE style as default
1557                         attr = (Ecore_IMF_Preedit_Attr *)calloc (1, sizeof (Ecore_IMF_Preedit_Attr));
1558                         if (attr == NULL)
1559                             continue;
1560                         attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1561                         attr->start_index = begin_pos;
1562                         attr->end_index = pos;
1563                         *attrs = eina_list_append(*attrs, (void *)attr);
1564                     }
1565                 }
1566                 delete [] attrs_flag;
1567             }
1568         }
1569     } else {
1570         if (str)
1571             *str = strdup ("");
1572
1573         if (cursor_pos)
1574             *cursor_pos = 0;
1575
1576         if (attrs)
1577             *attrs = NULL;
1578     }
1579 }
1580
1581 /**
1582  * isf_imf_context_use_preedit_set
1583  * @ctx: a #Ecore_IMF_Context
1584  * @use_preedit: Whether the IM context should use the preedit string.
1585  *
1586  * This function will be called by Ecore IMF.
1587  *
1588  * Set whether the IM context should use the preedit string to display feedback.
1589  * If is 0 (default is 1), then the IM context may use some other method to
1590  * display feedback, such as displaying it in a child of the root window.
1591  */
1592 EAPI void
1593 isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
1594 {
1595     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit == EINA_TRUE ? "true" : "false") << "...\n";
1596
1597     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1598
1599     if (!_on_the_spot) return;
1600
1601     if (context_scim && context_scim->impl) {
1602         bool old = context_scim->impl->use_preedit;
1603         context_scim->impl->use_preedit = use_preedit;
1604         if (context_scim == _focused_ic) {
1605             _panel_client.prepare (context_scim->id);
1606
1607             if (old != use_preedit)
1608                 set_ic_capabilities (context_scim);
1609
1610             if (context_scim->impl->preedit_string.length ())
1611                 slot_show_preedit_string (context_scim->impl->si);
1612
1613             _panel_client.send ();
1614         }
1615     }
1616 }
1617
1618 /**
1619  * isf_imf_context_prediction_allow_set
1620  * @ctx: a #Ecore_IMF_Context
1621  * @prediction: Whether the IM context should use the prediction.
1622  *
1623  * This function will be called by Ecore IMF.
1624  *
1625  * Set whether the IM context should use the prediction.
1626  */
1627 EAPI void
1628 isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction)
1629 {
1630     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction == EINA_TRUE ? "true" : "false") << "...\n";
1631
1632     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1633
1634     if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction) {
1635         context_scim->impl->prediction_allow = prediction;
1636         set_prediction_allow (context_scim->impl->si, prediction);
1637     }
1638 }
1639
1640 /**
1641  * isf_imf_context_prediction_allow_get
1642  * @ctx: a #Ecore_IMF_Context
1643  *
1644  * This function will be called by Ecore IMF.
1645  *
1646  * To get prediction allow flag for the IM context.
1647  *
1648  * Return value: the prediction allow flag for the IM context
1649  */
1650 EAPI Eina_Bool
1651 isf_imf_context_prediction_allow_get (Ecore_IMF_Context* ctx)
1652 {
1653     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1654
1655     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1656
1657     Eina_Bool ret = EINA_FALSE;
1658     if (context_scim && context_scim->impl) {
1659         ret = context_scim->impl->prediction_allow;
1660     } else {
1661         std::cerr << __FUNCTION__ << " failed!!!\n";
1662     }
1663     return ret;
1664 }
1665
1666 /**
1667  * isf_imf_context_autocapital_type_set
1668  * @ctx: a #Ecore_IMF_Context
1669  * @autocapital_type: the autocapital type for the IM context.
1670  *
1671  * This function will be called by Ecore IMF.
1672  *
1673  * Set autocapital type for the IM context.
1674  */
1675 EAPI void
1676 isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1677 {
1678     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1679
1680     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1681
1682     if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1683         context_scim->impl->autocapital_type = autocapital_type;
1684     }
1685 }
1686
1687 /**
1688  * isf_imf_context_filter_event
1689  * @ctx: a #Ecore_IMF_Context
1690  * @type: The type of event defined by Ecore_IMF_Event_Type.
1691  * @event: The event itself.
1692  * Return value: %TRUE if the input method handled the key event.
1693  *
1694  * This function will be called by Ecore IMF.
1695  *
1696  * Allow an Ecore Input Context to internally handle an event. If this function
1697  * returns 1, then no further processing should be done for this event. Input
1698  * methods must be able to accept all types of events (simply returning 0 if
1699  * the event was not handled), but there is no obligation of any events to be
1700  * submitted to this function.
1701  */
1702 EAPI Eina_Bool
1703 isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
1704 {
1705     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1706
1707     EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1708     Eina_Bool ret = EINA_FALSE;
1709
1710     if (ic == NULL || ic->impl == NULL)
1711         return ret;
1712
1713     KeyEvent key;
1714     unsigned int timestamp;
1715
1716     if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1717         Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
1718         timestamp = ev->timestamp;
1719         scim_string_to_key (key, ev->key);
1720         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1721         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1722         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1723         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1724         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1725         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1726     } else if (type == ECORE_IMF_EVENT_KEY_UP) {
1727         Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
1728         timestamp = ev->timestamp;
1729         scim_string_to_key (key, ev->key);
1730         key.mask = SCIM_KEY_ReleaseMask;
1731         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1732         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1733         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1734         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1735         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1736         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1737     } else if (type == ECORE_IMF_EVENT_MOUSE_UP) {
1738         if (ecore_imf_context_input_panel_enabled_get (ctx)) {
1739             LOGD ("[Mouse-up event] ctx : %p\n", ctx);
1740             if (ic == _focused_ic)
1741                 ecore_imf_context_input_panel_show (ctx);
1742             else
1743                 LOGW ("Can't show IME because there is no focus. ctx : %p\n", ctx);
1744         }
1745         return EINA_FALSE;
1746     } else {
1747         return ret;
1748     }
1749
1750     key.mask &= _valid_key_mask;
1751
1752     _panel_client.prepare (ic->id);
1753
1754     ret = EINA_TRUE;
1755     if (!filter_hotkeys (ic, key)) {
1756         if (timestamp == 0) {
1757             ret = EINA_FALSE;
1758             // in case of generated event
1759             if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1760                 char code = key.get_ascii_code ();
1761                 if (isgraph (code)) {
1762                     char string[2] = {0};
1763                     snprintf (string, sizeof (string), "%c", code);
1764
1765                     if (strlen (string) != 0) {
1766                         ecore_imf_context_commit_event_add (ic->ctx, string);
1767                         ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)string);
1768                         caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1769                         ret = EINA_TRUE;
1770                     }
1771                 }
1772             }
1773             _panel_client.send ();
1774             return ret;
1775         }
1776
1777         if (!_focused_ic || !_focused_ic->impl->is_on ||
1778             !_focused_ic->impl->si->process_key_event (key)) {
1779             ret = EINA_FALSE;
1780         }
1781     }
1782
1783     _panel_client.send ();
1784
1785     return ret;
1786 }
1787
1788 /**
1789  * Set up an ISE specific data
1790  *
1791  * @param[in] ctx a #Ecore_IMF_Context
1792  * @param[in] data pointer of data to sets up to ISE
1793  * @param[in] length length of data
1794  */
1795 EAPI void isf_imf_context_imdata_set (Ecore_IMF_Context *ctx, const void* data, int length)
1796 {
1797     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " data length ( " << length << ") ...\n";
1798     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1799
1800     if (context_scim == NULL || data == NULL || length <= 0)
1801         return;
1802
1803     if (context_scim && context_scim->impl) {
1804         if (context_scim->impl->imdata)
1805             free (context_scim->impl->imdata);
1806
1807         context_scim->impl->imdata = calloc (1, length);
1808         memcpy (context_scim->impl->imdata, data, length);
1809         context_scim->impl->imdata_size = length;
1810
1811         if (context_scim->impl->si && _focused_ic == context_scim) {
1812             _panel_client.prepare (context_scim->id);
1813             context_scim->impl->si->set_imdata ((const char *)data, length);
1814             _panel_client.send ();
1815         }
1816     }
1817
1818     isf_imf_context_input_panel_imdata_set (ctx, data, length);
1819 }
1820
1821 /**
1822  * Get the ISE specific data from ISE
1823  *
1824  * @param[in] ctx a #Ecore_IMF_Context
1825  * @param[out] data pointer of data to return
1826  * @param[out] length length of data
1827  */
1828 EAPI void isf_imf_context_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
1829 {
1830     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1831
1832     isf_imf_context_input_panel_imdata_get (ctx, data, length);
1833 }
1834
1835 /* Panel Slot functions */
1836 static void
1837 panel_slot_reload_config (int context)
1838 {
1839     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1840
1841     _config->reload ();
1842 }
1843
1844 static void
1845 panel_slot_exit (int /* context */)
1846 {
1847     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1848
1849     finalize ();
1850 }
1851
1852 static void
1853 panel_slot_update_candidate_item_layout (int context, const std::vector<uint32> &row_items)
1854 {
1855     EcoreIMFContextISF *ic = find_ic (context);
1856     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " row size=" << row_items.size () << " ic=" << ic << "\n";
1857     if (ic && ic->impl) {
1858         _panel_client.prepare (ic->id);
1859         ic->impl->si->update_candidate_item_layout (row_items);
1860         _panel_client.send ();
1861     }
1862 }
1863
1864 static void
1865 panel_slot_update_lookup_table_page_size (int context, int page_size)
1866 {
1867     EcoreIMFContextISF *ic = find_ic (context);
1868     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1869     if (ic && ic->impl) {
1870         _panel_client.prepare (ic->id);
1871         ic->impl->si->update_lookup_table_page_size (page_size);
1872         _panel_client.send ();
1873     }
1874 }
1875
1876 static void
1877 panel_slot_lookup_table_page_up (int context)
1878 {
1879     EcoreIMFContextISF *ic = find_ic (context);
1880     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1881     if (ic && ic->impl) {
1882         _panel_client.prepare (ic->id);
1883         ic->impl->si->lookup_table_page_up ();
1884         _panel_client.send ();
1885     }
1886 }
1887
1888 static void
1889 panel_slot_lookup_table_page_down (int context)
1890 {
1891     EcoreIMFContextISF *ic = find_ic (context);
1892     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1893     if (ic && ic->impl) {
1894         _panel_client.prepare (ic->id);
1895         ic->impl->si->lookup_table_page_down ();
1896         _panel_client.send ();
1897     }
1898 }
1899
1900 static void
1901 panel_slot_trigger_property (int context, const String &property)
1902 {
1903     EcoreIMFContextISF *ic = find_ic (context);
1904     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
1905     if (ic && ic->impl) {
1906         _panel_client.prepare (ic->id);
1907         ic->impl->si->trigger_property (property);
1908         _panel_client.send ();
1909     }
1910 }
1911
1912 static void
1913 panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1914 {
1915     EcoreIMFContextISF *ic = find_ic (context);
1916     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
1917                            << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic != NULL ? ic->impl : 0) << " ic-uuid="
1918                            << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
1919     if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
1920         _panel_client.prepare (ic->id);
1921         SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1922         ic->impl->si->process_helper_event (helper_uuid, trans);
1923         _panel_client.send ();
1924     }
1925 }
1926
1927 static void
1928 panel_slot_move_preedit_caret (int context, int caret_pos)
1929 {
1930     EcoreIMFContextISF *ic = find_ic (context);
1931     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1932     if (ic && ic->impl) {
1933         _panel_client.prepare (ic->id);
1934         ic->impl->si->move_preedit_caret (caret_pos);
1935         _panel_client.send ();
1936     }
1937 }
1938
1939 static void
1940 panel_slot_update_preedit_caret (int context, int caret)
1941 {
1942     EcoreIMFContextISF *ic = find_ic (context);
1943     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
1944
1945     if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
1946         ic->impl->preedit_caret = caret;
1947         if (ic->impl->use_preedit) {
1948             if (!ic->impl->preedit_started) {
1949                 ecore_imf_context_preedit_start_event_add (ic->ctx);
1950                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
1951                 ic->impl->preedit_started = true;
1952             }
1953             ecore_imf_context_preedit_changed_event_add (ic->ctx);
1954             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1955         } else {
1956             _panel_client.prepare (ic->id);
1957             _panel_client.update_preedit_caret (ic->id, caret);
1958             _panel_client.send ();
1959         }
1960     }
1961 }
1962
1963 static void
1964 panel_slot_select_aux (int context, int aux_index)
1965 {
1966     EcoreIMFContextISF *ic = find_ic (context);
1967     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " aux=" << aux_index << " ic=" << ic << "\n";
1968     if (ic && ic->impl) {
1969         _panel_client.prepare (ic->id);
1970         ic->impl->si->select_aux (aux_index);
1971         _panel_client.send ();
1972     }
1973 }
1974
1975 static void
1976 panel_slot_select_candidate (int context, int cand_index)
1977 {
1978     EcoreIMFContextISF *ic = find_ic (context);
1979     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
1980     if (ic && ic->impl) {
1981         _panel_client.prepare (ic->id);
1982         ic->impl->si->select_candidate (cand_index);
1983         _panel_client.send ();
1984     }
1985 }
1986
1987 static int
1988 _keyname_to_keycode (const char *keyname)
1989 {
1990     int keycode = 0;
1991     int keysym;
1992     Display *display = (Display *)ecore_x_display_get ();
1993
1994     keysym = XStringToKeysym (keyname);
1995
1996     if (!strncmp (keyname, "Keycode-", 8)) {
1997         keycode = atoi (keyname + 8);
1998     } else {
1999         keycode = XKeysymToKeycode (display, keysym);
2000     }
2001
2002     return keycode;
2003 }
2004
2005 static Eina_Bool
2006 feed_key_event (EcoreIMFContextISF *ic, const KeyEvent &key, bool fake)
2007 {
2008     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2009
2010     if (key.code <= 0x7F ||
2011         (key.code >= SCIM_KEY_BackSpace && key.code <= SCIM_KEY_Delete) ||
2012         (key.code >= SCIM_KEY_Home && key.code <= SCIM_KEY_Hyper_R)) {
2013         // ascii code and function keys
2014         send_x_key_event (key, fake);
2015         return EINA_TRUE;
2016     } else {
2017         return EINA_FALSE;
2018     }
2019 }
2020
2021 static void
2022 panel_slot_process_key_event (int context, const KeyEvent &key)
2023 {
2024     EcoreIMFContextISF *ic = find_ic (context);
2025     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2026
2027     if (feed_key_event (ic, key, false) == EINA_TRUE) return;
2028
2029     if (ic && ic->impl) {
2030         _panel_client.prepare (ic->id);
2031
2032         if (!filter_hotkeys (ic, key)) {
2033             if (!_focused_ic || !_focused_ic->impl->is_on ||
2034                 !_focused_ic->impl->si->process_key_event (key)) {
2035                 _fallback_instance->process_key_event (key);
2036             }
2037         }
2038
2039         _panel_client.send ();
2040     }
2041 }
2042
2043 static void
2044 panel_slot_commit_string (int context, const WideString &wstr)
2045 {
2046     EcoreIMFContextISF *ic = find_ic (context);
2047     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2048
2049     if (ic && ic->impl) {
2050         if (_focused_ic != ic)
2051             return;
2052
2053         if (ic->impl->need_commit_preedit)
2054             panel_slot_hide_preedit_string (ic->id);
2055         ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2056         ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2057     }
2058 }
2059
2060 static void
2061 panel_slot_forward_key_event (int context, const KeyEvent &key)
2062 {
2063     EcoreIMFContextISF *ic = find_ic (context);
2064     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2065
2066     if (strlen (key.get_key_string ().c_str ()) >= 116)
2067         return;
2068
2069     feed_key_event (ic, key, true);
2070 }
2071
2072 static void
2073 panel_slot_request_help (int context)
2074 {
2075     EcoreIMFContextISF *ic = find_ic (context);
2076     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2077     if (ic && ic->impl) {
2078         _panel_client.prepare (ic->id);
2079         panel_req_show_help (ic);
2080         _panel_client.send ();
2081     }
2082 }
2083
2084 static void
2085 panel_slot_request_factory_menu (int context)
2086 {
2087     EcoreIMFContextISF *ic = find_ic (context);
2088     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2089     if (ic && ic->impl) {
2090         _panel_client.prepare (ic->id);
2091         panel_req_show_factory_menu (ic);
2092         _panel_client.send ();
2093     }
2094 }
2095
2096 static void
2097 panel_slot_change_factory (int context, const String &uuid)
2098 {
2099     EcoreIMFContextISF *ic = find_ic (context);
2100     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
2101     if (ic && ic->impl) {
2102         _panel_client.prepare (ic->id);
2103         ic->impl->si->reset ();
2104         open_specific_factory (ic, uuid);
2105         _panel_client.send ();
2106     }
2107 }
2108
2109 static void
2110 panel_slot_reset_keyboard_ise (int context)
2111 {
2112     EcoreIMFContextISF *ic = find_ic (context);
2113     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2114     if (ic && ic->impl) {
2115         WideString wstr = ic->impl->preedit_string;
2116         if (ic->impl->need_commit_preedit) {
2117             panel_slot_hide_preedit_string (ic->id);
2118
2119             if (wstr.length ()) {
2120                 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2121                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2122             }
2123         }
2124         _panel_client.prepare (ic->id);
2125         ic->impl->si->reset ();
2126         _panel_client.send ();
2127     }
2128 }
2129
2130 static void
2131 panel_slot_update_keyboard_ise (int context)
2132 {
2133     EcoreIMFContextISF *ic = find_ic (context);
2134     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2135
2136     _backend->add_module (_config, "socket", false);
2137 }
2138
2139 static void
2140 panel_slot_show_preedit_string (int context)
2141 {
2142     EcoreIMFContextISF *ic = find_ic (context);
2143     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << "\n";
2144
2145     if (ic && ic->impl && _focused_ic == ic) {
2146         if (!ic->impl->is_on)
2147             ic->impl->is_on = true;
2148
2149         if (ic->impl->use_preedit) {
2150             if (!ic->impl->preedit_started) {
2151                 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
2152                 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2153                 ic->impl->preedit_started     = true;
2154                 ic->impl->need_commit_preedit = true;
2155             }
2156         } else {
2157             _panel_client.prepare (ic->id);
2158             _panel_client.show_preedit_string (ic->id);
2159             _panel_client.send ();
2160         }
2161     }
2162 }
2163
2164 static void
2165 panel_slot_hide_preedit_string (int context)
2166 {
2167     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2168
2169     EcoreIMFContextISF *ic = find_ic (context);
2170
2171     if (ic && ic->impl && _focused_ic == ic) {
2172         if (!ic->impl->is_on)
2173             ic->impl->is_on = true;
2174
2175         bool emit = false;
2176         if (ic->impl->preedit_string.length ()) {
2177             ic->impl->preedit_string = WideString ();
2178             ic->impl->preedit_caret  = 0;
2179             ic->impl->preedit_attrlist.clear ();
2180             emit = true;
2181         }
2182         if (ic->impl->use_preedit) {
2183             if (emit) {
2184                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2185                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2186             }
2187             if (ic->impl->preedit_started) {
2188                 ecore_imf_context_preedit_end_event_add (ic->ctx);
2189                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2190                 ic->impl->preedit_started     = false;
2191                 ic->impl->need_commit_preedit = false;
2192             }
2193         } else {
2194             _panel_client.prepare (ic->id);
2195             _panel_client.hide_preedit_string (ic->id);
2196             _panel_client.send ();
2197         }
2198     }
2199 }
2200
2201 static void
2202 panel_slot_update_preedit_string (int context,
2203                                   const WideString    &str,
2204                                   const AttributeList &attrs)
2205 {
2206     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2207
2208     EcoreIMFContextISF *ic = find_ic (context);
2209
2210     if (ic && ic->impl && _focused_ic == ic) {
2211         if (!ic->impl->is_on)
2212             ic->impl->is_on = true;
2213
2214         if (ic->impl->preedit_string != str || str.length ()) {
2215             ic->impl->preedit_string   = str;
2216             ic->impl->preedit_attrlist = attrs;
2217
2218             if (ic->impl->use_preedit) {
2219                 if (!ic->impl->preedit_started) {
2220                     ecore_imf_context_preedit_start_event_add (ic->ctx);
2221                     ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2222                     ic->impl->preedit_started = true;
2223                     ic->impl->need_commit_preedit = true;
2224                 }
2225                 ic->impl->preedit_caret    = str.length ();
2226                 ic->impl->preedit_updating = true;
2227                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2228                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2229                 ic->impl->preedit_updating = false;
2230             } else {
2231                 _panel_client.prepare (ic->id);
2232                 _panel_client.update_preedit_string (ic->id, str, attrs);
2233                 _panel_client.send ();
2234             }
2235         }
2236     }
2237 }
2238
2239 static void
2240 panel_slot_get_surrounding_text (int context, int maxlen_before, int maxlen_after)
2241 {
2242     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2243
2244     EcoreIMFContextISF *ic = find_ic (context);
2245
2246     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2247         int cursor = 0;
2248         WideString text = WideString ();
2249         slot_get_surrounding_text (ic->impl->si, text, cursor, maxlen_before, maxlen_after);
2250         _panel_client.prepare (ic->id);
2251         _panel_client.update_surrounding_text (ic->id, text, cursor);
2252         _panel_client.send ();
2253     }
2254 }
2255
2256 static void
2257 panel_slot_delete_surrounding_text (int context, int offset, int len)
2258 {
2259     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2260
2261     EcoreIMFContextISF *ic = find_ic (context);
2262
2263     if (ic && ic->impl && _focused_ic == ic && ic->impl->si)
2264         slot_delete_surrounding_text (ic->impl->si, offset, len);
2265 }
2266
2267 static void
2268 panel_slot_update_displayed_candidate_number (int context, int number)
2269 {
2270     EcoreIMFContextISF *ic = find_ic (context);
2271     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " number=" << number << " ic=" << ic << "\n";
2272     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2273         _panel_client.prepare (ic->id);
2274         ic->impl->si->update_displayed_candidate_number (number);
2275         _panel_client.send ();
2276     }
2277 }
2278
2279 static void
2280 panel_slot_candidate_more_window_show (int context)
2281 {
2282     EcoreIMFContextISF *ic = find_ic (context);
2283     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2284     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2285         _panel_client.prepare (ic->id);
2286         ic->impl->si->candidate_more_window_show ();
2287         _panel_client.send ();
2288     }
2289 }
2290
2291 static void
2292 panel_slot_candidate_more_window_hide (int context)
2293 {
2294     EcoreIMFContextISF *ic = find_ic (context);
2295     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2296     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2297         _panel_client.prepare (ic->id);
2298         ic->impl->si->candidate_more_window_hide ();
2299         _panel_client.send ();
2300     }
2301 }
2302
2303 static void
2304 panel_slot_longpress_candidate (int context, int index)
2305 {
2306     EcoreIMFContextISF *ic = find_ic (context);
2307     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " index=" << index << " ic=" << ic << "\n";
2308     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2309         _panel_client.prepare (ic->id);
2310         ic->impl->si->longpress_candidate (index);
2311         _panel_client.send ();
2312     }
2313 }
2314
2315 static void
2316 panel_slot_update_client_id (int context, int client_id)
2317 {
2318     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " client_id=" << client_id << "\n";
2319
2320     _panel_client_id = client_id;
2321 }
2322
2323 /* Panel Requestion functions. */
2324 static void
2325 panel_req_show_help (EcoreIMFContextISF *ic)
2326 {
2327     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2328
2329     String help;
2330
2331     help =  String (_("Smart Common Input Method platform ")) +
2332             String (SCIM_VERSION) +
2333             String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2334
2335     if (ic && ic->impl) {
2336         IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2337         if (sf) {
2338             help += utf8_wcstombs (sf->get_name ());
2339             help += String (_(":\n\n"));
2340
2341             help += utf8_wcstombs (sf->get_help ());
2342             help += String (_("\n\n"));
2343
2344             help += utf8_wcstombs (sf->get_credits ());
2345         }
2346         _panel_client.show_help (ic->id, help);
2347     }
2348 }
2349
2350 static void
2351 panel_req_show_factory_menu (EcoreIMFContextISF *ic)
2352 {
2353     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2354
2355     std::vector<IMEngineFactoryPointer> factories;
2356     std::vector <PanelFactoryInfo> menu;
2357
2358     _backend->get_factories_for_encoding (factories, "UTF-8");
2359
2360     for (size_t i = 0; i < factories.size (); ++ i) {
2361         menu.push_back (PanelFactoryInfo (
2362                             factories [i]->get_uuid (),
2363                             utf8_wcstombs (factories [i]->get_name ()),
2364                             factories [i]->get_language (),
2365                             factories [i]->get_icon_file ()));
2366     }
2367
2368     if (menu.size ())
2369         _panel_client.show_factory_menu (ic->id, menu);
2370 }
2371
2372 static void
2373 panel_req_update_factory_info (EcoreIMFContextISF *ic)
2374 {
2375     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2376
2377     if (ic && ic->impl && ic == _focused_ic) {
2378         PanelFactoryInfo info;
2379         if (ic->impl->is_on) {
2380             IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2381             if (sf)
2382                 info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
2383         } else {
2384             info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
2385         }
2386         _panel_client.update_factory_info (ic->id, info);
2387     }
2388 }
2389
2390 static void
2391 panel_req_focus_in (EcoreIMFContextISF *ic)
2392 {
2393     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2394
2395     _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
2396 }
2397
2398 static void
2399 panel_req_update_spot_location (EcoreIMFContextISF *ic)
2400 {
2401     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2402
2403     _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
2404 }
2405
2406 static void
2407 panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos)
2408 {
2409     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2410
2411     _panel_client.update_cursor_position (ic->id, cursor_pos);
2412 }
2413
2414 static bool
2415 filter_hotkeys (EcoreIMFContextISF *ic, const KeyEvent &key)
2416 {
2417     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2418
2419     bool ret = false;
2420
2421     _frontend_hotkey_matcher.push_key_event (key);
2422     _imengine_hotkey_matcher.push_key_event (key);
2423
2424     FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
2425
2426     if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
2427         if (!ic->impl->is_on)
2428             turn_on_ic (ic);
2429         else
2430             turn_off_ic (ic);
2431
2432         _display_input_language (ic);
2433         ret = true;
2434     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
2435         if (!ic->impl->is_on) {
2436             turn_on_ic (ic);
2437             _display_input_language (ic);
2438         }
2439         ret = true;
2440     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
2441         if (ic->impl->is_on) {
2442             turn_off_ic (ic);
2443             _display_input_language (ic);
2444         }
2445         ret = true;
2446     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
2447         open_next_factory (ic);
2448         ret = true;
2449     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
2450         open_previous_factory (ic);
2451         ret = true;
2452     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
2453         panel_req_show_factory_menu (ic);
2454         ret = true;
2455     } else if (_imengine_hotkey_matcher.is_matched ()) {
2456         ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
2457         ISE_TYPE type = info.type;
2458         if (type == IMENGINE_T)
2459             open_specific_factory (ic, info.uuid);
2460         else if (type == HELPER_T)
2461             _panel_client.start_helper (ic->id, info.uuid);
2462         ret = true;
2463     }
2464     return ret;
2465 }
2466
2467 static bool
2468 panel_initialize (void)
2469 {
2470     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2471
2472     String display_name;
2473     {
2474         const char *p = getenv ("DISPLAY");
2475         if (p) display_name = String (p);
2476     }
2477
2478     if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
2479         int fd = _panel_client.get_connection_number ();
2480
2481         _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
2482 //        _panel_iochannel_err_handler  = ecore_main_fd_handler_add (fd, ECORE_FD_ERROR, panel_iochannel_handler, NULL, NULL, NULL);
2483
2484         SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
2485
2486         EcoreIMFContextISF *context_scim = _ic_list;
2487         while (context_scim != NULL) {
2488             _panel_client.prepare (context_scim->id);
2489             _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
2490             _panel_client.send ();
2491             context_scim = context_scim->next;
2492         }
2493
2494         if (_focused_ic) {
2495             _panel_client.prepare (_focused_ic->id);
2496             panel_req_focus_in (_focused_ic);
2497             _panel_client.send ();
2498         }
2499
2500         return true;
2501     }
2502     std::cerr << "panel_initialize () failed!!!\n";
2503     return false;
2504 }
2505
2506 static void
2507 panel_finalize (void)
2508 {
2509     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2510
2511     _panel_client.close_connection ();
2512
2513     if (_panel_iochannel_read_handler) {
2514         ecore_main_fd_handler_del (_panel_iochannel_read_handler);
2515         _panel_iochannel_read_handler = 0;
2516     }
2517     if (_panel_iochannel_err_handler) {
2518         ecore_main_fd_handler_del (_panel_iochannel_err_handler);
2519         _panel_iochannel_err_handler = 0;
2520     }
2521 }
2522
2523 static Eina_Bool
2524 panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
2525 {
2526     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2527
2528     if (fd_handler == _panel_iochannel_read_handler) {
2529         if (_panel_client.has_pending_event () && !_panel_client.filter_event ()) {
2530             panel_finalize ();
2531             panel_initialize ();
2532             return ECORE_CALLBACK_CANCEL;
2533         }
2534     } else if (fd_handler == _panel_iochannel_err_handler) {
2535         panel_finalize ();
2536         panel_initialize ();
2537         return ECORE_CALLBACK_CANCEL;
2538     }
2539     return ECORE_CALLBACK_RENEW;
2540 }
2541
2542 static void
2543 turn_on_ic (EcoreIMFContextISF *ic)
2544 {
2545     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2546
2547     if (ic && ic->impl && !ic->impl->is_on) {
2548         ic->impl->is_on = true;
2549
2550         if (ic == _focused_ic) {
2551             panel_req_focus_in (ic);
2552 //            panel_req_update_spot_location (ic);
2553             panel_req_update_factory_info (ic);
2554             _panel_client.turn_on (ic->id);
2555 //            _panel_client.hide_preedit_string (ic->id);
2556 //            _panel_client.hide_aux_string (ic->id);
2557 //            _panel_client.hide_lookup_table (ic->id);
2558             ic->impl->si->focus_in ();
2559             ic->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ic->ctx));
2560             set_prediction_allow (ic->impl->si, ic->impl->prediction_allow);
2561         }
2562
2563         //Record the IC on/off status
2564         if (_shared_input_method) {
2565             _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
2566             _config->flush ();
2567         }
2568
2569         if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2570             ecore_imf_context_preedit_start_event_add (ic->ctx);
2571             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2572             ecore_imf_context_preedit_changed_event_add (ic->ctx);
2573             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2574             ic->impl->preedit_started = true;
2575         }
2576     }
2577 }
2578
2579 static void
2580 turn_off_ic (EcoreIMFContextISF *ic)
2581 {
2582     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2583
2584     if (ic && ic->impl && ic->impl->is_on) {
2585         ic->impl->is_on = false;
2586
2587         if (ic == _focused_ic) {
2588             ic->impl->si->focus_out ();
2589
2590 //            panel_req_update_factory_info (ic);
2591             _panel_client.turn_off (ic->id);
2592         }
2593
2594         //Record the IC on/off status
2595         if (_shared_input_method) {
2596             _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2597             _config->flush ();
2598         }
2599
2600         if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2601             ecore_imf_context_preedit_changed_event_add (ic->ctx);
2602             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2603             ecore_imf_context_preedit_end_event_add (ic->ctx);
2604             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2605             ic->impl->preedit_started = false;
2606         }
2607     }
2608 }
2609
2610 static void
2611 set_ic_capabilities (EcoreIMFContextISF *ic)
2612 {
2613     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2614
2615     if (ic && ic->impl) {
2616         unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2617
2618         if (!_on_the_spot || !ic->impl->use_preedit)
2619             cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2620
2621         ic->impl->si->update_client_capabilities (cap);
2622     }
2623 }
2624
2625 static bool
2626 check_socket_frontend (void)
2627 {
2628     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2629
2630     SocketAddress address;
2631     SocketClient client;
2632
2633     uint32 magic;
2634
2635     address.set_address (scim_get_default_socket_frontend_address ());
2636
2637     if (!client.connect (address))
2638         return false;
2639
2640     if (!scim_socket_open_connection (magic,
2641                                       String ("ConnectionTester"),
2642                                       String ("SocketFrontEnd"),
2643                                       client,
2644                                       1000)) {
2645         return false;
2646     }
2647
2648     return true;
2649 }
2650
2651 void
2652 initialize (void)
2653 {
2654     std::vector<String>     config_list;
2655     std::vector<String>     engine_list;
2656     std::vector<String>     helper_list;
2657     std::vector<String>     load_engine_list;
2658
2659     std::vector<String>::iterator it;
2660
2661     bool                    manual = false;
2662     bool                    socket = true;
2663     String                  config_module_name = "simple";
2664
2665     SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore ISF IMModule...\n";
2666
2667     // Get system language.
2668     _language = scim_get_locale_language (scim_get_current_locale ());
2669
2670     if (socket) {
2671         // If no Socket FrontEnd is running, then launch one.
2672         // And set manual to false.
2673         bool check_result = check_socket_frontend ();
2674         if (!check_result) {
2675             std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
2676             //get modules list
2677             scim_get_imengine_module_list (engine_list);
2678             scim_get_helper_module_list (helper_list);
2679
2680             for (it = engine_list.begin (); it != engine_list.end (); it++) {
2681                 if (*it != "socket")
2682                     load_engine_list.push_back (*it);
2683             }
2684             for (it = helper_list.begin (); it != helper_list.end (); it++)
2685                 load_engine_list.push_back (*it);
2686             const char *new_argv [] = { "--no-stay", 0 };
2687             scim_launch (true,
2688                          config_module_name,
2689                          (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
2690                          "socket",
2691                          (char **)new_argv);
2692             manual = false;
2693         }
2694
2695         // If there is one Socket FrontEnd running and it's not manual mode,
2696         // then just use this Socket Frontend.
2697         if (!manual) {
2698             for (int i = 0; i < 200; ++i) {
2699                 if (check_result) {
2700                     config_module_name = "socket";
2701                     load_engine_list.clear ();
2702                     load_engine_list.push_back ("socket");
2703                     break;
2704                 }
2705                 scim_usleep (50000);
2706                 check_result = check_socket_frontend ();
2707             }
2708         }
2709     }
2710
2711     if (config_module_name != "dummy") {
2712         //load config module
2713         SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
2714         _config_module = new ConfigModule (config_module_name);
2715
2716         //create config instance
2717         if (_config_module != NULL && _config_module->valid ())
2718             _config = _config_module->create_config ();
2719     }
2720
2721     if (_config.null ()) {
2722         SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
2723
2724         if (_config_module) delete _config_module;
2725         _config_module = NULL;
2726
2727         _config = new DummyConfig ();
2728         config_module_name = "dummy";
2729     }
2730
2731     reload_config_callback (_config);
2732     _config->signal_connect_reload (slot (reload_config_callback));
2733
2734     // create backend
2735     _backend = new CommonBackEnd (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list);
2736
2737     if (_backend.null ()) {
2738         std::cerr << "Cannot create BackEnd Object!\n";
2739     } else {
2740         _backend->initialize (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list, false, false);
2741         _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
2742     }
2743
2744     if (_fallback_factory.null ())
2745         _fallback_factory = new DummyIMEngineFactory ();
2746
2747     _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
2748     _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
2749
2750     // Attach Panel Client signal.
2751     _panel_client.signal_connect_reload_config                 (slot (panel_slot_reload_config));
2752     _panel_client.signal_connect_exit                          (slot (panel_slot_exit));
2753     _panel_client.signal_connect_update_candidate_item_layout  (slot (panel_slot_update_candidate_item_layout));
2754     _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
2755     _panel_client.signal_connect_lookup_table_page_up          (slot (panel_slot_lookup_table_page_up));
2756     _panel_client.signal_connect_lookup_table_page_down        (slot (panel_slot_lookup_table_page_down));
2757     _panel_client.signal_connect_trigger_property              (slot (panel_slot_trigger_property));
2758     _panel_client.signal_connect_process_helper_event          (slot (panel_slot_process_helper_event));
2759     _panel_client.signal_connect_move_preedit_caret            (slot (panel_slot_move_preedit_caret));
2760     _panel_client.signal_connect_update_preedit_caret          (slot (panel_slot_update_preedit_caret));
2761     _panel_client.signal_connect_select_aux                    (slot (panel_slot_select_aux));
2762     _panel_client.signal_connect_select_candidate              (slot (panel_slot_select_candidate));
2763     _panel_client.signal_connect_process_key_event             (slot (panel_slot_process_key_event));
2764     _panel_client.signal_connect_commit_string                 (slot (panel_slot_commit_string));
2765     _panel_client.signal_connect_forward_key_event             (slot (panel_slot_forward_key_event));
2766     _panel_client.signal_connect_request_help                  (slot (panel_slot_request_help));
2767     _panel_client.signal_connect_request_factory_menu          (slot (panel_slot_request_factory_menu));
2768     _panel_client.signal_connect_change_factory                (slot (panel_slot_change_factory));
2769     _panel_client.signal_connect_reset_keyboard_ise            (slot (panel_slot_reset_keyboard_ise));
2770     _panel_client.signal_connect_update_keyboard_ise           (slot (panel_slot_update_keyboard_ise));
2771     _panel_client.signal_connect_show_preedit_string           (slot (panel_slot_show_preedit_string));
2772     _panel_client.signal_connect_hide_preedit_string           (slot (panel_slot_hide_preedit_string));
2773     _panel_client.signal_connect_update_preedit_string         (slot (panel_slot_update_preedit_string));
2774     _panel_client.signal_connect_get_surrounding_text          (slot (panel_slot_get_surrounding_text));
2775     _panel_client.signal_connect_delete_surrounding_text       (slot (panel_slot_delete_surrounding_text));
2776     _panel_client.signal_connect_update_displayed_candidate_number (slot (panel_slot_update_displayed_candidate_number));
2777     _panel_client.signal_connect_candidate_more_window_show    (slot (panel_slot_candidate_more_window_show));
2778     _panel_client.signal_connect_candidate_more_window_hide    (slot (panel_slot_candidate_more_window_hide));
2779     _panel_client.signal_connect_longpress_candidate           (slot (panel_slot_longpress_candidate));
2780     _panel_client.signal_connect_update_client_id              (slot (panel_slot_update_client_id));
2781
2782     if (!panel_initialize ()) {
2783         std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
2784     }
2785 }
2786
2787 static void
2788 finalize (void)
2789 {
2790     SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
2791
2792     // Reset this first so that the shared instance could be released correctly afterwards.
2793     _default_instance.reset ();
2794
2795     SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2796     while (_used_ic_impl_list) {
2797         // In case in "shared input method" mode,
2798         // all contexts share only one instance,
2799         // so we need point the reference pointer correctly before finalizing.
2800         _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2801         isf_imf_context_del (_used_ic_impl_list->parent->ctx);
2802     }
2803
2804     delete_all_ic_impl ();
2805
2806     _fallback_instance.reset ();
2807     _fallback_factory.reset ();
2808
2809     SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2810     _backend.reset ();
2811
2812     SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2813     _config.reset ();
2814
2815     if (_config_module) {
2816         SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2817         delete _config_module;
2818         _config_module = 0;
2819     }
2820
2821     _focused_ic = NULL;
2822     _ic_list = NULL;
2823
2824     _scim_initialized = false;
2825
2826     _panel_client.reset_signal_handler ();
2827     panel_finalize ();
2828 }
2829
2830 static void
2831 _popup_message (const char *_ptext)
2832 {
2833     if (_ptext == NULL)
2834         return;
2835
2836     notification_status_message_post(_ptext);
2837 }
2838
2839 static void
2840 _display_input_language (EcoreIMFContextISF *ic)
2841 {
2842     IMEngineFactoryPointer sf;
2843
2844     if (ic && ic->impl) {
2845         if (ic->impl->is_on) {
2846             sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2847             _popup_message (scim_get_language_name (sf->get_language ()).c_str ());
2848         }
2849         else {
2850             _popup_message (scim_get_language_name ("en").c_str());
2851         }
2852     }
2853 }
2854
2855 static void
2856 open_next_factory (EcoreIMFContextISF *ic)
2857 {
2858     SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2859     IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2860
2861     if (!sf.null ()) {
2862         turn_off_ic (ic);
2863         ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2864         ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2865         ic->impl->preedit_string = WideString ();
2866         ic->impl->preedit_caret = 0;
2867         attach_instance (ic->impl->si);
2868         _backend->set_default_factory (_language, sf->get_uuid ());
2869         _panel_client.register_input_context (ic->id, sf->get_uuid ());
2870         _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2871         set_ic_capabilities (ic);
2872         turn_on_ic (ic);
2873
2874         if (_shared_input_method) {
2875             _default_instance = ic->impl->si;
2876             ic->impl->shared_si = true;
2877         }
2878         _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2879     }
2880 }
2881
2882 static void
2883 open_previous_factory (EcoreIMFContextISF *ic)
2884 {
2885     if (ic == NULL)
2886         return;
2887
2888     SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2889     IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2890
2891     if (!sf.null ()) {
2892         turn_off_ic (ic);
2893         ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2894         ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2895         ic->impl->preedit_string = WideString ();
2896         ic->impl->preedit_caret = 0;
2897         attach_instance (ic->impl->si);
2898         _backend->set_default_factory (_language, sf->get_uuid ());
2899         _panel_client.register_input_context (ic->id, sf->get_uuid ());
2900         _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2901         set_ic_capabilities (ic);
2902         turn_on_ic (ic);
2903
2904         if (_shared_input_method) {
2905             _default_instance = ic->impl->si;
2906             ic->impl->shared_si = true;
2907         }
2908         _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2909     }
2910 }
2911
2912 static void
2913 open_specific_factory (EcoreIMFContextISF *ic,
2914                        const String     &uuid)
2915 {
2916     if (ic == NULL)
2917         return;
2918
2919     SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2920
2921     // The same input method is selected, just turn on the IC.
2922     if (ic->impl->si->get_factory_uuid () == uuid) {
2923         turn_on_ic (ic);
2924         return;
2925     }
2926
2927     IMEngineFactoryPointer sf = _backend->get_factory (uuid);
2928
2929     if (uuid.length () && !sf.null ()) {
2930         turn_off_ic (ic);
2931         ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2932         ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2933         ic->impl->preedit_string = WideString ();
2934         ic->impl->preedit_caret = 0;
2935         attach_instance (ic->impl->si);
2936         _backend->set_default_factory (_language, sf->get_uuid ());
2937         _panel_client.register_input_context (ic->id, sf->get_uuid ());
2938         set_ic_capabilities (ic);
2939         turn_on_ic (ic);
2940
2941         if (_shared_input_method) {
2942             _default_instance = ic->impl->si;
2943             ic->impl->shared_si = true;
2944         }
2945     } else {
2946         std::cerr << "open_specific_factory () is failed!!!!!!\n";
2947         LOGE ("open_specific_factory () is failed. ic : %x uuid : %s", ic->id, uuid.c_str());
2948
2949         // turn_off_ic comment out panel_req_update_factory_info ()
2950         //turn_off_ic (ic);
2951         if (ic && ic->impl->is_on) {
2952             ic->impl->is_on = false;
2953
2954             if (ic == _focused_ic) {
2955                 ic->impl->si->focus_out ();
2956
2957                 panel_req_update_factory_info (ic);
2958                 _panel_client.turn_off (ic->id);
2959             }
2960
2961             //Record the IC on/off status
2962             if (_shared_input_method) {
2963                 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2964                 _config->flush ();
2965             }
2966
2967             if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2968                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2969                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2970                 ecore_imf_context_preedit_end_event_add (ic->ctx);
2971                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2972                 ic->impl->preedit_started = false;
2973             }
2974         }
2975     }
2976 }
2977
2978 static void initialize_modifier_bits (Display *display)
2979 {
2980     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2981
2982     if (__current_display == display)
2983         return;
2984
2985     __current_display = display;
2986
2987     if (display == 0) {
2988         __current_alt_mask     = Mod1Mask;
2989         __current_meta_mask    = ShiftMask | Mod1Mask;
2990         __current_super_mask   = 0;
2991         __current_hyper_mask   = 0;
2992         __current_numlock_mask = Mod2Mask;
2993         return;
2994     }
2995
2996     XModifierKeymap *mods = NULL;
2997
2998     ::KeyCode ctrl_l  = XKeysymToKeycode (display, XK_Control_L);
2999     ::KeyCode ctrl_r  = XKeysymToKeycode (display, XK_Control_R);
3000     ::KeyCode meta_l  = XKeysymToKeycode (display, XK_Meta_L);
3001     ::KeyCode meta_r  = XKeysymToKeycode (display, XK_Meta_R);
3002     ::KeyCode alt_l   = XKeysymToKeycode (display, XK_Alt_L);
3003     ::KeyCode alt_r   = XKeysymToKeycode (display, XK_Alt_R);
3004     ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
3005     ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
3006     ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
3007     ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
3008     ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
3009
3010     int i, j;
3011
3012     mods = XGetModifierMapping (display);
3013     if (mods == NULL)
3014         return;
3015
3016     __current_alt_mask     = 0;
3017     __current_meta_mask    = 0;
3018     __current_super_mask   = 0;
3019     __current_hyper_mask   = 0;
3020     __current_numlock_mask = 0;
3021
3022     /* We skip the first three sets for Shift, Lock, and Control.  The
3023         remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5.  */
3024     for (i = 3; i < 8; i++) {
3025         for (j = 0; j < mods->max_keypermod; j++) {
3026             ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
3027             if (! code) continue;
3028             if (code == alt_l || code == alt_r)
3029                 __current_alt_mask |= (1 << i);
3030             else if (code == meta_l || code == meta_r)
3031                 __current_meta_mask |= (1 << i);
3032             else if (code == super_l || code == super_r)
3033                 __current_super_mask |= (1 << i);
3034             else if (code == hyper_l || code == hyper_r)
3035                 __current_hyper_mask |= (1 << i);
3036             else if (code == numlock)
3037                 __current_numlock_mask |= (1 << i);
3038         }
3039     }
3040
3041     /* Check whether there is a combine keys mapped to Meta */
3042     if (__current_meta_mask == 0) {
3043         char buf [32];
3044         XKeyEvent xkey;
3045         KeySym keysym_l, keysym_r;
3046
3047         xkey.type = KeyPress;
3048         xkey.display = display;
3049         xkey.serial = 0L;
3050         xkey.send_event = False;
3051         xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
3052         xkey.time = 0;
3053         xkey.same_screen = False;
3054         xkey.subwindow = None;
3055         xkey.window = None;
3056         xkey.root = DefaultRootWindow (display);
3057         xkey.state = ShiftMask;
3058
3059         xkey.keycode = meta_l;
3060         XLookupString (&xkey, buf, 32, &keysym_l, 0);
3061         xkey.keycode = meta_r;
3062         XLookupString (&xkey, buf, 32, &keysym_r, 0);
3063
3064         if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
3065             __current_meta_mask = ShiftMask + __current_alt_mask;
3066         else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
3067             __current_meta_mask = ShiftMask + ControlMask;
3068     }
3069
3070     XFreeModifiermap (mods);
3071 }
3072
3073 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
3074 {
3075     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3076
3077     unsigned int state = 0;
3078
3079     initialize_modifier_bits (display);
3080
3081     if (scimkeymask & SCIM_KEY_ShiftMask)    state |= ShiftMask;
3082     if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
3083     if (scimkeymask & SCIM_KEY_ControlMask)  state |= ControlMask;
3084     if (scimkeymask & SCIM_KEY_AltMask)      state |= __current_alt_mask;
3085     if (scimkeymask & SCIM_KEY_MetaMask)     state |= __current_meta_mask;
3086     if (scimkeymask & SCIM_KEY_SuperMask)    state |= __current_super_mask;
3087     if (scimkeymask & SCIM_KEY_HyperMask)    state |= __current_hyper_mask;
3088     if (scimkeymask & SCIM_KEY_NumLockMask)  state |= __current_numlock_mask;
3089
3090     return state;
3091 }
3092
3093 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake)
3094 {
3095     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3096
3097     XKeyEvent event;
3098     Window focus_win;
3099     Display *display = (Display *)ecore_x_display_get ();
3100     int revert = RevertToParent;
3101
3102     XGetInputFocus (display, &focus_win, &revert);
3103
3104     event.display     = display;
3105     event.window      = focus_win;
3106     event.root        = DefaultRootWindow (display);
3107     event.subwindow   = None;
3108     if (fake)
3109         event.time    = 0;
3110     else
3111         event.time    = get_time ();
3112
3113     event.x           = 1;
3114     event.y           = 1;
3115     event.x_root      = 1;
3116     event.y_root      = 1;
3117     event.same_screen = True;
3118     event.state       = modifiers;
3119     event.keycode     = keycode;
3120     if (press)
3121         event.type = KeyPress;
3122     else
3123         event.type = KeyRelease;
3124     event.send_event  = False;
3125     event.serial      = 0;
3126
3127     return event;
3128 }
3129
3130 static void send_x_key_event (const KeyEvent &key, bool fake)
3131 {
3132     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3133
3134     ::KeyCode keycode = 0;
3135     ::KeySym keysym = 0;
3136     int shift = 0;
3137     char key_string[256] = {0};
3138     char keysym_str[256] = {0};
3139
3140     // Obtain the X11 display.
3141     Display *display = (Display *)ecore_x_display_get ();
3142     if (display == NULL) {
3143         std::cerr << "ecore_x_display_get () failed\n";
3144         return;
3145     }
3146
3147     if (strncmp (key.get_key_string ().c_str (), "KeyRelease+", 11) == 0) {
3148         snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str () + 11);
3149     } else {
3150         snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str ());
3151     }
3152
3153     if (strncmp (key_string, "Shift+", 6) == 0) {
3154         snprintf (keysym_str, sizeof (keysym_str), "%s", key_string + 6);
3155     } else {
3156         snprintf (keysym_str, sizeof (keysym_str), "%s", key_string);
3157     }
3158
3159     // get x keysym, keycode, keyname, and key
3160     keysym = XStringToKeysym (keysym_str);
3161     if (keysym == NoSymbol)
3162         return;
3163
3164     keycode = _keyname_to_keycode (keysym_str);
3165     if (XkbKeycodeToKeysym (display, keycode, 0, 0) != keysym) {
3166         if (XkbKeycodeToKeysym (display, keycode, 0, 1) == keysym)
3167             shift = 1;
3168         else
3169             keycode = 0;
3170     } else {
3171         shift = 0;
3172     }
3173
3174     if (keycode == 0) {
3175         static int mod = 0;
3176         KeySym *keysyms;
3177         int keycode_min, keycode_max, keycode_num;
3178         int i;
3179
3180         XDisplayKeycodes (display, &keycode_min, &keycode_max);
3181         keysyms = XGetKeyboardMapping (display, keycode_min,
3182                 keycode_max - keycode_min + 1,
3183                 &keycode_num);
3184         mod = (mod + 1) & 0x7;
3185         i = (keycode_max - keycode_min - mod - 1) * keycode_num;
3186
3187         keysyms[i] = keysym;
3188         XChangeKeyboardMapping (display, keycode_min, keycode_num,
3189                 keysyms, (keycode_max - keycode_min));
3190         XFree (keysyms);
3191         XSync (display, False);
3192         keycode = keycode_max - mod - 1;
3193     }
3194
3195     unsigned int modifier = scim_x11_keymask_scim_to_x11 (display, key.mask);
3196
3197     if (shift)
3198         modifier |= ShiftMask;
3199
3200     XKeyEvent event;
3201     if (key.is_key_press ()) {
3202         if (shift) {
3203             event = createKeyEvent (true, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3204             XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3205         }
3206
3207         event = createKeyEvent (true, keycode, modifier, fake);
3208         XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3209     } else {
3210         event = createKeyEvent (false, keycode, modifier, fake);
3211         XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3212
3213         if (shift) {
3214             event = createKeyEvent (false, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3215             XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3216         }
3217     }
3218 }
3219
3220 static void
3221 attach_instance (const IMEngineInstancePointer &si)
3222 {
3223     si->signal_connect_show_preedit_string (
3224         slot (slot_show_preedit_string));
3225     si->signal_connect_show_aux_string (
3226         slot (slot_show_aux_string));
3227     si->signal_connect_show_lookup_table (
3228         slot (slot_show_lookup_table));
3229
3230     si->signal_connect_hide_preedit_string (
3231         slot (slot_hide_preedit_string));
3232     si->signal_connect_hide_aux_string (
3233         slot (slot_hide_aux_string));
3234     si->signal_connect_hide_lookup_table (
3235         slot (slot_hide_lookup_table));
3236
3237     si->signal_connect_update_preedit_caret (
3238         slot (slot_update_preedit_caret));
3239     si->signal_connect_update_preedit_string (
3240         slot (slot_update_preedit_string));
3241     si->signal_connect_update_aux_string (
3242         slot (slot_update_aux_string));
3243     si->signal_connect_update_lookup_table (
3244         slot (slot_update_lookup_table));
3245
3246     si->signal_connect_commit_string (
3247         slot (slot_commit_string));
3248
3249     si->signal_connect_forward_key_event (
3250         slot (slot_forward_key_event));
3251
3252     si->signal_connect_register_properties (
3253         slot (slot_register_properties));
3254
3255     si->signal_connect_update_property (
3256         slot (slot_update_property));
3257
3258     si->signal_connect_beep (
3259         slot (slot_beep));
3260
3261     si->signal_connect_start_helper (
3262         slot (slot_start_helper));
3263
3264     si->signal_connect_stop_helper (
3265         slot (slot_stop_helper));
3266
3267     si->signal_connect_send_helper_event (
3268         slot (slot_send_helper_event));
3269
3270     si->signal_connect_get_surrounding_text (
3271         slot (slot_get_surrounding_text));
3272
3273     si->signal_connect_delete_surrounding_text (
3274         slot (slot_delete_surrounding_text));
3275
3276     si->signal_connect_expand_candidate (
3277         slot (slot_expand_candidate));
3278     si->signal_connect_contract_candidate (
3279         slot (slot_contract_candidate));
3280
3281     si->signal_connect_set_candidate_style (
3282         slot (slot_set_candidate_style));
3283 }
3284
3285 // Implementation of slot functions
3286 static void
3287 slot_show_preedit_string (IMEngineInstanceBase *si)
3288 {
3289     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3290
3291     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3292
3293     if (ic && ic->impl && _focused_ic == ic) {
3294         if (ic->impl->use_preedit) {
3295             if (!ic->impl->preedit_started) {
3296                 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3297                 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3298                 ic->impl->preedit_started = true;
3299             }
3300             //if (ic->impl->preedit_string.length ())
3301             //    ecore_imf_context_preedit_changed_event_add (_focused_ic->ctx);
3302         } else {
3303             _panel_client.show_preedit_string (ic->id);
3304         }
3305     }
3306 }
3307
3308 static void
3309 slot_show_aux_string (IMEngineInstanceBase *si)
3310 {
3311     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3312
3313     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3314
3315     if (ic && ic->impl && _focused_ic == ic)
3316         _panel_client.show_aux_string (ic->id);
3317 }
3318
3319 static void
3320 slot_show_lookup_table (IMEngineInstanceBase *si)
3321 {
3322     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3323
3324     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3325
3326     if (ic && ic->impl && _focused_ic == ic)
3327         _panel_client.show_lookup_table (ic->id);
3328 }
3329
3330 static void
3331 slot_hide_preedit_string (IMEngineInstanceBase *si)
3332 {
3333     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3334
3335     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3336
3337     if (ic && ic->impl && _focused_ic == ic) {
3338         bool emit = false;
3339         if (ic->impl->preedit_string.length ()) {
3340             ic->impl->preedit_string = WideString ();
3341             ic->impl->preedit_caret = 0;
3342             ic->impl->preedit_attrlist.clear ();
3343             emit = true;
3344         }
3345         if (ic->impl->use_preedit) {
3346             if (emit) {
3347                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3348                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3349             }
3350             if (ic->impl->preedit_started) {
3351                 ecore_imf_context_preedit_end_event_add (ic->ctx);
3352                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
3353                 ic->impl->preedit_started = false;
3354             }
3355         } else {
3356             _panel_client.hide_preedit_string (ic->id);
3357         }
3358     }
3359 }
3360
3361 static void
3362 slot_hide_aux_string (IMEngineInstanceBase *si)
3363 {
3364     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3365
3366     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3367
3368     if (ic && ic->impl && _focused_ic == ic)
3369         _panel_client.hide_aux_string (ic->id);
3370 }
3371
3372 static void
3373 slot_hide_lookup_table (IMEngineInstanceBase *si)
3374 {
3375     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3376
3377     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3378
3379     if (ic && ic->impl && _focused_ic == ic)
3380         _panel_client.hide_lookup_table (ic->id);
3381 }
3382
3383 static void
3384 slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
3385 {
3386     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3387
3388     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3389
3390     if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
3391         ic->impl->preedit_caret = caret;
3392         if (ic->impl->use_preedit) {
3393             if (!ic->impl->preedit_started) {
3394                 ecore_imf_context_preedit_start_event_add (ic->ctx);
3395                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3396                 ic->impl->preedit_started = true;
3397             }
3398             ecore_imf_context_preedit_changed_event_add (ic->ctx);
3399             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3400         } else {
3401             _panel_client.update_preedit_caret (ic->id, caret);
3402         }
3403     }
3404 }
3405
3406 static void
3407 slot_update_preedit_string (IMEngineInstanceBase *si,
3408                             const WideString & str,
3409                             const AttributeList & attrs)
3410 {
3411     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3412
3413     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3414
3415     if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
3416         ic->impl->preedit_string   = str;
3417         ic->impl->preedit_attrlist = attrs;
3418         if (ic->impl->use_preedit) {
3419             if (!ic->impl->preedit_started) {
3420                 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3421                 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3422                 ic->impl->preedit_started = true;
3423             }
3424             ic->impl->preedit_caret    = str.length ();
3425             ic->impl->preedit_updating = true;
3426             ecore_imf_context_preedit_changed_event_add (ic->ctx);
3427             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3428             ic->impl->preedit_updating = false;
3429         } else {
3430             _panel_client.update_preedit_string (ic->id, str, attrs);
3431         }
3432     }
3433 }
3434
3435 static void
3436 slot_update_aux_string (IMEngineInstanceBase *si,
3437                         const WideString & str,
3438                         const AttributeList & attrs)
3439 {
3440     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3441
3442     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3443
3444     if (ic && ic->impl && _focused_ic == ic)
3445         _panel_client.update_aux_string (ic->id, str, attrs);
3446 }
3447
3448 static void
3449 slot_commit_string (IMEngineInstanceBase *si,
3450                     const WideString & str)
3451 {
3452     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3453
3454     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3455
3456     if (ic && ic->ctx) {
3457         if (strcmp (utf8_wcstombs (str).c_str (), " ") == 0)
3458             autoperiod_insert (ic->ctx);
3459
3460         ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ());
3461         ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3462     }
3463 }
3464
3465 static void
3466 slot_forward_key_event (IMEngineInstanceBase *si,
3467                         const KeyEvent & key)
3468 {
3469     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3470
3471     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3472
3473     if (ic && _focused_ic == ic) {
3474         if (!_fallback_instance->process_key_event (key)) {
3475             feed_key_event (ic, key, true);
3476         }
3477     }
3478 }
3479
3480 static void
3481 slot_update_lookup_table (IMEngineInstanceBase *si,
3482                           const LookupTable & table)
3483 {
3484     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3485
3486     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3487
3488     if (ic && ic->impl && _focused_ic == ic)
3489         _panel_client.update_lookup_table (ic->id, table);
3490 }
3491
3492 static void
3493 slot_register_properties (IMEngineInstanceBase *si,
3494                           const PropertyList & properties)
3495 {
3496     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3497
3498     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3499
3500     if (ic && ic->impl && _focused_ic == ic)
3501         _panel_client.register_properties (ic->id, properties);
3502 }
3503
3504 static void
3505 slot_update_property (IMEngineInstanceBase *si,
3506                       const Property & property)
3507 {
3508     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3509
3510     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3511
3512     if (ic && ic->impl && _focused_ic == ic)
3513         _panel_client.update_property (ic->id, property);
3514 }
3515
3516 static void
3517 slot_beep (IMEngineInstanceBase *si)
3518 {
3519     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3520
3521     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3522
3523     if (ic && ic->impl && _focused_ic == ic)
3524         ecore_x_bell (0);
3525 }
3526
3527 static void
3528 slot_start_helper (IMEngineInstanceBase *si,
3529                    const String &helper_uuid)
3530 {
3531     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3532
3533     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3534                            << (ic != NULL ? ic->id : -1) << " ic=" << ic
3535                            << " ic-uuid=" << ((ic != NULL ) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3536
3537     if (ic && ic->impl)
3538         _panel_client.start_helper (ic->id, helper_uuid);
3539 }
3540
3541 static void
3542 slot_stop_helper (IMEngineInstanceBase *si,
3543                   const String &helper_uuid)
3544 {
3545     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3546
3547     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic != NULL ? ic->id : -1) << " ic=" << ic << "...\n";
3548
3549     if (ic && ic->impl)
3550         _panel_client.stop_helper (ic->id, helper_uuid);
3551 }
3552
3553 static void
3554 slot_send_helper_event (IMEngineInstanceBase *si,
3555                         const String      &helper_uuid,
3556                         const Transaction &trans)
3557 {
3558     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3559
3560     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3561                            << (ic != NULL ? ic->id : -1) << " ic=" << ic
3562                            << " ic-uuid=" << ((ic != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3563
3564     if (ic && ic->impl)
3565         _panel_client.send_helper_event (ic->id, helper_uuid, trans);
3566 }
3567
3568 static bool
3569 slot_get_surrounding_text (IMEngineInstanceBase *si,
3570                            WideString            &text,
3571                            int                   &cursor,
3572                            int                    maxlen_before,
3573                            int                    maxlen_after)
3574 {
3575     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3576
3577     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3578
3579     if (ic && ic->impl && _focused_ic == ic) {
3580         char *surrounding = NULL;
3581         int   cursor_index;
3582         if (ecore_imf_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index)) {
3583             SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
3584             SCIM_DEBUG_FRONTEND(2) << "Cursor Index    : " << cursor_index <<"\n";
3585             WideString before = utf8_mbstowcs (String (surrounding));
3586             if (cursor_index > (int)before.length())
3587                 return false;
3588             WideString after = before;
3589             before = before.substr (0, cursor_index);
3590             after =  after.substr (cursor_index, after.length () - cursor_index);
3591             if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
3592                 before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
3593             else if (maxlen_before == 0)
3594                 before = WideString ();
3595             if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
3596                 after = WideString (after.begin (), after.begin () + maxlen_after);
3597             else if (maxlen_after == 0)
3598                 after = WideString ();
3599             text = before + after;
3600             cursor = before.length ();
3601             return true;
3602         }
3603     }
3604     return false;
3605 }
3606
3607 static bool
3608 slot_delete_surrounding_text (IMEngineInstanceBase *si,
3609                               int                   offset,
3610                               int                   len)
3611 {
3612     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3613
3614     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3615
3616     if (ic && ic->impl && _focused_ic == ic) {
3617         Ecore_IMF_Event_Delete_Surrounding ev;
3618         ev.ctx = _focused_ic->ctx;
3619         ev.n_chars = len;
3620         ev.offset = offset;
3621         ecore_imf_context_delete_surrounding_event_add (_focused_ic->ctx, offset, len);
3622         ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
3623         return true;
3624     }
3625     return false;
3626 }
3627
3628 static void
3629 slot_expand_candidate (IMEngineInstanceBase *si)
3630 {
3631     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3632
3633     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3634
3635     if (ic && ic->impl && _focused_ic == ic)
3636         _panel_client.expand_candidate (ic->id);
3637 }
3638
3639 static void
3640 slot_contract_candidate (IMEngineInstanceBase *si)
3641 {
3642     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3643
3644     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3645
3646     if (ic && ic->impl && _focused_ic == ic)
3647         _panel_client.contract_candidate (ic->id);
3648 }
3649
3650 static void
3651 slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode)
3652 {
3653     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3654
3655     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3656
3657     if (ic && ic->impl && _focused_ic == ic)
3658         _panel_client.set_candidate_style (ic->id, portrait_line, mode);
3659 }
3660
3661 static void
3662 reload_config_callback (const ConfigPointer &config)
3663 {
3664     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3665
3666     _frontend_hotkey_matcher.load_hotkeys (config);
3667     _imengine_hotkey_matcher.load_hotkeys (config);
3668
3669     KeyEvent key;
3670     scim_string_to_key (key,
3671                         config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
3672                                       String ("Shift+Control+Alt+Lock")));
3673
3674     _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
3675     _valid_key_mask |= SCIM_KEY_ReleaseMask;
3676     // Special treatment for two backslash keys on jp106 keyboard.
3677     _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
3678
3679     _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
3680     _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
3681
3682     // Get keyboard layout setting
3683     // Flush the global config first, in order to load the new configs from disk.
3684     scim_global_config_flush ();
3685
3686     _keyboard_layout = scim_get_default_keyboard_layout ();
3687 }
3688
3689 static void
3690 fallback_commit_string_cb (IMEngineInstanceBase  *si,
3691                            const WideString      &str)
3692 {
3693     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3694
3695     if (_focused_ic && _focused_ic->impl) {
3696         ecore_imf_context_commit_event_add (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
3697         ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3698     }
3699 }
3700
3701 /*
3702 vi:ts=4:expandtab:nowrap
3703 */