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