Close candidate more view when pressing smartreply item
[platform/core/uifw/ise-default.git] / src / ise.cpp
1 /*
2  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <vconf.h>
24 #include <Ecore.h>
25 #include <Ecore_IMF.h>
26 #include <Elementary.h>
27 #include <sclui.h>
28 #include <sclutils.h>
29 #include <inputmethod.h>
30 #include <inputmethod_internal.h>
31 #include <app_control.h>
32 #include <app_preference.h>
33 #include <ode/internal-encryption.h>
34 #ifdef HAVE_CBHM
35 #include <cbhm.h>
36 #endif
37 #include "autofill.h"
38 #include "ise.h"
39 #include "utils.h"
40 #include "option.h"
41 #include "languages.h"
42 #include "candidate-factory.h"
43 #include "ise-emoticon-mode.h"
44 #include "ise-emoticon-list.h"
45 #include "ise-stt-mode.h"
46 #include "ise-stt-option.h"
47 #include "ise-language-change.h"
48 #include "ise-tutorial-mode.h"
49 #include "modeindicator.h"
50 #include "w-input-smartreply.h"
51 #include "ise-floating-mode.h"
52 #include "ise-dbus.h"
53
54 #define EDJ_FILE                        RESDIR"/edje/mobile/customised_ctxpopup.edj"
55
56 #define EXIT_ISE_ON_HIDE 0
57 #define DEFER_ISE_CREATION 0
58
59 #define CANDIDATE_WINDOW_HEIGHT 84
60 using namespace scl;
61 #include <vector>
62 using namespace std;
63
64 static CSCLUI *g_ui = NULL;
65 CSCLUI* get_ui() { return g_ui; }
66
67 #ifdef HAVE_CBHM
68 static cbhm_h cbhm_handle;
69 static sclu32 cbhm_sel_type = 0;
70 static sclboolean g_set_mime_type = FALSE;
71 #endif
72
73 static int g_imdata_state = 0;
74
75 static sclboolean g_need_send_shift_event = FALSE;
76
77 extern void set_ise_imdata(const char * buf, size_t &len);
78 static void init_recent_used_punctuation();
79 static void update_recent_used_punctuation(const char *key_value);
80 static void set_ime_size(bool floating_mode, ISE_CANDIDATE_REQUEST candidate_req);
81 static sclboolean g_punctuation_popup_opened = FALSE;
82 static sclboolean g_popup_opened = FALSE;
83 static vector<string> g_recent_used_punctuation;
84 static const int MAX_DEFAULT_PUNCTUATION = 6;
85 static string g_default_punctuation[MAX_DEFAULT_PUNCTUATION] = {"-", "@", "'", "!", "?", ","};
86 static string g_current_punctuation[MAX_DEFAULT_PUNCTUATION-1] = {"RCENT1", "RCENT2", "RCENT3", "RCENT4", "RCENT5"};
87 static vector<string> g_softcandidate_string;
88 static bool g_softcandidate_show = false;
89 static bool g_input_panel_show = false;
90 static bool g_caps_mode_pending = false;
91 static bool g_floating_mode = false;
92 static bool g_candidate_more_view = false;
93 static bool g_ise_created = false;
94
95 static bool g_autofill_exist = false;
96 static int g_autofill_hint = 0;
97 static string g_autofill_string;
98 static vector<string> g_lookup_table_strings;
99 static vector<string> g_smartreply_strings;
100 #if EXIT_ISE_ON_HIDE
101 static Ecore_Timer *exit_timer = NULL;
102 #endif
103
104 static string g_app_id;
105 static string g_resource_id;
106
107 #define SOFT_CANDIDATE_DELETE_TIME (100.0/1000)
108 static Ecore_Timer *g_softcandidate_hide_timer = NULL;
109
110 static int g_ic = 0;
111 static int g_ic_smartreply = -1;
112
113 static KEYBOARD_STATE g_keyboard_state = {
114     0,
115     0,
116     ISE_LAYOUT_STYLE_NORMAL,
117     0,
118     FALSE,
119     TRUE,
120     FALSE,
121     "",
122     KEY_MODIFIER_NONE,
123     FALSE
124 };
125
126 KEYBOARD_STATE* get_keyboard_state() {
127     return &g_keyboard_state;
128 }
129
130 #define ISE_LAYOUT_NUMBERONLY_VARIATION_MAX 4
131 /*static const sclchar *_ise_numberonly_variation_name[ISE_LAYOUT_NUMBERONLY_VARIATION_MAX] = {
132     "DEFAULT", "SIG", "DEC", "SIGDEC"
133 };*/
134
135 #define SIG_DEC_SIZE        2
136 static scluint              _click_count = 0;
137 static const char          *_sig_dec[SIG_DEC_SIZE] = {".", "-"};
138 static scluint              _sig_dec_event[SIG_DEC_SIZE] = {'.', '-'};
139 static Ecore_Timer         *_commit_timer = NULL;
140
141 static sclu32               _context_layout = ISE_LAYOUT_STYLE_NORMAL;
142 static sclu32               _context_layout_variation = 0;
143
144 static Candidate           *g_candidate = NULL;
145 Candidate* get_candidate() {
146     return g_candidate;
147 }
148
149 static ISELanguageManager _language_manager;
150
151 class CandidateEventListener: public EventListener
152 {
153     public:
154         void on_event(const EventDesc &desc)
155         {
156             CSCLUI *ui = get_ui();
157             const MultiEventDesc &multidesc = dynamic_cast<const MultiEventDesc &>(desc);
158             LANGUAGE_INFO *info = _language_manager.get_language_info(_language_manager.get_current_language());
159
160             unsigned int smartreply_size = input_smartreply_get_reply_num();
161
162             switch (multidesc.type) {
163                 case MultiEventDesc::CANDIDATE_ITEM_MOUSE_DOWN:
164                     if (g_autofill_exist) {
165                         if (multidesc.index == 0) {
166                             char *text = autofill_get_string(g_app_id.c_str(), g_resource_id.c_str(), (Ecore_IMF_Input_Hints)g_autofill_hint);
167                             if (text) {
168                                 ise_send_string(text);
169                                 free(text);
170                             }
171                         } else if (multidesc.index < (int)smartreply_size + 1) {
172                             ise_send_string(g_softcandidate_string[multidesc.index].c_str());
173                             ise_update_table(g_smartreply_strings);
174                         } else {
175                             if (info && info->load_in_ime)
176                                 ime_select_candidate(multidesc.index - smartreply_size - 1);
177                             else
178                                 engine_loader_select_candidate(multidesc.index - smartreply_size - 1);
179                         }
180                     } else {
181                         if (multidesc.index < (int)smartreply_size) {
182                             ise_send_string(g_softcandidate_string[multidesc.index].c_str());
183                             ise_update_table(g_smartreply_strings);
184                         }
185                         else {
186                             if (info && info->load_in_ime)
187                                 ime_select_candidate(multidesc.index - smartreply_size);
188                             else
189                                 engine_loader_select_candidate(multidesc.index - smartreply_size);
190                         }
191                     }
192                     break;
193                 case MultiEventDesc::CANDIDATE_MORE_VIEW_SHOW:
194                     // when more parts shows, click on the candidate will
195                     // not affect the key click event
196                     g_candidate_more_view = true;
197                     if (!g_input_panel_show)
198                         set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_SHOW);
199                     if (ui)
200                         ui->disable_input_events(TRUE);
201                     break;
202                 case MultiEventDesc::CANDIDATE_MORE_VIEW_HIDE:
203                     g_candidate_more_view = false;
204                     if (!g_input_panel_show)
205                         set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_SHOW);
206                     if (ui)
207                         ui->disable_input_events(FALSE);
208                     break;
209                 default: break;
210             }
211         }
212 };
213 static CandidateEventListener g_candidate_event_listener;
214
215 #define MVK_Shift_L 0xffe1
216 #define MVK_Caps_Lock 0xffe5
217 #define MVK_Shift_Off 0xffe1
218 #define MVK_Shift_On 0xffe2
219 #define MVK_Shift_Lock 0xffe6
220 #define MVK_Shift_Enable 0x9fe7
221 #define MVK_Shift_Disable 0x9fe8
222 #define MVK_space 0x020
223 #define MVK_Done 0xff0d
224
225 #define CM_KEY_LIST_SIZE         5
226 #define MULTITAP_TIMEOUT         3.0
227 #define USER_KEYSTRING_OPTION    "OPTION"
228 #define USER_KEYSTRING_EMOTICON  "EMOTICON_LAYOUT"
229 #define USER_KEYSTRING_CLIPBOARD "CLIPBOARD"
230 #define USER_KEYSTRING_VOICE     "STT_3X4"
231 #define USER_KEYSTRING_FLOATING  "FLOATING"
232
233 #define USER_VOICE_LANGUAGE     "LANGUAGE"
234
235 static sclboolean           _cm_popup_opened = FALSE;
236 static const char          *_cm_key_list[CM_KEY_LIST_SIZE] = {USER_KEYSTRING_OPTION, USER_KEYSTRING_EMOTICON, USER_KEYSTRING_CLIPBOARD, USER_KEYSTRING_VOICE, USER_KEYSTRING_FLOATING};
237 static scluint              _current_cm_key_id = 0;
238 static Evas_Object* _guide_popup_setting = NULL;
239 static Evas_Object* _guide_popup_space = NULL;
240
241 /*
242  * This callback class will receive all response events from SCL
243  * So you should perform desired tasks in this class.
244  */
245 class CUIEventCallback : public ISCLUIEventCallback
246 {
247 public :
248     Ecore_Timer* word_timer = NULL;
249     static Eina_Bool _multi_tap_timer_cb(void *data)
250     {
251         LOGD("Time Out");
252         ise_send_event(MVK_Done, KEY_MASK_NULL);
253         return ECORE_CALLBACK_CANCEL;
254     }
255     SCLEventReturnType on_event_key_clicked(SclUIEventDesc event_desc);
256     SCLEventReturnType on_event_drag_state_changed(SclUIEventDesc event_desc);
257     SCLEventReturnType on_event_notification(SCLUINotiType noti_type, SclNotiDesc *etc_info);
258 };
259
260 static CUIEventCallback callback;
261
262 int ise_get_imdata_state()
263 {
264     return g_imdata_state;
265 }
266
267 void ise_set_imdata_state(int state)
268 {
269     g_imdata_state = state;
270 }
271
272 static void update_candidate_table()
273 {
274     g_softcandidate_string.clear();
275     vector<string>::iterator iter;
276
277     // add autofill string
278     if (g_autofill_exist)
279         g_softcandidate_string.push_back(g_autofill_string);
280
281     // add lookup table string(s)
282     iter = g_lookup_table_strings.begin();
283     for (; iter != g_lookup_table_strings.end(); ++iter)
284     {
285         g_softcandidate_string.push_back(string(iter->c_str()));
286     }
287
288     ise_update_table(g_softcandidate_string);
289 }
290
291 static void _input_smartreply_notify_cb(void *user_data)
292 {
293     g_smartreply_strings.clear();
294     char *candidate = NULL;
295
296     if (input_smartreply_is_enabled()) {
297         /* Append newly added smartreply list */
298         int len = input_smartreply_get_reply_num();
299         if (len > 0) {
300             for (int i = 0; i < len; i++) {
301                 int type;
302                 char *reply = (char *)"";
303                 reply = input_smartreply_get_nth_item(i, &type);
304                 if (reply == NULL)
305                     continue;
306                 SECURE_LOGD("SmartReply = [%d] %s", i, reply);
307                 candidate = reply;
308                 if (candidate) {
309                     g_smartreply_strings.push_back(string(candidate));
310                     free(candidate);
311                     candidate = NULL;
312                 }
313             }
314             g_ic_smartreply = g_ic;
315
316             ise_app_candidate_show();
317             g_softcandidate_string = g_smartreply_strings;
318             ise_update_table(g_softcandidate_string);
319         }
320     }
321 }
322
323 sclboolean
324 check_ic_temporary(int ic)
325 {
326     if ((ic & 0xFFFF) == 0) {
327         return TRUE;
328     }
329     return FALSE;
330 }
331
332 static void _reset_shift_state(void)
333 {
334     CSCLUI *ui = get_ui();
335     if (ui) {
336         /* Reset all shift state variables */
337         SCLShiftState old_shift_state = ui->get_shift_state();
338         SCLShiftState new_shift_state = SCL_SHIFT_STATE_OFF;
339         if (old_shift_state != new_shift_state) {
340             g_need_send_shift_event = true;
341             ui->set_shift_state(new_shift_state);
342         }
343         LOGD("Shift state changed from (%d) to (%d)\n", (int)old_shift_state, (int)new_shift_state);
344     }
345 }
346
347 static void set_caps_mode(sclboolean mode) {
348     CSCLUI *ui = get_ui();
349     LOGD("mode : %d\n", mode);
350     if (ui) {
351         if (ui->get_shift_state() != SCL_SHIFT_STATE_LOCK) {
352             ui->set_shift_state(mode ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF);
353             ui->set_autocapital_shift_state(!mode);
354
355             bool load_in_ime = false;
356             const sclchar *cur_lang = _language_manager.get_current_language();
357             if (cur_lang) {
358                 LANGUAGE_INFO *info = _language_manager.get_language_info(cur_lang);
359                 if (info)
360                     load_in_ime = info->load_in_ime;
361             }
362
363             if (load_in_ime)
364                 ime_send_imengine_event(mode ? MVK_Shift_On : MVK_Shift_Off, 0);
365             else
366                 engine_loader_send_imengine_event(mode ? MVK_Shift_On : MVK_Shift_Off, 0);
367         }
368     }
369 }
370
371 static void _reset_multitap_state(bool skip_commit = false)
372 {
373     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
374     if (!keyboard_state) return;
375
376     LOGD("keyboard_state.prev_modifier : %d", keyboard_state->prev_modifier);
377     if (keyboard_state->prev_modifier == KEY_MODIFIER_MULTITAP_START ||
378         keyboard_state->prev_modifier == KEY_MODIFIER_MULTITAP_REPEAT) {
379         if (!skip_commit) {
380             ise_send_string(keyboard_state->multitap_value.c_str());
381         }
382         ise_update_preedit_string("");
383     }
384     keyboard_state->multitap_value = "";
385     keyboard_state->prev_modifier = KEY_MODIFIER_NONE;
386     if (g_caps_mode_pending) {
387         g_caps_mode_pending = false;
388         set_caps_mode(keyboard_state->caps_mode);
389     }
390 }
391
392 static void ise_set_cm_private_key(scluint cm_key_id)
393 {
394     CSCLUI *ui = get_ui();
395     if (cm_key_id >= CM_KEY_LIST_SIZE || ui == NULL) {
396         LOGE("cm_key_id=%d\n", cm_key_id);
397         return;
398     }
399
400     if (strcmp(_cm_key_list[cm_key_id], USER_KEYSTRING_EMOTICON) == 0) {
401         sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
402             const_cast<sclchar*>("icon/54x54/icon_emotion_nor.png"),
403             const_cast<sclchar*>("icon/54x54/icon_emotion_press.png"),
404             const_cast<sclchar*>("icon/54x54/icon_emotion_dim.png")};
405         ui->set_private_key("CM_KEY", const_cast<sclchar*>(" "), imagelabel, NULL, 0, const_cast<sclchar*>(USER_KEYSTRING_EMOTICON), TRUE);
406     } else if (strcmp(_cm_key_list[cm_key_id], USER_KEYSTRING_OPTION) == 0) {
407         sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
408             const_cast<sclchar*>("icon/54x54/icon_setting_nor.png"),
409             const_cast<sclchar*>("icon/54x54/icon_setting_press.png"),
410             const_cast<sclchar*>("icon/54x54/icon_setting_dim.png")};
411         ui->set_private_key("CM_KEY", const_cast<sclchar*>(" "), imagelabel, NULL, 0, const_cast<sclchar*>(USER_KEYSTRING_OPTION), TRUE);
412     } else if (strcmp(_cm_key_list[cm_key_id], USER_KEYSTRING_CLIPBOARD) == 0) {
413         sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
414             const_cast<sclchar*>("icon/54x54/icon_clipboard_nor.png"),
415             const_cast<sclchar*>("icon/54x54/icon_clipboard_press.png"),
416             const_cast<sclchar*>("icon/54x54/icon_clipboard_dim.png")};
417         ui->set_private_key("CM_KEY", const_cast<sclchar*>(" "), imagelabel, NULL, 0, const_cast<sclchar*>(USER_KEYSTRING_CLIPBOARD), TRUE);
418     } else if (strcmp(_cm_key_list[cm_key_id], USER_KEYSTRING_VOICE) == 0) {
419         sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
420             const_cast<sclchar*>("icon/54x54/icon_mic_nor.png"),
421             const_cast<sclchar*>("icon/54x54/icon_mic_press.png"),
422             const_cast<sclchar*>("icon/54x54/icon_mic_dim.png")};
423         ui->set_private_key("CM_KEY", const_cast<sclchar*>(" "), imagelabel, NULL, 0, const_cast<sclchar*>(USER_KEYSTRING_VOICE), TRUE);
424     } else if (strcmp(_cm_key_list[cm_key_id], USER_KEYSTRING_FLOATING) == 0) {
425         sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
426             const_cast<sclchar*>("icon/54x54/icon_floating_keypad_nor.png"),
427             const_cast<sclchar*>("icon/54x54/icon_floating_keypad_press.png"),
428             const_cast<sclchar*>("icon/54x54/icon_floating_keypad_dim.png")};
429         ui->set_private_key("CM_KEY", const_cast<sclchar*>(" "), imagelabel, NULL, 0, const_cast<sclchar*>(USER_KEYSTRING_FLOATING), TRUE);
430     }
431 }
432
433 static void ise_update_space_key(void)
434 {
435     CSCLUI *ui = get_ui();
436     if (ui == NULL) {
437         LOGE("ui = NULL\n");
438         return;
439     }
440
441     scluint num = _language_manager.get_enabled_languages_num();
442     LOGD("language number: %d\n", num);
443     if (num <= 1) {
444         LANGUAGE_INFO *info = _language_manager.get_language_info(_language_manager.get_current_language());
445         if (info && info->enabled) {
446 #ifdef _WEARABLE
447             sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
448                 const_cast<sclchar*>("w_sip_3x4_btn_ic_space_no_arrow.png"),
449                 const_cast<sclchar*>("w_sip_3x4_btn_ic_space_no_arrow.png"),
450                 const_cast<sclchar*>("w_sip_3x4_btn_ic_space_no_arrow.png")};
451             ui->set_private_key("SPACE_KEY", const_cast<sclchar*>(info->display_name.c_str()), imagelabel, NULL, 0, const_cast<sclchar*>("Space"), TRUE);
452 #else
453             ui->enable_button("SPACE_ARROW_LEFT", false);
454             ui->enable_button("SPACE_ARROW_RIGHT", false);
455 #endif
456         }
457     } else {
458 #ifdef _WEARABLE
459         ui->unset_private_key("SPACE_KEY");
460 #else
461         ui->enable_button("SPACE_ARROW_LEFT", true);
462         ui->enable_button("SPACE_ARROW_RIGHT", true);
463 #endif
464     }
465 }
466
467 static scluint ise_get_cm_key_id(const sclchar *key_value)
468 {
469     for (int i = 0; i < CM_KEY_LIST_SIZE; ++i) {
470         if (0 == strcmp (key_value, _cm_key_list[i]))
471             return i;
472     }
473     return 0;
474 }
475
476 static bool ise_is_emoticons_disabled(void)
477 {
478     bool ret = true;
479
480     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
481     if (!keyboard_state) return ret;
482
483     sclu32 current_layout = keyboard_state->layout;
484     LOGD("layout=%d\n", current_layout);
485
486     if ((current_layout == ISE_LAYOUT_STYLE_NORMAL) ||
487         (current_layout == ISE_LAYOUT_STYLE_NUMBER) ||
488         (current_layout == ISE_LAYOUT_STYLE_EMOTICON))
489         ret = false;
490
491     if (g_imdata_state & IMDATA_ACTION_DISABLE_EMOTICONS)
492         ret = true;
493
494     return ret;
495 }
496
497 static Eina_Bool softcandidate_hide_timer_callback(void *data)
498 {
499     LOGD("Enter\n");
500     set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_HIDE);
501
502     Candidate *candidate = get_candidate();
503     if (candidate) {
504         candidate->hide();
505         g_softcandidate_show = false;
506     }
507     return ECORE_CALLBACK_CANCEL;
508 }
509
510 static void delete_softcandidate_hide_timer(void)
511 {
512     if (g_softcandidate_hide_timer) {
513         ecore_timer_del(g_softcandidate_hide_timer);
514         g_softcandidate_hide_timer = NULL;
515     }
516 }
517
518 static void add_softcandidate_hide_timer(void)
519 {
520     delete_softcandidate_hide_timer();
521     g_softcandidate_hide_timer = ecore_timer_add(SOFT_CANDIDATE_DELETE_TIME, softcandidate_hide_timer_callback, NULL);
522 }
523
524 static void create_softcandidate(void)
525 {
526     if (!g_candidate) {
527         g_candidate = CandidateFactory::make_candidate(CANDIDATE_MULTILINE, ime_get_main_window());
528         if (g_candidate) {
529             g_candidate->add_event_listener(&g_candidate_event_listener);
530         }
531     }
532 }
533
534 /**
535  * Send the given string to input framework
536  */
537 void
538 ise_send_string(const sclchar *key_value)
539 {
540     int ic = -1;
541     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
542     if (keyboard_state && !check_ic_temporary(keyboard_state->ic)) {
543         ic = keyboard_state->ic;
544     }
545     ime_commit_string(key_value);
546     LOGD("ic : %x, %s\n", ic, key_value);
547 }
548
549 /**
550 * Send the preedit string to input framework
551 */
552 void
553 ise_update_preedit_string(const sclchar *str, const sclboolean underline)
554 {
555     int ic = -1;
556     Eina_List *attr_list = NULL;
557     ime_preedit_attribute *preedit_attr;
558
559     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
560     if (keyboard_state && !check_ic_temporary(keyboard_state->ic)) {
561         ic = keyboard_state->ic;
562     }
563     if (underline) {
564         /* Count UTF-8 string length */
565         int len = 0;
566         const sclchar *s = str;
567         while (*s) len += (*s++ & 0xc0) != 0x80;
568
569         preedit_attr = (ime_preedit_attribute *)calloc(1, sizeof(ime_preedit_attribute));
570         if (preedit_attr) {
571             preedit_attr->start = 0;
572             preedit_attr->length = len;
573             preedit_attr->type = IME_ATTR_FONTSTYLE;
574             preedit_attr->value = IME_ATTR_FONTSTYLE_UNDERLINE;
575             attr_list = eina_list_append(attr_list, (void *)preedit_attr);
576         }
577
578         ime_update_preedit_string(str, attr_list);
579     } else {
580         ime_update_preedit_string(str, NULL);
581     }
582     LOGD("ic : %x, %s\n", ic, str);
583 }
584
585 /**
586 * Send the given event to input framework
587 */
588 void
589 ise_send_event(sclulong key_event, sclulong key_mask)
590 {
591     int ic = -1;
592     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
593     if (keyboard_state && !check_ic_temporary(keyboard_state->ic)) {
594         ic = keyboard_state->ic;
595     }
596     ime_send_key_event((ime_key_code_e)key_event, IME_KEY_MASK_PRESSED, false);
597     ime_send_key_event((ime_key_code_e)key_event, IME_KEY_MASK_RELEASED, false);
598
599     LOGD("ic : %x, %lx\n", (unsigned int)ic, key_event);
600 }
601
602 /**
603 * Forward the given event to input framework
604 */
605 void
606 ise_forward_key_event(sclulong key_event)
607 {
608     int ic = -1;
609     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
610     if (!check_ic_temporary(keyboard_state->ic)) {
611         ic = keyboard_state->ic;
612     }
613     ime_send_key_event((ime_key_code_e)key_event, IME_KEY_MASK_PRESSED, true);
614     ime_send_key_event((ime_key_code_e)key_event, IME_KEY_MASK_RELEASED, true);
615
616     LOGD("ic : %x, %lx\n", (unsigned int)ic, key_event);
617 }
618
619 /**
620  * @brief Delete commit timer.
621  *
622  * @return void
623  */
624 static void delete_commit_timer(void)
625 {
626     if (_commit_timer != NULL) {
627         ecore_timer_del(_commit_timer);
628         _commit_timer = NULL;
629     }
630 }
631
632 /**
633  * @brief Callback function for commit timer.
634  *
635  * @param data Data to pass when it is called.
636  *
637  * @return ECORE_CALLBACK_CANCEL
638  */
639 static Eina_Bool commit_timeout(void *data)
640 {
641     if (_commit_timer != NULL) {
642         ime_hide_preedit_string();
643         ise_forward_key_event(_sig_dec_event[(_click_count-1)%SIG_DEC_SIZE]);
644         _click_count = 0;
645     }
646     _commit_timer = NULL;
647     return ECORE_CALLBACK_CANCEL;
648 }
649
650 static sclboolean
651 on_input_mode_changed(const sclchar *key_value, sclulong key_event, sclint key_type)
652 {
653     sclboolean ret = FALSE;
654
655     CSCLUI *ui = get_ui();
656     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
657     if (ui && keyboard_state) {
658         if (key_value) {
659             SECURE_LOGD("key_value : %s\n", key_value);
660             if (strcmp(key_value, "CUR_LANG") == 0) {
661                 keyboard_state->disable_force_latin = TRUE;
662                 ret = _language_manager.select_current_language();
663             }
664             if (strcmp(key_value, "NEXT_LANG") == 0) {
665                 keyboard_state->disable_force_latin = TRUE;
666                 ret = _language_manager.select_next_language();
667             }
668         }
669
670         const sclchar *cur_lang = _language_manager.get_current_language();
671         if (cur_lang) {
672             LANGUAGE_INFO *info = _language_manager.get_language_info(cur_lang);
673             if (info) {
674                 if (info->accepts_caps_mode) {
675                     if (info->load_in_ime)
676                         ime_send_imengine_event(MVK_Shift_Enable, 0);
677                     else
678                         engine_loader_send_imengine_event(MVK_Shift_Enable, 0);
679
680                     set_caps_mode(keyboard_state->caps_mode);
681                 } else {
682                     if (info->load_in_ime)
683                         ime_send_imengine_event(MVK_Shift_Disable, 0);
684                     else
685                         engine_loader_send_imengine_event(MVK_Shift_Disable, 0);
686
687                     ui->set_shift_state(SCL_SHIFT_STATE_OFF);
688                 }
689             }
690         }
691         if (ise_emoticon_is_show()) {
692             ise_emoticon_destroy_layout();
693         }
694         if (key_value) {
695             if (!strcmp(key_value, USER_KEYSTRING_EMOTICON)) {
696                 ise_emoticon_init_list();
697 #ifdef _WEARABLE
698                     ise_emoticon_set_current_group(EMOTICON_GROUP_1);
699 #else
700                 if (ise_emoticon_get_recent_list_size() == 0)
701                     ise_emoticon_set_current_group(EMOTICON_GROUP_1);
702                 else
703                     ise_emoticon_set_current_group(EMOTICON_GROUP_RECENTLY_USED);
704 #endif
705                 SCLRotation rotation = ui->get_rotation();
706                 ise_emoticon_show_layout(ise_emoticon_get_current_group(), ROTATION_TO_DEGREE(rotation), false, ime_get_main_window());
707             }
708         }
709     }
710
711     return ret;
712 }
713
714 static void show_cbhm()
715 {
716 #ifdef HAVE_CBHM
717     int ret;
718
719     if (g_set_mime_type)
720         ret = cbhm_selection_type_set(cbhm_handle, static_cast<cbhm_sel_type_e>(cbhm_sel_type));
721     else
722         ret = cbhm_selection_type_set(cbhm_handle, CBHM_SEL_TYPE_TEXT);
723
724     if (ret != CBHM_ERROR_NONE)
725         LOGW("Failed to set selection type in cbhm. error : %d\n", ret);
726
727     ret = cbhm_show(cbhm_handle);
728     if (ret != CBHM_ERROR_NONE)
729         LOGW("cbhm show error : %d\n", ret);
730     else
731         LOGD("Show cbhm\n");
732 #endif
733 }
734
735 SCLEventReturnType CUIEventCallback::on_event_notification(SCLUINotiType noti_type, SclNotiDesc *etc_info)
736 {
737     CSCLUI *ui = get_ui();
738     SCLEventReturnType ret = SCL_EVENT_PASS_ON;
739     LOGD("noti type: %d, g_need_send_shift_event: %d\n", noti_type, g_need_send_shift_event);
740
741     if (noti_type == SCL_UINOTITYPE_SHIFT_STATE_CHANGE) {
742         if (g_need_send_shift_event) {
743             const sclchar *cur_lang = _language_manager.get_current_language();
744             if (cur_lang) {
745                 LANGUAGE_INFO *info = _language_manager.get_language_info(cur_lang);
746                 SclNotiShiftStateChangeDesc *desc = static_cast<SclNotiShiftStateChangeDesc*>(etc_info);
747                 if (info && desc) {
748                     if (info->accepts_caps_mode) {
749                         LOGD("shift state: %d\n", desc->shift_state);
750                         if (desc->shift_state == SCL_SHIFT_STATE_OFF) {
751                             if (info->load_in_ime)
752                                 ime_send_imengine_event(MVK_Shift_Off, 0);
753                             else
754                                 engine_loader_send_imengine_event(MVK_Shift_Off, 0);
755                         } else if (desc->shift_state == SCL_SHIFT_STATE_ON) {
756                             if (info->load_in_ime)
757                                 ime_send_imengine_event(MVK_Shift_On, 0);
758                             else
759                                 engine_loader_send_imengine_event(MVK_Shift_On, 0);
760                         } else if (desc->shift_state == SCL_SHIFT_STATE_LOCK) {
761                             if (info->load_in_ime)
762                                 ime_send_imengine_event(MVK_Shift_Lock, 0);
763                             else
764                                 engine_loader_send_imengine_event(MVK_Shift_Lock, 0);
765                         }
766                         ret = SCL_EVENT_PASS_ON;
767                     }
768                 }
769             }
770             g_need_send_shift_event = FALSE;
771         }
772     } else if (noti_type == SCL_UINOTITYPE_POPUP_OPENING) {
773         vector<string>::reverse_iterator iter = g_recent_used_punctuation.rbegin();
774         int punc_pos = 0;
775         for (; iter != g_recent_used_punctuation.rend(); ++iter)
776         {
777             if (ui)
778                 ui->set_string_substitution(g_current_punctuation[punc_pos].c_str(), iter->c_str());
779             punc_pos++;
780         }
781         SclNotiPopupOpeningDesc *openingDesc = (SclNotiPopupOpeningDesc *)etc_info;
782         if (ui && 0 == strcmp(openingDesc->input_mode, "CM_POPUP")) {
783             if (ise_is_emoticons_disabled())
784                 ui->enable_button("EMOTICON_KEY", false);
785             else
786                 ui->enable_button("EMOTICON_KEY", true);
787         }
788     } else if (noti_type == SCL_UINOTITYPE_POPUP_OPENED) {
789         g_popup_opened = TRUE;
790         SclNotiPopupOpenedDesc *openedDesc = (SclNotiPopupOpenedDesc *)etc_info;
791         if (0 == strcmp(openedDesc->input_mode, "PUNCTUATION_POPUP")) {
792             g_punctuation_popup_opened = TRUE;
793         } else if (0 == strcmp(openedDesc->input_mode, "CM_POPUP")) {
794             _cm_popup_opened = TRUE;
795         }
796     } else if (noti_type == SCL_UINOTITYPE_POPUP_CLOSED) {
797         g_popup_opened = FALSE;
798         SclNotiPopupClosedDesc *closedDesc = (SclNotiPopupClosedDesc *)etc_info;
799         if (closedDesc && closedDesc->input_mode) {
800             if (0 == strcmp(closedDesc->input_mode, "PUNCTUATION_POPUP")) {
801                 g_punctuation_popup_opened = FALSE;
802             } else if (0 == strcmp(closedDesc->input_mode, "CM_POPUP")) {
803                 _cm_popup_opened = FALSE;
804             }
805         }
806     } else if (noti_type == SCL_UINOTITYPE_INPUT_MODE_CHANGE) {
807         SclNotiInputModeChangeDesc *desc = static_cast<SclNotiInputModeChangeDesc*>(etc_info);
808         if (desc && ui) {
809             set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_NONE);
810
811             const char *input_mode = ui->get_input_mode();
812             if (input_mode) {
813                 if (strcmp(input_mode, "STT_3X4") == 0 &&
814                         strcmp(desc->input_mode, "STT_3X4") != 0) {
815                     ise_hide_stt_mode();
816                 }
817                 if (strcmp(input_mode, "STT_3X4") != 0 &&
818                         strcmp(desc->input_mode, "STT_3X4") == 0) {
819                     ise_show_stt_mode(NATIVE_WINDOW_CAST(ime_get_main_window()));
820                 }
821             }
822         }
823     }
824
825     return ret;
826 }
827
828 void ise_destory_popup_setting()
829 {
830     if (_guide_popup_setting != NULL) {
831         LOGD("destroy setting popup iter\n");
832         evas_object_del(_guide_popup_setting);
833         _guide_popup_setting = NULL;
834         CONFIG_VALUES *config_values = get_config_values();
835         if (config_values) {
836             config_values->first_guideset = TRUE;
837         }
838         write_ise_config_values();
839     }
840 }
841
842 void ise_destory_popup_space()
843 {
844     if (_guide_popup_space != NULL) {
845         LOGD("destroy space popup iter\n");
846         evas_object_del(_guide_popup_space);
847         _guide_popup_setting = NULL;
848         CONFIG_VALUES *config_values = get_config_values();
849         if (config_values) {
850             config_values->first_guidechange = TRUE;
851         }
852         write_ise_config_values();
853     }
854 }
855
856 Evas_Object *open_message_popup(Evas_Object *parentWnd)
857 {
858     static Evas_Object *msg_window = NULL;
859     if (msg_window) {
860         evas_object_del(msg_window);
861         msg_window = NULL;
862     }
863     msg_window = elm_win_add(parentWnd, "MCFMessagePopup", ELM_WIN_UTILITY);
864     if (msg_window) {
865         int w, h;
866         elm_win_borderless_set(msg_window, EINA_TRUE);
867         elm_win_alpha_set(msg_window, EINA_TRUE);
868         elm_win_title_set(msg_window, "ISF Popup");
869         elm_win_screen_size_get(msg_window, NULL, NULL, &w, &h);
870         elm_win_prop_focus_skip_set(msg_window, TRUE);
871         int rots[4] = {0, 90, 180, 270};
872         elm_win_wm_rotation_available_rotations_set(msg_window, rots, 4);
873         evas_object_resize(msg_window, w, h);
874     }
875
876     int rots[4] = { 0, 90, 180, 270 };
877     elm_win_wm_rotation_available_rotations_set(msg_window, rots, 4);
878     evas_object_show(msg_window);
879     return msg_window;
880 }
881
882 void _guideline_popup_setting_cb(void *data, Evas_Object *obj, void *event_info)
883 {
884     evas_object_smart_callback_del(obj, "dismissed", _guideline_popup_setting_cb);
885     evas_object_del(obj);
886     obj = NULL;
887     ise_destory_popup_setting();
888     CONFIG_VALUES *config_values = get_config_values();
889     if (config_values) {
890         config_values->first_guideset = TRUE;
891     }
892     write_ise_config_values();
893 }
894
895 void _guideline_popup_space_cb(void *data, Evas_Object *obj, void *event_info)
896 {
897     evas_object_smart_callback_del(obj, "dismissed", _guideline_popup_space_cb);
898     evas_object_del(obj);
899     obj = NULL;
900     ise_destory_popup_space();
901     CONFIG_VALUES *config_values = get_config_values();
902     if (config_values) {
903         config_values->first_guidechange = TRUE;
904     }
905     write_ise_config_values();
906 }
907
908 void ise_show_help_popup(sclulong keyEvent)
909 {
910     char buf[2048] = {0, };
911     int font_size = 40;
912     sclint scr_w = 0;
913     sclint scr_h = 0;
914     SclRectangle rectangle = {0};
915     Evas_Object *ctxpopup = NULL;
916     Elm_Theme *theme = NULL;
917
918     CSCLUI *ui = get_ui();
919     if (ui) {
920         ui->get_screen_resolution(&scr_w, &scr_h);
921
922         if (keyEvent == MVK_space) {
923             CONFIG_VALUES *config_values = get_config_values();
924             if (config_values) {
925                 config_values->first_guidechange = TRUE;
926             }
927             write_ise_config_values();
928             ui->get_button_geometry("SPACE_KEY", &rectangle);
929             _guide_popup_space = open_message_popup(NATIVE_WINDOW_CAST(ime_get_main_window()));
930
931             theme = elm_theme_new();
932             elm_theme_ref_set(theme, NULL);
933             elm_theme_extension_add(theme, EDJ_FILE);
934
935             ctxpopup = elm_ctxpopup_add(_guide_popup_space);
936             elm_object_theme_set(ctxpopup, theme);
937             evas_object_smart_callback_add(ctxpopup, "dismissed", _guideline_popup_space_cb, (void *)keyEvent);
938         } else {
939             CONFIG_VALUES *config_values = get_config_values();
940             if (config_values) {
941                 config_values->first_guideset = TRUE;
942             }
943             write_ise_config_values();
944             ui->get_button_geometry("CM_KEY", &rectangle);
945             _guide_popup_setting = open_message_popup(NATIVE_WINDOW_CAST(ime_get_main_window()));
946             theme = elm_theme_new();
947             elm_theme_ref_set(theme, NULL);
948             elm_theme_extension_add(theme, EDJ_FILE);
949             ctxpopup = elm_ctxpopup_add(_guide_popup_setting);
950             elm_object_theme_set(ctxpopup, theme);
951             evas_object_smart_callback_add(ctxpopup, "dismissed", _guideline_popup_setting_cb, (void *)keyEvent);
952         }
953     }
954
955     int rotation = elm_win_rotation_get(NATIVE_WINDOW_CAST(ime_get_main_window()));
956     if (rotation == 0 || rotation == 180) {
957         elm_object_style_set(ctxpopup, "customised_guideline_popup");
958     } else {
959         elm_object_style_set(ctxpopup, "customised_guideline_popup_landscape");
960     }
961
962     elm_ctxpopup_direction_priority_set(ctxpopup, ELM_CTXPOPUP_DIRECTION_UP,
963                           ELM_CTXPOPUP_DIRECTION_UNKNOWN,
964                           ELM_CTXPOPUP_DIRECTION_UNKNOWN,
965                           ELM_CTXPOPUP_DIRECTION_UNKNOWN);
966
967     Evas_Object* text = elm_label_add(ctxpopup);
968
969     if (keyEvent == MVK_space) {
970         snprintf(buf, sizeof(buf), "<font_style=Regular font_size=%d align=left wrap=mixed color=#000000>%s</>", font_size,
971             dgettext(PACKAGE, "IDS_IME_BODY_SWIPE_THE_SPACE_BAR_LEFT_OR_RIGHT_TO_CHANGE_BETWEEN_LANGUAGES"));
972     } else {
973         snprintf(buf, sizeof(buf), "<font_style=Regular font_size=%d align=left wrap=mixed color=#000000>%s</>", font_size,
974                dgettext(PACKAGE, "IDS_IME_BODY_TAP_AND_HOLD_THIS_KEY_TO_SEE_THE_SYMBOL_LIST_SELECT_ONE_TO_USE_IT_AS_A_SHORTCUT"));
975     }
976     elm_object_text_set(text, buf);
977     elm_object_content_set(ctxpopup, text);
978     Evas_Coord x, y, w, h;
979     evas_object_geometry_get(NATIVE_WINDOW_CAST(ime_get_main_window()), &x, &y, &w, &h);
980
981     if (rotation == 0 || rotation == 180) {
982         elm_label_wrap_width_set(text, (scr_w * 4) / 5);
983         evas_object_size_hint_min_set(ctxpopup, ELM_SCALE_SIZE(scr_w), ELM_SCALE_SIZE(50));
984         evas_object_size_hint_max_set(ctxpopup, ELM_SCALE_SIZE(scr_w), ELM_SCALE_SIZE(600));
985         evas_object_move(ctxpopup, rectangle.x + rectangle.width / 2,
986                     (scr_h - h) + rectangle.y - ELM_SCALE_SIZE(5));
987     } else {
988         elm_label_wrap_width_set(text, (scr_h * 4) / 5);
989         evas_object_size_hint_min_set(ctxpopup, ELM_SCALE_SIZE(scr_h), ELM_SCALE_SIZE(50));
990         evas_object_size_hint_max_set(ctxpopup, ELM_SCALE_SIZE(scr_h), ELM_SCALE_SIZE(600));
991         evas_object_move(ctxpopup, rectangle.x + rectangle.width / 2,
992                 (scr_w - h)+ rectangle.y - ELM_SCALE_SIZE(5));
993     }
994     elm_label_line_wrap_set(text, ELM_WRAP_MIXED);
995     evas_object_show(text);
996
997     if (keyEvent == MVK_space) {
998         evas_object_layer_set(_guide_popup_space, EVAS_LAYER_MAX);
999         evas_object_show(_guide_popup_space);
1000     } else {
1001         evas_object_layer_set(_guide_popup_setting, EVAS_LAYER_MAX);
1002         evas_object_show(_guide_popup_setting);
1003     }
1004
1005     evas_object_layer_set(ctxpopup, EVAS_LAYER_MAX);
1006     evas_object_show(ctxpopup);
1007 }
1008
1009 SCLEventReturnType CUIEventCallback::on_event_drag_state_changed(SclUIEventDesc event_desc)
1010 {
1011     SECURE_LOGD("button %s is clicked\n", event_desc.key_value);
1012     if (event_desc.event_type == EVENT_TYPE_MOVE) {
1013         if (event_desc.key_event == MVK_space) {
1014             SclRectangle rectangle = {0};
1015             CSCLUI *ui = get_ui();
1016             if (ui) ui->get_button_geometry("SPACE_KEY", &rectangle);
1017             ise_show_space_flick_language_change_popup(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
1018         }
1019     } else if (event_desc.event_type == EVENT_TYPE_RELEASE) {
1020         if (event_desc.key_event == MVK_space) {
1021             ise_destroy_space_flick_language_change_popup();
1022         }
1023
1024         if (g_floating_mode)
1025             ime_set_floating_drag_end();
1026     } else if (event_desc.event_type == EVENT_TYPE_PRESS) {
1027 #ifdef _MOBILE
1028         CONFIG_VALUES *config_values = get_config_values();
1029
1030         if (config_values && (!config_values->first_guideset) && event_desc.key_value && (strncmp(event_desc.key_value, "OPTION", strlen(event_desc.key_value)) == 0)) {
1031             ise_show_help_popup(event_desc.key_event);//show help popup in on_event_drag_state_changed other than on_event_key_clicked for fixing help popup show delay issue
1032             LOGD("setting popup show\n");
1033             return SCL_EVENT_PASS_ON;
1034         } else {
1035             ise_destory_popup_setting();//destory popup manually in case of abnormal situation
1036         }
1037 #endif
1038         if (g_floating_mode && event_desc.mouse_current_point.y <= FLOATING_TITLE_BAR_HEIGHT
1039             && event_desc.mouse_current_point.y >= 0)
1040             ime_set_floating_drag_start();
1041     }
1042     return SCL_EVENT_PASS_ON;
1043 }
1044
1045 static void launch_option()
1046 {
1047     app_control_h app_control;
1048     int ret = app_control_create(&app_control);
1049     if (ret != APP_CONTROL_ERROR_NONE) {
1050         LOGW("app_control_create returned %d\n", ret);
1051         return;
1052     }
1053
1054     ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
1055     if (ret != APP_CONTROL_ERROR_NONE) {
1056         LOGW("app_control_set_operation returned %d\n", ret);
1057         goto end;
1058     }
1059
1060     ret = app_control_set_app_id(app_control, "org.tizen.ise-default-setting");
1061     if (ret != APP_CONTROL_ERROR_NONE) {
1062         LOGW("app_control_set_app_id returned %d\n", ret);
1063         goto end;
1064     }
1065
1066     app_control_add_extra_data(app_control, "caller", "ise-default");
1067     app_control_set_launch_mode(app_control, APP_CONTROL_LAUNCH_MODE_GROUP);
1068
1069     ret = app_control_send_launch_request(app_control, NULL, NULL);
1070     if (ret != APP_CONTROL_ERROR_NONE) {
1071         goto end;
1072     }
1073
1074 end:
1075     if (app_control)
1076         app_control_destroy(app_control);
1077 }
1078
1079 SCLEventReturnType CUIEventCallback::on_event_key_clicked(SclUIEventDesc event_desc)
1080 {
1081     SCLEventReturnType ret = SCL_EVENT_PASS_ON;
1082     if (word_timer != NULL) {
1083         ecore_timer_del(word_timer);
1084         word_timer = NULL;
1085     }
1086
1087     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1088     if (!keyboard_state) return ret;
1089
1090     if (event_desc.key_modifier == KEY_MODIFIER_MULTITAP_START) {
1091         if (!keyboard_state->multitap_value.empty()) {
1092             ise_send_string(keyboard_state->multitap_value.c_str());
1093         }
1094         ise_update_preedit_string(event_desc.key_value);
1095         keyboard_state->multitap_value = event_desc.key_value;
1096     } else if (event_desc.key_modifier == KEY_MODIFIER_MULTITAP_REPEAT) {
1097         ise_update_preedit_string(event_desc.key_value);
1098         keyboard_state->multitap_value = event_desc.key_value;
1099     } else {
1100         _reset_multitap_state();
1101     }
1102     keyboard_state->prev_modifier = event_desc.key_modifier;
1103
1104     CSCLUI *ui = get_ui();
1105     if (ui) {
1106         switch (event_desc.key_type) {
1107         case KEY_TYPE_STRING: {
1108             if (event_desc.key_modifier != KEY_MODIFIER_MULTITAP_START &&
1109                 event_desc.key_modifier != KEY_MODIFIER_MULTITAP_REPEAT) {
1110                     if (event_desc.key_event) {
1111                         ise_forward_key_event(event_desc.key_event);
1112                     } else {
1113                         ise_send_string(event_desc.key_value);
1114                     }
1115             }
1116             if (!g_popup_opened) {
1117                 const sclchar *input_mode = ui->get_input_mode();
1118                 if (input_mode && ((0 == strcmp(input_mode, "SYM_QTY_1")) || (0 == strcmp(input_mode, "SYM_QTY_2")))) {
1119                     update_recent_used_punctuation(event_desc.key_value);
1120                 }
1121             } else if (g_punctuation_popup_opened) {
1122                 update_recent_used_punctuation(event_desc.key_value);
1123             }
1124             break;
1125         }
1126         case KEY_TYPE_CHAR: {
1127                 sclboolean need_forward = FALSE;
1128                 // FIXME : Should decide when to forward key events
1129                 const sclchar *input_mode = ui->get_input_mode();
1130                 if (input_mode) {
1131                     if (strcmp(input_mode, "SYM_QTY_1") == 0 ||
1132                             strcmp(input_mode, "SYM_QTY_2") == 0 ||
1133                             strcmp(input_mode, "PHONE_3X4") == 0 ||
1134                             strcmp(input_mode, "IPv6_3X4_123") == 0 ||
1135                             strcmp(input_mode, "IPv6_3X4_ABC") == 0 ||
1136                             strcmp(input_mode, "NUMONLY_3X4") == 0 ||
1137                             strcmp(input_mode, "NUMONLY_3X4_SIG") == 0 ||
1138                             strcmp(input_mode, "NUMONLY_3X4_DEC") == 0 ||
1139                             strcmp(input_mode, "NUMONLY_3X4_SIGDEC") == 0 ||
1140                             strcmp(input_mode, "DATETIME_3X4") == 0) {
1141                         need_forward = TRUE;
1142                     }
1143                 }
1144                 if (input_mode && strcmp (input_mode, "NUMONLY_3X4_SIGDEC") == 0 &&
1145                     strcmp(event_desc.key_value, ".") == 0) {
1146                     ime_update_preedit_string(_sig_dec[_click_count%SIG_DEC_SIZE], NULL);
1147                     ime_show_preedit_string();
1148                     delete_commit_timer();
1149                     _commit_timer = ecore_timer_add(1.0, commit_timeout, NULL);
1150                     _click_count++;
1151                 } else if (event_desc.key_event) {
1152                     commit_timeout(NULL);
1153                     if (need_forward) {
1154                         ise_forward_key_event(event_desc.key_event);
1155                     } else {
1156                         if (_cm_popup_opened) {
1157                             static sclchar current_cm_symbol[2] = {'\0'};
1158                             sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
1159                                 const_cast<sclchar*>(" "),
1160                                 const_cast<sclchar*>(" "),
1161                                 const_cast<sclchar*>(" ")};
1162                             if (event_desc.key_value) {
1163                                 current_cm_symbol[0] = event_desc.key_value[0];
1164                                 current_cm_symbol[1] = '\0';
1165                             }
1166                             ui->set_private_key("CM_KEY",
1167                                     const_cast<sclchar*>(current_cm_symbol),
1168                                     imagelabel, NULL, 0,
1169                                     const_cast<sclchar*>(current_cm_symbol), TRUE);
1170
1171                             _cm_popup_opened = FALSE;
1172                             _current_cm_key_id = -1;
1173                         }
1174 #ifdef _WEARABLE
1175                         /*
1176                         *
1177                         *change the keyboard mode of GLM from QWERTY to KEYPAD
1178                         *ensure the Number keypad won't be affected
1179                         *
1180                         */
1181                         if (keyboard_state->layout == ISE_LAYOUT_STYLE_NUMBER) {
1182                             ime_send_key_event(IME_KEY_Print, IME_KEY_MASK_CONTROL, false);
1183                         } else {
1184                             if (word_timer == NULL && (!get_candidate() || !g_softcandidate_show)) {
1185                                 word_timer = ecore_timer_add(MULTITAP_TIMEOUT, _multi_tap_timer_cb, NULL);
1186                             }
1187                             ime_send_key_event(IME_KEY_Select, IME_KEY_MASK_CONTROL, false);
1188                         }
1189 #endif
1190                         ise_send_event(event_desc.key_event, KEY_MASK_NULL);
1191                     }
1192                 }
1193                 if (input_mode) {
1194                     if ((strcmp(input_mode, "SYM_QTY_1") == 0) || (0 == strcmp(input_mode, "SYM_QTY_2"))) {
1195                         update_recent_used_punctuation(event_desc.key_value);
1196                     }
1197                 }
1198                 break;
1199             }
1200         case KEY_TYPE_CONTROL: {
1201                 commit_timeout(NULL);
1202
1203                 const char *long_shift = "LongShift";
1204                 const char *caps_lock = "CapsLock";
1205                 const char *delete_all = "DeleteAll";
1206                 const char *hide_panel = "Hide";
1207                 if (strncmp(event_desc.key_value, long_shift, strlen(long_shift)) == 0) {
1208                     LOGD("shift key is longpress\n");
1209                     ui->set_shift_state(SCL_SHIFT_STATE_ON);
1210                     g_need_send_shift_event = TRUE;
1211                     //ise_send_event (MVK_Shift_Lock, KEY_MASK_NULL);
1212                 } else if (strncmp(event_desc.key_value, caps_lock, strlen(caps_lock)) == 0) {
1213                     bool load_in_ime = false;
1214                     const sclchar *cur_lang = _language_manager.get_current_language();
1215                     if (cur_lang) {
1216                         LANGUAGE_INFO *info = _language_manager.get_language_info(cur_lang);
1217                         if (info)
1218                             load_in_ime = info->load_in_ime;
1219                     }
1220
1221                     if (ui->get_shift_state() != SCL_SHIFT_STATE_LOCK) {
1222                         ui->set_shift_state(SCL_SHIFT_STATE_LOCK);
1223                         if (load_in_ime)
1224                             ime_send_imengine_event(MVK_Shift_Lock, 0);
1225                         else
1226                             engine_loader_send_imengine_event(MVK_Shift_Lock, 0);
1227                     } else {
1228                         ui->set_shift_state(SCL_SHIFT_STATE_OFF);
1229                         if (load_in_ime)
1230                             ime_send_imengine_event(MVK_Shift_Off, 0);
1231                         else
1232                             engine_loader_send_imengine_event(MVK_Shift_Off, 0);
1233                     }
1234                     //g_need_send_shift_event = TRUE;
1235                 } else if (strncmp(event_desc.key_value, delete_all, strlen(delete_all)) == 0) {
1236                     ime_delete_surrounding_text((INT_MAX / 2) * -1, INT_MAX);
1237                 } else if (strncmp(event_desc.key_value, hide_panel, strlen(hide_panel)) == 0) {
1238                     ise_hide();
1239                     ime_request_hide();
1240                 } else if (event_desc.key_event) {
1241                     if (keyboard_state->layout == ISE_LAYOUT_STYLE_VOICE) {
1242                         ise_stt_stop();
1243                     }
1244 #ifdef _WEARABLE
1245                     if (event_desc.key_event == MVK_Done) {
1246                         LOGD("ENTER");
1247                         //commit the preedit string first
1248                         ise_send_event(event_desc.key_event, KEY_MASK_NULL);
1249                     }
1250 #endif
1251                     ise_send_event(event_desc.key_event, KEY_MASK_NULL);
1252                     if (event_desc.key_event == MVK_Shift_L) {
1253                         g_need_send_shift_event = TRUE;
1254                     }
1255                 }
1256                 break;
1257            }
1258         case KEY_TYPE_MODECHANGE:
1259 #ifdef _MOBILE
1260             if (_guide_popup_setting != NULL) {//popup is showing
1261                 break;
1262             }
1263 #endif
1264             if (strcmp(event_desc.key_value, USER_VOICE_LANGUAGE) == 0) {
1265                 if (!get_setting_window_open_status()) {
1266                     ise_hide_stt_mode();
1267 #ifdef _WEARABLE
1268                     hide_indicator_window();
1269 #endif
1270                     create_setting_window();
1271                 }
1272             } else if (strcmp(event_desc.key_value, USER_KEYSTRING_VOICE) == 0) {
1273                 keyboard_state->layout = ISE_LAYOUT_STYLE_VOICE;
1274                 ui->set_input_mode("STT_3X4");
1275
1276             } else if (strcmp(event_desc.key_value, USER_KEYSTRING_OPTION) == 0) {
1277                 launch_option();
1278
1279                 ret = SCL_EVENT_DONE;
1280             } else if (strcmp(event_desc.key_value, USER_KEYSTRING_CLIPBOARD) == 0) {
1281                 show_cbhm();
1282
1283                 ret = SCL_EVENT_DONE;
1284             } else if (strcmp(event_desc.key_value, USER_KEYSTRING_FLOATING) == 0) {
1285                 CONFIG_VALUES *config_values = get_config_values();
1286
1287                 if (g_floating_mode) {
1288                     if (config_values) {
1289                         config_values->floating_mode = false;
1290                     }
1291                 } else {
1292                     if (config_values) {
1293                         config_values->floating_mode = true;
1294                     }
1295                 }
1296                 write_ise_config_values();
1297
1298                 ret = SCL_EVENT_DONE;
1299             } else if (on_input_mode_changed(event_desc.key_value, event_desc.key_event, event_desc.key_type)) {
1300                 ret = SCL_EVENT_DONE;
1301             }
1302             if (_cm_popup_opened) {
1303                 if (strcmp(event_desc.key_value, USER_KEYSTRING_EMOTICON) == 0 ||
1304                     strcmp(event_desc.key_value, USER_KEYSTRING_VOICE) == 0 ||
1305                     strcmp(event_desc.key_value, USER_KEYSTRING_FLOATING) == 0) {
1306                     scluint id = ise_get_cm_key_id(event_desc.key_value);
1307                     if (id != _current_cm_key_id) {
1308                         _current_cm_key_id = id;
1309                         ise_set_cm_private_key(_current_cm_key_id);
1310                     }
1311                 }
1312                 _cm_popup_opened = FALSE;
1313             }
1314             if (strlen(event_desc.key_value) == 1) {
1315                 const char allowed_chars_in_modechange[] = {
1316                     ',', '?', '!', '`', '~'
1317                 };
1318                 const int allowed_chars_in_modechange_num =
1319                     sizeof(allowed_chars_in_modechange) / sizeof(char);
1320                 for (unsigned int loop = 0;loop < sizeof(allowed_chars_in_modechange_num);loop++) {
1321                     if (*(event_desc.key_value) == allowed_chars_in_modechange[loop]) {
1322                         ise_send_string(event_desc.key_value);
1323                     }
1324                 }
1325             }
1326             break;
1327         case KEY_TYPE_USER:
1328             if (strcmp(event_desc.key_value, USER_KEYSTRING_OPTION) == 0) {
1329                 //open_option_window(NULL, ROTATION_TO_DEGREE(ui->get_rotation()));
1330                 launch_option();
1331
1332                 ret = SCL_EVENT_DONE;
1333             } else if (strcmp(event_desc.key_value, USER_KEYSTRING_CLIPBOARD) == 0) {
1334                 show_cbhm();
1335                 ret = SCL_EVENT_DONE;
1336             } else if (strcmp(event_desc.key_value, "Cancel") == 0) {
1337                 ret = SCL_EVENT_DONE;
1338                 const sclchar *input_mode = ui->get_input_mode();
1339                 if (input_mode && strcmp(input_mode, "STT_3X4") == 0 ) {
1340                     keyboard_state->need_reset = TRUE;
1341                     voice_result_string_flush();
1342                     ise_set_layout(keyboard_state->layout, keyboard_state->layout_variation);
1343                     if (keyboard_state->visible_state)
1344                         ise_show(keyboard_state->ic);
1345                 }
1346 #ifdef _TV
1347                 ise_send_event(IME_KEY_Cancel, KEY_MASK_NULL);
1348                 ime_request_hide();
1349 #endif
1350             }  else if (strcmp(event_desc.key_value, "Done") == 0) {
1351 #ifdef _TV
1352                 ret = SCL_EVENT_DONE;
1353                 ise_send_event(IME_KEY_Return, KEY_MASK_NULL);
1354                 ime_request_hide();
1355 #endif
1356             }  else {
1357                 const sclchar *input_mode = ui->get_input_mode();
1358                 if ((NULL != input_mode) && (!strcmp(input_mode, "EMOTICON_LAYOUT"))) {
1359                     if (ise_emoticon_is_show()) {
1360                         ise_emoticon_destroy_layout();
1361                     }
1362 #ifdef _WEARABLE
1363                     emoticon_group_t group_id = EMOTICON_GROUP_1;
1364                     if (ise_emoticon_get_current_group() < EMOTICON_GROUP_3)
1365                         group_id = (emoticon_group_t)(ise_emoticon_get_current_group() + 1);
1366
1367                     ise_set_emoticon_label(group_id);
1368 #else
1369                     emoticon_group_t group_id = ise_emoticon_get_group_id(event_desc.key_value);
1370 #endif
1371                     if ((group_id >= 0) && (group_id < MAX_EMOTICON_GROUP)) {
1372                         SCLRotation rotation = ui->get_rotation();
1373                         ise_emoticon_show_layout(group_id, ROTATION_TO_DEGREE(rotation), false, ime_get_main_window());
1374                     }
1375                 }
1376             }
1377             if (_cm_popup_opened) {
1378                 if (strcmp(event_desc.key_value, USER_KEYSTRING_OPTION) == 0 ||
1379                     strcmp(event_desc.key_value, USER_KEYSTRING_CLIPBOARD) == 0) {
1380                     scluint id = ise_get_cm_key_id(event_desc.key_value);
1381                     if (id != _current_cm_key_id) {
1382                         _current_cm_key_id = id;
1383                         ise_set_cm_private_key(_current_cm_key_id);
1384                     }
1385                 }
1386                 _cm_popup_opened = FALSE;
1387             }
1388             break;
1389         default:
1390             break;
1391         }
1392     }
1393
1394     return ret;
1395 }
1396
1397 void
1398 ise_set_layout(sclu32 layout, sclu32 layout_variation)
1399 {
1400     /* Check if the layoutIdx is in the valid range */
1401     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1402     if (layout < ISE_LAYOUT_STYLE_MAX) {
1403         if (keyboard_state->layout != layout ||
1404             keyboard_state->layout_variation != layout_variation) {
1405             keyboard_state->need_reset = TRUE;
1406         }
1407         keyboard_state->layout = layout;
1408         keyboard_state->layout_variation = layout_variation;
1409         LOGD("layout:%d, variation:%d\n", keyboard_state->layout, keyboard_state->layout_variation);
1410     }
1411 }
1412
1413 void
1414 ise_reset_context()
1415 {
1416     LOGD("");
1417     _reset_multitap_state(true);
1418     CONFIG_VALUES *config_values = get_config_values();
1419     if (config_values) {
1420         _language_manager.reset_language(config_values->selected_language.c_str());
1421     }
1422 }
1423
1424 void
1425 ise_reset_input_context()
1426 {
1427     LOGD("");
1428     _reset_multitap_state(true);
1429     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1430     if (keyboard_state) keyboard_state->disable_force_latin = FALSE;
1431     CONFIG_VALUES *config_values = get_config_values();
1432     if (config_values) {
1433         _language_manager.reset_language(config_values->selected_language.c_str());
1434     }
1435 }
1436
1437 void
1438 ise_focus_in(int ic)
1439 {
1440     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1441     if (!keyboard_state) return;
1442
1443     LOGD("ic : %x , %x , g_ic : %x , %x, g_focused_ic : %x , %x\n", ic, check_ic_temporary(ic),
1444             keyboard_state->ic, check_ic_temporary(keyboard_state->ic),
1445             keyboard_state->focused_ic, check_ic_temporary(keyboard_state->focused_ic));
1446     if (check_ic_temporary(keyboard_state->ic) && !check_ic_temporary(ic)) {
1447         keyboard_state->ic = ic;
1448     }
1449     keyboard_state->focused_ic = ic;
1450 }
1451
1452 static void save_autofill_data()
1453 {
1454     char *text = NULL;
1455     int cursor;
1456
1457     if (g_autofill_hint == 0)
1458         return;
1459
1460     ime_get_surrounding_text(-1, -1, &text, &cursor);
1461     SECURE_LOGD("surrounding text : %s\n", text);
1462     if (!text) return;
1463
1464     autofill_save_string(g_app_id.c_str(), g_resource_id.c_str(), (Ecore_IMF_Input_Hints)g_autofill_hint, text);
1465
1466     free(text);
1467 }
1468
1469 void
1470 ise_focus_out(int ic)
1471 {
1472     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1473     if (keyboard_state) keyboard_state->focused_ic = 0;
1474     _reset_multitap_state(true);
1475
1476     save_autofill_data();
1477 }
1478
1479 bool ise_is_guideline_popup_enable_layout(void)
1480 {
1481     bool ret;
1482     switch (_context_layout)
1483     {
1484         case ISE_LAYOUT_STYLE_PHONENUMBER:
1485         case ISE_LAYOUT_STYLE_IP:
1486         case ISE_LAYOUT_STYLE_MONTH:
1487         case ISE_LAYOUT_STYLE_NUMBERONLY:
1488         case ISE_LAYOUT_STYLE_HEX:
1489         case ISE_LAYOUT_STYLE_TERMINAL:
1490         case ISE_LAYOUT_STYLE_DATETIME:
1491         case ISE_LAYOUT_STYLE_PASSWORD:
1492             ret = false;
1493             break;
1494         default:
1495             ret = true;
1496             break;
1497     }
1498     return ret;
1499 }
1500
1501 #if EXIT_ISE_ON_HIDE
1502 static Eina_Bool exit_timer_cb(void *data)
1503 {
1504     if (exit_timer) ecore_timer_del(exit_timer);
1505     exit_timer = NULL;
1506     elm_exit();
1507     return ECORE_CALLBACK_CANCEL;
1508 }
1509 #endif
1510
1511 void
1512 ise_show(int ic)
1513 {
1514     CONFIG_VALUES *config_values = get_config_values();
1515 #if EXIT_ISE_ON_HIDE
1516     if (exit_timer) ecore_timer_del(exit_timer);
1517     exit_timer = NULL;
1518 #endif
1519     sclboolean reset_inputmode = FALSE;
1520     g_input_panel_show = true;
1521
1522     CSCLUI *ui = get_ui();
1523     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1524     if (ui && keyboard_state) {
1525         read_ise_config_values();
1526
1527         if (config_values) {
1528             _language_manager.set_enabled_languages(config_values->enabled_languages);
1529         }
1530         const sclchar *cur_lang = _language_manager.get_current_language();
1531
1532 #ifdef _WEARABLE
1533         ise_check_wearable_candidate();
1534         /*
1535          *Clear the personalized data
1536          */
1537         if (config_values && config_values->dataclear) {
1538             ime_send_key_event(IME_KEY_Clear, IME_KEY_MASK_CONTROL, false);
1539             config_values->dataclear = FALSE;
1540         }
1541 #endif
1542         LOGD("ic : %x , %x , g_ic : %x , %x, g_focused_ic : %x , %x\n", ic, check_ic_temporary(ic),
1543                 keyboard_state->ic, check_ic_temporary(keyboard_state->ic),
1544                 keyboard_state->focused_ic, check_ic_temporary(keyboard_state->focused_ic));
1545
1546         if (check_ic_temporary(ic) && !check_ic_temporary(keyboard_state->focused_ic)) {
1547             ic = keyboard_state->focused_ic;
1548         }
1549
1550         if (!check_ic_temporary(ic) && check_ic_temporary(keyboard_state->focused_ic)) {
1551             keyboard_state->focused_ic = ic;
1552         }
1553
1554         if (ic == keyboard_state->focused_ic) {
1555             if (keyboard_state->layout == ISE_LAYOUT_STYLE_PHONENUMBER ||
1556                 keyboard_state->layout == ISE_LAYOUT_STYLE_IP ||
1557                 keyboard_state->layout == ISE_LAYOUT_STYLE_MONTH ||
1558                 keyboard_state->layout == ISE_LAYOUT_STYLE_NUMBERONLY) {
1559                 ime_set_engine_loader_flag(true);
1560                 engine_loader_set_imengine(DEFAULT_KEYBOARD_ISE_UUID, DEFAULT_KEYBOARD_ISE_PKGID);
1561             }
1562         }
1563
1564         const char *input_mode = ui->get_input_mode();
1565
1566         /* Reset input mode if the input context value has changed */
1567         if (ic != keyboard_state->ic) {
1568             /* Do not reset input mode if STT's setting window was opened */
1569             if (get_setting_window_open_status() && input_mode && strcmp(input_mode, "STT_3X4") == 0) {
1570                 LOGD("Setting window was opened while using STT, skip resetting input mode");
1571             } else {
1572                 reset_inputmode = TRUE;
1573             }
1574         }
1575
1576         keyboard_state->ic = ic;
1577         /* Reset input mode if the current language is not the selected language */
1578         if (cur_lang) {
1579             if (config_values && config_values->selected_language.compare(cur_lang) != 0) {
1580                 reset_inputmode = TRUE;
1581             }
1582         }
1583
1584         /* No matter what, just reset the inputmode if it needs to */
1585         if (keyboard_state->need_reset) {
1586             /* Do not reset input mode if STT's setting window was opened */
1587             if (get_setting_window_open_status() && input_mode && strcmp(input_mode, "STT_3X4") == 0) {
1588                 LOGD("Setting window was opened while using STT, skip resetting input mode");
1589             } else {
1590                 reset_inputmode = TRUE;
1591             }
1592         }
1593         keyboard_state->need_reset = FALSE;
1594
1595         /* If the current layout requires latin language and current our language is not latin, enable the primary latin */
1596         sclboolean force_primary_latin = FALSE;
1597         LANGUAGE_INFO *info =
1598             (config_values ? _language_manager.get_language_info(config_values->selected_language.c_str()) : NULL);
1599         if (info) {
1600             if (g_ise_default_values[keyboard_state->layout].force_latin && !(info->is_latin_language)) {
1601                 if (!keyboard_state->disable_force_latin) {
1602                     force_primary_latin = TRUE;
1603                 }
1604             }
1605         }
1606         if (force_primary_latin) {
1607             /* If there is enabled latin-based language, select it */
1608             sclboolean selected = FALSE;
1609             for (scluint loop = 0;!selected && loop < _language_manager.get_languages_num();loop++) {
1610                 LANGUAGE_INFO *info = _language_manager.get_language_info(loop);
1611                 if (info) {
1612                     if (info->enabled && info->is_latin_language) {
1613                         selected = _language_manager.select_language(info->name.c_str());
1614                         if (selected) force_primary_latin = FALSE;
1615                     }
1616                 }
1617             }
1618             if (!selected) {
1619                 _language_manager.set_language_enabled_temporarily(PRIMARY_LATIN_LANGUAGE, TRUE);
1620             }
1621         }
1622
1623         if (reset_inputmode) {
1624             ise_reset_context();
1625
1626             bool filename_layout = false;
1627
1628             /* Turn the shift state off if we need to reset our input mode, only when auto-capitalization is not set  */
1629             if (!(keyboard_state->caps_mode)) {
1630                 ui->set_shift_state(SCL_SHIFT_STATE_OFF);
1631             }
1632             if (keyboard_state->layout < ISE_LAYOUT_STYLE_MAX) {
1633                 sclu32 layout_index = keyboard_state->layout;
1634                 if (keyboard_state->layout == ISE_LAYOUT_STYLE_NUMBERONLY &&
1635                     keyboard_state->layout_variation > 0 &&
1636                     keyboard_state->layout_variation < ISE_LAYOUT_NUMBERONLY_VARIATION_MAX) {
1637                     layout_index = ISE_LAYOUT_STYLE_NUMBERONLY_SIG + keyboard_state->layout_variation - 1;
1638                 } else if (keyboard_state->layout == ISE_LAYOUT_STYLE_PASSWORD && keyboard_state->layout_variation > 0) {
1639                     layout_index = ISE_LAYOUT_STYLE_PASSWD_3X4;
1640                 }
1641
1642                 if (keyboard_state->layout == ISE_LAYOUT_STYLE_NORMAL &&
1643                     keyboard_state->layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1644                     filename_layout = true;
1645                 else
1646                     filename_layout = false;
1647
1648                 ui->enable_button("exclamation", !filename_layout);
1649                 ui->enable_button("question", !filename_layout);
1650                 ui->enable_button("divide", !filename_layout);
1651                 ui->enable_button("multiply", !filename_layout);
1652                 ui->enable_button("colon", !filename_layout);
1653                 ui->enable_button("quotation", !filename_layout);
1654
1655                 ui->enable_button("CM_KEY", !access("/home", X_OK));
1656
1657                 LOGD("new layout index : %d\n", layout_index);
1658                 /* If this layout requires specific input mode, set it */
1659                 if (strlen(g_ise_default_values[layout_index].input_mode) > 0) {
1660                     ui->set_input_mode(g_ise_default_values[layout_index].input_mode);
1661                     set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_NONE);
1662                 } else {
1663                     if (force_primary_latin) {
1664                         _language_manager.select_language(PRIMARY_LATIN_LANGUAGE, TRUE);
1665                     } else if (config_values) {
1666                         if (!(_language_manager.select_language(config_values->selected_language.c_str()))) {
1667                             _language_manager.select_language(PRIMARY_LATIN_LANGUAGE);
1668                         }
1669                     }
1670                 }
1671                 ui->set_cur_sublayout(g_ise_default_values[layout_index].sublayout_name);
1672                 if (ise_emoticon_is_show()) {
1673                     ise_emoticon_destroy_layout();
1674                 }
1675
1676                 if (keyboard_state->layout == ISE_LAYOUT_STYLE_EMOTICON) {
1677                     ise_emoticon_init_list();
1678 #ifdef _WEARABLE
1679                     ise_emoticon_set_current_group(EMOTICON_GROUP_1);
1680                     ise_set_emoticon_label(1);
1681 #else
1682                     if (ise_emoticon_get_recent_list_size() == 0)
1683                         ise_emoticon_set_current_group(EMOTICON_GROUP_1);
1684                     else
1685                         ise_emoticon_set_current_group(EMOTICON_GROUP_RECENTLY_USED);
1686 #endif
1687                     SCLRotation rotation = ui->get_rotation();
1688                     ise_emoticon_show_layout(ise_emoticon_get_current_group(), ROTATION_TO_DEGREE(rotation), false, ime_get_main_window());
1689                 }
1690             }
1691         }
1692
1693         if (info) {
1694             if (info->accepts_caps_mode) {
1695                 // FIXME this if condition means the AC is off
1696                 if (keyboard_state->layout != ISE_LAYOUT_STYLE_NORMAL) {
1697                     ui->set_autocapital_shift_state(TRUE);
1698                     ui->set_shift_state(SCL_SHIFT_STATE_OFF);
1699                 } else {
1700                     ise_send_event(MVK_Shift_Enable, KEY_MASK_NULL);
1701                     // Auto Capital is supported only in normal layout
1702                     if (keyboard_state->caps_mode) {
1703                         ui->set_autocapital_shift_state(FALSE);
1704                     }
1705                 }
1706             } else {
1707                 ui->set_autocapital_shift_state(TRUE);
1708                 ise_send_event(MVK_Shift_Disable, KEY_MASK_NULL);
1709                 ui->set_shift_state(SCL_SHIFT_STATE_OFF);
1710             }
1711         } else {
1712             ui->set_autocapital_shift_state(TRUE);
1713         }
1714
1715         // Update CM key button
1716         if (_current_cm_key_id < CM_KEY_LIST_SIZE) {
1717             if (strcmp(_cm_key_list[_current_cm_key_id], USER_KEYSTRING_EMOTICON) == 0) {
1718                 if (ise_is_emoticons_disabled())
1719                     ise_set_cm_private_key(ise_get_cm_key_id(USER_KEYSTRING_OPTION));
1720                 else
1721                     ise_set_cm_private_key(_current_cm_key_id);
1722             }
1723         }
1724
1725         // Update space key button
1726         ise_update_space_key();
1727
1728         ui->show();
1729         ui->disable_input_events(FALSE);
1730 #ifdef _IVI
1731         ui->enable_button("CM_KEY", false);
1732 #endif
1733
1734 #ifdef _MOBILE
1735         if (ise_is_guideline_popup_enable_layout()) {
1736             if ((config_values && config_values->first_guidechange) && (_language_manager.get_enabled_languages_num() > 1)) {
1737                 ise_show_help_popup(MVK_space);
1738                 LOGD("space popup show\n");
1739             } else {
1740                 ise_destory_popup_space();
1741             }
1742         }
1743 #endif
1744
1745         // Update IME size
1746         if (config_values && config_values->floating_mode != g_floating_mode)
1747             g_floating_mode = config_values->floating_mode;
1748
1749         Candidate *candidate = get_candidate();
1750         if (candidate && candidate->get_visible())
1751             set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_SHOW);
1752         else
1753             set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_NONE);
1754     }
1755
1756     keyboard_state->visible_state = TRUE;
1757
1758 #ifdef _WEARABLE
1759     int dot_num = 5;
1760     switch (_context_layout) {
1761         case ISE_LAYOUT_STYLE_PHONENUMBER:
1762         case ISE_LAYOUT_STYLE_IP:
1763         case ISE_LAYOUT_STYLE_MONTH:
1764         case ISE_LAYOUT_STYLE_NUMBERONLY:
1765         case ISE_LAYOUT_STYLE_DATETIME:
1766         case ISE_LAYOUT_STYLE_TERMINAL:
1767             dot_num = 0;
1768             break;
1769         case ISE_LAYOUT_STYLE_EMAIL:
1770         case ISE_LAYOUT_STYLE_URL:
1771             dot_num = 4;
1772             break;
1773         case ISE_LAYOUT_STYLE_PASSWORD:
1774             if (_context_layout == ISE_LAYOUT_STYLE_PASSWORD &&
1775                 _context_layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1776                 dot_num = 0;
1777             else
1778                 dot_num = 3;
1779             break;
1780         default:
1781             dot_num = 5;
1782     }
1783
1784     if (dot_num > 0) {
1785         sclint width = 0;
1786         sclint height = 0;
1787         if (ui)
1788             ui->get_screen_resolution(&width, &height);
1789
1790         create_indicator_window(width, height);
1791         destroy_indicator_dots();
1792
1793         int focus_dot = 0;
1794         switch (keyboard_state->layout) {
1795             case ISE_LAYOUT_STYLE_NUMBER:
1796                 focus_dot = 1;
1797                 break;
1798             case ISE_LAYOUT_STYLE_HEX:
1799                 focus_dot = 2;
1800                 break;
1801             case ISE_LAYOUT_STYLE_EMOTICON:
1802                 focus_dot = 3;
1803                 break;
1804             case ISE_LAYOUT_STYLE_VOICE:
1805                 if (_context_layout == ISE_LAYOUT_STYLE_EMAIL ||
1806                     _context_layout == ISE_LAYOUT_STYLE_URL)
1807                     focus_dot = 3;
1808                 else
1809                     focus_dot = 4;
1810                 break;
1811             default:
1812                 break;
1813         }
1814
1815         create_indicator_dots(dot_num, focus_dot);
1816         show_indicator_window();
1817     } else {
1818         hide_indicator_window();
1819     }
1820     if (keyboard_state->layout == ISE_LAYOUT_STYLE_NORMAL && config_values && config_values->number_tutorial_enable) {
1821         ise_show_tutorial_mode_popup(keyboard_state->layout);
1822         config_values->number_tutorial_enable = false;
1823         write_ise_config_values();
1824     }
1825 #endif
1826
1827     if (get_setting_window_open_status()) {
1828         ise_show_stt_mode(NATIVE_WINDOW_CAST(ime_get_main_window()));
1829     }
1830     set_setting_window_open_status(FALSE);
1831
1832     if (keyboard_state->layout == ISE_LAYOUT_STYLE_VOICE) {
1833         ise_show_stt_mode(NATIVE_WINDOW_CAST(ime_get_main_window()));
1834     }
1835 }
1836
1837 /**
1838  * Sets screen rotation
1839  */
1840 void
1841 ise_set_screen_rotation(int degree)
1842 {
1843     CSCLUI *ui = get_ui();
1844     if (ui) {
1845         ui->set_rotation(DEGREE_TO_SCLROTATION(degree));
1846     }
1847
1848     Candidate *candidate = get_candidate();
1849     if (candidate) {
1850         candidate->rotate(degree);
1851         if (g_softcandidate_show) {
1852             candidate->update(g_softcandidate_string);
1853         }
1854     }
1855 }
1856
1857 void
1858 ise_set_accessibility_state(bool state)
1859 {
1860     CSCLUI *ui = get_ui();
1861     if (ui) {
1862         ui->enable_tts(state);
1863     }
1864 }
1865
1866 void
1867 ise_hide()
1868 {
1869     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
1870     CSCLUI *ui = get_ui();
1871     if (ui) {
1872         /* There's no need to update screen when hiding */
1873         ui->set_update_pending(TRUE);
1874         ui->disable_input_events(TRUE);
1875         ui->hide();
1876     }
1877     CONFIG_VALUES *config_values = get_config_values();
1878     if (config_values) {
1879         _language_manager.reset_language(config_values->selected_language.c_str());
1880     }
1881
1882     _click_count = 0;
1883     delete_commit_timer();
1884     ise_destory_popup_space();
1885     ise_destory_popup_setting();
1886
1887     if (keyboard_state) keyboard_state->visible_state = FALSE;
1888
1889     _reset_shift_state();
1890     _reset_multitap_state(true);
1891
1892     /* If we were in STT mode, try to reset input mode on our next show event */
1893     if (ui && keyboard_state) {
1894         const char *inputmode = ui->get_input_mode();
1895         if (inputmode && strcmp(inputmode, "STT_3X4") == 0 ) {
1896             keyboard_state->need_reset = TRUE;
1897             ise_hide_stt_mode();
1898         }
1899     }
1900
1901     g_input_panel_show = false;
1902     if (g_softcandidate_show && get_candidate())
1903         set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_SHOW);
1904 #ifdef _WEARABLE
1905     hide_indicator_window();
1906     if (check_is_tutorial_show()) {
1907         ise_destroy_tutorial_mode_popup();
1908     }
1909 #endif
1910 #if EXIT_ISE_ON_HIDE
1911     if (exit_timer) ecore_timer_del(exit_timer);
1912     exit_timer = ecore_timer_add(1.0, exit_timer_cb, NULL);
1913 #endif
1914 }
1915
1916 static void ise_keypad_mode_changed_cb(const char *key, void *user_data)
1917 {
1918     read_ise_keypad_mode();
1919 }
1920
1921 static void ise_enabled_languages_changed_cb(const char *key, void *user_data)
1922 {
1923     read_ise_enabled_languages();
1924 }
1925
1926 static void ise_selected_language_changed_cb(const char *key, void *user_data)
1927 {
1928     read_ise_selected_language();
1929 }
1930
1931 static void ise_autocapital_mode_changed_cb(const char *key, void *user_data)
1932 {
1933     read_ise_autocapital_mode();
1934 }
1935
1936 static void ise_autopunctuate_mode_changed_cb(const char *key, void *user_data)
1937 {
1938     read_ise_autopunctuation_mode();
1939 }
1940
1941 static void ise_sound_mode_changed_cb(const char *key, void *user_data)
1942 {
1943     read_ise_sound_mode();
1944
1945     CONFIG_VALUES *config_values = get_config_values();
1946     CSCLUI *ui = get_ui();
1947     if (config_values && ui) {
1948         ui->enable_sound(config_values->sound_on);
1949     }
1950 }
1951
1952 static void ise_vibration_mode_changed_cb(const char *key, void *user_data)
1953 {
1954     read_ise_vibration_mode();
1955
1956     CONFIG_VALUES *config_values = get_config_values();
1957     CSCLUI *ui = get_ui();
1958     if (config_values && ui) {
1959         ui->enable_vibration(config_values->vibration_on);
1960     }
1961 }
1962
1963 static void ise_character_preview_mode_changed_cb(const char *key, void *user_data)
1964 {
1965     read_ise_character_preview_mode();
1966
1967     CONFIG_VALUES *config_values = get_config_values();
1968     CSCLUI *ui = get_ui();
1969     if (config_values && ui) {
1970         ui->enable_magnifier(config_values->preview_on);
1971     }
1972 }
1973
1974 static void ise_setting_guide_popup_changed_cb(const char *key, void *user_data)
1975 {
1976     read_ise_setting_guide_popup_mode();
1977 }
1978
1979 static void ise_language_guide_popup_changed_cb(const char *key, void *user_data)
1980 {
1981     read_ise_language_guide_popup_mode();
1982 }
1983
1984 static void ise_floating_mode_changed_cb(const char *key, void *user_data)
1985 {
1986     read_ise_floating_mode();
1987     CONFIG_VALUES *config_values = get_config_values();
1988     if (config_values) {
1989         g_floating_mode = config_values->floating_mode;
1990     }
1991
1992     ime_set_floating_mode(g_floating_mode);
1993     if (g_candidate && g_floating_mode != g_candidate->get_floating_mode()) {
1994         delete_softcandidate_hide_timer();
1995         delete g_candidate;
1996         g_candidate = NULL;
1997
1998         create_softcandidate();
1999         if (g_candidate && g_candidate->get_visible()) {
2000             g_softcandidate_show = true;
2001             g_candidate->show();
2002             set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_SHOW);
2003             return;
2004         }
2005     }
2006     set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_NONE);
2007 }
2008
2009 static void register_preference_changed_callback(void)
2010 {
2011     if (preference_set_changed_cb(ISE_CONFIG_KEYPAD_MODE, ise_keypad_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2012         LOGW("Failed to set ise_keypad_mode_changed_cb()");
2013
2014     if (preference_set_changed_cb(ISE_CONFIG_ENABLED_LANGUAGES, ise_enabled_languages_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2015         LOGW("Failed to set ise_enabled_languages_changed_cb()");
2016
2017     if (preference_set_changed_cb(ISE_CONFIG_SELECTED_LANGUAGE, ise_selected_language_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2018         LOGW("Failed to set ise_selected_language_changed_cb()");
2019
2020     if (preference_set_changed_cb(ISE_CONFIG_AUTO_CAPITALISE, ise_autocapital_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2021         LOGW("Failed to set ise_autocapital_mode_changed_cb()");
2022
2023     if (preference_set_changed_cb(ISE_CONFIG_AUTO_PUNCTUATE, ise_autopunctuate_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2024         LOGW("Failed to set ise_autopunctuate_mode_changed_cb()");
2025
2026     if (preference_set_changed_cb(ISE_CONFIG_SOUND_ON, ise_sound_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2027         LOGW("Failed to set ise_sound_mode_changed_cb()");
2028
2029     if (preference_set_changed_cb(ISE_CONFIG_VIBRATION_ON, ise_vibration_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2030         LOGW("Failed to set ise_vibration_mode_changed_cb()");
2031
2032     if (preference_set_changed_cb(ISE_CONFIG_PREVIEW_ON, ise_character_preview_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2033         LOGW("Failed to set ise_character_preview_mode_changed_cb()");
2034
2035     if (preference_set_changed_cb(ISE_CONFIG_FIRST_GUIDELINE_POPUP_FOR_SETTING, ise_setting_guide_popup_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2036         LOGW("Failed to set ise_setting_guide_popup_changed_cb()");
2037
2038     if (preference_set_changed_cb(ISE_CONFIG_FIRST_GUIDELINE_POPUP_FOR_LANGUAGE_CHANGE, ise_language_guide_popup_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2039         LOGW("Failed to set ise_language_guide_popup_changed_cb()");
2040
2041     if (preference_set_changed_cb(ISE_CONFIG_FLOATING_MODE, ise_floating_mode_changed_cb, NULL) != PREFERENCE_ERROR_NONE)
2042         LOGW("Failed to set ise_floating_mode_changed_cb()");
2043 }
2044
2045 static void ise_mount_changed_cb(void *user_data)
2046 {
2047     register_preference_changed_callback();
2048 }
2049
2050 void
2051 ise_create()
2052 {
2053     LOGD("");
2054
2055     CONFIG_VALUES *config_values = get_config_values();
2056
2057     if (!g_ui) {
2058         g_ui = new CSCLUI;
2059     }
2060
2061     bindtextdomain(PACKAGE, LOCALEDIR);
2062     textdomain(PACKAGE);
2063
2064     /* Set scl_parser_type
2065      * default type is text xml
2066      * use command: export sclres_type="sclres_binary" to enable use binary resource
2067      * please make sure there is sclresource.bin in resource folder
2068      * Or you can use `xml2binary $resource_dir` to generate the sclresource.bin
2069      * xml2binary is in the libscl-ui-devel package
2070      */
2071     SCLParserType scl_parser_type = SCL_PARSER_TYPE_XML;
2072     char* sclres_type = getenv("sclres_type");
2073     if (sclres_type != NULL && 0 == strcmp("sclres_binary", sclres_type)) {
2074         scl_parser_type = SCL_PARSER_TYPE_BINARY_XML;
2075     } else {
2076         scl_parser_type = SCL_PARSER_TYPE_XML;
2077     }
2078
2079     if (g_ui) {
2080         if (ime_get_main_window()) {
2081             g_ise_created = true;
2082
2083             sclboolean succeeded = FALSE;
2084
2085             const sclchar *entry_path = MAIN_ENTRY_XML_PATH;
2086             int nwidth  = 0;
2087             int nheight = 0;
2088             CSCLUtils *utils = CSCLUtils::get_instance();
2089             if (utils) {
2090                 utils->get_screen_resolution(&nwidth, &nheight);
2091             }
2092             _language_manager.set_resource_file_path(entry_path);
2093             const sclchar *resource_file_path = _language_manager.get_resource_file_path();
2094
2095             if (resource_file_path) {
2096                 if (strlen(resource_file_path) > 0) {
2097                     succeeded = g_ui->init(ime_get_main_window(), scl_parser_type, resource_file_path);
2098                 }
2099             }
2100             if (!succeeded) {
2101                 g_ui->init(ime_get_main_window(), scl_parser_type, MAIN_ENTRY_XML_PATH);
2102             }
2103
2104             g_ui->set_longkey_duration(elm_config_longpress_timeout_get() * 1000);
2105
2106             /* Default ISE callback */
2107             g_ui->set_ui_event_callback(&callback);
2108
2109             /* Accumulated customized ISE callbacks, depending on the input modes */
2110             for (scluint loop = 0;loop < _language_manager.get_languages_num();loop++) {
2111                 LANGUAGE_INFO *language = _language_manager.get_language_info(loop);
2112                 if (language) {
2113                     for (scluint inner_loop = 0;inner_loop < language->input_modes.size();inner_loop++) {
2114                         INPUT_MODE_INFO &info = language->input_modes.at(inner_loop);
2115                         LOGD("Registering callback for input mode %s : %p\n", info.name.c_str(), language->callback);
2116                         g_ui->set_ui_event_callback(language->callback, info.name.c_str());
2117                     }
2118                 }
2119             }
2120
2121             read_ise_config_values();
2122             if (config_values) {
2123                 _language_manager.set_enabled_languages(config_values->enabled_languages);
2124                 _language_manager.select_language(config_values->selected_language.c_str());
2125                 vconf_set_bool(VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, config_values->auto_capitalise);
2126                 vconf_set_bool(VCONFKEY_AUTOPERIOD_ALLOW_BOOL, config_values->auto_punctuate);
2127                 g_ui->enable_sound(config_values->sound_on);
2128                 g_ui->enable_vibration(config_values->vibration_on);
2129                 g_ui->enable_magnifier(config_values->preview_on);
2130                 g_floating_mode = config_values->floating_mode;
2131             }
2132 #ifdef _TV
2133             g_ui->enable_highlight_ui(TRUE);
2134 #endif
2135             ime_set_floating_mode(g_floating_mode);
2136         }
2137
2138         set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_NONE);
2139
2140         bool exist = false;
2141
2142         preference_is_existing(ISE_CONFIG_KEYPAD_MODE, &exist);
2143         if (!exist)
2144             write_ise_config_values();
2145
2146         int state;
2147         if (ode_internal_encryption_get_state(&state) == ODE_ERROR_NONE) {
2148             if (state == ODE_STATE_ENCRYPTED) {
2149                 if (ode_internal_encryption_set_mount_event_cb(ise_mount_changed_cb, NULL) != ODE_ERROR_NONE)
2150                     LOGW("Failed to set mount_event_cb()");
2151             } else if (state == ODE_STATE_UNENCRYPTED) {
2152                 register_preference_changed_callback();
2153             }
2154         } else {
2155             LOGW("Failed to get encryption_state");
2156         }
2157     }
2158     init_recent_used_punctuation();
2159 }
2160
2161 void
2162 ise_destroy()
2163 {
2164     ise_hide_stt_mode();
2165
2166     CSCLUI *ui = get_ui();
2167     if (ui) {
2168         LOGD("calling ui->fini()\n");
2169         ui->fini();
2170         LOGD("deleting ui\n");
2171         delete ui;
2172         ui = NULL;
2173     }
2174
2175     if (g_candidate) {
2176         delete g_candidate;
2177         g_candidate = NULL;
2178     }
2179
2180 #ifdef _WEARABLE
2181     destroy_indicator_window();
2182 #endif
2183
2184     /* This is necessary. If this is not called, 3rd party IME might have auto period input regardless its settings */
2185     vconf_set_bool(VCONFKEY_AUTOPERIOD_ALLOW_BOOL, false);
2186
2187 #if EXIT_ISE_ON_HIDE
2188     if (exit_timer) ecore_timer_del(exit_timer);
2189     exit_timer = NULL;
2190 #endif
2191 }
2192
2193 void
2194 ise_app_candidate_show()
2195 {
2196 #ifdef _WEARABLE
2197     if (!g_softcandidate_show) {
2198         return;
2199     }
2200 #endif
2201     LOGD("Enter\n");
2202     delete_softcandidate_hide_timer();
2203
2204     create_softcandidate();
2205
2206     g_softcandidate_show = true;
2207     Candidate *candidate = get_candidate();
2208     if (candidate) {
2209         candidate->show();
2210         set_ime_size(g_floating_mode, ISE_CANDIDATE_REQ_SHOW);
2211     }
2212 }
2213
2214 void
2215 ise_app_candidate_hide()
2216 {
2217     LOGD("Enter\n");
2218
2219     Candidate *candidate = get_candidate();
2220     if (!candidate || !g_softcandidate_show) {
2221         LOGD("No candidate\n");
2222         return;
2223     }
2224
2225     if (g_ic_smartreply != -1 || g_autofill_exist)
2226         return;
2227
2228     add_softcandidate_hide_timer();
2229 }
2230
2231 #ifdef _WEARABLE
2232 void ise_check_wearable_candidate()
2233 {
2234     CONFIG_VALUES *config_values = get_config_values();
2235     if (!config_values) return;
2236
2237     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2238     if (!keyboard_state) return;
2239
2240     if (!config_values->prediction_on) {
2241         ise_app_candidate_hide();
2242     } else if (keyboard_state->layout == ISE_LAYOUT_STYLE_PHONENUMBER ||
2243                   keyboard_state->layout == ISE_LAYOUT_STYLE_VOICE ||
2244                   keyboard_state->layout == ISE_LAYOUT_STYLE_IP ||
2245                   keyboard_state->layout == ISE_LAYOUT_STYLE_MONTH ||
2246                   keyboard_state->layout == ISE_LAYOUT_STYLE_NUMBERONLY ||
2247                   keyboard_state->layout == ISE_LAYOUT_STYLE_PASSWD_3X4||
2248                   keyboard_state->layout == ISE_LAYOUT_STYLE_PASSWORD) {
2249         ise_app_candidate_hide();
2250     } else {
2251         g_softcandidate_show = true;
2252         ise_app_candidate_show();
2253     }
2254 }
2255
2256 void ise_set_emoticon_label(int group_id)
2257 {
2258     const int BUF_LEN = 16;
2259     char buf[BUF_LEN] = {0};
2260     snprintf(buf, BUF_LEN, "%d/3", group_id);
2261     CSCLUI *ui = get_ui();
2262     if (ui) ui->set_private_key("EMOTICON_GROUP_ID", buf, NULL, NULL, 0, const_cast<sclchar*>("EMOTICON_GROUP_NEXT"), TRUE);
2263 }
2264 #endif
2265
2266 // when it is the time to auto_cap, the
2267 // ise_set_caps_mode is called.
2268 // -------------------------------------------------------
2269 // For example: [How are you. Fine.], the
2270 // auto-capital process is as below:
2271 // Note: "["<--this is the beginning,
2272 // "|"<--this is the cursor position
2273 // 1) call ise_set_caps_mode, auto_cap = on
2274 //    input: "H",
2275 //    result: [H|
2276 // 2) call ise_set_caps_mode, auto_cap = off
2277 //    input: "o"
2278 //    result: [Ho|
2279 // 3) input: "w are you. "
2280 //    result: [How are you. |
2281 // 4) call ise_set_caps_mode, auto_cap = on
2282 //    input: "F"
2283 //    result: [How are you. F
2284 // 5) input: "ine."
2285 //    result: [How are you. Fine.|
2286 // --------------------------------------------------------
2287 // If we want to change the auto_cap, eg,
2288 // if we want to input [How Are you.]
2289 // Note the "Are" is not use auto-capital rule.
2290 // we should use:
2291 //    ise_send_event(MVK_Shift_On, SclCoreKeyMask_Null);
2292 // when we are want to input "A"
2293 // following input still has the auto_cap rule.
2294 void
2295 ise_set_caps_mode(unsigned int mode)
2296 {
2297     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2298     if (!keyboard_state) return;
2299
2300     LOGD("caps_mode : %d\n", mode);
2301     if (mode) {
2302         keyboard_state->caps_mode = TRUE;
2303     } else {
2304         keyboard_state->caps_mode = FALSE;
2305     }
2306     g_caps_mode_pending = false;
2307     const sclchar *cur_lang = _language_manager.get_current_language();
2308     if (cur_lang) {
2309         LANGUAGE_INFO *info = _language_manager.get_language_info(cur_lang);
2310         if (info) {
2311             if (info->accepts_caps_mode) {
2312                 /* If we are inputting multitap character, do not manipulate shift mode */
2313                 if (keyboard_state->prev_modifier != KEY_MODIFIER_MULTITAP_START &&
2314                     keyboard_state->prev_modifier != KEY_MODIFIER_MULTITAP_REPEAT) {
2315                     set_caps_mode(keyboard_state->caps_mode);
2316                 } else {
2317                     g_caps_mode_pending = true;
2318                     LOGD("Currently composing multitap string, skipping caps request");
2319                 }
2320             }
2321         }
2322     }
2323 }
2324
2325 void
2326 ise_update_cursor_position(int position)
2327 {
2328     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2329     if (!keyboard_state) return;
2330
2331     LOGD("cursor position : %d\n", position);
2332     CSCLUI *ui = get_ui();
2333     if (ui && keyboard_state->layout == ISE_LAYOUT_STYLE_URL) {
2334 #ifndef _TV
2335         if (position > 0) {
2336             ui->set_string_substitution("www.", ".com");
2337         } else {
2338             ui->unset_string_substitution("www.");
2339         }
2340 #endif
2341     }
2342 }
2343
2344 void ise_set_return_key_type(unsigned int type)
2345 {
2346     const int BUF_LEN = 256;
2347     char buf[BUF_LEN] = {0};
2348
2349     CSCLUI *ui = get_ui();
2350     if (!ui) return;
2351
2352     LOGD("return key type : %d\n", type);
2353     switch (type)
2354     {
2355     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE:
2356         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_DONE);
2357         break;
2358     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO:
2359         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_GO);
2360         break;
2361     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN:
2362         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_JOIN);
2363         break;
2364     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN:
2365         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_LOGIN);
2366         break;
2367     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT:
2368         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_NEXT);
2369         break;
2370     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH:
2371         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_SEARCH);
2372         break;
2373     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND:
2374         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_SEND);
2375         break;
2376     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN:
2377         snprintf(buf, BUF_LEN, ISE_RETURN_KEY_LABEL_SIGNIN);
2378         break;
2379     case ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT:
2380         break;
2381     default:
2382         LOGW("Unknown return key type : %d\n", type);
2383         type = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2384         break;
2385     }
2386
2387     if (type == ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT) {
2388         ui->unset_private_key("Enter");
2389 #ifdef _TV
2390         ui->unset_private_key("Done");
2391 #endif
2392     } else {
2393 #ifdef _WEARABLE
2394         if (type == ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH) {
2395             sclchar* imagelabel[SCL_BUTTON_STATE_MAX] = {
2396                 const_cast<sclchar*>("w_sip_3x4_btn_ic_search.png"),
2397                 const_cast<sclchar*>("w_sip_3x4_btn_ic_search_p.png"),
2398                 const_cast<sclchar*>("w_sip_3x4_btn_ic_search_d.png")};
2399             ui->set_private_key("Enter", const_cast<sclchar*>(""), imagelabel, NULL, 0, const_cast<sclchar*>("Enter"), TRUE);
2400             return;
2401         }
2402 #endif
2403
2404 #ifdef _TV
2405         ui->set_private_key("Done", buf, NULL, NULL, 0, const_cast<sclchar*>("Done"), TRUE);
2406 #else
2407         static sclchar *imagelabel[SCL_BUTTON_STATE_MAX] = {
2408             const_cast<sclchar*>(" "), const_cast<sclchar*>(" "), const_cast<sclchar*>(" ")
2409         };
2410
2411         ui->set_private_key("Enter", buf, imagelabel, NULL, 0, const_cast<sclchar*>("Enter"), TRUE);
2412 #endif
2413         LOGD("return key label : %s\n", buf);
2414     }
2415 }
2416
2417 void ise_set_return_key_disable(unsigned int disabled)
2418 {
2419     CSCLUI *ui = get_ui();
2420     LOGD("enable : %d\n", !disabled);
2421 #ifdef _TV
2422     if (ui)
2423         ui->enable_button("Done", !disabled);
2424 #else
2425     if (ui)
2426         ui->enable_button("Enter", !disabled);
2427 #endif
2428 }
2429
2430 void ise_get_language_locale(char **locale)
2431 {
2432     LANGUAGE_INFO *info = _language_manager.get_current_language_info();
2433     if (info) {
2434         if (!(info->locale_string.empty())) {
2435             *locale = strdup(info->locale_string.c_str());
2436         }
2437     }
2438 }
2439
2440 void ise_update_table(const vector<string> &vec_str)
2441 {
2442     if (!get_candidate() || !g_softcandidate_show) {
2443         create_softcandidate();
2444     }
2445
2446     Candidate *candidate = get_candidate();
2447     if (candidate) {
2448         candidate->update(vec_str);
2449     }
2450 }
2451
2452 void ise_process_key_event(scim::KeyEvent& key, sclu32 &ret)
2453 {
2454     Eina_Bool back_key_pressed = EINA_FALSE;
2455     Eina_Bool back_key_released = EINA_FALSE;
2456
2457     if (key.get_key_string().compare("XF86Back") == 0) {
2458         back_key_pressed = EINA_TRUE;
2459     } else if (key.get_key_string().compare("KeyRelease+XF86Back") == 0) {
2460         back_key_released = EINA_TRUE;
2461     }
2462
2463     if (back_key_pressed || back_key_released) {
2464         if (g_popup_opened == TRUE) {
2465             if (back_key_released) {
2466                 CSCLUI *ui = get_ui();
2467                 if (ui) ui->close_all_popups();
2468             }
2469             ret = 1;
2470             return;
2471         }
2472     }
2473
2474     ret = 0;
2475     CSCLUI *ui = get_ui();
2476 #ifdef _TV
2477     Candidate *candidate = get_candidate();
2478     if (candidate) {
2479         if (!candidate->soft_candidate_flag()) {
2480             if (ui) {
2481                 if (key.dev_name.compare("ime") != 0) {
2482                     ret = (sclu32)ui->process_key_event(key.get_key_string().c_str());
2483                 }
2484             }
2485         }
2486         if (!ret) {
2487             ret = candidate->soft_candidate_handle_key_event(key.get_key_string().c_str());
2488         }
2489     } else {
2490         if (ui) {
2491             /* Process this key event if it was not generated by ime */
2492             if (key.dev_name.compare("ime") != 0) {
2493                 ret = (sclu32)ui->process_key_event(key.get_key_string().c_str());
2494             }
2495         }
2496     }
2497 #else
2498     if (ui) {
2499         /* Process this key event if it was not generated by ime */
2500         if (key.dev_name.compare("ime") != 0) {
2501             ret = (sclu32)ui->process_key_event(key.get_key_string().c_str());
2502         }
2503     }
2504 #endif
2505 }
2506
2507 static void init_recent_used_punctuation()
2508 {
2509     if (g_recent_used_punctuation.empty())
2510     {
2511         g_recent_used_punctuation.push_back("#");
2512         g_recent_used_punctuation.push_back("$");
2513         g_recent_used_punctuation.push_back("%");
2514         g_recent_used_punctuation.push_back("^");
2515         g_recent_used_punctuation.push_back("&");
2516     }
2517 }
2518
2519 static void update_recent_used_punctuation(const char * key_value)
2520 {
2521     if (NULL == key_value)
2522     {
2523         return;
2524     }
2525     for (int i = 0; i < 10; ++i)
2526     {
2527         char buf[5] = {0};
2528         snprintf(buf, sizeof(buf), "%d", i);
2529         if (strcmp(key_value, buf) == 0)
2530         {
2531             return;
2532         }
2533     }
2534     string strKey = string(key_value);
2535     for (int i = 0; i < MAX_DEFAULT_PUNCTUATION; ++i)
2536     {
2537         if (0 == strKey.compare(g_default_punctuation[i].c_str()))
2538         {
2539             return;
2540         }
2541     }
2542     vector<string>::iterator iter = g_recent_used_punctuation.begin();
2543     for (; iter != g_recent_used_punctuation.end(); ++iter)
2544     {
2545         if (0 == strKey.compare(iter->c_str()))
2546         {
2547             break;
2548         }
2549     }
2550     if (iter != g_recent_used_punctuation.end())
2551     {
2552         g_recent_used_punctuation.erase(iter);
2553     }
2554     g_recent_used_punctuation.push_back(strKey);
2555     if (g_recent_used_punctuation.size() > MAX_DEFAULT_PUNCTUATION-1)
2556     {
2557         g_recent_used_punctuation.erase(g_recent_used_punctuation.begin());
2558     }
2559 }
2560
2561 static void set_ime_size(bool floating_mode, ISE_CANDIDATE_REQUEST candidate_req)
2562 {
2563     CSCLUI *ui = get_ui();
2564     if (!ui)
2565         return;
2566
2567     Candidate *candidate = get_candidate();
2568
2569     const char *input_mode = ui->get_input_mode();
2570     if (!input_mode)
2571         return;
2572
2573     SclSize size_portrait = ui->get_input_mode_size(input_mode, DISPLAYMODE_PORTRAIT);
2574     SclSize size_landscape = ui->get_input_mode_size(input_mode, DISPLAYMODE_LANDSCAPE);
2575
2576     if (floating_mode) {
2577         size_portrait.width *= FLOATING_SCALE_RATE;
2578         size_portrait.height *= FLOATING_SCALE_RATE;
2579         size_landscape.width *= FLOATING_SCALE_RATE;
2580         size_landscape.height *= FLOATING_SCALE_RATE;
2581         switch (candidate_req) {
2582             case ISE_CANDIDATE_REQ_NONE:
2583                 if (candidate && candidate->get_visible()) {
2584                     ui->set_custom_starting_coordinates(0, FLOATING_TITLE_BAR_HEIGHT + candidate->get_height());
2585                     size_portrait.height += candidate->get_height();
2586                     size_landscape.height += candidate->get_height();
2587                 } else {
2588                     ui->set_custom_starting_coordinates(0, FLOATING_TITLE_BAR_HEIGHT);
2589                 }
2590                 break;
2591             case ISE_CANDIDATE_REQ_SHOW:
2592                 ui->set_custom_starting_coordinates(0, FLOATING_TITLE_BAR_HEIGHT + candidate->get_height());
2593                 if (g_input_panel_show || g_candidate_more_view) {
2594                     size_portrait.height += candidate->get_height();
2595                     size_landscape.height += candidate->get_height();
2596                 } else {
2597                     size_portrait.height = candidate->get_height();
2598                     size_landscape.height = candidate->get_height();
2599                 }
2600                 break;
2601             case ISE_CANDIDATE_REQ_HIDE:
2602                 ui->set_custom_starting_coordinates(0, FLOATING_TITLE_BAR_HEIGHT);
2603                 break;
2604             default: break;
2605         }
2606
2607         if (ui->get_custom_scale_rate_x() != FLOATING_SCALE_RATE || ui->get_custom_scale_rate_y() != FLOATING_SCALE_RATE)
2608             ui->set_custom_scale_rate(FLOATING_SCALE_RATE, FLOATING_SCALE_RATE);
2609
2610         ime_set_size(size_portrait.width, size_portrait.height + FLOATING_TITLE_BAR_HEIGHT,
2611             size_landscape.width, size_landscape.height + FLOATING_TITLE_BAR_HEIGHT);
2612
2613 #if defined(_MOBILE) || defined(_COMMON)
2614         ise_destroy_move_handler();
2615         int rotation = elm_win_rotation_get(NATIVE_WINDOW_CAST(ime_get_main_window()));
2616         int handler_width = (rotation == 0 || rotation == 180) ? size_portrait.width : size_landscape.width;
2617         ise_show_move_handler(handler_width, FLOATING_TITLE_BAR_HEIGHT);
2618 #endif
2619     } else {
2620         switch (candidate_req) {
2621             case ISE_CANDIDATE_REQ_NONE:
2622                 if (candidate && candidate->get_visible()) {
2623                     ui->set_custom_starting_coordinates(0, candidate->get_height());
2624                     size_portrait.height += candidate->get_height();
2625                     size_landscape.height += candidate->get_height();
2626                 } else {
2627                     ui->set_custom_starting_coordinates(0, 0);
2628                 }
2629                 break;
2630             case ISE_CANDIDATE_REQ_SHOW:
2631                 if (candidate) {
2632                     ui->set_custom_starting_coordinates(0, candidate->get_height());
2633                     if (g_input_panel_show || g_candidate_more_view) {
2634                         size_portrait.height += candidate->get_height();
2635                         size_landscape.height += candidate->get_height();
2636                     } else {
2637                         size_portrait.height = candidate->get_height();
2638                         size_landscape.height = candidate->get_height();
2639                     }
2640                 }
2641                 break;
2642             case ISE_CANDIDATE_REQ_HIDE:
2643                 ui->set_custom_starting_coordinates(0, 0);
2644                 break;
2645             default: break;
2646         }
2647
2648         if (ui->get_custom_scale_rate_x() != 1.0 || ui->get_custom_scale_rate_y() != 1.0)
2649             ui->set_custom_scale_rate(1.0, 1.0);
2650
2651         ime_set_size(size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
2652
2653 #if defined(_MOBILE) || defined(_COMMON)
2654         ise_destroy_move_handler();
2655 #endif
2656     }
2657 }
2658
2659 static void ime_app_create_cb(void *user_data)
2660 {
2661     if (!engine_loader_dbus_init(NULL))
2662         LOGE("Failed to initialize dbus");
2663
2664 #if !(DEFER_ISE_CREATION)
2665     ise_create();
2666 #endif
2667     elm_app_name_set(PACKAGE);
2668
2669     char *elm_scale = getenv("ELM_SCALE");
2670     LOGD("ELM_SCALE : %s", elm_scale);
2671
2672     if (elm_scale)
2673         elm_app_base_scale_set(atof(elm_scale));
2674
2675 #ifdef HAVE_CBHM
2676     cbhm_open_service(&cbhm_handle);
2677 #endif
2678 }
2679
2680 static void ime_app_exit_cb(void *user_data)
2681 {
2682     ise_hide();
2683     ise_destroy();
2684
2685     if (!engine_loader_dbus_shutdown())
2686         LOGE("Failed to finalize dbus");
2687
2688 #ifdef HAVE_CBHM
2689     cbhm_close_service(cbhm_handle);
2690     cbhm_handle = NULL;
2691 #endif
2692 }
2693
2694 static void show_autofill_data(Ecore_IMF_Input_Hints input_hints)
2695 {
2696     g_autofill_exist = false;
2697     char *text = autofill_get_string(g_app_id.c_str(), g_resource_id.c_str(), input_hints);
2698
2699     if (text) {
2700         g_autofill_string = string(text);
2701         free(text);
2702     } else {
2703         g_autofill_string = string("");
2704     }
2705     SECURE_LOGD("autofill string : %s", g_autofill_string.c_str());
2706
2707     if (g_autofill_string.length() > 0) {
2708         g_autofill_exist = true;
2709
2710         ise_app_candidate_show();
2711         update_candidate_table();
2712     }
2713 }
2714
2715 static void ime_app_show_cb(int ic, ime_context_h ime_ctx, void *user_data)
2716 {
2717     Ise_Context iseContext;
2718     bool return_key_state, prediction_allow, password_mode, caps_mode;
2719     ime_layout_variation_e layout_variation;
2720
2721     if (!g_ise_created)
2722         ise_create();
2723
2724     ime_context_get_layout(ime_ctx, &iseContext.layout);
2725
2726     ime_context_get_layout_variation(ime_ctx, &layout_variation);
2727     iseContext.layout_variation =  (int)layout_variation;
2728
2729     ime_context_get_cursor_position(ime_ctx, &iseContext.cursor_pos);
2730     ime_context_get_autocapital_type(ime_ctx, &iseContext.autocapital_type);
2731     ime_context_get_return_key_type(ime_ctx, &iseContext.return_key_type);
2732     ime_context_get_return_key_state(ime_ctx, &return_key_state);
2733
2734     ime_context_get_prediction_mode(ime_ctx, &prediction_allow);
2735     iseContext.prediction_allow = prediction_allow;
2736
2737     ime_context_get_password_mode(ime_ctx, &password_mode);
2738     iseContext.password_mode = password_mode;
2739
2740     ime_context_get_input_hint(ime_ctx, &iseContext.input_hint);
2741     ime_context_get_bidi_direction(ime_ctx, &iseContext.bidi_direction);
2742     ime_context_get_language(ime_ctx, &iseContext.language);
2743     ime_context_get_caps_mode(ime_ctx, &caps_mode);
2744     iseContext.caps_mode = caps_mode;
2745
2746     iseContext.return_key_disabled = return_key_state;
2747
2748     engine_loader_set_input_hint((uint32_t)iseContext.input_hint);
2749     engine_loader_update_bidi_direction((uint32_t)iseContext.bidi_direction);
2750
2751     g_ic = ic;
2752
2753     g_autofill_hint = iseContext.input_hint & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK;
2754
2755     LOGD("input hint : %x, autofill hint : %x\n", iseContext.input_hint, g_autofill_hint);
2756
2757     // show autofill data
2758     show_autofill_data((Ecore_IMF_Input_Hints)g_autofill_hint);
2759
2760     //g_ise_common->set_keyboard_ise_by_uuid(KEYBD_ISE_UUID);
2761
2762     /* Don't update screen until all the information is correctly set */
2763     CSCLUI *ui = get_ui();
2764     if (ui)
2765         ui->set_update_pending(TRUE);
2766
2767     ise_reset_context(); // reset ISE
2768
2769     // if (iseContext.language == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET) {
2770     //     LOGD("alphabet");
2771     //     ise_explictly_set_language(PRIMARY_LATIN_LANGUAGE_INDEX);
2772     // }
2773     // else {
2774     //     LOGD("non-alphabet");
2775     // }
2776
2777     _context_layout = iseContext.layout;
2778     _context_layout_variation = iseContext.layout_variation;
2779     ise_set_layout(iseContext.layout, iseContext.layout_variation);
2780
2781     ise_set_return_key_type(iseContext.return_key_type);
2782     ise_set_return_key_disable(iseContext.return_key_disabled);
2783
2784     ise_set_caps_mode(iseContext.caps_mode);
2785     ise_update_cursor_position(iseContext.cursor_pos);
2786
2787     ise_show(ic);
2788
2789     /* Now we update the whole screen */
2790     if (ui)
2791         ui->set_update_pending(FALSE);
2792 }
2793
2794 static void ime_app_hide_cb(int ic, void *user_data)
2795 {
2796     LOGD("Enter\n");
2797     ise_hide();
2798 #ifdef HAVE_CBHM
2799     g_set_mime_type = FALSE;
2800 #endif
2801     g_ic_smartreply = -1;
2802 }
2803
2804 static void ime_app_return_key_type_set_cb(Ecore_IMF_Input_Panel_Return_Key_Type type, void *user_data)
2805 {
2806     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2807     if (!keyboard_state) return;
2808
2809     LOGD("return key type : %d\n", type);
2810     ise_set_return_key_type(type);
2811
2812     if (keyboard_state->visible_state)
2813         ise_show(keyboard_state->ic);
2814 }
2815
2816 static void ime_app_return_key_state_set_cb(bool disabled, void *user_data)
2817 {
2818     LOGD("return key disabled : %d\n", disabled);
2819     ise_set_return_key_disable(disabled);
2820 }
2821
2822 static void ime_app_language_set_cb(Ecore_IMF_Input_Panel_Lang language, void *user_data)
2823 {
2824     LOGD("language : %d\n", language);
2825
2826     // if (language == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET) {
2827     //     ise_explictly_set_language(PRIMARY_LATIN_LANGUAGE_INDEX);
2828     // }
2829 }
2830
2831 static void ime_app_input_context_reset_cb(void *user_data)
2832 {
2833     ise_reset_input_context();
2834     engine_loader_reset_input_context();
2835 }
2836
2837 static void ime_app_cursor_position_updated_cb(int cursor_pos, void *user_data)
2838 {
2839     LOGD("cursor position : %d\n", cursor_pos);
2840     ise_update_cursor_position(cursor_pos);
2841     engine_loader_update_cursor_position(cursor_pos);
2842 }
2843
2844 static void ime_app_language_requested_cb(void *user_data, char **lang_code)
2845 {
2846     ise_get_language_locale(lang_code);
2847 }
2848
2849 static void ime_app_surrounding_text_updated_cb(int context_id, const char *text, int cursor_pos, void *user_data)
2850 {
2851     SECURE_LOGD("surrounding text:%s, cursor=%d\n", text, cursor_pos);
2852     ime_delete_surrounding_text(-cursor_pos, strlen(text));
2853 }
2854
2855 static void ime_app_focus_in_cb(int context_id, void *user_data)
2856 {
2857     LOGD("Enter\n");
2858     ise_focus_in(context_id);
2859     Candidate *candidate = get_candidate();
2860     if (input_smartreply_get_reply_num() == 0 && g_softcandidate_show) {
2861         if (candidate) {
2862             ise_app_candidate_hide();
2863             candidate->hide();
2864         }
2865     }
2866
2867     engine_loader_focus_in();
2868 }
2869
2870 static void ime_app_focus_out_cb(int context_id, void *user_data)
2871 {
2872     LOGD("Enter\n");
2873     ise_focus_out(context_id);
2874     g_imdata_state = 0;
2875 #ifdef HAVE_CBHM
2876     g_set_mime_type = FALSE;
2877 #endif
2878     input_smartreply_deinit();
2879     g_ic_smartreply = -1;
2880
2881     g_autofill_exist = false;
2882     g_autofill_hint = 0;
2883
2884     g_app_id = string("");
2885     g_resource_id = string("");
2886
2887     g_autofill_string = string("");
2888     g_smartreply_strings.clear();
2889     g_lookup_table_strings.clear();
2890     g_softcandidate_string.clear();
2891
2892     engine_loader_focus_out();
2893 }
2894
2895 static void ime_app_layout_set_cb(Ecore_IMF_Input_Panel_Layout layout, void *user_data)
2896 {
2897     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2898     if (!keyboard_state) return;
2899
2900     LOGD("layout=%d\n", layout);
2901     /* Check if the layoutIdx is in the valid range */
2902     if (static_cast<int>(layout) < static_cast<int>(ISE_LAYOUT_STYLE_MAX)) {
2903         if (keyboard_state->layout != layout) {
2904             keyboard_state->need_reset = TRUE;
2905         }
2906         keyboard_state->layout = layout;
2907         _context_layout = layout;
2908         _context_layout_variation = 0;
2909     }
2910     if (keyboard_state->visible_state)
2911         ise_show(keyboard_state->ic);
2912
2913     engine_loader_set_layout(static_cast<uint32_t>(layout));
2914 }
2915
2916 static void ime_app_rotation_degree_changed_cb(int degree, void *user_data)
2917 {
2918     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2919     if (!keyboard_state) return;
2920
2921     CSCLUI *ui = get_ui();
2922     ise_set_screen_rotation(degree);
2923
2924     LOGD("degree=%d\n", degree);
2925 #if defined(_MOBILE) || defined(_COMMON)
2926     if (ui && g_floating_mode) {
2927         int handler_width;
2928         ise_destroy_move_handler();
2929         if (degree == 0 || degree == 180) {
2930             SclSize size_portrait = ui->get_input_mode_size(ui->get_input_mode(), DISPLAYMODE_PORTRAIT);
2931             handler_width = size_portrait.width * FLOATING_SCALE_RATE;
2932         } else {
2933             SclSize size_landscape = ui->get_input_mode_size(ui->get_input_mode(), DISPLAYMODE_LANDSCAPE);
2934             handler_width = size_landscape.width * FLOATING_SCALE_RATE;
2935         }
2936         ise_show_move_handler(handler_width, FLOATING_TITLE_BAR_HEIGHT);
2937     }
2938 #endif
2939     if (ise_emoticon_is_show()) {
2940         ise_emoticon_destroy_layout();
2941     }
2942     if (keyboard_state->layout == ISE_LAYOUT_STYLE_VOICE) {
2943         ise_hide_stt_mode();
2944     }
2945     if (keyboard_state->layout == ISE_LAYOUT_STYLE_EMOTICON) {
2946         ise_emoticon_show_layout(ise_emoticon_get_current_group(), degree, false, ime_get_main_window());
2947     } else if (ui) {
2948         const sclchar *input_mode = ui->get_input_mode();
2949         if (input_mode) {
2950             if (!(strcmp(input_mode, "EMOTICON_LAYOUT")))
2951                 ise_emoticon_show_layout(ise_emoticon_get_current_group(), degree, false, ime_get_main_window());
2952             else if (!(strcmp(input_mode, "STT_3X4")))
2953                 ise_show_stt_mode(NATIVE_WINDOW_CAST(ime_get_main_window()));
2954         }
2955     }
2956 }
2957
2958 static void ime_app_accessibility_state_changed_cb(bool state, void *user_data)
2959 {
2960     LOGD("state=%d\n", state);
2961     ise_set_accessibility_state(state);
2962 }
2963
2964 static void ime_app_imdata_set_cb(void *data, unsigned int data_length, void *user_data)
2965 {
2966     LOGD("Enter\n");
2967     g_imdata_state = 0;
2968     size_t _len = data_length;
2969     set_ise_imdata((sclchar *)data, _len);
2970     engine_loader_set_imdata((const char*)data, (uint32_t)data_length);
2971 }
2972
2973 static bool ime_app_process_key_event_cb(ime_key_code_e keycode, ime_key_mask_e keymask, ime_device_info_h dev_info, void *user_data)
2974 {
2975     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
2976     if (!keyboard_state) return FALSE;
2977
2978     scim::KeyEvent key(keycode, keymask);
2979     unsigned int ret;
2980     char *dev_name = NULL;
2981     Ecore_IMF_Device_Class dev_class;
2982     Ecore_IMF_Device_Subclass dev_subclass;
2983
2984     if (ime_device_info_get_name(dev_info, &dev_name) == IME_ERROR_NONE) {
2985         key.dev_name = dev_name;
2986     }
2987
2988     if (ime_device_info_get_class(dev_info, &dev_class) == IME_ERROR_NONE) {
2989         key.dev_class = dev_class;
2990     }
2991
2992     if (ime_device_info_get_subclass(dev_info, &dev_subclass) == IME_ERROR_NONE) {
2993         key.dev_subclass = dev_subclass;
2994     }
2995
2996     if (keyboard_state->visible_state)
2997         ise_process_key_event(key, ret);
2998     else
2999         ret = FALSE;
3000
3001     if (dev_name)
3002         free(dev_name);
3003
3004     return ret;
3005 }
3006
3007 static void ime_app_process_key_event_with_imengine_cb(scim::KeyEvent &key, uint32_t serial, void *user_data)
3008 {
3009     LANGUAGE_INFO *info = _language_manager.get_language_info(_language_manager.get_current_language());
3010     if (info && info->need_surrounding_text)
3011         engine_loader_process_key_event(key, serial, true);
3012     else
3013         engine_loader_process_key_event(key, serial, false);
3014 }
3015
3016 static void ime_app_caps_mode_changed_cb(int mode, void *user_data)
3017 {
3018     ise_set_caps_mode(mode);
3019 }
3020
3021 static void ime_app_candidate_show_cb(int context_id, void *user_data)
3022 {
3023 #ifdef _WEARABLE
3024     ise_check_wearable_candidate();
3025 #else
3026     ise_app_candidate_show();
3027 #endif
3028 }
3029
3030 static void ime_app_candidate_hide_cb(int context_id, void *user_data)
3031 {
3032 #ifdef _WEARABLE
3033     ise_check_wearable_candidate();
3034 #else
3035     ise_app_candidate_hide();
3036 #endif
3037 }
3038
3039 static void ime_app_lookup_table_changed_cb(Eina_List *list, void *user_data)
3040 {
3041     vector<string> candidate_strings;
3042     char *candidate;
3043     void *data;
3044     Eina_List *l;
3045
3046     g_lookup_table_strings.clear();
3047
3048     if (list) {
3049         EINA_LIST_FOREACH(list, l, data) {
3050             candidate = (char *)data;
3051             if (candidate) {
3052                 g_lookup_table_strings.push_back(string(candidate));
3053                 candidate_strings.push_back(string(candidate));
3054             }
3055         }
3056     }
3057
3058     if (input_smartreply_get_reply_num() > 0) {
3059         if (candidate_strings[0] == "#" && candidate_strings[1] == "$") {
3060             char *text = NULL;
3061             int cursor;
3062             ime_get_surrounding_text(0, 0, &text, &cursor);
3063             if (text)
3064                 free(text);
3065
3066             if (cursor == 0)
3067                 return;
3068         }
3069     }
3070
3071     update_candidate_table();
3072 }
3073
3074 #ifdef _WEARABLE
3075 static void ime_app_process_input_device_event_cb(ime_input_device_type_e device_type, ime_input_device_event_h device_event, void *user_data)
3076 {
3077     KEYBOARD_STATE *keyboard_state = get_keyboard_state();
3078     if (!keyboard_state) return;
3079
3080     if (device_type == IME_INPUT_DEVICE_TYPE_ROTARY) {
3081         ime_input_device_rotary_direction_e direction;
3082         if (IME_ERROR_NONE == ime_input_device_rotary_get_direction(device_event, &direction)) {
3083             sclu32 new_layout = keyboard_state->layout;
3084             if (direction == IME_INPUT_DEVICE_ROTARY_DIRECTION_CLOCKWISE) {
3085                 LOGD("CLOCKWISE\n");
3086                 switch (keyboard_state->layout) {
3087                     case ISE_LAYOUT_STYLE_NORMAL:
3088                     case ISE_LAYOUT_STYLE_EMAIL:
3089                     case ISE_LAYOUT_STYLE_URL:
3090                     case ISE_LAYOUT_STYLE_PASSWORD:
3091                         if (_context_layout == ISE_LAYOUT_STYLE_PASSWORD &&
3092                             _context_layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
3093                             ;   // PASSWORD NUMBER ONLY, do nothing
3094                         else
3095                             new_layout = ISE_LAYOUT_STYLE_NUMBER;
3096                         break;
3097                     case ISE_LAYOUT_STYLE_NUMBER:
3098                         new_layout = ISE_LAYOUT_STYLE_HEX;
3099                         break;
3100                     case ISE_LAYOUT_STYLE_HEX:
3101                         if (_context_layout == ISE_LAYOUT_STYLE_EMAIL ||
3102                             _context_layout == ISE_LAYOUT_STYLE_URL)
3103                             new_layout = ISE_LAYOUT_STYLE_VOICE;
3104                         else if (_context_layout == ISE_LAYOUT_STYLE_PASSWORD)
3105                             new_layout = _context_layout;
3106                         else
3107                             new_layout = ISE_LAYOUT_STYLE_EMOTICON;
3108                         break;
3109                     case ISE_LAYOUT_STYLE_EMOTICON:
3110                         if (_context_layout == ISE_LAYOUT_STYLE_EMAIL ||
3111                             _context_layout == ISE_LAYOUT_STYLE_URL ||
3112                             _context_layout == ISE_LAYOUT_STYLE_PASSWORD)
3113                             new_layout = _context_layout;
3114                         else
3115                             new_layout = ISE_LAYOUT_STYLE_VOICE;
3116                         break;
3117                     case ISE_LAYOUT_STYLE_VOICE:
3118                         new_layout = ISE_LAYOUT_STYLE_NORMAL;
3119                         break;
3120                     default:
3121                         ;
3122                 }
3123             } else if (direction == IME_INPUT_DEVICE_ROTARY_DIRECTION_COUNTER_CLOCKWISE) {
3124                 LOGD("COUNTER_CLOCKWISE\n");
3125                 switch (keyboard_state->layout) {
3126                     case ISE_LAYOUT_STYLE_NORMAL:
3127                     case ISE_LAYOUT_STYLE_EMAIL:
3128                     case ISE_LAYOUT_STYLE_URL:
3129                     case ISE_LAYOUT_STYLE_PASSWORD:
3130                         if (_context_layout == ISE_LAYOUT_STYLE_PASSWORD &&
3131                             _context_layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
3132                             ;   // PASSWORD NUMBER ONLY, do nothing
3133                         else if (_context_layout == ISE_LAYOUT_STYLE_PASSWORD)
3134                             new_layout = ISE_LAYOUT_STYLE_HEX;
3135                         else
3136                             new_layout = ISE_LAYOUT_STYLE_VOICE;
3137                         break;
3138                     case ISE_LAYOUT_STYLE_NUMBER:
3139                         if (_context_layout == ISE_LAYOUT_STYLE_EMAIL ||
3140                             _context_layout == ISE_LAYOUT_STYLE_URL ||
3141                             _context_layout == ISE_LAYOUT_STYLE_PASSWORD)
3142                             new_layout = _context_layout;
3143                         else
3144                             new_layout = ISE_LAYOUT_STYLE_NORMAL;
3145                         break;
3146                     case ISE_LAYOUT_STYLE_HEX:
3147                         new_layout = ISE_LAYOUT_STYLE_NUMBER;
3148                         break;
3149                     case ISE_LAYOUT_STYLE_EMOTICON:
3150                         new_layout = ISE_LAYOUT_STYLE_HEX;
3151                         break;
3152                     case ISE_LAYOUT_STYLE_VOICE:
3153                         if (_context_layout == ISE_LAYOUT_STYLE_EMAIL ||
3154                             _context_layout == ISE_LAYOUT_STYLE_URL)
3155                             new_layout = ISE_LAYOUT_STYLE_HEX;
3156                         else
3157                             new_layout = ISE_LAYOUT_STYLE_EMOTICON;
3158                         break;
3159                     default:
3160                         ;
3161                 }
3162             }
3163
3164             CONFIG_VALUES *config_values = get_config_values();
3165             if (check_is_tutorial_show() && config_values) {
3166                 read_ise_config_values();
3167                 if ((direction == IME_INPUT_DEVICE_ROTARY_DIRECTION_COUNTER_CLOCKWISE && !config_values->number_tutorial_enable && !config_values->symbol_tutorial_enable) ||
3168                     (direction == IME_INPUT_DEVICE_ROTARY_DIRECTION_CLOCKWISE && config_values->symbol_tutorial_enable)) {
3169                     new_layout = keyboard_state->layout;
3170                 } else if (direction == IME_INPUT_DEVICE_ROTARY_DIRECTION_COUNTER_CLOCKWISE && config_values->symbol_tutorial_enable) {
3171                     ise_destroy_tutorial_mode_popup();
3172                     config_values->symbol_tutorial_enable = false;
3173                      write_ise_config_values();
3174                 } else if (direction == IME_INPUT_DEVICE_ROTARY_DIRECTION_CLOCKWISE && !config_values->number_tutorial_enable) {
3175                     ise_destroy_tutorial_mode_popup();
3176                     new_layout = ISE_LAYOUT_STYLE_NUMBER;
3177                     if (!config_values->symbol_tutorial_enable) {
3178                         ise_show_tutorial_mode_popup(new_layout);
3179                         config_values->symbol_tutorial_enable = true;
3180                          write_ise_config_values();
3181                     }
3182                 }
3183             }
3184
3185             if (new_layout != keyboard_state->layout && new_layout < ISE_LAYOUT_STYLE_MAX) {
3186                 keyboard_state->need_reset = TRUE;
3187                 keyboard_state->layout = new_layout;
3188
3189                 if (keyboard_state->visible_state) {
3190                     _reset_multitap_state();
3191                     if (config_values) {
3192                         _language_manager.reset_language(config_values->selected_language.c_str());
3193                     }
3194                     ise_show(keyboard_state->ic);
3195                 }
3196             }
3197         }
3198     }
3199 }
3200 #endif
3201
3202 static void ime_app_prediction_hint_set_cb(const char *prediction_hint, void *user_data)
3203 {
3204     char *sender = (char *)"mms";
3205     char *caller_id = (char *)"mms";
3206     char *hint = (char *)prediction_hint;
3207
3208     if (!prediction_hint) return;
3209     SECURE_LOGD("prediction hint : %s\n", prediction_hint);
3210
3211     if (strlen(prediction_hint) > 0) {
3212         input_smartreply_init(caller_id, sender, hint);
3213         input_smartreply_set_notify(_input_smartreply_notify_cb, NULL);
3214
3215         if (input_smartreply_is_enabled()) {
3216             input_smartreply_get_reply_async();
3217         }
3218     }
3219 }
3220
3221 static void ime_app_mime_type_set_request_cb(const char *mime_types, void *user_data)
3222 {
3223     LOGD("mime type : %s\n", mime_types);
3224
3225 #ifdef HAVE_CBHM
3226     g_set_mime_type = TRUE;
3227     cbhm_sel_type = 0;
3228     string str(mime_types), text_key = "text/", image_key = "image/";
3229
3230     if (str.find(text_key) != string::npos)
3231         cbhm_sel_type |= CBHM_SEL_TYPE_TEXT;
3232
3233     if (str.find(image_key) != string::npos)
3234         cbhm_sel_type |= CBHM_SEL_TYPE_IMAGE;
3235
3236     LOGD("cbhm_sel_type=0x%x", cbhm_sel_type);
3237 #endif
3238 }
3239
3240 static void ime_app_prediction_hint_data_set_cb(const char *key, const char *value, void *user_data)
3241 {
3242     SECURE_LOGD("key : %s, value : %s\n", key, value);
3243
3244     if (string(key) == "appid")
3245         g_app_id = string(value ? value : "");
3246     else if (string(key) == "res_id")
3247         g_resource_id = string(value ? value : "");
3248 }
3249
3250 static void ime_app_autocapital_type_set_cb(uint32_t type, void *user_data)
3251 {
3252     LOGD("autocapital type : %u\n", type);
3253     engine_loader_set_autocapital_type(type);
3254 }
3255
3256 static void ime_app_prediction_allow_set_cb(uint32_t prediction_allow, void *user_data)
3257 {
3258     LOGD("prediction allow : %u\n", prediction_allow);
3259     engine_loader_set_prediction_allow(prediction_allow);
3260 }
3261
3262 static void ime_app_trigger_property_set_cb(const char *property, void *user_data)
3263 {
3264     LOGD("trigger property : %s\n", property);
3265     engine_loader_trigger_property(property);
3266 }
3267
3268 static void ime_app_candidate_more_window_show_cb(void *user_data)
3269 {
3270     LOGD("");
3271     engine_loader_show_candidate_more_window();
3272 }
3273
3274 static void ime_app_candidate_more_window_hide_cb(void *user_data)
3275 {
3276     LOGD("");
3277     engine_loader_hide_candidate_more_window();
3278 }
3279
3280 static void ime_app_aux_select_cb(uint32_t item, void *user_data)
3281 {
3282     LOGD("aux select : %u\n", item);
3283     engine_loader_select_aux(item);
3284 }
3285
3286 static void ime_app_candidate_select_cb(uint32_t item, void *user_data)
3287 {
3288     LOGD("candidate select : %u\n", item);
3289     engine_loader_select_candidate(item);
3290 }
3291
3292 static void ime_app_candidate_table_page_up_cb(void *user_data)
3293 {
3294     LOGD("");
3295     engine_loader_candidate_table_page_up();
3296 }
3297
3298 static void ime_app_candidate_table_page_down_cb(void *user_data)
3299 {
3300     LOGD("");
3301     engine_loader_candidate_table_page_down();
3302 }
3303
3304 static void ime_app_candidate_table_page_size_chaned_cb(uint32_t size, void *user_data)
3305 {
3306     LOGD("candidate page size : %u\n", size);
3307     engine_loader_change_candidate_page_size(size);
3308 }
3309
3310 static void ime_app_candidate_item_layout_set_cb(vector<uint32_t> item, void *user_data)
3311 {
3312     LOGD("item layout size : %zu", item.size());
3313     engine_loader_set_candidate_item_layout(item);
3314 }
3315
3316 static void ime_app_displayed_candidate_number_chaned_cb(uint32_t page_num, void *user_data)
3317 {
3318     LOGD("candidate number changed : %u\n", page_num);
3319     engine_loader_change_candidate_number(page_num);
3320 }
3321
3322 static void ime_app_candidate_item_long_pressed_cb(uint32_t index, void *user_data)
3323 {
3324     LOGD("candidate item : %u\n", index);
3325     engine_loader_long_press_candidate_item(index);
3326 }
3327
3328 #ifdef __cplusplus
3329 extern "C"{
3330 #endif
3331 EXPORTED void ime_app_main(int argc, char **argv)
3332 {
3333     ime_callback_s basic_callback = {
3334         ime_app_create_cb,
3335         ime_app_exit_cb,
3336         ime_app_show_cb,
3337         ime_app_hide_cb
3338     };
3339
3340     ime_event_set_focus_in_cb(ime_app_focus_in_cb, NULL);
3341     ime_event_set_focus_out_cb(ime_app_focus_out_cb, NULL);
3342     ime_event_set_rotation_degree_changed_cb(ime_app_rotation_degree_changed_cb, NULL);
3343     ime_event_set_accessibility_state_changed_cb(ime_app_accessibility_state_changed_cb, NULL);
3344     ime_event_set_layout_set_cb(ime_app_layout_set_cb, NULL);
3345     ime_event_set_caps_mode_changed_cb(ime_app_caps_mode_changed_cb, NULL);
3346     ime_event_set_cursor_position_updated_cb(ime_app_cursor_position_updated_cb, NULL);
3347     ime_event_set_surrounding_text_updated_cb(ime_app_surrounding_text_updated_cb, NULL);
3348     ime_event_set_return_key_type_set_cb(ime_app_return_key_type_set_cb, NULL);
3349     ime_event_set_return_key_state_set_cb(ime_app_return_key_state_set_cb, NULL);
3350     ime_event_set_language_set_cb(ime_app_language_set_cb, NULL);
3351     ime_event_set_imdata_set_cb(ime_app_imdata_set_cb, NULL);
3352     ime_event_set_process_key_event_cb(ime_app_process_key_event_cb, NULL);
3353     ime_event_set_process_key_event_with_imengine_cb(ime_app_process_key_event_with_imengine_cb, NULL);
3354
3355     ime_event_set_candidate_show_cb(ime_app_candidate_show_cb, NULL);
3356     ime_event_set_candidate_hide_cb(ime_app_candidate_hide_cb, NULL);
3357     ime_event_set_lookup_table_changed_cb(ime_app_lookup_table_changed_cb, NULL);
3358
3359 #ifdef _WEARABLE
3360     ime_event_set_process_input_device_event_cb(ime_app_process_input_device_event_cb, NULL);
3361 #endif
3362
3363     ime_event_set_input_context_reset_cb(ime_app_input_context_reset_cb, NULL);
3364     ime_event_set_language_requested_cb(ime_app_language_requested_cb, NULL);
3365
3366     ime_event_set_prediction_hint_set_cb(ime_app_prediction_hint_set_cb, NULL);
3367     ime_event_set_mime_type_set_request_cb(ime_app_mime_type_set_request_cb, NULL);
3368     ime_event_set_prediction_hint_data_set_cb(ime_app_prediction_hint_data_set_cb, NULL);
3369
3370     ime_event_set_autocapital_type_set_cb(ime_app_autocapital_type_set_cb, NULL);
3371     ime_event_set_prediction_allow_set_cb(ime_app_prediction_allow_set_cb, NULL);
3372     ime_event_set_trigger_property_set_cb(ime_app_trigger_property_set_cb, NULL);
3373     ime_event_set_candidate_more_window_show_cb(ime_app_candidate_more_window_show_cb, NULL);
3374     ime_event_set_candidate_more_window_hide_cb(ime_app_candidate_more_window_hide_cb, NULL);
3375     ime_event_set_aux_select_cb(ime_app_aux_select_cb, NULL);
3376     ime_event_set_candidate_select_cb(ime_app_candidate_select_cb, NULL);
3377     ime_event_set_candidate_table_page_up_cb(ime_app_candidate_table_page_up_cb, NULL);
3378     ime_event_set_candidate_table_page_down_cb(ime_app_candidate_table_page_down_cb, NULL);
3379     ime_event_set_candidate_table_page_size_chaned_cb(ime_app_candidate_table_page_size_chaned_cb, NULL);
3380     ime_event_set_candidate_item_layout_set_cb(ime_app_candidate_item_layout_set_cb, NULL);
3381     ime_event_set_displayed_candidate_number_chaned_cb(ime_app_displayed_candidate_number_chaned_cb, NULL);
3382     ime_event_set_candidate_item_long_pressed_cb(ime_app_candidate_item_long_pressed_cb, NULL);
3383
3384 #if DEFER_ISE_CREATION
3385     ime_set_window_creation_defer_flag(TRUE);
3386 #endif
3387
3388     ime_run(&basic_callback, NULL);
3389 }
3390 #ifdef __cplusplus
3391 }
3392 #endif
3393
3394 EXPORTED int main(int argc, char *argv[])
3395 {
3396     ime_app_main(argc, argv);
3397
3398     return 0;
3399 }