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