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