Tizen 2.4 SDK Rev6 Release
[framework/uifw/efl.git] / src / lib / edje / edje_entry.c
1 #include "edje_private.h"
2
3 #ifdef HAVE_ECORE_IMF
4 static Eina_Bool _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
5 static void      _edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx, void *event_info);
6 static void      _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx, void *event_info);
7 static void      _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx, void *event);
8 static void      _edje_entry_imf_event_selection_set_cb(void *data, Ecore_IMF_Context *ctx, void *event_info);
9 static Eina_Bool _edje_entry_imf_retrieve_selection_cb(void *data, Ecore_IMF_Context *ctx, char **text);
10 #endif
11
12 typedef struct _Entry Entry;
13 typedef struct _Sel Sel;
14 typedef struct _Anchor Anchor;
15
16 static void _edje_entry_imf_cursor_location_set(Entry *en);
17 static void _edje_entry_imf_cursor_info_set(Entry *en);
18 static void _range_del_emit(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en);
19 static void _text_filter_format_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c, const char *text);
20
21 struct _Entry
22 {
23    Edje_Real_Part *rp;
24    Edje *ed;
25    Evas_Coord ox, oy;
26    Evas_Object *cursor_bg;
27    Evas_Object *cursor_fg, *cursor_fg2;
28    Evas_Textblock_Cursor *cursor;
29    Evas_Textblock_Cursor *sel_start, *sel_end;
30    Evas_Textblock_Cursor *cursor_user, *cursor_user_extra;
31    Evas_Textblock_Cursor *preedit_start, *preedit_end;
32    Ecore_Timer *pw_timer;
33    Eina_List *sel;
34    Eina_List *anchors;
35    Eina_List *anchorlist;
36    Eina_List *itemlist;
37    Eina_List *seq;
38    char *selection;
39    Edje_Input_Panel_Lang input_panel_lang;
40    Eina_Bool composing : 1;
41    Eina_Bool selecting : 1;
42    Eina_Bool have_selection : 1;
43    Eina_Bool select_allow : 1;
44    Eina_Bool select_mod_start : 1;
45    Eina_Bool select_mod_end : 1;
46    Eina_Bool had_sel : 1;
47    Eina_Bool input_panel_enable : 1;
48    Eina_Bool prediction_allow : 1;
49    // TIZEN_ONLY(20150716): Add edje_object_part_text_freeze, thaw APIs for freezing cursor movements.
50    Eina_Bool freeze : 1;
51    //
52
53 #ifdef HAVE_ECORE_IMF
54    Eina_Bool have_preedit : 1;
55    Eina_Bool commit_cancel : 1; // For skipping useless commit
56    Ecore_IMF_Context *imf_context;
57 #endif
58 };
59
60 struct _Sel
61 {
62    Evas_Textblock_Rectangle rect;
63    Evas_Object *obj_fg, *obj_bg, *obj, *sobj;
64 };
65
66 struct _Anchor
67 {
68    Entry *en;
69    char *name;
70    Evas_Textblock_Cursor *start, *end;
71    Eina_List *sel;
72    Eina_Bool item : 1;
73 };
74
75 #ifdef HAVE_ECORE_IMF
76 static void
77 _preedit_clear(Entry *en)
78 {
79    if (en->preedit_start)
80      {
81         evas_textblock_cursor_free(en->preedit_start);
82         en->preedit_start = NULL;
83      }
84
85    if (en->preedit_end)
86      {
87         evas_textblock_cursor_free(en->preedit_end);
88         en->preedit_end = NULL;
89      }
90
91    en->have_preedit = EINA_FALSE;
92 }
93
94 static void
95 _preedit_del(Entry *en)
96 {
97    if (!en || !en->have_preedit) return;
98    if (!en->preedit_start || !en->preedit_end) return;
99    if (!evas_textblock_cursor_compare(en->preedit_start, en->preedit_end)) return;
100
101    /* delete the preedit characters */
102    evas_textblock_cursor_range_delete(en->preedit_start, en->preedit_end);
103 }
104
105 static void
106 _edje_entry_focus_in_cb(void *data, Evas_Object *o, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
107 {
108    Edje_Real_Part *rp;
109    Entry *en;
110    Edje *ed;
111
112    rp = data;
113    if ((!rp) || (rp->type != EDJE_RP_TYPE_TEXT) ||
114        (!rp->typedata.text)) return;
115    if (!rp->typedata.text->entry_data) return;
116
117    ed = _edje_fetch(o);
118    if (!ed) return;
119
120    en = rp->typedata.text->entry_data;
121    if (!en || !en->imf_context) return;
122
123    if (evas_object_focus_get(ed->obj))
124      {
125         ecore_imf_context_focus_in(en->imf_context);
126         _edje_entry_imf_cursor_info_set(en);
127      }
128 }
129
130 static void
131 _edje_entry_focus_out_cb(void *data, Evas_Object *o EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
132 {
133    Edje_Real_Part *rp;
134    Entry *en;
135
136    rp = data;
137    if ((!rp) || (rp->type != EDJE_RP_TYPE_TEXT) ||
138        (!rp->typedata.text)) return;
139    if (!rp->typedata.text->entry_data) return;
140
141    en = rp->typedata.text->entry_data;
142    if (!en || !en->imf_context) return;
143
144    ecore_imf_context_reset(en->imf_context);
145    ecore_imf_context_focus_out(en->imf_context);
146 }
147 #endif
148
149 static void
150 _edje_focus_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
151 {
152    Edje *ed = data;
153 #ifdef HAVE_ECORE_IMF
154    Edje_Real_Part *rp;
155    Entry *en;
156 #endif
157
158    _edje_emit(ed, "focus,in", "");
159 #ifdef HAVE_ECORE_IMF
160    rp = ed->focused_part;
161    if (!rp) return;
162    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
163        (!rp->typedata.text)) return;
164    en = rp->typedata.text->entry_data;
165    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
166        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
167      return;
168
169    if (!en->imf_context) return;
170
171    ecore_imf_context_focus_in(en->imf_context);
172    _edje_entry_imf_cursor_info_set(en);
173 #endif
174 }
175
176 static void
177 _edje_focus_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
178 {
179    Edje *ed = data;
180 #ifdef HAVE_ECORE_IMF
181    Edje_Real_Part *rp = ed->focused_part;
182    Entry *en;
183 #endif
184
185    _edje_emit(ed, "focus,out", "");
186
187 #ifdef HAVE_ECORE_IMF
188    if (!rp) return;
189    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
190        (!rp->typedata.text)) return;
191    en = rp->typedata.text->entry_data;
192    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
193        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
194      return;
195
196    if (!en->imf_context) return;
197
198    ecore_imf_context_reset(en->imf_context);
199    ecore_imf_context_focus_out(en->imf_context);
200 #endif
201 }
202
203 static Edje_Entry_Change_Info *
204 _text_filter_markup_prepend_internal(Edje *ed, Entry *en, Evas_Textblock_Cursor *c,
205                                      char *text,
206                                      const char *fmtpre, const char *fmtpost,
207                                      Eina_Bool clearsel, Eina_Bool changeinfo)
208 {
209    Edje_Markup_Filter_Callback *cb;
210    Eina_List *l;
211    Eina_Bool have_sel = EINA_FALSE;
212
213    if ((clearsel) && (en->have_selection))
214      {
215         _range_del_emit(ed, en->cursor, en->rp->object, en);
216         have_sel= EINA_TRUE;
217      }
218
219    EINA_LIST_FOREACH(ed->markup_filter_callbacks, l, cb)
220      {
221         if (!strcmp(cb->part, en->rp->part->name))
222           {
223              cb->func(cb->data, ed->obj, cb->part, &text);
224              if (!text) break;
225           }
226      }
227 #ifdef HAVE_ECORE_IMF
228    // For skipping useless commit
229    if (en->have_preedit && (!text || !strcmp(text, "")))
230      en->commit_cancel = EINA_TRUE;
231    else
232      en->commit_cancel = EINA_FALSE;
233 #endif
234    if (text)
235      {
236         Edje_Entry_Change_Info *info = NULL;
237
238         if (changeinfo)
239           {
240              info = calloc(1, sizeof(*info));
241              if (info)
242                {
243                   info->insert = EINA_TRUE;
244                   info->change.insert.content = eina_stringshare_add(text);
245                   info->change.insert.plain_length =
246                     eina_unicode_utf8_get_len(info->change.insert.content);
247                }
248           }
249         if (have_sel)
250           {
251             if (info)
252               {
253                  info->merge = EINA_TRUE;
254               }
255           }
256         if (info) info->change.insert.pos =
257           evas_textblock_cursor_pos_get(en->cursor);
258         if (fmtpre) _text_filter_format_prepend(ed, en, en->cursor, fmtpre);
259         evas_object_textblock_text_markup_prepend(c, text);
260         free(text);
261         if (fmtpost) _text_filter_format_prepend(ed, en, en->cursor, fmtpost);
262         return info;
263      }
264    return NULL;
265 }
266
267 static Edje_Entry_Change_Info *
268 _text_filter_text_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c,
269                           const char *text,
270                           const char *fmtpre, const char *fmtpost,
271                           Eina_Bool clearsel, Eina_Bool changeinfo)
272 {
273    char *text2 = NULL;
274    Edje_Text_Insert_Filter_Callback *cb;
275    Eina_List *l;
276
277    EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
278
279    if ((clearsel) && (en->have_selection))
280      {
281         _range_del_emit(ed, en->cursor, en->rp->object, en);
282      }
283
284    text2 = strdup(text);
285    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
286      {
287         if (!strcmp(cb->part, en->rp->part->name))
288           {
289              cb->func(cb->data, ed->obj, cb->part, EDJE_TEXT_FILTER_TEXT, &text2);
290              if (!text2) break;
291           }
292      }
293    if (text2)
294      {
295         char *markup_text;
296         Edje_Entry_Change_Info *info = NULL;
297
298         markup_text = evas_textblock_text_utf8_to_markup(NULL, text2);
299         free(text2);
300         if (markup_text)
301           info = _text_filter_markup_prepend_internal(ed, en, c, markup_text,
302                                                      fmtpre, fmtpost,
303                                                      clearsel, changeinfo);
304         return info;
305      }
306    return NULL;
307 }
308
309 static void
310 _text_filter_format_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c, const char *text)
311 {
312    char *text2;
313    Edje_Text_Insert_Filter_Callback *cb;
314    Eina_List *l;
315
316    EINA_SAFETY_ON_NULL_RETURN(text);
317    text2 = strdup(text);
318    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
319      {
320         if (!strcmp(cb->part, en->rp->part->name))
321           {
322              cb->func(cb->data, ed->obj, cb->part, EDJE_TEXT_FILTER_FORMAT, &text2);
323              if (!text2) break;
324           }
325      }
326    if (text2)
327      {
328         char *s, *markup_text;
329
330         s = text2;
331         if (*s == '+')
332           {
333              s++;
334              while (*s == ' ') s++;
335              if (!*s)
336                {
337                   free(text2);
338                   return;
339                }
340              markup_text = (char*) malloc(strlen(s) + 3);
341              if (markup_text)
342                {
343                   *(markup_text) = '<';
344                   strncpy((markup_text + 1), s, strlen(s));
345                   *(markup_text + strlen(s) + 1) = '>';
346                   *(markup_text + strlen(s) + 2) = '\0';
347                }
348           }
349         else if (s[0] == '-')
350           {
351              s++;
352              while (*s == ' ') s++;
353              if (!*s)
354                {
355                   free(text2);
356                   return;
357                }
358              markup_text = (char*) malloc(strlen(s) + 4);
359              if (markup_text)
360                {
361                   *(markup_text) = '<';
362                   *(markup_text + 1) = '/';
363                   strncpy((markup_text + 2), s, strlen(s));
364                   *(markup_text + strlen(s) + 2) = '>';
365                   *(markup_text + strlen(s) + 3) = '\0';
366                }
367           }
368         else
369           {
370              markup_text = (char*) malloc(strlen(s) + 4);
371              if (markup_text)
372                {
373                   *(markup_text) = '<';
374                   strncpy((markup_text + 1), s, strlen(s));
375                   *(markup_text + strlen(s) + 1) = '/';
376                   *(markup_text + strlen(s) + 2) = '>';
377                   *(markup_text + strlen(s) + 3) = '\0';
378                }
379           }
380         free(text2);
381         if (markup_text)
382           _text_filter_markup_prepend_internal(ed, en, c, markup_text,
383                                                NULL, NULL,
384                                                EINA_FALSE, EINA_FALSE);
385      }
386 }
387
388 static Edje_Entry_Change_Info *
389 _text_filter_markup_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c,
390                             const char *text,
391                             const char *fmtpre, const char *fmtpost,
392                             Eina_Bool clearsel, Eina_Bool changeinfo)
393 {
394    char *text2;
395    Edje_Text_Insert_Filter_Callback *cb;
396    Eina_List *l;
397
398    EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
399
400    if ((clearsel) && (en->have_selection))
401      {
402         _range_del_emit(ed, en->cursor, en->rp->object, en);
403      }
404
405    text2 = strdup(text);
406    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
407      {
408         if (!strcmp(cb->part, en->rp->part->name))
409           {
410              cb->func(cb->data, ed->obj, cb->part, EDJE_TEXT_FILTER_MARKUP, &text2);
411              if (!text2) break;
412           }
413      }
414    if (text2)
415      {
416         Edje_Entry_Change_Info *info;
417
418         info = _text_filter_markup_prepend_internal(ed, en, c, text2,
419                                                     fmtpre, fmtpost,
420                                                     clearsel, changeinfo);
421         return info;
422      }
423    return NULL;
424 }
425
426 static void
427 _curs_update_from_curs(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED, Entry *en, Evas_Coord *cx, Evas_Coord *cy)
428 {
429    Evas_Coord cw, ch;
430    Evas_Textblock_Cursor_Type cur_type;
431    if (c != en->cursor) return;
432    switch (en->rp->part->cursor_mode)
433      {
434       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
435          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
436          break;
437       case EDJE_ENTRY_CURSOR_MODE_UNDER:
438          /* no break for a reason */
439       default:
440          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
441      }
442    evas_textblock_cursor_geometry_get(c, cx, cy, &cw, &ch, NULL, cur_type);
443    *cx += (cw / 2);
444    *cy += (ch / 2);
445 }
446
447 static int
448 _curs_line_last_get(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en EINA_UNUSED)
449 {
450    Evas_Textblock_Cursor *cc;
451    int ln;
452
453    cc = evas_object_textblock_cursor_new(o);
454    evas_textblock_cursor_paragraph_last(cc);
455    ln = evas_textblock_cursor_line_geometry_get(cc, NULL, NULL, NULL, NULL);
456    evas_textblock_cursor_free(cc);
457    return ln;
458 }
459
460 static void
461 _curs_lin_start(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED,
462                 Entry *en EINA_UNUSED)
463 {
464    evas_textblock_cursor_line_char_first(c);
465 }
466
467 static void
468 _curs_lin_end(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED,
469               Entry *en EINA_UNUSED)
470 {
471    evas_textblock_cursor_line_char_last(c);
472 }
473
474 static void
475 _curs_start(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED,
476             Entry *en EINA_UNUSED)
477 {
478    evas_textblock_cursor_paragraph_first(c);
479 }
480
481 static void
482 _curs_end(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED, Entry *en EINA_UNUSED)
483 {
484    evas_textblock_cursor_paragraph_last(c);
485 }
486
487 static Eina_Bool
488 _curs_jump_line(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int ln)
489 {
490    Evas_Coord cx, cy;
491    Evas_Coord lx, ly, lw, lh;
492    int last = _curs_line_last_get(c, o, en);
493
494    if (ln < 0) return EINA_FALSE;
495    if (ln > last) return EINA_FALSE;
496
497    _curs_update_from_curs(c, o, en, &cx, &cy);
498
499    if (!evas_object_textblock_line_number_geometry_get(o, ln, &lx, &ly, &lw, &lh))
500      return EINA_FALSE;
501    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
502    //if (evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
503    if (evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
504      return EINA_TRUE;
505    evas_textblock_cursor_line_set(c, ln);
506    if (cx < (lx + (lw / 2)))
507      {
508         if (ln == last) _curs_end(c, o, en);
509         _curs_lin_start(c, o, en);
510      }
511    else
512      {
513         if (ln == last)
514           _curs_end(c, o, en);
515         else
516           _curs_lin_end(c, o, en);
517      }
518    return EINA_TRUE;
519 }
520
521 static Eina_Bool
522 _curs_jump_line_by(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int by)
523 {
524    int ln;
525
526    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL) + by;
527    return _curs_jump_line(c, o, en, ln);
528 }
529
530 static Eina_Bool
531 _curs_up(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
532 {
533    return _curs_jump_line_by(c, o, en, -1);
534 }
535
536 static Eina_Bool
537 _curs_down(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
538 {
539    return _curs_jump_line_by(c, o, en, 1);
540 }
541
542 static void
543 _sel_start(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
544 {
545    if (en->sel_start) return;
546    en->sel_start = evas_object_textblock_cursor_new(o);
547    evas_textblock_cursor_copy(c, en->sel_start);
548    en->sel_end = evas_object_textblock_cursor_new(o);
549    evas_textblock_cursor_copy(c, en->sel_end);
550
551    en->have_selection = EINA_FALSE;
552    if (en->selection)
553      {
554         free(en->selection);
555         en->selection = NULL;
556      }
557 }
558
559 static void
560 _sel_enable(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED,
561             Evas_Object *o EINA_UNUSED, Entry *en)
562 {
563    if (en->have_selection) return;
564    en->have_selection = EINA_TRUE;
565    if (en->selection)
566      {
567         free(en->selection);
568         en->selection = NULL;
569      }
570
571    _edje_entry_imf_context_reset(en->rp);
572    _edje_emit(ed, "selection,start", en->rp->part->name);
573 }
574
575 static void
576 _sel_extend(Edje *ed, Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
577 {
578    if (!en->sel_end) return;
579    _sel_enable(ed, c, o, en);
580    if (!evas_textblock_cursor_compare(c, en->sel_end)) return;
581
582    evas_textblock_cursor_copy(c, en->sel_end);
583
584    _edje_entry_imf_cursor_info_set(en);
585
586    if (en->selection)
587      {
588         free(en->selection);
589         en->selection = NULL;
590      }
591    _edje_emit(ed, "selection,changed", en->rp->part->name);
592 }
593
594 static void
595 _sel_preextend(Edje *ed, Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
596 {
597    if (!en->sel_end) return;
598    _sel_enable(ed, c, o, en);
599    if (!evas_textblock_cursor_compare(c, en->sel_start)) return;
600
601    evas_textblock_cursor_copy(c, en->sel_start);
602
603    _edje_entry_imf_cursor_info_set(en);
604
605    if (en->selection)
606      {
607         free(en->selection);
608         en->selection = NULL;
609      }
610    _edje_emit(ed, "selection,changed", en->rp->part->name);
611 }
612
613 static void
614 _sel_clear(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
615 {
616    en->had_sel = EINA_FALSE;
617    if (en->sel_start)
618      {
619         evas_textblock_cursor_free(en->sel_start);
620         evas_textblock_cursor_free(en->sel_end);
621         en->sel_start = NULL;
622         en->sel_end = NULL;
623      }
624    if (en->selection)
625      {
626         free(en->selection);
627         en->selection = NULL;
628      }
629    while (en->sel)
630      {
631         Sel *sel;
632
633         sel = en->sel->data;
634         if (sel->obj_bg) evas_object_del(sel->obj_bg);
635         if (sel->obj_fg) evas_object_del(sel->obj_fg);
636         free(sel);
637         en->sel = eina_list_remove_list(en->sel, en->sel);
638      }
639    if (en->have_selection)
640      {
641         en->have_selection = EINA_FALSE;
642         _edje_emit(ed, "selection,cleared", en->rp->part->name);
643      }
644 }
645
646 static void
647 _sel_update(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en)
648 {
649    Evas_Coord x, y;
650    Evas_Object *smart, *clip;
651
652    smart = evas_object_smart_parent_get(o);
653    clip = evas_object_clip_get(o);
654    if (!en->sel_start)
655       return;
656
657    evas_object_geometry_get(o, &x, &y, NULL, NULL);
658    if (en->have_selection)
659      {
660         Eina_Iterator *range = NULL;
661         Eina_List *l;
662         Sel *sel;
663         Evas_Textblock_Rectangle *r;
664
665         range = evas_textblock_cursor_range_simple_geometry_get(en->sel_start,
666                                                                 en->sel_end);
667
668         l = en->sel;
669         EINA_ITERATOR_FOREACH(range, r)
670           {
671              if (!l)
672                {
673                   Evas_Object *ob;
674
675                   sel = calloc(1, sizeof(Sel));
676                   en->sel = eina_list_append(en->sel, sel);
677                   ob = edje_object_add(ed->base->evas);
678                   edje_object_file_set(ob, ed->path, en->rp->part->source);
679                   evas_object_smart_member_add(ob, smart);
680                   evas_object_stack_below(ob, o);
681                   evas_object_clip_set(ob, clip);
682                   evas_object_pass_events_set(ob, EINA_TRUE);
683                   evas_object_show(ob);
684                   sel->obj_bg = ob;
685                   _edje_subobj_register(ed, sel->obj_bg);
686
687                   ob = edje_object_add(ed->base->evas);
688                   edje_object_file_set(ob, ed->path, en->rp->part->source2);
689                   evas_object_smart_member_add(ob, smart);
690                   evas_object_stack_above(ob, o);
691                   evas_object_clip_set(ob, clip);
692                   evas_object_pass_events_set(ob, EINA_TRUE);
693                   evas_object_show(ob);
694                   sel->obj_fg = ob;
695                   _edje_subobj_register(ed, sel->obj_fg);
696                }
697              else
698                {
699                   sel = eina_list_data_get(l);
700                   l = l->next;
701                }
702              *(&(sel->rect)) = *r;
703
704              if (sel->obj_bg)
705                {
706                   evas_object_move(sel->obj_bg, x + r->x, y + r->y);
707                   evas_object_resize(sel->obj_bg, r->w, r->h);
708                }
709              if (sel->obj_fg)
710                {
711                   evas_object_move(sel->obj_fg, x + r->x, y + r->y);
712                   evas_object_resize(sel->obj_fg, r->w, r->h);
713                }
714              free(r);
715           }
716         eina_iterator_free(range);
717
718         /* delete redundant selection rects */
719         while (l)
720           {
721              Eina_List *temp = l->next;
722              sel = eina_list_data_get(l);
723              if (sel)
724                {
725                   if (sel->obj_bg) evas_object_del(sel->obj_bg);
726                   if (sel->obj_fg) evas_object_del(sel->obj_fg);
727                   free(sel);
728                }
729              en->sel = eina_list_remove_list(en->sel, l);
730              l = temp;
731           }
732      }
733 }
734
735 static void
736 _edje_anchor_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
737 {
738    Anchor *an = data;
739    Evas_Event_Mouse_Down *ev = event_info;
740    Edje_Real_Part *rp = an->en->rp;
741    char *buf, *n;
742    size_t len;
743    int ignored;
744    Entry *en;
745    Edje *ed = an->en->ed;
746
747    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
748        (!rp->typedata.text)) return;
749    en = rp->typedata.text->entry_data;
750    if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
751        (en->select_allow))
752      return;
753
754    ignored = rp->part->ignore_flags & ev->event_flags;
755    if ((!ev->event_flags) || (!ignored))
756      {
757         n = an->name;
758         if (!n) n = "";
759         len = 200 + strlen(n);
760         buf = alloca(len);
761         if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
762           snprintf(buf, len, "anchor,mouse,down,%i,%s,triple", ev->button, n);
763         else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
764           snprintf(buf, len, "anchor,mouse,down,%i,%s,double", ev->button, n);
765         else
766           snprintf(buf, len, "anchor,mouse,down,%i,%s", ev->button, n);
767         _edje_emit(ed, buf, rp->part->name);
768      }
769    ev->event_flags |= rp->part->mask_flags;
770 }
771
772 static void
773 _edje_anchor_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
774 {
775    Anchor *an = data;
776    Evas_Event_Mouse_Up *ev = event_info;
777    Edje_Real_Part *rp = an->en->rp;
778    char *buf, *n;
779    size_t len;
780    int ignored;
781    Entry *en;
782    Edje *ed = an->en->ed;
783
784    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
785        (!rp->typedata.text)) return;
786
787    en = rp->typedata.text->entry_data;
788    ignored = rp->part->ignore_flags & ev->event_flags;
789    n = an->name;
790    if (!n) n = "";
791    len = 200 + strlen(n);
792    buf = alloca(len);
793    if ((rp->part->select_mode != EDJE_ENTRY_SELECTION_MODE_EXPLICIT) ||
794        (!en->select_allow))
795      {
796         if ((!ev->event_flags) || (!ignored))
797           {
798              snprintf(buf, len, "anchor,mouse,up,%i,%s", ev->button, n);
799              _edje_emit(ed, buf, rp->part->name);
800           }
801      }
802    if ((rp->still_in) && (rp->clicked_button == ev->button) && (!ignored))
803      {
804         snprintf(buf, len, "anchor,mouse,clicked,%i,%s", ev->button, n);
805         _edje_emit(ed, buf, rp->part->name);
806      }
807    ev->event_flags |= rp->part->mask_flags;
808 }
809
810 static void
811 _edje_anchor_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
812 {
813    Anchor *an = data;
814    Evas_Event_Mouse_Move *ev = event_info;
815    Edje_Real_Part *rp = an->en->rp;
816    char *buf, *n;
817    size_t len;
818    int ignored;
819    Entry *en;
820    Edje *ed = an->en->ed;
821
822    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
823        (!rp->typedata.text)) return;
824    en = rp->typedata.text->entry_data;
825    if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
826        (en->select_allow))
827      return;
828
829    ignored = rp->part->ignore_flags & ev->event_flags;
830    if ((!ev->event_flags) || (!ignored))
831      {
832         n = an->name;
833         if (!n) n = "";
834         len = 200 + strlen(n);
835         buf = alloca(len);
836         snprintf(buf, len, "anchor,mouse,move,%s", n);
837         _edje_emit(ed, buf, rp->part->name);
838      }
839    ev->event_flags |= rp->part->mask_flags;
840 }
841
842 static void
843 _edje_anchor_mouse_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
844 {
845    Anchor *an = data;
846    Evas_Event_Mouse_In *ev = event_info;
847    Edje_Real_Part *rp = an->en->rp;
848    Edje *ed = an->en->ed;
849    char *buf, *n;
850    size_t len;
851    int ignored;
852
853    ignored = rp->part->ignore_flags & ev->event_flags;
854    if ((!ev->event_flags) || (!ignored))
855      {
856         /* set to allow handling in elementary, in case we have
857          * an unwanted event propagation */
858         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
859
860         n = an->name;
861         if (!n) n = "";
862         len = 200 + strlen(n);
863         buf = alloca(len);
864         snprintf(buf, len, "anchor,mouse,in,%s", n);
865         _edje_emit(ed, buf, rp->part->name);
866      }
867    ev->event_flags |= rp->part->mask_flags;
868 }
869
870 static void
871 _edje_anchor_mouse_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
872 {
873    Anchor *an = data;
874    Evas_Event_Mouse_Out *ev = event_info;
875    Edje_Real_Part *rp = an->en->rp;
876    char *buf, *n;
877    size_t len;
878    int ignored;
879    Edje *ed = an->en->ed;
880
881    ignored = rp->part->ignore_flags & ev->event_flags;
882    if ((!ev->event_flags) || (!ignored))
883      {
884         /* set to allow handling in elementary, in case we have
885          * an unwanted event propagation */
886         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
887
888         n = an->name;
889         if (!n) n = "";
890         len = 200 + strlen(n);
891         buf = alloca(len);
892         snprintf(buf, len, "anchor,mouse,out,%s", n);
893         _edje_emit(ed, buf, rp->part->name);
894      }
895    ev->event_flags |= rp->part->mask_flags;
896 }
897
898 static void
899 _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
900 {
901    Eina_List *l, *ll, *range = NULL;
902    Evas_Coord x, y, w, h;
903    Evas_Object *smart, *clip;
904    Sel *sel;
905    Anchor *an;
906    Edje *ed = en->ed;
907
908    smart = evas_object_smart_parent_get(o);
909    clip = evas_object_clip_get(o);
910    x = y = w = h = -1;
911    evas_object_geometry_get(o, &x, &y, &w, &h);
912    EINA_LIST_FOREACH(en->anchors, l, an)
913      {
914         // for item anchors
915         if (an->item)
916           {
917              Evas_Object *ob;
918
919              if (!an->sel)
920                {
921                   while (an->sel)
922                     {
923                        sel = an->sel->data;
924                        if (sel->obj_bg) evas_object_del(sel->obj_bg);
925                        if (sel->obj_fg) evas_object_del(sel->obj_fg);
926                        if (sel->obj) evas_object_del(sel->obj);
927                        free(sel);
928                        an->sel = eina_list_remove_list(an->sel, an->sel);
929                     }
930
931                   sel = calloc(1, sizeof(Sel));
932                   an->sel = eina_list_append(an->sel, sel);
933
934                   if (ed->item_provider.func)
935                     {
936                        ob = ed->item_provider.func
937                          (ed->item_provider.data, smart,
938                              en->rp->part->name, an->name);
939                        evas_object_smart_member_add(ob, smart);
940                        evas_object_stack_above(ob, o);
941                        evas_object_clip_set(ob, clip);
942                        evas_object_pass_events_set(ob, EINA_TRUE);
943                        evas_object_show(ob);
944                        sel->obj = ob;
945                     }
946                }
947           }
948         // for link anchors
949         else
950           {
951              range =
952                evas_textblock_cursor_range_geometry_get(an->start, an->end);
953              if (eina_list_count(range) != eina_list_count(an->sel))
954                {
955                   while (an->sel)
956                     {
957                        sel = an->sel->data;
958                        if (sel->obj_bg) evas_object_del(sel->obj_bg);
959                        if (sel->obj_fg) evas_object_del(sel->obj_fg);
960                        if (sel->obj) evas_object_del(sel->obj);
961                        free(sel);
962                        an->sel = eina_list_remove_list(an->sel, an->sel);
963                     }
964                   for (ll = range; ll; ll = eina_list_next(ll))
965                     {
966                        Evas_Object *ob;
967
968                        sel = calloc(1, sizeof(Sel));
969                        an->sel = eina_list_append(an->sel, sel);
970                        ob = edje_object_add(ed->base->evas);
971                        edje_object_file_set(ob, ed->path, en->rp->part->source5);
972                        evas_object_smart_member_add(ob, smart);
973                        evas_object_stack_below(ob, o);
974                        evas_object_clip_set(ob, clip);
975                        evas_object_pass_events_set(ob, EINA_TRUE);
976                        evas_object_show(ob);
977                        sel->obj_bg = ob;
978                        _edje_subobj_register(ed, sel->obj_bg);
979
980                        ob = edje_object_add(ed->base->evas);
981                        edje_object_file_set(ob, ed->path, en->rp->part->source6);
982                        evas_object_smart_member_add(ob, smart);
983                        evas_object_stack_above(ob, o);
984                        evas_object_clip_set(ob, clip);
985                        evas_object_pass_events_set(ob, EINA_TRUE);
986                        evas_object_show(ob);
987                        sel->obj_fg = ob;
988                        _edje_subobj_register(ed, sel->obj_fg);
989
990                        ob = evas_object_rectangle_add(ed->base->evas);
991                        evas_object_color_set(ob, 0, 0, 0, 0);
992                        evas_object_smart_member_add(ob, smart);
993                        evas_object_stack_above(ob, o);
994                        evas_object_clip_set(ob, clip);
995                        evas_object_repeat_events_set(ob, EINA_TRUE);
996                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_DOWN, _edje_anchor_mouse_down_cb, an);
997                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_UP, _edje_anchor_mouse_up_cb, an);
998                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_MOVE, _edje_anchor_mouse_move_cb, an);
999                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_IN, _edje_anchor_mouse_in_cb, an);
1000                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_OUT, _edje_anchor_mouse_out_cb, an);
1001                        evas_object_show(ob);
1002                        sel->obj = ob;
1003                     }
1004                }
1005           }
1006         EINA_LIST_FOREACH(an->sel, ll, sel)
1007           {
1008              if (an->item)
1009                {
1010                   Evas_Coord cx, cy, cw, ch;
1011
1012                   if (!evas_textblock_cursor_format_item_geometry_get
1013                       (an->start, &cx, &cy, &cw, &ch))
1014                     continue;
1015                   evas_object_move(sel->obj, x + cx, y + cy);
1016                   evas_object_resize(sel->obj, cw, ch);
1017                }
1018              else
1019                {
1020                   Evas_Textblock_Rectangle *r;
1021
1022                   r = range->data;
1023                   *(&(sel->rect)) = *r;
1024                   if (sel->obj_bg)
1025                     {
1026                        evas_object_move(sel->obj_bg, x + r->x, y + r->y);
1027                        evas_object_resize(sel->obj_bg, r->w, r->h);
1028                     }
1029                   if (sel->obj_fg)
1030                     {
1031                        evas_object_move(sel->obj_fg, x + r->x, y + r->y);
1032                        evas_object_resize(sel->obj_fg, r->w, r->h);
1033                     }
1034                   if (sel->obj)
1035                     {
1036                        evas_object_move(sel->obj, x + r->x, y + r->y);
1037                        evas_object_resize(sel->obj, r->w, r->h);
1038                     }
1039                   range = eina_list_remove_list(range, range);
1040                   free(r);
1041                }
1042           }
1043      }
1044 }
1045
1046 static void
1047 _anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
1048 {
1049    while (en->anchorlist)
1050      {
1051         free(en->anchorlist->data);
1052         en->anchorlist = eina_list_remove_list(en->anchorlist, en->anchorlist);
1053      }
1054    while (en->itemlist)
1055      {
1056         free(en->itemlist->data);
1057         en->itemlist = eina_list_remove_list(en->itemlist, en->itemlist);
1058      }
1059    while (en->anchors)
1060      {
1061         Anchor *an = en->anchors->data;
1062
1063         evas_textblock_cursor_free(an->start);
1064         evas_textblock_cursor_free(an->end);
1065         while (an->sel)
1066           {
1067              Sel *sel = an->sel->data;
1068              if (sel->obj_bg) evas_object_del(sel->obj_bg);
1069              if (sel->obj_fg) evas_object_del(sel->obj_fg);
1070              if (sel->obj) evas_object_del(sel->obj);
1071              free(sel);
1072              an->sel = eina_list_remove_list(an->sel, an->sel);
1073           }
1074         free(an->name);
1075         free(an);
1076         en->anchors = eina_list_remove_list(en->anchors, en->anchors);
1077      }
1078 }
1079
1080 /* FIXME: This is horrible. It's just a copy&paste (with some adjustments)
1081  * from textblock. I didn't want to introduce any non-API links between the
1082  * libs so I just copied it. Should have been handled differently. */
1083 static char *
1084 _anchor_format_parse(const char *item)
1085 {
1086    const char *start, *end;
1087    char *tmp;
1088    size_t len;
1089
1090    start = strchr(item, '=');
1091    if (!start) return NULL;
1092
1093    start++; /* Advance after the '=' */
1094    /* If we can find a quote as the first non-space char,
1095     * our new delimiter is a quote, not a space. */
1096    while (*start == ' ')
1097       start++;
1098
1099    if (*start == '\'')
1100      {
1101         start++;
1102         end = strchr(start, '\'');
1103         while ((end) && (end > start) && (end[-1] == '\\'))
1104           end = strchr(end + 1, '\'');
1105      }
1106    else
1107      {
1108         end = strchr(start, ' ');
1109         while ((end) && (end > start) && (end[-1] == '\\'))
1110           end = strchr(end + 1, ' ');
1111      }
1112
1113    /* Null terminate before the spaces */
1114    if (end) len = end - start;
1115    else len = strlen(start);
1116
1117    tmp = malloc(len + 1);
1118    strncpy(tmp, start, len);
1119    tmp[len] = '\0';
1120
1121    return tmp;
1122 }
1123
1124 static void
1125 _anchors_get(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
1126 {
1127    const Eina_List *anchors_a, *anchors_item;
1128    Anchor *an = NULL;
1129    _anchors_clear(c, o, en);
1130
1131    anchors_a = evas_textblock_node_format_list_get(o, "a");
1132    anchors_item = evas_textblock_node_format_list_get(o, "item");
1133
1134    if (anchors_a)
1135      {
1136         const Evas_Object_Textblock_Node_Format *node;
1137         const Eina_List *itr;
1138         EINA_LIST_FOREACH(anchors_a, itr, node)
1139           {
1140              const char *s = evas_textblock_node_format_text_get(node);
1141              char *p;
1142              an = calloc(1, sizeof(Anchor));
1143              if (!an)
1144                break;
1145
1146              an->en = en;
1147              p = strstr(s, "href=");
1148              if (p)
1149                {
1150                   an->name = _anchor_format_parse(p);
1151                }
1152              en->anchors = eina_list_append(en->anchors, an);
1153              an->start = evas_object_textblock_cursor_new(o);
1154              an->end = evas_object_textblock_cursor_new(o);
1155              evas_textblock_cursor_at_format_set(an->start, node);
1156              evas_textblock_cursor_copy(an->start, an->end);
1157
1158              /* Close the anchor, if the anchor was without text,
1159               * free it as well */
1160              node = evas_textblock_node_format_next_get(node);
1161              for (; node; node = evas_textblock_node_format_next_get(node))
1162                {
1163                   s = evas_textblock_node_format_text_get(node);
1164                   if ((!strcmp(s, "- a")) || (!strcmp(s, "-a")))
1165                     break;
1166                }
1167
1168              if (node)
1169                {
1170                   evas_textblock_cursor_at_format_set(an->end, node);
1171                }
1172              else if (!evas_textblock_cursor_compare(an->start, an->end))
1173                {
1174                   if (an->name) free(an->name);
1175                   evas_textblock_cursor_free(an->start);
1176                   evas_textblock_cursor_free(an->end);
1177                   en->anchors = eina_list_remove(en->anchors, an);
1178                   free(an);
1179                }
1180              an = NULL;
1181           }
1182      }
1183
1184    if (anchors_item)
1185      {
1186         const Evas_Object_Textblock_Node_Format *node;
1187         const Eina_List *itr;
1188         EINA_LIST_FOREACH(anchors_item, itr, node)
1189           {
1190              const char *s = evas_textblock_node_format_text_get(node);
1191              char *p;
1192              an = calloc(1, sizeof(Anchor));
1193              if (!an)
1194                break;
1195
1196              an->en = en;
1197              an->item = 1;
1198              p = strstr(s, "href=");
1199              if (p)
1200                {
1201                   an->name = _anchor_format_parse(p);
1202                }
1203              en->anchors = eina_list_append(en->anchors, an);
1204              an->start = evas_object_textblock_cursor_new(o);
1205              an->end = evas_object_textblock_cursor_new(o);
1206              evas_textblock_cursor_at_format_set(an->start, node);
1207              evas_textblock_cursor_copy(an->start, an->end);
1208              /* Although needed in textblock, don't bother with finding the end
1209               * here cause it doesn't really matter. */
1210           }
1211      }
1212 }
1213
1214 static void
1215 _free_entry_change_info(void *_info)
1216 {
1217    Edje_Entry_Change_Info *info = (Edje_Entry_Change_Info *) _info;
1218    if (info->insert)
1219      {
1220         eina_stringshare_del(info->change.insert.content);
1221      }
1222    else
1223      {
1224         eina_stringshare_del(info->change.del.content);
1225      }
1226    free(info);
1227 }
1228
1229 static void
1230 _range_del_emit(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
1231 {
1232    size_t start, end;
1233    char *tmp;
1234    Edje_Entry_Change_Info *info;
1235
1236    start = evas_textblock_cursor_pos_get(en->sel_start);
1237    end = evas_textblock_cursor_pos_get(en->sel_end);
1238    if (start == end)
1239       goto noop;
1240
1241    info = calloc(1, sizeof(*info));
1242    info->insert = EINA_FALSE;
1243    info->change.del.start = start;
1244    info->change.del.end = end;
1245
1246    tmp = evas_textblock_cursor_range_text_get(en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
1247    info->change.del.content = eina_stringshare_add(tmp);
1248    if (tmp) free(tmp);
1249    evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1250    _edje_emit(ed, "entry,changed", en->rp->part->name);
1251    _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info,
1252                    _free_entry_change_info);
1253 noop:
1254    _sel_clear(ed, en->cursor, en->rp->object, en);
1255 }
1256
1257 //static void
1258 //_range_del(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
1259 //{
1260 //   evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1261 //   _sel_clear(ed, en->cursor, en->rp->object, en);
1262 //}
1263
1264 static void
1265 _delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos,
1266              Eina_Bool backspace)
1267 {
1268    if (!evas_textblock_cursor_char_next(c))
1269      {
1270         return;
1271      }
1272    evas_textblock_cursor_char_prev(c);
1273
1274    Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1275    char *tmp = evas_textblock_cursor_content_get(c);
1276
1277    info->insert = EINA_FALSE;
1278    if (backspace)
1279      {
1280         info->change.del.start = pos - 1;
1281         info->change.del.end = pos;
1282      }
1283    else
1284      {
1285         info->change.del.start = pos + 1;
1286         info->change.del.end = pos;
1287      }
1288
1289    info->change.del.content = eina_stringshare_add(tmp);
1290    if (tmp) free(tmp);
1291
1292    evas_textblock_cursor_char_delete(c);
1293    _edje_emit(ed, "entry,changed", en->rp->part->name);
1294    _edje_emit_full(ed, "entry,changed,user", en->rp->part->name,
1295                    info, _free_entry_change_info);
1296 }
1297
1298 static void
1299 _edje_entry_hide_visible_password(Edje *ed, Edje_Real_Part *rp)
1300 {
1301    const Evas_Object_Textblock_Node_Format *node;
1302    node = evas_textblock_node_format_first_get(rp->object);
1303    for (; node; node = evas_textblock_node_format_next_get(node))
1304      {
1305         const char *text = evas_textblock_node_format_text_get(node);
1306         if (text)
1307           {
1308              if (!strcmp(text, "+ password=off"))
1309                {
1310                   evas_textblock_node_format_remove_pair(rp->object,
1311                                                          (Evas_Object_Textblock_Node_Format *) node);
1312                   _edje_emit(ed, "entry,changed", rp->part->name);
1313                   break;
1314                }
1315           }
1316      }
1317    _edje_entry_real_part_configure(ed, rp);
1318 }
1319
1320 static Eina_Bool
1321 _password_timer_cb(void *data)
1322 {
1323    Entry *en = (Entry *)data;
1324    _edje_entry_hide_visible_password(en->ed, en->rp);
1325    en->pw_timer = NULL;
1326    return ECORE_CALLBACK_CANCEL;
1327 }
1328
1329 static Eina_Bool
1330 _is_modifier(const char *key)
1331 {
1332    if ((!strncmp(key, "Shift", 5)) ||
1333        (!strncmp(key, "Control", 7)) ||
1334        (!strncmp(key, "Alt", 3)) ||
1335        (!strncmp(key, "Meta", 4)) ||
1336        (!strncmp(key, "Super", 5)) ||
1337        (!strncmp(key, "Hyper", 5)) ||
1338        (!strcmp(key, "Scroll_Lock")) ||
1339        (!strcmp(key, "Num_Lock")) ||
1340        (!strcmp(key, "Caps_Lock")))
1341      return EINA_TRUE;
1342    return EINA_FALSE;
1343 }
1344
1345 static void
1346 _compose_seq_reset(Entry *en)
1347 {
1348    char *str;
1349
1350    EINA_LIST_FREE(en->seq, str) eina_stringshare_del(str);
1351    en->composing = EINA_FALSE;
1352 }
1353
1354 static void
1355 _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1356 {
1357    Edje *ed = data;
1358    Evas_Event_Key_Down *ev = event_info;
1359    Edje_Real_Part *rp = ed->focused_part;
1360    Entry *en;
1361    Eina_Bool control, alt, shift;
1362    Eina_Bool multiline;
1363    Eina_Bool cursor_changed;
1364    int old_cur_pos;
1365    if (!rp) return;
1366    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
1367        (!rp->typedata.text)) return;
1368    en = rp->typedata.text->entry_data;
1369    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1370        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1371      return;
1372    if (!ev->key) return;
1373
1374    _edje_emit(ed, "entry,keydown", rp->part->name);
1375 #ifdef HAVE_ECORE_IMF
1376    if (en->imf_context)
1377      {
1378         Ecore_IMF_Event_Key_Down ecore_ev;
1379         ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
1380         if (!en->composing)
1381           {
1382              if (ecore_imf_context_filter_event(en->imf_context,
1383                                                 ECORE_IMF_EVENT_KEY_DOWN,
1384                                                 (Ecore_IMF_Event *)&ecore_ev))
1385                {
1386                   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1387                   return;
1388                }
1389           }
1390      }
1391 #endif
1392
1393    old_cur_pos = evas_textblock_cursor_pos_get(en->cursor);
1394
1395    control = evas_key_modifier_is_set(ev->modifiers, "Control");
1396    alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
1397    shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
1398    multiline = rp->part->multiline;
1399    cursor_changed = EINA_FALSE;
1400    if (!strcmp(ev->key, "Escape"))
1401      {
1402         _compose_seq_reset(en);
1403         // dead keys here. Escape for now (should emit these)
1404         _edje_emit(ed, "entry,key,escape", rp->part->name);
1405         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1406      }
1407    else if (!strcmp(ev->key, "Up") ||
1408             (!strcmp(ev->key, "KP_Up") && !ev->string))
1409      {
1410         _compose_seq_reset(en);
1411         if (multiline)
1412           {
1413              if (en->have_selection &&
1414                  (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1415                ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1416              if (en->select_allow)
1417                {
1418                   if (shift)
1419                     {
1420                        _sel_start(en->cursor, rp->object, en);
1421                        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1422                     }
1423                   else if (en->have_selection)
1424                     {
1425                        if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1426                          evas_textblock_cursor_copy(en->sel_start, en->cursor);
1427                        else
1428                          evas_textblock_cursor_copy(en->sel_end, en->cursor);
1429                        _sel_clear(ed, en->cursor, rp->object, en);
1430                     }
1431                }
1432              if (_curs_up(en->cursor, rp->object, en))
1433                ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1434              if (en->select_allow)
1435                {
1436                   if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1437                   else _sel_clear(ed, en->cursor, rp->object, en);
1438                }
1439           }
1440         _edje_emit(ed, "entry,key,up", rp->part->name);
1441         _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1442      }
1443    else if (!strcmp(ev->key, "Down") ||
1444             (!strcmp(ev->key, "KP_Down") && !ev->string))
1445      {
1446         _compose_seq_reset(en);
1447         if (multiline)
1448           {
1449              if (en->have_selection &&
1450                  (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1451                ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1452              if (en->select_allow)
1453                {
1454                   if (shift)
1455                     {
1456                        _sel_start(en->cursor, rp->object, en);
1457                        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1458                     }
1459                   else if (en->have_selection)
1460                     {
1461                        if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1462                          evas_textblock_cursor_copy(en->sel_end, en->cursor);
1463                        else
1464                          evas_textblock_cursor_copy(en->sel_start, en->cursor);
1465                        _sel_clear(ed, en->cursor, rp->object, en);
1466                     }
1467                }
1468              if (_curs_down(en->cursor, rp->object, en))
1469                ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1470              if (en->select_allow)
1471                {
1472                   if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1473                   else _sel_clear(ed, en->cursor, rp->object, en);
1474                }
1475           }
1476         _edje_emit(ed, "entry,key,down", rp->part->name);
1477         _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1478      }
1479    else if (!strcmp(ev->key, "Left") ||
1480             (!strcmp(ev->key, "KP_Left") && !ev->string))
1481      {
1482         _compose_seq_reset(en);
1483         if (en->have_selection &&
1484             (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1485           ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1486         if (en->select_allow)
1487           {
1488              if (shift)
1489                {
1490                   _sel_start(en->cursor, rp->object, en);
1491                   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1492                }
1493              else
1494                {
1495                   if (en->have_selection)
1496                     {
1497                        if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1498                          evas_textblock_cursor_copy(en->sel_start, en->cursor);
1499                        else
1500                          evas_textblock_cursor_copy(en->sel_end, en->cursor);
1501                        _sel_clear(ed, en->cursor, rp->object, en);
1502                     }
1503                }
1504           }
1505         // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
1506         //if (evas_textblock_cursor_char_prev(en->cursor))
1507         if (evas_textblock_cursor_cluster_prev(en->cursor))
1508           ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1509         /* If control is pressed, go to the start of the word */
1510         if (control) evas_textblock_cursor_word_start(en->cursor);
1511         if (en->select_allow)
1512           {
1513              if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1514              else _sel_clear(ed, en->cursor, rp->object, en);
1515           }
1516         _edje_emit(ed, "entry,key,left", rp->part->name);
1517         _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1518      }
1519    else if (!strcmp(ev->key, "Right") ||
1520             (!strcmp(ev->key, "KP_Right") && !ev->string))
1521      {
1522         _compose_seq_reset(en);
1523         if (en->have_selection &&
1524             (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1525           ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1526         if (en->select_allow)
1527           {
1528              if (shift)
1529                {
1530                   _sel_start(en->cursor, rp->object, en);
1531                   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1532                }
1533              else
1534                {
1535                   if (en->have_selection)
1536                     {
1537                        if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1538                          evas_textblock_cursor_copy(en->sel_end, en->cursor);
1539                        else
1540                          evas_textblock_cursor_copy(en->sel_start, en->cursor);
1541                        _sel_clear(ed, en->cursor, rp->object, en);
1542                     }
1543                }
1544           }
1545         /* If control is pressed, go to the end of the word */
1546         if (control) evas_textblock_cursor_word_end(en->cursor);
1547         // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
1548         //if (evas_textblock_cursor_char_next(en->cursor))
1549         if (evas_textblock_cursor_cluster_next(en->cursor))
1550           ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1551         if (en->select_allow)
1552           {
1553              if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1554              else _sel_clear(ed, en->cursor, rp->object, en);
1555           }
1556         _edje_emit(ed, "entry,key,right", rp->part->name);
1557         _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1558      }
1559    else if (!strcmp(ev->key, "BackSpace"))
1560      {
1561         _compose_seq_reset(en);
1562         if (control && !en->have_selection)
1563           {
1564              // del to start of previous word
1565              _sel_start(en->cursor, rp->object, en);
1566
1567              // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
1568              //evas_textblock_cursor_char_prev(en->cursor);
1569              evas_textblock_cursor_cluster_prev(en->cursor);
1570              //
1571              evas_textblock_cursor_word_start(en->cursor);
1572
1573              _sel_preextend(ed, en->cursor, rp->object, en);
1574
1575              _range_del_emit(ed, en->cursor, rp->object, en);
1576           }
1577         else if ((alt) && (shift))
1578           {
1579              // undo last action
1580           }
1581         else
1582           {
1583              if (en->have_selection)
1584                {
1585                   _range_del_emit(ed, en->cursor, rp->object, en);
1586                }
1587              else
1588                {
1589                   if (evas_textblock_cursor_char_prev(en->cursor))
1590                     {
1591                        _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_TRUE);
1592                     }
1593                }
1594           }
1595         _sel_clear(ed, en->cursor, rp->object, en);
1596         _anchors_get(en->cursor, rp->object, en);
1597         _edje_emit(ed, "entry,key,backspace", rp->part->name);
1598         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1599      }
1600    else if (!strcmp(ev->key, "Delete") ||
1601             (!strcmp(ev->key, "KP_Delete") && !ev->string))
1602      {
1603         _compose_seq_reset(en);
1604         if (control)
1605           {
1606              // del to end of next word
1607              _sel_start(en->cursor, rp->object, en);
1608
1609              evas_textblock_cursor_word_end(en->cursor);
1610              // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
1611              //evas_textblock_cursor_char_next(en->cursor);
1612              evas_textblock_cursor_cluster_next(en->cursor);
1613              //
1614
1615              _sel_extend(ed, en->cursor, rp->object, en);
1616
1617              _range_del_emit(ed, en->cursor, rp->object, en);
1618           }
1619         else if (shift)
1620           {
1621              // cut
1622           }
1623         else
1624           {
1625              if (en->have_selection)
1626                {
1627                   _range_del_emit(ed, en->cursor, rp->object, en);
1628                }
1629              else
1630                {
1631                   _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_FALSE);
1632                }
1633           }
1634         _sel_clear(ed, en->cursor, rp->object, en);
1635         _anchors_get(en->cursor, rp->object, en);
1636         _edje_emit(ed, "entry,key,delete", rp->part->name);
1637         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1638      }
1639    else if ((!alt) &&
1640             (!strcmp(ev->key, "Home") ||
1641              ((!strcmp(ev->key, "KP_Home")) && !ev->string)))
1642      {
1643         _compose_seq_reset(en);
1644         if (en->select_allow)
1645           {
1646              if (shift) _sel_start(en->cursor, rp->object, en);
1647              else _sel_clear(ed, en->cursor, rp->object, en);
1648           }
1649         if ((control) && (multiline))
1650           _curs_start(en->cursor, rp->object, en);
1651         else
1652           _curs_lin_start(en->cursor, rp->object, en);
1653         if (en->select_allow)
1654           {
1655              if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1656           }
1657         _edje_emit(ed, "entry,key,home", rp->part->name);
1658         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1659      }
1660    else if ((!alt) &&
1661             (!strcmp(ev->key, "End") ||
1662              ((!strcmp(ev->key, "KP_End")) && !ev->string)))
1663      {
1664         _compose_seq_reset(en);
1665         if (en->select_allow)
1666           {
1667              if (shift) _sel_start(en->cursor, rp->object, en);
1668              else _sel_clear(ed, en->cursor, rp->object, en);
1669           }
1670         if ((control) && (multiline))
1671           _curs_end(en->cursor, rp->object, en);
1672         else
1673           _curs_lin_end(en->cursor, rp->object, en);
1674         if (en->select_allow)
1675           {
1676              if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1677           }
1678         _edje_emit(ed, "entry,key,end", rp->part->name);
1679         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1680      }
1681    else if ((control) && (!shift) && (!strcmp(ev->key, "v")))
1682      {
1683         _compose_seq_reset(en);
1684         _edje_emit(ed, "entry,paste,request", rp->part->name);
1685         _edje_emit(ed, "entry,paste,request,3", rp->part->name);
1686         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1687      }
1688    else if ((control) && (!strcmp(ev->key, "a")))
1689      {
1690         _compose_seq_reset(en);
1691         if (shift)
1692           {
1693              _edje_emit(ed, "entry,selection,none,request", rp->part->name);
1694              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1695           }
1696         else
1697           {
1698              _edje_emit(ed, "entry,selection,all,request", rp->part->name);
1699              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1700           }
1701      }
1702    else if ((control) && (((!shift) && !strcmp(ev->key, "c")) || !strcmp(ev->key, "Insert")))
1703      {
1704         _compose_seq_reset(en);
1705         _edje_emit(ed, "entry,copy,notify", rp->part->name);
1706         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1707      }
1708    else if ((control) && (!shift) && ((!strcmp(ev->key, "x") || (!strcmp(ev->key, "m")))))
1709      {
1710         _compose_seq_reset(en);
1711         _edje_emit(ed, "entry,cut,notify", rp->part->name);
1712         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1713      }
1714    else if ((control) && (!strcmp(ev->key, "z")))
1715      {
1716         _compose_seq_reset(en);
1717         if (shift)
1718           {
1719              // redo
1720              _edje_emit(ed, "entry,redo,request", rp->part->name);
1721           }
1722         else
1723           {
1724              // undo
1725              _edje_emit(ed, "entry,undo,request", rp->part->name);
1726           }
1727         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1728      }
1729    else if ((control) && (!shift) && (!strcmp(ev->key, "y")))
1730      {
1731         _compose_seq_reset(en);
1732         // redo
1733         _edje_emit(ed, "entry,redo,request", rp->part->name);
1734         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1735      }
1736    //else if ((control) && (!shift) && (!strcmp(ev->key, "w")))
1737      //{
1738         //_compose_seq_reset(en);
1739         //_sel_clear(ed, en->cursor, rp->object, en);
1740          //select current word?
1741         //ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1742      //}
1743    else if (!strcmp(ev->key, "Tab"))
1744      {
1745         _compose_seq_reset(en);
1746         if (multiline)
1747           {
1748              if (shift)
1749                {
1750                   // remove a tab
1751                }
1752              else
1753                {
1754                   Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1755                   info->insert = EINA_TRUE;
1756                   info->change.insert.plain_length = 1;
1757
1758                   if (en->have_selection)
1759                     {
1760                        _range_del_emit(ed, en->cursor, rp->object, en);
1761                        info->merge = EINA_TRUE;
1762                     }
1763                   info->change.insert.pos =
1764                      evas_textblock_cursor_pos_get(en->cursor);
1765                   info->change.insert.content = eina_stringshare_add("<tab/>");
1766                   _text_filter_format_prepend(ed, en, en->cursor, "tab");
1767                   _anchors_get(en->cursor, rp->object, en);
1768                   _edje_emit(ed, "entry,changed", rp->part->name);
1769                   _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1770                                   info, _free_entry_change_info);
1771                }
1772              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1773           }
1774         _edje_emit(ed, "entry,key,tab", rp->part->name);
1775      }
1776    else if ((!strcmp(ev->key, "ISO_Left_Tab")) && (multiline))
1777      {
1778         _compose_seq_reset(en);
1779         // remove a tab
1780         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1781      }
1782    else if (!strcmp(ev->key, "Prior") ||
1783             (!strcmp(ev->key, "KP_Prior") && !ev->string))
1784      {
1785         _compose_seq_reset(en);
1786         if (en->select_allow)
1787           {
1788              if (shift) _sel_start(en->cursor, rp->object, en);
1789              else _sel_clear(ed, en->cursor, rp->object, en);
1790           }
1791         if (!_curs_jump_line_by(en->cursor, rp->object, en, -10))
1792           {
1793              evas_textblock_cursor_line_set(en->cursor, 0);
1794              _curs_lin_start(en->cursor, rp->object, en);
1795           }
1796         if (en->select_allow)
1797           {
1798              if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1799              else _sel_clear(ed, en->cursor, rp->object, en);
1800           }
1801         _edje_emit(ed, "entry,key,pgup", rp->part->name);
1802         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1803      }
1804    else if (!strcmp(ev->key, "Next") ||
1805             (!strcmp(ev->key, "KP_Next") && !ev->string))
1806      {
1807         _compose_seq_reset(en);
1808         if (en->select_allow)
1809           {
1810              if (shift) _sel_start(en->cursor, rp->object, en);
1811              else _sel_clear(ed, en->cursor, rp->object, en);
1812           }
1813         if (!_curs_jump_line_by(en->cursor, rp->object, en, 10))
1814           {
1815              int last = _curs_line_last_get(en->cursor, rp->object, en);
1816              evas_textblock_cursor_line_set(en->cursor, last);
1817              _curs_lin_end(en->cursor, rp->object, en);
1818           }
1819         if (en->select_allow)
1820           {
1821              if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1822              else _sel_clear(ed, en->cursor, rp->object, en);
1823           }
1824         _edje_emit(ed, "entry,key,pgdn", rp->part->name);
1825         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1826      }
1827    else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
1828      {
1829         _compose_seq_reset(en);
1830         if (multiline)
1831           {
1832              Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1833              info->insert = EINA_TRUE;
1834              info->change.insert.plain_length = 1;
1835              if (en->have_selection)
1836                {
1837                   _range_del_emit(ed, en->cursor, rp->object, en);
1838                   info->merge = EINA_TRUE;
1839                }
1840
1841              info->change.insert.pos =
1842                 evas_textblock_cursor_pos_get(en->cursor);
1843              if (shift ||
1844                  evas_object_textblock_legacy_newline_get(rp->object))
1845                {
1846                   _text_filter_format_prepend(ed, en, en->cursor, "br");
1847                   info->change.insert.content = eina_stringshare_add("<br/>");
1848                }
1849              else
1850                {
1851                   _text_filter_format_prepend(ed, en, en->cursor, "ps");
1852                   info->change.insert.content = eina_stringshare_add("<ps/>");
1853                }
1854              _anchors_get(en->cursor, rp->object, en);
1855              _edje_emit(ed, "entry,changed", rp->part->name);
1856              _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1857                              info, _free_entry_change_info);
1858              _edje_emit(ed, "cursor,changed", rp->part->name);
1859              cursor_changed = EINA_TRUE;
1860              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1861           }
1862         _edje_emit(ed, "entry,key,enter", rp->part->name);
1863      }
1864    else
1865      {
1866         char *compres = NULL, *string = (char *)ev->string;
1867         Eina_Bool free_string = EINA_FALSE;
1868         Ecore_Compose_State state;
1869
1870         if (!en->composing)
1871           {
1872              _compose_seq_reset(en);
1873              en->seq = eina_list_append(en->seq, eina_stringshare_add(ev->key));
1874              state = ecore_compose_get(en->seq, &compres);
1875              if (state == ECORE_COMPOSE_MIDDLE) en->composing = EINA_TRUE;
1876              else en->composing = EINA_FALSE;
1877              if (!en->composing)
1878                {
1879                   free(compres);
1880                   compres = NULL;
1881                   _compose_seq_reset(en);
1882                   if (ev->string && (!ev->string[1]) && (ev->string[0] < 0x20))
1883                     goto end;
1884                }
1885              else
1886                {
1887                   free(compres);
1888                   compres = NULL;
1889                   goto end;
1890                }
1891           }
1892         else
1893           {
1894              if (_is_modifier(ev->key)) goto end;
1895              en->seq = eina_list_append(en->seq, eina_stringshare_add(ev->key));
1896              state = ecore_compose_get(en->seq, &compres);
1897              if (state == ECORE_COMPOSE_NONE)
1898                {
1899                   _compose_seq_reset(en);
1900                   free(compres);
1901                   compres = NULL;
1902                }
1903              else if (state == ECORE_COMPOSE_DONE)
1904                {
1905                   _compose_seq_reset(en);
1906                   if (compres)
1907                     {
1908                        string = compres;
1909                        free_string = EINA_TRUE;
1910                     }
1911                   else free(compres);
1912                   compres = NULL;
1913                }
1914              else
1915                {
1916                   free(compres);
1917                   compres = NULL;
1918                   goto end;
1919                }
1920           }
1921         if (string)
1922           {
1923              Edje_Entry_Change_Info *info = NULL;
1924 // if PASSWORD_SHOW_LAST mode, appending text with password=off tag
1925              if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
1926                  _edje_password_show_last)
1927                {
1928                   _edje_entry_hide_visible_password(ed, en->rp);
1929                   info = _text_filter_text_prepend(ed, en, en->cursor, string,
1930                                                    "+ password=off",
1931                                                    "- password",
1932                                                    EINA_TRUE, EINA_TRUE);
1933                   if (info)
1934                     {
1935                        if (en->pw_timer)
1936                          {
1937                             ecore_timer_del(en->pw_timer);
1938                             en->pw_timer = NULL;
1939                          }
1940                        if (_edje_password_show_last_timeout >= 0)
1941                          en->pw_timer = ecore_timer_add
1942                            (_edje_password_show_last_timeout,
1943                              _password_timer_cb, en);
1944                     }
1945                }
1946              else
1947                info = _text_filter_text_prepend(ed, en, en->cursor, string,
1948                                                 NULL, NULL,
1949                                                 EINA_TRUE, EINA_TRUE);
1950              _anchors_get(en->cursor, rp->object, en);
1951              if (info)
1952                {
1953                   _edje_emit(ed, "entry,changed", rp->part->name);
1954                   _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1955                                   info, _free_entry_change_info);
1956                   _edje_emit(ed, "cursor,changed", rp->part->name);
1957                   cursor_changed = EINA_TRUE;
1958                   ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1959                }
1960              if (free_string) free(string);
1961           }
1962      }
1963 end:
1964    if (!cursor_changed &&
1965        (old_cur_pos != evas_textblock_cursor_pos_get(en->cursor)))
1966      _edje_emit(ed, "cursor,changed", rp->part->name);
1967
1968    _edje_entry_imf_cursor_info_set(en);
1969    _edje_entry_real_part_configure(ed, rp);
1970 }
1971
1972 static void
1973 _edje_key_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1974 {
1975    Edje *ed = data;
1976    Edje_Real_Part *rp = ed->focused_part;
1977    Entry *en;
1978
1979    if (!rp) return;
1980    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
1981        (!rp->typedata.text)) return;
1982    en = rp->typedata.text->entry_data;
1983    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1984        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1985      return;
1986
1987    _edje_emit(ed, "entry,keyup", rp->part->name);
1988 #ifdef HAVE_ECORE_IMF
1989    if (en->imf_context)
1990      {
1991         Evas_Event_Key_Up *ev = event_info;
1992         Ecore_IMF_Event_Key_Up ecore_ev;
1993
1994         ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev);
1995         if (ecore_imf_context_filter_event(en->imf_context,
1996                                            ECORE_IMF_EVENT_KEY_UP,
1997                                            (Ecore_IMF_Event *)&ecore_ev))
1998           return;
1999      }
2000 #else
2001    (void) event_info;
2002 #endif
2003 }
2004
2005 static void
2006 _edje_part_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2007 {
2008    Edje_Real_Part *rp = data;
2009    Entry *en;
2010    if (!rp) return;
2011    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2012        (!rp->typedata.text)) return;
2013    en = rp->typedata.text->entry_data;
2014    if (!en) return;
2015    _edje_entry_imf_cursor_location_set(en);
2016 }
2017
2018 static void
2019 _edje_part_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2020 {
2021    Evas_Coord cx, cy;
2022    Edje_Real_Part *rp = data;
2023    Evas_Event_Mouse_Down *ev = event_info;
2024    Entry *en;
2025    Evas_Coord x, y, w, h;
2026    //   Eina_Bool multiline;
2027    Evas_Textblock_Cursor *tc = NULL;
2028    // TIZEN_ONLY (20150825): For cursor positioning when mouse down
2029    Evas_Coord fh = 0, cly = 0;
2030    Evas_Textblock_Cursor *line_cur;
2031    //
2032    Eina_Bool dosel = EINA_FALSE;
2033    Eina_Bool shift;
2034    if ((!rp) || (!ev)) return;
2035    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
2036    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2037        (!rp->typedata.text)) return;
2038    en = rp->typedata.text->entry_data;
2039    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2040        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2041      return;
2042    if ((ev->button != 1) && (ev->button != 2)) return;
2043
2044 #ifdef HAVE_ECORE_IMF
2045    if (en->imf_context)
2046      {
2047         Ecore_IMF_Event_Mouse_Down ecore_ev;
2048         ecore_imf_evas_event_mouse_down_wrap(ev, &ecore_ev);
2049         if (ecore_imf_context_filter_event(en->imf_context,
2050                                            ECORE_IMF_EVENT_MOUSE_DOWN,
2051                                            (Ecore_IMF_Event *)&ecore_ev))
2052           return;
2053      }
2054 #endif
2055
2056    _edje_entry_imf_context_reset(rp);
2057
2058    shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
2059    en->select_mod_start = EINA_FALSE;
2060    en->select_mod_end = EINA_FALSE;
2061
2062    if (en->select_allow && ev->button != 2) dosel = EINA_TRUE;
2063    if (dosel)
2064      {
2065         if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
2066           {
2067              if (shift)
2068                {
2069                   tc = evas_object_textblock_cursor_new(rp->object);
2070                   evas_textblock_cursor_copy(en->cursor, tc);
2071                   if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
2072                     evas_textblock_cursor_line_char_first(en->cursor);
2073                   else
2074                     evas_textblock_cursor_line_char_last(en->cursor);
2075                   _sel_extend(en->ed, en->cursor, rp->object, en);
2076                }
2077              else
2078                {
2079                   en->have_selection = EINA_FALSE;
2080                   en->selecting = EINA_FALSE;
2081                   _sel_clear(en->ed, en->cursor, rp->object, en);
2082                   tc = evas_object_textblock_cursor_new(rp->object);
2083                   evas_textblock_cursor_copy(en->cursor, tc);
2084                   evas_textblock_cursor_line_char_first(en->cursor);
2085                   _sel_start(en->cursor, rp->object, en);
2086                   evas_textblock_cursor_line_char_last(en->cursor);
2087                   _sel_extend(en->ed, en->cursor, rp->object, en);
2088                }
2089              goto end;
2090           }
2091         else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
2092           {
2093              if (shift)
2094                {
2095                   tc = evas_object_textblock_cursor_new(rp->object);
2096                   evas_textblock_cursor_copy(en->cursor, tc);
2097                   if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
2098                     evas_textblock_cursor_word_start(en->cursor);
2099                   else
2100                     {
2101                        evas_textblock_cursor_word_end(en->cursor);
2102                        // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
2103                        //evas_textblock_cursor_char_next(en->cursor);
2104                        evas_textblock_cursor_cluster_next(en->cursor);
2105                        //
2106                     }
2107                   _sel_extend(en->ed, en->cursor, rp->object, en);
2108                }
2109              else
2110                {
2111                   en->have_selection = EINA_FALSE;
2112                   en->selecting = EINA_FALSE;
2113                   _sel_clear(en->ed, en->cursor, rp->object, en);
2114                   tc = evas_object_textblock_cursor_new(rp->object);
2115                   evas_textblock_cursor_copy(en->cursor, tc);
2116                   evas_textblock_cursor_word_start(en->cursor);
2117                   _sel_start(en->cursor, rp->object, en);
2118                   evas_textblock_cursor_word_end(en->cursor);
2119                   // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
2120                   //evas_textblock_cursor_char_next(en->cursor);
2121                   evas_textblock_cursor_cluster_next(en->cursor);
2122                   //
2123                   _sel_extend(en->ed, en->cursor, rp->object, en);
2124                }
2125              goto end;
2126           }
2127      }
2128    tc = evas_object_textblock_cursor_new(rp->object);
2129    evas_textblock_cursor_copy(en->cursor, tc);
2130    //   multiline = rp->part->multiline;
2131    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2132    cx = ev->canvas.x - x;
2133    cy = ev->canvas.y - y;
2134    // TIZEN_ONLY (20150825): For cursor positioning when down up
2135    evas_object_textblock_size_formatted_get(rp->object, NULL, &fh);
2136    if (cy > fh)
2137      {
2138         cy = fh - 1;
2139      }
2140    line_cur = evas_object_textblock_cursor_new(rp->object);
2141    evas_textblock_cursor_paragraph_first(line_cur);
2142    evas_textblock_cursor_line_geometry_get(line_cur, NULL, &cly, NULL, NULL);
2143
2144    if (cy < cly)
2145      {
2146         cy = cly;
2147      }
2148    evas_textblock_cursor_free(line_cur);
2149    //
2150    // TIZEN ONLY (20150909): only change cursor position in mouse up
2151    //if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2152    if (dosel && !evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2153    //
2154      {
2155         Evas_Coord lx, ly, lw, lh;
2156         int line;
2157
2158         line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
2159         if (line == -1)
2160           {
2161              if (rp->part->multiline)
2162                _curs_end(en->cursor, rp->object, en);
2163              else
2164                {
2165                   evas_textblock_cursor_paragraph_first(en->cursor);
2166                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2167                   if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2168                     _curs_end(en->cursor, rp->object, en);
2169                }
2170           }
2171         else
2172           {
2173              int lnum;
2174
2175              lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2176              if (lnum < 0)
2177                {
2178                   _curs_lin_start(en->cursor, rp->object, en);
2179                }
2180              else
2181                {
2182                   if (cx <= lx)
2183                     _curs_lin_start(en->cursor, rp->object, en);
2184                   else
2185                     _curs_lin_end(en->cursor, rp->object, en);
2186                }
2187           }
2188      }
2189    if (dosel)
2190      {
2191         if ((en->have_selection) &&
2192             (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT))
2193           {
2194              if (shift)
2195                _sel_extend(en->ed, en->cursor, rp->object, en);
2196              else
2197                {
2198                   Eina_List *first, *last;
2199                   FLOAT_T sc;
2200
2201                   first = en->sel;
2202                   last = eina_list_last(en->sel);
2203                   if (first && last)
2204                     {
2205                        Evas_Textblock_Rectangle *r1, *r2;
2206                        Evas_Coord d, d1, d2;
2207
2208                        r1 = first->data;
2209                        r2 = last->data;
2210                        d = r1->x - cx;
2211                        d1 = d * d;
2212                        d = (r1->y + (r1->h / 2)) - cy;
2213                        d1 += d * d;
2214                        d = r2->x + r2->w - 1 - cx;
2215                        d2 = d * d;
2216                        d = (r2->y + (r2->h / 2)) - cy;
2217                        d2 += d * d;
2218                        sc = DIV(en->ed->scale, en->ed->file->base_scale);
2219                        if (sc == ZERO) sc = DIV(_edje_scale, en->ed->file->base_scale);
2220                        d = (Evas_Coord)MUL(FROM_INT(20), sc); // FIXME: maxing number!
2221                        d = d * d;
2222                        if (d1 < d2)
2223                          {
2224                             if (d1 <= d)
2225                               {
2226                                  en->select_mod_start = EINA_TRUE;
2227                                  en->selecting = EINA_TRUE;
2228                               }
2229                          }
2230                        else
2231                          {
2232                             if (d2 <= d)
2233                               {
2234                                  en->select_mod_end = EINA_TRUE;
2235                                  en->selecting = EINA_TRUE;
2236                               }
2237                          }
2238                     }
2239                }
2240           }
2241         else
2242           {
2243              if ((en->have_selection) && (shift))
2244                _sel_extend(en->ed, en->cursor, rp->object, en);
2245              else
2246                {
2247                   en->selecting = EINA_TRUE;
2248                   _sel_clear(en->ed, en->cursor, rp->object, en);
2249                   _sel_start(en->cursor, rp->object, en);
2250                }
2251           }
2252      }
2253  end:
2254    if (evas_textblock_cursor_compare(tc, en->cursor))
2255      {
2256         _edje_emit(en->ed, "cursor,changed", rp->part->name);
2257         _edje_emit(en->ed, "cursor,changed,manual", rp->part->name);
2258      }
2259    evas_textblock_cursor_free(tc);
2260
2261    _edje_entry_real_part_configure(en->ed, rp);
2262    if (ev->button == 2)
2263      {
2264         _edje_emit(en->ed, "entry,paste,request", rp->part->name);
2265         _edje_emit(en->ed, "entry,paste,request,1", rp->part->name);
2266      }
2267 }
2268
2269 static void
2270 _edje_part_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2271 {
2272    Evas_Coord cx, cy;
2273    Edje_Real_Part *rp = data;
2274    Evas_Event_Mouse_Up *ev = event_info;
2275    Entry *en;
2276    Evas_Coord x, y, w, h;
2277    // TIZEN_ONLY (20150813): For cursor positioning when mouse up
2278    Evas_Coord fh = 0, cly = 0;
2279    Evas_Textblock_Cursor *line_cur;
2280    //
2281    Evas_Textblock_Cursor *tc;
2282    if ((!ev) || (ev->button != 1)) return;
2283    if (!rp) return;
2284    if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) return;
2285    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) return;
2286    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2287        (!rp->typedata.text)) return;
2288    en = rp->typedata.text->entry_data;
2289    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2290        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2291      return;
2292
2293
2294    /* We don't check for ON_HOLD because we'd like to end selection anyway when
2295     * mouse is up, even if it's held. */
2296    // TIZEN_ONLY(20150709): When parent is moving entry needs not to update
2297    // cursor and above comment seems not be valid since when parent is moving selection
2298    // cannot be ended.
2299    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
2300      {
2301         _edje_entry_imf_cursor_info_set(en);
2302         return;
2303      }
2304    //
2305
2306 #ifdef HAVE_ECORE_IMF
2307    if (en->imf_context)
2308      {
2309         Ecore_IMF_Event_Mouse_Up ecore_ev;
2310         ecore_imf_evas_event_mouse_up_wrap(ev, &ecore_ev);
2311         if (ecore_imf_context_filter_event(en->imf_context,
2312                                            ECORE_IMF_EVENT_MOUSE_UP,
2313                                            (Ecore_IMF_Event *)&ecore_ev))
2314           return;
2315      }
2316 #endif
2317
2318    tc = evas_object_textblock_cursor_new(rp->object);
2319    evas_textblock_cursor_copy(en->cursor, tc);
2320    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2321    cx = ev->canvas.x - x;
2322    cy = ev->canvas.y - y;
2323    // TIZEN_ONLY (20150813): For cursor positioning when mouse up
2324    evas_object_textblock_size_formatted_get(rp->object, NULL, &fh);
2325    if (cy > fh)
2326      {
2327         cy = fh - 1;
2328      }
2329    line_cur = evas_object_textblock_cursor_new(rp->object);
2330    evas_textblock_cursor_paragraph_first(line_cur);
2331    evas_textblock_cursor_line_geometry_get(line_cur, NULL, &cly, NULL, NULL);
2332
2333    if (cy < cly)
2334      {
2335         cy = cly;
2336      }
2337    evas_textblock_cursor_free(line_cur);
2338    //
2339    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs. //
2340    //if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2341    if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, cy))
2342      {
2343         Evas_Coord lx, ly, lw, lh;
2344         int line;
2345
2346         line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
2347         if (line == -1)
2348           {
2349              if (rp->part->multiline)
2350                _curs_end(en->cursor, rp->object, en);
2351              else
2352                {
2353                   evas_textblock_cursor_paragraph_first(en->cursor);
2354                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2355                   // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
2356                   //if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2357                   if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, ly + (lh / 2)))
2358                     _curs_end(en->cursor, rp->object, en);
2359                }
2360           }
2361         else
2362           {
2363              int lnum;
2364
2365              lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2366              if (lnum < 0)
2367                {
2368                   _curs_lin_start(en->cursor, rp->object, en);
2369                }
2370              else
2371                {
2372                   if (cx <= lx)
2373                     _curs_lin_start(en->cursor, rp->object, en);
2374                   else
2375                     _curs_lin_end(en->cursor, rp->object, en);
2376                }
2377           }
2378      }
2379    if (en->select_allow)
2380      {
2381         if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2382           {
2383              if (en->had_sel)
2384                {
2385                   if (en->select_mod_end)
2386                      _sel_extend(en->ed, en->cursor, rp->object, en);
2387                   else if (en->select_mod_start)
2388                      _sel_preextend(en->ed, en->cursor, rp->object, en);
2389                }
2390              else
2391                 _sel_extend(en->ed, en->cursor, rp->object, en);
2392              //evas_textblock_cursor_copy(en->cursor, en->sel_end);
2393           }
2394         else
2395           {
2396              evas_textblock_cursor_copy(en->cursor, en->sel_end);
2397           }
2398      }
2399    if (en->selecting)
2400      {
2401         if (en->have_selection)
2402           en->had_sel = EINA_TRUE;
2403         en->selecting = EINA_FALSE;
2404      }
2405    if (evas_textblock_cursor_compare(tc, en->cursor))
2406      {
2407         _edje_emit(en->ed, "cursor,changed", rp->part->name);
2408         _edje_emit(en->ed, "cursor,changed,manual", rp->part->name);
2409      }
2410
2411    _edje_entry_imf_cursor_info_set(en);
2412
2413    evas_textblock_cursor_free(tc);
2414
2415    _edje_entry_real_part_configure(en->ed, rp);
2416 }
2417
2418 static void
2419 _edje_part_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2420 {
2421    Evas_Coord cx, cy;
2422    Edje_Real_Part *rp = data;
2423    Evas_Event_Mouse_Move *ev = event_info;
2424    Entry *en;
2425    Evas_Coord x, y, w, h;
2426    Evas_Textblock_Cursor *tc;
2427
2428    if ((!rp) || (!ev)) return;
2429    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2430        (!rp->typedata.text)) return;
2431    en = rp->typedata.text->entry_data;
2432    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2433        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2434      return;
2435
2436 #ifdef HAVE_ECORE_IMF
2437    if (en->imf_context)
2438      {
2439         Ecore_IMF_Event_Mouse_Move ecore_ev;
2440         ecore_imf_evas_event_mouse_move_wrap(ev, &ecore_ev);
2441         if (ecore_imf_context_filter_event(en->imf_context,
2442                                            ECORE_IMF_EVENT_MOUSE_MOVE,
2443                                            (Ecore_IMF_Event *)&ecore_ev))
2444           return;
2445      }
2446 #endif
2447
2448    if (en->selecting)
2449      {
2450         tc = evas_object_textblock_cursor_new(rp->object);
2451         evas_textblock_cursor_copy(en->cursor, tc);
2452         evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2453         cx = ev->cur.canvas.x - x;
2454         cy = ev->cur.canvas.y - y;
2455         // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
2456         //if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2457         if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, cy))
2458           {
2459              Evas_Coord lx, ly, lw, lh;
2460
2461              if (evas_textblock_cursor_line_coord_set(en->cursor, cy) < 0)
2462                {
2463                   if (rp->part->multiline)
2464                     _curs_end(en->cursor, rp->object, en);
2465                   else
2466                     {
2467                        evas_textblock_cursor_paragraph_first(en->cursor);
2468                        evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2469                        // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
2470                        //if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2471                        if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, ly + (lh / 2)))
2472                          _curs_end(en->cursor, rp->object, en);
2473                     }
2474                }
2475              else
2476                {
2477                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2478                   if (cx <= lx)
2479                     _curs_lin_start(en->cursor, rp->object, en);
2480                   else
2481                     _curs_lin_end(en->cursor, rp->object, en);
2482                }
2483           }
2484         if (en->select_allow)
2485           {
2486              if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2487                {
2488                   if (en->had_sel)
2489                     {
2490                        if (en->select_mod_end)
2491                           _sel_extend(en->ed, en->cursor, rp->object, en);
2492                        else if (en->select_mod_start)
2493                           _sel_preextend(en->ed, en->cursor, rp->object, en);
2494                     }
2495                   else
2496                      _sel_extend(en->ed, en->cursor, rp->object, en);
2497                }
2498              else
2499                {
2500                   _sel_extend(en->ed, en->cursor, rp->object, en);
2501                }
2502
2503              if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) != 0)
2504                _sel_enable(en->ed, en->cursor, rp->object, en);
2505              if (en->have_selection)
2506                _sel_update(en->ed, en->cursor, rp->object, en);
2507           }
2508         if (evas_textblock_cursor_compare(tc, en->cursor))
2509           {
2510              _edje_emit(en->ed, "cursor,changed", rp->part->name);
2511              _edje_emit(en->ed, "cursor,changed,manual", rp->part->name);
2512           }
2513         evas_textblock_cursor_free(tc);
2514
2515         _edje_entry_real_part_configure(en->ed, rp);
2516      }
2517 }
2518
2519 static void
2520 _evas_focus_in_cb(void *data, Evas *e, EINA_UNUSED void *event_info)
2521 {
2522    Edje *ed = (Edje *)data;
2523    if (!ed) return;
2524
2525    if (evas_focus_get(e) == ed->obj)
2526      {
2527         _edje_focus_in_cb(data, NULL, NULL, NULL);
2528      }
2529 }
2530
2531 static void
2532 _evas_focus_out_cb(void *data, Evas *e, EINA_UNUSED void *event_info)
2533 {
2534    Edje *ed = (Edje *)data;
2535    if (!ed) return;
2536
2537    if (evas_focus_get(e) == ed->obj)
2538      {
2539         _edje_focus_out_cb(data, NULL, NULL, NULL);
2540      }
2541 }
2542
2543 /***************************************************************/
2544 void
2545 _edje_entry_init(Edje *ed)
2546 {
2547    if (!ed->has_entries)
2548      return;
2549    if (ed->entries_inited)
2550      return;
2551    ed->entries_inited = EINA_TRUE;
2552
2553    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb, ed);
2554    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb, ed);
2555    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb, ed);
2556    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb, ed);
2557    evas_event_callback_add(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed);
2558    evas_event_callback_add(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed);
2559 }
2560
2561 void
2562 _edje_entry_shutdown(Edje *ed)
2563 {
2564    if ((!ed) || (!ed->has_entries))
2565      return;
2566    if (!ed->entries_inited)
2567      return;
2568    ed->entries_inited = EINA_FALSE;
2569
2570    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb);
2571    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb);
2572    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb);
2573    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb);
2574    if (evas_event_callback_del_full(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed) != ed)
2575      ERR("could not unregister EVAS_CALLBACK_FOCUS_IN");
2576    if (evas_event_callback_del_full(ed->base->evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed) != ed)
2577      ERR("could not unregister EVAS_CALLBACK_FOCUS_OUT");
2578 }
2579
2580 void
2581 _edje_entry_real_part_init(Edje *ed, Edje_Real_Part *rp, Ecore_IMF_Context *ic)
2582 {
2583    Entry *en;
2584 #ifdef HAVE_ECORE_IMF
2585    const char *ctx_id;
2586    const Ecore_IMF_Context_Info *ctx_info;
2587 #endif
2588
2589    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2590        (!rp->typedata.text)) return;
2591    en = calloc(1, sizeof(Entry));
2592    if (!en) return;
2593    rp->typedata.text->entry_data = en;
2594    en->rp = rp;
2595    en->ed = ed;
2596
2597    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOVE, _edje_part_move_cb, rp);
2598
2599    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_DOWN, _edje_part_mouse_down_cb, rp);
2600    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_UP, _edje_part_mouse_up_cb, rp);
2601    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_MOVE, _edje_part_mouse_move_cb, rp);
2602
2603    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
2604      en->select_allow = EINA_TRUE;
2605
2606    if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2607      {
2608         Edje_Part_Description_Text *txt;
2609
2610         txt = (Edje_Part_Description_Text *)rp->chosen_description;
2611
2612         en->select_allow = EINA_FALSE;
2613         if (txt && edje_string_get(&txt->text.repch))
2614           evas_object_textblock_replace_char_set(rp->object, edje_string_get(&txt->text.repch));
2615         else
2616           evas_object_textblock_replace_char_set(rp->object, "*");
2617      }
2618
2619    en->cursor_bg = edje_object_add(ed->base->evas);
2620    edje_object_file_set(en->cursor_bg, ed->path, rp->part->source3);
2621    evas_object_smart_member_add(en->cursor_bg, ed->obj);
2622    evas_object_stack_below(en->cursor_bg, rp->object);
2623    evas_object_clip_set(en->cursor_bg, evas_object_clip_get(rp->object));
2624    evas_object_pass_events_set(en->cursor_bg, EINA_TRUE);
2625    _edje_subobj_register(ed, en->cursor_bg);
2626
2627    en->cursor_fg = edje_object_add(ed->base->evas);
2628    edje_object_file_set(en->cursor_fg, ed->path, rp->part->source4);
2629    evas_object_smart_member_add(en->cursor_fg, ed->obj);
2630    evas_object_stack_above(en->cursor_fg, rp->object);
2631    evas_object_clip_set(en->cursor_fg, evas_object_clip_get(rp->object));
2632    evas_object_pass_events_set(en->cursor_fg, EINA_TRUE);
2633    _edje_subobj_register(ed, en->cursor_fg);
2634
2635    /* A proxy to the main cursor. */
2636    if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
2637      {
2638         en->cursor_fg2 = evas_object_image_add(ed->base->evas);
2639         evas_object_image_source_set(en->cursor_fg2, en->cursor_fg);
2640         evas_object_image_fill_set(en->cursor_fg2, 0, 0, 1, 1);
2641         evas_object_smart_member_add(en->cursor_fg2, ed->obj);
2642         evas_object_stack_above(en->cursor_fg2, rp->object);
2643         evas_object_clip_set(en->cursor_fg2, evas_object_clip_get(rp->object));
2644         evas_object_pass_events_set(en->cursor_fg2, EINA_TRUE);
2645         _edje_subobj_register(en->ed, en->cursor_fg2);
2646      }
2647
2648    evas_object_textblock_legacy_newline_set(rp->object, EINA_TRUE);
2649
2650    if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2651      {
2652         evas_object_show(en->cursor_bg);
2653         evas_object_show(en->cursor_fg);
2654         evas_object_show(en->cursor_fg2);
2655         en->input_panel_enable = EINA_TRUE;
2656
2657 #ifdef HAVE_ECORE_IMF
2658         _edje_need_imf();
2659
2660         en->commit_cancel = EINA_FALSE;
2661
2662         edje_object_signal_callback_add(ed->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb, rp);
2663         edje_object_signal_callback_add(ed->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb, rp);
2664
2665         // TIZEN_ONLY(20131129): Reuse ecore_imf_context when theme is changed
2666
2667         if (ic)
2668           en->imf_context = ic;
2669         else
2670           {
2671              ctx_id = ecore_imf_context_default_id_get();
2672              if (ctx_id)
2673                {
2674                   ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
2675                   if (!ctx_info->canvas_type ||
2676                       strcmp(ctx_info->canvas_type, "evas") == 0)
2677                     {
2678                        en->imf_context = ecore_imf_context_add(ctx_id);
2679                     }
2680                   else
2681                     {
2682                        ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
2683                        if (ctx_id)
2684                          {
2685                             en->imf_context = ecore_imf_context_add(ctx_id);
2686                          }
2687                     }
2688                }
2689              else
2690                 en->imf_context = NULL;
2691
2692              if (!en->imf_context) goto done;
2693           }
2694
2695         ecore_imf_context_client_window_set
2696            (en->imf_context,
2697                (void *)ecore_evas_window_get
2698                (ecore_evas_ecore_evas_get(ed->base->evas)));
2699         ecore_imf_context_client_canvas_set(en->imf_context, ed->base->evas);
2700
2701         ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context,
2702                                                             _edje_entry_imf_retrieve_surrounding_cb, ed);
2703         ecore_imf_context_retrieve_selection_callback_set(en->imf_context, _edje_entry_imf_retrieve_selection_cb, ed);
2704         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb, ed);
2705         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb, ed);
2706         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb, ed);
2707         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_SELECTION_SET, _edje_entry_imf_event_selection_set_cb, ed);
2708         ecore_imf_context_input_mode_set(en->imf_context,
2709                                          rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD ?
2710                                          ECORE_IMF_INPUT_MODE_INVISIBLE : ECORE_IMF_INPUT_MODE_FULL);
2711
2712         if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2713           ecore_imf_context_input_panel_language_set(en->imf_context, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
2714 #endif
2715      }
2716    else
2717      {
2718 #ifdef HAVE_ECORE_IMF
2719         if (ic)
2720           ecore_imf_context_del(ic);
2721 #endif
2722      }
2723 #ifdef HAVE_ECORE_IMF
2724 done:
2725 #endif
2726    en->cursor = (Evas_Textblock_Cursor *)evas_object_textblock_cursor_get(rp->object);
2727 }
2728
2729 void
2730 _edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part *rp, Eina_Bool reuse_ic)
2731 {
2732    Entry *en;
2733
2734    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2735        (!rp->typedata.text)) return;
2736    en = rp->typedata.text->entry_data;
2737    if (!en) return;
2738    rp->typedata.text->entry_data = NULL;
2739    _sel_clear(ed, en->cursor, rp->object, en);
2740    _anchors_clear(en->cursor, rp->object, en);
2741 #ifdef HAVE_ECORE_IMF
2742    _preedit_clear(en);
2743 #endif
2744    evas_object_del(en->cursor_bg);
2745    evas_object_del(en->cursor_fg);
2746    evas_object_del(en->cursor_fg2);
2747
2748    if (en->pw_timer)
2749      {
2750         ecore_timer_del(en->pw_timer);
2751         en->pw_timer = NULL;
2752      }
2753
2754 #ifdef HAVE_ECORE_IMF
2755    if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2756      {
2757         if (en->imf_context)
2758           {
2759              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb);
2760              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb);
2761              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb);
2762              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_SELECTION_SET, _edje_entry_imf_event_selection_set_cb);
2763
2764              if (!reuse_ic)
2765                {
2766                   ecore_imf_context_del(en->imf_context);
2767                   en->imf_context = NULL;
2768                }
2769           }
2770
2771         edje_object_signal_callback_del(ed->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb);
2772         edje_object_signal_callback_del(ed->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb);
2773      }
2774 #endif
2775    _compose_seq_reset(en);
2776
2777    free(en);
2778 }
2779
2780 void
2781 _edje_entry_real_part_configure(Edje *ed, Edje_Real_Part *rp)
2782 {
2783    Evas_Coord x, y, w, h, xx, yy, ww, hh, xx2, yy2;
2784    Entry *en;
2785    Evas_Textblock_Cursor_Type cur_type;
2786    Eina_Bool bidi_cursor = EINA_FALSE;
2787
2788    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2789        (!rp->typedata.text)) return;
2790    en = rp->typedata.text->entry_data;
2791    if (!en) return;
2792    switch (rp->part->cursor_mode)
2793      {
2794       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2795          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2796          break;
2797       case EDJE_ENTRY_CURSOR_MODE_UNDER:
2798          /* no break for a reason */
2799       default:
2800          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2801      }
2802
2803    _sel_update(ed, en->cursor, rp->object, en);
2804    _anchors_update(en->cursor, rp->object, en);
2805    x = y = w = h = -1;
2806    xx = yy = ww = hh = -1;
2807    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2808    bidi_cursor = evas_textblock_cursor_geometry_bidi_get(en->cursor, &xx, &yy, &ww, &hh, &xx2, &yy2, NULL, NULL, cur_type);
2809    if (ww < 1) ww = 1;
2810    if (hh < 1) hh = 1;
2811    if (en->cursor_bg)
2812      {
2813         evas_object_move(en->cursor_bg, x + xx, y + yy);
2814         evas_object_resize(en->cursor_bg, ww, hh);
2815      }
2816    if (en->cursor_fg)
2817      {
2818         evas_object_move(en->cursor_fg, x + xx, y + yy);
2819         evas_object_resize(en->cursor_fg, ww, hh);
2820      }
2821    if (en->cursor_fg2)
2822      {
2823         if (bidi_cursor)
2824           {
2825              evas_object_image_fill_set(en->cursor_fg2, 0, 0, ww, hh / 2);
2826              evas_object_move(en->cursor_fg2, x + xx2, y + yy2 + (hh / 2));
2827              evas_object_resize(en->cursor_fg, ww, hh / 2);
2828              evas_object_resize(en->cursor_fg2, ww, hh / 2);
2829
2830              evas_object_show(en->cursor_fg2);
2831           }
2832         else
2833           {
2834              evas_object_hide(en->cursor_fg2);
2835           }
2836      }
2837 }
2838
2839 // TIZEN_ONLY(20150128): Add evas_textblock_cursor_range_text_valid_markup_get API.
2840 const char *
2841 _edje_entry_selection_valid_markup_get(Edje_Real_Part *rp)
2842 {
2843    Entry *en;
2844
2845    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2846        (!rp->typedata.text)) return NULL;
2847    en = rp->typedata.text->entry_data;
2848    if (!en) return NULL;
2849    // get selection - convert to markup
2850    if ((!en->selection) && (en->have_selection))
2851      en->selection = evas_textblock_cursor_range_text_valid_markup_get
2852         (en->sel_start, en->sel_end);
2853    return en->selection;
2854 }
2855 //
2856
2857 const char *
2858 _edje_entry_selection_get(Edje_Real_Part *rp)
2859 {
2860    Entry *en;
2861
2862    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2863        (!rp->typedata.text)) return NULL;
2864    en = rp->typedata.text->entry_data;
2865    if (!en) return NULL;
2866    // get selection - convert to markup
2867    if ((!en->selection) && (en->have_selection))
2868      en->selection = evas_textblock_cursor_range_text_get
2869         (en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
2870    return en->selection;
2871 }
2872
2873 const char *
2874 _edje_entry_text_get(Edje_Real_Part *rp)
2875 {
2876    Entry *en;
2877
2878    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2879        (!rp->typedata.text)) return NULL;
2880    en = rp->typedata.text->entry_data;
2881    if (!en) return NULL;
2882    // get text - convert to markup
2883    return evas_object_textblock_text_markup_get(rp->object);
2884 }
2885
2886 void
2887 _edje_entry_text_markup_set(Edje_Real_Part *rp, const char *text)
2888 {
2889    Entry *en;
2890
2891    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2892        (!rp->typedata.text)) return;
2893    en = rp->typedata.text->entry_data;
2894    if (!en) return;
2895    _edje_entry_imf_context_reset(rp);
2896    // set text as markup
2897    _sel_clear(en->ed, en->cursor, rp->object, en);
2898    evas_object_textblock_text_markup_set(rp->object, text);
2899    _edje_entry_set_cursor_start(rp);
2900
2901    _anchors_get(en->cursor, rp->object, en);
2902    _edje_emit(en->ed, "entry,changed", rp->part->name);
2903    // TIZEN_ONLY(20150716): Add edje_object_part_text_freeze, thaw APIs for freezing cursor movements.
2904    //_edje_entry_imf_cursor_info_set(en);
2905    //
2906    //_edje_entry_real_part_configure(en->ed, rp);
2907    if (!en->freeze)
2908      {
2909         _edje_entry_imf_cursor_info_set(en);
2910         _edje_entry_real_part_configure(en->ed, rp);
2911      }
2912    //
2913 #if 0
2914    /* Don't emit cursor changed cause it didn't. It's just init to 0. */
2915    _edje_emit(en->ed, "cursor,changed", rp->part->name);
2916 #endif
2917 }
2918
2919 void
2920 _edje_entry_text_markup_append(Edje_Real_Part *rp, const char *text)
2921 {
2922    Entry *en;
2923
2924    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2925        (!rp->typedata.text)) return;
2926    en = rp->typedata.text->entry_data;
2927    Evas_Textblock_Cursor *end_cur;
2928    if (!en) return;
2929    end_cur = evas_object_textblock_cursor_new(rp->object);
2930    evas_textblock_cursor_paragraph_last(end_cur);
2931
2932    _text_filter_markup_prepend(en->ed, en, end_cur, text, NULL, NULL,
2933                                EINA_TRUE, EINA_FALSE);
2934    evas_textblock_cursor_free(end_cur);
2935
2936    /* We are updating according to the real cursor on purpose */
2937    _anchors_get(en->cursor, rp->object, en);
2938    _edje_emit(en->ed, "entry,changed", rp->part->name);
2939
2940    _edje_entry_real_part_configure(en->ed, rp);
2941 }
2942
2943 void
2944 _edje_entry_text_markup_insert(Edje_Real_Part *rp, const char *text)
2945 {
2946    Entry *en;
2947
2948    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2949        (!rp->typedata.text)) return;
2950    en = rp->typedata.text->entry_data;
2951    if (!en) return;
2952    _edje_entry_imf_context_reset(rp);
2953
2954    // prepend markup @ cursor pos .. XXX: do we need to do this? maybe not?
2955 //   if (en->have_selection)
2956 //     _range_del(en->cursor, rp->object, en);
2957    _text_filter_markup_prepend(en->ed, en, en->cursor, text, NULL, NULL,
2958                                EINA_TRUE, EINA_FALSE);
2959    _anchors_get(en->cursor, rp->object, en);
2960    _edje_emit(en->ed, "entry,changed", rp->part->name);
2961    _edje_emit(en->ed, "cursor,changed", rp->part->name);
2962
2963    _edje_entry_imf_cursor_info_set(en);
2964    _edje_entry_real_part_configure(en->ed, rp);
2965 }
2966
2967 void
2968 _edje_entry_set_cursor_start(Edje_Real_Part *rp)
2969 {
2970    Entry *en;
2971
2972    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2973        (!rp->typedata.text)) return;
2974    en = rp->typedata.text->entry_data;
2975    if (!en) return;
2976    _curs_start(en->cursor, rp->object, en);
2977
2978    // TIZEN_ONLY(20150716): Add edje_object_part_text_freeze, thaw APIs for freezing cursor movements.
2979    //_edje_entry_imf_cursor_info_set(en);
2980    if (!en->freeze)
2981      _edje_entry_imf_cursor_info_set(en);
2982    //
2983 }
2984
2985 void
2986 _edje_entry_set_cursor_end(Edje_Real_Part *rp)
2987 {
2988    Entry *en;
2989
2990    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2991        (!rp->typedata.text)) return;
2992    en = rp->typedata.text->entry_data;
2993    if (!en) return;
2994    _curs_end(en->cursor, rp->object, en);
2995
2996    _edje_entry_imf_cursor_info_set(en);
2997 }
2998
2999 void
3000 _edje_entry_select_none(Edje_Real_Part *rp)
3001 {
3002    Entry *en;
3003
3004    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3005        (!rp->typedata.text)) return;
3006    en = rp->typedata.text->entry_data;
3007    if (!en) return;
3008    _sel_clear(en->ed, en->cursor, rp->object, en);
3009    //TIZEN_ONLY (20150821): Selection is being handled in elm so on mouse up
3010    //selection is clear so cursor info is not sent to imf,
3011    //h/w mouse does not need this.
3012    _edje_entry_imf_cursor_info_set(en);
3013    //
3014 }
3015
3016 void
3017 _edje_entry_select_all(Edje_Real_Part *rp)
3018 {
3019    Entry *en;
3020
3021    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3022        (!rp->typedata.text)) return;
3023    en = rp->typedata.text->entry_data;
3024    if (!en) return;
3025
3026    _edje_entry_imf_context_reset(rp);
3027
3028    _sel_clear(en->ed, en->cursor, rp->object, en);
3029    _curs_start(en->cursor, rp->object, en);
3030    _sel_enable(en->ed, en->cursor, rp->object, en);
3031    _sel_start(en->cursor, rp->object, en);
3032    _curs_end(en->cursor, rp->object, en);
3033    _sel_extend(en->ed, en->cursor, rp->object, en);
3034
3035    _edje_entry_real_part_configure(en->ed, rp);
3036 }
3037
3038 void
3039 _edje_entry_select_begin(Edje_Real_Part *rp)
3040 {
3041    Entry *en;
3042
3043    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3044        (!rp->typedata.text)) return;
3045    en = rp->typedata.text->entry_data;
3046    if (!en) return;
3047
3048    _sel_clear(en->ed, en->cursor, rp->object, en);
3049    _sel_enable(en->ed, en->cursor, rp->object, en);
3050    _sel_start(en->cursor, rp->object, en);
3051    _sel_extend(en->ed, en->cursor, rp->object, en);
3052
3053    _edje_entry_real_part_configure(en->ed, rp);
3054 }
3055
3056 void
3057 _edje_entry_select_extend(Edje_Real_Part *rp)
3058 {
3059    Entry *en;
3060
3061    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3062        (!rp->typedata.text)) return;
3063    en = rp->typedata.text->entry_data;
3064    if (!en) return;
3065    _sel_extend(en->ed, en->cursor, rp->object, en);
3066
3067    _edje_entry_real_part_configure(en->ed, rp);
3068 }
3069
3070 const Eina_List *
3071 _edje_entry_anchor_geometry_get(Edje_Real_Part *rp, const char *anchor)
3072 {
3073    Entry *en;
3074    Eina_List *l;
3075    Anchor *an;
3076
3077    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3078        (!rp->typedata.text)) return NULL;
3079    en = rp->typedata.text->entry_data;
3080    if (!en) return NULL;
3081    EINA_LIST_FOREACH(en->anchors, l, an)
3082      {
3083         const char *n = an->name;
3084         if ((an->item) || (!n)) continue;
3085         if (!strcmp(anchor, n))
3086           return an->sel;
3087      }
3088    return NULL;
3089 }
3090
3091 const Eina_List *
3092 _edje_entry_anchors_list(Edje_Real_Part *rp)
3093 {
3094    Entry *en;
3095    Eina_List *l, *anchors = NULL;
3096    Anchor *an;
3097
3098    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3099        (!rp->typedata.text)) return NULL;
3100    en = rp->typedata.text->entry_data;
3101    if (!en) return NULL;
3102    if (!en->anchorlist)
3103      {
3104         EINA_LIST_FOREACH(en->anchors, l, an)
3105           {
3106              const char *n = an->name;
3107              if ((an->item) || (!n)) continue;
3108              anchors = eina_list_append(anchors, strdup(n));
3109           }
3110         en->anchorlist = anchors;
3111      }
3112    return en->anchorlist;
3113 }
3114
3115 Eina_Bool
3116 _edje_entry_item_geometry_get(Edje_Real_Part *rp, const char *item, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
3117 {
3118    Entry *en;
3119    Eina_List *l;
3120    Anchor *an;
3121
3122    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3123        (!rp->typedata.text)) return EINA_FALSE;
3124    en = rp->typedata.text->entry_data;
3125    if (!en) return EINA_FALSE;
3126    EINA_LIST_FOREACH(en->anchors, l, an)
3127      {
3128         const char *n = an->name;
3129         if (!an->item) continue;
3130         if (!n) n = "";
3131         if (!strcmp(item, n))
3132           {
3133              evas_textblock_cursor_format_item_geometry_get(an->start, cx, cy, cw, ch);
3134              return EINA_TRUE;
3135           }
3136      }
3137    return EINA_FALSE;
3138 }
3139
3140 const Eina_List *
3141 _edje_entry_items_list(Edje_Real_Part *rp)
3142 {
3143    Entry *en;
3144    Eina_List *l, *items = NULL;
3145    Anchor *an;
3146
3147    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3148        (!rp->typedata.text)) return NULL;
3149    en = rp->typedata.text->entry_data;
3150    if (!en) return NULL;
3151    if (!en->itemlist)
3152      {
3153         EINA_LIST_FOREACH(en->anchors, l, an)
3154           {
3155              const char *n = an->name;
3156              if (!an->item) continue;
3157              if (!n) n = "";
3158              items = eina_list_append(items, strdup(n));
3159           }
3160         en->itemlist = items;
3161      }
3162    return en->itemlist;
3163 }
3164
3165 void
3166 _edje_entry_cursor_geometry_get(Edje_Real_Part *rp, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_BiDi_Direction *cdir)
3167 {
3168    Evas_Coord x, y, w, h, xx, yy, ww, hh;
3169    Entry *en;
3170    Evas_Textblock_Cursor_Type cur_type;
3171    Evas_BiDi_Direction dir;
3172
3173    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3174        (!rp->typedata.text)) return;
3175    en = rp->typedata.text->entry_data;
3176    if (!en) return;
3177    switch (rp->part->cursor_mode)
3178      {
3179       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
3180          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
3181          break;
3182       case EDJE_ENTRY_CURSOR_MODE_UNDER:
3183          /* no break for a reason */
3184       default:
3185          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
3186      }
3187
3188    x = y = w = h = -1;
3189    xx = yy = ww = hh = -1;
3190    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
3191    evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, &dir, cur_type);
3192    if (ww < 1) ww = 1;
3193    if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
3194      edje_object_size_min_restricted_calc(en->cursor_fg, &ww, NULL, ww, 0);
3195    if (hh < 1) hh = 1;
3196    if (cx) *cx = x + xx;
3197    if (cy) *cy = y + yy;
3198    if (cw) *cw = ww;
3199    if (ch) *ch = hh;
3200    if (cdir) *cdir = dir;
3201 }
3202
3203 void
3204 _edje_entry_user_insert(Edje_Real_Part *rp, const char *text)
3205 {
3206    Entry *en;
3207    Edje_Entry_Change_Info *info;
3208
3209    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3210        (!rp->typedata.text)) return;
3211    en = rp->typedata.text->entry_data;
3212    if (!en) return;
3213    _edje_entry_imf_context_reset(rp);
3214    info = _text_filter_markup_prepend(en->ed, en, en->cursor, text, NULL, NULL,
3215                                      EINA_TRUE, EINA_TRUE);
3216    _anchors_get(en->cursor, rp->object, en);
3217    if (info)
3218      {
3219         _edje_emit(en->ed, "entry,changed", rp->part->name);
3220         _edje_emit_full(en->ed, "entry,changed,user", rp->part->name,
3221                         info, _free_entry_change_info);
3222         _edje_emit(en->ed, "cursor,changed", rp->part->name);
3223      }
3224
3225    _edje_entry_imf_cursor_info_set(en);
3226    _edje_entry_real_part_configure(en->ed, rp);
3227 }
3228
3229 void
3230 _edje_entry_select_allow_set(Edje_Real_Part *rp, Eina_Bool allow)
3231 {
3232    Entry *en;
3233
3234    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3235        (!rp->typedata.text)) return;
3236    en = rp->typedata.text->entry_data;
3237    if (!en) return;
3238
3239    en->select_allow = allow;
3240 }
3241
3242 Eina_Bool
3243 _edje_entry_select_allow_get(const Edje_Real_Part *rp)
3244 {
3245    Entry *en;
3246
3247    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3248        (!rp->typedata.text)) return EINA_FALSE;
3249    en = rp->typedata.text->entry_data;
3250    if (!en) return EINA_FALSE;
3251    return en->select_allow;
3252 }
3253
3254 void
3255 _edje_entry_select_abort(Edje_Real_Part *rp)
3256 {
3257    Entry *en;
3258
3259    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3260        (!rp->typedata.text)) return;
3261    en = rp->typedata.text->entry_data;
3262    if (!en) return;
3263    if (en->selecting)
3264      {
3265         en->selecting = EINA_FALSE;
3266
3267         _edje_entry_imf_context_reset(rp);
3268         _edje_entry_imf_cursor_info_set(en);
3269         _edje_entry_real_part_configure(en->ed, rp);
3270      }
3271 }
3272
3273 void *
3274 _edje_entry_imf_context_get(Edje_Real_Part *rp)
3275 {
3276 #ifdef HAVE_ECORE_IMF
3277    Entry *en;
3278
3279    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3280        (!rp->typedata.text)) return NULL;
3281    en = rp->typedata.text->entry_data;
3282    if (!en) return NULL;
3283
3284    return en->imf_context;
3285 #else
3286    return NULL;
3287    (void)rp;
3288 #endif
3289 }
3290
3291 void
3292 _edje_entry_autocapital_type_set(Edje_Real_Part *rp, Edje_Text_Autocapital_Type autocapital_type)
3293 {
3294 #ifdef HAVE_ECORE_IMF
3295    Entry *en;
3296
3297    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3298        (!rp->typedata.text)) return;
3299    en = rp->typedata.text->entry_data;
3300    if (!en) return;
3301
3302    if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
3303      autocapital_type = EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3304
3305    if (en->imf_context)
3306      ecore_imf_context_autocapital_type_set(en->imf_context, (Ecore_IMF_Autocapital_Type)autocapital_type);
3307 #else
3308    (void)rp;
3309    (void)autocapital_type;
3310 #endif
3311 }
3312
3313 Edje_Text_Autocapital_Type
3314 _edje_entry_autocapital_type_get(Edje_Real_Part *rp)
3315 {
3316 #ifdef HAVE_ECORE_IMF
3317    Entry *en;
3318
3319    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3320        (!rp->typedata.text)) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3321    en = rp->typedata.text->entry_data;
3322    if (!en) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3323
3324    if (en->imf_context)
3325      return (Edje_Text_Autocapital_Type)ecore_imf_context_autocapital_type_get(en->imf_context);
3326    return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3327 #else
3328    return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3329    (void)rp;
3330 #endif
3331 }
3332
3333 void
3334 _edje_entry_prediction_allow_set(Edje_Real_Part *rp, Eina_Bool prediction)
3335 {
3336    Entry *en;
3337
3338    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3339        (!rp->typedata.text)) return;
3340    en = rp->typedata.text->entry_data;
3341    if (!en) return;
3342    en->prediction_allow = prediction;
3343 #ifdef HAVE_ECORE_IMF
3344    if (en->imf_context)
3345      ecore_imf_context_prediction_allow_set(en->imf_context, prediction);
3346 #endif
3347 }
3348
3349 Eina_Bool
3350 _edje_entry_prediction_allow_get(Edje_Real_Part *rp)
3351 {
3352    Entry *en;
3353
3354    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3355        (!rp->typedata.text)) return EINA_FALSE;
3356    en = rp->typedata.text->entry_data;
3357    if (!en) return EINA_FALSE;
3358    return en->prediction_allow;
3359 }
3360
3361 void
3362 _edje_entry_input_hint_set(Edje_Real_Part *rp, Edje_Input_Hints input_hints)
3363 {
3364    Entry *en;
3365
3366    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3367        (!rp->typedata.text)) return;
3368    en = rp->typedata.text->entry_data;
3369    if (!en) return;
3370 #ifdef HAVE_ECORE_IMF
3371    if (en->imf_context)
3372      ecore_imf_context_input_hint_set(en->imf_context, (Ecore_IMF_Input_Hints)input_hints);
3373 #else
3374    (void) input_hints;
3375 #endif
3376 }
3377
3378 Edje_Input_Hints
3379 _edje_entry_input_hint_get(const Edje_Real_Part *rp)
3380 {
3381    Entry *en;
3382
3383    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3384        (!rp->typedata.text)) return EDJE_INPUT_HINT_NONE;
3385    en = rp->typedata.text->entry_data;
3386    if (!en) return EDJE_INPUT_HINT_NONE;
3387 #ifdef HAVE_ECORE_IMF
3388    if (en->imf_context)
3389      return (Edje_Input_Hints)ecore_imf_context_input_hint_get(en->imf_context);
3390 #endif
3391
3392    return EDJE_INPUT_HINT_NONE;
3393 }
3394
3395 void
3396 _edje_entry_input_panel_enabled_set(Edje_Real_Part *rp, Eina_Bool enabled)
3397 {
3398    Entry *en;
3399
3400    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3401        (!rp->typedata.text)) return;
3402    en = rp->typedata.text->entry_data;
3403    if (!en) return;
3404    en->input_panel_enable = enabled;
3405 #ifdef HAVE_ECORE_IMF
3406    if (en->imf_context)
3407      ecore_imf_context_input_panel_enabled_set(en->imf_context, enabled);
3408 #endif
3409 }
3410
3411 Eina_Bool
3412 _edje_entry_input_panel_enabled_get(Edje_Real_Part *rp)
3413 {
3414    Entry *en;
3415
3416    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3417        (!rp->typedata.text)) return EINA_FALSE;
3418    en = rp->typedata.text->entry_data;
3419    if (!en) return EINA_FALSE;
3420    return en->input_panel_enable;
3421 }
3422
3423 void
3424 _edje_entry_input_panel_show(Edje_Real_Part *rp)
3425 {
3426 #ifdef HAVE_ECORE_IMF
3427    Entry *en;
3428
3429    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3430        (!rp->typedata.text)) return;
3431    en = rp->typedata.text->entry_data;
3432    if (!en) return;
3433    if (en->imf_context)
3434      ecore_imf_context_input_panel_show(en->imf_context);
3435 #else
3436    (void)rp;
3437 #endif
3438 }
3439
3440 void
3441 _edje_entry_input_panel_hide(Edje_Real_Part *rp)
3442 {
3443 #ifdef HAVE_ECORE_IMF
3444    Entry *en;
3445
3446    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3447        (!rp->typedata.text)) return;
3448    en = rp->typedata.text->entry_data;
3449    if (!en) return;
3450    if (en->imf_context)
3451      ecore_imf_context_input_panel_hide(en->imf_context);
3452 #else
3453    (void)rp;
3454 #endif
3455 }
3456
3457 void
3458 _edje_entry_input_panel_language_set(Edje_Real_Part *rp, Edje_Input_Panel_Lang lang)
3459 {
3460    Entry *en;
3461
3462    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3463        (!rp->typedata.text)) return;
3464    en = rp->typedata.text->entry_data;
3465    if (!en) return;
3466    en->input_panel_lang = lang;
3467 #ifdef HAVE_ECORE_IMF
3468    if (en->imf_context)
3469      ecore_imf_context_input_panel_language_set(en->imf_context, (Ecore_IMF_Input_Panel_Lang)lang);
3470 #endif
3471 }
3472
3473 Edje_Input_Panel_Lang
3474 _edje_entry_input_panel_language_get(Edje_Real_Part *rp)
3475 {
3476    Entry *en;
3477
3478    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3479        (!rp->typedata.text)) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
3480    en = rp->typedata.text->entry_data;
3481    if (!en) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
3482    return en->input_panel_lang;
3483 }
3484
3485 void
3486 _edje_entry_input_panel_imdata_set(Edje_Real_Part *rp, const void *data, int len)
3487 {
3488 #ifdef HAVE_ECORE_IMF
3489    Entry *en;
3490
3491    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3492        (!rp->typedata.text)) return;
3493    en = rp->typedata.text->entry_data;
3494    if (!en) return;
3495    if (en->imf_context)
3496      ecore_imf_context_input_panel_imdata_set(en->imf_context, data, len);
3497 #else
3498    (void)rp;
3499    (void)data;
3500    (void)len;
3501 #endif
3502 }
3503
3504 void
3505 _edje_entry_input_panel_imdata_get(Edje_Real_Part *rp, void *data, int *len)
3506 {
3507 #ifdef HAVE_ECORE_IMF
3508    Entry *en;
3509
3510    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3511        (!rp->typedata.text)) return;
3512    en = rp->typedata.text->entry_data;
3513    if (!en) return;
3514    if (en->imf_context)
3515      ecore_imf_context_input_panel_imdata_get(en->imf_context, data, len);
3516 #else
3517    (void)rp;
3518    (void)data;
3519    (void)len;
3520 #endif
3521 }
3522
3523 void
3524 _edje_entry_input_panel_return_key_type_set(Edje_Real_Part *rp, Edje_Input_Panel_Return_Key_Type return_key_type)
3525 {
3526 #ifdef HAVE_ECORE_IMF
3527    Entry *en;
3528
3529    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3530        (!rp->typedata.text)) return;
3531    en = rp->typedata.text->entry_data;
3532    if (!en) return;
3533    if (en->imf_context)
3534      ecore_imf_context_input_panel_return_key_type_set(en->imf_context, (Ecore_IMF_Input_Panel_Return_Key_Type)return_key_type);
3535 #else
3536    (void)rp;
3537    (void)return_key_type;
3538 #endif
3539 }
3540
3541 Edje_Input_Panel_Return_Key_Type
3542 _edje_entry_input_panel_return_key_type_get(Edje_Real_Part *rp)
3543 {
3544 #ifdef HAVE_ECORE_IMF
3545    Entry *en;
3546
3547    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3548        (!rp->typedata.text)) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3549    en = rp->typedata.text->entry_data;
3550    if (!en) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3551    if (en->imf_context)
3552      return (Edje_Input_Panel_Return_Key_Type)ecore_imf_context_input_panel_return_key_type_get(en->imf_context);
3553    return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3554 #else
3555    return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3556    (void)rp;
3557 #endif
3558 }
3559
3560 void
3561 _edje_entry_input_panel_return_key_disabled_set(Edje_Real_Part *rp, Eina_Bool disabled)
3562 {
3563 #ifdef HAVE_ECORE_IMF
3564    Entry *en;
3565
3566    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3567        (!rp->typedata.text)) return;
3568    en = rp->typedata.text->entry_data;
3569    if (!en) return;
3570    if (en->imf_context)
3571      ecore_imf_context_input_panel_return_key_disabled_set(en->imf_context, disabled);
3572 #else
3573    (void)rp;
3574    (void)disabled;
3575 #endif
3576 }
3577
3578 Eina_Bool
3579 _edje_entry_input_panel_return_key_disabled_get(Edje_Real_Part *rp)
3580 {
3581 #ifdef HAVE_ECORE_IMF
3582    Entry *en;
3583
3584    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3585        (!rp->typedata.text)) return EINA_FALSE;
3586    en = rp->typedata.text->entry_data;
3587    if (!en) return EINA_FALSE;
3588    if (en->imf_context)
3589      return ecore_imf_context_input_panel_return_key_disabled_get(en->imf_context);
3590    return EINA_FALSE;
3591 #else
3592    return EINA_FALSE;
3593    (void)rp;
3594 #endif
3595 }
3596
3597 #ifdef HAVE_ECORE_IMF
3598 void
3599 _edje_entry_input_panel_show_on_demand_set(Edje_Real_Part *rp, Eina_Bool ondemand)
3600 #else
3601 void
3602 _edje_entry_input_panel_show_on_demand_set(Edje_Real_Part *rp, Eina_Bool ondemand EINA_UNUSED)
3603 #endif
3604 {
3605    Entry *en;
3606
3607    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3608        (!rp->typedata.text)) return;
3609    en = rp->typedata.text->entry_data;
3610    if (!en) return;
3611 #ifdef HAVE_ECORE_IMF
3612    if (en->imf_context)
3613      ecore_imf_context_input_panel_show_on_demand_set(en->imf_context, ondemand);
3614 #endif
3615 }
3616
3617 Eina_Bool
3618 _edje_entry_input_panel_show_on_demand_get(Edje_Real_Part *rp)
3619 {
3620    Entry *en;
3621
3622    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3623        (!rp->typedata.text)) return EINA_FALSE;
3624    en = rp->typedata.text->entry_data;
3625    if (!en) return EINA_FALSE;
3626 #ifdef HAVE_ECORE_IMF
3627    if (en->imf_context) {
3628        Eina_Bool ret = ecore_imf_context_input_panel_show_on_demand_get(en->imf_context);
3629        return ret;
3630    }
3631 #endif
3632    return EINA_FALSE;
3633 }
3634
3635 static Evas_Textblock_Cursor *
3636 _cursor_get(Edje_Real_Part *rp, Edje_Cursor cur)
3637 {
3638    Entry *en;
3639
3640    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3641        (!rp->typedata.text)) return NULL;
3642    en = rp->typedata.text->entry_data;
3643    if (!en) return NULL;
3644    switch (cur)
3645      {
3646       case EDJE_CURSOR_MAIN:
3647          return en->cursor;
3648       case EDJE_CURSOR_SELECTION_BEGIN:
3649          return en->sel_start;
3650       case EDJE_CURSOR_SELECTION_END:
3651          return en->sel_end;
3652       case EDJE_CURSOR_PREEDIT_START:
3653          if (!en->preedit_start)
3654            en->preedit_start = evas_object_textblock_cursor_new(rp->object);
3655          return en->preedit_start;
3656       case EDJE_CURSOR_PREEDIT_END:
3657          if (!en->preedit_end)
3658            en->preedit_end = evas_object_textblock_cursor_new(rp->object);
3659          return en->preedit_end;
3660       case EDJE_CURSOR_USER:
3661          if (!en->cursor_user)
3662            en->cursor_user = evas_object_textblock_cursor_new(rp->object);
3663          return en->cursor_user;
3664       case EDJE_CURSOR_USER_EXTRA:
3665          if (!en->cursor_user_extra)
3666            en->cursor_user_extra = evas_object_textblock_cursor_new(rp->object);
3667          return en->cursor_user_extra;
3668       default:
3669          break;
3670      }
3671    return NULL;
3672 }
3673
3674 Eina_Bool
3675 _edje_entry_cursor_next(Edje_Real_Part *rp, Edje_Cursor cur)
3676 {
3677    Entry *en;
3678    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3679
3680    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3681        (!rp->typedata.text)) return EINA_FALSE;
3682    en = rp->typedata.text->entry_data;
3683    if (!en) return EINA_FALSE;
3684
3685    if (!c) return EINA_FALSE;
3686
3687    _edje_entry_imf_context_reset(rp);
3688
3689    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
3690    //if (!evas_textblock_cursor_char_next(c))
3691    if (!evas_textblock_cursor_cluster_next(c))
3692      {
3693         return EINA_FALSE;
3694      }
3695    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3696    _edje_entry_imf_cursor_info_set(en);
3697
3698    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3699    _edje_entry_real_part_configure(en->ed, rp);
3700    return EINA_TRUE;
3701 }
3702
3703 Eina_Bool
3704 _edje_entry_cursor_prev(Edje_Real_Part *rp, Edje_Cursor cur)
3705 {
3706    Entry *en;
3707    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3708
3709    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3710        (!rp->typedata.text)) return EINA_FALSE;
3711    en = rp->typedata.text->entry_data;
3712    if (!en) return EINA_FALSE;
3713    if (!c) return EINA_FALSE;
3714
3715    _edje_entry_imf_context_reset(rp);
3716
3717    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
3718    //if (!evas_textblock_cursor_char_prev(c))
3719    if (!evas_textblock_cursor_cluster_prev(c))
3720      {
3721         if (evas_textblock_cursor_paragraph_prev(c)) goto ok;
3722         else return EINA_FALSE;
3723      }
3724 ok:
3725    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3726
3727    _edje_entry_imf_cursor_info_set(en);
3728
3729    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3730    _edje_entry_real_part_configure(en->ed, rp);
3731    return EINA_TRUE;
3732 }
3733
3734 Eina_Bool
3735 _edje_entry_cursor_up(Edje_Real_Part *rp, Edje_Cursor cur)
3736 {
3737    Entry *en;
3738    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3739    Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
3740    int ln;
3741
3742    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3743        (!rp->typedata.text)) return EINA_FALSE;
3744    en = rp->typedata.text->entry_data;
3745    if (!en) return EINA_FALSE;
3746    if (!c) return EINA_FALSE;
3747
3748    _edje_entry_imf_context_reset(rp);
3749
3750    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
3751    ln--;
3752    if (ln < 0) return EINA_FALSE;
3753    if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
3754                                                        &lx, &ly, &lw, &lh))
3755      return EINA_FALSE;
3756    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
3757    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
3758    //if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
3759    if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
3760      {
3761         if (cx < (lx + (lw / 2)))
3762           evas_textblock_cursor_line_char_last(c);
3763         else
3764           evas_textblock_cursor_line_char_last(c);
3765      }
3766    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3767
3768    _edje_entry_imf_cursor_info_set(en);
3769
3770    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3771    _edje_entry_real_part_configure(en->ed, rp);
3772    return EINA_TRUE;
3773 }
3774
3775 Eina_Bool
3776 _edje_entry_cursor_down(Edje_Real_Part *rp, Edje_Cursor cur)
3777 {
3778    Entry *en;
3779    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3780    Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
3781    int ln;
3782
3783    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3784        (!rp->typedata.text)) return EINA_FALSE;
3785    en = rp->typedata.text->entry_data;
3786    if (!en) return EINA_FALSE;
3787    if (!c) return EINA_FALSE;
3788
3789    _edje_entry_imf_context_reset(rp);
3790
3791    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
3792    ln++;
3793    if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
3794                                                        &lx, &ly, &lw, &lh))
3795      return EINA_FALSE;
3796    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
3797    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
3798    //if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
3799    if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
3800      {
3801         if (cx < (lx + (lw / 2)))
3802           evas_textblock_cursor_line_char_last(c);
3803         else
3804           evas_textblock_cursor_line_char_last(c);
3805      }
3806    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3807
3808    _edje_entry_imf_cursor_info_set(en);
3809    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3810    _edje_entry_real_part_configure(en->ed, rp);
3811    return EINA_TRUE;
3812 }
3813
3814 void
3815 _edje_entry_cursor_begin(Edje_Real_Part *rp, Edje_Cursor cur)
3816 {
3817    Entry *en;
3818    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3819
3820    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3821        (!rp->typedata.text)) return;
3822    en = rp->typedata.text->entry_data;
3823    if (!en) return;
3824    if (!c) return;
3825
3826    _edje_entry_imf_context_reset(rp);
3827
3828    evas_textblock_cursor_paragraph_first(c);
3829    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3830
3831    _edje_entry_imf_cursor_info_set(en);
3832    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3833    _edje_entry_real_part_configure(en->ed, rp);
3834 }
3835
3836 void
3837 _edje_entry_cursor_end(Edje_Real_Part *rp, Edje_Cursor cur)
3838 {
3839    Entry *en;
3840    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3841
3842    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3843        (!rp->typedata.text)) return;
3844    en = rp->typedata.text->entry_data;
3845    if (!en) return;
3846    if (!c) return;
3847
3848    _edje_entry_imf_context_reset(rp);
3849
3850    _curs_end(c, rp->object, rp->typedata.text->entry_data);
3851    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3852
3853    _edje_entry_imf_cursor_info_set(en);
3854
3855    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3856    _edje_entry_real_part_configure(en->ed, rp);
3857 }
3858
3859 void
3860 _edje_entry_cursor_copy(Edje_Real_Part *rp, Edje_Cursor cur, Edje_Cursor dst)
3861 {
3862    Entry *en;
3863    Evas_Textblock_Cursor *c;
3864    Evas_Textblock_Cursor *d;
3865
3866    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3867        (!rp->typedata.text)) return;
3868    en = rp->typedata.text->entry_data;
3869    if (!en) return;
3870    c = _cursor_get(rp, cur);
3871    if (!c) return;
3872    d = _cursor_get(rp, dst);
3873    if (!d) return;
3874    evas_textblock_cursor_copy(c, d);
3875    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3876
3877    _edje_entry_imf_context_reset(rp);
3878    _edje_entry_imf_cursor_info_set(en);
3879    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3880    _edje_entry_real_part_configure(en->ed, rp);
3881 }
3882
3883 void
3884 _edje_entry_cursor_line_begin(Edje_Real_Part *rp, Edje_Cursor cur)
3885 {
3886    Entry *en;
3887    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3888
3889    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3890        (!rp->typedata.text)) return;
3891    en = rp->typedata.text->entry_data;
3892    if (!en) return;
3893    if (!c) return;
3894    _edje_entry_imf_context_reset(rp);
3895
3896    evas_textblock_cursor_line_char_first(c);
3897    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3898
3899    _edje_entry_imf_cursor_info_set(en);
3900
3901    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3902    _edje_entry_real_part_configure(en->ed, rp);
3903 }
3904
3905 void
3906 _edje_entry_cursor_line_end(Edje_Real_Part *rp, Edje_Cursor cur)
3907 {
3908    Entry *en;
3909    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3910
3911    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3912        (!rp->typedata.text)) return;
3913    en = rp->typedata.text->entry_data;
3914    if (!en) return;
3915    if (!c) return;
3916    _edje_entry_imf_context_reset(rp);
3917    evas_textblock_cursor_line_char_last(c);
3918    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3919
3920    _edje_entry_imf_cursor_info_set(en);
3921    _edje_emit(en->ed, "cursor,changed", rp->part->name);
3922    _edje_entry_real_part_configure(en->ed, rp);
3923 }
3924
3925 Eina_Bool
3926 _edje_entry_cursor_coord_set(Edje_Real_Part *rp, Edje_Cursor cur,
3927                              Evas_Coord x, Evas_Coord y)
3928 {
3929    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3930    if (!c) return EINA_FALSE;
3931    Entry *en = rp->typedata.text->entry_data;
3932    if ((cur == EDJE_CURSOR_SELECTION_BEGIN) ||
3933        (cur == EDJE_CURSOR_SELECTION_END))
3934      {
3935         if (en->have_selection)
3936           {
3937              // TIZEN ONLY(20150727): Clear selection (doing with sel handler)
3938              if (en->selection)
3939                {
3940                   free(en->selection);
3941                   en->selection = NULL;
3942                }
3943              //
3944              _edje_emit(en->ed, "selection,changed", rp->part->name);
3945           }
3946      }
3947    // TIZEN_ONLY(20150127): Add evas_textblock_cursor_cluster_* APIs.
3948    //return evas_textblock_cursor_char_coord_set(c, x, y);
3949    return evas_textblock_cursor_cluster_coord_set(c, x, y);
3950    //
3951 }
3952
3953 Eina_Bool
3954 _edje_entry_cursor_is_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
3955 {
3956    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3957    if (!c) return EINA_FALSE;
3958    if (evas_textblock_cursor_is_format(c)) return EINA_TRUE;
3959    return EINA_FALSE;
3960 }
3961
3962 Eina_Bool
3963 _edje_entry_cursor_is_visible_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
3964 {
3965    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3966    if (!c) return EINA_FALSE;
3967    return evas_textblock_cursor_format_is_visible_get(c);
3968 }
3969
3970 char *
3971 _edje_entry_cursor_content_get(Edje_Real_Part *rp, Edje_Cursor cur)
3972 {
3973    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3974
3975    if (!c) return NULL;
3976
3977    return evas_textblock_cursor_content_get(c);
3978 }
3979
3980 void
3981 _edje_entry_cursor_pos_set(Edje_Real_Part *rp, Edje_Cursor cur, int pos)
3982 {
3983    Entry *en;
3984    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3985
3986    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3987        (!rp->typedata.text)) return;
3988    en = rp->typedata.text->entry_data;
3989    if (!en) return;
3990    if (!c) return;
3991    /* Abort if cursor position didn't really change */
3992    if (evas_textblock_cursor_pos_get(c) == pos)
3993      return;
3994
3995    _edje_entry_imf_context_reset(rp);
3996    evas_textblock_cursor_pos_set(c, pos);
3997    _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
3998
3999    // TIZEN_ONLY(20150716): Add edje_object_part_text_freeze, thaw APIs for freezing cursor movements.
4000    //_edje_entry_imf_cursor_info_set(en);
4001    //_edje_emit(en->ed, "cursor,changed", rp->part->name);
4002    //_edje_entry_real_part_configure(en->ed, rp);
4003    _edje_emit(en->ed, "cursor,changed", rp->part->name);
4004    if (!en->freeze)
4005      {
4006         if (!en->have_selection)
4007           {
4008              _edje_entry_imf_cursor_info_set(en);
4009           }
4010         _edje_entry_real_part_configure(en->ed, rp);
4011      }
4012    //
4013 }
4014
4015 int
4016 _edje_entry_cursor_pos_get(Edje_Real_Part *rp, Edje_Cursor cur)
4017 {
4018    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4019    if (!c) return 0;
4020    return evas_textblock_cursor_pos_get(c);
4021 }
4022
4023 void
4024 _edje_entry_input_panel_layout_set(Edje_Real_Part *rp, Edje_Input_Panel_Layout layout)
4025 {
4026 #ifdef HAVE_ECORE_IMF
4027    Entry *en;
4028
4029    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4030        (!rp->typedata.text)) return;
4031    en = rp->typedata.text->entry_data;
4032    if (!en) return;
4033    if (en->imf_context)
4034      ecore_imf_context_input_panel_layout_set(en->imf_context, (Ecore_IMF_Input_Panel_Layout)layout);
4035 #else
4036    (void) rp;
4037    (void) layout;
4038 #endif
4039 }
4040
4041 Edje_Input_Panel_Layout
4042 _edje_entry_input_panel_layout_get(Edje_Real_Part *rp)
4043 {
4044 #ifdef HAVE_ECORE_IMF
4045    Entry *en;
4046
4047    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4048        (!rp->typedata.text)) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4049    en = rp->typedata.text->entry_data;
4050    if (!en) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4051    if (en->imf_context)
4052      return (Edje_Input_Panel_Layout)ecore_imf_context_input_panel_layout_get(en->imf_context);
4053    return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4054 #else
4055    return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4056    (void)rp;
4057 #endif
4058 }
4059
4060 void
4061 _edje_entry_input_panel_layout_variation_set(Edje_Real_Part *rp, int variation)
4062 {
4063    Entry *en;
4064
4065    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4066        (!rp->typedata.text)) return;
4067    en = rp->typedata.text->entry_data;
4068    if (!en) return;
4069 #ifdef HAVE_ECORE_IMF
4070    if (en->imf_context)
4071      ecore_imf_context_input_panel_layout_variation_set(en->imf_context, variation);
4072 #else
4073    (void) variation;
4074 #endif
4075 }
4076
4077 int
4078 _edje_entry_input_panel_layout_variation_get(Edje_Real_Part *rp)
4079 {
4080    Entry *en;
4081
4082    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4083        (!rp->typedata.text)) return 0;
4084    en = rp->typedata.text->entry_data;
4085    if (!en) return 0;
4086 #ifdef HAVE_ECORE_IMF
4087    if (en->imf_context)
4088      return ecore_imf_context_input_panel_layout_variation_get(en->imf_context);
4089 #endif
4090
4091    return 0;
4092 }
4093
4094 void
4095 _edje_entry_imf_context_reset(Edje_Real_Part *rp)
4096 {
4097 #ifdef HAVE_ECORE_IMF
4098    Entry *en;
4099
4100    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4101        (!rp->typedata.text)) return;
4102    en = rp->typedata.text->entry_data;
4103    if (!en) return;
4104    if (en->imf_context)
4105      ecore_imf_context_reset(en->imf_context);
4106    if (en->commit_cancel)
4107       en->commit_cancel = EINA_FALSE;
4108 #else
4109    (void)rp;
4110 #endif
4111 }
4112
4113 static void
4114 _edje_entry_imf_cursor_location_set(Entry *en)
4115 {
4116 #ifdef HAVE_ECORE_IMF
4117    Evas_Coord cx, cy, cw, ch;
4118    Evas_BiDi_Direction dir;
4119    if (!en || !en->rp || !en->imf_context) return;
4120
4121    _edje_entry_cursor_geometry_get(en->rp, &cx, &cy, &cw, &ch, &dir);
4122    ecore_imf_context_cursor_location_set(en->imf_context, cx, cy, cw, ch);
4123    ecore_imf_context_bidi_direction_set(en->imf_context, (Ecore_IMF_BiDi_Direction)dir);
4124 #else
4125    (void) en;
4126 #endif
4127 }
4128
4129 static void
4130 _edje_entry_imf_cursor_info_set(Entry *en)
4131 {
4132    int cursor_pos;
4133
4134 #ifdef HAVE_ECORE_IMF
4135    if (!en || !en->rp || !en->imf_context) return;
4136
4137    if (en->have_selection)
4138      {
4139         if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
4140           cursor_pos = evas_textblock_cursor_pos_get(en->sel_start);
4141         else
4142           cursor_pos = evas_textblock_cursor_pos_get(en->sel_end);
4143      }
4144    else
4145      cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
4146
4147    ecore_imf_context_cursor_position_set(en->imf_context, cursor_pos);
4148
4149    _edje_entry_imf_cursor_location_set(en);
4150 #else
4151    (void) en;
4152 #endif
4153 }
4154
4155 #ifdef HAVE_ECORE_IMF
4156 // TIZEN_ONLY (20150814): Pass correct cursor position and correct text to imf when selection is there
4157 // FIXME: Need to be pushed in upstream
4158 /*
4159 static Eina_Bool
4160 _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text, int *cursor_pos)
4161 {
4162    Edje *ed = data;
4163    Edje_Real_Part *rp = ed->focused_part;
4164    Entry *en = NULL;
4165    const char *str;
4166    char *plain_text;
4167
4168    if (!rp) return EINA_FALSE;
4169    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4170        (!rp->typedata.text)) return EINA_FALSE;
4171    else
4172      en = rp->typedata.text->entry_data;
4173    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4174        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4175      return EINA_FALSE;
4176
4177    if (text)
4178      {
4179         str = _edje_entry_text_get(rp);
4180         if (str)
4181           {
4182              plain_text = evas_textblock_text_markup_to_utf8(NULL, str);
4183
4184              if (plain_text)
4185                {
4186                   *text = strdup(plain_text);
4187
4188                   free(plain_text);
4189                   plain_text = NULL;
4190                }
4191              else
4192                *text = strdup("");
4193           }
4194         else
4195           *text = strdup("");
4196      }
4197
4198    if (cursor_pos)
4199      {
4200         if (en->cursor)
4201           *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
4202         else
4203           *cursor_pos = 0;
4204      }
4205
4206    return EINA_TRUE;
4207 }*/
4208
4209 static Eina_Bool
4210 _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text, int *cursor_pos)
4211 {
4212    Edje *ed = data;
4213    Edje_Real_Part *rp = ed->focused_part;
4214    Entry *en = NULL;
4215    const char *str;
4216    char *plain_text;
4217    Eina_Strbuf *buf = NULL;
4218
4219    if (!rp) return EINA_FALSE;
4220    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4221        (!rp->typedata.text)) return EINA_FALSE;
4222    else
4223      en = rp->typedata.text->entry_data;
4224    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4225        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4226      return EINA_FALSE;
4227
4228    if (text)
4229      {
4230         str = _edje_entry_text_get(rp);
4231         if (str)
4232           {
4233              plain_text = evas_textblock_text_markup_to_utf8(NULL, str);
4234
4235              if (plain_text)
4236                {
4237                   if (en->have_selection)
4238                     {
4239                        buf = eina_strbuf_new();
4240
4241                        if (en->sel_start)
4242                          eina_strbuf_append_n(buf, plain_text, evas_textblock_cursor_pos_get(en->sel_start));
4243                        else
4244                          eina_strbuf_append(buf, plain_text);
4245
4246                        *text = strdup(eina_strbuf_string_get(buf));
4247                        eina_strbuf_free(buf);
4248                     }
4249                   else
4250                     *text = strdup(plain_text);
4251
4252                   free(plain_text);
4253                   plain_text = NULL;
4254                }
4255              else
4256                *text = strdup("");
4257           }
4258         else
4259           *text = strdup("");
4260      }
4261
4262    if (cursor_pos)
4263      {
4264         if (en->have_selection && en->sel_start)
4265           *cursor_pos = evas_textblock_cursor_pos_get(en->sel_start);
4266         else if (en->cursor)
4267           *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
4268         else
4269           *cursor_pos = 0;
4270      }
4271
4272    return EINA_TRUE;
4273 }
4274 //
4275
4276 static void
4277 _edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info)
4278 {
4279    Edje *ed = data;
4280    Edje_Real_Part *rp = ed->focused_part;
4281    Entry *en = NULL;
4282    char *commit_str = event_info;
4283    Edje_Entry_Change_Info *info = NULL;
4284
4285    if ((!rp)) return;
4286    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4287        (!rp->typedata.text)) return;
4288    else
4289      en = rp->typedata.text->entry_data;
4290    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4291        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4292      return;
4293
4294    if (en->have_selection)
4295      {
4296         if (strcmp(commit_str, ""))
4297           {
4298              /* delete selected characters */
4299              _range_del_emit(ed, en->cursor, rp->object, en);
4300              _sel_clear(ed, en->cursor, rp->object, en);
4301           }
4302      }
4303
4304    /* delete preedit characters */
4305    _preedit_del(en);
4306    _preedit_clear(en);
4307
4308    // Skipping commit process when it is useless
4309    if (en->commit_cancel)
4310      {
4311         en->commit_cancel = EINA_FALSE;
4312         return;
4313      }
4314
4315    if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
4316        _edje_password_show_last)
4317      _edje_entry_hide_visible_password(ed, en->rp);
4318    if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
4319        _edje_password_show_last && (!en->preedit_start))
4320      {
4321         info = _text_filter_text_prepend(ed, en, en->cursor, commit_str,
4322                                          "+ password=off", "- password",
4323                                          EINA_TRUE, EINA_TRUE);
4324         if (info)
4325           {
4326              if (en->pw_timer)
4327                {
4328                   ecore_timer_del(en->pw_timer);
4329                   en->pw_timer = NULL;
4330                }
4331              if (_edje_password_show_last_timeout >= 0)
4332                en->pw_timer = ecore_timer_add
4333                  (_edje_password_show_last_timeout,
4334                    _password_timer_cb, en);
4335           }
4336      }
4337    else
4338      {
4339         info = _text_filter_text_prepend(ed, en, en->cursor, commit_str,
4340                                          NULL, NULL,
4341                                          EINA_TRUE, EINA_TRUE);
4342      }
4343
4344
4345    _edje_entry_imf_cursor_info_set(en);
4346    _anchors_get(en->cursor, rp->object, en);
4347    if (info)
4348      {
4349         _edje_emit(ed, "entry,changed", rp->part->name);
4350         _edje_emit_full(ed, "entry,changed,user", rp->part->name,
4351                         info, _free_entry_change_info);
4352         _edje_emit(ed, "cursor,changed", rp->part->name);
4353      }
4354    _edje_entry_imf_cursor_info_set(en);
4355    _edje_entry_real_part_configure(ed, rp);
4356 }
4357
4358 static void
4359 _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info EINA_UNUSED)
4360 {
4361    Edje *ed = data;
4362    Edje_Real_Part *rp = ed->focused_part;
4363    Entry *en = NULL;
4364    int cursor_pos;
4365    int preedit_start_pos, preedit_end_pos;
4366    char *preedit_string;
4367    char *markup_txt = NULL;
4368    char *tagname[] = {NULL, "preedit", "preedit_sel", "preedit_highlight",
4369                       "preedit_sub1", "preedit_sub2", "preedit_sub3", "preedit_sub4"};
4370    int i;
4371    size_t preedit_type_size = sizeof(tagname) / sizeof(tagname[0]);
4372    Eina_Bool preedit_end_state = EINA_FALSE;
4373    Eina_List *attrs = NULL, *l = NULL;
4374    Ecore_IMF_Preedit_Attr *attr;
4375    Eina_Strbuf *buf;
4376    Eina_Strbuf *preedit_attr_str;
4377
4378    if ((!rp)) return;
4379
4380    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4381        (!rp->typedata.text)) return;
4382    else
4383      en = rp->typedata.text->entry_data;
4384    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4385        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4386      return;
4387
4388    if (!en->imf_context) return;
4389
4390    ecore_imf_context_preedit_string_with_attributes_get(en->imf_context,
4391                                                         &preedit_string,
4392                                                         &attrs, &cursor_pos);
4393    if (!preedit_string) return;
4394
4395    if (!strcmp(preedit_string, ""))
4396      preedit_end_state = EINA_TRUE;
4397
4398    if (en->have_selection && !preedit_end_state)
4399      _range_del_emit(ed, en->cursor, rp->object, en);
4400
4401    /* delete preedit characters */
4402    _preedit_del(en);
4403
4404    preedit_start_pos = evas_textblock_cursor_pos_get(en->cursor);
4405
4406    /* insert preedit character(s) */
4407    if (strlen(preedit_string) > 0)
4408      {
4409         buf = eina_strbuf_new();
4410         if (attrs)
4411           {
4412              EINA_LIST_FOREACH(attrs, l, attr)
4413                {
4414                   if (attr->preedit_type < preedit_type_size &&
4415                       tagname[attr->preedit_type])
4416                     {
4417                        preedit_attr_str = eina_strbuf_new();
4418                        if (preedit_attr_str)
4419                          {
4420                             eina_strbuf_append_n(preedit_attr_str, preedit_string + attr->start_index, attr->end_index - attr->start_index);
4421                             markup_txt = evas_textblock_text_utf8_to_markup(NULL, eina_strbuf_string_get(preedit_attr_str));
4422
4423                             if (markup_txt)
4424                               {
4425                                  eina_strbuf_append_printf(buf, "<%s>%s</%s>", tagname[attr->preedit_type], markup_txt, tagname[attr->preedit_type]);
4426                                  free(markup_txt);
4427                               }
4428                             eina_strbuf_free(preedit_attr_str);
4429                          }
4430                     }
4431                   else
4432                     eina_strbuf_append(buf, preedit_string);
4433                }
4434           }
4435         else
4436           {
4437              eina_strbuf_append(buf, preedit_string);
4438           }
4439
4440         // For skipping useless commit
4441         if (!preedit_end_state)
4442            en->have_preedit = EINA_TRUE;
4443
4444         if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
4445             _edje_password_show_last)
4446           {
4447              Edje_Entry_Change_Info *info;
4448
4449              _edje_entry_hide_visible_password(ed, en->rp);
4450            // TIZEN_ONLY(20150629): In case of unicode language preedit status is needed to be maintained
4451            // so markup text comes from imf
4452               info = _text_filter_markup_prepend(ed, en, en->cursor,
4453                                                     eina_strbuf_string_get(buf),
4454                                                     "+ password=off",
4455                                                     "- password",
4456                                                     EINA_TRUE, EINA_TRUE);
4457               //info = _text_filter_text_prepend(ed, en, en->cursor,
4458               //                                eina_strbuf_string_get(buf),
4459               //                                 "+ password=off",
4460               //                                 "- password",
4461               //                                 EINA_TRUE, EINA_TRUE);
4462               //
4463            //
4464              if (info)
4465                {
4466                   if (en->pw_timer)
4467                     {
4468                        ecore_timer_del(en->pw_timer);
4469                        en->pw_timer = NULL;
4470                     }
4471                   if (_edje_password_show_last_timeout >= 0)
4472                     en->pw_timer = ecore_timer_add
4473                       (_edje_password_show_last_timeout,
4474                         _password_timer_cb, en);
4475                   free(info);
4476                }
4477           }
4478         else
4479           _text_filter_markup_prepend(ed, en, en->cursor,
4480                                       eina_strbuf_string_get(buf),
4481                                       NULL, NULL,
4482                                       EINA_TRUE, EINA_FALSE);
4483         eina_strbuf_free(buf);
4484      }
4485
4486    if (!preedit_end_state)
4487      {
4488         /* set preedit start cursor */
4489         if (!en->preedit_start)
4490           en->preedit_start = evas_object_textblock_cursor_new(rp->object);
4491         evas_textblock_cursor_copy(en->cursor, en->preedit_start);
4492
4493         /* set preedit end cursor */
4494         if (!en->preedit_end)
4495           en->preedit_end = evas_object_textblock_cursor_new(rp->object);
4496         evas_textblock_cursor_copy(en->cursor, en->preedit_end);
4497
4498         preedit_end_pos = evas_textblock_cursor_pos_get(en->cursor);
4499
4500         for (i = 0; i < (preedit_end_pos - preedit_start_pos); i++)
4501           {
4502              evas_textblock_cursor_char_prev(en->preedit_start);
4503           }
4504
4505         en->have_preedit = EINA_TRUE;
4506
4507         /* set cursor position */
4508         evas_textblock_cursor_pos_set(en->cursor, preedit_start_pos + cursor_pos);
4509      }
4510
4511    _edje_entry_imf_cursor_info_set(en);
4512    _anchors_get(en->cursor, rp->object, en);
4513    _edje_emit(ed, "preedit,changed", rp->part->name);
4514    _edje_emit(ed, "cursor,changed", rp->part->name);
4515
4516    /* delete attribute list */
4517    if (attrs)
4518      {
4519         EINA_LIST_FREE(attrs, attr) free(attr);
4520      }
4521
4522    free(preedit_string);
4523 }
4524
4525 static void
4526 _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info)
4527 {
4528    Edje *ed = data;
4529    Edje_Real_Part *rp = ed->focused_part;
4530    Entry *en = NULL;
4531    Ecore_IMF_Event_Delete_Surrounding *ev = event_info;
4532    Evas_Textblock_Cursor *del_start, *del_end;
4533    Edje_Entry_Change_Info *info;
4534    int cursor_pos;
4535    int start, end;
4536
4537    if ((!rp) || (!ev)) return;
4538    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4539        (!rp->typedata.text)) return;
4540    else
4541      en = rp->typedata.text->entry_data;
4542    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4543        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4544      return;
4545
4546    cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
4547
4548    del_start = evas_object_textblock_cursor_new(en->rp->object);
4549    evas_textblock_cursor_pos_set(del_start, cursor_pos + ev->offset);
4550
4551    del_end = evas_object_textblock_cursor_new(en->rp->object);
4552    evas_textblock_cursor_pos_set(del_end, cursor_pos + ev->offset + ev->n_chars);
4553
4554    start = evas_textblock_cursor_pos_get(del_start);
4555    end = evas_textblock_cursor_pos_get(del_end);
4556    if (start == end) goto end;
4557
4558    evas_textblock_cursor_range_delete(del_start, del_end);
4559    _anchors_get(en->cursor, rp->object, en);
4560    _anchors_update(en->cursor, rp->object, en);
4561
4562    info = calloc(1, sizeof(*info));
4563    info->insert = EINA_FALSE;
4564    info->change.del.start = start;
4565    info->change.del.end = end;
4566    _edje_emit(ed, "entry,changed", en->rp->part->name);
4567    _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info,
4568                    _free_entry_change_info);
4569    _edje_emit(ed, "cursor,changed", en->rp->part->name);
4570    _edje_emit(ed, "cursor,changed,manual", en->rp->part->name);
4571
4572    _edje_entry_imf_cursor_info_set(en);
4573    _edje_entry_real_part_configure(ed, rp);
4574
4575 end:
4576    evas_textblock_cursor_free(del_start);
4577    evas_textblock_cursor_free(del_end);
4578 }
4579
4580 static void
4581 _edje_entry_imf_event_selection_set_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info)
4582 {
4583    Edje *ed = data;
4584    Edje_Real_Part *rp = ed->focused_part;
4585    Entry *en = NULL;
4586    Ecore_IMF_Event_Selection *ev = event_info;
4587
4588    if ((!rp) || (!ev)) return;
4589    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4590        (!rp->typedata.text)) return;
4591    else
4592      en = rp->typedata.text->entry_data;
4593    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4594        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4595      return;
4596
4597    if (ev->start == ev->end)
4598      {
4599         _edje_entry_cursor_pos_set(rp, EDJE_CURSOR_MAIN, ev->start);
4600      }
4601    else
4602      {
4603         _sel_clear(ed, en->cursor, rp->object, en);
4604         evas_textblock_cursor_pos_set(en->cursor, ev->start);
4605         _sel_enable(ed, en->cursor, rp->object, en);
4606         _sel_start(en->cursor, rp->object, en);
4607         evas_textblock_cursor_pos_set(en->cursor, ev->end);
4608         _sel_extend(ed, en->cursor, rp->object, en);
4609      }
4610
4611    _edje_entry_real_part_configure(en->ed, rp);
4612 }
4613
4614 static Eina_Bool
4615 _edje_entry_imf_retrieve_selection_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text)
4616 {
4617    Edje *ed = data;
4618    Edje_Real_Part *rp = ed->focused_part;
4619    Entry *en = NULL;
4620
4621    if (!rp) return EINA_FALSE;
4622    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4623        (!rp->typedata.text)) return EINA_FALSE;
4624    else
4625      en = rp->typedata.text->entry_data;
4626    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4627        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4628      return EINA_FALSE;
4629
4630    if (en->have_selection)
4631      {
4632         if (text)
4633           *text = strdup(_edje_entry_selection_get(rp));
4634         return EINA_TRUE;
4635      }
4636    else
4637      return EINA_FALSE;
4638 }
4639 #endif
4640
4641 // TIZEN_ONLY(20150716): Add edje_object_part_text_freeze, thaw APIs for freezing cursor movements.
4642 void _edje_entry_freeze(Edje_Real_Part *rp)
4643 {
4644    Entry *en = NULL;
4645
4646    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4647        (!rp->typedata.text)) return;
4648
4649    en = rp->typedata.text->entry_data;
4650    if (!en) return;
4651
4652    en->freeze = EINA_TRUE;
4653 }
4654
4655 void _edje_entry_thaw(Edje_Real_Part *rp)
4656 {
4657    Entry *en = NULL;
4658
4659    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4660        (!rp->typedata.text)) return;
4661
4662    en = rp->typedata.text->entry_data;
4663    if (!en) return;
4664
4665    en->freeze = EINA_FALSE;
4666
4667    _edje_entry_imf_cursor_info_set(en);
4668    _edje_entry_real_part_configure(en->ed, rp);
4669 }
4670 ////////////////////////////////////////////////////////////////////////////////////////////////
4671
4672 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/