[immodule] avoid to send focus-in in the input panel disabled context
[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         if (ecore_imf_context_input_panel_enabled_get (ctx) == EINA_TRUE)
1139             isf_imf_context_control_focus_in (ctx);
1140
1141         _panel_client.prepare (context_scim->id);
1142
1143         // Handle the "Shared Input Method" mode.
1144         if (_shared_input_method) {
1145             SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
1146             IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1147             if (!factory.null ()) {
1148                 if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
1149                     _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
1150                     attach_instance (_default_instance);
1151                     SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
1152                 }
1153
1154                 context_scim->impl->shared_si = true;
1155                 context_scim->impl->si = _default_instance;
1156
1157                 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1158                 context_scim->impl->preedit_string.clear ();
1159                 context_scim->impl->preedit_attrlist.clear ();
1160                 context_scim->impl->preedit_caret = 0;
1161                 context_scim->impl->preedit_started = false;
1162                 need_cap = true;
1163                 need_reset = true;
1164                 need_reg = true;
1165             }
1166         } else if (context_scim->impl->shared_si) {
1167             SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
1168             IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1169             if (!factory.null ()) {
1170                 context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
1171                 context_scim->impl->preedit_string.clear ();
1172                 context_scim->impl->preedit_attrlist.clear ();
1173                 context_scim->impl->preedit_caret = 0;
1174                 context_scim->impl->preedit_started = false;
1175                 attach_instance (context_scim->impl->si);
1176                 need_cap = true;
1177                 need_reg = true;
1178                 context_scim->impl->shared_si = false;
1179                 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
1180             }
1181         }
1182
1183         context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
1184
1185         if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
1186         if (need_cap) set_ic_capabilities (context_scim);
1187
1188         panel_req_focus_in (context_scim);
1189 //        panel_req_update_spot_location (context_scim);
1190 //        panel_req_update_factory_info (context_scim);
1191
1192         if (need_reset) context_scim->impl->si->reset ();
1193         if (context_scim->impl->is_on) {
1194             _panel_client.turn_on (context_scim->id);
1195 //            _panel_client.hide_preedit_string (context_scim->id);
1196 //            _panel_client.hide_aux_string (context_scim->id);
1197 //            _panel_client.hide_lookup_table (context_scim->id);
1198             context_scim->impl->si->focus_in ();
1199             context_scim->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ctx));
1200             set_prediction_allow (context_scim->impl->si, context_scim->impl->prediction_allow);
1201             if (context_scim->impl->imdata)
1202                 context_scim->impl->si->set_imdata ((const char *)context_scim->impl->imdata, context_scim->impl->imdata_size);
1203         } else {
1204             _panel_client.turn_off (context_scim->id);
1205         }
1206
1207         _panel_client.send ();
1208     }
1209
1210     LOGD ("ctx : %p\n", ctx);
1211
1212     if (ecore_imf_context_input_panel_enabled_get (ctx))
1213         ecore_imf_context_input_panel_show (ctx);
1214     else
1215         LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
1216 }
1217
1218 /**
1219  * isf_imf_context_focus_out
1220  * @ctx: a #Ecore_IMF_Context
1221  *
1222  * This function will be called by Ecore IMF.
1223  *
1224  * Notify the Input Method Context that the widget to which its correspond has lost focus.
1225  */
1226 EAPI void
1227 isf_imf_context_focus_out (Ecore_IMF_Context *ctx)
1228 {
1229     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1230     Eina_Bool lock_scr;
1231
1232     if (!context_scim) return;
1233
1234     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1235
1236     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1237
1238         WideString wstr = context_scim->impl->preedit_string;
1239
1240         LOGD ("ctx : %p\n", ctx);
1241
1242         if (ecore_imf_context_input_panel_enabled_get (ctx))
1243             ecore_imf_context_input_panel_hide (ctx);
1244
1245         if (context_scim->impl->need_commit_preedit) {
1246             panel_slot_hide_preedit_string (context_scim->id);
1247
1248             if (wstr.length ()) {
1249                 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1250                 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1251             }
1252             _panel_client.prepare (context_scim->id);
1253             _panel_client.reset_input_context (context_scim->id);
1254             _panel_client.send ();
1255         }
1256
1257         lock_scr = check_focus_out_by_lockscreen (ctx);
1258
1259         if (!lock_scr)
1260             _panel_client.prepare (context_scim->id);
1261
1262         context_scim->impl->si->focus_out ();
1263         context_scim->impl->si->reset ();
1264
1265         if (!lock_scr) {
1266 //          if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1267             _panel_client.focus_out (context_scim->id);
1268             _panel_client.send ();
1269         }
1270         _focused_ic = 0;
1271     }
1272 }
1273
1274 /**
1275  * isf_imf_context_reset
1276  * @ctx: a #Ecore_IMF_Context
1277  *
1278  * This function will be called by Ecore IMF.
1279  *
1280  * Notify the Input Method Context that a change such as a change in cursor
1281  * position has been made. This will typically cause the Input Method Context
1282  * to clear the preedit state.
1283  */
1284 EAPI void
1285 isf_imf_context_reset (Ecore_IMF_Context *ctx)
1286 {
1287     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1288
1289     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1290
1291     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1292         WideString wstr = context_scim->impl->preedit_string;
1293
1294         _panel_client.prepare (context_scim->id);
1295         context_scim->impl->si->reset ();
1296         _panel_client.reset_input_context (context_scim->id);
1297         _panel_client.send ();
1298
1299         if (context_scim->impl->need_commit_preedit) {
1300             panel_slot_hide_preedit_string (context_scim->id);
1301
1302             if (wstr.length ()) {
1303                 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1304                 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1305             }
1306         }
1307     }
1308 }
1309
1310 /**
1311  * isf_imf_context_cursor_position_set
1312  * @ctx: a #Ecore_IMF_Context
1313  * @cursor_pos: New cursor position in characters.
1314  *
1315  * This function will be called by Ecore IMF.
1316  *
1317  * Notify the Input Method Context that a change in the cursor position has been made.
1318  */
1319 EAPI void
1320 isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos)
1321 {
1322     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1323
1324     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1325
1326     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1327         if (context_scim->impl->cursor_pos != cursor_pos) {
1328             LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
1329             context_scim->impl->cursor_pos = cursor_pos;
1330
1331             caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1332
1333             if (context_scim->impl->preedit_updating)
1334                 return;
1335             _panel_client.prepare (context_scim->id);
1336             context_scim->impl->si->update_cursor_position (cursor_pos);
1337             panel_req_update_cursor_position (context_scim, cursor_pos);
1338             _panel_client.send ();
1339         }
1340     }
1341 }
1342
1343 /**
1344  * isf_imf_context_cursor_location_set
1345  * @ctx: a #Ecore_IMF_Context
1346  * @x: x position of New cursor.
1347  * @y: y position of New cursor.
1348  * @w: the width of New cursor.
1349  * @h: the height of New cursor.
1350  *
1351  * This function will be called by Ecore IMF.
1352  *
1353  * Notify the Input Method Context that a change in the cursor location has been made.
1354  */
1355 EAPI void
1356 isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
1357 {
1358     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1359
1360     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1361     Ecore_Evas *ee;
1362     int canvas_x, canvas_y;
1363     int new_cursor_x, new_cursor_y;
1364
1365     if (cw == 0 && ch == 0)
1366         return;
1367
1368     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1369         if (context_scim->impl->client_canvas) {
1370             ee = ecore_evas_ecore_evas_get (context_scim->impl->client_canvas);
1371             if (!ee) return;
1372
1373             ecore_evas_geometry_get (ee, &canvas_x, &canvas_y, NULL, NULL);
1374         }
1375         else {
1376             if (context_scim->impl->client_window)
1377                 window_to_screen_geometry_get (context_scim->impl->client_window, &canvas_x, &canvas_y);
1378             else
1379                 return;
1380         }
1381
1382         new_cursor_x = canvas_x + cx;
1383         new_cursor_y = canvas_y + cy + ch;
1384
1385         // Don't update spot location while updating preedit string.
1386         if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
1387             return;
1388
1389         if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y) {
1390             context_scim->impl->cursor_x     = new_cursor_x;
1391             context_scim->impl->cursor_y     = new_cursor_y;
1392             context_scim->impl->cursor_top_y = canvas_y + cy;
1393             _panel_client.prepare (context_scim->id);
1394             panel_req_update_spot_location (context_scim);
1395             _panel_client.send ();
1396             SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
1397         }
1398     }
1399 }
1400
1401 /**
1402  * isf_imf_context_input_mode_set
1403  * @ctx: a #Ecore_IMF_Context
1404  * @input_mode: the input mode
1405  *
1406  * This function will be called by Ecore IMF.
1407  *
1408  * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
1409  * is in Ecore_IMF.h.
1410  */
1411 EAPI void
1412 isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
1413 {
1414     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1415
1416     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1417     if (context_scim && context_scim->impl) {
1418         context_scim->impl->input_mode = input_mode;
1419     }
1420 }
1421
1422 /**
1423  * isf_imf_context_preedit_string_get
1424  * @ctx: a #Ecore_IMF_Context
1425  * @str: the preedit string
1426  * @cursor_pos: the cursor position
1427  *
1428  * This function will be called by Ecore IMF.
1429  *
1430  * To get the preedit string of the input method.
1431  */
1432 EAPI void
1433 isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
1434 {
1435     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1436
1437     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1438
1439     if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1440         String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1441
1442         if (str) {
1443             if (mbs.length ())
1444                 *str = strdup (mbs.c_str ());
1445             else
1446                 *str = strdup ("");
1447         }
1448
1449         if (cursor_pos) {
1450             *cursor_pos = context_scim->impl->preedit_caret;
1451         }
1452     } else {
1453         if (str)
1454             *str = strdup ("");
1455
1456         if (cursor_pos)
1457             *cursor_pos = 0;
1458     }
1459 }
1460
1461 EAPI void
1462 isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
1463 {
1464     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1465
1466     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1467
1468     if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1469         String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1470
1471         if (str) {
1472             if (mbs.length ())
1473                 *str = strdup (mbs.c_str ());
1474             else
1475                 *str = strdup ("");
1476         }
1477
1478         if (cursor_pos) {
1479             *cursor_pos = context_scim->impl->preedit_caret;
1480         }
1481
1482         if (attrs) {
1483             if (mbs.length ()) {
1484                 int start_index, end_index;
1485                 int wlen = context_scim->impl->preedit_string.length ();
1486                 Ecore_IMF_Preedit_Attr *attr = NULL;
1487                 AttributeList::const_iterator i;
1488                 bool *attrs_flag = new bool [mbs.length ()];
1489                 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1490                 for (i = context_scim->impl->preedit_attrlist.begin ();
1491                     i != context_scim->impl->preedit_attrlist.end (); ++i) {
1492                     start_index = i->get_start ();
1493                     end_index = i->get_end ();
1494                     if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1495                         start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1496                         end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1497                         if (i->get_type () == SCIM_ATTR_DECORATE) {
1498                             attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof (Ecore_IMF_Preedit_Attr));
1499                             if (attr == NULL)
1500                                 continue;
1501                             attr->start_index = start_index;
1502                             attr->end_index = end_index;
1503
1504                             if (i->get_value () == SCIM_ATTR_DECORATE_UNDERLINE) {
1505                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1506                                 *attrs = eina_list_append (*attrs, (void *)attr);
1507                             } else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE) {
1508                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1509                                 *attrs = eina_list_append (*attrs, (void *)attr);
1510                             } else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
1511                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1512                                 *attrs = eina_list_append (*attrs, (void *)attr);
1513                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR1) {
1514                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
1515                                 *attrs = eina_list_append (*attrs, (void *)attr);
1516                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR2) {
1517                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
1518                                 *attrs = eina_list_append (*attrs, (void *)attr);
1519                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR3) {
1520                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
1521                                 *attrs = eina_list_append (*attrs, (void *)attr);
1522                             } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR4) {
1523                                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
1524                                 *attrs = eina_list_append (*attrs, (void *)attr);
1525                             } else {
1526                                 free (attr);
1527                             }
1528                             switch(i->get_value())
1529                             {
1530                                 case SCIM_ATTR_DECORATE_UNDERLINE:
1531                                 case SCIM_ATTR_DECORATE_REVERSE:
1532                                 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1533                                 case SCIM_ATTR_DECORATE_BGCOLOR1:
1534                                 case SCIM_ATTR_DECORATE_BGCOLOR2:
1535                                 case SCIM_ATTR_DECORATE_BGCOLOR3:
1536                                 case SCIM_ATTR_DECORATE_BGCOLOR4:
1537                                     // Record which character has attribute.
1538                                     for (int pos = start_index; pos < end_index; ++pos)
1539                                         attrs_flag [pos] = 1;
1540                                     break;
1541                                 default:
1542                                     break;
1543                             }
1544                         } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1545                             SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1546                         } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1547                             SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1548                         }
1549                     }
1550                 }
1551                 // Add underline for all characters which don't have attribute.
1552                 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1553                     if (!attrs_flag [pos]) {
1554                         int begin_pos = pos;
1555                         while (pos < mbs.length () && !attrs_flag [pos])
1556                             ++pos;
1557                         // use REVERSE style as default
1558                         attr = (Ecore_IMF_Preedit_Attr *)calloc (1, sizeof (Ecore_IMF_Preedit_Attr));
1559                         if (attr == NULL)
1560                             continue;
1561                         attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1562                         attr->start_index = begin_pos;
1563                         attr->end_index = pos;
1564                         *attrs = eina_list_append(*attrs, (void *)attr);
1565                     }
1566                 }
1567                 delete [] attrs_flag;
1568             }
1569         }
1570     } else {
1571         if (str)
1572             *str = strdup ("");
1573
1574         if (cursor_pos)
1575             *cursor_pos = 0;
1576
1577         if (attrs)
1578             *attrs = NULL;
1579     }
1580 }
1581
1582 /**
1583  * isf_imf_context_use_preedit_set
1584  * @ctx: a #Ecore_IMF_Context
1585  * @use_preedit: Whether the IM context should use the preedit string.
1586  *
1587  * This function will be called by Ecore IMF.
1588  *
1589  * Set whether the IM context should use the preedit string to display feedback.
1590  * If is 0 (default is 1), then the IM context may use some other method to
1591  * display feedback, such as displaying it in a child of the root window.
1592  */
1593 EAPI void
1594 isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
1595 {
1596     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit == EINA_TRUE ? "true" : "false") << "...\n";
1597
1598     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1599
1600     if (!_on_the_spot) return;
1601
1602     if (context_scim && context_scim->impl) {
1603         bool old = context_scim->impl->use_preedit;
1604         context_scim->impl->use_preedit = use_preedit;
1605         if (context_scim == _focused_ic) {
1606             _panel_client.prepare (context_scim->id);
1607
1608             if (old != use_preedit)
1609                 set_ic_capabilities (context_scim);
1610
1611             if (context_scim->impl->preedit_string.length ())
1612                 slot_show_preedit_string (context_scim->impl->si);
1613
1614             _panel_client.send ();
1615         }
1616     }
1617 }
1618
1619 /**
1620  * isf_imf_context_prediction_allow_set
1621  * @ctx: a #Ecore_IMF_Context
1622  * @prediction: Whether the IM context should use the prediction.
1623  *
1624  * This function will be called by Ecore IMF.
1625  *
1626  * Set whether the IM context should use the prediction.
1627  */
1628 EAPI void
1629 isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction)
1630 {
1631     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction == EINA_TRUE ? "true" : "false") << "...\n";
1632
1633     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1634
1635     if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction) {
1636         context_scim->impl->prediction_allow = prediction;
1637         set_prediction_allow (context_scim->impl->si, prediction);
1638     }
1639 }
1640
1641 /**
1642  * isf_imf_context_prediction_allow_get
1643  * @ctx: a #Ecore_IMF_Context
1644  *
1645  * This function will be called by Ecore IMF.
1646  *
1647  * To get prediction allow flag for the IM context.
1648  *
1649  * Return value: the prediction allow flag for the IM context
1650  */
1651 EAPI Eina_Bool
1652 isf_imf_context_prediction_allow_get (Ecore_IMF_Context* ctx)
1653 {
1654     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1655
1656     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1657
1658     Eina_Bool ret = EINA_FALSE;
1659     if (context_scim && context_scim->impl) {
1660         ret = context_scim->impl->prediction_allow;
1661     } else {
1662         std::cerr << __FUNCTION__ << " failed!!!\n";
1663     }
1664     return ret;
1665 }
1666
1667 /**
1668  * isf_imf_context_autocapital_type_set
1669  * @ctx: a #Ecore_IMF_Context
1670  * @autocapital_type: the autocapital type for the IM context.
1671  *
1672  * This function will be called by Ecore IMF.
1673  *
1674  * Set autocapital type for the IM context.
1675  */
1676 EAPI void
1677 isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1678 {
1679     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1680
1681     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1682
1683     if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1684         context_scim->impl->autocapital_type = autocapital_type;
1685     }
1686 }
1687
1688 /**
1689  * isf_imf_context_filter_event
1690  * @ctx: a #Ecore_IMF_Context
1691  * @type: The type of event defined by Ecore_IMF_Event_Type.
1692  * @event: The event itself.
1693  * Return value: %TRUE if the input method handled the key event.
1694  *
1695  * This function will be called by Ecore IMF.
1696  *
1697  * Allow an Ecore Input Context to internally handle an event. If this function
1698  * returns 1, then no further processing should be done for this event. Input
1699  * methods must be able to accept all types of events (simply returning 0 if
1700  * the event was not handled), but there is no obligation of any events to be
1701  * submitted to this function.
1702  */
1703 EAPI Eina_Bool
1704 isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
1705 {
1706     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1707
1708     EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1709     Eina_Bool ret = EINA_FALSE;
1710
1711     if (ic == NULL || ic->impl == NULL)
1712         return ret;
1713
1714     KeyEvent key;
1715     unsigned int timestamp;
1716
1717     if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1718         Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
1719         timestamp = ev->timestamp;
1720         scim_string_to_key (key, ev->key);
1721         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1722         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1723         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1724         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1725         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1726         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1727     } else if (type == ECORE_IMF_EVENT_KEY_UP) {
1728         Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
1729         timestamp = ev->timestamp;
1730         scim_string_to_key (key, ev->key);
1731         key.mask = SCIM_KEY_ReleaseMask;
1732         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1733         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1734         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1735         if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1736         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1737         if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1738     } else if (type == ECORE_IMF_EVENT_MOUSE_UP) {
1739         if (ecore_imf_context_input_panel_enabled_get (ctx)) {
1740             LOGD ("[Mouse-up event] ctx : %p\n", ctx);
1741             if (ic == _focused_ic)
1742                 ecore_imf_context_input_panel_show (ctx);
1743             else
1744                 LOGW ("Can't show IME because there is no focus. ctx : %p\n", ctx);
1745         }
1746         return EINA_FALSE;
1747     } else {
1748         return ret;
1749     }
1750
1751     key.mask &= _valid_key_mask;
1752
1753     _panel_client.prepare (ic->id);
1754
1755     ret = EINA_TRUE;
1756     if (!filter_hotkeys (ic, key)) {
1757         if (timestamp == 0) {
1758             ret = EINA_FALSE;
1759             // in case of generated event
1760             if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1761                 char code = key.get_ascii_code ();
1762                 if (isgraph (code)) {
1763                     char string[2] = {0};
1764                     snprintf (string, sizeof (string), "%c", code);
1765
1766                     if (strlen (string) != 0) {
1767                         ecore_imf_context_commit_event_add (ic->ctx, string);
1768                         ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)string);
1769                         caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1770                         ret = EINA_TRUE;
1771                     }
1772                 }
1773             }
1774             _panel_client.send ();
1775             return ret;
1776         }
1777
1778         if (!_focused_ic || !_focused_ic->impl->is_on ||
1779             !_focused_ic->impl->si->process_key_event (key)) {
1780             ret = EINA_FALSE;
1781         }
1782     }
1783
1784     _panel_client.send ();
1785
1786     return ret;
1787 }
1788
1789 /**
1790  * Set up an ISE specific data
1791  *
1792  * @param[in] ctx a #Ecore_IMF_Context
1793  * @param[in] data pointer of data to sets up to ISE
1794  * @param[in] length length of data
1795  */
1796 EAPI void isf_imf_context_imdata_set (Ecore_IMF_Context *ctx, const void* data, int length)
1797 {
1798     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " data length ( " << length << ") ...\n";
1799     EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1800
1801     if (context_scim == NULL || data == NULL || length <= 0)
1802         return;
1803
1804     if (context_scim && context_scim->impl) {
1805         if (context_scim->impl->imdata)
1806             free (context_scim->impl->imdata);
1807
1808         context_scim->impl->imdata = calloc (1, length);
1809         memcpy (context_scim->impl->imdata, data, length);
1810         context_scim->impl->imdata_size = length;
1811
1812         if (context_scim->impl->si && _focused_ic == context_scim) {
1813             _panel_client.prepare (context_scim->id);
1814             context_scim->impl->si->set_imdata ((const char *)data, length);
1815             _panel_client.send ();
1816         }
1817     }
1818
1819     isf_imf_context_input_panel_imdata_set (ctx, data, length);
1820 }
1821
1822 /**
1823  * Get the ISE specific data from ISE
1824  *
1825  * @param[in] ctx a #Ecore_IMF_Context
1826  * @param[out] data pointer of data to return
1827  * @param[out] length length of data
1828  */
1829 EAPI void isf_imf_context_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
1830 {
1831     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1832
1833     isf_imf_context_input_panel_imdata_get (ctx, data, length);
1834 }
1835
1836 /* Panel Slot functions */
1837 static void
1838 panel_slot_reload_config (int context)
1839 {
1840     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1841
1842     _config->reload ();
1843 }
1844
1845 static void
1846 panel_slot_exit (int /* context */)
1847 {
1848     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1849
1850     finalize ();
1851 }
1852
1853 static void
1854 panel_slot_update_candidate_item_layout (int context, const std::vector<uint32> &row_items)
1855 {
1856     EcoreIMFContextISF *ic = find_ic (context);
1857     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " row size=" << row_items.size () << " ic=" << ic << "\n";
1858     if (ic && ic->impl) {
1859         _panel_client.prepare (ic->id);
1860         ic->impl->si->update_candidate_item_layout (row_items);
1861         _panel_client.send ();
1862     }
1863 }
1864
1865 static void
1866 panel_slot_update_lookup_table_page_size (int context, int page_size)
1867 {
1868     EcoreIMFContextISF *ic = find_ic (context);
1869     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1870     if (ic && ic->impl) {
1871         _panel_client.prepare (ic->id);
1872         ic->impl->si->update_lookup_table_page_size (page_size);
1873         _panel_client.send ();
1874     }
1875 }
1876
1877 static void
1878 panel_slot_lookup_table_page_up (int context)
1879 {
1880     EcoreIMFContextISF *ic = find_ic (context);
1881     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1882     if (ic && ic->impl) {
1883         _panel_client.prepare (ic->id);
1884         ic->impl->si->lookup_table_page_up ();
1885         _panel_client.send ();
1886     }
1887 }
1888
1889 static void
1890 panel_slot_lookup_table_page_down (int context)
1891 {
1892     EcoreIMFContextISF *ic = find_ic (context);
1893     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1894     if (ic && ic->impl) {
1895         _panel_client.prepare (ic->id);
1896         ic->impl->si->lookup_table_page_down ();
1897         _panel_client.send ();
1898     }
1899 }
1900
1901 static void
1902 panel_slot_trigger_property (int context, const String &property)
1903 {
1904     EcoreIMFContextISF *ic = find_ic (context);
1905     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
1906     if (ic && ic->impl) {
1907         _panel_client.prepare (ic->id);
1908         ic->impl->si->trigger_property (property);
1909         _panel_client.send ();
1910     }
1911 }
1912
1913 static void
1914 panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1915 {
1916     EcoreIMFContextISF *ic = find_ic (context);
1917     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
1918                            << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic != NULL ? ic->impl : 0) << " ic-uuid="
1919                            << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
1920     if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
1921         _panel_client.prepare (ic->id);
1922         SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1923         ic->impl->si->process_helper_event (helper_uuid, trans);
1924         _panel_client.send ();
1925     }
1926 }
1927
1928 static void
1929 panel_slot_move_preedit_caret (int context, int caret_pos)
1930 {
1931     EcoreIMFContextISF *ic = find_ic (context);
1932     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1933     if (ic && ic->impl) {
1934         _panel_client.prepare (ic->id);
1935         ic->impl->si->move_preedit_caret (caret_pos);
1936         _panel_client.send ();
1937     }
1938 }
1939
1940 static void
1941 panel_slot_update_preedit_caret (int context, int caret)
1942 {
1943     EcoreIMFContextISF *ic = find_ic (context);
1944     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
1945
1946     if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
1947         ic->impl->preedit_caret = caret;
1948         if (ic->impl->use_preedit) {
1949             if (!ic->impl->preedit_started) {
1950                 ecore_imf_context_preedit_start_event_add (ic->ctx);
1951                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
1952                 ic->impl->preedit_started = true;
1953             }
1954             ecore_imf_context_preedit_changed_event_add (ic->ctx);
1955             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1956         } else {
1957             _panel_client.prepare (ic->id);
1958             _panel_client.update_preedit_caret (ic->id, caret);
1959             _panel_client.send ();
1960         }
1961     }
1962 }
1963
1964 static void
1965 panel_slot_select_aux (int context, int aux_index)
1966 {
1967     EcoreIMFContextISF *ic = find_ic (context);
1968     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " aux=" << aux_index << " ic=" << ic << "\n";
1969     if (ic && ic->impl) {
1970         _panel_client.prepare (ic->id);
1971         ic->impl->si->select_aux (aux_index);
1972         _panel_client.send ();
1973     }
1974 }
1975
1976 static void
1977 panel_slot_select_candidate (int context, int cand_index)
1978 {
1979     EcoreIMFContextISF *ic = find_ic (context);
1980     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
1981     if (ic && ic->impl) {
1982         _panel_client.prepare (ic->id);
1983         ic->impl->si->select_candidate (cand_index);
1984         _panel_client.send ();
1985     }
1986 }
1987
1988 static int
1989 _keyname_to_keycode (const char *keyname)
1990 {
1991     int keycode = 0;
1992     int keysym;
1993     Display *display = (Display *)ecore_x_display_get ();
1994
1995     keysym = XStringToKeysym (keyname);
1996
1997     if (!strncmp (keyname, "Keycode-", 8)) {
1998         keycode = atoi (keyname + 8);
1999     } else {
2000         keycode = XKeysymToKeycode (display, keysym);
2001     }
2002
2003     return keycode;
2004 }
2005
2006 static Eina_Bool
2007 feed_key_event (EcoreIMFContextISF *ic, const KeyEvent &key, bool fake)
2008 {
2009     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2010
2011     if (key.code <= 0x7F ||
2012         (key.code >= SCIM_KEY_BackSpace && key.code <= SCIM_KEY_Delete) ||
2013         (key.code >= SCIM_KEY_Home && key.code <= SCIM_KEY_Hyper_R)) {
2014         // ascii code and function keys
2015         send_x_key_event (key, fake);
2016         return EINA_TRUE;
2017     } else {
2018         return EINA_FALSE;
2019     }
2020 }
2021
2022 static void
2023 panel_slot_process_key_event (int context, const KeyEvent &key)
2024 {
2025     EcoreIMFContextISF *ic = find_ic (context);
2026     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2027
2028     if (feed_key_event (ic, key, false) == EINA_TRUE) return;
2029
2030     if (ic && ic->impl) {
2031         _panel_client.prepare (ic->id);
2032
2033         if (!filter_hotkeys (ic, key)) {
2034             if (!_focused_ic || !_focused_ic->impl->is_on ||
2035                 !_focused_ic->impl->si->process_key_event (key)) {
2036                 _fallback_instance->process_key_event (key);
2037             }
2038         }
2039
2040         _panel_client.send ();
2041     }
2042 }
2043
2044 static void
2045 panel_slot_commit_string (int context, const WideString &wstr)
2046 {
2047     EcoreIMFContextISF *ic = find_ic (context);
2048     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2049
2050     if (ic && ic->impl) {
2051         if (_focused_ic != ic)
2052             return;
2053
2054         if (ic->impl->need_commit_preedit)
2055             panel_slot_hide_preedit_string (ic->id);
2056         ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2057         ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2058     }
2059 }
2060
2061 static void
2062 panel_slot_forward_key_event (int context, const KeyEvent &key)
2063 {
2064     EcoreIMFContextISF *ic = find_ic (context);
2065     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2066
2067     if (strlen (key.get_key_string ().c_str ()) >= 116)
2068         return;
2069
2070     feed_key_event (ic, key, true);
2071 }
2072
2073 static void
2074 panel_slot_request_help (int context)
2075 {
2076     EcoreIMFContextISF *ic = find_ic (context);
2077     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2078     if (ic && ic->impl) {
2079         _panel_client.prepare (ic->id);
2080         panel_req_show_help (ic);
2081         _panel_client.send ();
2082     }
2083 }
2084
2085 static void
2086 panel_slot_request_factory_menu (int context)
2087 {
2088     EcoreIMFContextISF *ic = find_ic (context);
2089     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2090     if (ic && ic->impl) {
2091         _panel_client.prepare (ic->id);
2092         panel_req_show_factory_menu (ic);
2093         _panel_client.send ();
2094     }
2095 }
2096
2097 static void
2098 panel_slot_change_factory (int context, const String &uuid)
2099 {
2100     EcoreIMFContextISF *ic = find_ic (context);
2101     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
2102     if (ic && ic->impl) {
2103         _panel_client.prepare (ic->id);
2104         ic->impl->si->reset ();
2105         open_specific_factory (ic, uuid);
2106         _panel_client.send ();
2107     }
2108 }
2109
2110 static void
2111 panel_slot_reset_keyboard_ise (int context)
2112 {
2113     EcoreIMFContextISF *ic = find_ic (context);
2114     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2115     if (ic && ic->impl) {
2116         WideString wstr = ic->impl->preedit_string;
2117         if (ic->impl->need_commit_preedit) {
2118             panel_slot_hide_preedit_string (ic->id);
2119
2120             if (wstr.length ()) {
2121                 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2122                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2123             }
2124         }
2125         _panel_client.prepare (ic->id);
2126         ic->impl->si->reset ();
2127         _panel_client.send ();
2128     }
2129 }
2130
2131 static void
2132 panel_slot_update_keyboard_ise (int context)
2133 {
2134     EcoreIMFContextISF *ic = find_ic (context);
2135     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2136
2137     _backend->add_module (_config, "socket", false);
2138 }
2139
2140 static void
2141 panel_slot_show_preedit_string (int context)
2142 {
2143     EcoreIMFContextISF *ic = find_ic (context);
2144     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << "\n";
2145
2146     if (ic && ic->impl && _focused_ic == ic) {
2147         if (!ic->impl->is_on)
2148             ic->impl->is_on = true;
2149
2150         if (ic->impl->use_preedit) {
2151             if (!ic->impl->preedit_started) {
2152                 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
2153                 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2154                 ic->impl->preedit_started     = true;
2155                 ic->impl->need_commit_preedit = true;
2156             }
2157         } else {
2158             _panel_client.prepare (ic->id);
2159             _panel_client.show_preedit_string (ic->id);
2160             _panel_client.send ();
2161         }
2162     }
2163 }
2164
2165 static void
2166 panel_slot_hide_preedit_string (int context)
2167 {
2168     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2169
2170     EcoreIMFContextISF *ic = find_ic (context);
2171
2172     if (ic && ic->impl && _focused_ic == ic) {
2173         if (!ic->impl->is_on)
2174             ic->impl->is_on = true;
2175
2176         bool emit = false;
2177         if (ic->impl->preedit_string.length ()) {
2178             ic->impl->preedit_string = WideString ();
2179             ic->impl->preedit_caret  = 0;
2180             ic->impl->preedit_attrlist.clear ();
2181             emit = true;
2182         }
2183         if (ic->impl->use_preedit) {
2184             if (emit) {
2185                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2186                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2187             }
2188             if (ic->impl->preedit_started) {
2189                 ecore_imf_context_preedit_end_event_add (ic->ctx);
2190                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2191                 ic->impl->preedit_started     = false;
2192                 ic->impl->need_commit_preedit = false;
2193             }
2194         } else {
2195             _panel_client.prepare (ic->id);
2196             _panel_client.hide_preedit_string (ic->id);
2197             _panel_client.send ();
2198         }
2199     }
2200 }
2201
2202 static void
2203 panel_slot_update_preedit_string (int context,
2204                                   const WideString    &str,
2205                                   const AttributeList &attrs)
2206 {
2207     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2208
2209     EcoreIMFContextISF *ic = find_ic (context);
2210
2211     if (ic && ic->impl && _focused_ic == ic) {
2212         if (!ic->impl->is_on)
2213             ic->impl->is_on = true;
2214
2215         if (ic->impl->preedit_string != str || str.length ()) {
2216             ic->impl->preedit_string   = str;
2217             ic->impl->preedit_attrlist = attrs;
2218
2219             if (ic->impl->use_preedit) {
2220                 if (!ic->impl->preedit_started) {
2221                     ecore_imf_context_preedit_start_event_add (ic->ctx);
2222                     ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2223                     ic->impl->preedit_started = true;
2224                     ic->impl->need_commit_preedit = true;
2225                 }
2226                 ic->impl->preedit_caret    = str.length ();
2227                 ic->impl->preedit_updating = true;
2228                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2229                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2230                 ic->impl->preedit_updating = false;
2231             } else {
2232                 _panel_client.prepare (ic->id);
2233                 _panel_client.update_preedit_string (ic->id, str, attrs);
2234                 _panel_client.send ();
2235             }
2236         }
2237     }
2238 }
2239
2240 static void
2241 panel_slot_get_surrounding_text (int context, int maxlen_before, int maxlen_after)
2242 {
2243     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2244
2245     EcoreIMFContextISF *ic = find_ic (context);
2246
2247     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2248         int cursor = 0;
2249         WideString text = WideString ();
2250         slot_get_surrounding_text (ic->impl->si, text, cursor, maxlen_before, maxlen_after);
2251         _panel_client.prepare (ic->id);
2252         _panel_client.update_surrounding_text (ic->id, text, cursor);
2253         _panel_client.send ();
2254     }
2255 }
2256
2257 static void
2258 panel_slot_delete_surrounding_text (int context, int offset, int len)
2259 {
2260     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2261
2262     EcoreIMFContextISF *ic = find_ic (context);
2263
2264     if (ic && ic->impl && _focused_ic == ic && ic->impl->si)
2265         slot_delete_surrounding_text (ic->impl->si, offset, len);
2266 }
2267
2268 static void
2269 panel_slot_update_displayed_candidate_number (int context, int number)
2270 {
2271     EcoreIMFContextISF *ic = find_ic (context);
2272     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " number=" << number << " ic=" << ic << "\n";
2273     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2274         _panel_client.prepare (ic->id);
2275         ic->impl->si->update_displayed_candidate_number (number);
2276         _panel_client.send ();
2277     }
2278 }
2279
2280 static void
2281 panel_slot_candidate_more_window_show (int context)
2282 {
2283     EcoreIMFContextISF *ic = find_ic (context);
2284     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2285     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2286         _panel_client.prepare (ic->id);
2287         ic->impl->si->candidate_more_window_show ();
2288         _panel_client.send ();
2289     }
2290 }
2291
2292 static void
2293 panel_slot_candidate_more_window_hide (int context)
2294 {
2295     EcoreIMFContextISF *ic = find_ic (context);
2296     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2297     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2298         _panel_client.prepare (ic->id);
2299         ic->impl->si->candidate_more_window_hide ();
2300         _panel_client.send ();
2301     }
2302 }
2303
2304 static void
2305 panel_slot_longpress_candidate (int context, int index)
2306 {
2307     EcoreIMFContextISF *ic = find_ic (context);
2308     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " index=" << index << " ic=" << ic << "\n";
2309     if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2310         _panel_client.prepare (ic->id);
2311         ic->impl->si->longpress_candidate (index);
2312         _panel_client.send ();
2313     }
2314 }
2315
2316 static void
2317 panel_slot_update_client_id (int context, int client_id)
2318 {
2319     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " client_id=" << client_id << "\n";
2320
2321     _panel_client_id = client_id;
2322 }
2323
2324 /* Panel Requestion functions. */
2325 static void
2326 panel_req_show_help (EcoreIMFContextISF *ic)
2327 {
2328     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2329
2330     String help;
2331
2332     help =  String (_("Smart Common Input Method platform ")) +
2333             String (SCIM_VERSION) +
2334             String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2335
2336     if (ic && ic->impl) {
2337         IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2338         if (sf) {
2339             help += utf8_wcstombs (sf->get_name ());
2340             help += String (_(":\n\n"));
2341
2342             help += utf8_wcstombs (sf->get_help ());
2343             help += String (_("\n\n"));
2344
2345             help += utf8_wcstombs (sf->get_credits ());
2346         }
2347         _panel_client.show_help (ic->id, help);
2348     }
2349 }
2350
2351 static void
2352 panel_req_show_factory_menu (EcoreIMFContextISF *ic)
2353 {
2354     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2355
2356     std::vector<IMEngineFactoryPointer> factories;
2357     std::vector <PanelFactoryInfo> menu;
2358
2359     _backend->get_factories_for_encoding (factories, "UTF-8");
2360
2361     for (size_t i = 0; i < factories.size (); ++ i) {
2362         menu.push_back (PanelFactoryInfo (
2363                             factories [i]->get_uuid (),
2364                             utf8_wcstombs (factories [i]->get_name ()),
2365                             factories [i]->get_language (),
2366                             factories [i]->get_icon_file ()));
2367     }
2368
2369     if (menu.size ())
2370         _panel_client.show_factory_menu (ic->id, menu);
2371 }
2372
2373 static void
2374 panel_req_update_factory_info (EcoreIMFContextISF *ic)
2375 {
2376     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2377
2378     if (ic && ic->impl && ic == _focused_ic) {
2379         PanelFactoryInfo info;
2380         if (ic->impl->is_on) {
2381             IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2382             if (sf)
2383                 info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
2384         } else {
2385             info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
2386         }
2387         _panel_client.update_factory_info (ic->id, info);
2388     }
2389 }
2390
2391 static void
2392 panel_req_focus_in (EcoreIMFContextISF *ic)
2393 {
2394     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2395
2396     _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
2397 }
2398
2399 static void
2400 panel_req_update_spot_location (EcoreIMFContextISF *ic)
2401 {
2402     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2403
2404     _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
2405 }
2406
2407 static void
2408 panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos)
2409 {
2410     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2411
2412     _panel_client.update_cursor_position (ic->id, cursor_pos);
2413 }
2414
2415 static bool
2416 filter_hotkeys (EcoreIMFContextISF *ic, const KeyEvent &key)
2417 {
2418     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2419
2420     bool ret = false;
2421
2422     _frontend_hotkey_matcher.push_key_event (key);
2423     _imengine_hotkey_matcher.push_key_event (key);
2424
2425     FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
2426
2427     if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
2428         if (!ic->impl->is_on)
2429             turn_on_ic (ic);
2430         else
2431             turn_off_ic (ic);
2432
2433         _display_input_language (ic);
2434         ret = true;
2435     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
2436         if (!ic->impl->is_on) {
2437             turn_on_ic (ic);
2438             _display_input_language (ic);
2439         }
2440         ret = true;
2441     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
2442         if (ic->impl->is_on) {
2443             turn_off_ic (ic);
2444             _display_input_language (ic);
2445         }
2446         ret = true;
2447     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
2448         open_next_factory (ic);
2449         ret = true;
2450     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
2451         open_previous_factory (ic);
2452         ret = true;
2453     } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
2454         panel_req_show_factory_menu (ic);
2455         ret = true;
2456     } else if (_imengine_hotkey_matcher.is_matched ()) {
2457         ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
2458         ISE_TYPE type = info.type;
2459         if (type == IMENGINE_T)
2460             open_specific_factory (ic, info.uuid);
2461         else if (type == HELPER_T)
2462             _panel_client.start_helper (ic->id, info.uuid);
2463         ret = true;
2464     }
2465     return ret;
2466 }
2467
2468 static bool
2469 panel_initialize (void)
2470 {
2471     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2472
2473     String display_name;
2474     {
2475         const char *p = getenv ("DISPLAY");
2476         if (p) display_name = String (p);
2477     }
2478
2479     if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
2480         int fd = _panel_client.get_connection_number ();
2481
2482         _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
2483 //        _panel_iochannel_err_handler  = ecore_main_fd_handler_add (fd, ECORE_FD_ERROR, panel_iochannel_handler, NULL, NULL, NULL);
2484
2485         SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
2486
2487         EcoreIMFContextISF *context_scim = _ic_list;
2488         while (context_scim != NULL) {
2489             _panel_client.prepare (context_scim->id);
2490             _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
2491             _panel_client.send ();
2492             context_scim = context_scim->next;
2493         }
2494
2495         if (_focused_ic) {
2496             _panel_client.prepare (_focused_ic->id);
2497             panel_req_focus_in (_focused_ic);
2498             _panel_client.send ();
2499         }
2500
2501         return true;
2502     }
2503     std::cerr << "panel_initialize () failed!!!\n";
2504     return false;
2505 }
2506
2507 static void
2508 panel_finalize (void)
2509 {
2510     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2511
2512     _panel_client.close_connection ();
2513
2514     if (_panel_iochannel_read_handler) {
2515         ecore_main_fd_handler_del (_panel_iochannel_read_handler);
2516         _panel_iochannel_read_handler = 0;
2517     }
2518     if (_panel_iochannel_err_handler) {
2519         ecore_main_fd_handler_del (_panel_iochannel_err_handler);
2520         _panel_iochannel_err_handler = 0;
2521     }
2522 }
2523
2524 static Eina_Bool
2525 panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
2526 {
2527     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2528
2529     if (fd_handler == _panel_iochannel_read_handler) {
2530         if (_panel_client.has_pending_event () && !_panel_client.filter_event ()) {
2531             panel_finalize ();
2532             panel_initialize ();
2533             return ECORE_CALLBACK_CANCEL;
2534         }
2535     } else if (fd_handler == _panel_iochannel_err_handler) {
2536         panel_finalize ();
2537         panel_initialize ();
2538         return ECORE_CALLBACK_CANCEL;
2539     }
2540     return ECORE_CALLBACK_RENEW;
2541 }
2542
2543 static void
2544 turn_on_ic (EcoreIMFContextISF *ic)
2545 {
2546     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2547
2548     if (ic && ic->impl && !ic->impl->is_on) {
2549         ic->impl->is_on = true;
2550
2551         if (ic == _focused_ic) {
2552             panel_req_focus_in (ic);
2553 //            panel_req_update_spot_location (ic);
2554             panel_req_update_factory_info (ic);
2555             _panel_client.turn_on (ic->id);
2556 //            _panel_client.hide_preedit_string (ic->id);
2557 //            _panel_client.hide_aux_string (ic->id);
2558 //            _panel_client.hide_lookup_table (ic->id);
2559             ic->impl->si->focus_in ();
2560             ic->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ic->ctx));
2561             set_prediction_allow (ic->impl->si, ic->impl->prediction_allow);
2562         }
2563
2564         //Record the IC on/off status
2565         if (_shared_input_method) {
2566             _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
2567             _config->flush ();
2568         }
2569
2570         if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2571             ecore_imf_context_preedit_start_event_add (ic->ctx);
2572             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2573             ecore_imf_context_preedit_changed_event_add (ic->ctx);
2574             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2575             ic->impl->preedit_started = true;
2576         }
2577     }
2578 }
2579
2580 static void
2581 turn_off_ic (EcoreIMFContextISF *ic)
2582 {
2583     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2584
2585     if (ic && ic->impl && ic->impl->is_on) {
2586         ic->impl->is_on = false;
2587
2588         if (ic == _focused_ic) {
2589             ic->impl->si->focus_out ();
2590
2591 //            panel_req_update_factory_info (ic);
2592             _panel_client.turn_off (ic->id);
2593         }
2594
2595         //Record the IC on/off status
2596         if (_shared_input_method) {
2597             _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2598             _config->flush ();
2599         }
2600
2601         if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2602             ecore_imf_context_preedit_changed_event_add (ic->ctx);
2603             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2604             ecore_imf_context_preedit_end_event_add (ic->ctx);
2605             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2606             ic->impl->preedit_started = false;
2607         }
2608     }
2609 }
2610
2611 static void
2612 set_ic_capabilities (EcoreIMFContextISF *ic)
2613 {
2614     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2615
2616     if (ic && ic->impl) {
2617         unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2618
2619         if (!_on_the_spot || !ic->impl->use_preedit)
2620             cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2621
2622         ic->impl->si->update_client_capabilities (cap);
2623     }
2624 }
2625
2626 static bool
2627 check_socket_frontend (void)
2628 {
2629     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2630
2631     SocketAddress address;
2632     SocketClient client;
2633
2634     uint32 magic;
2635
2636     address.set_address (scim_get_default_socket_frontend_address ());
2637
2638     if (!client.connect (address))
2639         return false;
2640
2641     if (!scim_socket_open_connection (magic,
2642                                       String ("ConnectionTester"),
2643                                       String ("SocketFrontEnd"),
2644                                       client,
2645                                       1000)) {
2646         return false;
2647     }
2648
2649     return true;
2650 }
2651
2652 void
2653 initialize (void)
2654 {
2655     std::vector<String>     config_list;
2656     std::vector<String>     engine_list;
2657     std::vector<String>     helper_list;
2658     std::vector<String>     load_engine_list;
2659
2660     std::vector<String>::iterator it;
2661
2662     bool                    manual = false;
2663     bool                    socket = true;
2664     String                  config_module_name = "simple";
2665
2666     SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore ISF IMModule...\n";
2667
2668     // Get system language.
2669     _language = scim_get_locale_language (scim_get_current_locale ());
2670
2671     if (socket) {
2672         // If no Socket FrontEnd is running, then launch one.
2673         // And set manual to false.
2674         bool check_result = check_socket_frontend ();
2675         if (!check_result) {
2676             std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
2677             //get modules list
2678             scim_get_imengine_module_list (engine_list);
2679             scim_get_helper_module_list (helper_list);
2680
2681             for (it = engine_list.begin (); it != engine_list.end (); it++) {
2682                 if (*it != "socket")
2683                     load_engine_list.push_back (*it);
2684             }
2685             for (it = helper_list.begin (); it != helper_list.end (); it++)
2686                 load_engine_list.push_back (*it);
2687             const char *new_argv [] = { "--no-stay", 0 };
2688             scim_launch (true,
2689                          config_module_name,
2690                          (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
2691                          "socket",
2692                          (char **)new_argv);
2693             manual = false;
2694         }
2695
2696         // If there is one Socket FrontEnd running and it's not manual mode,
2697         // then just use this Socket Frontend.
2698         if (!manual) {
2699             for (int i = 0; i < 200; ++i) {
2700                 if (check_result) {
2701                     config_module_name = "socket";
2702                     load_engine_list.clear ();
2703                     load_engine_list.push_back ("socket");
2704                     break;
2705                 }
2706                 scim_usleep (50000);
2707                 check_result = check_socket_frontend ();
2708             }
2709         }
2710     }
2711
2712     if (config_module_name != "dummy") {
2713         //load config module
2714         SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
2715         _config_module = new ConfigModule (config_module_name);
2716
2717         //create config instance
2718         if (_config_module != NULL && _config_module->valid ())
2719             _config = _config_module->create_config ();
2720     }
2721
2722     if (_config.null ()) {
2723         SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
2724
2725         if (_config_module) delete _config_module;
2726         _config_module = NULL;
2727
2728         _config = new DummyConfig ();
2729         config_module_name = "dummy";
2730     }
2731
2732     reload_config_callback (_config);
2733     _config->signal_connect_reload (slot (reload_config_callback));
2734
2735     // create backend
2736     _backend = new CommonBackEnd (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list);
2737
2738     if (_backend.null ()) {
2739         std::cerr << "Cannot create BackEnd Object!\n";
2740     } else {
2741         _backend->initialize (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list, false, false);
2742         _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
2743     }
2744
2745     if (_fallback_factory.null ())
2746         _fallback_factory = new DummyIMEngineFactory ();
2747
2748     _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
2749     _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
2750
2751     // Attach Panel Client signal.
2752     _panel_client.signal_connect_reload_config                 (slot (panel_slot_reload_config));
2753     _panel_client.signal_connect_exit                          (slot (panel_slot_exit));
2754     _panel_client.signal_connect_update_candidate_item_layout  (slot (panel_slot_update_candidate_item_layout));
2755     _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
2756     _panel_client.signal_connect_lookup_table_page_up          (slot (panel_slot_lookup_table_page_up));
2757     _panel_client.signal_connect_lookup_table_page_down        (slot (panel_slot_lookup_table_page_down));
2758     _panel_client.signal_connect_trigger_property              (slot (panel_slot_trigger_property));
2759     _panel_client.signal_connect_process_helper_event          (slot (panel_slot_process_helper_event));
2760     _panel_client.signal_connect_move_preedit_caret            (slot (panel_slot_move_preedit_caret));
2761     _panel_client.signal_connect_update_preedit_caret          (slot (panel_slot_update_preedit_caret));
2762     _panel_client.signal_connect_select_aux                    (slot (panel_slot_select_aux));
2763     _panel_client.signal_connect_select_candidate              (slot (panel_slot_select_candidate));
2764     _panel_client.signal_connect_process_key_event             (slot (panel_slot_process_key_event));
2765     _panel_client.signal_connect_commit_string                 (slot (panel_slot_commit_string));
2766     _panel_client.signal_connect_forward_key_event             (slot (panel_slot_forward_key_event));
2767     _panel_client.signal_connect_request_help                  (slot (panel_slot_request_help));
2768     _panel_client.signal_connect_request_factory_menu          (slot (panel_slot_request_factory_menu));
2769     _panel_client.signal_connect_change_factory                (slot (panel_slot_change_factory));
2770     _panel_client.signal_connect_reset_keyboard_ise            (slot (panel_slot_reset_keyboard_ise));
2771     _panel_client.signal_connect_update_keyboard_ise           (slot (panel_slot_update_keyboard_ise));
2772     _panel_client.signal_connect_show_preedit_string           (slot (panel_slot_show_preedit_string));
2773     _panel_client.signal_connect_hide_preedit_string           (slot (panel_slot_hide_preedit_string));
2774     _panel_client.signal_connect_update_preedit_string         (slot (panel_slot_update_preedit_string));
2775     _panel_client.signal_connect_get_surrounding_text          (slot (panel_slot_get_surrounding_text));
2776     _panel_client.signal_connect_delete_surrounding_text       (slot (panel_slot_delete_surrounding_text));
2777     _panel_client.signal_connect_update_displayed_candidate_number (slot (panel_slot_update_displayed_candidate_number));
2778     _panel_client.signal_connect_candidate_more_window_show    (slot (panel_slot_candidate_more_window_show));
2779     _panel_client.signal_connect_candidate_more_window_hide    (slot (panel_slot_candidate_more_window_hide));
2780     _panel_client.signal_connect_longpress_candidate           (slot (panel_slot_longpress_candidate));
2781     _panel_client.signal_connect_update_client_id              (slot (panel_slot_update_client_id));
2782
2783     if (!panel_initialize ()) {
2784         std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
2785     }
2786 }
2787
2788 static void
2789 finalize (void)
2790 {
2791     SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
2792
2793     // Reset this first so that the shared instance could be released correctly afterwards.
2794     _default_instance.reset ();
2795
2796     SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2797     while (_used_ic_impl_list) {
2798         // In case in "shared input method" mode,
2799         // all contexts share only one instance,
2800         // so we need point the reference pointer correctly before finalizing.
2801         _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2802         isf_imf_context_del (_used_ic_impl_list->parent->ctx);
2803     }
2804
2805     delete_all_ic_impl ();
2806
2807     _fallback_instance.reset ();
2808     _fallback_factory.reset ();
2809
2810     SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2811     _backend.reset ();
2812
2813     SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2814     _config.reset ();
2815
2816     if (_config_module) {
2817         SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2818         delete _config_module;
2819         _config_module = 0;
2820     }
2821
2822     _focused_ic = NULL;
2823     _ic_list = NULL;
2824
2825     _scim_initialized = false;
2826
2827     _panel_client.reset_signal_handler ();
2828     panel_finalize ();
2829 }
2830
2831 static void
2832 _popup_message (const char *_ptext)
2833 {
2834     if (_ptext == NULL)
2835         return;
2836
2837     notification_status_message_post(_ptext);
2838 }
2839
2840 static void
2841 _display_input_language (EcoreIMFContextISF *ic)
2842 {
2843     IMEngineFactoryPointer sf;
2844
2845     if (ic && ic->impl) {
2846         if (ic->impl->is_on) {
2847             sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2848             _popup_message (scim_get_language_name (sf->get_language ()).c_str ());
2849         }
2850         else {
2851             _popup_message (scim_get_language_name ("en").c_str());
2852         }
2853     }
2854 }
2855
2856 static void
2857 open_next_factory (EcoreIMFContextISF *ic)
2858 {
2859     SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2860     IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2861
2862     if (!sf.null ()) {
2863         turn_off_ic (ic);
2864         ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2865         ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2866         ic->impl->preedit_string = WideString ();
2867         ic->impl->preedit_caret = 0;
2868         attach_instance (ic->impl->si);
2869         _backend->set_default_factory (_language, sf->get_uuid ());
2870         _panel_client.register_input_context (ic->id, sf->get_uuid ());
2871         _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2872         set_ic_capabilities (ic);
2873         turn_on_ic (ic);
2874
2875         if (_shared_input_method) {
2876             _default_instance = ic->impl->si;
2877             ic->impl->shared_si = true;
2878         }
2879         _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2880     }
2881 }
2882
2883 static void
2884 open_previous_factory (EcoreIMFContextISF *ic)
2885 {
2886     if (ic == NULL)
2887         return;
2888
2889     SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2890     IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2891
2892     if (!sf.null ()) {
2893         turn_off_ic (ic);
2894         ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2895         ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2896         ic->impl->preedit_string = WideString ();
2897         ic->impl->preedit_caret = 0;
2898         attach_instance (ic->impl->si);
2899         _backend->set_default_factory (_language, sf->get_uuid ());
2900         _panel_client.register_input_context (ic->id, sf->get_uuid ());
2901         _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2902         set_ic_capabilities (ic);
2903         turn_on_ic (ic);
2904
2905         if (_shared_input_method) {
2906             _default_instance = ic->impl->si;
2907             ic->impl->shared_si = true;
2908         }
2909         _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2910     }
2911 }
2912
2913 static void
2914 open_specific_factory (EcoreIMFContextISF *ic,
2915                        const String     &uuid)
2916 {
2917     if (ic == NULL)
2918         return;
2919
2920     SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2921
2922     // The same input method is selected, just turn on the IC.
2923     if (ic->impl->si->get_factory_uuid () == uuid) {
2924         turn_on_ic (ic);
2925         return;
2926     }
2927
2928     IMEngineFactoryPointer sf = _backend->get_factory (uuid);
2929
2930     if (uuid.length () && !sf.null ()) {
2931         turn_off_ic (ic);
2932         ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2933         ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2934         ic->impl->preedit_string = WideString ();
2935         ic->impl->preedit_caret = 0;
2936         attach_instance (ic->impl->si);
2937         _backend->set_default_factory (_language, sf->get_uuid ());
2938         _panel_client.register_input_context (ic->id, sf->get_uuid ());
2939         set_ic_capabilities (ic);
2940         turn_on_ic (ic);
2941
2942         if (_shared_input_method) {
2943             _default_instance = ic->impl->si;
2944             ic->impl->shared_si = true;
2945         }
2946     } else {
2947         std::cerr << "open_specific_factory () is failed!!!!!!\n";
2948         LOGE ("open_specific_factory () is failed. ic : %x uuid : %s", ic->id, uuid.c_str());
2949
2950         // turn_off_ic comment out panel_req_update_factory_info ()
2951         //turn_off_ic (ic);
2952         if (ic && ic->impl->is_on) {
2953             ic->impl->is_on = false;
2954
2955             if (ic == _focused_ic) {
2956                 ic->impl->si->focus_out ();
2957
2958                 panel_req_update_factory_info (ic);
2959                 _panel_client.turn_off (ic->id);
2960             }
2961
2962             //Record the IC on/off status
2963             if (_shared_input_method) {
2964                 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2965                 _config->flush ();
2966             }
2967
2968             if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2969                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2970                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2971                 ecore_imf_context_preedit_end_event_add (ic->ctx);
2972                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2973                 ic->impl->preedit_started = false;
2974             }
2975         }
2976     }
2977 }
2978
2979 static void initialize_modifier_bits (Display *display)
2980 {
2981     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2982
2983     if (__current_display == display)
2984         return;
2985
2986     __current_display = display;
2987
2988     if (display == 0) {
2989         __current_alt_mask     = Mod1Mask;
2990         __current_meta_mask    = ShiftMask | Mod1Mask;
2991         __current_super_mask   = 0;
2992         __current_hyper_mask   = 0;
2993         __current_numlock_mask = Mod2Mask;
2994         return;
2995     }
2996
2997     XModifierKeymap *mods = NULL;
2998
2999     ::KeyCode ctrl_l  = XKeysymToKeycode (display, XK_Control_L);
3000     ::KeyCode ctrl_r  = XKeysymToKeycode (display, XK_Control_R);
3001     ::KeyCode meta_l  = XKeysymToKeycode (display, XK_Meta_L);
3002     ::KeyCode meta_r  = XKeysymToKeycode (display, XK_Meta_R);
3003     ::KeyCode alt_l   = XKeysymToKeycode (display, XK_Alt_L);
3004     ::KeyCode alt_r   = XKeysymToKeycode (display, XK_Alt_R);
3005     ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
3006     ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
3007     ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
3008     ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
3009     ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
3010
3011     int i, j;
3012
3013     mods = XGetModifierMapping (display);
3014     if (mods == NULL)
3015         return;
3016
3017     __current_alt_mask     = 0;
3018     __current_meta_mask    = 0;
3019     __current_super_mask   = 0;
3020     __current_hyper_mask   = 0;
3021     __current_numlock_mask = 0;
3022
3023     /* We skip the first three sets for Shift, Lock, and Control.  The
3024         remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5.  */
3025     for (i = 3; i < 8; i++) {
3026         for (j = 0; j < mods->max_keypermod; j++) {
3027             ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
3028             if (! code) continue;
3029             if (code == alt_l || code == alt_r)
3030                 __current_alt_mask |= (1 << i);
3031             else if (code == meta_l || code == meta_r)
3032                 __current_meta_mask |= (1 << i);
3033             else if (code == super_l || code == super_r)
3034                 __current_super_mask |= (1 << i);
3035             else if (code == hyper_l || code == hyper_r)
3036                 __current_hyper_mask |= (1 << i);
3037             else if (code == numlock)
3038                 __current_numlock_mask |= (1 << i);
3039         }
3040     }
3041
3042     /* Check whether there is a combine keys mapped to Meta */
3043     if (__current_meta_mask == 0) {
3044         char buf [32];
3045         XKeyEvent xkey;
3046         KeySym keysym_l, keysym_r;
3047
3048         xkey.type = KeyPress;
3049         xkey.display = display;
3050         xkey.serial = 0L;
3051         xkey.send_event = False;
3052         xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
3053         xkey.time = 0;
3054         xkey.same_screen = False;
3055         xkey.subwindow = None;
3056         xkey.window = None;
3057         xkey.root = DefaultRootWindow (display);
3058         xkey.state = ShiftMask;
3059
3060         xkey.keycode = meta_l;
3061         XLookupString (&xkey, buf, 32, &keysym_l, 0);
3062         xkey.keycode = meta_r;
3063         XLookupString (&xkey, buf, 32, &keysym_r, 0);
3064
3065         if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
3066             __current_meta_mask = ShiftMask + __current_alt_mask;
3067         else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
3068             __current_meta_mask = ShiftMask + ControlMask;
3069     }
3070
3071     XFreeModifiermap (mods);
3072 }
3073
3074 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
3075 {
3076     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3077
3078     unsigned int state = 0;
3079
3080     initialize_modifier_bits (display);
3081
3082     if (scimkeymask & SCIM_KEY_ShiftMask)    state |= ShiftMask;
3083     if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
3084     if (scimkeymask & SCIM_KEY_ControlMask)  state |= ControlMask;
3085     if (scimkeymask & SCIM_KEY_AltMask)      state |= __current_alt_mask;
3086     if (scimkeymask & SCIM_KEY_MetaMask)     state |= __current_meta_mask;
3087     if (scimkeymask & SCIM_KEY_SuperMask)    state |= __current_super_mask;
3088     if (scimkeymask & SCIM_KEY_HyperMask)    state |= __current_hyper_mask;
3089     if (scimkeymask & SCIM_KEY_NumLockMask)  state |= __current_numlock_mask;
3090
3091     return state;
3092 }
3093
3094 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake)
3095 {
3096     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3097
3098     XKeyEvent event;
3099     Window focus_win;
3100     Display *display = (Display *)ecore_x_display_get ();
3101     int revert = RevertToParent;
3102
3103     XGetInputFocus (display, &focus_win, &revert);
3104
3105     event.display     = display;
3106     event.window      = focus_win;
3107     event.root        = DefaultRootWindow (display);
3108     event.subwindow   = None;
3109     if (fake)
3110         event.time    = 0;
3111     else
3112         event.time    = get_time ();
3113
3114     event.x           = 1;
3115     event.y           = 1;
3116     event.x_root      = 1;
3117     event.y_root      = 1;
3118     event.same_screen = True;
3119     event.state       = modifiers;
3120     event.keycode     = keycode;
3121     if (press)
3122         event.type = KeyPress;
3123     else
3124         event.type = KeyRelease;
3125     event.send_event  = False;
3126     event.serial      = 0;
3127
3128     return event;
3129 }
3130
3131 static void send_x_key_event (const KeyEvent &key, bool fake)
3132 {
3133     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3134
3135     ::KeyCode keycode = 0;
3136     ::KeySym keysym = 0;
3137     int shift = 0;
3138     char key_string[256] = {0};
3139     char keysym_str[256] = {0};
3140
3141     // Obtain the X11 display.
3142     Display *display = (Display *)ecore_x_display_get ();
3143     if (display == NULL) {
3144         std::cerr << "ecore_x_display_get () failed\n";
3145         return;
3146     }
3147
3148     if (strncmp (key.get_key_string ().c_str (), "KeyRelease+", 11) == 0) {
3149         snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str () + 11);
3150     } else {
3151         snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str ());
3152     }
3153
3154     if (strncmp (key_string, "Shift+", 6) == 0) {
3155         snprintf (keysym_str, sizeof (keysym_str), "%s", key_string + 6);
3156     } else {
3157         snprintf (keysym_str, sizeof (keysym_str), "%s", key_string);
3158     }
3159
3160     // get x keysym, keycode, keyname, and key
3161     keysym = XStringToKeysym (keysym_str);
3162     if (keysym == NoSymbol)
3163         return;
3164
3165     keycode = _keyname_to_keycode (keysym_str);
3166     if (XkbKeycodeToKeysym (display, keycode, 0, 0) != keysym) {
3167         if (XkbKeycodeToKeysym (display, keycode, 0, 1) == keysym)
3168             shift = 1;
3169         else
3170             keycode = 0;
3171     } else {
3172         shift = 0;
3173     }
3174
3175     if (keycode == 0) {
3176         static int mod = 0;
3177         KeySym *keysyms;
3178         int keycode_min, keycode_max, keycode_num;
3179         int i;
3180
3181         XDisplayKeycodes (display, &keycode_min, &keycode_max);
3182         keysyms = XGetKeyboardMapping (display, keycode_min,
3183                 keycode_max - keycode_min + 1,
3184                 &keycode_num);
3185         mod = (mod + 1) & 0x7;
3186         i = (keycode_max - keycode_min - mod - 1) * keycode_num;
3187
3188         keysyms[i] = keysym;
3189         XChangeKeyboardMapping (display, keycode_min, keycode_num,
3190                 keysyms, (keycode_max - keycode_min));
3191         XFree (keysyms);
3192         XSync (display, False);
3193         keycode = keycode_max - mod - 1;
3194     }
3195
3196     unsigned int modifier = scim_x11_keymask_scim_to_x11 (display, key.mask);
3197
3198     if (shift)
3199         modifier |= ShiftMask;
3200
3201     XKeyEvent event;
3202     if (key.is_key_press ()) {
3203         if (shift) {
3204             event = createKeyEvent (true, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3205             XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3206         }
3207
3208         event = createKeyEvent (true, keycode, modifier, fake);
3209         XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3210     } else {
3211         event = createKeyEvent (false, keycode, modifier, fake);
3212         XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3213
3214         if (shift) {
3215             event = createKeyEvent (false, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3216             XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3217         }
3218     }
3219 }
3220
3221 static void
3222 attach_instance (const IMEngineInstancePointer &si)
3223 {
3224     si->signal_connect_show_preedit_string (
3225         slot (slot_show_preedit_string));
3226     si->signal_connect_show_aux_string (
3227         slot (slot_show_aux_string));
3228     si->signal_connect_show_lookup_table (
3229         slot (slot_show_lookup_table));
3230
3231     si->signal_connect_hide_preedit_string (
3232         slot (slot_hide_preedit_string));
3233     si->signal_connect_hide_aux_string (
3234         slot (slot_hide_aux_string));
3235     si->signal_connect_hide_lookup_table (
3236         slot (slot_hide_lookup_table));
3237
3238     si->signal_connect_update_preedit_caret (
3239         slot (slot_update_preedit_caret));
3240     si->signal_connect_update_preedit_string (
3241         slot (slot_update_preedit_string));
3242     si->signal_connect_update_aux_string (
3243         slot (slot_update_aux_string));
3244     si->signal_connect_update_lookup_table (
3245         slot (slot_update_lookup_table));
3246
3247     si->signal_connect_commit_string (
3248         slot (slot_commit_string));
3249
3250     si->signal_connect_forward_key_event (
3251         slot (slot_forward_key_event));
3252
3253     si->signal_connect_register_properties (
3254         slot (slot_register_properties));
3255
3256     si->signal_connect_update_property (
3257         slot (slot_update_property));
3258
3259     si->signal_connect_beep (
3260         slot (slot_beep));
3261
3262     si->signal_connect_start_helper (
3263         slot (slot_start_helper));
3264
3265     si->signal_connect_stop_helper (
3266         slot (slot_stop_helper));
3267
3268     si->signal_connect_send_helper_event (
3269         slot (slot_send_helper_event));
3270
3271     si->signal_connect_get_surrounding_text (
3272         slot (slot_get_surrounding_text));
3273
3274     si->signal_connect_delete_surrounding_text (
3275         slot (slot_delete_surrounding_text));
3276
3277     si->signal_connect_expand_candidate (
3278         slot (slot_expand_candidate));
3279     si->signal_connect_contract_candidate (
3280         slot (slot_contract_candidate));
3281
3282     si->signal_connect_set_candidate_style (
3283         slot (slot_set_candidate_style));
3284 }
3285
3286 // Implementation of slot functions
3287 static void
3288 slot_show_preedit_string (IMEngineInstanceBase *si)
3289 {
3290     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3291
3292     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3293
3294     if (ic && ic->impl && _focused_ic == ic) {
3295         if (ic->impl->use_preedit) {
3296             if (!ic->impl->preedit_started) {
3297                 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3298                 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3299                 ic->impl->preedit_started = true;
3300             }
3301             //if (ic->impl->preedit_string.length ())
3302             //    ecore_imf_context_preedit_changed_event_add (_focused_ic->ctx);
3303         } else {
3304             _panel_client.show_preedit_string (ic->id);
3305         }
3306     }
3307 }
3308
3309 static void
3310 slot_show_aux_string (IMEngineInstanceBase *si)
3311 {
3312     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3313
3314     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3315
3316     if (ic && ic->impl && _focused_ic == ic)
3317         _panel_client.show_aux_string (ic->id);
3318 }
3319
3320 static void
3321 slot_show_lookup_table (IMEngineInstanceBase *si)
3322 {
3323     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3324
3325     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3326
3327     if (ic && ic->impl && _focused_ic == ic)
3328         _panel_client.show_lookup_table (ic->id);
3329 }
3330
3331 static void
3332 slot_hide_preedit_string (IMEngineInstanceBase *si)
3333 {
3334     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3335
3336     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3337
3338     if (ic && ic->impl && _focused_ic == ic) {
3339         bool emit = false;
3340         if (ic->impl->preedit_string.length ()) {
3341             ic->impl->preedit_string = WideString ();
3342             ic->impl->preedit_caret = 0;
3343             ic->impl->preedit_attrlist.clear ();
3344             emit = true;
3345         }
3346         if (ic->impl->use_preedit) {
3347             if (emit) {
3348                 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3349                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3350             }
3351             if (ic->impl->preedit_started) {
3352                 ecore_imf_context_preedit_end_event_add (ic->ctx);
3353                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
3354                 ic->impl->preedit_started = false;
3355             }
3356         } else {
3357             _panel_client.hide_preedit_string (ic->id);
3358         }
3359     }
3360 }
3361
3362 static void
3363 slot_hide_aux_string (IMEngineInstanceBase *si)
3364 {
3365     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3366
3367     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3368
3369     if (ic && ic->impl && _focused_ic == ic)
3370         _panel_client.hide_aux_string (ic->id);
3371 }
3372
3373 static void
3374 slot_hide_lookup_table (IMEngineInstanceBase *si)
3375 {
3376     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3377
3378     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3379
3380     if (ic && ic->impl && _focused_ic == ic)
3381         _panel_client.hide_lookup_table (ic->id);
3382 }
3383
3384 static void
3385 slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
3386 {
3387     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3388
3389     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3390
3391     if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
3392         ic->impl->preedit_caret = caret;
3393         if (ic->impl->use_preedit) {
3394             if (!ic->impl->preedit_started) {
3395                 ecore_imf_context_preedit_start_event_add (ic->ctx);
3396                 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3397                 ic->impl->preedit_started = true;
3398             }
3399             ecore_imf_context_preedit_changed_event_add (ic->ctx);
3400             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3401         } else {
3402             _panel_client.update_preedit_caret (ic->id, caret);
3403         }
3404     }
3405 }
3406
3407 static void
3408 slot_update_preedit_string (IMEngineInstanceBase *si,
3409                             const WideString & str,
3410                             const AttributeList & attrs)
3411 {
3412     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3413
3414     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3415
3416     if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
3417         ic->impl->preedit_string   = str;
3418         ic->impl->preedit_attrlist = attrs;
3419         if (ic->impl->use_preedit) {
3420             if (!ic->impl->preedit_started) {
3421                 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3422                 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3423                 ic->impl->preedit_started = true;
3424             }
3425             ic->impl->preedit_caret    = str.length ();
3426             ic->impl->preedit_updating = true;
3427             ecore_imf_context_preedit_changed_event_add (ic->ctx);
3428             ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3429             ic->impl->preedit_updating = false;
3430         } else {
3431             _panel_client.update_preedit_string (ic->id, str, attrs);
3432         }
3433     }
3434 }
3435
3436 static void
3437 slot_update_aux_string (IMEngineInstanceBase *si,
3438                         const WideString & str,
3439                         const AttributeList & attrs)
3440 {
3441     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3442
3443     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3444
3445     if (ic && ic->impl && _focused_ic == ic)
3446         _panel_client.update_aux_string (ic->id, str, attrs);
3447 }
3448
3449 static void
3450 slot_commit_string (IMEngineInstanceBase *si,
3451                     const WideString & str)
3452 {
3453     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3454
3455     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3456
3457     if (ic && ic->ctx) {
3458         if (strcmp (utf8_wcstombs (str).c_str (), " ") == 0)
3459             autoperiod_insert (ic->ctx);
3460
3461         ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ());
3462         ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3463     }
3464 }
3465
3466 static void
3467 slot_forward_key_event (IMEngineInstanceBase *si,
3468                         const KeyEvent & key)
3469 {
3470     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3471
3472     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3473
3474     if (ic && _focused_ic == ic) {
3475         if (!_fallback_instance->process_key_event (key)) {
3476             feed_key_event (ic, key, true);
3477         }
3478     }
3479 }
3480
3481 static void
3482 slot_update_lookup_table (IMEngineInstanceBase *si,
3483                           const LookupTable & table)
3484 {
3485     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3486
3487     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3488
3489     if (ic && ic->impl && _focused_ic == ic)
3490         _panel_client.update_lookup_table (ic->id, table);
3491 }
3492
3493 static void
3494 slot_register_properties (IMEngineInstanceBase *si,
3495                           const PropertyList & properties)
3496 {
3497     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3498
3499     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3500
3501     if (ic && ic->impl && _focused_ic == ic)
3502         _panel_client.register_properties (ic->id, properties);
3503 }
3504
3505 static void
3506 slot_update_property (IMEngineInstanceBase *si,
3507                       const Property & property)
3508 {
3509     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3510
3511     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3512
3513     if (ic && ic->impl && _focused_ic == ic)
3514         _panel_client.update_property (ic->id, property);
3515 }
3516
3517 static void
3518 slot_beep (IMEngineInstanceBase *si)
3519 {
3520     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3521
3522     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3523
3524     if (ic && ic->impl && _focused_ic == ic)
3525         ecore_x_bell (0);
3526 }
3527
3528 static void
3529 slot_start_helper (IMEngineInstanceBase *si,
3530                    const String &helper_uuid)
3531 {
3532     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3533
3534     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3535                            << (ic != NULL ? ic->id : -1) << " ic=" << ic
3536                            << " ic-uuid=" << ((ic != NULL ) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3537
3538     if (ic && ic->impl)
3539         _panel_client.start_helper (ic->id, helper_uuid);
3540 }
3541
3542 static void
3543 slot_stop_helper (IMEngineInstanceBase *si,
3544                   const String &helper_uuid)
3545 {
3546     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3547
3548     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic != NULL ? ic->id : -1) << " ic=" << ic << "...\n";
3549
3550     if (ic && ic->impl)
3551         _panel_client.stop_helper (ic->id, helper_uuid);
3552 }
3553
3554 static void
3555 slot_send_helper_event (IMEngineInstanceBase *si,
3556                         const String      &helper_uuid,
3557                         const Transaction &trans)
3558 {
3559     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3560
3561     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3562                            << (ic != NULL ? ic->id : -1) << " ic=" << ic
3563                            << " ic-uuid=" << ((ic != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3564
3565     if (ic && ic->impl)
3566         _panel_client.send_helper_event (ic->id, helper_uuid, trans);
3567 }
3568
3569 static bool
3570 slot_get_surrounding_text (IMEngineInstanceBase *si,
3571                            WideString            &text,
3572                            int                   &cursor,
3573                            int                    maxlen_before,
3574                            int                    maxlen_after)
3575 {
3576     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3577
3578     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3579
3580     if (ic && ic->impl && _focused_ic == ic) {
3581         char *surrounding = NULL;
3582         int   cursor_index;
3583         if (ecore_imf_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index)) {
3584             SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
3585             SCIM_DEBUG_FRONTEND(2) << "Cursor Index    : " << cursor_index <<"\n";
3586             WideString before = utf8_mbstowcs (String (surrounding));
3587             if (cursor_index > (int)before.length())
3588                 return false;
3589             WideString after = before;
3590             before = before.substr (0, cursor_index);
3591             after =  after.substr (cursor_index, after.length () - cursor_index);
3592             if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
3593                 before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
3594             else if (maxlen_before == 0)
3595                 before = WideString ();
3596             if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
3597                 after = WideString (after.begin (), after.begin () + maxlen_after);
3598             else if (maxlen_after == 0)
3599                 after = WideString ();
3600             text = before + after;
3601             cursor = before.length ();
3602             return true;
3603         }
3604     }
3605     return false;
3606 }
3607
3608 static bool
3609 slot_delete_surrounding_text (IMEngineInstanceBase *si,
3610                               int                   offset,
3611                               int                   len)
3612 {
3613     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3614
3615     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3616
3617     if (ic && ic->impl && _focused_ic == ic) {
3618         Ecore_IMF_Event_Delete_Surrounding ev;
3619         ev.ctx = _focused_ic->ctx;
3620         ev.n_chars = len;
3621         ev.offset = offset;
3622         ecore_imf_context_delete_surrounding_event_add (_focused_ic->ctx, offset, len);
3623         ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
3624         return true;
3625     }
3626     return false;
3627 }
3628
3629 static void
3630 slot_expand_candidate (IMEngineInstanceBase *si)
3631 {
3632     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3633
3634     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3635
3636     if (ic && ic->impl && _focused_ic == ic)
3637         _panel_client.expand_candidate (ic->id);
3638 }
3639
3640 static void
3641 slot_contract_candidate (IMEngineInstanceBase *si)
3642 {
3643     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3644
3645     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3646
3647     if (ic && ic->impl && _focused_ic == ic)
3648         _panel_client.contract_candidate (ic->id);
3649 }
3650
3651 static void
3652 slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode)
3653 {
3654     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3655
3656     EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3657
3658     if (ic && ic->impl && _focused_ic == ic)
3659         _panel_client.set_candidate_style (ic->id, portrait_line, mode);
3660 }
3661
3662 static void
3663 reload_config_callback (const ConfigPointer &config)
3664 {
3665     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3666
3667     _frontend_hotkey_matcher.load_hotkeys (config);
3668     _imengine_hotkey_matcher.load_hotkeys (config);
3669
3670     KeyEvent key;
3671     scim_string_to_key (key,
3672                         config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
3673                                       String ("Shift+Control+Alt+Lock")));
3674
3675     _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
3676     _valid_key_mask |= SCIM_KEY_ReleaseMask;
3677     // Special treatment for two backslash keys on jp106 keyboard.
3678     _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
3679
3680     _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
3681     _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
3682
3683     // Get keyboard layout setting
3684     // Flush the global config first, in order to load the new configs from disk.
3685     scim_global_config_flush ();
3686
3687     _keyboard_layout = scim_get_default_keyboard_layout ();
3688 }
3689
3690 static void
3691 fallback_commit_string_cb (IMEngineInstanceBase  *si,
3692                            const WideString      &str)
3693 {
3694     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3695
3696     if (_focused_ic && _focused_ic->impl) {
3697         ecore_imf_context_commit_event_add (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
3698         ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3699     }
3700 }
3701
3702 /*
3703 vi:ts=4:expandtab:nowrap
3704 */