Imported Upstream version 1.7.4
[platform/upstream/edje.git] / src / lib / 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 #endif
9
10 typedef struct _Entry Entry;
11 typedef struct _Sel Sel;
12 typedef struct _Anchor Anchor;
13
14 static void _edje_entry_imf_cursor_info_set(Entry *en);
15
16 struct _Entry
17 {
18    Edje_Real_Part *rp;
19    Evas_Object *cursor_bg;
20    Evas_Object *cursor_fg;
21    Evas_Textblock_Cursor *cursor;
22    Evas_Textblock_Cursor *sel_start, *sel_end;
23    Evas_Textblock_Cursor *cursor_user, *cursor_user_extra;
24    Evas_Textblock_Cursor *preedit_start, *preedit_end;
25    Ecore_Timer *pw_timer;
26    Eina_List *sel;
27    Eina_List *anchors;
28    Eina_List *anchorlist;
29    Eina_List *itemlist;
30    Eina_List *seq;
31    char *selection;
32    Edje_Input_Panel_Lang input_panel_lang;
33    Eina_Bool composing : 1;
34    Eina_Bool selecting : 1;
35    Eina_Bool have_selection : 1;
36    Eina_Bool select_allow : 1;
37    Eina_Bool select_mod_start : 1;
38    Eina_Bool select_mod_end : 1;
39    Eina_Bool had_sel : 1;
40    Eina_Bool input_panel_enable : 1;
41    Eina_Bool prediction_allow : 1;
42
43 #ifdef HAVE_ECORE_IMF
44    Eina_Bool have_preedit : 1;
45    Ecore_IMF_Context *imf_context;
46 #endif
47 };
48
49 struct _Sel
50 {
51    Evas_Textblock_Rectangle rect;
52    Evas_Object *obj_fg, *obj_bg, *obj, *sobj;
53 };
54
55 struct _Anchor
56 {
57    Entry *en;
58    char *name;
59    Evas_Textblock_Cursor *start, *end;
60    Eina_List *sel;
61    Eina_Bool item : 1;
62 };
63
64 #ifdef HAVE_ECORE_IMF
65 static void
66 _preedit_clear(Entry *en)
67 {
68    if (en->preedit_start)
69      {
70         evas_textblock_cursor_free(en->preedit_start);
71         en->preedit_start = NULL;
72      }
73
74    if (en->preedit_end)
75      {
76         evas_textblock_cursor_free(en->preedit_end);
77         en->preedit_end = NULL;
78      }
79
80    en->have_preedit = EINA_FALSE;
81 }
82
83 static void
84 _preedit_del(Entry *en)
85 {
86    if (!en || !en->have_preedit) return;
87    if (!en->preedit_start || !en->preedit_end) return;
88    if (!evas_textblock_cursor_compare(en->preedit_start, en->preedit_end)) return;
89
90    /* delete the preedit characters */
91    evas_textblock_cursor_range_delete(en->preedit_start, en->preedit_end);
92 }
93
94 static void
95 _edje_entry_focus_in_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
96 {
97    Edje_Real_Part *rp;
98    Entry *en;
99
100    rp = data;
101    if (!rp || !rp->entry_data || !rp->edje || !rp->edje->obj) return;
102
103    en = rp->entry_data;
104    if (!en || !en->imf_context) return;
105
106    if (evas_object_focus_get(rp->edje->obj))
107      {
108         ecore_imf_context_reset(en->imf_context);
109         ecore_imf_context_focus_in(en->imf_context);
110         _edje_entry_imf_cursor_info_set(en);
111      }
112 }
113
114 static void
115 _edje_entry_focus_out_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
116 {
117    Edje_Real_Part *rp;
118    Entry *en;
119
120    rp = data;
121    if (!rp || !rp->entry_data) return;
122
123    en = rp->entry_data;
124    if (!en || !en->imf_context) return;
125
126    ecore_imf_context_reset(en->imf_context);
127    _edje_entry_imf_cursor_info_set(en);
128    ecore_imf_context_focus_out(en->imf_context);
129 }
130 #endif
131
132 static void
133 _edje_focus_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
134 {
135    Edje *ed = data;
136 #ifdef HAVE_ECORE_IMF
137    Edje_Real_Part *rp;
138    Entry *en;
139 #endif
140
141    _edje_emit(ed, "focus,in", "");
142 #ifdef HAVE_ECORE_IMF
143    rp = ed->focused_part;
144    if (!rp) return;
145
146    en = rp->entry_data;
147    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
148        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
149      return;
150
151    if (!en->imf_context) return;
152
153    ecore_imf_context_reset(en->imf_context);
154    ecore_imf_context_focus_in(en->imf_context);
155    _edje_entry_imf_cursor_info_set(en);
156 #endif
157 }
158
159 static void
160 _edje_focus_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
161 {
162    Edje *ed = data;
163 #ifdef HAVE_ECORE_IMF
164    Edje_Real_Part *rp = ed->focused_part;
165    Entry *en;
166 #endif
167
168    _edje_emit(ed, "focus,out", "");
169
170 #ifdef HAVE_ECORE_IMF
171    if (!rp) return;
172    en = rp->entry_data;
173    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
174        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
175      return;
176
177    if (!en->imf_context) return;
178
179    ecore_imf_context_reset(en->imf_context);
180    _edje_entry_imf_cursor_info_set(en);
181    ecore_imf_context_focus_out(en->imf_context);
182 #endif
183 }
184
185 static void
186 _text_filter_markup_prepend_internal(Entry *en, Evas_Textblock_Cursor *c, char *text)
187 {
188    Edje_Markup_Filter_Callback *cb;
189    Eina_List *l;
190
191    EINA_LIST_FOREACH(en->rp->edje->markup_filter_callbacks, l, cb)
192      {
193         if (!strcmp(cb->part, en->rp->part->name))
194           {
195              cb->func(cb->data, en->rp->edje->obj, cb->part, &text);
196              if (!text) break;
197           }
198      }
199    if (text)
200      {
201         evas_object_textblock_text_markup_prepend(c, text);
202         free(text);
203      }
204 }
205
206 static void
207 _text_filter_text_prepend(Entry *en, Evas_Textblock_Cursor *c, const char *text)
208 {
209    char *text2;
210    Edje_Text_Insert_Filter_Callback *cb;
211    Eina_List *l;
212
213    text2 = strdup(text);
214    EINA_LIST_FOREACH(en->rp->edje->text_insert_filter_callbacks, l, cb)
215      {
216         if (!strcmp(cb->part, en->rp->part->name))
217           {
218              cb->func(cb->data, en->rp->edje->obj, cb->part, EDJE_TEXT_FILTER_TEXT, &text2);
219              if (!text2) break;
220           }
221      }
222    if (text2)
223      {
224         char *markup_text;
225         markup_text = evas_textblock_text_utf8_to_markup(NULL, text2);
226         free(text2);
227         if (markup_text)
228           _text_filter_markup_prepend_internal(en, c, markup_text);
229      }
230 }
231
232 static void
233 _text_filter_format_prepend(Entry *en, Evas_Textblock_Cursor *c, const char *text)
234 {
235    char *text2;
236    Edje_Text_Insert_Filter_Callback *cb;
237    Eina_List *l;
238
239    text2 = strdup(text);
240    EINA_LIST_FOREACH(en->rp->edje->text_insert_filter_callbacks, l, cb)
241      {
242         if (!strcmp(cb->part, en->rp->part->name))
243           {
244              cb->func(cb->data, en->rp->edje->obj, cb->part, EDJE_TEXT_FILTER_FORMAT, &text2);
245              if (!text2) break;
246           }
247      }
248    if (text2)
249      {
250         char *s, *markup_text;
251
252         s = text2;
253         if (*s == '+')
254           {
255              s++;
256              while (*s == ' ') s++;
257              if (!s)
258                {
259                   free(text2);
260                   return;
261                }
262              markup_text = (char*) malloc(strlen(s) + 3);
263              if (markup_text)
264                {
265                   *(markup_text) = '<';
266                   strncpy((markup_text + 1), s, strlen(s));
267                   *(markup_text + strlen(s) + 1) = '>';
268                   *(markup_text + strlen(s) + 2) = '\0';
269                }
270           }
271         else if (s[0] == '-')
272           {
273              s++;
274              while (*s == ' ') s++;
275              if (!s)
276                {
277                   free(text2);
278                   return;
279                }
280              markup_text = (char*) malloc(strlen(s) + 4);
281              if (markup_text)
282                {
283                   *(markup_text) = '<';
284                   *(markup_text + 1) = '/';
285                   strncpy((markup_text + 2), s, strlen(s));
286                   *(markup_text + strlen(s) + 2) = '>';
287                   *(markup_text + strlen(s) + 3) = '\0';
288                }
289           }
290         else
291           {
292              markup_text = (char*) malloc(strlen(s) + 4);
293              if (markup_text)
294                {
295                   *(markup_text) = '<';
296                   strncpy((markup_text + 1), s, strlen(s));
297                   *(markup_text + strlen(s) + 1) = '/';
298                   *(markup_text + strlen(s) + 2) = '>';
299                   *(markup_text + strlen(s) + 3) = '\0';
300                }
301           }
302         free(text2);
303         if (markup_text)
304           _text_filter_markup_prepend_internal(en, c, markup_text);
305      }
306 }
307
308 static void
309 _text_filter_markup_prepend(Entry *en, Evas_Textblock_Cursor *c, const char *text)
310 {
311    char *text2;
312    Edje_Text_Insert_Filter_Callback *cb;
313    Eina_List *l;
314
315    text2 = strdup(text);
316    EINA_LIST_FOREACH(en->rp->edje->text_insert_filter_callbacks, l, cb)
317      {
318         if (!strcmp(cb->part, en->rp->part->name))
319           {
320              cb->func(cb->data, en->rp->edje->obj, cb->part, EDJE_TEXT_FILTER_MARKUP, &text2);
321              if (!text2) break;
322           }
323      }
324    if (text2)
325      _text_filter_markup_prepend_internal(en, c, text2);
326 }
327
328 static void
329 _curs_update_from_curs(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__, Entry *en, Evas_Coord *cx, Evas_Coord *cy)
330 {
331    Evas_Coord cw, ch;
332    Evas_Textblock_Cursor_Type cur_type;
333    if (c != en->cursor) return;
334    switch (en->rp->part->cursor_mode)
335      {
336       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
337          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
338          break;
339       case EDJE_ENTRY_CURSOR_MODE_UNDER:
340          /* no break for a resaon */
341       default:
342          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
343      }
344    evas_textblock_cursor_geometry_get(c, cx, cy, &cw, &ch, NULL, cur_type);
345    *cx += (cw / 2);
346    *cy += (ch / 2);
347 }
348
349 static int
350 _curs_line_last_get(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o, Entry *en __UNUSED__)
351 {
352    Evas_Textblock_Cursor *cc;
353    int ln;
354
355    cc = evas_object_textblock_cursor_new(o);
356    evas_textblock_cursor_paragraph_last(cc);
357    ln = evas_textblock_cursor_line_geometry_get(cc, NULL, NULL, NULL, NULL);
358    evas_textblock_cursor_free(cc);
359    return ln;
360 }
361
362 static void
363 _curs_lin_start(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
364                 Entry *en __UNUSED__)
365 {
366    evas_textblock_cursor_line_char_first(c);
367 }
368
369 static void
370 _curs_lin_end(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
371               Entry *en __UNUSED__)
372 {
373    evas_textblock_cursor_line_char_last(c);
374 }
375
376 static void
377 _curs_start(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
378             Entry *en __UNUSED__)
379 {
380    evas_textblock_cursor_paragraph_first(c);
381 }
382
383 static void
384 _curs_end(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__, Entry *en __UNUSED__)
385 {
386    evas_textblock_cursor_paragraph_last(c);
387 }
388
389 static void
390 _curs_jump_line(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int ln)
391 {
392    Evas_Coord cx, cy;
393    Evas_Coord lx, ly, lw, lh;
394    int last = _curs_line_last_get(c, o, en);
395
396    if (ln < 0) ln = 0;
397    else
398      {
399         if (ln > last) ln = last;
400      }
401
402    _curs_update_from_curs(c, o, en, &cx, &cy);
403
404    if (!evas_object_textblock_line_number_geometry_get(o, ln, &lx, &ly, &lw, &lh))
405      return;
406    if (evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
407      return;
408    evas_textblock_cursor_line_set(c, ln);
409    if (cx < (lx + (lw / 2)))
410      {
411         if (ln == last) _curs_end(c, o, en);
412         _curs_lin_start(c, o, en);
413      }
414    else
415      {
416         if (ln == last)
417           _curs_end(c, o, en);
418         else
419           _curs_lin_end(c, o, en);
420      }
421 }
422
423 static void
424 _curs_jump_line_by(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int by)
425 {
426    int ln;
427
428    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL) + by;
429    _curs_jump_line(c, o, en, ln);
430 }
431
432 static void
433 _curs_up(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
434 {
435    _curs_jump_line_by(c, o, en, -1);
436 }
437
438 static void
439 _curs_down(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
440 {
441    _curs_jump_line_by(c, o, en, 1);
442 }
443
444 static void
445 _sel_start(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
446 {
447    if (en->sel_start) return;
448    en->sel_start = evas_object_textblock_cursor_new(o);
449    evas_textblock_cursor_copy(c, en->sel_start);
450    en->sel_end = evas_object_textblock_cursor_new(o);
451    evas_textblock_cursor_copy(c, en->sel_end);
452
453    en->have_selection = EINA_FALSE;
454    if (en->selection)
455      {
456         free(en->selection);
457         en->selection = NULL;
458      }
459 }
460
461 static void
462 _sel_enable(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
463 {
464    if (en->have_selection) return;
465    en->have_selection = EINA_TRUE;
466    if (en->selection)
467      {
468         free(en->selection);
469         en->selection = NULL;
470      }
471    _edje_emit(en->rp->edje, "selection,start", en->rp->part->name);
472 }
473
474 static void
475 _sel_extend(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
476 {
477    if (!en->sel_end) return;
478    _edje_entry_imf_context_reset(en->rp);
479    _sel_enable(c, o, en);
480    if (!evas_textblock_cursor_compare(c, en->sel_end)) return;
481    evas_textblock_cursor_copy(c, en->sel_end);
482    if (en->selection)
483      {
484         free(en->selection);
485         en->selection = NULL;
486      }
487    _edje_emit(en->rp->edje, "selection,changed", en->rp->part->name);
488 }
489
490 static void
491 _sel_preextend(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
492 {
493    if (!en->sel_end) return;
494    _edje_entry_imf_context_reset(en->rp);
495    _sel_enable(c, o, en);
496    if (!evas_textblock_cursor_compare(c, en->sel_start)) return;
497    evas_textblock_cursor_copy(c, en->sel_start);
498    if (en->selection)
499      {
500         free(en->selection);
501         en->selection = NULL;
502      }
503    _edje_emit(en->rp->edje, "selection,changed", en->rp->part->name);
504 }
505
506 static void
507 _sel_clear(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
508 {
509    en->had_sel = EINA_FALSE;
510    if (en->sel_start)
511      {
512         evas_textblock_cursor_free(en->sel_start);
513         evas_textblock_cursor_free(en->sel_end);
514         en->sel_start = NULL;
515         en->sel_end = NULL;
516      }
517    if (en->selection)
518      {
519         free(en->selection);
520         en->selection = NULL;
521      }
522    while (en->sel)
523      {
524         Sel *sel;
525
526         sel = en->sel->data;
527         if (sel->obj_bg) evas_object_del(sel->obj_bg);
528         if (sel->obj_fg) evas_object_del(sel->obj_fg);
529         free(sel);
530         en->sel = eina_list_remove_list(en->sel, en->sel);
531      }
532    if (en->have_selection)
533      {
534         en->have_selection = EINA_FALSE;
535         _edje_emit(en->rp->edje, "selection,cleared", en->rp->part->name);
536      }
537 }
538
539 static void
540 _sel_update(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o, Entry *en)
541 {
542    Eina_List *range = NULL, *l;
543    Sel *sel;
544    Evas_Coord x, y, w, h;
545    Evas_Object *smart, *clip;
546
547    smart = evas_object_smart_parent_get(o);
548    clip = evas_object_clip_get(o);
549    if (en->sel_start)
550      range = evas_textblock_cursor_range_geometry_get(en->sel_start, en->sel_end);
551    else
552      return;
553    if (eina_list_count(range) != eina_list_count(en->sel))
554      {
555         while (en->sel)
556           {
557              sel = en->sel->data;
558              if (sel->obj_bg) evas_object_del(sel->obj_bg);
559              if (sel->obj_fg) evas_object_del(sel->obj_fg);
560              free(sel);
561              en->sel = eina_list_remove_list(en->sel, en->sel);
562           }
563         if (en->have_selection)
564           {
565              for (l = range; l; l = eina_list_next(l))
566                {
567                   Evas_Object *ob;
568
569                   sel = calloc(1, sizeof(Sel));
570                   en->sel = eina_list_append(en->sel, sel);
571                   ob = edje_object_add(en->rp->edje->base.evas);
572                   edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source);
573                   evas_object_smart_member_add(ob, smart);
574                   evas_object_stack_below(ob, o);
575                   evas_object_clip_set(ob, clip);
576                   evas_object_pass_events_set(ob, EINA_TRUE);
577                   evas_object_show(ob);
578                   sel->obj_bg = ob;
579                   _edje_subobj_register(en->rp->edje, sel->obj_bg);
580
581                   ob = edje_object_add(en->rp->edje->base.evas);
582                   edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source2);
583                   evas_object_smart_member_add(ob, smart);
584                   evas_object_stack_above(ob, o);
585                   evas_object_clip_set(ob, clip);
586                   evas_object_pass_events_set(ob, EINA_TRUE);
587                   evas_object_show(ob);
588                   sel->obj_fg = ob;
589                   _edje_subobj_register(en->rp->edje, sel->obj_fg);
590                }
591           }
592      }
593    x = y = w = h = -1;
594    evas_object_geometry_get(o, &x, &y, &w, &h);
595    if (en->have_selection)
596      {
597         EINA_LIST_FOREACH(en->sel, l, sel)
598           {
599              Evas_Textblock_Rectangle *r;
600
601              r = range->data;
602              if (sel->obj_bg)
603                {
604                   evas_object_move(sel->obj_bg, x + r->x, y + r->y);
605                   evas_object_resize(sel->obj_bg, r->w, r->h);
606                }
607              if (sel->obj_fg)
608                {
609                   evas_object_move(sel->obj_fg, x + r->x, y + r->y);
610                   evas_object_resize(sel->obj_fg, r->w, r->h);
611                }
612              *(&(sel->rect)) = *r;
613              range = eina_list_remove_list(range, range);
614              free(r);
615           }
616      }
617    else
618      {
619         while (range)
620           {
621              free(range->data);
622              range = eina_list_remove_list(range, range);
623           }
624      }
625 }
626
627 static void
628 _edje_anchor_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
629 {
630    Anchor *an = data;
631    Evas_Event_Mouse_Down *ev = event_info;
632    Edje_Real_Part *rp = an->en->rp;
633    char *buf, *n;
634    size_t len;
635    int ignored;
636    Entry *en;
637
638    en = rp->entry_data;
639    if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
640        (en->select_allow))
641      return;
642    ignored = rp->part->ignore_flags & ev->event_flags;
643    if ((!ev->event_flags) || (!ignored))
644      {
645         n = an->name;
646         if (!n) n = "";
647         len = 200 + strlen(n);
648         buf = alloca(len);
649         if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
650           snprintf(buf, len, "anchor,mouse,down,%i,%s,triple", ev->button, n);
651         else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
652           snprintf(buf, len, "anchor,mouse,down,%i,%s,double", ev->button, n);
653         else
654           snprintf(buf, len, "anchor,mouse,down,%i,%s", ev->button, n);
655         _edje_emit(rp->edje, buf, rp->part->name);
656      }
657 }
658
659 static void
660 _edje_anchor_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
661 {
662    Anchor *an = data;
663    Evas_Event_Mouse_Up *ev = event_info;
664    Edje_Real_Part *rp = an->en->rp;
665    char *buf, *n;
666    size_t len;
667    int ignored;
668    Entry *en;
669
670    en = rp->entry_data;
671    ignored = rp->part->ignore_flags & ev->event_flags;
672    if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
673        (en->select_allow))
674      return;
675    n = an->name;
676    if (!n) n = "";
677    len = 200 + strlen(n);
678    buf = alloca(len);
679    if ((!ev->event_flags) || (!ignored))
680      {
681         snprintf(buf, len, "anchor,mouse,up,%i,%s", ev->button, n);
682         _edje_emit(rp->edje, buf, rp->part->name);
683      }
684    if ((rp->still_in) && (rp->clicked_button == ev->button) && (!ignored))
685      {
686         snprintf(buf, len, "anchor,mouse,clicked,%i,%s", ev->button, n);
687         _edje_emit(rp->edje, buf, rp->part->name);
688      }
689 }
690
691 static void
692 _edje_anchor_mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
693 {
694    Anchor *an = data;
695    Evas_Event_Mouse_Move *ev = event_info;
696    Edje_Real_Part *rp = an->en->rp;
697    char *buf, *n;
698    size_t len;
699    int ignored;
700    Entry *en;
701
702    en = rp->entry_data;
703    if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
704        (en->select_allow))
705      return;
706    ignored = rp->part->ignore_flags & ev->event_flags;
707    if ((!ev->event_flags) || (!ignored))
708      {
709         n = an->name;
710         if (!n) n = "";
711         len = 200 + strlen(n);
712         buf = alloca(len);
713         snprintf(buf, len, "anchor,mouse,move,%s", n);
714         _edje_emit(rp->edje, buf, rp->part->name);
715      }
716 }
717
718 static void
719 _edje_anchor_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
720 {
721    Anchor *an = data;
722    Evas_Event_Mouse_In *ev = event_info;
723    Edje_Real_Part *rp = an->en->rp;
724    char *buf, *n;
725    size_t len;
726    int ignored;
727
728    ignored = rp->part->ignore_flags & ev->event_flags;
729    if ((!ev->event_flags) || (!ignored))
730      {
731         n = an->name;
732         if (!n) n = "";
733         len = 200 + strlen(n);
734         buf = alloca(len);
735         snprintf(buf, len, "anchor,mouse,in,%s", n);
736         _edje_emit(rp->edje, buf, rp->part->name);
737      }
738 }
739
740 static void
741 _edje_anchor_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
742 {
743    Anchor *an = data;
744    Evas_Event_Mouse_Out *ev = event_info;
745    Edje_Real_Part *rp = an->en->rp;
746    char *buf, *n;
747    size_t len;
748    int ignored;
749
750    ignored = rp->part->ignore_flags & ev->event_flags;
751    if ((!ev->event_flags) || (!ignored))
752      {
753         n = an->name;
754         if (!n) n = "";
755         len = 200 + strlen(n);
756         buf = alloca(len);
757         snprintf(buf, len, "anchor,mouse,out,%s", n);
758         _edje_emit(rp->edje, buf, rp->part->name);
759      }
760 }
761
762 static void
763 _anchors_update(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o, Entry *en)
764 {
765    Eina_List *l, *ll, *range = NULL;
766    Evas_Coord x, y, w, h;
767    Evas_Object *smart, *clip;
768    Sel *sel;
769    Anchor *an;
770
771    smart = evas_object_smart_parent_get(o);
772    clip = evas_object_clip_get(o);
773    x = y = w = h = -1;
774    evas_object_geometry_get(o, &x, &y, &w, &h);
775    EINA_LIST_FOREACH(en->anchors, l, an)
776      {
777         // for item anchors
778         if (an->item)
779           {
780              Evas_Object *ob;
781
782              if (!an->sel)
783                {
784                   while (an->sel)
785                     {
786                        sel = an->sel->data;
787                        if (sel->obj_bg) evas_object_del(sel->obj_bg);
788                        if (sel->obj_fg) evas_object_del(sel->obj_fg);
789                        if (sel->obj) evas_object_del(sel->obj);
790                        free(sel);
791                        an->sel = eina_list_remove_list(an->sel, an->sel);
792                     }
793
794                   sel = calloc(1, sizeof(Sel));
795                   an->sel = eina_list_append(an->sel, sel);
796
797                   if (en->rp->edje->item_provider.func)
798                     {
799                        ob = en->rp->edje->item_provider.func
800                          (en->rp->edje->item_provider.data, smart,
801                              en->rp->part->name, an->name);
802                        evas_object_smart_member_add(ob, smart);
803                        evas_object_stack_above(ob, o);
804                        evas_object_clip_set(ob, clip);
805                        evas_object_pass_events_set(ob, EINA_TRUE);
806                        evas_object_show(ob);
807                        sel->obj = ob;
808                     }
809                }
810           }
811         // for link anchors
812         else
813           {
814              range =
815                evas_textblock_cursor_range_geometry_get(an->start, an->end);
816              if (eina_list_count(range) != eina_list_count(an->sel))
817                {
818                   while (an->sel)
819                     {
820                        sel = an->sel->data;
821                        if (sel->obj_bg) evas_object_del(sel->obj_bg);
822                        if (sel->obj_fg) evas_object_del(sel->obj_fg);
823                        if (sel->obj) evas_object_del(sel->obj);
824                        free(sel);
825                        an->sel = eina_list_remove_list(an->sel, an->sel);
826                     }
827                   for (ll = range; ll; ll = eina_list_next(ll))
828                     {
829                        Evas_Object *ob;
830
831                        sel = calloc(1, sizeof(Sel));
832                        an->sel = eina_list_append(an->sel, sel);
833                        ob = edje_object_add(en->rp->edje->base.evas);
834                        edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source5);
835                        evas_object_smart_member_add(ob, smart);
836                        evas_object_stack_below(ob, o);
837                        evas_object_clip_set(ob, clip);
838                        evas_object_pass_events_set(ob, EINA_TRUE);
839                        evas_object_show(ob);
840                        sel->obj_bg = ob;
841                        _edje_subobj_register(en->rp->edje, sel->obj_bg);
842
843                        ob = edje_object_add(en->rp->edje->base.evas);
844                        edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source6);
845                        evas_object_smart_member_add(ob, smart);
846                        evas_object_stack_above(ob, o);
847                        evas_object_clip_set(ob, clip);
848                        evas_object_pass_events_set(ob, EINA_TRUE);
849                        evas_object_show(ob);
850                        sel->obj_fg = ob;
851                        _edje_subobj_register(en->rp->edje, sel->obj_fg);
852
853                        ob = evas_object_rectangle_add(en->rp->edje->base.evas);
854                        evas_object_color_set(ob, 0, 0, 0, 0);
855                        evas_object_smart_member_add(ob, smart);
856                        evas_object_stack_above(ob, o);
857                        evas_object_clip_set(ob, clip);
858                        evas_object_repeat_events_set(ob, EINA_TRUE);
859                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_DOWN, _edje_anchor_mouse_down_cb, an);
860                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_UP, _edje_anchor_mouse_up_cb, an);
861                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_MOVE, _edje_anchor_mouse_move_cb, an);
862                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_IN, _edje_anchor_mouse_in_cb, an);
863                        evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_OUT, _edje_anchor_mouse_out_cb, an);
864                        evas_object_show(ob);
865                        sel->obj = ob;
866                     }
867                }
868           }
869         EINA_LIST_FOREACH(an->sel, ll, sel)
870           {
871              if (an->item)
872                {
873                   Evas_Coord cx, cy, cw, ch;
874
875                   if (!evas_textblock_cursor_format_item_geometry_get
876                       (an->start, &cx, &cy, &cw, &ch))
877                     continue;
878                   evas_object_move(sel->obj, x + cx, y + cy);
879                   evas_object_resize(sel->obj, cw, ch);
880                }
881              else
882                {
883                   Evas_Textblock_Rectangle *r;
884
885                   r = range->data;
886                   *(&(sel->rect)) = *r;
887                   if (sel->obj_bg)
888                     {
889                        evas_object_move(sel->obj_bg, x + r->x, y + r->y);
890                        evas_object_resize(sel->obj_bg, r->w, r->h);
891                     }
892                   if (sel->obj_fg)
893                     {
894                        evas_object_move(sel->obj_fg, x + r->x, y + r->y);
895                        evas_object_resize(sel->obj_fg, r->w, r->h);
896                     }
897                   if (sel->obj)
898                     {
899                        evas_object_move(sel->obj, x + r->x, y + r->y);
900                        evas_object_resize(sel->obj, r->w, r->h);
901                     }
902                   range = eina_list_remove_list(range, range);
903                   free(r);
904                }
905           }
906      }
907 }
908
909 static void
910 _anchors_clear(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
911 {
912    while (en->anchorlist)
913      {
914         free(en->anchorlist->data);
915         en->anchorlist = eina_list_remove_list(en->anchorlist, en->anchorlist);
916      }
917    while (en->itemlist)
918      {
919         free(en->itemlist->data);
920         en->itemlist = eina_list_remove_list(en->itemlist, en->itemlist);
921      }
922    while (en->anchors)
923      {
924         Anchor *an = en->anchors->data;
925
926         evas_textblock_cursor_free(an->start);
927         evas_textblock_cursor_free(an->end);
928         while (an->sel)
929           {
930              Sel *sel = an->sel->data;
931              if (sel->obj_bg) evas_object_del(sel->obj_bg);
932              if (sel->obj_fg) evas_object_del(sel->obj_fg);
933              if (sel->obj) evas_object_del(sel->obj);
934              free(sel);
935              an->sel = eina_list_remove_list(an->sel, an->sel);
936           }
937         free(an->name);
938         free(an);
939         en->anchors = eina_list_remove_list(en->anchors, en->anchors);
940      }
941 }
942
943 static void
944 _anchors_get(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
945 {
946    const Eina_List *anchors_a, *anchors_item;
947    Anchor *an = NULL;
948    _anchors_clear(c, o, en);
949
950    anchors_a = evas_textblock_node_format_list_get(o, "a");
951    anchors_item = evas_textblock_node_format_list_get(o, "item");
952
953    if (anchors_a)
954      {
955         const Evas_Object_Textblock_Node_Format *node;
956         const Eina_List *itr;
957         EINA_LIST_FOREACH(anchors_a, itr, node)
958           {
959              const char *s = evas_textblock_node_format_text_get(node);
960              char *p;
961              an = calloc(1, sizeof(Anchor));
962              if (!an)
963                break;
964
965              an->en = en;
966              p = strstr(s, "href=");
967              if (p)
968                {
969                   an->name = strdup(p + 5);
970                }
971              en->anchors = eina_list_append(en->anchors, an);
972              an->start = evas_object_textblock_cursor_new(o);
973              an->end = evas_object_textblock_cursor_new(o);
974              evas_textblock_cursor_at_format_set(an->start, node);
975              evas_textblock_cursor_copy(an->start, an->end);
976
977              /* Close the anchor, if the anchor was without text,
978               * free it as well */
979              node = evas_textblock_node_format_next_get(node);
980              for (; node; node = evas_textblock_node_format_next_get(node))
981                {
982                   s = evas_textblock_node_format_text_get(node);
983                   if ((!strcmp(s, "- a")) || (!strcmp(s, "-a")))
984                     break;
985                }
986
987              if (node)
988                {
989                   evas_textblock_cursor_at_format_set(an->end, node);
990                }
991              else if (!evas_textblock_cursor_compare(an->start, an->end))
992                {
993                   if (an->name) free(an->name);
994                   evas_textblock_cursor_free(an->start);
995                   evas_textblock_cursor_free(an->end);
996                   en->anchors = eina_list_remove(en->anchors, an);
997                   free(an);
998                }
999              an = NULL;
1000           }
1001      }
1002
1003    if (anchors_item)
1004      {
1005         const Evas_Object_Textblock_Node_Format *node;
1006         const Eina_List *itr;
1007         EINA_LIST_FOREACH(anchors_item, itr, node)
1008           {
1009              const char *s = evas_textblock_node_format_text_get(node);
1010              char *p;
1011              an = calloc(1, sizeof(Anchor));
1012              if (!an)
1013                break;
1014
1015              an->en = en;
1016              an->item = 1;
1017              p = strstr(s, "href=");
1018              if (p)
1019                {
1020                   an->name = strdup(p + 5);
1021                }
1022              en->anchors = eina_list_append(en->anchors, an);
1023              an->start = evas_object_textblock_cursor_new(o);
1024              an->end = evas_object_textblock_cursor_new(o);
1025              evas_textblock_cursor_at_format_set(an->start, node);
1026              evas_textblock_cursor_copy(an->start, an->end);
1027              /* Although needed in textblock, don't bother with finding the end
1028               * here cause it doesn't really matter. */
1029           }
1030      }
1031 }
1032
1033 static void
1034 _free_entry_change_info(void *_info)
1035 {
1036    Edje_Entry_Change_Info *info = (Edje_Entry_Change_Info *) _info;
1037    if (info->insert)
1038      {
1039         eina_stringshare_del(info->change.insert.content);
1040      }
1041    else
1042      {
1043         eina_stringshare_del(info->change.del.content);
1044      }
1045    free(info);
1046 }
1047
1048 static void
1049 _range_del_emit(Edje *ed, Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
1050 {
1051    size_t start, end;
1052    char *tmp;
1053    Edje_Entry_Change_Info *info;
1054
1055    start = evas_textblock_cursor_pos_get(en->sel_start);
1056    end = evas_textblock_cursor_pos_get(en->sel_end);
1057    if (start == end)
1058       goto noop;
1059
1060    info = calloc(1, sizeof(*info));
1061    info->insert = EINA_FALSE;
1062    info->change.del.start = start;
1063    info->change.del.end = end;
1064
1065    tmp = evas_textblock_cursor_range_text_get(en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
1066    info->change.del.content = eina_stringshare_add(tmp);
1067    if (tmp) free(tmp);
1068    evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1069    _edje_emit(ed, "entry,changed", en->rp->part->name);
1070    _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info,
1071                    _free_entry_change_info);
1072 noop:
1073    _sel_clear(en->cursor, en->rp->object, en);
1074 }
1075
1076 static void
1077 _range_del(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
1078 {
1079    evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1080    _sel_clear(en->cursor, en->rp->object, en);
1081 }
1082
1083 static void
1084 _delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos,
1085              Eina_Bool backspace)
1086 {
1087    if (!evas_textblock_cursor_char_next(c))
1088      {
1089         return;
1090      }
1091    evas_textblock_cursor_char_prev(c);
1092
1093    Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1094    char *tmp = evas_textblock_cursor_content_get(c);
1095
1096    info->insert = EINA_FALSE;
1097    if (backspace)
1098      {
1099         info->change.del.start = pos - 1;
1100         info->change.del.end = pos;
1101      }
1102    else
1103      {
1104         info->change.del.start = pos + 1;
1105         info->change.del.end = pos;
1106      }
1107
1108    info->change.del.content = eina_stringshare_add(tmp);
1109    if (tmp) free(tmp);
1110
1111    evas_textblock_cursor_char_delete(c);
1112    _edje_emit(ed, "entry,changed", en->rp->part->name);
1113    _edje_emit_full(ed, "entry,changed,user", en->rp->part->name,
1114                    info, _free_entry_change_info);
1115 }
1116
1117 static void
1118 _edje_entry_hide_visible_password(Edje_Real_Part *rp)
1119 {
1120    const Evas_Object_Textblock_Node_Format *node;
1121    node = evas_textblock_node_format_first_get(rp->object);
1122    for (; node; node = evas_textblock_node_format_next_get(node))
1123      {
1124         const char *text = evas_textblock_node_format_text_get(node);
1125         if (text)
1126           {
1127              if (!strcmp(text, "+ password=off"))
1128                {
1129                   evas_textblock_node_format_remove_pair(rp->object,
1130                                                          (Evas_Object_Textblock_Node_Format *) node);
1131                   break;
1132                }
1133           }
1134      }
1135    _edje_entry_real_part_configure(rp);
1136    _edje_emit(rp->edje, "entry,changed", rp->part->name);
1137 }
1138
1139 static Eina_Bool
1140 _password_timer_cb(void *data)
1141 {
1142    Entry *en = (Entry *)data;
1143    _edje_entry_hide_visible_password(en->rp);
1144    en->pw_timer = NULL;
1145    return ECORE_CALLBACK_CANCEL;
1146 }
1147
1148 static Eina_Bool
1149 _is_modifier(const char *key)
1150 {
1151    if ((!strncmp(key, "Shift", 5)) ||
1152        (!strncmp(key, "Control", 7)) ||
1153        (!strncmp(key, "Alt", 3)) ||
1154        (!strncmp(key, "Meta", 4)) ||
1155        (!strncmp(key, "Super", 5)) ||
1156        (!strncmp(key, "Hyper", 5)) ||
1157        (!strcmp(key, "Scroll_Lock")) ||
1158        (!strcmp(key, "Num_Lock")) ||
1159        (!strcmp(key, "Caps_Lock")))
1160      return EINA_TRUE;
1161    return EINA_FALSE;
1162 }
1163
1164 static void
1165 _compose_seq_reset(Entry *en)
1166 {
1167    char *str;
1168    
1169    EINA_LIST_FREE(en->seq, str) eina_stringshare_del(str);
1170    en->composing = EINA_FALSE;
1171 }
1172
1173 static void
1174 _edje_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1175 {
1176    Edje *ed = data;
1177    Evas_Event_Key_Down *ev = event_info;
1178    Edje_Real_Part *rp = ed->focused_part;
1179    Entry *en;
1180    Eina_Bool control, alt, shift;
1181    Eina_Bool multiline;
1182    Eina_Bool cursor_changed;
1183    int old_cur_pos;
1184    if (!rp) return;
1185    en = rp->entry_data;
1186    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1187        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1188      return;
1189    if (!ev->keyname) return;
1190
1191 #ifdef HAVE_ECORE_IMF
1192    if (en->imf_context)
1193      {
1194         Ecore_IMF_Event_Key_Down ecore_ev;
1195         ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
1196         if (!en->composing)
1197           {
1198              if (ecore_imf_context_filter_event(en->imf_context,
1199                                                 ECORE_IMF_EVENT_KEY_DOWN,
1200                                                 (Ecore_IMF_Event *)&ecore_ev))
1201                return;
1202           }
1203      }
1204 #endif
1205
1206    if ((!strcmp(ev->keyname, "Escape")) ||
1207        (!strcmp(ev->keyname, "Return")) || (!strcmp(ev->keyname, "KP_Enter")))
1208      _edje_entry_imf_context_reset(rp);
1209
1210    old_cur_pos = evas_textblock_cursor_pos_get(en->cursor);
1211
1212    control = evas_key_modifier_is_set(ev->modifiers, "Control");
1213    alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
1214    shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
1215    multiline = rp->part->multiline;
1216    cursor_changed = EINA_FALSE;
1217    if (!strcmp(ev->keyname, "Escape"))
1218      {
1219         _compose_seq_reset(en);
1220         // dead keys here. Escape for now (should emit these)
1221         _edje_emit(ed, "entry,key,escape", rp->part->name);
1222         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1223      }
1224    else if (!strcmp(ev->keyname, "Up") ||
1225             (!strcmp(ev->keyname, "KP_Up") && !ev->string))
1226      {
1227         _compose_seq_reset(en);
1228         if (multiline)
1229           {
1230              if (en->select_allow)
1231                {
1232                   if (shift) _sel_start(en->cursor, rp->object, en);
1233                   else _sel_clear(en->cursor, rp->object, en);
1234                }
1235              _curs_up(en->cursor, rp->object, en);
1236              if (en->select_allow)
1237                {
1238                   if (shift) _sel_extend(en->cursor, rp->object, en);
1239                   else _sel_clear(en->cursor, rp->object, en);
1240                }
1241              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1242           }
1243         _edje_emit(ed, "entry,key,up", rp->part->name);
1244         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
1245      }
1246    else if (!strcmp(ev->keyname, "Down") ||
1247             (!strcmp(ev->keyname, "KP_Down") && !ev->string))
1248      {
1249         _compose_seq_reset(en);
1250         if (multiline)
1251           {
1252              if (en->select_allow)
1253                {
1254                   if (shift) _sel_start(en->cursor, rp->object, en);
1255                   else _sel_clear(en->cursor, rp->object, en);
1256                }
1257              _curs_down(en->cursor, rp->object, en);
1258              if (en->select_allow)
1259                {
1260                   if (shift) _sel_extend(en->cursor, rp->object, en);
1261                   else _sel_clear(en->cursor, rp->object, en);
1262                }
1263              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1264           }
1265         _edje_emit(ed, "entry,key,down", rp->part->name);
1266         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
1267      }
1268    else if (!strcmp(ev->keyname, "Left") ||
1269             (!strcmp(ev->keyname, "KP_Left") && !ev->string))
1270      {
1271         _compose_seq_reset(en);
1272         if (en->select_allow)
1273           {
1274              if (shift) _sel_start(en->cursor, rp->object, en);
1275              else _sel_clear(en->cursor, rp->object, en);
1276           }
1277         evas_textblock_cursor_char_prev(en->cursor);
1278         /* If control is pressed, go to the start of the word */
1279         if (control) evas_textblock_cursor_word_start(en->cursor);
1280         if (en->select_allow)
1281           {
1282              if (shift) _sel_extend(en->cursor, rp->object, en);
1283              else _sel_clear(en->cursor, rp->object, en);
1284           }
1285         _edje_emit(ed, "entry,key,left", rp->part->name);
1286         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
1287         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1288      }
1289    else if (!strcmp(ev->keyname, "Right") ||
1290             (!strcmp(ev->keyname, "KP_Right") && !ev->string))
1291      {
1292         _compose_seq_reset(en);
1293         if (en->select_allow)
1294           {
1295              if (shift) _sel_start(en->cursor, rp->object, en);
1296              else _sel_clear(en->cursor, rp->object, en);
1297           }
1298         /* If control is pressed, go to the end of the word */
1299         if (control) evas_textblock_cursor_word_end(en->cursor);
1300         evas_textblock_cursor_char_next(en->cursor);
1301         if (en->select_allow)
1302           {
1303              if (shift) _sel_extend(en->cursor, rp->object, en);
1304              else _sel_clear(en->cursor, rp->object, en);
1305           }
1306         _edje_emit(ed, "entry,key,right", rp->part->name);
1307         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
1308         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1309      }
1310    else if (!strcmp(ev->keyname, "BackSpace"))
1311      {
1312         _compose_seq_reset(en);
1313         if (control && !en->have_selection)
1314           {
1315              // del to start of previous word
1316              _sel_start(en->cursor, rp->object, en);
1317
1318              evas_textblock_cursor_char_prev(en->cursor);
1319              evas_textblock_cursor_word_start(en->cursor);
1320
1321              _sel_preextend(en->cursor, rp->object, en);
1322
1323              _range_del_emit(ed, en->cursor, rp->object, en);
1324           }
1325         else if ((alt) && (shift))
1326           {
1327              // undo last action
1328           }
1329         else
1330           {
1331              if (en->have_selection)
1332                {
1333                   _range_del_emit(ed, en->cursor, rp->object, en);
1334                }
1335              else
1336                {
1337                   if (evas_textblock_cursor_char_prev(en->cursor))
1338                     {
1339                        _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_TRUE);
1340                     }
1341                }
1342           }
1343         _sel_clear(en->cursor, rp->object, en);
1344         _anchors_get(en->cursor, rp->object, en);
1345         _edje_emit(ed, "entry,key,backspace", rp->part->name);
1346         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1347      }
1348    else if (!strcmp(ev->keyname, "Delete") ||
1349             (!strcmp(ev->keyname, "KP_Delete") && !ev->string))
1350      {
1351         _compose_seq_reset(en);
1352         if (control)
1353           {
1354              // del to end of next word
1355              _sel_start(en->cursor, rp->object, en);
1356
1357              evas_textblock_cursor_word_end(en->cursor);
1358              evas_textblock_cursor_char_next(en->cursor);
1359
1360              _sel_extend(en->cursor, rp->object, en);
1361
1362              _range_del_emit(ed, en->cursor, rp->object, en);
1363           }
1364         else if (shift)
1365           {
1366              // cut
1367           }
1368         else
1369           {
1370              if (en->have_selection)
1371                {
1372                   _range_del_emit(ed, en->cursor, rp->object, en);
1373                }
1374              else
1375                {
1376                   _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_FALSE);
1377                }
1378           }
1379         _sel_clear(en->cursor, rp->object, en);
1380         _anchors_get(en->cursor, rp->object, en);
1381         _edje_emit(ed, "entry,key,delete", rp->part->name);
1382         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1383      }
1384    else if (!strcmp(ev->keyname, "Home") ||
1385             ((!strcmp(ev->keyname, "KP_Home")) && !ev->string))
1386      {
1387         _compose_seq_reset(en);
1388         if (en->select_allow)
1389           {
1390              if (shift) _sel_start(en->cursor, rp->object, en);
1391              else _sel_clear(en->cursor, rp->object, en);
1392           }
1393         if ((control) && (multiline))
1394           _curs_start(en->cursor, rp->object, en);
1395         else
1396           _curs_lin_start(en->cursor, rp->object, en);
1397         if (en->select_allow)
1398           {
1399              if (shift) _sel_extend(en->cursor, rp->object, en);
1400           }
1401         _edje_emit(ed, "entry,key,home", rp->part->name);
1402         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1403      }
1404    else if (!strcmp(ev->keyname, "End") ||
1405             ((!strcmp(ev->keyname, "KP_End")) && !ev->string))
1406      {
1407         _compose_seq_reset(en);
1408         if (en->select_allow)
1409           {
1410              if (shift) _sel_start(en->cursor, rp->object, en);
1411              else _sel_clear(en->cursor, rp->object, en);
1412           }
1413         if ((control) && (multiline))
1414           _curs_end(en->cursor, rp->object, en);
1415         else
1416           _curs_lin_end(en->cursor, rp->object, en);
1417         if (en->select_allow)
1418           {
1419              if (shift) _sel_extend(en->cursor, rp->object, en);
1420           }
1421         _edje_emit(ed, "entry,key,end", rp->part->name);
1422         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1423      }
1424    else if ((control) && (!shift) && (!strcmp(ev->keyname, "v")))
1425      {
1426         _compose_seq_reset(en);
1427         _edje_emit(ed, "entry,paste,request", rp->part->name);
1428         _edje_emit(ed, "entry,paste,request,3", rp->part->name);
1429         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1430      }
1431    else if ((control) && (!strcmp(ev->keyname, "a")))
1432      {
1433         _compose_seq_reset(en);
1434         if (shift)
1435           {
1436              _edje_emit(ed, "entry,selection,none,request", rp->part->name);
1437              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1438           }
1439         else
1440           {
1441              _edje_emit(ed, "entry,selection,all,request", rp->part->name);
1442              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1443           }
1444      }
1445    else if ((control) && (((!shift) && !strcmp(ev->keyname, "c")) || !strcmp(ev->keyname, "Insert")))
1446      {
1447         _compose_seq_reset(en);
1448         _edje_emit(ed, "entry,copy,notify", rp->part->name);
1449         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1450      }
1451    else if ((control) && (!shift) && ((!strcmp(ev->keyname, "x") || (!strcmp(ev->keyname, "m")))))
1452      {
1453         _compose_seq_reset(en);
1454         _edje_emit(ed, "entry,cut,notify", rp->part->name);
1455         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1456      }
1457    else if ((control) && (!strcmp(ev->keyname, "z")))
1458      {
1459         _compose_seq_reset(en);
1460         if (shift)
1461           {
1462              // redo
1463              _edje_emit(ed, "entry,redo,request", rp->part->name);
1464           }
1465         else
1466           {
1467              // undo
1468              _edje_emit(ed, "entry,undo,request", rp->part->name);
1469           }
1470         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1471      }
1472    else if ((control) && (!shift) && (!strcmp(ev->keyname, "y")))
1473      {
1474         _compose_seq_reset(en);
1475         // redo
1476         _edje_emit(ed, "entry,redo,request", rp->part->name);
1477         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1478      }
1479    else if ((control) && (!shift) && (!strcmp(ev->keyname, "w")))
1480      {
1481         _compose_seq_reset(en);
1482         _sel_clear(en->cursor, rp->object, en);
1483         // select current word?
1484         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1485      }
1486    else if (!strcmp(ev->keyname, "Tab"))
1487      {
1488         _compose_seq_reset(en);
1489         if (multiline)
1490           {
1491              if (shift)
1492                {
1493                   // remove a tab
1494                }
1495              else
1496                {
1497                   Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1498                   info->insert = EINA_TRUE;
1499                   info->change.insert.plain_length = 1;
1500
1501                   if (en->have_selection)
1502                     {
1503                        _range_del_emit(ed, en->cursor, rp->object, en);
1504                        info->merge = EINA_TRUE;
1505                     }
1506                   info->change.insert.pos =
1507                      evas_textblock_cursor_pos_get(en->cursor);
1508                   info->change.insert.content = eina_stringshare_add("<tab/>");
1509                   //yy
1510 //                  evas_textblock_cursor_format_prepend(en->cursor, "tab");
1511                   _text_filter_format_prepend(en, en->cursor, "tab");
1512                   _anchors_get(en->cursor, rp->object, en);
1513                   _edje_emit(ed, "entry,changed", rp->part->name);
1514                   _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1515                                   info, _free_entry_change_info);
1516                }
1517              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1518           }
1519         _edje_emit(ed, "entry,key,tab", rp->part->name);
1520      }
1521    else if ((!strcmp(ev->keyname, "ISO_Left_Tab")) && (multiline))
1522      {
1523         _compose_seq_reset(en);
1524         // remove a tab
1525         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1526      }
1527    else if (!strcmp(ev->keyname, "Prior") ||
1528             (!strcmp(ev->keyname, "KP_Prior") && !ev->string))
1529      {
1530         _compose_seq_reset(en);
1531         if (en->select_allow)
1532           {
1533              if (shift) _sel_start(en->cursor, rp->object, en);
1534              else _sel_clear(en->cursor, rp->object, en);
1535           }
1536         _curs_jump_line_by(en->cursor, rp->object, en, -10);
1537         if (en->select_allow)
1538           {
1539              if (shift) _sel_extend(en->cursor, rp->object, en);
1540              else _sel_clear(en->cursor, rp->object, en);
1541           }
1542         _edje_emit(ed, "entry,key,pgup", rp->part->name);
1543         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1544      }
1545    else if (!strcmp(ev->keyname, "Next") ||
1546             (!strcmp(ev->keyname, "KP_Next") && !ev->string))
1547      {
1548         _compose_seq_reset(en);
1549         if (en->select_allow)
1550           {
1551              if (shift) _sel_start(en->cursor, rp->object, en);
1552              else _sel_clear(en->cursor, rp->object, en);
1553           }
1554         _curs_jump_line_by(en->cursor, rp->object, en, 10);
1555         if (en->select_allow)
1556           {
1557              if (shift) _sel_extend(en->cursor, rp->object, en);
1558              else _sel_clear(en->cursor, rp->object, en);
1559           }
1560         _edje_emit(ed, "entry,key,pgdn", rp->part->name);
1561         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1562      }
1563    else if ((!strcmp(ev->keyname, "Return")) || (!strcmp(ev->keyname, "KP_Enter")))
1564      {
1565         _compose_seq_reset(en);
1566         if (multiline)
1567           {
1568              Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1569              info->insert = EINA_TRUE;
1570              info->change.insert.plain_length = 1;
1571              if (en->have_selection)
1572                {
1573                   _range_del_emit(ed, en->cursor, rp->object, en);
1574                   info->merge = EINA_TRUE;
1575                }
1576
1577              info->change.insert.pos =
1578                 evas_textblock_cursor_pos_get(en->cursor);
1579              if (shift ||
1580                  evas_object_textblock_legacy_newline_get(rp->object))
1581                {
1582                   //yy
1583 //                  evas_textblock_cursor_format_prepend(en->cursor, "br");
1584                   _text_filter_format_prepend(en, en->cursor, "br");
1585                   info->change.insert.content = eina_stringshare_add("<br/>");
1586                }
1587              else
1588                {
1589                   //yy
1590 //                  evas_textblock_cursor_format_prepend(en->cursor, "ps");
1591                   _text_filter_format_prepend(en, en->cursor, "ps");
1592                   info->change.insert.content = eina_stringshare_add("<ps/>");
1593                }
1594              _anchors_get(en->cursor, rp->object, en);
1595              _edje_emit(ed, "entry,changed", rp->part->name);
1596              _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1597                              info, _free_entry_change_info);
1598              _edje_emit(ed, "cursor,changed", rp->part->name);
1599              cursor_changed = EINA_TRUE;
1600              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1601           }
1602         _edje_emit(ed, "entry,key,enter", rp->part->name);
1603      }
1604    else
1605      {
1606         char *compres = NULL, *string = (char *)ev->string;
1607         Eina_Bool free_string = EINA_FALSE;
1608         Ecore_Compose_State state;
1609         
1610         if (!en->composing)
1611           {
1612              _compose_seq_reset(en);
1613              en->seq = eina_list_append(en->seq, eina_stringshare_add(ev->key));
1614              state = ecore_compose_get(en->seq, &compres);
1615              if (state == ECORE_COMPOSE_MIDDLE) en->composing = EINA_TRUE;
1616              else en->composing = EINA_FALSE;
1617              if (!en->composing) _compose_seq_reset(en);
1618              else goto end;
1619           }
1620         else
1621           {
1622              if (_is_modifier(ev->key)) goto end;
1623              en->seq = eina_list_append(en->seq, eina_stringshare_add(ev->key));
1624              state = ecore_compose_get(en->seq, &compres);
1625              if (state == ECORE_COMPOSE_NONE) _compose_seq_reset(en);
1626              else if (state == ECORE_COMPOSE_DONE)
1627                {
1628                   _compose_seq_reset(en);
1629                   if (compres)
1630                     {
1631                        string = compres;
1632                        free_string = EINA_TRUE;
1633                     }
1634                }
1635              else goto end;
1636           }
1637         if (string)
1638           {
1639              Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1640              info->insert = EINA_TRUE;
1641              info->change.insert.plain_length = 1;
1642              info->change.insert.content = eina_stringshare_add(string);
1643
1644              if (en->have_selection)
1645                {
1646                   _range_del_emit(ed, en->cursor, rp->object, en);
1647                   info->merge = EINA_TRUE;
1648                }
1649
1650              info->change.insert.pos =
1651                 evas_textblock_cursor_pos_get(en->cursor);
1652              // if PASSWORD_SHOW_LAST mode, appending text with password=off tag
1653              if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
1654                  _edje_password_show_last)
1655                {
1656                   _edje_entry_hide_visible_password(en->rp);
1657                   _text_filter_format_prepend(en, en->cursor, "+ password=off");
1658                   _text_filter_text_prepend(en, en->cursor, string);
1659                   _text_filter_format_prepend(en, en->cursor, "- password");
1660                   if (en->pw_timer)
1661                     {
1662                        ecore_timer_del(en->pw_timer);
1663                        en->pw_timer = NULL;
1664                     }
1665                   en->pw_timer = ecore_timer_add(TO_DOUBLE(_edje_password_show_last_timeout),
1666                                                  _password_timer_cb, en);
1667                }
1668              else
1669                _text_filter_text_prepend(en, en->cursor, string);
1670              _anchors_get(en->cursor, rp->object, en);
1671              _edje_emit(ed, "entry,changed", rp->part->name);
1672              _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1673                              info, _free_entry_change_info);
1674              _edje_emit(ed, "cursor,changed", rp->part->name);
1675              cursor_changed = EINA_TRUE;
1676              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1677           }
1678         if (free_string) free(string);
1679      }
1680 end:
1681    if (!cursor_changed && (old_cur_pos != evas_textblock_cursor_pos_get(en->cursor)))
1682      _edje_emit(ed, "cursor,changed", rp->part->name);
1683
1684    _edje_entry_imf_cursor_info_set(en);
1685    _edje_entry_real_part_configure(rp);
1686 }
1687
1688 static void
1689 _edje_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1690 {
1691    Edje *ed = data;
1692    Edje_Real_Part *rp = ed->focused_part;
1693    Entry *en;
1694
1695    if (!rp) return;
1696    en = rp->entry_data;
1697    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1698        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1699      return;
1700
1701 #ifdef HAVE_ECORE_IMF
1702    if (en->imf_context)
1703      {
1704         Evas_Event_Key_Up *ev = event_info;
1705         Ecore_IMF_Event_Key_Up ecore_ev;
1706
1707         ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev);
1708         if (ecore_imf_context_filter_event(en->imf_context,
1709                                            ECORE_IMF_EVENT_KEY_UP,
1710                                            (Ecore_IMF_Event *)&ecore_ev))
1711           return;
1712      }
1713 #else
1714    (void) event_info;
1715 #endif
1716 }
1717
1718 static void
1719 _edje_part_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1720 {
1721    Edje_Real_Part *rp = data;
1722    Entry *en;
1723    if (!rp) return;
1724    en = rp->entry_data;
1725    if (!en) return;
1726    _edje_entry_imf_cursor_info_set(en);
1727 }
1728
1729 static void
1730 _edje_part_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1731 {
1732    Evas_Coord cx, cy;
1733    Edje_Real_Part *rp = data;
1734    Evas_Event_Mouse_Down *ev = event_info;
1735    Entry *en;
1736    Evas_Coord x, y, w, h;
1737    //   Eina_Bool multiline;
1738    Evas_Textblock_Cursor *tc = NULL;
1739    Eina_Bool dosel = EINA_FALSE;
1740    Eina_Bool shift;
1741    if ((!rp) || (!ev)) return;
1742    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1743    en = rp->entry_data;
1744    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1745        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
1746      return;
1747    if ((ev->button != 1) && (ev->button != 2)) return;
1748
1749 #ifdef HAVE_ECORE_IMF
1750    if (en->imf_context)
1751      {
1752         Ecore_IMF_Event_Mouse_Down ecore_ev;
1753         ecore_imf_evas_event_mouse_down_wrap(ev, &ecore_ev);
1754         if (ecore_imf_context_filter_event(en->imf_context,
1755                                            ECORE_IMF_EVENT_MOUSE_DOWN,
1756                                            (Ecore_IMF_Event *)&ecore_ev))
1757           return;
1758      }
1759 #endif
1760
1761    _edje_entry_imf_context_reset(rp);
1762
1763    shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
1764    en->select_mod_start = EINA_FALSE;
1765    en->select_mod_end = EINA_FALSE;
1766    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
1767      dosel = EINA_TRUE;
1768    else if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
1769      {
1770         if (en->select_allow) dosel = EINA_TRUE;
1771      }
1772    if (ev->button == 2) dosel = EINA_FALSE;
1773    if (dosel)
1774      {
1775         evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1776         cx = ev->canvas.x - x;
1777         cy = ev->canvas.y - y;
1778         if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
1779           {
1780              if (shift)
1781                {
1782                   tc = evas_object_textblock_cursor_new(rp->object);
1783                   evas_textblock_cursor_copy(en->cursor, tc);
1784                   if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
1785                     evas_textblock_cursor_line_char_first(en->cursor);
1786                   else
1787                     evas_textblock_cursor_line_char_last(en->cursor);
1788                   _sel_extend(en->cursor, rp->object, en);
1789                }
1790              else
1791                {
1792                   en->have_selection = EINA_FALSE;
1793                   en->selecting = EINA_FALSE;
1794                   _sel_clear(en->cursor, rp->object, en);
1795                   tc = evas_object_textblock_cursor_new(rp->object);
1796                   evas_textblock_cursor_copy(en->cursor, tc);
1797                   evas_textblock_cursor_line_char_first(en->cursor);
1798                   _sel_start(en->cursor, rp->object, en);
1799                   evas_textblock_cursor_line_char_last(en->cursor);
1800                   _sel_extend(en->cursor, rp->object, en);
1801                }
1802              goto end;
1803           }
1804         else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1805           {
1806              if (shift)
1807                {
1808                   tc = evas_object_textblock_cursor_new(rp->object);
1809                   evas_textblock_cursor_copy(en->cursor, tc);
1810                   if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
1811                     evas_textblock_cursor_word_start(en->cursor);
1812                   else
1813                     {
1814                        evas_textblock_cursor_word_end(en->cursor);
1815                        evas_textblock_cursor_char_next(en->cursor);
1816                     }
1817                   _sel_extend(en->cursor, rp->object, en);
1818                }
1819              else
1820                {
1821                   en->have_selection = EINA_FALSE;
1822                   en->selecting = EINA_FALSE;
1823                   _sel_clear(en->cursor, rp->object, en);
1824                   tc = evas_object_textblock_cursor_new(rp->object);
1825                   evas_textblock_cursor_copy(en->cursor, tc);
1826                   evas_textblock_cursor_word_start(en->cursor);
1827                   _sel_start(en->cursor, rp->object, en);
1828                   evas_textblock_cursor_word_end(en->cursor);
1829                   evas_textblock_cursor_char_next(en->cursor);
1830                   _sel_extend(en->cursor, rp->object, en);
1831                }
1832              goto end;
1833           }
1834      }
1835    tc = evas_object_textblock_cursor_new(rp->object);
1836    evas_textblock_cursor_copy(en->cursor, tc);
1837    //   multiline = rp->part->multiline;
1838    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1839    cx = ev->canvas.x - x;
1840    cy = ev->canvas.y - y;
1841    if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
1842      {
1843         Evas_Coord lx, ly, lw, lh;
1844         int line;
1845
1846         line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
1847         if (line == -1)
1848           {
1849              if (rp->part->multiline)
1850                _curs_end(en->cursor, rp->object, en);
1851              else
1852                {
1853                   evas_textblock_cursor_paragraph_first(en->cursor);
1854                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1855                   if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
1856                     _curs_end(en->cursor, rp->object, en);
1857                }
1858           }
1859         else
1860           {
1861              int lnum;
1862
1863              lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1864              if (lnum < 0)
1865                {
1866                   _curs_lin_start(en->cursor, rp->object, en);
1867                }
1868              else
1869                {
1870                   if (cx <= lx)
1871                     _curs_lin_start(en->cursor, rp->object, en);
1872                   else
1873                     _curs_lin_end(en->cursor, rp->object, en);
1874                }
1875           }
1876      }
1877    if (dosel)
1878      {
1879         if ((en->have_selection) &&
1880             (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT))
1881           {
1882              if (shift)
1883                _sel_extend(en->cursor, rp->object, en);
1884              else
1885                {
1886                   Eina_List *first, *last;
1887                   FLOAT_T sc;
1888
1889                   first = en->sel;
1890                   last = eina_list_last(en->sel);
1891                   if (first && last)
1892                     {
1893                        Evas_Textblock_Rectangle *r1, *r2;
1894                        Evas_Coord d, d1, d2;
1895                        
1896                        r1 = first->data;
1897                        r2 = last->data;
1898                        d = r1->x - cx;
1899                        d1 = d * d;
1900                        d = (r1->y + (r1->h / 2)) - cy;
1901                        d1 += d * d;
1902                        d = r2->x + r2->w - 1 - cx;
1903                        d2 = d * d;
1904                        d = (r2->y + (r2->h / 2)) - cy;
1905                        d2 += d * d;
1906                        sc = rp->edje->scale;
1907                        if (sc == ZERO) sc = _edje_scale;
1908                        d = (Evas_Coord)MUL(FROM_INT(20), sc); // FIXME: maxing number!
1909                        d = d * d;
1910                        if (d1 < d2)
1911                          {
1912                             if (d1 <= d)
1913                               {
1914                                  en->select_mod_start = EINA_TRUE;
1915                                  en->selecting = EINA_TRUE;
1916                               }
1917                          }
1918                        else
1919                          {
1920                             if (d2 <= d)
1921                               {
1922                                  en->select_mod_end = EINA_TRUE;
1923                                  en->selecting = EINA_TRUE;
1924                               }
1925                          }
1926                     }
1927                }
1928           }
1929         else
1930           {
1931              if ((en->have_selection) && (shift))
1932                _sel_extend(en->cursor, rp->object, en);
1933              else
1934                {
1935                   en->selecting = EINA_TRUE;
1936                   _sel_clear(en->cursor, rp->object, en);
1937                   if (en->select_allow)
1938                     {
1939                        _sel_start(en->cursor, rp->object, en);
1940                     }
1941                }
1942           }
1943      }
1944  end:
1945    if (evas_textblock_cursor_compare(tc, en->cursor))
1946      {
1947         _edje_emit(rp->edje, "cursor,changed", rp->part->name);
1948         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
1949      }
1950    evas_textblock_cursor_free(tc);
1951
1952    _edje_entry_imf_cursor_info_set(en);
1953
1954    _edje_entry_real_part_configure(rp);
1955    if (ev->button == 2)
1956      {
1957         _edje_emit(rp->edje, "entry,paste,request", rp->part->name);
1958         _edje_emit(rp->edje, "entry,paste,request,1", rp->part->name);
1959      }
1960 }
1961
1962 static void
1963 _edje_part_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1964 {
1965    Evas_Coord cx, cy;
1966    Edje_Real_Part *rp = data;
1967    Evas_Event_Mouse_Up *ev = event_info;
1968    Entry *en;
1969    Evas_Coord x, y, w, h;
1970    Evas_Textblock_Cursor *tc;
1971    if ((!ev) || (ev->button != 1)) return;
1972    if (!rp) return;
1973    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1974    if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) return;
1975    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) return;
1976    en = rp->entry_data;
1977    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1978        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
1979      return;
1980
1981 #ifdef HAVE_ECORE_IMF
1982    if (en->imf_context)
1983      {
1984         Ecore_IMF_Event_Mouse_Up ecore_ev;
1985         ecore_imf_evas_event_mouse_up_wrap(ev, &ecore_ev);
1986         if (ecore_imf_context_filter_event(en->imf_context,
1987                                            ECORE_IMF_EVENT_MOUSE_UP,
1988                                            (Ecore_IMF_Event *)&ecore_ev))
1989           return;
1990      }
1991 #endif
1992
1993    _edje_entry_imf_context_reset(rp);
1994
1995    tc = evas_object_textblock_cursor_new(rp->object);
1996    evas_textblock_cursor_copy(en->cursor, tc);
1997    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1998    cx = ev->canvas.x - x;
1999    cy = ev->canvas.y - y;
2000    if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2001      {
2002         Evas_Coord lx, ly, lw, lh;
2003         int line;
2004
2005         line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
2006         if (line == -1)
2007           {
2008              if (rp->part->multiline)
2009                _curs_end(en->cursor, rp->object, en);
2010              else
2011                {
2012                   evas_textblock_cursor_paragraph_first(en->cursor);
2013                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2014                   if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2015                     _curs_end(en->cursor, rp->object, en);
2016                }
2017           }
2018         else
2019           {
2020              int lnum;
2021
2022              lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2023              if (lnum < 0)
2024                {
2025                   _curs_lin_start(en->cursor, rp->object, en);
2026                }
2027              else
2028                {
2029                   if (cx <= lx)
2030                     _curs_lin_start(en->cursor, rp->object, en);
2031                   else
2032                     _curs_lin_end(en->cursor, rp->object, en);
2033                }
2034           }
2035      }
2036    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2037      {
2038         if (en->select_allow)
2039           {
2040              if (en->had_sel)
2041                {
2042                   if (en->select_mod_end)
2043                     _sel_extend(en->cursor, rp->object, en);
2044                   else if (en->select_mod_start)
2045                     _sel_preextend(en->cursor, rp->object, en);
2046                }
2047              else
2048                _sel_extend(en->cursor, rp->object, en);
2049              //evas_textblock_cursor_copy(en->cursor, en->sel_end);
2050           }
2051      }
2052    else
2053      evas_textblock_cursor_copy(en->cursor, en->sel_end);
2054    if (en->selecting)
2055      {
2056         if (en->have_selection)
2057           en->had_sel = EINA_TRUE;
2058         en->selecting = EINA_FALSE;
2059      }
2060    if (evas_textblock_cursor_compare(tc, en->cursor))
2061      {
2062         _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2063         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
2064      }
2065    evas_textblock_cursor_free(tc);
2066
2067    _edje_entry_imf_cursor_info_set(en);
2068    _edje_entry_real_part_configure(rp);
2069 }
2070
2071 static void
2072 _edje_part_mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2073 {
2074    Evas_Coord cx, cy;
2075    Edje_Real_Part *rp = data;
2076    Evas_Event_Mouse_Move *ev = event_info;
2077    Entry *en;
2078    Evas_Coord x, y, w, h;
2079    Evas_Textblock_Cursor *tc;
2080    if (!rp || (!ev)) return;
2081    en = rp->entry_data;
2082    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2083        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2084      return;
2085
2086 #ifdef HAVE_ECORE_IMF
2087    if (en->imf_context)
2088      {
2089         Ecore_IMF_Event_Mouse_Move ecore_ev;
2090         ecore_imf_evas_event_mouse_move_wrap(ev, &ecore_ev);
2091         if (ecore_imf_context_filter_event(en->imf_context,
2092                                            ECORE_IMF_EVENT_MOUSE_MOVE,
2093                                            (Ecore_IMF_Event *)&ecore_ev))
2094           return;
2095      }
2096 #endif
2097
2098    if (en->selecting)
2099      {
2100         tc = evas_object_textblock_cursor_new(rp->object);
2101         evas_textblock_cursor_copy(en->cursor, tc);
2102         evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2103         cx = ev->cur.canvas.x - x;
2104         cy = ev->cur.canvas.y - y;
2105         if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2106           {
2107              Evas_Coord lx, ly, lw, lh;
2108
2109              if (evas_textblock_cursor_line_coord_set(en->cursor, cy) < 0)
2110                {
2111                   if (rp->part->multiline)
2112                     _curs_end(en->cursor, rp->object, en);
2113                   else
2114                     {
2115                        evas_textblock_cursor_paragraph_first(en->cursor);
2116                        evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2117                        if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2118                          _curs_end(en->cursor, rp->object, en);
2119                     }
2120                }
2121              else
2122                {
2123                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2124                   if (cx <= lx)
2125                     _curs_lin_start(en->cursor, rp->object, en);
2126                   else
2127                     _curs_lin_end(en->cursor, rp->object, en);
2128                }
2129           }
2130         if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2131           {
2132              if (en->select_allow)
2133                {
2134                   if (en->had_sel)
2135                     {
2136                        if (en->select_mod_end)
2137                          _sel_extend(en->cursor, rp->object, en);
2138                        else if (en->select_mod_start)
2139                          _sel_preextend(en->cursor, rp->object, en);
2140                     }
2141                   else
2142                     _sel_extend(en->cursor, rp->object, en);
2143                }
2144           }
2145         else
2146           {
2147              _sel_extend(en->cursor, rp->object, en);
2148           }
2149         if (en->select_allow)
2150           {
2151              if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) != 0)
2152                _sel_enable(en->cursor, rp->object, en);
2153              if (en->have_selection)
2154                _sel_update(en->cursor, rp->object, en);
2155           }
2156         if (evas_textblock_cursor_compare(tc, en->cursor))
2157           {
2158              _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2159              _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
2160           }
2161         evas_textblock_cursor_free(tc);
2162
2163         _edje_entry_imf_context_reset(rp);
2164         _edje_entry_imf_cursor_info_set(en);
2165
2166         _edje_entry_real_part_configure(rp);
2167      }
2168 }
2169
2170 static void
2171 _evas_focus_in_cb(void *data, Evas *e, __UNUSED__ void *event_info)
2172 {
2173    Edje *ed = (Edje *)data;
2174    if (!ed) return;
2175
2176    if (evas_focus_get(e) == ed->obj)
2177      {
2178         _edje_focus_in_cb(data, NULL, NULL, NULL);
2179      }
2180 }
2181
2182 static void
2183 _evas_focus_out_cb(void *data, Evas *e, __UNUSED__ void *event_info)
2184 {
2185    Edje *ed = (Edje *)data;
2186    if (!ed) return;
2187
2188    if (evas_focus_get(e) == ed->obj)
2189      {
2190         _edje_focus_out_cb(data, NULL, NULL, NULL);
2191      }
2192 }
2193
2194 /***************************************************************/
2195 void
2196 _edje_entry_init(Edje *ed)
2197 {
2198    if (!ed->has_entries)
2199      return;
2200    if (ed->entries_inited)
2201      return;
2202    ed->entries_inited = EINA_TRUE;
2203
2204    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb, ed);
2205    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb, ed);
2206    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb, ed);
2207    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb, ed);
2208    evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed);
2209    evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed);
2210 }
2211
2212 void
2213 _edje_entry_shutdown(Edje *ed)
2214 {
2215    if ((!ed) || (!ed->has_entries))
2216      return;
2217    if (!ed->entries_inited)
2218      return;
2219    ed->entries_inited = EINA_FALSE;
2220
2221    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb);
2222    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb);
2223    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb);
2224    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb);
2225    if (evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed) != ed)
2226      ERR("could not unregister EVAS_CALLBACK_FOCUS_IN");
2227    if (evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed) != ed)
2228      ERR("could not unregister EVAS_CALLBACK_FOCUS_OUT");
2229 }
2230
2231 void
2232 _edje_entry_real_part_init(Edje_Real_Part *rp)
2233 {
2234    Entry *en;
2235 #ifdef HAVE_ECORE_IMF
2236    const char *ctx_id;
2237    const Ecore_IMF_Context_Info *ctx_info;
2238 #endif
2239
2240    en = calloc(1, sizeof(Entry));
2241    if (!en) return;
2242    rp->entry_data = en;
2243    en->rp = rp;
2244
2245    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOVE, _edje_part_move_cb, rp);
2246
2247    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_DOWN, _edje_part_mouse_down_cb, rp);
2248    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_UP, _edje_part_mouse_up_cb, rp);
2249    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_MOVE, _edje_part_mouse_move_cb, rp);
2250
2251    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
2252      en->select_allow = EINA_TRUE;
2253
2254    if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2255      {
2256         Edje_Part_Description_Text *txt;
2257
2258         txt = (Edje_Part_Description_Text *)rp->chosen_description;
2259
2260         en->select_allow = EINA_FALSE;
2261         if (txt && edje_string_get(&txt->text.repch))
2262           evas_object_textblock_replace_char_set(rp->object, edje_string_get(&txt->text.repch));
2263         else
2264           evas_object_textblock_replace_char_set(rp->object, "*");
2265      }
2266
2267    en->cursor_bg = edje_object_add(rp->edje->base.evas);
2268    edje_object_file_set(en->cursor_bg, rp->edje->path, rp->part->source3);
2269    evas_object_smart_member_add(en->cursor_bg, rp->edje->obj);
2270    evas_object_stack_below(en->cursor_bg, rp->object);
2271    evas_object_clip_set(en->cursor_bg, evas_object_clip_get(rp->object));
2272    evas_object_pass_events_set(en->cursor_bg, EINA_TRUE);
2273    _edje_subobj_register(en->rp->edje, en->cursor_bg);
2274
2275    en->cursor_fg = edje_object_add(rp->edje->base.evas);
2276    edje_object_file_set(en->cursor_fg, rp->edje->path, rp->part->source4);
2277    evas_object_smart_member_add(en->cursor_fg, rp->edje->obj);
2278    evas_object_stack_above(en->cursor_fg, rp->object);
2279    evas_object_clip_set(en->cursor_fg, evas_object_clip_get(rp->object));
2280    evas_object_pass_events_set(en->cursor_fg, EINA_TRUE);
2281    _edje_subobj_register(en->rp->edje, en->cursor_fg);
2282
2283    evas_object_textblock_legacy_newline_set(rp->object, EINA_TRUE);
2284
2285    if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2286      {
2287         evas_object_show(en->cursor_bg);
2288         evas_object_show(en->cursor_fg);
2289         en->input_panel_enable = EINA_TRUE;
2290
2291 #ifdef HAVE_ECORE_IMF
2292         ecore_imf_init();
2293
2294         edje_object_signal_callback_add(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb, rp);
2295         edje_object_signal_callback_add(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb, rp);
2296
2297         ctx_id = ecore_imf_context_default_id_get();
2298         if (ctx_id)
2299           {
2300              ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
2301              if (!ctx_info->canvas_type ||
2302                  strcmp(ctx_info->canvas_type, "evas") == 0)
2303                {
2304                   en->imf_context = ecore_imf_context_add(ctx_id);
2305                }
2306              else
2307                {
2308                   ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
2309                   if (ctx_id)
2310                     {
2311                        en->imf_context = ecore_imf_context_add(ctx_id);
2312                     }
2313                }
2314           }
2315         else
2316           en->imf_context = NULL;
2317
2318         if (!en->imf_context) goto done;
2319
2320         ecore_imf_context_client_window_set
2321            (en->imf_context,
2322                (void *)ecore_evas_window_get
2323                (ecore_evas_ecore_evas_get(rp->edje->base.evas)));
2324         ecore_imf_context_client_canvas_set(en->imf_context, rp->edje->base.evas);
2325
2326         ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context,
2327                                                             _edje_entry_imf_retrieve_surrounding_cb, rp->edje);
2328         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb, rp->edje);
2329         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb, rp->edje);
2330         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb, rp->edje);
2331         ecore_imf_context_input_mode_set(en->imf_context,
2332                                          rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD ?
2333                                          ECORE_IMF_INPUT_MODE_INVISIBLE : ECORE_IMF_INPUT_MODE_FULL);
2334
2335         if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2336           ecore_imf_context_input_panel_language_set(en->imf_context, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
2337 #endif
2338      }
2339 #ifdef HAVE_ECORE_IMF
2340 done:
2341 #endif
2342    en->cursor = (Evas_Textblock_Cursor *)evas_object_textblock_cursor_get(rp->object);
2343 }
2344
2345 void
2346 _edje_entry_real_part_shutdown(Edje_Real_Part *rp)
2347 {
2348    Entry *en = rp->entry_data;
2349    if (!en) return;
2350    rp->entry_data = NULL;
2351    _sel_clear(en->cursor, rp->object, en);
2352    _anchors_clear(en->cursor, rp->object, en);
2353 #ifdef HAVE_ECORE_IMF
2354    _preedit_clear(en);
2355 #endif
2356    evas_object_del(en->cursor_bg);
2357    evas_object_del(en->cursor_fg);
2358
2359    if (en->pw_timer)
2360      {
2361         ecore_timer_del(en->pw_timer);
2362         en->pw_timer = NULL;
2363      }
2364
2365 #ifdef HAVE_ECORE_IMF
2366    if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2367      {
2368         if (en->imf_context)
2369           {
2370              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb);
2371              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb);
2372              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb);
2373
2374              ecore_imf_context_del(en->imf_context);
2375              en->imf_context = NULL;
2376           }
2377
2378         edje_object_signal_callback_del(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb);
2379         edje_object_signal_callback_del(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb);
2380         ecore_imf_shutdown();
2381      }
2382 #endif
2383    _compose_seq_reset(en);
2384    
2385    free(en);
2386 }
2387
2388 void
2389 _edje_entry_real_part_configure(Edje_Real_Part *rp)
2390 {
2391    Evas_Coord x, y, w, h, xx, yy, ww, hh;
2392    Entry *en = rp->entry_data;
2393    Evas_Textblock_Cursor_Type cur_type;
2394    if (!en) return;
2395    switch (rp->part->cursor_mode)
2396      {
2397       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2398          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2399          break;
2400       case EDJE_ENTRY_CURSOR_MODE_UNDER:
2401          /* no break for a resaon */
2402       default:
2403          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2404      }
2405
2406    _sel_update(en->cursor, rp->object, en);
2407    _anchors_update(en->cursor, rp->object, en);
2408    x = y = w = h = -1;
2409    xx = yy = ww = hh = -1;
2410    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2411    evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
2412    if (ww < 1) ww = 1;
2413    if (hh < 1) hh = 1;
2414    if (en->cursor_bg)
2415      {
2416         evas_object_move(en->cursor_bg, x + xx, y + yy);
2417         evas_object_resize(en->cursor_bg, ww, hh);
2418      }
2419    if (en->cursor_fg)
2420      {
2421         evas_object_move(en->cursor_fg, x + xx, y + yy);
2422         evas_object_resize(en->cursor_fg, ww, hh);
2423      }
2424 }
2425
2426 const char *
2427 _edje_entry_selection_get(Edje_Real_Part *rp)
2428 {
2429    Entry *en = rp->entry_data;
2430    if (!en) return NULL;
2431    // get selection - convert to markup
2432    if ((!en->selection) && (en->have_selection))
2433      en->selection = evas_textblock_cursor_range_text_get
2434         (en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
2435    return en->selection;
2436 }
2437
2438 const char *
2439 _edje_entry_text_get(Edje_Real_Part *rp)
2440 {
2441    Entry *en = rp->entry_data;
2442    if (!en) return NULL;
2443    // get text - convert to markup
2444    return evas_object_textblock_text_markup_get(rp->object);
2445 }
2446
2447 void
2448 _edje_entry_text_markup_set(Edje_Real_Part *rp, const char *text)
2449 {
2450    Entry *en = rp->entry_data;
2451    if (!en) return;
2452    _edje_entry_imf_context_reset(rp);
2453    // set text as markup
2454    _sel_clear(en->cursor, rp->object, en);
2455    evas_object_textblock_text_markup_set(rp->object, text);
2456    _edje_entry_set_cursor_start(rp);
2457
2458    _anchors_get(en->cursor, rp->object, en);
2459    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2460    _edje_entry_imf_cursor_info_set(en);
2461
2462    _edje_entry_real_part_configure(rp);
2463 #if 0
2464    /* Don't emit cursor changed cause it didn't. It's just init to 0. */
2465    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2466 #endif
2467 }
2468
2469 void
2470 _edje_entry_text_markup_append(Edje_Real_Part *rp, const char *text)
2471 {
2472    Entry *en = rp->entry_data;
2473    Evas_Textblock_Cursor *end_cur;
2474    if (!en) return;
2475    end_cur = evas_object_textblock_cursor_new(rp->object);
2476    evas_textblock_cursor_paragraph_last(end_cur);
2477
2478    _text_filter_markup_prepend(en, end_cur, text);
2479    evas_textblock_cursor_free(end_cur);
2480
2481    /* We are updating according to the real cursor on purpose */
2482    _anchors_get(en->cursor, rp->object, en);
2483    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2484
2485    _edje_entry_real_part_configure(rp);
2486 }
2487
2488 void
2489 _edje_entry_text_markup_insert(Edje_Real_Part *rp, const char *text)
2490 {
2491    Entry *en = rp->entry_data;
2492    if (!en) return;
2493    _edje_entry_imf_context_reset(rp);
2494
2495    // prepend markup @ cursor pos
2496    if (en->have_selection)
2497      _range_del(en->cursor, rp->object, en);
2498    //xx
2499 //   evas_object_textblock_text_markup_prepend(en->cursor, text);
2500    _text_filter_markup_prepend(en, en->cursor, text);
2501    _anchors_get(en->cursor, rp->object, en);
2502    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2503    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2504
2505    _edje_entry_imf_cursor_info_set(en);
2506    _edje_entry_real_part_configure(rp);
2507 }
2508
2509 void
2510 _edje_entry_set_cursor_start(Edje_Real_Part *rp)
2511 {
2512    Entry *en = rp->entry_data;
2513    if (!en) return;
2514    _curs_start(en->cursor, rp->object, en);
2515
2516    _edje_entry_imf_cursor_info_set(en);
2517 }
2518
2519 void
2520 _edje_entry_set_cursor_end(Edje_Real_Part *rp)
2521 {
2522    Entry *en = rp->entry_data;
2523    if (!en) return;
2524    _curs_end(en->cursor, rp->object, en);
2525
2526    _edje_entry_imf_cursor_info_set(en);
2527 }
2528
2529 void
2530 _edje_entry_select_none(Edje_Real_Part *rp)
2531 {
2532    Entry *en = rp->entry_data;
2533    if (!en) return;
2534    _sel_clear(en->cursor, rp->object, en);
2535 }
2536
2537 void
2538 _edje_entry_select_all(Edje_Real_Part *rp)
2539 {
2540    Entry *en = rp->entry_data;
2541    if (!en) return;
2542
2543    _edje_entry_imf_context_reset(rp);
2544
2545    _sel_clear(en->cursor, rp->object, en);
2546    _curs_start(en->cursor, rp->object, en);
2547    _sel_enable(en->cursor, rp->object, en);
2548    _sel_start(en->cursor, rp->object, en);
2549    _curs_end(en->cursor, rp->object, en);
2550    _sel_extend(en->cursor, rp->object, en);
2551
2552    _edje_entry_imf_cursor_info_set(en);
2553    _edje_entry_real_part_configure(rp);
2554 }
2555
2556 void
2557 _edje_entry_select_begin(Edje_Real_Part *rp)
2558 {
2559    Entry *en = rp->entry_data;
2560    if (!en) return;
2561
2562    _edje_entry_imf_context_reset(rp);
2563
2564    _sel_clear(en->cursor, rp->object, en);
2565    _sel_enable(en->cursor, rp->object, en);
2566    _sel_start(en->cursor, rp->object, en);
2567    _sel_extend(en->cursor, rp->object, en);
2568
2569    _edje_entry_imf_cursor_info_set(en);
2570
2571    _edje_entry_real_part_configure(rp);
2572 }
2573
2574 void
2575 _edje_entry_select_extend(Edje_Real_Part *rp)
2576 {
2577    Entry *en = rp->entry_data;
2578    if (!en) return;
2579    _edje_entry_imf_context_reset(rp);
2580    _sel_extend(en->cursor, rp->object, en);
2581
2582    _edje_entry_imf_cursor_info_set(en);
2583
2584    _edje_entry_real_part_configure(rp);
2585 }
2586
2587 const Eina_List *
2588 _edje_entry_anchor_geometry_get(Edje_Real_Part *rp, const char *anchor)
2589 {
2590    Entry *en = rp->entry_data;
2591    Eina_List *l;
2592    Anchor *an;
2593
2594    if (!en) return NULL;
2595    EINA_LIST_FOREACH(en->anchors, l, an)
2596      {
2597         if (an->item) continue;
2598         if (!strcmp(anchor, an->name))
2599           return an->sel;
2600      }
2601    return NULL;
2602 }
2603
2604 const Eina_List *
2605 _edje_entry_anchors_list(Edje_Real_Part *rp)
2606 {
2607    Entry *en = rp->entry_data;
2608    Eina_List *l, *anchors = NULL;
2609    Anchor *an;
2610
2611    if (!en) return NULL;
2612    if (!en->anchorlist)
2613      {
2614         EINA_LIST_FOREACH(en->anchors, l, an)
2615           {
2616              const char *n = an->name;
2617              if (an->item) continue;
2618              if (!n) n = "";
2619              anchors = eina_list_append(anchors, strdup(n));
2620           }
2621         en->anchorlist = anchors;
2622      }
2623    return en->anchorlist;
2624 }
2625
2626 Eina_Bool
2627 _edje_entry_item_geometry_get(Edje_Real_Part *rp, const char *item, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
2628 {
2629    Entry *en = rp->entry_data;
2630    Eina_List *l;
2631    Anchor *an;
2632
2633    if (!en) return EINA_FALSE;
2634    EINA_LIST_FOREACH(en->anchors, l, an)
2635      {
2636         if (an->item) continue;
2637         if (!strcmp(item, an->name))
2638           {
2639              evas_textblock_cursor_format_item_geometry_get(an->start, cx, cy, cw, ch);
2640              return EINA_TRUE;
2641           }
2642      }
2643    return EINA_FALSE;
2644 }
2645
2646 const Eina_List *
2647 _edje_entry_items_list(Edje_Real_Part *rp)
2648 {
2649    Entry *en = rp->entry_data;
2650    Eina_List *l, *items = NULL;
2651    Anchor *an;
2652
2653    if (!en) return NULL;
2654    if (!en->itemlist)
2655      {
2656         EINA_LIST_FOREACH(en->anchors, l, an)
2657           {
2658              const char *n = an->name;
2659              if (an->item) continue;
2660              if (!n) n = "";
2661              items = eina_list_append(items, strdup(n));
2662           }
2663         en->itemlist = items;
2664      }
2665    return en->itemlist;
2666 }
2667
2668 void
2669 _edje_entry_cursor_geometry_get(Edje_Real_Part *rp, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
2670 {
2671    Evas_Coord x, y, w, h, xx, yy, ww, hh;
2672    Entry *en = rp->entry_data;
2673    Evas_Textblock_Cursor_Type cur_type;
2674    if (!en) return;
2675    switch (rp->part->cursor_mode)
2676      {
2677       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2678          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2679          break;
2680       case EDJE_ENTRY_CURSOR_MODE_UNDER:
2681          /* no break for a resaon */
2682       default:
2683          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2684      }
2685
2686    x = y = w = h = -1;
2687    xx = yy = ww = hh = -1;
2688    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2689    evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
2690    if (ww < 1) ww = 1;
2691    if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
2692      edje_object_size_min_restricted_calc(en->cursor_fg, &ww, NULL, ww, 0);
2693    if (hh < 1) hh = 1;
2694    if (cx) *cx = x + xx;
2695    if (cy) *cy = y + yy;
2696    if (cw) *cw = ww;
2697    if (ch) *ch = hh;
2698 }
2699
2700 void
2701 _edje_entry_user_insert(Edje_Real_Part *rp, const char *text)
2702 {
2703    Entry *en = rp->entry_data;
2704    Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
2705    info->insert = EINA_TRUE;
2706    info->change.insert.plain_length = 1;
2707    info->change.insert.content = eina_stringshare_add(text);
2708      {
2709         char *tmp;
2710         tmp = evas_textblock_text_markup_to_utf8(rp->object,
2711                                                  info->change.insert.content);
2712         info->change.insert.plain_length = eina_unicode_utf8_get_len(tmp);
2713         free(tmp);
2714      }
2715
2716    if (en->have_selection)
2717      {
2718         _range_del_emit(rp->edje, en->cursor, rp->object, en);
2719         info->merge = EINA_TRUE;
2720      }
2721    info->change.insert.pos = evas_textblock_cursor_pos_get(en->cursor);
2722    _text_filter_markup_prepend(en, en->cursor, text);
2723    _anchors_get(en->cursor, rp->object, en);
2724    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2725    _edje_emit_full(rp->edje, "entry,changed,user", rp->part->name,
2726                    info, _free_entry_change_info);
2727    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2728
2729    _edje_entry_imf_cursor_info_set(en);
2730    _edje_entry_real_part_configure(rp);
2731 }
2732
2733 void
2734 _edje_entry_select_allow_set(Edje_Real_Part *rp, Eina_Bool allow)
2735 {
2736    Entry *en = rp->entry_data;
2737    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
2738      return;
2739    en->select_allow = allow;
2740 }
2741
2742 Eina_Bool
2743 _edje_entry_select_allow_get(const Edje_Real_Part *rp)
2744 {
2745    const Entry *en = rp->entry_data;
2746    return en->select_allow;
2747 }
2748
2749 void
2750 _edje_entry_select_abort(Edje_Real_Part *rp)
2751 {
2752    Entry *en = rp->entry_data;
2753    if (en->selecting)
2754      {
2755         en->selecting = EINA_FALSE;
2756
2757         _edje_entry_imf_context_reset(rp);
2758         _edje_entry_imf_cursor_info_set(en);
2759         _edje_entry_real_part_configure(rp);
2760      }
2761 }
2762
2763 void *
2764 _edje_entry_imf_context_get(Edje_Real_Part *rp)
2765 {
2766    Entry *en = rp->entry_data;
2767    if (!en) return NULL;
2768
2769 #ifdef HAVE_ECORE_IMF
2770    return en->imf_context;
2771 #else
2772    return NULL;
2773 #endif
2774 }
2775
2776 void
2777 _edje_entry_autocapital_type_set(Edje_Real_Part *rp, Edje_Text_Autocapital_Type autocapital_type)
2778 {
2779    Entry *en = rp->entry_data;
2780    if (!en) return;
2781
2782    if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2783      autocapital_type = EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2784
2785 #ifdef HAVE_ECORE_IMF
2786    if (en->imf_context)
2787      ecore_imf_context_autocapital_type_set(en->imf_context, autocapital_type);
2788 #endif
2789 }
2790
2791 Edje_Text_Autocapital_Type
2792 _edje_entry_autocapital_type_get(Edje_Real_Part *rp)
2793 {
2794    Entry *en = rp->entry_data;
2795    if (!en) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2796
2797 #ifdef HAVE_ECORE_IMF
2798    if (en->imf_context)
2799      return ecore_imf_context_autocapital_type_get(en->imf_context);
2800 #endif
2801
2802    return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2803 }
2804
2805 void
2806 _edje_entry_prediction_allow_set(Edje_Real_Part *rp, Eina_Bool prediction)
2807 {
2808    Entry *en = rp->entry_data;
2809
2810    if (!en) return;
2811    en->prediction_allow = prediction;
2812 #ifdef HAVE_ECORE_IMF
2813    if (en->imf_context)
2814      ecore_imf_context_prediction_allow_set(en->imf_context, prediction);
2815 #endif
2816 }
2817
2818 Eina_Bool
2819 _edje_entry_prediction_allow_get(Edje_Real_Part *rp)
2820 {
2821    Entry *en = rp->entry_data;
2822    if (!en) return EINA_FALSE;
2823
2824    return en->prediction_allow;
2825 }
2826
2827 void
2828 _edje_entry_input_panel_enabled_set(Edje_Real_Part *rp, Eina_Bool enabled)
2829 {
2830    Entry *en = rp->entry_data;
2831
2832    if (!en) return;
2833    en->input_panel_enable = enabled;
2834 #ifdef HAVE_ECORE_IMF
2835    if (en->imf_context)
2836      ecore_imf_context_input_panel_enabled_set(en->imf_context, enabled);
2837 #endif
2838 }
2839
2840 Eina_Bool
2841 _edje_entry_input_panel_enabled_get(Edje_Real_Part *rp)
2842 {
2843    Entry *en = rp->entry_data;
2844    if (!en) return EINA_FALSE;
2845
2846    return en->input_panel_enable;
2847 }
2848
2849 void
2850 _edje_entry_input_panel_show(Edje_Real_Part *rp)
2851 {
2852    Entry *en = rp->entry_data;
2853
2854    if (!en) return;
2855 #ifdef HAVE_ECORE_IMF
2856    if (en->imf_context)
2857      ecore_imf_context_input_panel_show(en->imf_context);
2858 #endif
2859 }
2860
2861 void
2862 _edje_entry_input_panel_hide(Edje_Real_Part *rp)
2863 {
2864    Entry *en = rp->entry_data;
2865
2866    if (!en) return;
2867 #ifdef HAVE_ECORE_IMF
2868    if (en->imf_context)
2869      ecore_imf_context_input_panel_hide(en->imf_context);
2870 #endif
2871 }
2872
2873 void
2874 _edje_entry_input_panel_language_set(Edje_Real_Part *rp, Edje_Input_Panel_Lang lang)
2875 {
2876    Entry *en = rp->entry_data;
2877
2878    if (!en) return;
2879    en->input_panel_lang = lang;
2880 #ifdef HAVE_ECORE_IMF
2881    if (en->imf_context)
2882      ecore_imf_context_input_panel_language_set(en->imf_context, lang);
2883 #endif
2884 }
2885
2886 Edje_Input_Panel_Lang
2887 _edje_entry_input_panel_language_get(Edje_Real_Part *rp)
2888 {
2889    Entry *en = rp->entry_data;
2890    if (!en) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
2891
2892    return en->input_panel_lang;
2893 }
2894
2895 #ifdef HAVE_ECORE_IMF
2896 void
2897 _edje_entry_input_panel_imdata_set(Edje_Real_Part *rp, const void *data, int len)
2898 #else
2899 void
2900 _edje_entry_input_panel_imdata_set(Edje_Real_Part *rp, const void *data __UNUSED__, int len __UNUSED__)
2901 #endif
2902 {
2903    Entry *en = rp->entry_data;
2904    if (!en) return;
2905 #ifdef HAVE_ECORE_IMF
2906    if (en->imf_context)
2907      ecore_imf_context_input_panel_imdata_set(en->imf_context, data, len);
2908 #endif
2909 }
2910
2911 #ifdef HAVE_ECORE_IMF
2912 void
2913 _edje_entry_input_panel_imdata_get(Edje_Real_Part *rp, void *data, int *len)
2914 #else
2915 void
2916 _edje_entry_input_panel_imdata_get(Edje_Real_Part *rp, void *data __UNUSED__, int *len __UNUSED__)
2917 #endif
2918 {
2919    Entry *en = rp->entry_data;
2920    if (!en) return;
2921 #ifdef HAVE_ECORE_IMF
2922    if (en->imf_context)
2923      ecore_imf_context_input_panel_imdata_get(en->imf_context, data, len);
2924 #endif
2925 }
2926
2927 #ifdef HAVE_ECORE_IMF
2928 void
2929 _edje_entry_input_panel_return_key_type_set(Edje_Real_Part *rp, Edje_Input_Panel_Return_Key_Type return_key_type)
2930 #else
2931 void
2932 _edje_entry_input_panel_return_key_type_set(Edje_Real_Part *rp, Edje_Input_Panel_Return_Key_Type return_key_type __UNUSED__)
2933 #endif
2934 {
2935    Entry *en = rp->entry_data;
2936    if (!en) return;
2937 #ifdef HAVE_ECORE_IMF
2938    if (en->imf_context)
2939      ecore_imf_context_input_panel_return_key_type_set(en->imf_context, return_key_type);
2940 #endif
2941 }
2942
2943 Edje_Input_Panel_Return_Key_Type
2944 _edje_entry_input_panel_return_key_type_get(Edje_Real_Part *rp)
2945 {
2946    Entry *en = rp->entry_data;
2947    if (!en) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2948 #ifdef HAVE_ECORE_IMF
2949    if (en->imf_context)
2950      return ecore_imf_context_input_panel_return_key_type_get(en->imf_context);
2951 #endif
2952    return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2953 }
2954
2955 #ifdef HAVE_ECORE_IMF
2956 void
2957 _edje_entry_input_panel_return_key_disabled_set(Edje_Real_Part *rp, Eina_Bool disabled)
2958 #else
2959 void
2960 _edje_entry_input_panel_return_key_disabled_set(Edje_Real_Part *rp, Eina_Bool disabled __UNUSED__)
2961 #endif
2962 {
2963    Entry *en = rp->entry_data;
2964    if (!en) return;
2965 #ifdef HAVE_ECORE_IMF
2966    if (en->imf_context)
2967      ecore_imf_context_input_panel_return_key_disabled_set(en->imf_context, disabled);
2968 #endif
2969 }
2970
2971 Eina_Bool
2972 _edje_entry_input_panel_return_key_disabled_get(Edje_Real_Part *rp)
2973 {
2974    Entry *en = rp->entry_data;
2975    if (!en) return EINA_FALSE;
2976 #ifdef HAVE_ECORE_IMF
2977    if (en->imf_context)
2978      return ecore_imf_context_input_panel_return_key_disabled_get(en->imf_context);
2979 #endif
2980    return EINA_FALSE;
2981 }
2982
2983 static Evas_Textblock_Cursor *
2984 _cursor_get(Edje_Real_Part *rp, Edje_Cursor cur)
2985 {
2986    Entry *en = rp->entry_data;
2987    if (!en) return NULL;
2988
2989    switch (cur)
2990      {
2991       case EDJE_CURSOR_MAIN:
2992          return en->cursor;
2993       case EDJE_CURSOR_SELECTION_BEGIN:
2994          return en->sel_start;
2995       case EDJE_CURSOR_SELECTION_END:
2996          return en->sel_end;
2997       case EDJE_CURSOR_PREEDIT_START:
2998          if (!en->preedit_start)
2999            en->preedit_start = evas_object_textblock_cursor_new(rp->object);
3000          return en->preedit_start;
3001       case EDJE_CURSOR_PREEDIT_END:
3002          if (!en->preedit_end)
3003            en->preedit_end = evas_object_textblock_cursor_new(rp->object);
3004          return en->preedit_end;
3005       case EDJE_CURSOR_USER:
3006          if (!en->cursor_user)
3007            en->cursor_user = evas_object_textblock_cursor_new(rp->object);
3008          return en->cursor_user;
3009       case EDJE_CURSOR_USER_EXTRA:
3010          if (!en->cursor_user_extra)
3011            en->cursor_user_extra = evas_object_textblock_cursor_new(rp->object);
3012          return en->cursor_user_extra;
3013       default:
3014          break;
3015      }
3016    return NULL;
3017 }
3018
3019 Eina_Bool
3020 _edje_entry_cursor_next(Edje_Real_Part *rp, Edje_Cursor cur)
3021 {
3022    Entry *en = rp->entry_data;
3023    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3024    if (!c) return EINA_FALSE;
3025
3026    _edje_entry_imf_context_reset(rp);
3027
3028    if (!evas_textblock_cursor_char_next(c))
3029      {
3030         return EINA_FALSE;
3031      }
3032    _sel_update(c, rp->object, rp->entry_data);
3033    _edje_entry_imf_cursor_info_set(en);
3034
3035    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3036    _edje_entry_real_part_configure(rp);
3037    return EINA_TRUE;
3038 }
3039
3040 Eina_Bool
3041 _edje_entry_cursor_prev(Edje_Real_Part *rp, Edje_Cursor cur)
3042 {
3043    Entry *en = rp->entry_data;
3044    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3045    if (!c) return EINA_FALSE;
3046
3047    _edje_entry_imf_context_reset(rp);
3048
3049    if (!evas_textblock_cursor_char_prev(c))
3050      {
3051         if (evas_textblock_cursor_paragraph_prev(c)) goto ok;
3052         else return EINA_FALSE;
3053      }
3054 ok:
3055    _sel_update(c, rp->object, rp->entry_data);
3056
3057    _edje_entry_imf_cursor_info_set(en);
3058
3059    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3060    _edje_entry_real_part_configure(rp);
3061    return EINA_TRUE;
3062 }
3063
3064 Eina_Bool
3065 _edje_entry_cursor_up(Edje_Real_Part *rp, Edje_Cursor cur)
3066 {
3067    Entry *en = rp->entry_data;
3068    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3069    Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
3070    int ln;
3071    if (!c) return EINA_FALSE;
3072
3073    _edje_entry_imf_context_reset(rp);
3074
3075    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
3076    ln--;
3077    if (ln < 0) return EINA_FALSE;
3078    if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
3079                                                        &lx, &ly, &lw, &lh))
3080      return EINA_FALSE;
3081    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
3082    if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
3083      {
3084         if (cx < (lx + (lw / 2)))
3085           evas_textblock_cursor_line_char_last(c);
3086         else
3087           evas_textblock_cursor_line_char_last(c);
3088      }
3089    _sel_update(c, rp->object, rp->entry_data);
3090
3091    _edje_entry_imf_cursor_info_set(en);
3092
3093    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3094    _edje_entry_real_part_configure(rp);
3095    return EINA_TRUE;
3096 }
3097
3098 Eina_Bool
3099 _edje_entry_cursor_down(Edje_Real_Part *rp, Edje_Cursor cur)
3100 {
3101    Entry *en = rp->entry_data;
3102    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3103    Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
3104    int ln;
3105    if (!c) return EINA_FALSE;
3106
3107    _edje_entry_imf_context_reset(rp);
3108
3109    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
3110    ln++;
3111    if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
3112                                                        &lx, &ly, &lw, &lh))
3113      return EINA_FALSE;
3114    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
3115    if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
3116      {
3117         if (cx < (lx + (lw / 2)))
3118           evas_textblock_cursor_line_char_last(c);
3119         else
3120           evas_textblock_cursor_line_char_last(c);
3121      }
3122    _sel_update(c, rp->object, rp->entry_data);
3123
3124    _edje_entry_imf_cursor_info_set(en);
3125    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3126    _edje_entry_real_part_configure(rp);
3127    return EINA_TRUE;
3128 }
3129
3130 void
3131 _edje_entry_cursor_begin(Edje_Real_Part *rp, Edje_Cursor cur)
3132 {
3133    Entry *en = rp->entry_data;
3134    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3135    if (!c) return;
3136
3137    _edje_entry_imf_context_reset(rp);
3138
3139    evas_textblock_cursor_paragraph_first(c);
3140    _sel_update(c, rp->object, rp->entry_data);
3141
3142    _edje_entry_imf_cursor_info_set(en);
3143    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3144    _edje_entry_real_part_configure(rp);
3145 }
3146
3147 void
3148 _edje_entry_cursor_end(Edje_Real_Part *rp, Edje_Cursor cur)
3149 {
3150    Entry *en = rp->entry_data;
3151    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3152    if (!c) return;
3153
3154    _edje_entry_imf_context_reset(rp);
3155
3156    _curs_end(c, rp->object, rp->entry_data);
3157    _sel_update(c, rp->object, rp->entry_data);
3158
3159    _edje_entry_imf_cursor_info_set(en);
3160
3161    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3162    _edje_entry_real_part_configure(rp);
3163 }
3164
3165 void
3166 _edje_entry_cursor_copy(Edje_Real_Part *rp, Edje_Cursor cur, Edje_Cursor dst)
3167 {
3168    Entry *en = rp->entry_data;
3169    Evas_Textblock_Cursor *c;
3170    Evas_Textblock_Cursor *d;
3171
3172    c = _cursor_get(rp, cur);
3173    if (!c) return;
3174    d = _cursor_get(rp, dst);
3175    if (!d) return;
3176    evas_textblock_cursor_copy(c, d);
3177    _sel_update(c, rp->object, rp->entry_data);
3178
3179    _edje_entry_imf_context_reset(rp);
3180    _edje_entry_imf_cursor_info_set(en);
3181    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3182    _edje_entry_real_part_configure(rp);
3183 }
3184
3185 void
3186 _edje_entry_cursor_line_begin(Edje_Real_Part *rp, Edje_Cursor cur)
3187 {
3188    Entry *en = rp->entry_data;
3189    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3190    if (!c) return;
3191    _edje_entry_imf_context_reset(rp);
3192
3193    evas_textblock_cursor_line_char_first(c);
3194    _sel_update(c, rp->object, rp->entry_data);
3195
3196    _edje_entry_imf_cursor_info_set(en);
3197
3198    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3199    _edje_entry_real_part_configure(rp);
3200 }
3201
3202 void
3203 _edje_entry_cursor_line_end(Edje_Real_Part *rp, Edje_Cursor cur)
3204 {
3205    Entry *en = rp->entry_data;
3206    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3207    if (!c) return;
3208    _edje_entry_imf_context_reset(rp);
3209    evas_textblock_cursor_line_char_last(c);
3210    _sel_update(c, rp->object, rp->entry_data);
3211
3212    _edje_entry_imf_cursor_info_set(en);
3213    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3214    _edje_entry_real_part_configure(rp);
3215 }
3216
3217 Eina_Bool
3218 _edje_entry_cursor_coord_set(Edje_Real_Part *rp, Edje_Cursor cur,
3219                              Evas_Coord x, Evas_Coord y)
3220 {
3221    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3222    if (!c) return EINA_FALSE;
3223    return evas_textblock_cursor_char_coord_set(c, x, y);
3224 }
3225
3226 Eina_Bool
3227 _edje_entry_cursor_is_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
3228 {
3229    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3230    if (!c) return EINA_FALSE;
3231    if (evas_textblock_cursor_is_format(c)) return EINA_TRUE;
3232    return EINA_FALSE;
3233 }
3234
3235 Eina_Bool
3236 _edje_entry_cursor_is_visible_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
3237 {
3238    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3239    if (!c) return EINA_FALSE;
3240    return evas_textblock_cursor_format_is_visible_get(c);
3241 }
3242
3243 char *
3244 _edje_entry_cursor_content_get(Edje_Real_Part *rp, Edje_Cursor cur)
3245 {
3246    static char *s = NULL;
3247    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3248
3249    if (!c) return NULL;
3250    if (s)
3251      {
3252         free(s);
3253         s = NULL;
3254      }
3255
3256    s = evas_textblock_cursor_content_get(c);
3257    return s;
3258 }
3259
3260 void
3261 _edje_entry_cursor_pos_set(Edje_Real_Part *rp, Edje_Cursor cur, int pos)
3262 {
3263    Entry *en = rp->entry_data;
3264    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3265    if (!c) return;
3266    /* Abort if cursor position didn't really change */
3267    if (evas_textblock_cursor_pos_get(c) == pos)
3268      return;
3269
3270    _edje_entry_imf_context_reset(rp);
3271    evas_textblock_cursor_pos_set(c, pos);
3272    _sel_update(c, rp->object, rp->entry_data);
3273
3274    _edje_entry_imf_cursor_info_set(en);
3275    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3276    _edje_entry_real_part_configure(rp);
3277 }
3278
3279 int
3280 _edje_entry_cursor_pos_get(Edje_Real_Part *rp, Edje_Cursor cur)
3281 {
3282    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3283    if (!c) return 0;
3284    return evas_textblock_cursor_pos_get(c);
3285 }
3286
3287 void
3288 _edje_entry_input_panel_layout_set(Edje_Real_Part *rp, Edje_Input_Panel_Layout layout)
3289 {
3290    Entry *en = rp->entry_data;
3291    if (!en) return;
3292 #ifdef HAVE_ECORE_IMF
3293    if (en->imf_context)
3294      ecore_imf_context_input_panel_layout_set(en->imf_context, layout);
3295 #else
3296    (void) layout;
3297 #endif
3298 }
3299
3300 Edje_Input_Panel_Layout
3301 _edje_entry_input_panel_layout_get(Edje_Real_Part *rp)
3302 {
3303    Entry *en = rp->entry_data;
3304    if (!en) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
3305 #ifdef HAVE_ECORE_IMF
3306    if (en->imf_context)
3307      return ecore_imf_context_input_panel_layout_get(en->imf_context);
3308 #endif
3309
3310    return EDJE_INPUT_PANEL_LAYOUT_INVALID;
3311 }
3312
3313 void
3314 _edje_entry_imf_context_reset(Edje_Real_Part *rp)
3315 {
3316    Entry *en = rp->entry_data;
3317    if (!en) return;
3318 #ifdef HAVE_ECORE_IMF
3319    if (en->imf_context)
3320      ecore_imf_context_reset(en->imf_context);
3321 #endif
3322 }
3323
3324 static void
3325 _edje_entry_imf_cursor_info_set(Entry *en)
3326 {
3327 #ifdef HAVE_ECORE_IMF
3328    Evas_Coord cx, cy, cw, ch;
3329    if (!en || !en->rp || !en->imf_context) return;
3330
3331    _edje_entry_cursor_geometry_get(en->rp, &cx, &cy, &cw, &ch);
3332
3333    ecore_imf_context_cursor_position_set(en->imf_context,
3334                                          evas_textblock_cursor_pos_get(en->cursor));
3335    ecore_imf_context_cursor_location_set(en->imf_context, cx, cy, cw, ch);
3336 #else
3337    (void) en;
3338 #endif
3339 }
3340
3341 #ifdef HAVE_ECORE_IMF
3342 static Eina_Bool
3343 _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, char **text, int *cursor_pos)
3344 {
3345    Edje *ed = data;
3346    Edje_Real_Part *rp = ed->focused_part;
3347    Entry *en;
3348    const char *str;
3349
3350    if (!rp) return EINA_FALSE;
3351    en = rp->entry_data;
3352    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3353        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3354      return EINA_FALSE;
3355
3356    if (text)
3357      {
3358         str = _edje_entry_text_get(rp);
3359         *text = str ? strdup(str) : strdup("");
3360      }
3361
3362    if (cursor_pos)
3363      *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
3364
3365    return EINA_TRUE;
3366 }
3367
3368 static void
3369 _edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, void *event_info)
3370 {
3371    Edje *ed = data;
3372    Edje_Real_Part *rp = ed->focused_part;
3373    Entry *en;
3374    char *commit_str = event_info;
3375    int start_pos;
3376
3377    if ((!rp)) return;
3378
3379    en = rp->entry_data;
3380    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3381        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3382      return;
3383
3384    if (en->have_selection)
3385      {
3386         if (strcmp(commit_str, ""))
3387           {
3388              /* delete selected characters */
3389              _range_del_emit(ed, en->cursor, rp->object, en);
3390              _sel_clear(en->cursor, rp->object, en);
3391           }
3392      }
3393
3394    start_pos = evas_textblock_cursor_pos_get(en->cursor);
3395
3396 #ifdef HAVE_ECORE_IMF
3397    /* delete preedit characters */
3398    _preedit_del(en);
3399    _preedit_clear(en);
3400 #endif
3401
3402    if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3403        _edje_password_show_last)
3404      _edje_entry_hide_visible_password(en->rp);
3405    if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3406        _edje_password_show_last && (!en->preedit_start))
3407      {
3408         _text_filter_format_prepend(en, en->cursor, "+ password=off");
3409         _text_filter_text_prepend(en, en->cursor, commit_str);
3410         _text_filter_format_prepend(en, en->cursor, "- password");
3411
3412         if (en->pw_timer)
3413           {
3414              ecore_timer_del(en->pw_timer);
3415              en->pw_timer = NULL;
3416           }
3417         en->pw_timer = ecore_timer_add(TO_DOUBLE(_edje_password_show_last_timeout),
3418                                        _password_timer_cb, en);
3419      }
3420    else
3421      _text_filter_text_prepend(en, en->cursor, commit_str);
3422
3423
3424    _edje_entry_imf_cursor_info_set(en);
3425    _anchors_get(en->cursor, rp->object, en);
3426    _edje_emit(rp->edje, "entry,changed", rp->part->name);
3427
3428      {
3429         Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
3430         info->insert = EINA_TRUE;
3431         info->change.insert.pos = start_pos;
3432         info->change.insert.content = eina_stringshare_add(commit_str);
3433         info->change.insert.plain_length =
3434            eina_unicode_utf8_get_len(info->change.insert.content);
3435         _edje_emit_full(ed, "entry,changed,user", rp->part->name,
3436                         info, _free_entry_change_info);
3437         _edje_emit(ed, "cursor,changed", rp->part->name);
3438      }
3439
3440    _edje_entry_imf_cursor_info_set(en);
3441    _edje_entry_real_part_configure(rp);
3442 }
3443
3444 static void
3445 _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, void *event_info __UNUSED__)
3446 {
3447    Edje *ed = data;
3448    Edje_Real_Part *rp = ed->focused_part;
3449    Entry *en;
3450    int cursor_pos;
3451    int preedit_start_pos, preedit_end_pos;
3452    char *preedit_string;
3453    int i;
3454    Eina_Bool preedit_end_state = EINA_FALSE;
3455    Eina_List *attrs = NULL, *l = NULL;
3456    Ecore_IMF_Preedit_Attr *attr;
3457    Eina_Strbuf *buf;
3458
3459    if ((!rp)) return;
3460
3461    en = rp->entry_data;
3462    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3463        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3464      return;
3465
3466    if (!en->imf_context) return;
3467
3468    ecore_imf_context_preedit_string_with_attributes_get(en->imf_context,
3469                                                         &preedit_string,
3470                                                         &attrs, &cursor_pos);
3471    if (!preedit_string) return;
3472
3473    if (!strcmp(preedit_string, ""))
3474      preedit_end_state = EINA_TRUE;
3475
3476    if (en->have_selection && !preedit_end_state)
3477      {
3478         /* delete selected characters */
3479         _range_del_emit(ed, en->cursor, rp->object, en);
3480      }
3481
3482    /* delete preedit characters */
3483    _preedit_del(en);
3484
3485    preedit_start_pos = evas_textblock_cursor_pos_get(en->cursor);
3486
3487    /* insert preedit character(s) */
3488    if (strlen(preedit_string) > 0)
3489      {
3490         buf = eina_strbuf_new();
3491         if (attrs)
3492           {
3493              EINA_LIST_FOREACH(attrs, l, attr)
3494                {
3495                   if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB1)
3496                     {
3497                        eina_strbuf_append(buf, "<preedit>");
3498                        eina_strbuf_append_n(buf, preedit_string + attr->start_index,
3499                                             attr->end_index - attr->start_index);
3500                        eina_strbuf_append(buf, "</preedit>");
3501                     }
3502
3503                   else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB2 ||
3504                            attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3)
3505                     {
3506                        eina_strbuf_append(buf, "<preedit_sel>");
3507                        eina_strbuf_append_n(buf, preedit_string + attr->start_index,
3508                                             attr->end_index - attr->start_index);
3509                        eina_strbuf_append(buf, "</preedit_sel>");
3510                     }
3511                }
3512           }
3513         else
3514           {
3515              eina_strbuf_append(buf, preedit_string);
3516           }
3517         if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3518             _edje_password_show_last)
3519           {
3520              _edje_entry_hide_visible_password(en->rp);
3521              _text_filter_format_prepend(en, en->cursor, "+ password=off");
3522              _text_filter_markup_prepend(en, en->cursor, eina_strbuf_string_get(buf));
3523              _text_filter_format_prepend(en, en->cursor, "- password");
3524              if (en->pw_timer)
3525                {
3526                   ecore_timer_del(en->pw_timer);
3527                   en->pw_timer = NULL;
3528                }
3529              en->pw_timer = ecore_timer_add(TO_DOUBLE(_edje_password_show_last_timeout),
3530                                             _password_timer_cb, en);
3531           }
3532         else
3533           {
3534              _text_filter_markup_prepend(en, en->cursor, eina_strbuf_string_get(buf));
3535           }
3536         eina_strbuf_free(buf);
3537      }
3538
3539    if (!preedit_end_state)
3540      {
3541         /* set preedit start cursor */
3542         if (!en->preedit_start)
3543           en->preedit_start = evas_object_textblock_cursor_new(rp->object);
3544         evas_textblock_cursor_copy(en->cursor, en->preedit_start);
3545
3546         /* set preedit end cursor */
3547         if (!en->preedit_end)
3548           en->preedit_end = evas_object_textblock_cursor_new(rp->object);
3549         evas_textblock_cursor_copy(en->cursor, en->preedit_end);
3550
3551         preedit_end_pos = evas_textblock_cursor_pos_get(en->cursor);
3552
3553         for (i = 0; i < (preedit_end_pos - preedit_start_pos); i++)
3554           {
3555              evas_textblock_cursor_char_prev(en->preedit_start);
3556           }
3557
3558         en->have_preedit = EINA_TRUE;
3559
3560         /* set cursor position */
3561         evas_textblock_cursor_pos_set(en->cursor, preedit_start_pos + cursor_pos);
3562      }
3563
3564    _edje_entry_imf_cursor_info_set(en);
3565    _anchors_get(en->cursor, rp->object, en);
3566    _edje_emit(rp->edje, "preedit,changed", rp->part->name);
3567    _edje_emit(ed, "cursor,changed", rp->part->name);
3568
3569    /* delete attribute list */
3570    if (attrs)
3571      {
3572         EINA_LIST_FREE(attrs, attr) free(attr);
3573      }
3574
3575    free(preedit_string);
3576 }
3577
3578 static void
3579 _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, void *event_info)
3580 {
3581    Edje *ed = data;
3582    Edje_Real_Part *rp = ed->focused_part;
3583    Entry *en;
3584    Ecore_IMF_Event_Delete_Surrounding *ev = event_info;
3585    Evas_Textblock_Cursor *del_start, *del_end;
3586    int cursor_pos;
3587
3588    if ((!rp) || (!ev)) return;
3589    en = rp->entry_data;
3590    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3591        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3592      return;
3593
3594    cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
3595
3596    del_start = evas_object_textblock_cursor_new(en->rp->object);
3597    evas_textblock_cursor_pos_set(del_start, cursor_pos + ev->offset);
3598
3599    del_end = evas_object_textblock_cursor_new(en->rp->object);
3600    evas_textblock_cursor_pos_set(del_end, cursor_pos + ev->offset + ev->n_chars);
3601
3602    evas_textblock_cursor_range_delete(del_start, del_end);
3603
3604    evas_textblock_cursor_free(del_start);
3605    evas_textblock_cursor_free(del_end);
3606 }
3607 #endif
3608
3609 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/