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