Imported Upstream version 1.7.1
[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) 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    shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
1762    en->select_mod_start = EINA_FALSE;
1763    en->select_mod_end = EINA_FALSE;
1764    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
1765      dosel = EINA_TRUE;
1766    else if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
1767      {
1768         if (en->select_allow) dosel = EINA_TRUE;
1769      }
1770    if (ev->button == 2) dosel = EINA_FALSE;
1771    if (dosel)
1772      {
1773         evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1774         cx = ev->canvas.x - x;
1775         cy = ev->canvas.y - y;
1776         if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
1777           {
1778              if (shift)
1779                {
1780                   tc = evas_object_textblock_cursor_new(rp->object);
1781                   evas_textblock_cursor_copy(en->cursor, tc);
1782                   if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
1783                     evas_textblock_cursor_line_char_first(en->cursor);
1784                   else
1785                     evas_textblock_cursor_line_char_last(en->cursor);
1786                   _sel_extend(en->cursor, rp->object, en);
1787                }
1788              else
1789                {
1790                   en->have_selection = EINA_FALSE;
1791                   en->selecting = EINA_FALSE;
1792                   _sel_clear(en->cursor, rp->object, en);
1793                   tc = evas_object_textblock_cursor_new(rp->object);
1794                   evas_textblock_cursor_copy(en->cursor, tc);
1795                   evas_textblock_cursor_line_char_first(en->cursor);
1796                   _sel_start(en->cursor, rp->object, en);
1797                   evas_textblock_cursor_line_char_last(en->cursor);
1798                   _sel_extend(en->cursor, rp->object, en);
1799                }
1800              goto end;
1801           }
1802         else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1803           {
1804              if (shift)
1805                {
1806                   tc = evas_object_textblock_cursor_new(rp->object);
1807                   evas_textblock_cursor_copy(en->cursor, tc);
1808                   if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
1809                     evas_textblock_cursor_word_start(en->cursor);
1810                   else
1811                     {
1812                        evas_textblock_cursor_word_end(en->cursor);
1813                        evas_textblock_cursor_char_next(en->cursor);
1814                     }
1815                   _sel_extend(en->cursor, rp->object, en);
1816                }
1817              else
1818                {
1819                   en->have_selection = EINA_FALSE;
1820                   en->selecting = EINA_FALSE;
1821                   _sel_clear(en->cursor, rp->object, en);
1822                   tc = evas_object_textblock_cursor_new(rp->object);
1823                   evas_textblock_cursor_copy(en->cursor, tc);
1824                   evas_textblock_cursor_word_start(en->cursor);
1825                   _sel_start(en->cursor, rp->object, en);
1826                   evas_textblock_cursor_word_end(en->cursor);
1827                   evas_textblock_cursor_char_next(en->cursor);
1828                   _sel_extend(en->cursor, rp->object, en);
1829                }
1830              goto end;
1831           }
1832      }
1833    tc = evas_object_textblock_cursor_new(rp->object);
1834    evas_textblock_cursor_copy(en->cursor, tc);
1835    //   multiline = rp->part->multiline;
1836    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1837    cx = ev->canvas.x - x;
1838    cy = ev->canvas.y - y;
1839    if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
1840      {
1841         Evas_Coord lx, ly, lw, lh;
1842         int line;
1843
1844         line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
1845         if (line == -1)
1846           {
1847              if (rp->part->multiline)
1848                _curs_end(en->cursor, rp->object, en);
1849              else
1850                {
1851                   evas_textblock_cursor_paragraph_first(en->cursor);
1852                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1853                   if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
1854                     _curs_end(en->cursor, rp->object, en);
1855                }
1856           }
1857         else
1858           {
1859              int lnum;
1860
1861              lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1862              if (lnum < 0)
1863                {
1864                   _curs_lin_start(en->cursor, rp->object, en);
1865                }
1866              else
1867                {
1868                   if (cx <= lx)
1869                     _curs_lin_start(en->cursor, rp->object, en);
1870                   else
1871                     _curs_lin_end(en->cursor, rp->object, en);
1872                }
1873           }
1874      }
1875    if (dosel)
1876      {
1877         if ((en->have_selection) &&
1878             (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT))
1879           {
1880              if (shift)
1881                _sel_extend(en->cursor, rp->object, en);
1882              else
1883                {
1884                   Eina_List *first, *last;
1885                   FLOAT_T sc;
1886
1887                   first = en->sel;
1888                   last = eina_list_last(en->sel);
1889                   if (first && last)
1890                     {
1891                        Evas_Textblock_Rectangle *r1, *r2;
1892                        Evas_Coord d, d1, d2;
1893                        
1894                        r1 = first->data;
1895                        r2 = last->data;
1896                        d = r1->x - cx;
1897                        d1 = d * d;
1898                        d = (r1->y + (r1->h / 2)) - cy;
1899                        d1 += d * d;
1900                        d = r2->x + r2->w - 1 - cx;
1901                        d2 = d * d;
1902                        d = (r2->y + (r2->h / 2)) - cy;
1903                        d2 += d * d;
1904                        sc = rp->edje->scale;
1905                        if (sc == ZERO) sc = _edje_scale;
1906                        d = (Evas_Coord)MUL(FROM_INT(20), sc); // FIXME: maxing number!
1907                        d = d * d;
1908                        if (d1 < d2)
1909                          {
1910                             if (d1 <= d)
1911                               {
1912                                  en->select_mod_start = EINA_TRUE;
1913                                  en->selecting = EINA_TRUE;
1914                               }
1915                          }
1916                        else
1917                          {
1918                             if (d2 <= d)
1919                               {
1920                                  en->select_mod_end = EINA_TRUE;
1921                                  en->selecting = EINA_TRUE;
1922                               }
1923                          }
1924                     }
1925                }
1926           }
1927         else
1928           {
1929              if ((en->have_selection) && (shift))
1930                _sel_extend(en->cursor, rp->object, en);
1931              else
1932                {
1933                   en->selecting = EINA_TRUE;
1934                   _sel_clear(en->cursor, rp->object, en);
1935                   if (en->select_allow)
1936                     {
1937                        _sel_start(en->cursor, rp->object, en);
1938                     }
1939                }
1940           }
1941      }
1942  end:
1943    if (evas_textblock_cursor_compare(tc, en->cursor))
1944      {
1945         _edje_emit(rp->edje, "cursor,changed", rp->part->name);
1946         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
1947      }
1948    evas_textblock_cursor_free(tc);
1949
1950    _edje_entry_imf_cursor_info_set(en);
1951
1952    _edje_entry_real_part_configure(rp);
1953    if (ev->button == 2)
1954      {
1955         _edje_emit(rp->edje, "entry,paste,request", rp->part->name);
1956         _edje_emit(rp->edje, "entry,paste,request,1", rp->part->name);
1957      }
1958 }
1959
1960 static void
1961 _edje_part_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1962 {
1963    Evas_Coord cx, cy;
1964    Edje_Real_Part *rp = data;
1965    Evas_Event_Mouse_Up *ev = event_info;
1966    Entry *en;
1967    Evas_Coord x, y, w, h;
1968    Evas_Textblock_Cursor *tc;
1969    if (ev->button != 1) return;
1970    if (!rp) return;
1971    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1972    if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) return;
1973    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) return;
1974    en = rp->entry_data;
1975    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1976        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
1977      return;
1978
1979 #ifdef HAVE_ECORE_IMF
1980    if (en->imf_context)
1981      {
1982         Ecore_IMF_Event_Mouse_Up ecore_ev;
1983         ecore_imf_evas_event_mouse_up_wrap(ev, &ecore_ev);
1984         if (ecore_imf_context_filter_event(en->imf_context,
1985                                            ECORE_IMF_EVENT_MOUSE_UP,
1986                                            (Ecore_IMF_Event *)&ecore_ev))
1987           return;
1988      }
1989 #endif
1990
1991    _edje_entry_imf_context_reset(rp);
1992
1993    tc = evas_object_textblock_cursor_new(rp->object);
1994    evas_textblock_cursor_copy(en->cursor, tc);
1995    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1996    cx = ev->canvas.x - x;
1997    cy = ev->canvas.y - y;
1998    if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
1999      {
2000         Evas_Coord lx, ly, lw, lh;
2001         int line;
2002
2003         line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
2004         if (line == -1)
2005           {
2006              if (rp->part->multiline)
2007                _curs_end(en->cursor, rp->object, en);
2008              else
2009                {
2010                   evas_textblock_cursor_paragraph_first(en->cursor);
2011                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2012                   if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2013                     _curs_end(en->cursor, rp->object, en);
2014                }
2015           }
2016         else
2017           {
2018              int lnum;
2019
2020              lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2021              if (lnum < 0)
2022                {
2023                   _curs_lin_start(en->cursor, rp->object, en);
2024                }
2025              else
2026                {
2027                   if (cx <= lx)
2028                     _curs_lin_start(en->cursor, rp->object, en);
2029                   else
2030                     _curs_lin_end(en->cursor, rp->object, en);
2031                }
2032           }
2033      }
2034    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2035      {
2036         if (en->select_allow)
2037           {
2038              if (en->had_sel)
2039                {
2040                   if (en->select_mod_end)
2041                     _sel_extend(en->cursor, rp->object, en);
2042                   else if (en->select_mod_start)
2043                     _sel_preextend(en->cursor, rp->object, en);
2044                }
2045              else
2046                _sel_extend(en->cursor, rp->object, en);
2047              //evas_textblock_cursor_copy(en->cursor, en->sel_end);
2048           }
2049      }
2050    else
2051      evas_textblock_cursor_copy(en->cursor, en->sel_end);
2052    if (en->selecting)
2053      {
2054         if (en->have_selection)
2055           en->had_sel = EINA_TRUE;
2056         en->selecting = EINA_FALSE;
2057      }
2058    if (evas_textblock_cursor_compare(tc, en->cursor))
2059      {
2060         _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2061         _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
2062      }
2063    evas_textblock_cursor_free(tc);
2064
2065    _edje_entry_imf_cursor_info_set(en);
2066    _edje_entry_real_part_configure(rp);
2067 }
2068
2069 static void
2070 _edje_part_mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2071 {
2072    Evas_Coord cx, cy;
2073    Edje_Real_Part *rp = data;
2074    Evas_Event_Mouse_Move *ev = event_info;
2075    Entry *en;
2076    Evas_Coord x, y, w, h;
2077    Evas_Textblock_Cursor *tc;
2078    if (!rp) return;
2079    en = rp->entry_data;
2080    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2081        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2082      return;
2083
2084 #ifdef HAVE_ECORE_IMF
2085    if (en->imf_context)
2086      {
2087         Ecore_IMF_Event_Mouse_Move ecore_ev;
2088         ecore_imf_evas_event_mouse_move_wrap(ev, &ecore_ev);
2089         if (ecore_imf_context_filter_event(en->imf_context,
2090                                            ECORE_IMF_EVENT_MOUSE_MOVE,
2091                                            (Ecore_IMF_Event *)&ecore_ev))
2092           return;
2093      }
2094 #endif
2095
2096    if (en->selecting)
2097      {
2098         tc = evas_object_textblock_cursor_new(rp->object);
2099         evas_textblock_cursor_copy(en->cursor, tc);
2100         evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2101         cx = ev->cur.canvas.x - x;
2102         cy = ev->cur.canvas.y - y;
2103         if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
2104           {
2105              Evas_Coord lx, ly, lw, lh;
2106
2107              if (evas_textblock_cursor_line_coord_set(en->cursor, cy) < 0)
2108                {
2109                   if (rp->part->multiline)
2110                     _curs_end(en->cursor, rp->object, en);
2111                   else
2112                     {
2113                        evas_textblock_cursor_paragraph_first(en->cursor);
2114                        evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2115                        if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
2116                          _curs_end(en->cursor, rp->object, en);
2117                     }
2118                }
2119              else
2120                {
2121                   evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2122                   if (cx <= lx)
2123                     _curs_lin_start(en->cursor, rp->object, en);
2124                   else
2125                     _curs_lin_end(en->cursor, rp->object, en);
2126                }
2127           }
2128         if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2129           {
2130              if (en->select_allow)
2131                {
2132                   if (en->had_sel)
2133                     {
2134                        if (en->select_mod_end)
2135                          _sel_extend(en->cursor, rp->object, en);
2136                        else if (en->select_mod_start)
2137                          _sel_preextend(en->cursor, rp->object, en);
2138                     }
2139                   else
2140                     _sel_extend(en->cursor, rp->object, en);
2141                }
2142           }
2143         else
2144           {
2145              _sel_extend(en->cursor, rp->object, en);
2146           }
2147         if (en->select_allow)
2148           {
2149              if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) != 0)
2150                _sel_enable(en->cursor, rp->object, en);
2151              if (en->have_selection)
2152                _sel_update(en->cursor, rp->object, en);
2153           }
2154         if (evas_textblock_cursor_compare(tc, en->cursor))
2155           {
2156              _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2157              _edje_emit(rp->edje, "cursor,changed,manual", rp->part->name);
2158           }
2159         evas_textblock_cursor_free(tc);
2160
2161         _edje_entry_imf_context_reset(rp);
2162         _edje_entry_imf_cursor_info_set(en);
2163
2164         _edje_entry_real_part_configure(rp);
2165      }
2166 }
2167
2168 static void
2169 _evas_focus_in_cb(void *data, Evas *e, __UNUSED__ void *event_info)
2170 {
2171    Edje *ed = (Edje *)data;
2172
2173    if (evas_focus_get(e) == ed->obj)
2174      {
2175         _edje_focus_in_cb(data, NULL, NULL, NULL);
2176      }
2177 }
2178
2179 static void
2180 _evas_focus_out_cb(void *data, Evas *e, __UNUSED__ void *event_info)
2181 {
2182    Edje *ed = (Edje *)data;
2183
2184    if (evas_focus_get(e) == ed->obj)
2185      {
2186         _edje_focus_out_cb(data, NULL, NULL, NULL);
2187      }
2188 }
2189
2190 /***************************************************************/
2191 void
2192 _edje_entry_init(Edje *ed)
2193 {
2194    if (!ed->has_entries)
2195      return;
2196    if (ed->entries_inited)
2197      return;
2198    ed->entries_inited = EINA_TRUE;
2199
2200    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb, ed);
2201    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb, ed);
2202    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb, ed);
2203    evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb, ed);
2204    evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed);
2205    evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed);
2206 }
2207
2208 void
2209 _edje_entry_shutdown(Edje *ed)
2210 {
2211    if (!ed->has_entries)
2212      return;
2213    if (!ed->entries_inited)
2214      return;
2215    ed->entries_inited = EINA_FALSE;
2216
2217    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb);
2218    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb);
2219    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb);
2220    evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb);
2221    if (evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed) != ed)
2222      ERR("could not unregister EVAS_CALLBACK_FOCUS_IN");
2223    if (evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed) != ed)
2224      ERR("could not unregister EVAS_CALLBACK_FOCUS_OUT");
2225 }
2226
2227 void
2228 _edje_entry_real_part_init(Edje_Real_Part *rp)
2229 {
2230    Entry *en;
2231 #ifdef HAVE_ECORE_IMF
2232    const char *ctx_id;
2233    const Ecore_IMF_Context_Info *ctx_info;
2234 #endif
2235
2236    en = calloc(1, sizeof(Entry));
2237    if (!en) return;
2238    rp->entry_data = en;
2239    en->rp = rp;
2240
2241    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOVE, _edje_part_move_cb, rp);
2242
2243    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_DOWN, _edje_part_mouse_down_cb, rp);
2244    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_UP, _edje_part_mouse_up_cb, rp);
2245    evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_MOVE, _edje_part_mouse_move_cb, rp);
2246
2247    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
2248      en->select_allow = EINA_TRUE;
2249
2250    if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2251      {
2252         Edje_Part_Description_Text *txt;
2253
2254         txt = (Edje_Part_Description_Text *)rp->chosen_description;
2255
2256         en->select_allow = EINA_FALSE;
2257         if (txt && edje_string_get(&txt->text.repch))
2258           evas_object_textblock_replace_char_set(rp->object, edje_string_get(&txt->text.repch));
2259         else
2260           evas_object_textblock_replace_char_set(rp->object, "*");
2261      }
2262
2263    en->cursor_bg = edje_object_add(rp->edje->base.evas);
2264    edje_object_file_set(en->cursor_bg, rp->edje->path, rp->part->source3);
2265    evas_object_smart_member_add(en->cursor_bg, rp->edje->obj);
2266    evas_object_stack_below(en->cursor_bg, rp->object);
2267    evas_object_clip_set(en->cursor_bg, evas_object_clip_get(rp->object));
2268    evas_object_pass_events_set(en->cursor_bg, EINA_TRUE);
2269    _edje_subobj_register(en->rp->edje, en->cursor_bg);
2270
2271    en->cursor_fg = edje_object_add(rp->edje->base.evas);
2272    edje_object_file_set(en->cursor_fg, rp->edje->path, rp->part->source4);
2273    evas_object_smart_member_add(en->cursor_fg, rp->edje->obj);
2274    evas_object_stack_above(en->cursor_fg, rp->object);
2275    evas_object_clip_set(en->cursor_fg, evas_object_clip_get(rp->object));
2276    evas_object_pass_events_set(en->cursor_fg, EINA_TRUE);
2277    _edje_subobj_register(en->rp->edje, en->cursor_fg);
2278
2279    evas_object_textblock_legacy_newline_set(rp->object, EINA_TRUE);
2280
2281    if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2282      {
2283         evas_object_show(en->cursor_bg);
2284         evas_object_show(en->cursor_fg);
2285         en->input_panel_enable = EINA_TRUE;
2286
2287 #ifdef HAVE_ECORE_IMF
2288         ecore_imf_init();
2289
2290         edje_object_signal_callback_add(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb, rp);
2291         edje_object_signal_callback_add(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb, rp);
2292
2293         ctx_id = ecore_imf_context_default_id_get();
2294         if (ctx_id)
2295           {
2296              ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
2297              if (!ctx_info->canvas_type ||
2298                  strcmp(ctx_info->canvas_type, "evas") == 0)
2299                {
2300                   en->imf_context = ecore_imf_context_add(ctx_id);
2301                }
2302              else
2303                {
2304                   ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
2305                   if (ctx_id)
2306                     {
2307                        en->imf_context = ecore_imf_context_add(ctx_id);
2308                     }
2309                }
2310           }
2311         else
2312           en->imf_context = NULL;
2313
2314         if (!en->imf_context) goto done;
2315
2316         ecore_imf_context_client_window_set
2317            (en->imf_context,
2318                (void *)ecore_evas_window_get
2319                (ecore_evas_ecore_evas_get(rp->edje->base.evas)));
2320         ecore_imf_context_client_canvas_set(en->imf_context, rp->edje->base.evas);
2321
2322         ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context,
2323                                                             _edje_entry_imf_retrieve_surrounding_cb, rp->edje);
2324         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb, rp->edje);
2325         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb, rp->edje);
2326         ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb, rp->edje);
2327         ecore_imf_context_input_mode_set(en->imf_context,
2328                                          rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD ?
2329                                          ECORE_IMF_INPUT_MODE_INVISIBLE : ECORE_IMF_INPUT_MODE_FULL);
2330
2331         if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2332           ecore_imf_context_input_panel_language_set(en->imf_context, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
2333 #endif
2334      }
2335 #ifdef HAVE_ECORE_IMF
2336 done:
2337 #endif
2338    en->cursor = (Evas_Textblock_Cursor *)evas_object_textblock_cursor_get(rp->object);
2339 }
2340
2341 void
2342 _edje_entry_real_part_shutdown(Edje_Real_Part *rp)
2343 {
2344    Entry *en = rp->entry_data;
2345    if (!en) return;
2346    rp->entry_data = NULL;
2347    _sel_clear(en->cursor, rp->object, en);
2348    _anchors_clear(en->cursor, rp->object, en);
2349 #ifdef HAVE_ECORE_IMF
2350    _preedit_clear(en);
2351 #endif
2352    evas_object_del(en->cursor_bg);
2353    evas_object_del(en->cursor_fg);
2354
2355    if (en->pw_timer)
2356      {
2357         ecore_timer_del(en->pw_timer);
2358         en->pw_timer = NULL;
2359      }
2360
2361 #ifdef HAVE_ECORE_IMF
2362    if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2363      {
2364         if (en->imf_context)
2365           {
2366              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb);
2367              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb);
2368              ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb);
2369
2370              ecore_imf_context_del(en->imf_context);
2371              en->imf_context = NULL;
2372           }
2373
2374         edje_object_signal_callback_del(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb);
2375         edje_object_signal_callback_del(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb);
2376         ecore_imf_shutdown();
2377      }
2378 #endif
2379    _compose_seq_reset(en);
2380    
2381    free(en);
2382 }
2383
2384 void
2385 _edje_entry_real_part_configure(Edje_Real_Part *rp)
2386 {
2387    Evas_Coord x, y, w, h, xx, yy, ww, hh;
2388    Entry *en = rp->entry_data;
2389    Evas_Textblock_Cursor_Type cur_type;
2390    if (!en) return;
2391    switch (rp->part->cursor_mode)
2392      {
2393       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2394          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2395          break;
2396       case EDJE_ENTRY_CURSOR_MODE_UNDER:
2397          /* no break for a resaon */
2398       default:
2399          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2400      }
2401
2402    _sel_update(en->cursor, rp->object, en);
2403    _anchors_update(en->cursor, rp->object, en);
2404    x = y = w = h = -1;
2405    xx = yy = ww = hh = -1;
2406    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2407    evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
2408    if (ww < 1) ww = 1;
2409    if (hh < 1) hh = 1;
2410    if (en->cursor_bg)
2411      {
2412         evas_object_move(en->cursor_bg, x + xx, y + yy);
2413         evas_object_resize(en->cursor_bg, ww, hh);
2414      }
2415    if (en->cursor_fg)
2416      {
2417         evas_object_move(en->cursor_fg, x + xx, y + yy);
2418         evas_object_resize(en->cursor_fg, ww, hh);
2419      }
2420 }
2421
2422 const char *
2423 _edje_entry_selection_get(Edje_Real_Part *rp)
2424 {
2425    Entry *en = rp->entry_data;
2426    if (!en) return NULL;
2427    // get selection - convert to markup
2428    if ((!en->selection) && (en->have_selection))
2429      en->selection = evas_textblock_cursor_range_text_get
2430         (en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
2431    return en->selection;
2432 }
2433
2434 const char *
2435 _edje_entry_text_get(Edje_Real_Part *rp)
2436 {
2437    Entry *en = rp->entry_data;
2438    if (!en) return NULL;
2439    // get text - convert to markup
2440    return evas_object_textblock_text_markup_get(rp->object);
2441 }
2442
2443 void
2444 _edje_entry_text_markup_set(Edje_Real_Part *rp, const char *text)
2445 {
2446    Entry *en = rp->entry_data;
2447    if (!en) return;
2448    _edje_entry_imf_context_reset(rp);
2449    // set text as markup
2450    _sel_clear(en->cursor, rp->object, en);
2451    evas_object_textblock_text_markup_set(rp->object, text);
2452    _edje_entry_set_cursor_start(rp);
2453
2454    _anchors_get(en->cursor, rp->object, en);
2455    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2456    _edje_entry_imf_cursor_info_set(en);
2457
2458    _edje_entry_real_part_configure(rp);
2459 #if 0
2460    /* Don't emit cursor changed cause it didn't. It's just init to 0. */
2461    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2462 #endif
2463 }
2464
2465 void
2466 _edje_entry_text_markup_append(Edje_Real_Part *rp, const char *text)
2467 {
2468    Entry *en = rp->entry_data;
2469    Evas_Textblock_Cursor *end_cur;
2470    if (!en) return;
2471    end_cur = evas_object_textblock_cursor_new(rp->object);
2472    evas_textblock_cursor_paragraph_last(end_cur);
2473
2474    _text_filter_markup_prepend(en, end_cur, text);
2475    evas_textblock_cursor_free(end_cur);
2476
2477    /* We are updating according to the real cursor on purpose */
2478    _anchors_get(en->cursor, rp->object, en);
2479    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2480
2481    _edje_entry_real_part_configure(rp);
2482 }
2483
2484 void
2485 _edje_entry_text_markup_insert(Edje_Real_Part *rp, const char *text)
2486 {
2487    Entry *en = rp->entry_data;
2488    if (!en) return;
2489    _edje_entry_imf_context_reset(rp);
2490
2491    // prepend markup @ cursor pos
2492    if (en->have_selection)
2493      _range_del(en->cursor, rp->object, en);
2494    //xx
2495 //   evas_object_textblock_text_markup_prepend(en->cursor, text);
2496    _text_filter_markup_prepend(en, en->cursor, text);
2497    _anchors_get(en->cursor, rp->object, en);
2498    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2499    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2500
2501    _edje_entry_imf_cursor_info_set(en);
2502    _edje_entry_real_part_configure(rp);
2503 }
2504
2505 void
2506 _edje_entry_set_cursor_start(Edje_Real_Part *rp)
2507 {
2508    Entry *en = rp->entry_data;
2509    if (!en) return;
2510    _curs_start(en->cursor, rp->object, en);
2511
2512    _edje_entry_imf_cursor_info_set(en);
2513 }
2514
2515 void
2516 _edje_entry_set_cursor_end(Edje_Real_Part *rp)
2517 {
2518    Entry *en = rp->entry_data;
2519    if (!en) return;
2520    _curs_end(en->cursor, rp->object, en);
2521
2522    _edje_entry_imf_cursor_info_set(en);
2523 }
2524
2525 void
2526 _edje_entry_select_none(Edje_Real_Part *rp)
2527 {
2528    Entry *en = rp->entry_data;
2529    if (!en) return;
2530    _sel_clear(en->cursor, rp->object, en);
2531 }
2532
2533 void
2534 _edje_entry_select_all(Edje_Real_Part *rp)
2535 {
2536    Entry *en = rp->entry_data;
2537    if (!en) return;
2538
2539    _edje_entry_imf_context_reset(rp);
2540
2541    _sel_clear(en->cursor, rp->object, en);
2542    _curs_start(en->cursor, rp->object, en);
2543    _sel_enable(en->cursor, rp->object, en);
2544    _sel_start(en->cursor, rp->object, en);
2545    _curs_end(en->cursor, rp->object, en);
2546    _sel_extend(en->cursor, rp->object, en);
2547
2548    _edje_entry_imf_cursor_info_set(en);
2549    _edje_entry_real_part_configure(rp);
2550 }
2551
2552 void
2553 _edje_entry_select_begin(Edje_Real_Part *rp)
2554 {
2555    Entry *en = rp->entry_data;
2556    if (!en) return;
2557
2558    _edje_entry_imf_context_reset(rp);
2559
2560    _sel_clear(en->cursor, rp->object, en);
2561    _sel_enable(en->cursor, rp->object, en);
2562    _sel_start(en->cursor, rp->object, en);
2563    _sel_extend(en->cursor, rp->object, en);
2564
2565    _edje_entry_imf_cursor_info_set(en);
2566
2567    _edje_entry_real_part_configure(rp);
2568 }
2569
2570 void
2571 _edje_entry_select_extend(Edje_Real_Part *rp)
2572 {
2573    Entry *en = rp->entry_data;
2574    if (!en) return;
2575    _edje_entry_imf_context_reset(rp);
2576    _sel_extend(en->cursor, rp->object, en);
2577
2578    _edje_entry_imf_cursor_info_set(en);
2579
2580    _edje_entry_real_part_configure(rp);
2581 }
2582
2583 const Eina_List *
2584 _edje_entry_anchor_geometry_get(Edje_Real_Part *rp, const char *anchor)
2585 {
2586    Entry *en = rp->entry_data;
2587    Eina_List *l;
2588    Anchor *an;
2589
2590    if (!en) return NULL;
2591    EINA_LIST_FOREACH(en->anchors, l, an)
2592      {
2593         if (an->item) continue;
2594         if (!strcmp(anchor, an->name))
2595           return an->sel;
2596      }
2597    return NULL;
2598 }
2599
2600 const Eina_List *
2601 _edje_entry_anchors_list(Edje_Real_Part *rp)
2602 {
2603    Entry *en = rp->entry_data;
2604    Eina_List *l, *anchors = NULL;
2605    Anchor *an;
2606
2607    if (!en) return NULL;
2608    if (!en->anchorlist)
2609      {
2610         EINA_LIST_FOREACH(en->anchors, l, an)
2611           {
2612              const char *n = an->name;
2613              if (an->item) continue;
2614              if (!n) n = "";
2615              anchors = eina_list_append(anchors, strdup(n));
2616           }
2617         en->anchorlist = anchors;
2618      }
2619    return en->anchorlist;
2620 }
2621
2622 Eina_Bool
2623 _edje_entry_item_geometry_get(Edje_Real_Part *rp, const char *item, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
2624 {
2625    Entry *en = rp->entry_data;
2626    Eina_List *l;
2627    Anchor *an;
2628
2629    if (!en) return EINA_FALSE;
2630    EINA_LIST_FOREACH(en->anchors, l, an)
2631      {
2632         if (an->item) continue;
2633         if (!strcmp(item, an->name))
2634           {
2635              evas_textblock_cursor_format_item_geometry_get(an->start, cx, cy, cw, ch);
2636              return EINA_TRUE;
2637           }
2638      }
2639    return EINA_FALSE;
2640 }
2641
2642 const Eina_List *
2643 _edje_entry_items_list(Edje_Real_Part *rp)
2644 {
2645    Entry *en = rp->entry_data;
2646    Eina_List *l, *items = NULL;
2647    Anchor *an;
2648
2649    if (!en) return NULL;
2650    if (!en->itemlist)
2651      {
2652         EINA_LIST_FOREACH(en->anchors, l, an)
2653           {
2654              const char *n = an->name;
2655              if (an->item) continue;
2656              if (!n) n = "";
2657              items = eina_list_append(items, strdup(n));
2658           }
2659         en->itemlist = items;
2660      }
2661    return en->itemlist;
2662 }
2663
2664 void
2665 _edje_entry_cursor_geometry_get(Edje_Real_Part *rp, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
2666 {
2667    Evas_Coord x, y, w, h, xx, yy, ww, hh;
2668    Entry *en = rp->entry_data;
2669    Evas_Textblock_Cursor_Type cur_type;
2670    if (!en) return;
2671    switch (rp->part->cursor_mode)
2672      {
2673       case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2674          cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2675          break;
2676       case EDJE_ENTRY_CURSOR_MODE_UNDER:
2677          /* no break for a resaon */
2678       default:
2679          cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2680      }
2681
2682    x = y = w = h = -1;
2683    xx = yy = ww = hh = -1;
2684    evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2685    evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
2686    if (ww < 1) ww = 1;
2687    if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
2688      edje_object_size_min_restricted_calc(en->cursor_fg, &ww, NULL, ww, 0);
2689    if (hh < 1) hh = 1;
2690    if (cx) *cx = x + xx;
2691    if (cy) *cy = y + yy;
2692    if (cw) *cw = ww;
2693    if (ch) *ch = hh;
2694 }
2695
2696 void
2697 _edje_entry_user_insert(Edje_Real_Part *rp, const char *text)
2698 {
2699    Entry *en = rp->entry_data;
2700    Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
2701    info->insert = EINA_TRUE;
2702    info->change.insert.plain_length = 1;
2703    info->change.insert.content = eina_stringshare_add(text);
2704      {
2705         char *tmp;
2706         tmp = evas_textblock_text_markup_to_utf8(rp->object,
2707                                                  info->change.insert.content);
2708         info->change.insert.plain_length = eina_unicode_utf8_get_len(tmp);
2709         free(tmp);
2710      }
2711
2712    if (en->have_selection)
2713      {
2714         _range_del_emit(rp->edje, en->cursor, rp->object, en);
2715         info->merge = EINA_TRUE;
2716      }
2717    info->change.insert.pos = evas_textblock_cursor_pos_get(en->cursor);
2718    _text_filter_markup_prepend(en, en->cursor, text);
2719    _anchors_get(en->cursor, rp->object, en);
2720    _edje_emit(rp->edje, "entry,changed", rp->part->name);
2721    _edje_emit_full(rp->edje, "entry,changed,user", rp->part->name,
2722                    info, _free_entry_change_info);
2723    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2724 }
2725
2726 void
2727 _edje_entry_select_allow_set(Edje_Real_Part *rp, Eina_Bool allow)
2728 {
2729    Entry *en = rp->entry_data;
2730    if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
2731      return;
2732    en->select_allow = allow;
2733 }
2734
2735 Eina_Bool
2736 _edje_entry_select_allow_get(const Edje_Real_Part *rp)
2737 {
2738    const Entry *en = rp->entry_data;
2739    return en->select_allow;
2740 }
2741
2742 void
2743 _edje_entry_select_abort(Edje_Real_Part *rp)
2744 {
2745    Entry *en = rp->entry_data;
2746    if (en->selecting)
2747      {
2748         en->selecting = EINA_FALSE;
2749
2750         _edje_entry_imf_context_reset(rp);
2751         _edje_entry_imf_cursor_info_set(en);
2752         _edje_entry_real_part_configure(rp);
2753      }
2754 }
2755
2756 void *
2757 _edje_entry_imf_context_get(Edje_Real_Part *rp)
2758 {
2759    Entry *en = rp->entry_data;
2760    if (!en) return NULL;
2761
2762 #ifdef HAVE_ECORE_IMF
2763    return en->imf_context;
2764 #else
2765    return NULL;
2766 #endif
2767 }
2768
2769 void
2770 _edje_entry_autocapital_type_set(Edje_Real_Part *rp, Edje_Text_Autocapital_Type autocapital_type)
2771 {
2772    Entry *en = rp->entry_data;
2773    if (!en) return;
2774
2775    if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2776      autocapital_type = EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2777
2778 #ifdef HAVE_ECORE_IMF
2779    if (en->imf_context)
2780      ecore_imf_context_autocapital_type_set(en->imf_context, autocapital_type);
2781 #endif
2782 }
2783
2784 Edje_Text_Autocapital_Type
2785 _edje_entry_autocapital_type_get(Edje_Real_Part *rp)
2786 {
2787    Entry *en = rp->entry_data;
2788    if (!en) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2789
2790 #ifdef HAVE_ECORE_IMF
2791    if (en->imf_context)
2792      return ecore_imf_context_autocapital_type_get(en->imf_context);
2793 #endif
2794
2795    return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2796 }
2797
2798 void
2799 _edje_entry_prediction_allow_set(Edje_Real_Part *rp, Eina_Bool prediction)
2800 {
2801    Entry *en = rp->entry_data;
2802
2803    if (!en) return;
2804    en->prediction_allow = prediction;
2805 #ifdef HAVE_ECORE_IMF
2806    if (en->imf_context)
2807      ecore_imf_context_prediction_allow_set(en->imf_context, prediction);
2808 #endif
2809 }
2810
2811 Eina_Bool
2812 _edje_entry_prediction_allow_get(Edje_Real_Part *rp)
2813 {
2814    Entry *en = rp->entry_data;
2815    if (!en) return EINA_FALSE;
2816
2817    return en->prediction_allow;
2818 }
2819
2820 void
2821 _edje_entry_input_panel_enabled_set(Edje_Real_Part *rp, Eina_Bool enabled)
2822 {
2823    Entry *en = rp->entry_data;
2824
2825    if (!en) return;
2826    en->input_panel_enable = enabled;
2827 #ifdef HAVE_ECORE_IMF
2828    if (en->imf_context)
2829      ecore_imf_context_input_panel_enabled_set(en->imf_context, enabled);
2830 #endif
2831 }
2832
2833 Eina_Bool
2834 _edje_entry_input_panel_enabled_get(Edje_Real_Part *rp)
2835 {
2836    Entry *en = rp->entry_data;
2837    if (!en) return EINA_FALSE;
2838
2839    return en->input_panel_enable;
2840 }
2841
2842 void
2843 _edje_entry_input_panel_show(Edje_Real_Part *rp)
2844 {
2845    Entry *en = rp->entry_data;
2846
2847    if (!en) return;
2848 #ifdef HAVE_ECORE_IMF
2849    if (en->imf_context)
2850      ecore_imf_context_input_panel_show(en->imf_context);
2851 #endif
2852 }
2853
2854 void
2855 _edje_entry_input_panel_hide(Edje_Real_Part *rp)
2856 {
2857    Entry *en = rp->entry_data;
2858
2859    if (!en) return;
2860 #ifdef HAVE_ECORE_IMF
2861    if (en->imf_context)
2862      ecore_imf_context_input_panel_hide(en->imf_context);
2863 #endif
2864 }
2865
2866 void
2867 _edje_entry_input_panel_language_set(Edje_Real_Part *rp, Edje_Input_Panel_Lang lang)
2868 {
2869    Entry *en = rp->entry_data;
2870
2871    if (!en) return;
2872    en->input_panel_lang = lang;
2873 #ifdef HAVE_ECORE_IMF
2874    if (en->imf_context)
2875      ecore_imf_context_input_panel_language_set(en->imf_context, lang);
2876 #endif
2877 }
2878
2879 Edje_Input_Panel_Lang
2880 _edje_entry_input_panel_language_get(Edje_Real_Part *rp)
2881 {
2882    Entry *en = rp->entry_data;
2883    if (!en) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
2884
2885    return en->input_panel_lang;
2886 }
2887
2888 #ifdef HAVE_ECORE_IMF
2889 void
2890 _edje_entry_input_panel_imdata_set(Edje_Real_Part *rp, const void *data, int len)
2891 #else
2892 void
2893 _edje_entry_input_panel_imdata_set(Edje_Real_Part *rp, const void *data __UNUSED__, int len __UNUSED__)
2894 #endif
2895 {
2896    Entry *en = rp->entry_data;
2897    if (!en) return;
2898 #ifdef HAVE_ECORE_IMF
2899    if (en->imf_context)
2900      ecore_imf_context_input_panel_imdata_set(en->imf_context, data, len);
2901 #endif
2902 }
2903
2904 #ifdef HAVE_ECORE_IMF
2905 void
2906 _edje_entry_input_panel_imdata_get(Edje_Real_Part *rp, void *data, int *len)
2907 #else
2908 void
2909 _edje_entry_input_panel_imdata_get(Edje_Real_Part *rp, void *data __UNUSED__, int *len __UNUSED__)
2910 #endif
2911 {
2912    Entry *en = rp->entry_data;
2913    if (!en) return;
2914 #ifdef HAVE_ECORE_IMF
2915    if (en->imf_context)
2916      ecore_imf_context_input_panel_imdata_get(en->imf_context, data, len);
2917 #endif
2918 }
2919
2920 #ifdef HAVE_ECORE_IMF
2921 void
2922 _edje_entry_input_panel_return_key_type_set(Edje_Real_Part *rp, Edje_Input_Panel_Return_Key_Type return_key_type)
2923 #else
2924 void
2925 _edje_entry_input_panel_return_key_type_set(Edje_Real_Part *rp, Edje_Input_Panel_Return_Key_Type return_key_type __UNUSED__)
2926 #endif
2927 {
2928    Entry *en = rp->entry_data;
2929    if (!en) return;
2930 #ifdef HAVE_ECORE_IMF
2931    if (en->imf_context)
2932      ecore_imf_context_input_panel_return_key_type_set(en->imf_context, return_key_type);
2933 #endif
2934 }
2935
2936 Edje_Input_Panel_Return_Key_Type
2937 _edje_entry_input_panel_return_key_type_get(Edje_Real_Part *rp)
2938 {
2939    Entry *en = rp->entry_data;
2940    if (!en) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2941 #ifdef HAVE_ECORE_IMF
2942    if (en->imf_context)
2943      return ecore_imf_context_input_panel_return_key_type_get(en->imf_context);
2944 #endif
2945    return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2946 }
2947
2948 #ifdef HAVE_ECORE_IMF
2949 void
2950 _edje_entry_input_panel_return_key_disabled_set(Edje_Real_Part *rp, Eina_Bool disabled)
2951 #else
2952 void
2953 _edje_entry_input_panel_return_key_disabled_set(Edje_Real_Part *rp, Eina_Bool disabled __UNUSED__)
2954 #endif
2955 {
2956    Entry *en = rp->entry_data;
2957    if (!en) return;
2958 #ifdef HAVE_ECORE_IMF
2959    if (en->imf_context)
2960      ecore_imf_context_input_panel_return_key_disabled_set(en->imf_context, disabled);
2961 #endif
2962 }
2963
2964 Eina_Bool
2965 _edje_entry_input_panel_return_key_disabled_get(Edje_Real_Part *rp)
2966 {
2967    Entry *en = rp->entry_data;
2968    if (!en) return EINA_FALSE;
2969 #ifdef HAVE_ECORE_IMF
2970    if (en->imf_context)
2971      return ecore_imf_context_input_panel_return_key_disabled_get(en->imf_context);
2972 #endif
2973    return EINA_FALSE;
2974 }
2975
2976 static Evas_Textblock_Cursor *
2977 _cursor_get(Edje_Real_Part *rp, Edje_Cursor cur)
2978 {
2979    Entry *en = rp->entry_data;
2980    if (!en) return NULL;
2981
2982    switch (cur)
2983      {
2984       case EDJE_CURSOR_MAIN:
2985          return en->cursor;
2986       case EDJE_CURSOR_SELECTION_BEGIN:
2987          return en->sel_start;
2988       case EDJE_CURSOR_SELECTION_END:
2989          return en->sel_end;
2990       case EDJE_CURSOR_PREEDIT_START:
2991          if (!en->preedit_start)
2992            en->preedit_start = evas_object_textblock_cursor_new(rp->object);
2993          return en->preedit_start;
2994       case EDJE_CURSOR_PREEDIT_END:
2995          if (!en->preedit_end)
2996            en->preedit_end = evas_object_textblock_cursor_new(rp->object);
2997          return en->preedit_end;
2998       case EDJE_CURSOR_USER:
2999          if (!en->cursor_user)
3000            en->cursor_user = evas_object_textblock_cursor_new(rp->object);
3001          return en->cursor_user;
3002       case EDJE_CURSOR_USER_EXTRA:
3003          if (!en->cursor_user_extra)
3004            en->cursor_user_extra = evas_object_textblock_cursor_new(rp->object);
3005          return en->cursor_user_extra;
3006       default:
3007          break;
3008      }
3009    return NULL;
3010 }
3011
3012 Eina_Bool
3013 _edje_entry_cursor_next(Edje_Real_Part *rp, Edje_Cursor cur)
3014 {
3015    Entry *en = rp->entry_data;
3016    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3017    if (!c) return EINA_FALSE;
3018
3019    _edje_entry_imf_context_reset(rp);
3020
3021    if (!evas_textblock_cursor_char_next(c))
3022      {
3023         return EINA_FALSE;
3024      }
3025    _sel_update(c, rp->object, rp->entry_data);
3026    _edje_entry_imf_cursor_info_set(en);
3027
3028    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3029    _edje_entry_real_part_configure(rp);
3030    return EINA_TRUE;
3031 }
3032
3033 Eina_Bool
3034 _edje_entry_cursor_prev(Edje_Real_Part *rp, Edje_Cursor cur)
3035 {
3036    Entry *en = rp->entry_data;
3037    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3038    if (!c) return EINA_FALSE;
3039
3040    _edje_entry_imf_context_reset(rp);
3041
3042    if (!evas_textblock_cursor_char_prev(c))
3043      {
3044         if (evas_textblock_cursor_paragraph_prev(c)) goto ok;
3045         else return EINA_FALSE;
3046      }
3047 ok:
3048    _sel_update(c, rp->object, rp->entry_data);
3049
3050    _edje_entry_imf_cursor_info_set(en);
3051
3052    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3053    _edje_entry_real_part_configure(rp);
3054    return EINA_TRUE;
3055 }
3056
3057 Eina_Bool
3058 _edje_entry_cursor_up(Edje_Real_Part *rp, Edje_Cursor cur)
3059 {
3060    Entry *en = rp->entry_data;
3061    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3062    Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
3063    int ln;
3064    if (!c) return EINA_FALSE;
3065
3066    _edje_entry_imf_context_reset(rp);
3067
3068    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
3069    ln--;
3070    if (ln < 0) return EINA_FALSE;
3071    if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
3072                                                        &lx, &ly, &lw, &lh))
3073      return EINA_FALSE;
3074    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
3075    if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
3076      {
3077         if (cx < (lx + (lw / 2)))
3078           evas_textblock_cursor_line_char_last(c);
3079         else
3080           evas_textblock_cursor_line_char_last(c);
3081      }
3082    _sel_update(c, rp->object, rp->entry_data);
3083
3084    _edje_entry_imf_cursor_info_set(en);
3085
3086    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3087    _edje_entry_real_part_configure(rp);
3088    return EINA_TRUE;
3089 }
3090
3091 Eina_Bool
3092 _edje_entry_cursor_down(Edje_Real_Part *rp, Edje_Cursor cur)
3093 {
3094    Entry *en = rp->entry_data;
3095    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3096    Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
3097    int ln;
3098    if (!c) return EINA_FALSE;
3099
3100    _edje_entry_imf_context_reset(rp);
3101
3102    ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
3103    ln++;
3104    if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
3105                                                        &lx, &ly, &lw, &lh))
3106      return EINA_FALSE;
3107    evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
3108    if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
3109      {
3110         if (cx < (lx + (lw / 2)))
3111           evas_textblock_cursor_line_char_last(c);
3112         else
3113           evas_textblock_cursor_line_char_last(c);
3114      }
3115    _sel_update(c, rp->object, rp->entry_data);
3116
3117    _edje_entry_imf_cursor_info_set(en);
3118    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3119    _edje_entry_real_part_configure(rp);
3120    return EINA_TRUE;
3121 }
3122
3123 void
3124 _edje_entry_cursor_begin(Edje_Real_Part *rp, Edje_Cursor cur)
3125 {
3126    Entry *en = rp->entry_data;
3127    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3128    if (!c) return;
3129
3130    _edje_entry_imf_context_reset(rp);
3131
3132    evas_textblock_cursor_paragraph_first(c);
3133    _sel_update(c, rp->object, rp->entry_data);
3134
3135    _edje_entry_imf_cursor_info_set(en);
3136    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3137    _edje_entry_real_part_configure(rp);
3138 }
3139
3140 void
3141 _edje_entry_cursor_end(Edje_Real_Part *rp, Edje_Cursor cur)
3142 {
3143    Entry *en = rp->entry_data;
3144    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3145    if (!c) return;
3146
3147    _edje_entry_imf_context_reset(rp);
3148
3149    _curs_end(c, rp->object, rp->entry_data);
3150    _sel_update(c, rp->object, rp->entry_data);
3151
3152    _edje_entry_imf_cursor_info_set(en);
3153
3154    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3155    _edje_entry_real_part_configure(rp);
3156 }
3157
3158 void
3159 _edje_entry_cursor_copy(Edje_Real_Part *rp, Edje_Cursor cur, Edje_Cursor dst)
3160 {
3161    Entry *en = rp->entry_data;
3162    Evas_Textblock_Cursor *c;
3163    Evas_Textblock_Cursor *d;
3164
3165    c = _cursor_get(rp, cur);
3166    if (!c) return;
3167    d = _cursor_get(rp, dst);
3168    if (!d) return;
3169    evas_textblock_cursor_copy(c, d);
3170    _sel_update(c, rp->object, rp->entry_data);
3171
3172    _edje_entry_imf_context_reset(rp);
3173    _edje_entry_imf_cursor_info_set(en);
3174    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3175    _edje_entry_real_part_configure(rp);
3176 }
3177
3178 void
3179 _edje_entry_cursor_line_begin(Edje_Real_Part *rp, Edje_Cursor cur)
3180 {
3181    Entry *en = rp->entry_data;
3182    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3183    if (!c) return;
3184    _edje_entry_imf_context_reset(rp);
3185
3186    evas_textblock_cursor_line_char_first(c);
3187    _sel_update(c, rp->object, rp->entry_data);
3188
3189    _edje_entry_imf_cursor_info_set(en);
3190
3191    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3192    _edje_entry_real_part_configure(rp);
3193 }
3194
3195 void
3196 _edje_entry_cursor_line_end(Edje_Real_Part *rp, Edje_Cursor cur)
3197 {
3198    Entry *en = rp->entry_data;
3199    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3200    if (!c) return;
3201    _edje_entry_imf_context_reset(rp);
3202    evas_textblock_cursor_line_char_last(c);
3203    _sel_update(c, rp->object, rp->entry_data);
3204
3205    _edje_entry_imf_cursor_info_set(en);
3206    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3207    _edje_entry_real_part_configure(rp);
3208 }
3209
3210 Eina_Bool
3211 _edje_entry_cursor_coord_set(Edje_Real_Part *rp, Edje_Cursor cur,
3212                              Evas_Coord x, Evas_Coord y)
3213 {
3214    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3215    if (!c) return EINA_FALSE;
3216    return evas_textblock_cursor_char_coord_set(c, x, y);
3217 }
3218
3219 Eina_Bool
3220 _edje_entry_cursor_is_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
3221 {
3222    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3223    if (!c) return EINA_FALSE;
3224    if (evas_textblock_cursor_is_format(c)) return EINA_TRUE;
3225    return EINA_FALSE;
3226 }
3227
3228 Eina_Bool
3229 _edje_entry_cursor_is_visible_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
3230 {
3231    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3232    if (!c) return EINA_FALSE;
3233    return evas_textblock_cursor_format_is_visible_get(c);
3234 }
3235
3236 char *
3237 _edje_entry_cursor_content_get(Edje_Real_Part *rp, Edje_Cursor cur)
3238 {
3239    static char *s = NULL;
3240    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3241
3242    if (!c) return NULL;
3243    if (s)
3244      {
3245         free(s);
3246         s = NULL;
3247      }
3248
3249    s = evas_textblock_cursor_content_get(c);
3250    return s;
3251 }
3252
3253 void
3254 _edje_entry_cursor_pos_set(Edje_Real_Part *rp, Edje_Cursor cur, int pos)
3255 {
3256    Entry *en = rp->entry_data;
3257    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3258    if (!c) return;
3259    /* Abort if cursor position didn't really change */
3260    if (evas_textblock_cursor_pos_get(c) == pos)
3261      return;
3262
3263    _edje_entry_imf_context_reset(rp);
3264    evas_textblock_cursor_pos_set(c, pos);
3265    _sel_update(c, rp->object, rp->entry_data);
3266
3267    _edje_entry_imf_cursor_info_set(en);
3268    _edje_emit(rp->edje, "cursor,changed", rp->part->name);
3269    _edje_entry_real_part_configure(rp);
3270 }
3271
3272 int
3273 _edje_entry_cursor_pos_get(Edje_Real_Part *rp, Edje_Cursor cur)
3274 {
3275    Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
3276    if (!c) return 0;
3277    return evas_textblock_cursor_pos_get(c);
3278 }
3279
3280 void
3281 _edje_entry_input_panel_layout_set(Edje_Real_Part *rp, Edje_Input_Panel_Layout layout)
3282 {
3283    Entry *en = rp->entry_data;
3284    if (!en) return;
3285 #ifdef HAVE_ECORE_IMF
3286    if (en->imf_context)
3287      ecore_imf_context_input_panel_layout_set(en->imf_context, layout);
3288 #else
3289    (void) layout;
3290 #endif
3291 }
3292
3293 Edje_Input_Panel_Layout
3294 _edje_entry_input_panel_layout_get(Edje_Real_Part *rp)
3295 {
3296    Entry *en = rp->entry_data;
3297    if (!en) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
3298 #ifdef HAVE_ECORE_IMF
3299    if (en->imf_context)
3300      return ecore_imf_context_input_panel_layout_get(en->imf_context);
3301 #endif
3302
3303    return EDJE_INPUT_PANEL_LAYOUT_INVALID;
3304 }
3305
3306 void
3307 _edje_entry_imf_context_reset(Edje_Real_Part *rp)
3308 {
3309    Entry *en = rp->entry_data;
3310    if (!en) return;
3311 #ifdef HAVE_ECORE_IMF
3312    if (en->imf_context)
3313      ecore_imf_context_reset(en->imf_context);
3314 #endif
3315 }
3316
3317 static void
3318 _edje_entry_imf_cursor_info_set(Entry *en)
3319 {
3320 #ifdef HAVE_ECORE_IMF
3321    Evas_Coord cx, cy, cw, ch;
3322    if (!en || !en->rp || !en->imf_context) return;
3323
3324    _edje_entry_cursor_geometry_get(en->rp, &cx, &cy, &cw, &ch);
3325
3326    ecore_imf_context_cursor_position_set(en->imf_context,
3327                                          evas_textblock_cursor_pos_get(en->cursor));
3328    ecore_imf_context_cursor_location_set(en->imf_context, cx, cy, cw, ch);
3329 #else
3330    (void) en;
3331 #endif
3332 }
3333
3334 #ifdef HAVE_ECORE_IMF
3335 static Eina_Bool
3336 _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, char **text, int *cursor_pos)
3337 {
3338    Edje *ed = data;
3339    Edje_Real_Part *rp = ed->focused_part;
3340    Entry *en;
3341    const char *str;
3342
3343    if (!rp) return EINA_FALSE;
3344    en = rp->entry_data;
3345    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3346        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3347      return EINA_FALSE;
3348
3349    if (text)
3350      {
3351         str = _edje_entry_text_get(rp);
3352         *text = str ? strdup(str) : strdup("");
3353      }
3354
3355    if (cursor_pos)
3356      *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
3357
3358    return EINA_TRUE;
3359 }
3360
3361 static void
3362 _edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, void *event_info)
3363 {
3364    Edje *ed = data;
3365    Edje_Real_Part *rp = ed->focused_part;
3366    Entry *en;
3367    char *commit_str = event_info;
3368    int start_pos;
3369
3370    if ((!rp)) return;
3371
3372    en = rp->entry_data;
3373    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3374        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3375      return;
3376
3377    if (en->have_selection)
3378      {
3379         if (strcmp(commit_str, ""))
3380           {
3381              /* delete selected characters */
3382              _range_del_emit(ed, en->cursor, rp->object, en);
3383              _sel_clear(en->cursor, rp->object, en);
3384           }
3385      }
3386
3387    start_pos = evas_textblock_cursor_pos_get(en->cursor);
3388
3389 #ifdef HAVE_ECORE_IMF
3390    /* delete preedit characters */
3391    _preedit_del(en);
3392    _preedit_clear(en);
3393 #endif
3394
3395    if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3396        _edje_password_show_last)
3397      _edje_entry_hide_visible_password(en->rp);
3398    if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3399        _edje_password_show_last && (!en->preedit_start))
3400      {
3401         _text_filter_format_prepend(en, en->cursor, "+ password=off");
3402         _text_filter_text_prepend(en, en->cursor, commit_str);
3403         _text_filter_format_prepend(en, en->cursor, "- password");
3404
3405         if (en->pw_timer)
3406           {
3407              ecore_timer_del(en->pw_timer);
3408              en->pw_timer = NULL;
3409           }
3410         en->pw_timer = ecore_timer_add(TO_DOUBLE(_edje_password_show_last_timeout),
3411                                        _password_timer_cb, en);
3412      }
3413    else
3414      _text_filter_text_prepend(en, en->cursor, commit_str);
3415
3416
3417    _edje_entry_imf_cursor_info_set(en);
3418    _anchors_get(en->cursor, rp->object, en);
3419    _edje_emit(rp->edje, "entry,changed", rp->part->name);
3420
3421      {
3422         Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
3423         info->insert = EINA_TRUE;
3424         info->change.insert.pos = start_pos;
3425         info->change.insert.content = eina_stringshare_add(commit_str);
3426         info->change.insert.plain_length =
3427            eina_unicode_utf8_get_len(info->change.insert.content);
3428         _edje_emit_full(ed, "entry,changed,user", rp->part->name,
3429                         info, _free_entry_change_info);
3430         _edje_emit(ed, "cursor,changed", rp->part->name);
3431      }
3432 }
3433
3434 static void
3435 _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, void *event_info __UNUSED__)
3436 {
3437    Edje *ed = data;
3438    Edje_Real_Part *rp = ed->focused_part;
3439    Entry *en;
3440    int cursor_pos;
3441    int preedit_start_pos, preedit_end_pos;
3442    char *preedit_string;
3443    int i;
3444    Eina_Bool preedit_end_state = EINA_FALSE;
3445    Eina_List *attrs = NULL, *l = NULL;
3446    Ecore_IMF_Preedit_Attr *attr;
3447    Eina_Strbuf *buf;
3448
3449    if ((!rp)) return;
3450
3451    en = rp->entry_data;
3452    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3453        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3454      return;
3455
3456    if (!en->imf_context) return;
3457
3458    ecore_imf_context_preedit_string_with_attributes_get(en->imf_context,
3459                                                         &preedit_string,
3460                                                         &attrs, &cursor_pos);
3461    if (!preedit_string) return;
3462
3463    if (!strcmp(preedit_string, ""))
3464      preedit_end_state = EINA_TRUE;
3465
3466    if (en->have_selection && !preedit_end_state)
3467      {
3468         /* delete selected characters */
3469         _range_del_emit(ed, en->cursor, rp->object, en);
3470      }
3471
3472    /* delete preedit characters */
3473    _preedit_del(en);
3474
3475    preedit_start_pos = evas_textblock_cursor_pos_get(en->cursor);
3476
3477    /* insert preedit character(s) */
3478    if (strlen(preedit_string) > 0)
3479      {
3480         buf = eina_strbuf_new();
3481         if (attrs)
3482           {
3483              EINA_LIST_FOREACH(attrs, l, attr)
3484                {
3485                   if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB1)
3486                     {
3487                        eina_strbuf_append(buf, "<preedit>");
3488                        eina_strbuf_append_n(buf, preedit_string + attr->start_index,
3489                                             attr->end_index - attr->start_index);
3490                        eina_strbuf_append(buf, "</preedit>");
3491                     }
3492
3493                   else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB2 ||
3494                            attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3)
3495                     {
3496                        eina_strbuf_append(buf, "<preedit_sel>");
3497                        eina_strbuf_append_n(buf, preedit_string + attr->start_index,
3498                                             attr->end_index - attr->start_index);
3499                        eina_strbuf_append(buf, "</preedit_sel>");
3500                     }
3501                }
3502           }
3503         else
3504           {
3505              eina_strbuf_append(buf, preedit_string);
3506           }
3507         if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3508             _edje_password_show_last)
3509           {
3510              _edje_entry_hide_visible_password(en->rp);
3511              _text_filter_format_prepend(en, en->cursor, "+ password=off");
3512              _text_filter_markup_prepend(en, en->cursor, eina_strbuf_string_get(buf));
3513              _text_filter_format_prepend(en, en->cursor, "- password");
3514              if (en->pw_timer)
3515                {
3516                   ecore_timer_del(en->pw_timer);
3517                   en->pw_timer = NULL;
3518                }
3519              en->pw_timer = ecore_timer_add(TO_DOUBLE(_edje_password_show_last_timeout),
3520                                             _password_timer_cb, en);
3521           }
3522         else
3523           {
3524              _text_filter_markup_prepend(en, en->cursor, eina_strbuf_string_get(buf));
3525           }
3526         eina_strbuf_free(buf);
3527      }
3528
3529    if (!preedit_end_state)
3530      {
3531         /* set preedit start cursor */
3532         if (!en->preedit_start)
3533           en->preedit_start = evas_object_textblock_cursor_new(rp->object);
3534         evas_textblock_cursor_copy(en->cursor, en->preedit_start);
3535
3536         /* set preedit end cursor */
3537         if (!en->preedit_end)
3538           en->preedit_end = evas_object_textblock_cursor_new(rp->object);
3539         evas_textblock_cursor_copy(en->cursor, en->preedit_end);
3540
3541         preedit_end_pos = evas_textblock_cursor_pos_get(en->cursor);
3542
3543         for (i = 0; i < (preedit_end_pos - preedit_start_pos); i++)
3544           {
3545              evas_textblock_cursor_char_prev(en->preedit_start);
3546           }
3547
3548         en->have_preedit = EINA_TRUE;
3549
3550         /* set cursor position */
3551         evas_textblock_cursor_pos_set(en->cursor, preedit_start_pos + cursor_pos);
3552      }
3553
3554    _edje_entry_imf_cursor_info_set(en);
3555    _anchors_get(en->cursor, rp->object, en);
3556    _edje_emit(rp->edje, "preedit,changed", rp->part->name);
3557    _edje_emit(ed, "cursor,changed", rp->part->name);
3558
3559    /* delete attribute list */
3560    if (attrs)
3561      {
3562         EINA_LIST_FREE(attrs, attr) free(attr);
3563      }
3564
3565    free(preedit_string);
3566 }
3567
3568 static void
3569 _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, void *event_info)
3570 {
3571    Edje *ed = data;
3572    Edje_Real_Part *rp = ed->focused_part;
3573    Entry *en;
3574    Ecore_IMF_Event_Delete_Surrounding *ev = event_info;
3575    Evas_Textblock_Cursor *del_start, *del_end;
3576    int cursor_pos;
3577
3578    if ((!rp) || (!ev)) return;
3579    en = rp->entry_data;
3580    if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3581        (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3582      return;
3583
3584    cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
3585
3586    del_start = evas_object_textblock_cursor_new(en->rp->object);
3587    evas_textblock_cursor_pos_set(del_start, cursor_pos + ev->offset);
3588
3589    del_end = evas_object_textblock_cursor_new(en->rp->object);
3590    evas_textblock_cursor_pos_set(del_end, cursor_pos + ev->offset + ev->n_chars);
3591
3592    evas_textblock_cursor_range_delete(del_start, del_end);
3593
3594    evas_textblock_cursor_free(del_start);
3595    evas_textblock_cursor_free(del_end);
3596 }
3597 #endif
3598
3599 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/