1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_LAYOUT_CALC_PROTECTED
6 #define EFL_ACCESS_OBJECT_PROTECTED
7 #define EFL_ACCESS_TEXT_PROTECTED
8 #define EFL_ACCESS_EDITABLE_TEXT_PROTECTED
9 #define ELM_LAYOUT_PROTECTED
10 #define EFL_UI_FOCUS_OBJECT_PROTECTED
11 #define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED 1
12 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
13 #define EFL_PART_PROTECTED
14 
15 #include <Elementary.h>
16 #include <Elementary_Cursor.h>
17 #include "elm_priv.h"
18 #include "elm_widget_entry.h"
19 
20 #include "elm_entry_part.eo.h"
21 #include "elm_part_helper.h"
22 #include "elm_hoversel_eo.h"
23 
24 #define MY_CLASS ELM_ENTRY_CLASS
25 #define MY_CLASS_PFX elm_entry
26 
27 #define MY_CLASS_NAME "Elm_Entry"
28 #define MY_CLASS_NAME_LEGACY "elm_entry"
29 
30 /* Maximum chunk size to be inserted to the entry at once
31  * FIXME: This size is arbitrary, should probably choose a better size.
32  * Possibly also find a way to set it to a low value for weak computers,
33  * and to a big value for better computers. */
34 #define ELM_ENTRY_CHUNK_SIZE 10000
35 #define ELM_ENTRY_DELAY_WRITE_TIME 2.0
36 
37 #define ELM_PRIV_ENTRY_SIGNALS(cmd) \
38    cmd(SIG_ABORTED, "aborted", "") \
39    cmd(SIG_ACTIVATED, "activated", "") \
40    cmd(SIG_ANCHOR_CLICKED, "anchor,clicked", "") \
41    cmd(SIG_ANCHOR_DOWN, "anchor,down", "") \
42    cmd(SIG_ANCHOR_HOVER_OPENED, "anchor,hover,opened", "") \
43    cmd(SIG_ANCHOR_IN, "anchor,in", "") \
44    cmd(SIG_ANCHOR_OUT, "anchor,out", "") \
45    cmd(SIG_ANCHOR_UP, "anchor,up", "") \
46    cmd(SIG_CHANGED, "changed", "") \
47    cmd(SIG_CHANGED_USER, "changed,user", "") \
48    cmd(SIG_CLICKED, "clicked", "") \
49    cmd(SIG_CLICKED_DOUBLE, "clicked,double", "") \
50    cmd(SIG_CLICKED_TRIPLE, "clicked,triple", "") \
51    cmd(SIG_CURSOR_CHANGED, "cursor,changed", "") \
52    cmd(SIG_CURSOR_CHANGED_MANUAL, "cursor,changed,manual", "") \
53    cmd(SIG_FOCUSED, "focused", "") \
54    cmd(SIG_UNFOCUSED, "unfocused", "") \
55    cmd(SIG_LONGPRESSED, "longpressed", "") \
56    cmd(SIG_MAX_LENGTH, "maxlength,reached", "") \
57    cmd(SIG_PREEDIT_CHANGED, "preedit,changed", "") \
58    cmd(SIG_PRESS, "press", "") \
59    cmd(SIG_REDO_REQUEST, "redo,request", "") \
60    cmd(SIG_SELECTION_CHANGED, "selection,changed", "") \
61    cmd(SIG_SELECTION_CLEARED, "selection,cleared", "") \
62    cmd(SIG_SELECTION_COPY, "selection,copy", "") \
63    cmd(SIG_SELECTION_CUT, "selection,cut", "") \
64    cmd(SIG_SELECTION_PASTE, "selection,paste", "") \
65    cmd(SIG_SELECTION_START, "selection,start", "") \
66    cmd(SIG_TEXT_SET_DONE, "text,set,done", "") \
67    cmd(SIG_THEME_CHANGED, "theme,changed", "") \
68    cmd(SIG_UNDO_REQUEST, "undo,request", "") \
69    cmd(SIG_REJECTED, "rejected", "")
70 
71 ELM_PRIV_ENTRY_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
72 
73 #define ENTRY_PASSWORD_MASK_CHARACTER 0x002A
74 
75 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
76    ELM_PRIV_ENTRY_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
77    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
78    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
79    {NULL, NULL}
80 };
81 #undef ELM_PRIV_ENTRY_SIGNALS
82 
83 static const Elm_Layout_Part_Alias_Description _text_aliases[] =
84 {
85    {"default", "elm.text"},
86    {"guide", "elm.guide"},
87    {NULL, NULL}
88 };
89 
90 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
91 {
92    {"icon", "elm.swallow.icon"},
93    {"end", "elm.swallow.end"},
94    {NULL, NULL}
95 };
96 
97 static Eina_List *entries = NULL;
98 
99 struct _Mod_Api
100 {
101    void (*obj_hook)(Evas_Object *obj);
102    void (*obj_unhook)(Evas_Object *obj);
103    void (*obj_longpress)(Evas_Object *obj);
104 };
105 
106 static void _create_selection_handlers(Evas_Object *obj, Elm_Entry_Data *sd);
107 static void _magnifier_move(void *data);
108 
109 static Evas_Object *
_entry_win_get(Evas_Object * obj)110 _entry_win_get(Evas_Object *obj)
111 {
112    Evas_Object *top;
113    top = elm_widget_top_get(obj);
114    if ((!elm_win_window_id_get(top)) && (elm_win_type_get(top) == ELM_WIN_INLINED_IMAGE))
115      top = efl_ui_win_inlined_parent_get(top);
116    return top;
117 }
118 
119 static Mod_Api *
_module_find(Evas_Object * obj EINA_UNUSED)120 _module_find(Evas_Object *obj EINA_UNUSED)
121 {
122    static Elm_Module *m = NULL;
123 
124    if (m) goto ok;  // already found - just use
125    if (!(m = _elm_module_find_as("entry/api"))) return NULL;
126    // get module api
127    m->api = malloc(sizeof(Mod_Api));
128    if (!m->api) return NULL;
129 
130    ((Mod_Api *)(m->api))->obj_hook = // called on creation
131      _elm_module_symbol_get(m, "obj_hook");
132    ((Mod_Api *)(m->api))->obj_unhook = // called on deletion
133      _elm_module_symbol_get(m, "obj_unhook");
134    ((Mod_Api *)(m->api))->obj_longpress = // called on long press menu
135      _elm_module_symbol_get(m, "obj_longpress");
136 ok: // ok - return api
137    return m->api;
138 }
139 
140 static char *
_file_load(Eo * obj)141 _file_load(Eo *obj)
142 {
143    Eina_File *f;
144    char *text = NULL;
145    void *tmp = NULL;
146    size_t size;
147 
148    f = eina_file_dup(efl_file_mmap_get(obj));
149    size = eina_file_size_get(f);
150    if (size)
151      {
152         tmp = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
153         if (!tmp) goto on_error;
154      }
155 
156    text = malloc(size + 1);
157    if (!text) goto on_error;
158 
159    if (size)
160      memcpy(text, tmp, size);
161    text[size] = 0;
162 
163    if (eina_file_map_faulted(f, tmp))
164      {
165         ELM_SAFE_FREE(text, free);
166      }
167 
168  on_error:
169    if (tmp) eina_file_map_free(f, tmp);
170    eina_file_close(f);
171 
172    return text;
173 }
174 
175 static char *
_plain_load(Eo * obj)176 _plain_load(Eo *obj)
177 {
178    char *text;
179 
180    text = _file_load(obj);
181    if (text)
182      {
183         char *text2;
184 
185         text2 = elm_entry_utf8_to_markup(text);
186         free(text);
187         return text2;
188      }
189 
190    return NULL;
191 }
192 
193 static Eina_Error
_load_do(Evas_Object * obj)194 _load_do(Evas_Object *obj)
195 {
196    char *text;
197    Eina_Bool fail = EINA_FALSE;
198    Eina_Error err = 0;
199 
200    ELM_ENTRY_DATA_GET(obj, sd);
201 
202    if (!sd->file)
203      {
204         elm_object_text_set(obj, "");
205         return 0;
206      }
207 
208    switch (sd->format)
209      {
210       case ELM_TEXT_FORMAT_PLAIN_UTF8:
211         text = _plain_load(obj);
212         fail = !text;
213         break;
214 
215       case ELM_TEXT_FORMAT_MARKUP_UTF8:
216         text = _file_load(obj);
217         fail = !text;
218         break;
219 
220       default:
221         text = NULL;
222         err = EINVAL;
223         break;
224      }
225    if (fail)
226      {
227         err = errno;
228         /* FIXME: this is more like a hint but not totally accurate... */
229         if (!err) err = ENOENT;
230      }
231 
232    if (text)
233      {
234         elm_object_text_set(obj, text);
235         free(text);
236 
237         return 0;
238      }
239    elm_object_text_set(obj, "");
240 
241    return err;
242 }
243 
244 static void
_utf8_markup_save(const char * file,const char * text)245 _utf8_markup_save(const char *file,
246                   const char *text)
247 {
248    FILE *f;
249 
250    if (!text)
251      {
252         ecore_file_unlink(file);
253         return;
254      }
255 
256    f = fopen(file, "wb");
257    if (!f)
258      {
259         ERR("Failed to open %s for writing", file);
260         return;
261      }
262 
263    if (fputs(text, f) == EOF)
264      ERR("Failed to write text to file %s", file);
265    fclose(f);
266 }
267 
268 static void
_utf8_plain_save(const char * file,const char * text)269 _utf8_plain_save(const char *file,
270                  const char *text)
271 {
272    char *text2;
273 
274    text2 = elm_entry_markup_to_utf8(text);
275    if (!text2)
276      return;
277 
278    _utf8_markup_save(file, text2);
279    free(text2);
280 }
281 
282 static void
_save_do(Evas_Object * obj)283 _save_do(Evas_Object *obj)
284 {
285    ELM_ENTRY_DATA_GET(obj, sd);
286 
287    if (!efl_file_loaded_get(obj)) return;
288    switch (sd->format)
289      {
290       case ELM_TEXT_FORMAT_PLAIN_UTF8:
291         _utf8_plain_save(sd->file, elm_object_text_get(obj));
292         break;
293 
294       case ELM_TEXT_FORMAT_MARKUP_UTF8:
295         _utf8_markup_save(sd->file, elm_object_text_get(obj));
296         break;
297 
298       default:
299         break;
300      }
301 }
302 
303 static Eina_Bool
_delay_write(void * data)304 _delay_write(void *data)
305 {
306    ELM_ENTRY_DATA_GET(data, sd);
307 
308    _save_do(data);
309    sd->delay_write = NULL;
310 
311    return ECORE_CALLBACK_CANCEL;
312 }
313 
314 static void
_elm_entry_guide_update(Evas_Object * obj,Eina_Bool has_text)315 _elm_entry_guide_update(Evas_Object *obj,
316                         Eina_Bool has_text)
317 {
318    ELM_ENTRY_DATA_GET(obj, sd);
319 
320    if ((has_text) && (!sd->has_text))
321      edje_object_signal_emit(sd->entry_edje, "elm,guide,disabled", "elm");
322    else if ((!has_text) && (sd->has_text))
323      edje_object_signal_emit(sd->entry_edje, "elm,guide,enabled", "elm");
324 
325    sd->has_text = has_text;
326 }
327 
328 static void
_validate(Evas_Object * obj)329 _validate(Evas_Object *obj)
330 {
331    ELM_ENTRY_DATA_GET(obj, sd);
332    Eina_Bool res;
333    Elm_Validate_Content vc;
334    Eina_Strbuf *buf;
335 
336    if (sd->validators == 0) return;
337 
338    vc.text = edje_object_part_text_get(sd->entry_edje, "elm.text");
339    res = efl_event_callback_legacy_call(obj, ELM_ENTRY_EVENT_VALIDATE, (void *)&vc);
340    buf = eina_strbuf_new();
341    eina_strbuf_append_printf(buf, "validation,%s,%s", vc.signal, res == EINA_FALSE ? "fail" : "pass");
342    edje_object_signal_emit(sd->scr_edje, eina_strbuf_string_get(buf), "elm");
343    eina_tmpstr_del(vc.signal);
344    eina_strbuf_free(buf);
345 }
346 
347 static Elm_Entry_Markup_Filter *
_filter_new(Elm_Entry_Filter_Cb func,void * data)348 _filter_new(Elm_Entry_Filter_Cb func,
349             void *data)
350 {
351    Elm_Entry_Markup_Filter *tf = ELM_NEW(Elm_Entry_Markup_Filter);
352 
353    if (!tf) return NULL;
354 
355    tf->func = func;
356    tf->orig_data = data;
357    if (func == elm_entry_filter_limit_size)
358      {
359         Elm_Entry_Filter_Limit_Size *lim = data, *lim2;
360 
361         if (!data)
362           {
363              free(tf);
364 
365              return NULL;
366           }
367 
368         lim2 = malloc(sizeof(Elm_Entry_Filter_Limit_Size));
369         if (!lim2)
370           {
371              free(tf);
372 
373              return NULL;
374           }
375         memcpy(lim2, lim, sizeof(Elm_Entry_Filter_Limit_Size));
376         tf->data = lim2;
377      }
378    else if (func == elm_entry_filter_accept_set)
379      {
380         Elm_Entry_Filter_Accept_Set *as = data, *as2;
381 
382         if (!data)
383           {
384              free(tf);
385 
386              return NULL;
387           }
388         as2 = malloc(sizeof(Elm_Entry_Filter_Accept_Set));
389         if (!as2)
390           {
391              free(tf);
392 
393              return NULL;
394           }
395         if (as->accepted)
396           as2->accepted = eina_stringshare_add(as->accepted);
397         else
398           as2->accepted = NULL;
399         if (as->rejected)
400           as2->rejected = eina_stringshare_add(as->rejected);
401         else
402           as2->rejected = NULL;
403         tf->data = as2;
404      }
405    else
406      tf->data = data;
407    return tf;
408 }
409 
410 static void
_filter_free(Elm_Entry_Markup_Filter * tf)411 _filter_free(Elm_Entry_Markup_Filter *tf)
412 {
413    if (tf->func == elm_entry_filter_limit_size)
414      {
415         Elm_Entry_Filter_Limit_Size *lim = tf->data;
416 
417         free(lim);
418      }
419    else if (tf->func == elm_entry_filter_accept_set)
420      {
421         Elm_Entry_Filter_Accept_Set *as = tf->data;
422 
423         if (as)
424           {
425              eina_stringshare_del(as->accepted);
426              eina_stringshare_del(as->rejected);
427 
428              free(as);
429           }
430      }
431    free(tf);
432 }
433 
434 static void
_mirrored_set(Evas_Object * obj,Eina_Bool rtl)435 _mirrored_set(Evas_Object *obj,
436               Eina_Bool rtl)
437 {
438    ELM_ENTRY_DATA_GET(obj, sd);
439 
440    edje_object_mirrored_set(sd->entry_edje, rtl);
441 
442    if (sd->anchor_hover.hover)
443      efl_ui_mirrored_set(sd->anchor_hover.hover, rtl);
444 }
445 
446 static void
_hide_selection_handler(Evas_Object * obj)447 _hide_selection_handler(Evas_Object *obj)
448 {
449    ELM_ENTRY_DATA_GET(obj, sd);
450 
451    if (!sd->start_handler) return;
452 
453    if (sd->start_handler_shown)
454      {
455         edje_object_signal_emit(sd->start_handler, "elm,handler,hide", "elm");
456         sd->start_handler_shown = EINA_FALSE;
457      }
458    if (sd->end_handler_shown)
459      {
460         edje_object_signal_emit(sd->end_handler, "elm,handler,hide", "elm");
461         sd->end_handler_shown = EINA_FALSE;
462      }
463 }
464 
465 static Eina_Rectangle *
_viewport_region_get(Evas_Object * obj)466 _viewport_region_get(Evas_Object *obj)
467 {
468    ELM_ENTRY_DATA_GET(obj, sd);
469    Eina_Rectangle *rect = eina_rectangle_new(0, 0, 0, 0);
470    Evas_Object *parent;
471 
472    if (!rect) return NULL;
473    if (sd->scroll)
474      elm_interface_scrollable_content_viewport_geometry_get
475            (obj, &rect->x, &rect->y, &rect->w, &rect->h);
476    else
477      evas_object_geometry_get(sd->entry_edje, &rect->x, &rect->y, &rect->w, &rect->h);
478 
479    parent = elm_widget_parent_get(obj);
480    while (parent)
481      {
482         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
483           {
484              Eina_Rectangle r;
485              EINA_RECTANGLE_SET(&r, 0, 0, 0, 0);
486              evas_object_geometry_get(parent, &r.x, &r.y, &r.w, &r.h);
487              if (!eina_rectangle_intersection(rect, &r))
488                {
489                   rect->x = rect->y = rect->w = rect->h = 0;
490                   break;
491                }
492           }
493         parent = elm_widget_parent_get(parent);
494      }
495 
496    return rect;
497 }
498 
499 static void
_update_selection_handler(Evas_Object * obj)500 _update_selection_handler(Evas_Object *obj)
501 {
502    ELM_ENTRY_DATA_GET(obj, sd);
503 
504    Evas_Coord sx, sy, sh;
505    Evas_Coord ent_x, ent_y;
506    Evas_Coord ex, ey, eh;
507    int start_pos, end_pos, last_pos;
508 
509    if (!sd->sel_handler_disabled)
510      {
511         Eina_Rectangle *rect;
512         Evas_Coord hx, hy;
513         Eina_Bool hidden = EINA_FALSE;
514 
515         if (!sd->start_handler)
516           _create_selection_handlers(obj, sd);
517 
518         rect = _viewport_region_get(obj);
519         start_pos = edje_object_part_text_cursor_pos_get
520            (sd->entry_edje, "elm.text", EDJE_CURSOR_SELECTION_BEGIN);
521         end_pos = edje_object_part_text_cursor_pos_get
522            (sd->entry_edje, "elm.text", EDJE_CURSOR_SELECTION_END);
523 
524         evas_object_geometry_get(sd->entry_edje, &ent_x, &ent_y, NULL, NULL);
525         last_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
526                                                         EDJE_CURSOR_MAIN);
527         edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
528                                              EDJE_CURSOR_MAIN, start_pos);
529         edje_object_part_text_cursor_geometry_get(sd->entry_edje, "elm.text",
530                                                   &sx, &sy, NULL, &sh);
531         edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
532                                              EDJE_CURSOR_MAIN, end_pos);
533         edje_object_part_text_cursor_geometry_get(sd->entry_edje, "elm.text",
534                                                   &ex, &ey, NULL, &eh);
535         edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
536                                              EDJE_CURSOR_MAIN, last_pos);
537         if (start_pos < end_pos)
538           {
539              hx = ent_x + sx;
540              hy = ent_y + sy + sh;
541              evas_object_move(sd->start_handler, hx, hy);
542           }
543         else
544           {
545              hx = ent_x + ex;
546              hy = ent_y + ey + eh;
547              evas_object_move(sd->start_handler, hx, hy);
548           }
549         if (!eina_rectangle_xcoord_inside(rect, hx) ||
550             !eina_rectangle_ycoord_inside(rect, hy))
551           {
552              hidden = EINA_TRUE;
553           }
554         if (!sd->start_handler_shown && !hidden)
555           {
556              edje_object_signal_emit(sd->start_handler,
557                                      "elm,handler,show", "elm");
558              sd->start_handler_shown = EINA_TRUE;
559           }
560         else if (sd->start_handler_shown && hidden)
561           {
562              edje_object_signal_emit(sd->start_handler,
563                                      "elm,handler,hide", "elm");
564              sd->start_handler_shown = EINA_FALSE;
565           }
566 
567         hidden = EINA_FALSE;
568         if (start_pos < end_pos)
569           {
570              hx = ent_x + ex;
571              hy = ent_y + ey + eh;
572              evas_object_move(sd->end_handler, hx, hy);
573           }
574         else
575           {
576              hx = ent_x + sx;
577              hy = ent_y + sy + sh;
578              evas_object_move(sd->end_handler, hx, hy);
579           }
580         if (!eina_rectangle_xcoord_inside(rect, hx) ||
581             !eina_rectangle_ycoord_inside(rect, hy))
582           {
583              hidden = EINA_TRUE;
584           }
585         if (!sd->end_handler_shown && !hidden)
586           {
587              edje_object_signal_emit(sd->end_handler,
588                                      "elm,handler,show", "elm");
589              sd->end_handler_shown = EINA_TRUE;
590           }
591         else if (sd->end_handler_shown && hidden)
592           {
593              edje_object_signal_emit(sd->end_handler,
594                                      "elm,handler,hide", "elm");
595              sd->end_handler_shown = EINA_FALSE;
596           }
597         eina_rectangle_free(rect);
598      }
599    else
600      {
601         if (sd->start_handler_shown)
602           {
603              edje_object_signal_emit(sd->start_handler,
604                                      "elm,handler,hide", "elm");
605              sd->start_handler_shown = EINA_FALSE;
606           }
607         if (sd->end_handler_shown)
608           {
609              edje_object_signal_emit(sd->end_handler,
610                                      "elm,handler,hide", "elm");
611              sd->end_handler_shown = EINA_FALSE;
612           }
613      }
614 }
615 
616 static const char *
_elm_entry_theme_group_get(Evas_Object * obj)617 _elm_entry_theme_group_get(Evas_Object *obj)
618 {
619    ELM_ENTRY_DATA_GET(obj, sd);
620 
621    if (sd->editable)
622      {
623         if (sd->password) return "base-password";
624         else
625           {
626              if (sd->single_line) return "base-single";
627              else
628                {
629                   switch (sd->line_wrap)
630                     {
631                      case ELM_WRAP_CHAR:
632                        return "base-charwrap";
633 
634                      case ELM_WRAP_WORD:
635                        return "base";
636 
637                      case ELM_WRAP_MIXED:
638                        return "base-mixedwrap";
639 
640                      case ELM_WRAP_NONE:
641                      default:
642                        return "base-nowrap";
643                     }
644                }
645           }
646      }
647    else
648      {
649         if (sd->password) return "base-password";
650         else
651           {
652              if (sd->single_line) return "base-single-noedit";
653              else
654                {
655                   switch (sd->line_wrap)
656                     {
657                      case ELM_WRAP_CHAR:
658                        return "base-noedit-charwrap";
659 
660                      case ELM_WRAP_WORD:
661                        return "base-noedit";
662 
663                      case ELM_WRAP_MIXED:
664                        return "base-noedit-mixedwrap";
665 
666                      case ELM_WRAP_NONE:
667                      default:
668                        return "base-nowrap-noedit";
669                     }
670                }
671           }
672      }
673 }
674 
675 static void
_edje_entry_user_insert(Evas_Object * obj,const char * data)676 _edje_entry_user_insert(Evas_Object *obj, const char *data)
677 {
678    if (!data) return;
679    ELM_ENTRY_DATA_GET(obj, sd);
680 
681    sd->changed = EINA_TRUE;
682    edje_object_part_text_user_insert(sd->entry_edje, "elm.text", data);
683    elm_layout_sizing_eval(obj);
684 }
685 
686 static Eina_Bool
_selection_data_cb(void * data EINA_UNUSED,Evas_Object * obj,Elm_Selection_Data * sel_data)687 _selection_data_cb(void *data EINA_UNUSED,
688                    Evas_Object *obj,
689                    Elm_Selection_Data *sel_data)
690 {
691    char *buf;
692 
693    if (!sel_data->data) return EINA_FALSE;
694    ELM_ENTRY_DATA_GET(obj, sd);
695 
696    buf = malloc(sel_data->len + 1);
697    if (!buf)
698      {
699         ERR("Failed to allocate memory, obj: %p", obj);
700         return EINA_FALSE;
701      }
702    memcpy(buf, sel_data->data, sel_data->len);
703    buf[sel_data->len] = '\0';
704 
705    if ((sel_data->format & ELM_SEL_FORMAT_IMAGE) &&
706        (sd->cnp_mode != ELM_CNP_MODE_NO_IMAGE))
707      {
708         char *entry_tag;
709         int len;
710         static const char *tag_string =
711            "<item absize=240x180 href=file://%s></item>";
712 
713         len = strlen(tag_string) + strlen(buf);
714         entry_tag = alloca(len + 1);
715         snprintf(entry_tag, len + 1, tag_string, buf);
716         _edje_entry_user_insert(obj, entry_tag);
717      }
718    else if (sd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
719      {
720         char *txt = _elm_util_text_to_mkup(buf);
721         if (txt)
722           {
723              _edje_entry_user_insert(obj, txt);
724              free(txt);
725           }
726         else
727           {
728              ERR("Failed to convert text to markup text!");
729           }
730      }
731    else
732      {
733         if (!(sel_data->format & ELM_SEL_FORMAT_MARKUP))
734           {
735              char *txt = _elm_util_text_to_mkup(buf);
736              if (txt)
737                {
738                   _edje_entry_user_insert(obj, txt);
739                   free(txt);
740                }
741           }
742         else
743         _edje_entry_user_insert(obj, buf);
744      }
745    free(buf);
746 
747    return EINA_TRUE;
748 }
749 
750 static void
_dnd_enter_cb(void * data EINA_UNUSED,Evas_Object * obj)751 _dnd_enter_cb(void *data EINA_UNUSED,
752               Evas_Object *obj)
753 {
754    elm_object_focus_set(obj, EINA_TRUE);
755 }
756 
757 static void
_dnd_leave_cb(void * data EINA_UNUSED,Evas_Object * obj)758 _dnd_leave_cb(void *data EINA_UNUSED,
759               Evas_Object *obj)
760 {
761    if (_elm_config->desktop_entry)
762      elm_object_focus_set(obj, EINA_FALSE);
763 }
764 
765 static void
_dnd_pos_cb(void * data EINA_UNUSED,Evas_Object * obj,Evas_Coord x,Evas_Coord y,Elm_Xdnd_Action action EINA_UNUSED)766 _dnd_pos_cb(void *data EINA_UNUSED,
767             Evas_Object *obj,
768             Evas_Coord x,
769             Evas_Coord y,
770             Elm_Xdnd_Action action EINA_UNUSED)
771 {
772    int pos;
773    Evas_Coord ox, oy, ex, ey;
774 
775    ELM_ENTRY_DATA_GET(obj, sd);
776 
777    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
778    evas_object_geometry_get(sd->entry_edje, &ex, &ey, NULL, NULL);
779    x = x + ox - ex;
780    y = y + oy - ey;
781 
782    edje_object_part_text_cursor_coord_set
783       (sd->entry_edje, "elm.text", EDJE_CURSOR_USER, x, y);
784    pos = edje_object_part_text_cursor_pos_get
785       (sd->entry_edje, "elm.text", EDJE_CURSOR_USER);
786    edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
787                                         EDJE_CURSOR_MAIN, pos);
788 }
789 
790 static Eina_Bool
_dnd_drop_cb(void * data EINA_UNUSED,Evas_Object * obj,Elm_Selection_Data * drop)791 _dnd_drop_cb(void *data EINA_UNUSED,
792               Evas_Object *obj,
793               Elm_Selection_Data *drop)
794 {
795    Eina_Bool rv;
796 
797    ELM_ENTRY_DATA_GET(obj, sd);
798 
799    rv = edje_object_part_text_cursor_coord_set
800        (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN, drop->x, drop->y);
801 
802    if (!rv) WRN("Warning: Failed to position cursor: paste anyway");
803 
804    rv = _selection_data_cb(NULL, obj, drop);
805 
806    return rv;
807 }
808 
809 static Elm_Sel_Format
_get_drop_format(Evas_Object * obj)810 _get_drop_format(Evas_Object *obj)
811 {
812    ELM_ENTRY_DATA_GET(obj, sd);
813 
814    if ((sd->editable) && (!sd->single_line) && (!sd->password) && (!sd->disabled))
815      return ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE;
816    return ELM_SEL_FORMAT_MARKUP;
817 }
818 
819 static void
_flush_disabled_state(Eo * obj,Elm_Entry_Data * sd)820 _flush_disabled_state(Eo *obj, Elm_Entry_Data *sd)
821 {
822    const char *emission;
823    emission = efl_ui_widget_disabled_get(obj) ? "elm,state,disabled" : "elm,state,enabled";
824    edje_object_signal_emit(sd->entry_edje, emission, "elm");
825    if (sd->scroll)
826      {
827         edje_object_signal_emit(sd->scr_edje, emission, "elm");
828         elm_interface_scrollable_freeze_set(obj, efl_ui_widget_disabled_get(obj));
829      }
830 }
831 
832 /* we can't reuse layout's here, because it's on entry_edje only */
833 EOLIAN static void
_elm_entry_efl_ui_widget_disabled_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool disabled)834 _elm_entry_efl_ui_widget_disabled_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool disabled)
835 {
836 
837    efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
838 
839    elm_drop_target_del(obj, sd->drop_format,
840                        _dnd_enter_cb, NULL,
841                        _dnd_leave_cb, NULL,
842                        _dnd_pos_cb, NULL,
843                        _dnd_drop_cb, NULL);
844 
845    _flush_disabled_state(obj, sd);
846    sd->disabled = efl_ui_widget_disabled_get(obj);
847 
848    if (!efl_ui_widget_disabled_get(obj))
849      {
850         sd->drop_format = _get_drop_format(obj);
851         elm_drop_target_add(obj, sd->drop_format,
852                             _dnd_enter_cb, NULL,
853                             _dnd_leave_cb, NULL,
854                             _dnd_pos_cb, NULL,
855                             _dnd_drop_cb, NULL);
856      }
857 }
858 
859 /* It gets the background object from from_edje object and
860  * sets the background object to to_edje object.
861  * The background object has to be moved to proper Edje object
862  * when scrollable status is changed. */
863 static void
_elm_entry_background_switch(Evas_Object * from_edje,Evas_Object * to_edje)864 _elm_entry_background_switch(Evas_Object *from_edje, Evas_Object *to_edje)
865 {
866    Evas_Object *bg_obj;
867 
868    if (!from_edje || !to_edje) return;
869 
870    if (edje_object_part_exists(from_edje, "elm.swallow.background") &&
871        edje_object_part_exists(to_edje, "elm.swallow.background") &&
872        !edje_object_part_swallow_get(to_edje, "elm.swallow.background"))
873      {
874         bg_obj = edje_object_part_swallow_get(from_edje, "elm.swallow.background");
875 
876         if (bg_obj)
877           {
878              edje_object_part_unswallow(from_edje, bg_obj);
879              edje_object_part_swallow(to_edje, "elm.swallow.background", bg_obj);
880           }
881      }
882 }
883 
884 /* we can't issue the layout's theming code here, cause it assumes an
885  * unique edje object, always */
886 EOLIAN static Eina_Error
_elm_entry_efl_ui_widget_theme_apply(Eo * obj,Elm_Entry_Data * sd)887 _elm_entry_efl_ui_widget_theme_apply(Eo *obj, Elm_Entry_Data *sd)
888 {
889    const char *str;
890    const char *t;
891    const char *stl_user;
892    const char *style = elm_widget_style_get(obj);
893    Eina_Error theme_apply;
894    int cursor_pos;
895 
896    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_ERROR_GENERIC);
897 
898    // Note: We are skipping elm_layout here! This is by design.
899    // This assumes the following inheritance: my_class -> layout -> widget ...
900    theme_apply = efl_ui_widget_theme_apply(efl_cast(obj, EFL_UI_WIDGET_CLASS));
901    if (theme_apply == EFL_UI_THEME_APPLY_ERROR_GENERIC) return EFL_UI_THEME_APPLY_ERROR_GENERIC;
902 
903    evas_event_freeze(evas_object_evas_get(obj));
904 
905    edje_object_part_text_hide_visible_password(sd->entry_edje, "elm.text");
906 
907    edje_object_mirrored_set
908      (wd->resize_obj, efl_ui_mirrored_get(obj));
909 
910    edje_object_scale_set
911      (wd->resize_obj,
912      efl_gfx_entity_scale_get(obj) * elm_config_scale_get());
913    if (sd->scroll)
914      {
915         edje_object_scale_set
916            (sd->entry_edje,
917             efl_gfx_entity_scale_get(obj) * elm_config_scale_get());
918      }
919 
920    _mirrored_set(obj, efl_ui_mirrored_get(obj));
921 
922    stl_user = eina_stringshare_add(edje_object_part_text_style_user_peek(sd->entry_edje, "elm.text"));
923    t = eina_stringshare_add(elm_object_text_get(obj));
924 
925    elm_widget_theme_object_set
926      (obj, sd->entry_edje, "entry", _elm_entry_theme_group_get(obj), style);
927 
928    if (sd->sel_allow && _elm_config->desktop_entry)
929      edje_object_part_text_select_allow_set
930         (sd->entry_edje, "elm.text", EINA_TRUE);
931    else
932      edje_object_part_text_select_allow_set
933         (sd->entry_edje, "elm.text", EINA_FALSE);
934 
935    edje_object_part_text_style_user_push(sd->entry_edje, "elm.text", stl_user);
936    eina_stringshare_del(stl_user);
937 
938    cursor_pos = edje_object_part_text_cursor_pos_get
939                    (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
940 
941    if (cursor_pos != sd->cursor_pos)
942      {
943         sd->cursor_pos = cursor_pos;
944         sd->cur_changed = EINA_TRUE;
945      }
946 
947    elm_object_text_set(obj, t);
948    eina_stringshare_del(t);
949 
950    if (elm_widget_disabled_get(obj))
951      edje_object_signal_emit(sd->entry_edje, "elm,state,disabled", "elm");
952 
953    edje_object_part_text_input_panel_layout_set
954      (sd->entry_edje, "elm.text", (Edje_Input_Panel_Layout)sd->input_panel_layout);
955    edje_object_part_text_input_panel_layout_variation_set
956      (sd->entry_edje, "elm.text", sd->input_panel_layout_variation);
957    edje_object_part_text_autocapital_type_set
958      (sd->entry_edje, "elm.text", (Edje_Text_Autocapital_Type)sd->autocapital_type);
959    edje_object_part_text_prediction_allow_set
960      (sd->entry_edje, "elm.text", sd->prediction_allow);
961    edje_object_part_text_input_hint_set
962      (sd->entry_edje, "elm.text", (Edje_Input_Hints)sd->input_hints);
963    edje_object_part_text_input_panel_enabled_set
964      (sd->entry_edje, "elm.text", sd->input_panel_enable);
965    edje_object_part_text_input_panel_imdata_set
966      (sd->entry_edje, "elm.text", sd->input_panel_imdata,
967      sd->input_panel_imdata_len);
968    edje_object_part_text_input_panel_return_key_type_set
969      (sd->entry_edje, "elm.text", (Edje_Input_Panel_Return_Key_Type)sd->input_panel_return_key_type);
970    edje_object_part_text_input_panel_return_key_disabled_set
971      (sd->entry_edje, "elm.text", sd->input_panel_return_key_disabled);
972    edje_object_part_text_input_panel_show_on_demand_set
973      (sd->entry_edje, "elm.text", sd->input_panel_show_on_demand);
974    edje_object_part_text_prediction_hint_set
975      (sd->entry_edje, "elm.text", sd->prediction_hint);
976 
977    evas_object_ref(obj);
978 
979    if (cursor_pos) elm_entry_cursor_pos_set(obj, cursor_pos);
980 
981    if (efl_ui_focus_object_focus_get(obj))
982      {
983         edje_object_signal_emit(sd->entry_edje, "elm,action,focus", "elm");
984         if (sd->scroll)
985           edje_object_signal_emit(sd->scr_edje, "elm,action,focus", "elm");
986      }
987 
988    edje_object_message_signal_process(sd->entry_edje);
989 
990    Evas_Object* clip = evas_object_clip_get(sd->entry_edje);
991    evas_object_clip_set(sd->hit_rect, clip);
992 
993    if (sd->scroll)
994      {
995         Eina_Error err = EFL_UI_THEME_APPLY_ERROR_GENERIC;
996 
997         efl_ui_mirrored_set(obj, efl_ui_mirrored_get(obj));
998 
999         if (sd->single_line)
1000           err = elm_widget_theme_object_set
1001           (obj, sd->scr_edje, "scroller", "entry_single", style);
1002         if (err)
1003           elm_widget_theme_object_set
1004           (obj, sd->scr_edje, "scroller", "entry", style);
1005 
1006         elm_interface_scrollable_reset_signals(obj);
1007         _elm_entry_background_switch(sd->entry_edje, sd->scr_edje);
1008 
1009         str = edje_object_data_get(sd->scr_edje, "focus_highlight");
1010      }
1011    else
1012      {
1013         _elm_entry_background_switch(sd->scr_edje, sd->entry_edje);
1014 
1015         str = edje_object_data_get(sd->entry_edje, "focus_highlight");
1016      }
1017 
1018    if ((str) && (!strcmp(str, "on")))
1019      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
1020    else
1021      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
1022 
1023    if (sd->start_handler)
1024      {
1025         _elm_theme_object_set(obj, sd->start_handler,
1026                                     "entry", "handler/start", style);
1027         _elm_theme_object_set(obj, sd->end_handler,
1028                                     "entry", "handler/end", style);
1029      }
1030    elm_entry_icon_visible_set(obj, EINA_TRUE);
1031    elm_entry_end_visible_set(obj, EINA_TRUE);
1032 
1033    if (sd->scroll)
1034      efl_layout_signal_emit(sd->entry_edje, "elm,scroll,enable", "elm");
1035    else
1036      efl_layout_signal_emit(sd->entry_edje, "elm,scroll,disable", "elm");
1037 
1038    sd->changed = EINA_TRUE;
1039    elm_layout_sizing_eval(obj);
1040 
1041    sd->has_text = !sd->has_text;
1042    _elm_entry_guide_update(obj, !sd->has_text);
1043    evas_event_thaw(evas_object_evas_get(obj));
1044    evas_event_thaw_eval(evas_object_evas_get(obj));
1045 
1046    efl_event_callback_legacy_call(obj, EFL_UI_LAYOUT_EVENT_THEME_CHANGED, NULL);
1047 
1048    evas_object_unref(obj);
1049 
1050    _flush_disabled_state(obj, sd);
1051 
1052    return theme_apply;
1053 }
1054 
1055 static void
_cursor_geometry_recalc(Evas_Object * obj)1056 _cursor_geometry_recalc(Evas_Object *obj)
1057 {
1058    ELM_ENTRY_DATA_GET(obj, sd);
1059 
1060    if (!sd->deferred_recalc_job)
1061      {
1062         if (sd->cur_changed)
1063           {
1064              Eina_Rect sr = {};
1065 
1066              sd->cur_changed = EINA_FALSE;
1067              edje_object_part_text_cursor_geometry_get
1068                (sd->entry_edje, "elm.text", &sr.x, &sr.y, &sr.w, &sr.h);
1069              elm_widget_show_region_set(obj, sr, EINA_FALSE);
1070           }
1071      }
1072    else
1073      sd->deferred_cur = EINA_TRUE;
1074 }
1075 
1076 static void
_deferred_recalc_job(void * data)1077 _deferred_recalc_job(void *data)
1078 {
1079    Evas_Coord minh = -1, resw = -1, minw = -1, fw = 0, fh = 0;
1080 
1081    ELM_ENTRY_DATA_GET(data, sd);
1082 
1083    sd->deferred_recalc_job = NULL;
1084 
1085    evas_object_geometry_get(sd->entry_edje, NULL, NULL, &resw, NULL);
1086    edje_object_size_min_restricted_calc(sd->entry_edje, &minw, &minh, resw, 0);
1087    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1088 
1089    /* This is a hack to workaround the way min size hints are treated.
1090     * If the minimum width is smaller than the restricted width, it
1091     * means the minimum doesn't matter. */
1092    if (minw <= resw)
1093      {
1094         Evas_Coord ominw = -1;
1095 
1096         evas_object_size_hint_combined_min_get(data, &ominw, NULL);
1097         minw = ominw;
1098      }
1099 
1100    sd->ent_mw = minw;
1101    sd->ent_mh = minh;
1102 
1103    elm_coords_finger_size_adjust(1, &fw, 1, &fh);
1104    if (sd->scroll)
1105      {
1106         Evas_Coord vmw = 0, vmh = 0;
1107 
1108         edje_object_size_min_calc(sd->scr_edje, &vmw, &vmh);
1109         if (sd->single_line)
1110           {
1111              evas_object_size_hint_min_set(data, vmw, minh + vmh);
1112              evas_object_size_hint_max_set(data, -1, minh + vmh);
1113           }
1114         else
1115           {
1116              evas_object_size_hint_min_set(data, vmw, vmh);
1117              evas_object_size_hint_max_set(data, -1, -1);
1118           }
1119      }
1120    else
1121      {
1122         if (sd->single_line)
1123           {
1124              evas_object_size_hint_min_set(data, minw, minh);
1125              evas_object_size_hint_max_set(data, -1, minh);
1126           }
1127         else
1128           {
1129              evas_object_size_hint_min_set(data, fw, minh);
1130              evas_object_size_hint_max_set(data, -1, -1);
1131           }
1132      }
1133 
1134    if (sd->deferred_cur)
1135      {
1136         if (sd->cur_changed)
1137           {
1138              Eina_Rect sr = {};
1139 
1140              sd->cur_changed = EINA_FALSE;
1141              edje_object_part_text_cursor_geometry_get
1142                (sd->entry_edje, "elm.text", &sr.x, &sr.y, &sr.w, &sr.h);
1143              elm_widget_show_region_set(data, sr, EINA_FALSE);
1144           }
1145      }
1146 }
1147 
1148 EOLIAN static void
_elm_entry_efl_canvas_group_group_calculate(Eo * obj,Elm_Entry_Data * sd)1149 _elm_entry_efl_canvas_group_group_calculate(Eo *obj, Elm_Entry_Data *sd)
1150 {
1151    Evas_Coord minw = -1, minh = -1;
1152    Evas_Coord resw, resh;
1153 
1154    evas_object_geometry_get(obj, NULL, NULL, &resw, &resh);
1155 
1156    if (sd->line_wrap)
1157      {
1158         if ((resw == sd->last_w) && (!sd->changed))
1159           {
1160              if (sd->scroll)
1161                {
1162                   Evas_Coord vw = 0, vh = 0, w = 0, h = 0;
1163 
1164                   elm_interface_scrollable_content_viewport_geometry_get
1165                         (obj, NULL, NULL, &vw, &vh);
1166 
1167                   w = sd->ent_mw;
1168                   h = sd->ent_mh;
1169                   if (vw > sd->ent_mw) w = vw;
1170                   if (vh > sd->ent_mh) h = vh;
1171                   evas_object_resize(sd->entry_edje, w, h);
1172 
1173                   return;
1174                }
1175 
1176              return;
1177           }
1178 
1179         evas_event_freeze(evas_object_evas_get(obj));
1180         sd->changed = EINA_FALSE;
1181         sd->last_w = resw;
1182         if (sd->scroll)
1183           {
1184              Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
1185 
1186              evas_object_resize(sd->scr_edje, resw, resh);
1187              edje_object_size_min_calc(sd->scr_edje, &vmw, &vmh);
1188              elm_interface_scrollable_content_viewport_geometry_get
1189                    (obj, NULL, NULL, &vw, &vh);
1190              edje_object_size_min_restricted_calc
1191                (sd->entry_edje, &minw, &minh, vw, 0);
1192              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1193 
1194              /* This is a hack to workaround the way min size hints
1195               * are treated.  If the minimum width is smaller than the
1196               * restricted width, it means the minimum doesn't
1197               * matter. */
1198              if (minw <= vw)
1199                {
1200                   Evas_Coord ominw = -1;
1201 
1202                   evas_object_size_hint_combined_min_get(sd->entry_edje, &ominw, NULL);
1203                   minw = ominw;
1204                }
1205              sd->ent_mw = minw;
1206              sd->ent_mh = minh;
1207 
1208              if ((minw > 0) && (vw < minw)) vw = minw;
1209              if (minh > vh) vh = minh;
1210 
1211              if (sd->single_line) h = vmh + minh;
1212              else h = vmh;
1213 
1214              evas_object_resize(sd->entry_edje, vw, vh);
1215              evas_object_size_hint_min_set(obj, w, h);
1216 
1217              if (sd->single_line)
1218                evas_object_size_hint_max_set(obj, -1, h);
1219              else
1220                evas_object_size_hint_max_set(obj, -1, -1);
1221           }
1222         else
1223           {
1224              ecore_job_del(sd->deferred_recalc_job);
1225              sd->deferred_recalc_job =
1226                ecore_job_add(_deferred_recalc_job, obj);
1227           }
1228 
1229         evas_event_thaw(evas_object_evas_get(obj));
1230         evas_event_thaw_eval(evas_object_evas_get(obj));
1231      }
1232    else
1233      {
1234         if (!sd->changed) return;
1235         evas_event_freeze(evas_object_evas_get(obj));
1236         sd->changed = EINA_FALSE;
1237         sd->last_w = resw;
1238         if (sd->scroll)
1239           {
1240              Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
1241 
1242              edje_object_size_min_calc(sd->entry_edje, &minw, &minh);
1243              sd->ent_mw = minw;
1244              sd->ent_mh = minh;
1245              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1246 
1247              elm_interface_scrollable_content_viewport_geometry_get
1248                    (obj, NULL, NULL, &vw, &vh);
1249 
1250              if (minw > vw) vw = minw;
1251              if (minh > vh) vh = minh;
1252 
1253              evas_object_resize(sd->entry_edje, vw, vh);
1254              edje_object_size_min_calc(sd->scr_edje, &vmw, &vmh);
1255              if (sd->single_line) h = vmh + minh;
1256              else h = vmh;
1257 
1258              evas_object_size_hint_min_set(obj, w, h);
1259              if (sd->single_line)
1260                evas_object_size_hint_max_set(obj, -1, h);
1261              else
1262                evas_object_size_hint_max_set(obj, -1, -1);
1263           }
1264         else
1265           {
1266              edje_object_size_min_calc(sd->entry_edje, &minw, &minh);
1267              sd->ent_mw = minw;
1268              sd->ent_mh = minh;
1269              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1270              evas_object_size_hint_min_set(obj, minw, minh);
1271 
1272              if (sd->single_line)
1273                evas_object_size_hint_max_set(obj, -1, minh);
1274              else
1275                evas_object_size_hint_max_set(obj, -1, -1);
1276           }
1277         evas_event_thaw(evas_object_evas_get(obj));
1278         evas_event_thaw_eval(evas_object_evas_get(obj));
1279      }
1280 
1281    _cursor_geometry_recalc(obj);
1282 }
1283 
1284 static void
_return_key_enabled_check(Evas_Object * obj)1285 _return_key_enabled_check(Evas_Object *obj)
1286 {
1287    Eina_Bool return_key_disabled = EINA_FALSE;
1288 
1289    ELM_ENTRY_DATA_GET(obj, sd);
1290 
1291    if (!sd->auto_return_key) return;
1292 
1293    if (elm_entry_is_empty(obj) == EINA_TRUE)
1294      return_key_disabled = EINA_TRUE;
1295 
1296    elm_entry_input_panel_return_key_disabled_set(obj, return_key_disabled);
1297 }
1298 
1299 static void
_elm_entry_focus_update(Eo * obj,Elm_Entry_Data * sd)1300 _elm_entry_focus_update(Eo *obj, Elm_Entry_Data *sd)
1301 {
1302    Evas_Object *top;
1303    Eina_Bool top_is_win = EINA_FALSE;
1304 
1305    top = elm_widget_top_get(obj);
1306    if (top && efl_isa(top, EFL_UI_WIN_CLASS))
1307      top_is_win = EINA_TRUE;
1308 
1309    if (efl_ui_focus_object_focus_get(obj) && sd->editable)
1310      {
1311         evas_object_focus_set(sd->entry_edje, EINA_TRUE);
1312         edje_object_signal_emit(sd->entry_edje, "elm,action,focus", "elm");
1313         if (sd->scroll)
1314           edje_object_signal_emit(sd->scr_edje, "elm,action,focus", "elm");
1315 
1316         if (top && top_is_win && sd->input_panel_enable && !sd->input_panel_show_on_demand &&
1317             !edje_object_part_text_imf_context_get(sd->entry_edje, "elm.text"))
1318           elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
1319         if (_elm_config->atspi_mode)
1320           efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_FOCUSED, EINA_TRUE);
1321         _return_key_enabled_check(obj);
1322         _validate(obj);
1323      }
1324    else
1325      {
1326         edje_object_signal_emit(sd->entry_edje, "elm,action,unfocus", "elm");
1327         if (sd->scroll)
1328           edje_object_signal_emit(sd->scr_edje, "elm,action,unfocus", "elm");
1329         evas_object_focus_set(sd->entry_edje, EINA_FALSE);
1330         if (top && top_is_win && sd->input_panel_enable &&
1331             !edje_object_part_text_imf_context_get(sd->entry_edje, "elm.text"))
1332           elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
1333         if (_elm_config->atspi_mode)
1334           efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_FOCUSED, EINA_FALSE);
1335 
1336         if (_elm_config->selection_clear_enable)
1337           {
1338              if ((sd->have_selection) && (!sd->hoversel))
1339                {
1340                   sd->sel_mode = EINA_FALSE;
1341                   elm_widget_scroll_hold_pop(obj);
1342                   edje_object_part_text_select_allow_set(sd->entry_edje, "elm.text", EINA_FALSE);
1343                   edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
1344                   edje_object_part_text_select_none(sd->entry_edje, "elm.text");
1345                }
1346           }
1347         if (sd->scr_edje)
1348           edje_object_signal_emit(sd->scr_edje, "validation,default", "elm");
1349      }
1350 }
1351 
1352 EOLIAN static Eina_Bool
_elm_entry_efl_ui_focus_object_on_focus_update(Eo * obj,Elm_Entry_Data * sd)1353 _elm_entry_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Entry_Data *sd)
1354 {
1355    _elm_entry_focus_update(obj, sd);
1356 
1357    return EINA_TRUE;
1358 }
1359 
1360 EOLIAN static Eina_Rect
_elm_entry_efl_ui_widget_interest_region_get(const Eo * obj,Elm_Entry_Data * sd)1361 _elm_entry_efl_ui_widget_interest_region_get(const Eo *obj, Elm_Entry_Data *sd)
1362 {
1363    Evas_Coord cx, cy, cw, ch;
1364    Evas_Coord edx, edy;
1365    Evas_Coord elx, ely, elw, elh;
1366    Eina_Rect r;
1367 
1368    edje_object_part_text_cursor_geometry_get
1369      (sd->entry_edje, "elm.text", &cx, &cy, &cw, &ch);
1370 
1371    if (sd->single_line)
1372      {
1373         evas_object_geometry_get(sd->entry_edje, &edx, &edy, NULL, &ch);
1374         cy = 0;
1375      }
1376    else
1377      {
1378         evas_object_geometry_get(sd->entry_edje, &edx, &edy, NULL, NULL);
1379      }
1380    evas_object_geometry_get(obj, &elx, &ely, &elw, &elh);
1381 
1382    r.x = cx + edx - elx;
1383    if ((cw < elw) && (r.x + cw > elw)) r.x = elw - cw;
1384    r.y = cy + edy - ely;
1385    if ((ch < elh) && (r.y + ch > elh)) r.y = elh - ch;
1386    r.w = MAX(cw, 1);
1387    r.h = MAX(ch, 1);
1388 
1389    return r;
1390 }
1391 
1392 static void
_show_region_hook(void * data EINA_UNUSED,Evas_Object * obj,Eina_Rect r)1393 _show_region_hook(void *data EINA_UNUSED, Evas_Object *obj, Eina_Rect r)
1394 {
1395    elm_interface_scrollable_content_region_show(obj, r.x, r.y, r.w, r.h);
1396 }
1397 
1398 EOLIAN static Eina_Bool
_elm_entry_efl_ui_widget_widget_sub_object_del(Eo * obj,Elm_Entry_Data * sd,Evas_Object * sobj)1399 _elm_entry_efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Entry_Data *sd, Evas_Object *sobj)
1400 {
1401    Eina_Bool ret = EINA_FALSE;
1402    /* unfortunately entry doesn't follow the signal pattern
1403     * elm,state,icon,{visible,hidden}, so we have to replicate this
1404     * smart function */
1405    if (sobj == edje_object_part_swallow_get(sd->scr_edje, "elm.swallow.icon"))
1406      {
1407         edje_object_signal_emit(sd->scr_edje, "elm,action,hide,icon", "elm");
1408      }
1409    else if (sobj == edje_object_part_swallow_get(sd->scr_edje, "elm.swallow.end"))
1410      {
1411         edje_object_signal_emit(sd->scr_edje, "elm,action,hide,end", "elm");
1412      }
1413 
1414    ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj);
1415    if (!ret) return EINA_FALSE;
1416 
1417    return EINA_TRUE;
1418 }
1419 
1420 static void
_hoversel_position(Evas_Object * obj)1421 _hoversel_position(Evas_Object *obj)
1422 {
1423    Evas_Coord cx, cy, cw, ch, x, y, mw, mh, w, h;
1424 
1425    ELM_ENTRY_DATA_GET(obj, sd);
1426 
1427    cx = cy = 0;
1428    cw = ch = 1;
1429    evas_object_geometry_get(sd->entry_edje, &x, &y, &w, &h);
1430    if (sd->use_down)
1431      {
1432         cx = sd->downx - x;
1433         cy = sd->downy - y;
1434         cw = 1;
1435         ch = 1;
1436      }
1437    else
1438      edje_object_part_text_cursor_geometry_get
1439        (sd->entry_edje, "elm.text", &cx, &cy, &cw, &ch);
1440 
1441    if (efl_canvas_group_need_recalculate_get(sd->hoversel))
1442      efl_canvas_group_calculate(sd->hoversel);
1443    evas_object_size_hint_combined_min_get(sd->hoversel, &mw, &mh);
1444    if (cx + mw > w)
1445      cx = w - mw;
1446    if (cy + mh > h)
1447      cy = h - mh;
1448    evas_object_geometry_set(sd->hoversel, x + cx, y + cy, mw, mh);
1449 }
1450 
1451 static void
_hover_del_job(void * data)1452 _hover_del_job(void *data)
1453 {
1454    ELM_ENTRY_DATA_GET(data, sd);
1455 
1456    ELM_SAFE_FREE(sd->hoversel, evas_object_del);
1457    sd->hov_deljob = NULL;
1458 }
1459 
1460 static void
_hover_dismissed_cb(void * data,const Efl_Event * event EINA_UNUSED)1461 _hover_dismissed_cb(void *data, const Efl_Event *event EINA_UNUSED)
1462 {
1463    ELM_ENTRY_DATA_GET(data, sd);
1464 
1465    sd->use_down = 0;
1466    if (sd->hoversel) evas_object_hide(sd->hoversel);
1467    if (sd->sel_mode)
1468      {
1469         if (!_elm_config->desktop_entry)
1470           {
1471              if (!sd->password)
1472                edje_object_part_text_select_allow_set
1473                  (sd->entry_edje, "elm.text", EINA_TRUE);
1474           }
1475      }
1476    elm_widget_scroll_freeze_pop(data);
1477    ecore_job_del(sd->hov_deljob);
1478    sd->hov_deljob = ecore_job_add(_hover_del_job, data);
1479 }
1480 
1481 static void
_hover_selected_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1482 _hover_selected_cb(void *data,
1483                    Evas_Object *obj EINA_UNUSED,
1484                    void *event_info EINA_UNUSED)
1485 {
1486    ELM_ENTRY_DATA_GET(data, sd);
1487 
1488    if (!sd->sel_allow) return;
1489 
1490    sd->sel_mode = EINA_TRUE;
1491    edje_object_part_text_select_none(sd->entry_edje, "elm.text");
1492 
1493    if (!_elm_config->desktop_entry)
1494      {
1495         if (!sd->password)
1496           edje_object_part_text_select_allow_set
1497             (sd->entry_edje, "elm.text", EINA_TRUE);
1498      }
1499    edje_object_signal_emit(sd->entry_edje, "elm,state,select,on", "elm");
1500 
1501    if (!_elm_config->desktop_entry)
1502      elm_widget_scroll_hold_push(data);
1503 }
1504 
1505 static char *
_item_tags_remove(const char * str)1506 _item_tags_remove(const char *str)
1507 {
1508    char *ret;
1509    Eina_Strbuf *buf;
1510 
1511    if (!str)
1512      return NULL;
1513 
1514    buf = eina_strbuf_new();
1515    if (!buf)
1516      return NULL;
1517 
1518    if (!eina_strbuf_append(buf, str))
1519      {
1520         eina_strbuf_free(buf);
1521         return NULL;
1522      }
1523 
1524    while (EINA_TRUE)
1525      {
1526         const char *temp = eina_strbuf_string_get(buf);
1527         char *start_tag = NULL;
1528         char *end_tag = NULL;
1529         size_t sindex;
1530         size_t eindex;
1531 
1532         start_tag = strstr(temp, "<item");
1533         if (!start_tag)
1534           start_tag = strstr(temp, "</item");
1535         if (start_tag)
1536           end_tag = strstr(start_tag, ">");
1537         else
1538           break;
1539         if (!end_tag || start_tag > end_tag)
1540           break;
1541 
1542         sindex = start_tag - temp;
1543         eindex = end_tag - temp + 1;
1544         if (!eina_strbuf_remove(buf, sindex, eindex))
1545           break;
1546      }
1547 
1548    ret = eina_strbuf_string_steal(buf);
1549    eina_strbuf_free(buf);
1550 
1551    return ret;
1552 }
1553 
1554 void
_elm_entry_entry_paste(Evas_Object * obj,const char * entry)1555 _elm_entry_entry_paste(Evas_Object *obj,
1556                        const char *entry)
1557 {
1558    char *str = NULL;
1559 
1560    if (!entry) return;
1561 
1562    ELM_ENTRY_CHECK(obj);
1563    ELM_ENTRY_DATA_GET(obj, sd);
1564 
1565    if (!sd) return;
1566    if (sd->cnp_mode == ELM_CNP_MODE_NO_IMAGE)
1567      {
1568         str = _item_tags_remove(entry);
1569         if (!str) str = strdup(entry);
1570      }
1571    else
1572      str = strdup(entry);
1573    if (!str) str = (char *)entry;
1574 
1575    _edje_entry_user_insert(obj, str);
1576 
1577    if (str != entry) free(str);
1578 }
1579 
1580 static void
_paste_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1581 _paste_cb(void *data,
1582           Evas_Object *obj EINA_UNUSED,
1583           void *event_info EINA_UNUSED)
1584 {
1585    Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP;
1586 
1587    ELM_ENTRY_DATA_GET(data, sd);
1588 
1589    if (!sd) return;
1590    efl_event_callback_legacy_call
1591      (data, EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE, NULL);
1592 
1593    sd->selection_asked = EINA_TRUE;
1594 
1595    if (sd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
1596      formats = ELM_SEL_FORMAT_TEXT;
1597    else if (sd->cnp_mode != ELM_CNP_MODE_NO_IMAGE)
1598      formats |= ELM_SEL_FORMAT_IMAGE;
1599 
1600    elm_cnp_selection_get
1601      (data, ELM_SEL_TYPE_CLIPBOARD, formats, _selection_data_cb, NULL);
1602 }
1603 
1604 static void
_selection_clear(void * data,Elm_Sel_Type selection)1605 _selection_clear(void *data, Elm_Sel_Type selection)
1606 {
1607    ELM_ENTRY_DATA_GET(data, sd);
1608 
1609    if (!sd) return;
1610    if (!sd->have_selection) return;
1611    if ((selection == ELM_SEL_TYPE_CLIPBOARD) ||
1612        (selection == ELM_SEL_TYPE_PRIMARY))
1613      {
1614         elm_entry_select_none(data);
1615      }
1616 }
1617 
1618 static void
_selection_store(Elm_Sel_Type seltype,Evas_Object * obj)1619 _selection_store(Elm_Sel_Type seltype,
1620                  Evas_Object *obj)
1621 {
1622    const char *sel;
1623 
1624    ELM_ENTRY_DATA_GET(obj, sd);
1625 
1626    if (!sd) return;
1627    sel = edje_object_part_text_selection_get(sd->entry_edje, "elm.text");
1628    if ((!sel) || (!sel[0])) return;  /* avoid deleting our own selection */
1629 
1630    elm_cnp_selection_set
1631      (obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel) + 1);
1632    elm_cnp_selection_loss_callback_set(obj, seltype, _selection_clear, obj);
1633    if (seltype == ELM_SEL_TYPE_CLIPBOARD)
1634      eina_stringshare_replace(&sd->cut_sel, sel);
1635 }
1636 
1637 static void
_cut_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1638 _cut_cb(void *data,
1639         Evas_Object *obj EINA_UNUSED,
1640         void *event_info EINA_UNUSED)
1641 {
1642    ELM_ENTRY_DATA_GET(data, sd);
1643 
1644    if (!sd) return;
1645    efl_event_callback_legacy_call
1646      (data, EFL_UI_TEXTBOX_EVENT_SELECTION_CUT, NULL);
1647    /* Store it */
1648    sd->sel_mode = EINA_FALSE;
1649    if (!_elm_config->desktop_entry)
1650      edje_object_part_text_select_allow_set
1651        (sd->entry_edje, "elm.text", EINA_FALSE);
1652    edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
1653 
1654    if (!_elm_config->desktop_entry)
1655      elm_widget_scroll_hold_pop(data);
1656 
1657    _selection_store(ELM_SEL_TYPE_CLIPBOARD, data);
1658    _edje_entry_user_insert(data, "");
1659 }
1660 
1661 static void
_copy_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1662 _copy_cb(void *data,
1663          Evas_Object *obj EINA_UNUSED,
1664          void *event_info EINA_UNUSED)
1665 {
1666    ELM_ENTRY_DATA_GET(data, sd);
1667 
1668    if (!sd) return;
1669    efl_event_callback_legacy_call
1670      (data, EFL_UI_TEXTBOX_EVENT_SELECTION_COPY, NULL);
1671    sd->sel_mode = EINA_FALSE;
1672    if (!_elm_config->desktop_entry)
1673      {
1674         edje_object_part_text_select_allow_set
1675           (sd->entry_edje, "elm.text", EINA_FALSE);
1676         edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
1677         elm_widget_scroll_hold_pop(data);
1678      }
1679    _selection_store(ELM_SEL_TYPE_CLIPBOARD, data);
1680 }
1681 
1682 static void
_hover_cancel_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1683 _hover_cancel_cb(void *data,
1684                  Evas_Object *obj EINA_UNUSED,
1685                  void *event_info EINA_UNUSED)
1686 {
1687    ELM_ENTRY_DATA_GET(data, sd);
1688 
1689    if (!sd) return;
1690    sd->sel_mode = EINA_FALSE;
1691    if (!_elm_config->desktop_entry)
1692      edje_object_part_text_select_allow_set
1693        (sd->entry_edje, "elm.text", EINA_FALSE);
1694    edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
1695    if (!_elm_config->desktop_entry)
1696      elm_widget_scroll_hold_pop(data);
1697    edje_object_part_text_select_none(sd->entry_edje, "elm.text");
1698 }
1699 
1700 static void
_hover_item_clicked_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1701 _hover_item_clicked_cb(void *data,
1702                        Evas_Object *obj EINA_UNUSED,
1703                        void *event_info EINA_UNUSED)
1704 {
1705    Elm_Entry_Context_Menu_Item *it = data;
1706    if (!it) return;
1707 
1708    if (it->func) it->func(it->data, it->obj, it);
1709 }
1710 
1711 static void
_menu_call(Evas_Object * obj)1712 _menu_call(Evas_Object *obj)
1713 {
1714    Evas_Object *top;
1715    const Eina_List *l;
1716    const Elm_Entry_Context_Menu_Item *it;
1717 
1718    ELM_ENTRY_DATA_GET(obj, sd);
1719 
1720    if (!sd) return;
1721    if (sd->anchor_hover.hover) return;
1722 
1723    efl_event_callback_legacy_call(obj, ELM_ENTRY_EVENT_CONTEXT_OPEN, NULL);
1724 
1725    if ((sd->api) && (sd->api->obj_longpress))
1726      {
1727         sd->api->obj_longpress(obj);
1728      }
1729    else if (sd->context_menu)
1730      {
1731         const char *context_menu_orientation;
1732         Eina_Bool ownersel;
1733 
1734         ownersel = elm_cnp_clipboard_selection_has_owner(obj);
1735         if (!sd->items)
1736           {
1737              /* prevent stupid blank hoversel */
1738              if (sd->have_selection && sd->password) return;
1739              if (_elm_config->desktop_entry && (!sd->have_selection) && ((!sd->editable) || (!ownersel)))
1740                return;
1741           }
1742         if (sd->hoversel) evas_object_del(sd->hoversel);
1743         else elm_widget_scroll_freeze_push(obj);
1744 
1745         sd->hoversel = elm_hoversel_add(obj);
1746         elm_object_tree_focus_allow_set(sd->hoversel, EINA_FALSE);
1747         context_menu_orientation = edje_object_data_get
1748             (sd->entry_edje, "context_menu_orientation");
1749 
1750         if ((context_menu_orientation) &&
1751             (!strcmp(context_menu_orientation, "horizontal")))
1752           elm_hoversel_horizontal_set(sd->hoversel, EINA_TRUE);
1753 
1754         elm_object_style_set(sd->hoversel, "entry");
1755         elm_widget_sub_object_add(obj, sd->hoversel);
1756         elm_object_text_set(sd->hoversel, "Text");
1757         top = elm_widget_top_get(obj);
1758 
1759         if (top) elm_hoversel_hover_parent_set(sd->hoversel, top);
1760 
1761         efl_event_callback_add
1762           (sd->hoversel, ELM_HOVERSEL_EVENT_DISMISSED, _hover_dismissed_cb, obj);
1763         if (sd->have_selection)
1764           {
1765              if (!sd->password)
1766                {
1767                   if (sd->editable)
1768                     elm_hoversel_item_add
1769                        (sd->hoversel, E_("Cut"), NULL, ELM_ICON_NONE,
1770                         _cut_cb, obj);
1771                   elm_hoversel_item_add
1772                      (sd->hoversel, E_("Copy"), NULL, ELM_ICON_NONE,
1773                       _copy_cb, obj);
1774                   if (sd->editable && ownersel)
1775                     elm_hoversel_item_add
1776                        (sd->hoversel, E_("Paste"), NULL, ELM_ICON_NONE,
1777                         _paste_cb, obj);
1778                   elm_hoversel_item_add
1779                     (sd->hoversel, E_("Cancel"), NULL, ELM_ICON_NONE,
1780                     _hover_cancel_cb, obj);
1781                }
1782           }
1783         else
1784           {
1785              if (!sd->sel_mode)
1786                {
1787                   if (sd->sel_allow && !_elm_config->desktop_entry)
1788                     {
1789                        if (!sd->password)
1790                          elm_hoversel_item_add
1791                            (sd->hoversel, E_("Select"), NULL, ELM_ICON_NONE,
1792                            _hover_selected_cb, obj);
1793                     }
1794                   if (ownersel)
1795                     {
1796                        if (sd->editable)
1797                          elm_hoversel_item_add
1798                            (sd->hoversel, E_("Paste"), NULL, ELM_ICON_NONE,
1799                            _paste_cb, obj);
1800                     }
1801                }
1802              else
1803                elm_hoversel_item_add
1804                   (sd->hoversel, E_("Cancel"), NULL, ELM_ICON_NONE,
1805                    _hover_cancel_cb, obj);
1806           }
1807 
1808         EINA_LIST_FOREACH(sd->items, l, it)
1809           {
1810              elm_hoversel_item_add(sd->hoversel, it->label, it->icon_file,
1811                                    it->icon_type, _hover_item_clicked_cb, it);
1812           }
1813 
1814         if (sd->hoversel)
1815           {
1816              _hoversel_position(obj);
1817              elm_hoversel_hover_begin(sd->hoversel);
1818              evas_object_show(sd->hoversel);
1819           }
1820 
1821         if (!_elm_config->desktop_entry)
1822           {
1823              edje_object_part_text_select_allow_set
1824                (sd->entry_edje, "elm.text", EINA_FALSE);
1825              edje_object_part_text_select_abort(sd->entry_edje, "elm.text");
1826           }
1827      }
1828 }
1829 
1830 static void
_magnifier_proxy_update(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1831 _magnifier_proxy_update(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1832 {
1833    _magnifier_move(data);
1834 }
1835 
1836 static void
_magnifier_create(void * data)1837 _magnifier_create(void *data)
1838 {
1839    ELM_ENTRY_DATA_GET(data, sd);
1840 
1841    if (!sd) return;
1842    double scale = _elm_config->magnifier_scale;
1843    Evas *e;
1844    Evas_Coord w, h, mw, mh;
1845 
1846    evas_object_del(sd->mgf_proxy);
1847    evas_object_del(sd->mgf_bg);
1848    evas_object_del(sd->mgf_clip);
1849 
1850    e = evas_object_evas_get(data);
1851 
1852    //Bg
1853    sd->mgf_bg = edje_object_add(e);
1854    _elm_theme_object_set(data, sd->mgf_bg, "entry", "magnifier", "default");
1855    evas_object_show(sd->mgf_bg);
1856 
1857    //Proxy
1858    sd->mgf_proxy = evas_object_image_add(e);
1859    evas_object_event_callback_add(sd->mgf_proxy, EVAS_CALLBACK_RESIZE,
1860                                   _magnifier_proxy_update, data);
1861    evas_object_event_callback_add(sd->mgf_proxy, EVAS_CALLBACK_MOVE,
1862                                   _magnifier_proxy_update, data);
1863    edje_object_part_swallow(sd->mgf_bg, "elm.swallow.content", sd->mgf_proxy);
1864    evas_object_image_source_set(sd->mgf_proxy, data);
1865    evas_object_geometry_get(data, NULL, NULL, &w, &h);
1866 
1867    //Clipper
1868    sd->mgf_clip = evas_object_rectangle_add(e);
1869    evas_object_color_set(sd->mgf_clip, 0, 0, 0, 0);
1870    evas_object_show(sd->mgf_clip);
1871    evas_object_clip_set(sd->mgf_proxy, sd->mgf_clip);
1872 
1873    mw = (Evas_Coord)(scale * (float) w);
1874    mh = (Evas_Coord)(scale * (float) h);
1875    if ((mw <= 0) || (mh <= 0)) return;
1876 
1877    evas_object_layer_set(sd->mgf_bg, EVAS_LAYER_MAX);
1878    evas_object_layer_set(sd->mgf_proxy, EVAS_LAYER_MAX);
1879 }
1880 
1881 static void
_magnifier_move(void * data)1882 _magnifier_move(void *data)
1883 {
1884    ELM_ENTRY_DATA_GET(data, sd);
1885 
1886    if (!sd) return;
1887    Evas_Coord x, y, w, h;
1888    Evas_Coord px, py, pw, ph;
1889    Evas_Coord cx, cy, ch;
1890    Evas_Coord ex, ey;
1891    Evas_Coord mx, my, mw, mh;
1892    Evas_Coord diffx = 0;
1893    Evas_Object *top;
1894    double fx, fy, fw, fh;
1895    double scale = _elm_config->magnifier_scale;
1896 
1897    edje_object_part_text_cursor_geometry_get(sd->entry_edje, "elm.text",
1898                                              &cx, &cy, NULL, &ch);
1899    if (sd->scroll)
1900      {
1901         Evas_Coord ox, oy;
1902         evas_object_geometry_get(sd->scr_edje, &ex, &ey, NULL, NULL);
1903         elm_interface_scrollable_content_pos_get(data, &ox, &oy);
1904         ex -= ox;
1905         ey -= oy;
1906      }
1907    else
1908      {
1909         evas_object_geometry_get(data, &ex, &ey, NULL, NULL);
1910      }
1911    cx += ex;
1912    cy += ey;
1913 
1914    // calculate the position of the magnifier
1915    edje_object_parts_extends_calc(sd->mgf_bg, &x, &y, &w, &h);
1916 
1917    mx = cx - x - (w / 2);
1918    my = cy - y - h;
1919    mw = w;
1920    mh = h;
1921 
1922    // keep magnifier inside window
1923    top = elm_widget_top_get(data);
1924    if (top && efl_isa(top, EFL_UI_WIN_CLASS))
1925      {
1926         Evas_Coord wh, ww;
1927         evas_object_geometry_get(top, NULL, NULL, &ww, &wh);
1928         if (mx < 0)
1929           {
1930              diffx = mx;
1931              mx = 0;
1932           }
1933         if (mx + mw > ww)
1934           {
1935              diffx = - (ww - (mx + mw));
1936              mx = ww - mw;
1937           }
1938         if (my < 0)
1939           my = 0;
1940         if (my + mh > wh)
1941           my = wh - mh;
1942      }
1943 
1944    // move the magnifier to the proper position
1945    evas_object_move(sd->mgf_bg, mx, my);
1946 
1947    //Set the Proxy Render Area
1948    evas_object_geometry_get(data, &x, &y, &w, &h);
1949    evas_object_geometry_get(sd->mgf_proxy, &px, &py, &pw, &ph);
1950 
1951    fx = -((cx - x) * scale) + (pw * 0.5) + diffx;
1952    fy = -((cy - y) * scale) + (ph * 0.5) - (ch * 0.5 * scale);
1953    fw = w * scale;
1954    fh = h * scale;
1955    evas_object_image_fill_set(sd->mgf_proxy, fx, fy, fw, fh);
1956 
1957    //Update Clipper Area
1958    int tx = fx;
1959    int ty = fy;
1960    int tw = fw;
1961    int th = fh;
1962    if (tx > 0) px += tx;
1963    if (ty > 0) py += ty;
1964    if (-(tx - pw) > tw) pw -= (-((tx - pw) + tw));
1965    if (-(ty - ph) > th) ph -= (-((ty - ph) + th));
1966    evas_object_geometry_set(sd->mgf_clip, px, py, pw, ph);
1967 }
1968 
1969 static void
_magnifier_hide(void * data)1970 _magnifier_hide(void *data)
1971 {
1972    ELM_ENTRY_DATA_GET(data, sd);
1973    if (!sd) return;
1974    edje_object_signal_emit(sd->mgf_bg, "elm,action,hide,magnifier", "elm");
1975    elm_widget_scroll_freeze_pop(data);
1976    evas_object_hide(sd->mgf_clip);
1977 }
1978 
1979 static void
_magnifier_show(void * data)1980 _magnifier_show(void *data)
1981 {
1982    ELM_ENTRY_DATA_GET(data, sd);
1983    if (!sd) return;
1984    edje_object_signal_emit(sd->mgf_bg, "elm,action,show,magnifier", "elm");
1985    elm_widget_scroll_freeze_push(data);
1986    evas_object_show(sd->mgf_clip);
1987 }
1988 
1989 static Eina_Bool
_long_press_cb(void * data)1990 _long_press_cb(void *data)
1991 {
1992    ELM_ENTRY_DATA_GET(data, sd);
1993 
1994    if (!sd) return ECORE_CALLBACK_CANCEL;
1995    if (_elm_config->magnifier_enable)
1996      {
1997         _magnifier_create(data);
1998         _magnifier_show(data);
1999         _magnifier_move(data);
2000      }
2001    /* Context menu will not appear if context menu disabled is set
2002     * as false on a long press callback */
2003    else if (!_elm_config->context_menu_disabled &&
2004             (!_elm_config->desktop_entry))
2005      _menu_call(data);
2006 
2007    sd->long_pressed = EINA_TRUE;
2008 
2009    sd->longpress_timer = NULL;
2010    evas_object_smart_callback_call
2011      (data, "longpressed", NULL);
2012 
2013    return ECORE_CALLBACK_CANCEL;
2014 }
2015 
2016 static void
_key_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)2017 _key_down_cb(void *data,
2018                Evas *evas EINA_UNUSED,
2019                Evas_Object *obj EINA_UNUSED,
2020                void *event_info)
2021 {
2022    Evas_Event_Key_Down *ev = event_info;
2023    /* First check if context menu disabled is false or not, and
2024     * then check for key id */
2025    if ((!_elm_config->context_menu_disabled) && !strcmp(ev->key, "Menu"))
2026      _menu_call(data);
2027 }
2028 
2029 static void
_mouse_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)2030 _mouse_down_cb(void *data,
2031                Evas *evas EINA_UNUSED,
2032                Evas_Object *obj EINA_UNUSED,
2033                void *event_info)
2034 {
2035    Evas_Event_Mouse_Down *ev = event_info;
2036 
2037    ELM_ENTRY_DATA_GET(data, sd);
2038 
2039    if (!sd) return;
2040    if (sd->disabled) return;
2041    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
2042    sd->downx = ev->canvas.x;
2043    sd->downy = ev->canvas.y;
2044    sd->long_pressed = EINA_FALSE;
2045 
2046     if (ev->button == 1)
2047       {
2048          ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
2049          sd->longpress_timer = ecore_timer_add
2050            (_elm_config->longpress_timeout, _long_press_cb, data);
2051       }
2052     /* If right button is pressed and context menu disabled is true,
2053      * then only context menu will appear */
2054    else if (ev->button == 3 && (!_elm_config->context_menu_disabled))
2055      {
2056         if (_elm_config->desktop_entry)
2057           {
2058              sd->use_down = 1;
2059              _menu_call(data);
2060           }
2061      }
2062 }
2063 
2064 static void
_mouse_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)2065 _mouse_up_cb(void *data,
2066              Evas *evas EINA_UNUSED,
2067              Evas_Object *obj EINA_UNUSED,
2068              void *event_info)
2069 {
2070    Evas_Event_Mouse_Up *ev = event_info;
2071    Eina_Bool top_is_win = EINA_FALSE;
2072    Evas_Object *top;
2073 
2074    ELM_ENTRY_DATA_GET(data, sd);
2075 
2076    if (!sd) return;
2077    if (sd->disabled) return;
2078    if (ev->button == 1)
2079      {
2080         ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
2081         /* Since context menu disabled flag was checked at long press start while mouse
2082          * down, hence the same should be checked at mouse up from a long press
2083          * as well */
2084         if ((sd->long_pressed) && (_elm_config->magnifier_enable))
2085           {
2086              _magnifier_hide(data);
2087              if (!_elm_config->context_menu_disabled)
2088                {
2089                   _menu_call(data);
2090                }
2091           }
2092         else
2093           {
2094              top = elm_widget_top_get(data);
2095              if (top)
2096                {
2097                   if (efl_isa(top, EFL_UI_WIN_CLASS))
2098                     top_is_win = EINA_TRUE;
2099 
2100                   if (top_is_win && sd->input_panel_enable && sd->input_panel_show_on_demand &&
2101                       !edje_object_part_text_imf_context_get(sd->entry_edje, "elm.text"))
2102                     elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
2103                }
2104           }
2105      }
2106   /* Since context menu disabled flag was checked at mouse right key down,
2107    * hence the same should be stopped at mouse up of right key as well */
2108    else if ((ev->button == 3) && (!_elm_config->context_menu_disabled) &&
2109             (!_elm_config->desktop_entry))
2110      {
2111          sd->use_down = 1;
2112          _menu_call(data);
2113      }
2114 }
2115 
2116 static void
_mouse_move_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)2117 _mouse_move_cb(void *data,
2118                Evas *evas EINA_UNUSED,
2119                Evas_Object *obj EINA_UNUSED,
2120                void *event_info)
2121 {
2122    Evas_Event_Mouse_Move *ev = event_info;
2123 
2124    ELM_ENTRY_DATA_GET(data, sd);
2125 
2126    if (!sd) return;
2127    if (sd->disabled) return;
2128    if (ev->buttons == 1)
2129      {
2130         if ((sd->long_pressed) && (_elm_config->magnifier_enable))
2131           {
2132              Evas_Coord x, y;
2133              Eina_Bool rv;
2134 
2135              evas_object_geometry_get(sd->entry_edje, &x, &y, NULL, NULL);
2136              rv = edje_object_part_text_cursor_coord_set
2137                (sd->entry_edje, "elm.text", EDJE_CURSOR_USER,
2138                ev->cur.canvas.x - x, ev->cur.canvas.y - y);
2139              if (rv)
2140                {
2141                   edje_object_part_text_cursor_copy
2142                     (sd->entry_edje, "elm.text", EDJE_CURSOR_USER, EDJE_CURSOR_MAIN);
2143                }
2144              else
2145                WRN("Warning: Cannot move cursor");
2146 
2147              _magnifier_move(data);
2148           }
2149      }
2150    if (!sd->sel_mode)
2151      {
2152         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
2153           {
2154              ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
2155           }
2156         else if (sd->longpress_timer)
2157           {
2158              Evas_Coord dx, dy;
2159 
2160              dx = sd->downx - ev->cur.canvas.x;
2161              dx *= dx;
2162              dy = sd->downy - ev->cur.canvas.y;
2163              dy *= dy;
2164              if ((dx + dy) >
2165                  ((_elm_config->finger_size / 2) *
2166                   (_elm_config->finger_size / 2)))
2167                {
2168                   ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
2169                }
2170           }
2171      }
2172    else if (sd->longpress_timer)
2173      {
2174         Evas_Coord dx, dy;
2175 
2176         dx = sd->downx - ev->cur.canvas.x;
2177         dx *= dx;
2178         dy = sd->downy - ev->cur.canvas.y;
2179         dy *= dy;
2180         if ((dx + dy) >
2181             ((_elm_config->finger_size / 2) *
2182              (_elm_config->finger_size / 2)))
2183           {
2184              ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
2185           }
2186      }
2187 }
2188 
2189 static void
_entry_changed_handle(void * data,const Efl_Event_Description * event)2190 _entry_changed_handle(void *data,
2191                       const Efl_Event_Description* event)
2192 {
2193    Evas_Coord minh;
2194    const char *text;
2195 
2196    ELM_ENTRY_DATA_GET(data, sd);
2197 
2198    if (!sd) return;
2199    evas_event_freeze(evas_object_evas_get(data));
2200    sd->changed = EINA_TRUE;
2201    /* Reset the size hints which are no more relevant. Keep the
2202     * height, this is a hack, but doesn't really matter cause we'll
2203     * re-eval in a moment. */
2204    evas_object_size_hint_combined_min_get(data, NULL, &minh);
2205    evas_object_size_hint_min_set(data, -1, minh);
2206 
2207    elm_layout_sizing_eval(data);
2208    ELM_SAFE_FREE(sd->text, eina_stringshare_del);
2209    ELM_SAFE_FREE(sd->delay_write, ecore_timer_del);
2210    evas_event_thaw(evas_object_evas_get(data));
2211    evas_event_thaw_eval(evas_object_evas_get(data));
2212    if ((sd->auto_save) && (sd->file))
2213      sd->delay_write = ecore_timer_add(ELM_ENTRY_DELAY_WRITE_TIME,
2214                                        _delay_write, data);
2215 
2216    _return_key_enabled_check(data);
2217    text = edje_object_part_text_get(sd->entry_edje, "elm.text");
2218    if (text)
2219      {
2220         if (text[0])
2221           _elm_entry_guide_update(data, EINA_TRUE);
2222         else
2223           _elm_entry_guide_update(data, EINA_FALSE);
2224      }
2225    _validate(data);
2226 
2227    /* callback - this could call callbacks that delete the
2228     * entry... thus... any access to sd after this could be
2229     * invalid */
2230    efl_event_callback_legacy_call(data, event, NULL);
2231 }
2232 
2233 static void
_entry_changed_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2234 _entry_changed_signal_cb(void *data,
2235                          Evas_Object *obj EINA_UNUSED,
2236                          const char *emission EINA_UNUSED,
2237                          const char *source EINA_UNUSED)
2238 {
2239    _entry_changed_handle(data, ELM_ENTRY_EVENT_CHANGED);
2240 }
2241 
2242 static void
_entry_changed_user_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2243 _entry_changed_user_signal_cb(void *data,
2244                               Evas_Object *obj EINA_UNUSED,
2245                               const char *emission EINA_UNUSED,
2246                               const char *source EINA_UNUSED)
2247 {
2248    Elm_Entry_Change_Info info;
2249    Edje_Entry_Change_Info *edje_info = (Edje_Entry_Change_Info *)
2250      edje_object_signal_callback_extra_data_get();
2251 
2252    if (edje_info)
2253      {
2254         memcpy(&info, edje_info, sizeof(info));
2255         efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_CHANGED_USER, &info);
2256      }
2257    else
2258      {
2259         efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_CHANGED_USER, NULL);
2260      }
2261    if (_elm_config->atspi_mode)
2262      {
2263         Efl_Access_Text_Change_Info atspi_info;
2264         if (edje_info && edje_info->insert)
2265           {
2266              atspi_info.content = elm_entry_markup_to_utf8(edje_info->change.insert.content);
2267              atspi_info.pos = edje_info->change.insert.pos;
2268              atspi_info.len = edje_info->change.insert.plain_length;
2269              efl_access_object_event_emit(data, EFL_ACCESS_TEXT_EVENT_ACCESS_TEXT_INSERTED, &atspi_info);
2270              free((void *)atspi_info.content);
2271           }
2272         else if (edje_info && !edje_info->insert)
2273           {
2274              atspi_info.content = elm_entry_markup_to_utf8(edje_info->change.del.content);
2275              atspi_info.pos = MIN(edje_info->change.del.start, edje_info->change.del.end);
2276              atspi_info.len = MAX(edje_info->change.del.start, edje_info->change.del.end) - atspi_info.pos;
2277              efl_access_object_event_emit(data, EFL_ACCESS_TEXT_EVENT_ACCESS_TEXT_REMOVED, &atspi_info);
2278              free((void *)atspi_info.content);
2279           }
2280      }
2281 }
2282 
2283 static void
_entry_preedit_changed_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2284 _entry_preedit_changed_signal_cb(void *data,
2285                                  Evas_Object *obj EINA_UNUSED,
2286                                  const char *emission EINA_UNUSED,
2287                                  const char *source EINA_UNUSED)
2288 {
2289    char *text = NULL;
2290    Edje_Entry_Change_Info *edje_info = (Edje_Entry_Change_Info *)
2291                                   edje_object_signal_callback_extra_data_get();
2292    _entry_changed_handle(data, ELM_ENTRY_EVENT_PREEDIT_CHANGED);
2293 
2294    if (_elm_config->atspi_mode)
2295      {
2296         Efl_Access_Text_Change_Info atspi_info;
2297         if (edje_info && edje_info->insert)
2298           {
2299              text = elm_entry_markup_to_utf8(edje_info->change.insert.content);
2300              atspi_info.content = text;
2301              atspi_info.pos = edje_info->change.insert.pos;
2302              atspi_info.len = edje_info->change.insert.plain_length;
2303              efl_access_object_event_emit(
2304                                                        data,
2305                                                        EFL_ACCESS_TEXT_EVENT_ACCESS_TEXT_INSERTED,
2306                                                        &atspi_info);
2307              free(text);
2308           }
2309      }
2310 }
2311 
2312 static void
_entry_undo_request_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2313 _entry_undo_request_signal_cb(void *data,
2314                               Evas_Object *obj EINA_UNUSED,
2315                               const char *emission EINA_UNUSED,
2316                               const char *source EINA_UNUSED)
2317 {
2318    efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_UNDO_REQUEST, NULL);
2319 }
2320 
2321 static void
_entry_redo_request_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2322 _entry_redo_request_signal_cb(void *data,
2323                               Evas_Object *obj EINA_UNUSED,
2324                               const char *emission EINA_UNUSED,
2325                               const char *source EINA_UNUSED)
2326 {
2327    efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_REDO_REQUEST, NULL);
2328 }
2329 
2330 static void
_entry_selection_start_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2331 _entry_selection_start_signal_cb(void *data,
2332                                  Evas_Object *obj EINA_UNUSED,
2333                                  const char *emission EINA_UNUSED,
2334                                  const char *source EINA_UNUSED)
2335 {
2336    const Eina_List *l;
2337    Evas_Object *entry;
2338 
2339    EINA_LIST_FOREACH(entries, l, entry)
2340      {
2341         if (entry != data) elm_entry_select_none(entry);
2342      }
2343 
2344    Eina_Bool b_value = EINA_TRUE;
2345    efl_event_callback_legacy_call
2346      (data, EFL_TEXT_INTERACTIVE_EVENT_HAVE_SELECTION_CHANGED, &b_value);
2347 
2348    elm_object_focus_set(data, EINA_TRUE);
2349 }
2350 
2351 static void
_entry_selection_all_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2352 _entry_selection_all_signal_cb(void *data,
2353                                Evas_Object *obj EINA_UNUSED,
2354                                const char *emission EINA_UNUSED,
2355                                const char *source EINA_UNUSED)
2356 {
2357    elm_entry_select_all(data);
2358 }
2359 
2360 static void
_entry_selection_none_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2361 _entry_selection_none_signal_cb(void *data,
2362                                 Evas_Object *obj EINA_UNUSED,
2363                                 const char *emission EINA_UNUSED,
2364                                 const char *source EINA_UNUSED)
2365 {
2366    elm_entry_select_none(data);
2367 }
2368 
2369 // XXX: still try primary selection even if on wl in case it's
2370 // supported
2371 //static inline Eina_Bool
2372 //_entry_win_is_wl(Evas_Object *obj)
2373 //{
2374 //   Evas_Object *win = _entry_win_get(obj);
2375 //   /* primary selection does not exist (yet) */
2376 //   return win && elm_win_wl_window_get(win);
2377 //}
2378 
2379 static void
_entry_selection_changed_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2380 _entry_selection_changed_signal_cb(void *data,
2381                                    Evas_Object *obj EINA_UNUSED,
2382                                    const char *emission EINA_UNUSED,
2383                                    const char *source EINA_UNUSED)
2384 {
2385    ELM_ENTRY_DATA_GET(data, sd);
2386 
2387    if (!sd) return;
2388    sd->have_selection = EINA_TRUE;
2389    //FIXME how to get selection range in legacy !?
2390    Eina_Range range = EINA_RANGE_EMPTY();
2391    efl_event_callback_legacy_call
2392      (data, EFL_TEXT_INTERACTIVE_EVENT_SELECTION_CHANGED, &range);
2393    // XXX: still try primary selection even if on wl in case it's
2394    // supported
2395 //   if (!_entry_win_is_wl(data))
2396      _selection_store(ELM_SEL_TYPE_PRIMARY, data);
2397    _update_selection_handler(data);
2398    if (_elm_config->atspi_mode)
2399      efl_access_object_event_emit( data, EFL_ACCESS_TEXT_EVENT_ACCESS_TEXT_SELECTION_CHANGED, NULL);
2400 }
2401 
2402 static void
_entry_selection_cleared_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2403 _entry_selection_cleared_signal_cb(void *data,
2404                                    Evas_Object *obj EINA_UNUSED,
2405                                    const char *emission EINA_UNUSED,
2406                                    const char *source EINA_UNUSED)
2407 {
2408    ELM_ENTRY_DATA_GET(data, sd);
2409 
2410    if (!sd) return;
2411    if (!sd->have_selection) return;
2412 
2413    sd->have_selection = EINA_FALSE;
2414    Eina_Bool b_value = sd->have_selection;
2415    efl_event_callback_legacy_call
2416      (data, EFL_TEXT_INTERACTIVE_EVENT_HAVE_SELECTION_CHANGED, &b_value);
2417    // XXX: still try primary selection even if on wl in case it's
2418    // supported
2419 //   if (!_entry_win_is_wl(data))
2420      {
2421         if (sd->cut_sel)
2422           {
2423              elm_cnp_selection_set
2424                 (data, ELM_SEL_TYPE_PRIMARY, ELM_SEL_FORMAT_MARKUP,
2425                  sd->cut_sel, eina_stringshare_strlen(sd->cut_sel));
2426              elm_cnp_selection_loss_callback_set(data, ELM_SEL_TYPE_PRIMARY, _selection_clear, data);
2427 
2428              ELM_SAFE_FREE(sd->cut_sel, eina_stringshare_del);
2429           }
2430         else
2431           {
2432              elm_object_cnp_selection_clear(data, ELM_SEL_TYPE_PRIMARY);
2433           }
2434      }
2435    _hide_selection_handler(data);
2436 }
2437 
2438 static void
_entry_paste_request_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * source EINA_UNUSED)2439 _entry_paste_request_signal_cb(void *data,
2440                                Evas_Object *obj EINA_UNUSED,
2441                                const char *emission,
2442                                const char *source EINA_UNUSED)
2443 {
2444    Evas_Object *top;
2445 
2446    ELM_ENTRY_DATA_GET(data, sd);
2447 
2448    if (!sd) return;
2449    Elm_Sel_Type type = (emission[sizeof("ntry,paste,request,")] == '1') ?
2450      ELM_SEL_TYPE_PRIMARY : ELM_SEL_TYPE_CLIPBOARD;
2451 
2452    if (!sd->editable) return;
2453    // XXX: still try primary selection even if on wl in case it's
2454    // supported
2455 //   if ((type == ELM_SEL_TYPE_PRIMARY) && _entry_win_is_wl(data)) return;
2456    efl_event_callback_legacy_call
2457      (data, EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE, NULL);
2458 
2459    top = _entry_win_get(data);
2460    if (top)
2461      {
2462         Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_TEXT;
2463 
2464         sd->selection_asked = EINA_TRUE;
2465 
2466         if (sd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
2467           formats = ELM_SEL_FORMAT_TEXT;
2468         else if (sd->cnp_mode != ELM_CNP_MODE_NO_IMAGE)
2469           formats |= ELM_SEL_FORMAT_IMAGE;
2470 
2471         elm_cnp_selection_get(data, type, formats, _selection_data_cb, NULL);
2472      }
2473 }
2474 
2475 static void
_entry_copy_notify_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2476 _entry_copy_notify_signal_cb(void *data,
2477                              Evas_Object *obj EINA_UNUSED,
2478                              const char *emission EINA_UNUSED,
2479                              const char *source EINA_UNUSED)
2480 {
2481    _copy_cb(data, NULL, NULL);
2482 }
2483 
2484 static void
_entry_cut_notify_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2485 _entry_cut_notify_signal_cb(void *data,
2486                             Evas_Object *obj EINA_UNUSED,
2487                             const char *emission EINA_UNUSED,
2488                             const char *source EINA_UNUSED)
2489 {
2490    _cut_cb(data, NULL, NULL);
2491 }
2492 
2493 static void
_entry_cursor_changed_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2494 _entry_cursor_changed_signal_cb(void *data,
2495                                 Evas_Object *obj EINA_UNUSED,
2496                                 const char *emission EINA_UNUSED,
2497                                 const char *source EINA_UNUSED)
2498 {
2499    ELM_ENTRY_DATA_GET(data, sd);
2500    if (!sd) return;
2501    sd->cursor_pos = edje_object_part_text_cursor_pos_get
2502        (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
2503    sd->cur_changed = EINA_TRUE;
2504    if (efl_ui_focus_object_focus_get(data))
2505      edje_object_signal_emit(sd->entry_edje, "elm,action,show,cursor", "elm");
2506    _cursor_geometry_recalc(data);
2507 
2508    efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_CURSOR_CHANGED, NULL);
2509 
2510    if (_elm_config->atspi_mode)
2511      efl_access_object_event_emit( data, EFL_ACCESS_TEXT_EVENT_ACCESS_TEXT_CARET_MOVED, NULL);
2512 }
2513 
2514 static void
_entry_cursor_changed_manual_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2515 _entry_cursor_changed_manual_signal_cb(void *data,
2516                                        Evas_Object *obj EINA_UNUSED,
2517                                        const char *emission EINA_UNUSED,
2518                                        const char *source EINA_UNUSED)
2519 {
2520    efl_event_callback_legacy_call
2521      (data, ELM_ENTRY_EVENT_CURSOR_CHANGED_MANUAL, NULL);
2522    if (_elm_config->atspi_mode)
2523      efl_access_object_event_emit( data, EFL_ACCESS_TEXT_EVENT_ACCESS_TEXT_CARET_MOVED, NULL);
2524 }
2525 
2526 static void
_signal_anchor_geoms_do_things_with_lol(Elm_Entry_Data * sd,Elm_Entry_Anchor_Info * ei)2527 _signal_anchor_geoms_do_things_with_lol(Elm_Entry_Data *sd,
2528                                         Elm_Entry_Anchor_Info *ei)
2529 {
2530    Evas_Textblock_Rectangle *r;
2531    const Eina_List *geoms, *l;
2532    Evas_Coord px, py, x, y;
2533 
2534    geoms = edje_object_part_text_anchor_geometry_get
2535        (sd->entry_edje, "elm.text", ei->name);
2536 
2537    if (!geoms) return;
2538 
2539    evas_object_geometry_get(
2540       edje_object_part_object_get(sd->entry_edje, "elm.text"),
2541       &x, &y, NULL, NULL);
2542    evas_pointer_canvas_xy_get
2543      (evas_object_evas_get(sd->entry_edje), &px, &py);
2544 
2545    EINA_LIST_FOREACH(geoms, l, r)
2546      {
2547         if (((r->x + x) <= px) && ((r->y + y) <= py) &&
2548             ((r->x + x + r->w) > px) && ((r->y + y + r->h) > py))
2549           {
2550              ei->x = r->x + x;
2551              ei->y = r->y + y;
2552              ei->w = r->w;
2553              ei->h = r->h;
2554              break;
2555           }
2556      }
2557 }
2558 
2559 static void
_entry_anchor_down_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2560 _entry_anchor_down_signal_cb(void *data,
2561                              Evas_Object *obj EINA_UNUSED,
2562                              const char *emission EINA_UNUSED,
2563                              const char *source EINA_UNUSED)
2564 {
2565    Elm_Entry_Anchor_Info ei;
2566    const char *p;
2567    char *p2;
2568 
2569    ELM_ENTRY_DATA_GET(data, sd);
2570 
2571    if (!sd) return;
2572    p = emission + sizeof("nchor,mouse,down,");
2573    ei.button = strtol(p, &p2, 10);
2574    ei.name = p2 + 1;
2575    ei.x = ei.y = ei.w = ei.h = 0;
2576 
2577    _signal_anchor_geoms_do_things_with_lol(sd, &ei);
2578 
2579    if (!sd->disabled)
2580      efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ANCHOR_DOWN, &ei);
2581 }
2582 
2583 static void
_entry_anchor_up_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2584 _entry_anchor_up_signal_cb(void *data,
2585                            Evas_Object *obj EINA_UNUSED,
2586                            const char *emission EINA_UNUSED,
2587                            const char *source EINA_UNUSED)
2588 {
2589    Elm_Entry_Anchor_Info ei;
2590    const char *p;
2591    char *p2;
2592 
2593    ELM_ENTRY_DATA_GET(data, sd);
2594 
2595    if (!sd) return;
2596    p = emission + sizeof("nchor,mouse,up,");
2597    ei.button = strtol(p, &p2, 10);
2598    ei.name = p2 + 1;
2599    ei.x = ei.y = ei.w = ei.h = 0;
2600 
2601    _signal_anchor_geoms_do_things_with_lol(sd, &ei);
2602 
2603    if (!sd->disabled)
2604      efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ANCHOR_UP, &ei);
2605 }
2606 
2607 static void
_anchor_hover_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2608 _anchor_hover_del_cb(void *data,
2609                      Evas *e EINA_UNUSED,
2610                      Evas_Object *obj EINA_UNUSED,
2611                      void *event_info EINA_UNUSED)
2612 {
2613    ELM_ENTRY_DATA_GET(data, sd);
2614 
2615    if (!sd) return;
2616    ELM_SAFE_FREE(sd->anchor_hover.pop, evas_object_del);
2617    evas_object_event_callback_del_full
2618      (sd->anchor_hover.hover, EVAS_CALLBACK_DEL, _anchor_hover_del_cb, obj);
2619 }
2620 
2621 static void
_anchor_hover_clicked_cb(void * data,const Efl_Event * event EINA_UNUSED)2622 _anchor_hover_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED)
2623 {
2624    elm_entry_anchor_hover_end(data);
2625 }
2626 
2627 static void
_entry_hover_anchor_clicked_do(Evas_Object * obj,Elm_Entry_Anchor_Info * info)2628 _entry_hover_anchor_clicked_do(Evas_Object *obj,
2629                                Elm_Entry_Anchor_Info *info)
2630 {
2631    Evas_Object *hover_parent;
2632    Evas_Coord x, w, y, h, px, py;
2633    Elm_Entry_Anchor_Hover_Info ei;
2634 
2635    ELM_ENTRY_DATA_GET(obj, sd);
2636 
2637    if (!sd) return;
2638    if (sd->hoversel) return;
2639 
2640    ei.anchor_info = info;
2641 
2642    sd->anchor_hover.pop = elm_icon_add(obj);
2643    evas_object_geometry_set(sd->anchor_hover.pop,
2644                             info->x, info->y, info->w, info->h);
2645 
2646    sd->anchor_hover.hover = elm_hover_add(obj);
2647    evas_object_event_callback_add
2648      (sd->anchor_hover.hover, EVAS_CALLBACK_DEL, _anchor_hover_del_cb, obj);
2649    efl_ui_mirrored_set
2650      (sd->anchor_hover.hover, efl_ui_mirrored_get(obj));
2651    if (sd->anchor_hover.hover_style)
2652      elm_object_style_set
2653        (sd->anchor_hover.hover, sd->anchor_hover.hover_style);
2654 
2655    hover_parent = sd->anchor_hover.hover_parent;
2656    if (!hover_parent) hover_parent = obj;
2657    elm_hover_parent_set(sd->anchor_hover.hover, hover_parent);
2658    elm_hover_target_set(sd->anchor_hover.hover, sd->anchor_hover.pop);
2659    ei.hover = sd->anchor_hover.hover;
2660 
2661    evas_object_geometry_get(hover_parent, &x, &y, &w, &h);
2662    ei.hover_parent.x = x;
2663    ei.hover_parent.y = y;
2664    ei.hover_parent.w = w;
2665    ei.hover_parent.h = h;
2666    px = info->x + (info->w / 2);
2667    py = info->y + (info->h / 2);
2668    ei.hover_left = 1;
2669    if (px < (x + (w / 3))) ei.hover_left = 0;
2670    ei.hover_right = 1;
2671    if (px > (x + ((w * 2) / 3))) ei.hover_right = 0;
2672    ei.hover_top = 1;
2673    if (py < (y + (h / 3))) ei.hover_top = 0;
2674    ei.hover_bottom = 1;
2675    if (py > (y + ((h * 2) / 3))) ei.hover_bottom = 0;
2676 
2677    /* Swap right and left because they switch sides in RTL */
2678    if (efl_ui_mirrored_get(sd->anchor_hover.hover))
2679      {
2680         Eina_Bool tmp = ei.hover_left;
2681 
2682         ei.hover_left = ei.hover_right;
2683         ei.hover_right = tmp;
2684      }
2685 
2686    efl_event_callback_legacy_call(obj, ELM_ENTRY_EVENT_ANCHOR_HOVER_OPENED, &ei);
2687    efl_event_callback_add
2688      (sd->anchor_hover.hover, EFL_INPUT_EVENT_CLICKED, _anchor_hover_clicked_cb, obj);
2689 
2690    /* FIXME: Should just check if there's any callback registered to
2691     * the smart events instead.  This is used to determine if anyone
2692     * cares about the hover or not. */
2693    if (!elm_layout_content_get(sd->anchor_hover.hover, "middle") &&
2694        !elm_layout_content_get(sd->anchor_hover.hover, "left") &&
2695        !elm_layout_content_get(sd->anchor_hover.hover, "right") &&
2696        !elm_layout_content_get(sd->anchor_hover.hover, "top") &&
2697        !elm_layout_content_get(sd->anchor_hover.hover, "bottom"))
2698      {
2699         ELM_SAFE_FREE(sd->anchor_hover.hover, evas_object_del);
2700      }
2701    else
2702      evas_object_show(sd->anchor_hover.hover);
2703 }
2704 
2705 static void
_entry_anchor_clicked_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * source EINA_UNUSED)2706 _entry_anchor_clicked_signal_cb(void *data,
2707                                 Evas_Object *obj EINA_UNUSED,
2708                                 const char *emission,
2709                                 const char *source EINA_UNUSED)
2710 {
2711    Elm_Entry_Anchor_Info ei;
2712    const char *p;
2713    char *p2;
2714 
2715    ELM_ENTRY_DATA_GET(data, sd);
2716 
2717    if (!sd) return;
2718    p = emission + sizeof("nchor,mouse,clicked,");
2719    ei.button = strtol(p, &p2, 10);
2720    ei.name = p2 + 1;
2721    ei.x = ei.y = ei.w = ei.h = 0;
2722 
2723    _signal_anchor_geoms_do_things_with_lol(sd, &ei);
2724 
2725    if (!sd->disabled)
2726      {
2727         efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ANCHOR_CLICKED, &ei);
2728         _entry_hover_anchor_clicked_do(data, &ei);
2729      }
2730 }
2731 
2732 static void
_entry_anchor_move_signal_cb(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2733 _entry_anchor_move_signal_cb(void *data EINA_UNUSED,
2734                              Evas_Object *obj EINA_UNUSED,
2735                              const char *emission EINA_UNUSED,
2736                              const char *source EINA_UNUSED)
2737 {
2738 }
2739 
2740 static void
_entry_anchor_in_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2741 _entry_anchor_in_signal_cb(void *data,
2742                            Evas_Object *obj EINA_UNUSED,
2743                            const char *emission EINA_UNUSED,
2744                            const char *source EINA_UNUSED)
2745 {
2746    Elm_Entry_Anchor_Info ei;
2747 
2748    ELM_ENTRY_DATA_GET(data, sd);
2749 
2750    if (!sd) return;
2751    ei.name = emission + sizeof("nchor,mouse,in,");
2752    ei.button = 0;
2753    ei.x = ei.y = ei.w = ei.h = 0;
2754 
2755    _signal_anchor_geoms_do_things_with_lol(sd, &ei);
2756 
2757    if (!sd->disabled)
2758      efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ANCHOR_IN, &ei);
2759 }
2760 
2761 static void
_entry_anchor_out_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2762 _entry_anchor_out_signal_cb(void *data,
2763                             Evas_Object *obj EINA_UNUSED,
2764                             const char *emission EINA_UNUSED,
2765                             const char *source EINA_UNUSED)
2766 {
2767    Elm_Entry_Anchor_Info ei;
2768 
2769    ELM_ENTRY_DATA_GET(data, sd);
2770 
2771    if (!sd) return;
2772    ei.name = emission + sizeof("nchor,mouse,out,");
2773    ei.button = 0;
2774    ei.x = ei.y = ei.w = ei.h = 0;
2775 
2776    _signal_anchor_geoms_do_things_with_lol(sd, &ei);
2777 
2778    if (!sd->disabled)
2779      efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ANCHOR_OUT, &ei);
2780 }
2781 
2782 static void
_entry_key_enter_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2783 _entry_key_enter_signal_cb(void *data,
2784                            Evas_Object *obj EINA_UNUSED,
2785                            const char *emission EINA_UNUSED,
2786                            const char *source EINA_UNUSED)
2787 {
2788    ELM_ENTRY_DATA_GET(data, sd);
2789 
2790    if (sd->single_line)
2791      efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ACTIVATED, NULL);
2792 }
2793 
2794 static void
_entry_key_escape_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2795 _entry_key_escape_signal_cb(void *data,
2796                             Evas_Object *obj EINA_UNUSED,
2797                             const char *emission EINA_UNUSED,
2798                             const char *source EINA_UNUSED)
2799 {
2800    ELM_ENTRY_DATA_GET(data, sd);
2801 
2802    if (sd->single_line)
2803      efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_ABORTED, NULL);
2804 }
2805 
2806 static void
_entry_mouse_down_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2807 _entry_mouse_down_signal_cb(void *data,
2808                             Evas_Object *obj EINA_UNUSED,
2809                             const char *emission EINA_UNUSED,
2810                             const char *source EINA_UNUSED)
2811 {
2812    efl_event_callback_legacy_call(data, ELM_ENTRY_EVENT_PRESS, NULL);
2813 }
2814 
2815 static void
_entry_mouse_clicked_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2816 _entry_mouse_clicked_signal_cb(void *data,
2817                                Evas_Object *obj EINA_UNUSED,
2818                                const char *emission EINA_UNUSED,
2819                                const char *source EINA_UNUSED)
2820 {
2821    evas_object_smart_callback_call
2822      ( data, "clicked", NULL);
2823 }
2824 
2825 static void
_entry_mouse_double_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2826 _entry_mouse_double_signal_cb(void *data,
2827                               Evas_Object *obj EINA_UNUSED,
2828                               const char *emission EINA_UNUSED,
2829                               const char *source EINA_UNUSED)
2830 {
2831    evas_object_smart_callback_call
2832      ( data, "clicked,double", NULL);
2833 }
2834 
2835 static void
_entry_mouse_triple_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2836 _entry_mouse_triple_signal_cb(void *data,
2837                               Evas_Object *obj EINA_UNUSED,
2838                               const char *emission EINA_UNUSED,
2839                               const char *source EINA_UNUSED)
2840 {
2841    evas_object_smart_callback_call
2842      ( data, "clicked,triple", NULL);
2843 }
2844 
2845 static Evas_Object *
_item_get(void * data,Evas_Object * edje EINA_UNUSED,const char * part EINA_UNUSED,const char * item)2846 _item_get(void *data,
2847           Evas_Object *edje EINA_UNUSED,
2848           const char *part EINA_UNUSED,
2849           const char *item)
2850 {
2851    Eina_List *l;
2852    Evas_Object *o;
2853    Elm_Entry_Item_Provider *ip;
2854    const char *style = elm_widget_style_get(data);
2855 
2856    ELM_ENTRY_DATA_GET(data, sd);
2857 
2858    if (!sd) return NULL;
2859    EINA_LIST_FOREACH(sd->item_providers, l, ip)
2860      {
2861         o = ip->func(ip->data, data, item);
2862         if (o) return o;
2863      }
2864    if (item && !strncmp(item, "file://", 7))
2865      {
2866         const char *fname = item + 7;
2867 
2868         o = evas_object_image_filled_add(evas_object_evas_get(data));
2869         evas_object_image_load_orientation_set(o, EINA_TRUE);
2870         evas_object_image_file_set(o, fname, NULL);
2871         if (evas_object_image_load_error_get(o) == EVAS_LOAD_ERROR_NONE)
2872           {
2873              evas_object_show(o);
2874           }
2875         else
2876           {
2877              evas_object_del(o);
2878              o = edje_object_add(evas_object_evas_get(data));
2879              _elm_theme_object_set
2880                (data, o, "entry/emoticon", "wtf", style);
2881           }
2882         return o;
2883      }
2884 
2885    o = edje_object_add(evas_object_evas_get(data));
2886    if (_elm_theme_object_set
2887          (data, o, "entry", item, style) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
2888      _elm_theme_object_set
2889        (data, o, "entry/emoticon", "wtf", style);
2890    return o;
2891 }
2892 
2893 static Eina_Bool
_entry_has_new_line(const char * text)2894 _entry_has_new_line(const char *text)
2895 {
2896    if (!text) return EINA_FALSE;
2897 
2898    const char * pTemp = text;
2899 
2900    while ((pTemp = strchr(pTemp, '<')))
2901    {
2902       pTemp++;
2903       if (!strncmp(pTemp, "br", 2) || !strncmp(pTemp, "ps", 2))
2904       {
2905          pTemp += 2;
2906          if (pTemp[0] != '\0' && (pTemp[0] == '>' || (pTemp[0] == '/' && pTemp[1] == '>')))
2907          {
2908             return EINA_TRUE;
2909          }
2910       }
2911    }
2912    return EINA_FALSE;
2913 }
2914 
2915 static char *
_entry_remove_new_line(const char * text)2916 _entry_remove_new_line(const char *text)
2917 {
2918    Eina_Strbuf *str;
2919    char *new_text;
2920 
2921    if (!_entry_has_new_line(text)) return NULL;
2922 
2923    str = eina_strbuf_new();
2924    eina_strbuf_append(str, text);
2925    eina_strbuf_replace_all(str, "<br>", "");
2926    eina_strbuf_replace_all(str, "<br/>", "");
2927    eina_strbuf_replace_all(str, "<ps>", "");
2928    eina_strbuf_replace_all(str, "<ps/>", "");
2929    new_text = eina_strbuf_string_steal(str);
2930    eina_strbuf_free(str);
2931    return new_text;
2932 }
2933 
2934 static void
_entry_new_line_filter_init(Evas_Object * obj)2935 _entry_new_line_filter_init(Evas_Object *obj)
2936 {
2937    const char *text;
2938    char *text2 = NULL;
2939 
2940    if (elm_entry_is_empty(obj)) return;
2941 
2942    text = elm_entry_entry_get(obj);
2943    text2 = _entry_remove_new_line(text);
2944    if (text2)
2945      {
2946         elm_entry_entry_set(obj, text2);
2947         free(text2);
2948      }
2949 }
2950 
2951 static void
_entry_new_line_filter_cb(void * data EINA_UNUSED,Evas_Object * entry EINA_UNUSED,char ** text)2952 _entry_new_line_filter_cb(void *data EINA_UNUSED,
2953                           Evas_Object *entry EINA_UNUSED,
2954                           char **text)
2955 {
2956    char *ret;
2957 
2958    if (!*text) return;
2959 
2960    ret = _entry_remove_new_line(*text);
2961 
2962    if (ret)
2963      {
2964         free(*text);
2965         *text = ret;
2966      }
2967 }
2968 
2969 static void
_markup_filter_cb(void * data,Evas_Object * edje EINA_UNUSED,const char * part EINA_UNUSED,char ** text)2970 _markup_filter_cb(void *data,
2971                   Evas_Object *edje EINA_UNUSED,
2972                   const char *part EINA_UNUSED,
2973                   char **text)
2974 {
2975    Eina_List *l;
2976    Elm_Entry_Markup_Filter *tf;
2977 
2978    ELM_ENTRY_DATA_GET(data, sd);
2979 
2980    if (!sd) return;
2981    EINA_LIST_FOREACH(sd->markup_filters, l, tf)
2982      {
2983         tf->func(tf->data, data, text);
2984         if (!*text)
2985           break;
2986      }
2987 }
2988 
2989 /* This function is used to insert text by chunks in jobs */
2990 static Eina_Bool
_text_append_idler(void * data)2991 _text_append_idler(void *data)
2992 {
2993    int start;
2994    char backup;
2995    Evas_Object *obj = (Evas_Object *)data;
2996 
2997    ELM_ENTRY_DATA_GET(obj, sd);
2998 
2999    if (!sd) return ECORE_CALLBACK_CANCEL;
3000    evas_event_freeze(evas_object_evas_get(obj));
3001    ELM_SAFE_FREE(sd->text, eina_stringshare_del);
3002    sd->changed = EINA_TRUE;
3003 
3004    start = sd->append_text_position;
3005    if ((start + ELM_ENTRY_CHUNK_SIZE) < sd->append_text_len)
3006      {
3007         int pos = start;
3008         int tag_start, esc_start;
3009 
3010         tag_start = esc_start = -1;
3011         /* Find proper markup cut place */
3012         while (pos - start < ELM_ENTRY_CHUNK_SIZE)
3013           {
3014              int prev_pos = pos;
3015              Eina_Unicode tmp =
3016                eina_unicode_utf8_next_get(sd->append_text_left, &pos);
3017 
3018              if (esc_start == -1)
3019                {
3020                   if (tmp == '<')
3021                     tag_start = prev_pos;
3022                   else if (tmp == '>')
3023                     tag_start = -1;
3024                }
3025              if (tag_start == -1)
3026                {
3027                   if (tmp == '&')
3028                     esc_start = prev_pos;
3029                   else if (tmp == ';')
3030                     esc_start = -1;
3031                }
3032           }
3033 
3034         if (tag_start >= 0)
3035           {
3036              sd->append_text_position = tag_start;
3037           }
3038         else if (esc_start >= 0)
3039           {
3040              sd->append_text_position = esc_start;
3041           }
3042         else
3043           {
3044              sd->append_text_position = pos;
3045           }
3046      }
3047    else
3048      {
3049         sd->append_text_position = sd->append_text_len;
3050      }
3051 
3052    backup = sd->append_text_left[sd->append_text_position];
3053    sd->append_text_left[sd->append_text_position] = '\0';
3054 
3055    edje_object_part_text_append
3056      (sd->entry_edje, "elm.text", sd->append_text_left + start);
3057 
3058    sd->append_text_left[sd->append_text_position] = backup;
3059 
3060    evas_event_thaw(evas_object_evas_get(obj));
3061    evas_event_thaw_eval(evas_object_evas_get(obj));
3062 
3063    _elm_entry_guide_update(obj, EINA_TRUE);
3064 
3065    /* If there's still more to go, renew the idler, else, cleanup */
3066    if (sd->append_text_position < sd->append_text_len)
3067      {
3068         return ECORE_CALLBACK_RENEW;
3069      }
3070    else
3071      {
3072         edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
3073               EDJE_CURSOR_MAIN, sd->cursor_pos);
3074         free(sd->append_text_left);
3075         sd->append_text_left = NULL;
3076         sd->append_text_idler = NULL;
3077         efl_event_callback_legacy_call
3078           (obj, ELM_ENTRY_EVENT_TEXT_SET_DONE, NULL);
3079         return ECORE_CALLBACK_CANCEL;
3080      }
3081 }
3082 
3083 static void
my_string_copy_truncate(char * dest,const char * src,size_t len)3084 my_string_copy_truncate(char *dest, const char *src, size_t len)
3085 {
3086    char *p;
3087    for (p = dest; len > 0; p++, src++, len--)
3088      {
3089         *p = *src;
3090         if (*src == 0) break;
3091      }
3092 }
3093 
3094 static void
_chars_add_till_limit(Evas_Object * obj,char ** text,int can_add,Length_Unit unit)3095 _chars_add_till_limit(Evas_Object *obj,
3096                       char **text,
3097                       int can_add,
3098                       Length_Unit unit)
3099 {
3100    int i = 0, current_len = 0;
3101    char *new_text;
3102 
3103    if (!*text) return;
3104    if (unit >= LENGTH_UNIT_LAST) return;
3105    if (strstr(*text, "<preedit")) return;
3106 
3107    new_text = *text;
3108    current_len = strlen(*text);
3109    while (*new_text)
3110      {
3111         int idx = 0, unit_size = 0;
3112         char *markup, *utfstr;
3113 
3114         if (*new_text == '<')
3115           {
3116              while (*(new_text + idx) != '>')
3117                {
3118                   idx++;
3119                   if (!*(new_text + idx)) break;
3120                }
3121           }
3122         else if (*new_text == '&')
3123           {
3124              while (*(new_text + idx) != ';')
3125                {
3126                   idx++;
3127                   if (!*(new_text + idx)) break;
3128                }
3129           }
3130         idx = evas_string_char_next_get(new_text, idx, NULL);
3131         markup = malloc(idx + 1);
3132         if (markup)
3133           {
3134              strncpy(markup, new_text, idx);
3135              markup[idx] = 0;
3136              utfstr = elm_entry_markup_to_utf8(markup);
3137              if (utfstr)
3138                {
3139                   if (unit == LENGTH_UNIT_BYTE)
3140                     unit_size = strlen(utfstr);
3141                   else if (unit == LENGTH_UNIT_CHAR)
3142                     unit_size = evas_string_char_len_get(utfstr);
3143                   ELM_SAFE_FREE(utfstr, free);
3144                }
3145              ELM_SAFE_FREE(markup, free);
3146           }
3147         if (can_add < unit_size)
3148           {
3149              if (!i)
3150                {
3151                   efl_event_callback_legacy_call
3152                     (obj, ELM_ENTRY_EVENT_MAXLENGTH_REACHED, NULL);
3153                   ELM_SAFE_FREE(*text, free);
3154                   return;
3155                }
3156              can_add = 0;
3157              my_string_copy_truncate(new_text, new_text + idx,
3158                                      current_len - ((new_text + idx) - *text));
3159              current_len -= idx;
3160              (*text)[current_len] = 0;
3161           }
3162         else
3163           {
3164              new_text += idx;
3165              can_add -= unit_size;
3166           }
3167         i++;
3168      }
3169 
3170    efl_event_callback_legacy_call(obj, ELM_ENTRY_EVENT_MAXLENGTH_REACHED, NULL);
3171 }
3172 
3173 EOLIAN static void
_elm_entry_efl_layout_signal_signal_emit(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * emission,const char * source)3174 _elm_entry_efl_layout_signal_signal_emit(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const char *emission, const char *source)
3175 {
3176    /* always pass to both edje objs */
3177    edje_object_signal_emit(sd->entry_edje, emission, source);
3178    edje_object_message_signal_process(sd->entry_edje);
3179 
3180    if (sd->scr_edje)
3181      {
3182         edje_object_signal_emit(sd->scr_edje, emission, source);
3183         edje_object_message_signal_process(sd->scr_edje);
3184      }
3185 }
3186 
3187 static Eina_Bool
_elm_entry_efl_layout_signal_signal_callback_add(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)3188 _elm_entry_efl_layout_signal_signal_callback_add(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd,
3189                                                  const char *emission, const char *source,
3190                                                  void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
3191 {
3192    Eina_Bool ok;
3193 
3194    ok = efl_layout_signal_callback_add(sd->entry_edje, emission, source, func_data, func, func_free_cb);
3195    if (sd->scr_edje)
3196      ok = efl_layout_signal_callback_add(sd->scr_edje, emission, source, func_data, func, func_free_cb);
3197 
3198    return ok;
3199 }
3200 
3201 static Eina_Bool
_elm_entry_efl_layout_signal_signal_callback_del(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)3202 _elm_entry_efl_layout_signal_signal_callback_del(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd,
3203                                                  const char *emission, const char *source,
3204                                                  void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
3205 {
3206    Eina_Bool ok;
3207 
3208    ok = efl_layout_signal_callback_del(sd->entry_edje, emission, source, func_data, func, func_free_cb);
3209    if (sd->scr_edje)
3210      ok = efl_layout_signal_callback_del(sd->scr_edje, emission, source, func_data, func, func_free_cb);
3211 
3212    return ok;
3213 }
3214 
3215 // Legacy support... del() returns the user data.
3216 void
_elm_entry_signal_callback_add_legacy(Eo * obj,const char * emission,const char * source,Edje_Signal_Cb func_cb,void * data)3217 _elm_entry_signal_callback_add_legacy(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
3218 {
3219    Elm_Entry_Data *sd;
3220 
3221    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3222    if (!sd) return;
3223 
3224    _elm_layout_signal_callback_add_legacy(obj, sd->entry_edje, &sd->edje_signals,
3225                                           emission, source, func_cb, data);
3226 
3227    if (sd->scr_edje)
3228      efl_layout_signal_callback_add(sd->scr_edje, emission, source, data, func_cb, NULL);
3229 }
3230 
3231 void *
_elm_entry_signal_callback_del_legacy(Eo * obj,const char * emission,const char * source,Edje_Signal_Cb func_cb)3232 _elm_entry_signal_callback_del_legacy(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb)
3233 {
3234    Elm_Entry_Data *sd;
3235    void *data;
3236 
3237    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3238    if (!sd) return NULL;
3239 
3240    data = _elm_layout_signal_callback_del_legacy(obj, sd->entry_edje, &sd->edje_signals,
3241                                                  emission, source, func_cb);
3242 
3243    if (sd->scr_edje)
3244      efl_layout_signal_callback_del(sd->scr_edje, emission, source, data, func_cb, NULL);
3245 
3246    return data;
3247 }
3248 
3249 static Eina_Bool
_elm_entry_content_set(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,const char * part,Evas_Object * content)3250 _elm_entry_content_set(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, const char *part, Evas_Object *content)
3251 {
3252    Eina_Bool int_ret = EINA_FALSE;
3253    int_ret = efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content);
3254    if (!int_ret) return EINA_FALSE;
3255 
3256    /* too bad entry does not follow the pattern
3257     * "elm,state,{icon,end},visible", we have to repeat ourselves */
3258    if (!part || !strcmp(part, "icon") || !strcmp(part, "elm.swallow.icon"))
3259      elm_entry_icon_visible_set(obj, EINA_TRUE);
3260 
3261    if (part && (!strcmp(part, "end") || !strcmp(part, "elm.swallow.end")))
3262      elm_entry_end_visible_set(obj, EINA_TRUE);
3263 
3264    return EINA_TRUE;
3265 }
3266 
3267 static Evas_Object*
_elm_entry_content_unset(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,const char * part)3268 _elm_entry_content_unset(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, const char *part)
3269 {
3270    Evas_Object *ret = NULL;
3271    ret = efl_content_unset(efl_part(efl_super(obj, MY_CLASS), part));
3272    if (!ret) return NULL;
3273 
3274    /* too bad entry does not follow the pattern
3275     * "elm,state,{icon,end},hidden", we have to repeat ourselves */
3276    if (!part || !strcmp(part, "icon") || !strcmp(part, "elm.swallow.icon"))
3277      elm_entry_icon_visible_set(obj, EINA_FALSE);
3278 
3279    if (part && (!strcmp(part, "end") || !strcmp(part, "elm.swallow.end")))
3280      elm_entry_end_visible_set(obj, EINA_FALSE);
3281 
3282    return ret;
3283 }
3284 
3285 static void
_entry_text_append(Evas_Object * obj,const char * entry,Eina_Bool set)3286 _entry_text_append(Evas_Object* obj, const char* entry, Eina_Bool set)
3287 {
3288    int len = 0;
3289    if (!entry) return;
3290 
3291    ELM_ENTRY_DATA_GET(obj, sd);
3292    if (!sd) return;
3293    len = strlen(entry);
3294 
3295    if (sd->append_text_left)
3296      {
3297         char *tmpbuf;
3298 
3299         tmpbuf = realloc(sd->append_text_left, sd->append_text_len + len + 1);
3300         if (!tmpbuf)
3301           {
3302              /* Do something */
3303              return;
3304           }
3305         sd->append_text_left = tmpbuf;
3306         memcpy(sd->append_text_left + sd->append_text_len, entry, len + 1);
3307         sd->append_text_len += len;
3308      }
3309    else
3310      {
3311         if (len > ELM_ENTRY_CHUNK_SIZE)
3312           {
3313              sd->append_text_left = (char *)malloc(len + 1);
3314           }
3315 
3316         if (sd->append_text_left)
3317           {
3318              memcpy(sd->append_text_left, entry, len + 1);
3319              sd->append_text_position = 0;
3320              sd->append_text_len = len;
3321              sd->append_text_idler = ecore_idler_add(_text_append_idler, obj);
3322           }
3323         else
3324           {
3325              if (set)
3326                {
3327                   edje_object_part_text_set(sd->entry_edje, "elm.text", entry);
3328                }
3329              else
3330                {
3331                   edje_object_part_text_append(sd->entry_edje, "elm.text", entry);
3332                }
3333              edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
3334                    EDJE_CURSOR_MAIN, sd->cursor_pos);
3335              efl_event_callback_legacy_call(obj, ELM_ENTRY_EVENT_TEXT_SET_DONE, NULL);
3336           }
3337      }
3338 }
3339 
3340 static Eina_Bool
_elm_entry_text_set(Eo * obj,Elm_Entry_Data * sd,const char * part,const char * entry)3341 _elm_entry_text_set(Eo *obj, Elm_Entry_Data *sd, const char *part, const char *entry)
3342 {
3343    int len = 0;
3344    const char * current_text = NULL;
3345 
3346    if (!entry) entry = "";
3347    if (!_elm_layout_part_aliasing_eval(obj, &part, EINA_TRUE))
3348      return EINA_FALSE;
3349 
3350    if (strcmp(part, "elm.text"))
3351      {
3352         edje_object_part_text_set(sd->entry_edje, part, entry);
3353 
3354         return EINA_TRUE;
3355      }
3356 
3357    evas_event_freeze(evas_object_evas_get(obj));
3358 
3359    /* Clear currently pending job if there is one */
3360    if (sd->append_text_idler)
3361      {
3362         ecore_idler_del(sd->append_text_idler);
3363         ELM_SAFE_FREE(sd->append_text_left, free);
3364         sd->append_text_idler = NULL;
3365      }
3366 
3367    len = strlen(entry);
3368    if (sd->append_text_left)
3369      {
3370         free(sd->append_text_left);
3371         sd->append_text_left = NULL;
3372      }
3373 
3374    /* If old and new text are the same do nothing */
3375    current_text = edje_object_part_text_get(sd->entry_edje, "elm.text");
3376    if (eina_streq(current_text, entry))
3377      goto done;
3378 
3379    ELM_SAFE_FREE(sd->text, eina_stringshare_del);
3380    sd->changed = EINA_TRUE;
3381 
3382    /* Need to clear the entry first */
3383    sd->cursor_pos = edje_object_part_text_cursor_pos_get
3384        (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
3385    edje_object_part_text_set(sd->entry_edje, "elm.text", "");
3386    _entry_text_append(obj, entry, EINA_TRUE);
3387 
3388    if (len > 0)
3389      _elm_entry_guide_update(obj, EINA_TRUE);
3390    else
3391      _elm_entry_guide_update(obj, EINA_FALSE);
3392 
3393 done:
3394    evas_event_thaw(evas_object_evas_get(obj));
3395    evas_event_thaw_eval(evas_object_evas_get(obj));
3396    return EINA_TRUE;
3397 }
3398 
3399 static const char *
_elm_entry_text_get(Eo * obj,Elm_Entry_Data * sd,const char * item)3400 _elm_entry_text_get(Eo *obj, Elm_Entry_Data *sd, const char *item)
3401 {
3402    const char *text;
3403 
3404    if (!_elm_layout_part_aliasing_eval(obj, &item, EINA_TRUE))
3405      return NULL;
3406 
3407    if (strcmp(item, "elm.text"))
3408      return edje_object_part_text_get(sd->entry_edje, item);
3409 
3410    text = edje_object_part_text_get(sd->entry_edje, "elm.text");
3411    if (!text)
3412      {
3413         ERR("text=NULL for edje %p, part 'elm.text'", sd->entry_edje);
3414 
3415         return NULL;
3416      }
3417 
3418    if (sd->append_text_len > 0)
3419      {
3420         char *tmpbuf;
3421         size_t len, tlen;
3422 
3423         tlen = strlen(text);
3424         len = tlen + sd->append_text_len - sd->append_text_position;
3425         /* FIXME: need that or we do copy uninitialised data */
3426         tmpbuf = calloc(1, len + 1);
3427         if (!tmpbuf)
3428           {
3429              ERR("Failed to allocate memory for entry's text %p", obj);
3430              return NULL;
3431           }
3432         memcpy(tmpbuf, text, tlen);
3433 
3434         if (sd->append_text_left)
3435           memcpy(tmpbuf + tlen, sd->append_text_left
3436                  + sd->append_text_position, sd->append_text_len
3437                  - sd->append_text_position);
3438         tmpbuf[len] = '\0';
3439         eina_stringshare_replace(&sd->text, tmpbuf);
3440         free(tmpbuf);
3441      }
3442    else
3443      {
3444         eina_stringshare_replace(&sd->text, text);
3445      }
3446 
3447    return sd->text;
3448 }
3449 
3450 static char *
_access_info_cb(void * data EINA_UNUSED,Evas_Object * obj)3451 _access_info_cb(void *data EINA_UNUSED, Evas_Object *obj)
3452 {
3453    const char *txt;
3454 
3455    ELM_ENTRY_DATA_GET(obj, sd);
3456 
3457    if (!sd) return NULL;
3458    if (sd->password) return NULL;
3459 
3460    txt = elm_widget_access_info_get(obj);
3461 
3462    if (!txt)
3463      return _elm_util_mkup_to_text(elm_entry_entry_get(obj));
3464    else return strdup(txt);
3465 }
3466 
3467 static char *
_access_state_cb(void * data EINA_UNUSED,Evas_Object * obj)3468 _access_state_cb(void *data EINA_UNUSED, Evas_Object *obj)
3469 {
3470    Eina_Strbuf *buf;
3471    char *ret;
3472 
3473    ELM_ENTRY_DATA_GET(obj, sd);
3474 
3475    if (!sd) return NULL;
3476    ret = NULL;
3477    buf = eina_strbuf_new();
3478 
3479    if (elm_widget_disabled_get(obj))
3480      eina_strbuf_append(buf, "State: Disabled");
3481 
3482    if (!sd->editable)
3483      {
3484         if (!eina_strbuf_length_get(buf))
3485           eina_strbuf_append(buf, "State: Not Editable");
3486         else eina_strbuf_append(buf, ", Not Editable");
3487      }
3488 
3489    if (sd->password)
3490      {
3491         if (!eina_strbuf_length_get(buf))
3492           eina_strbuf_append(buf, "State: Password");
3493         else eina_strbuf_append(buf, ", Password");
3494      }
3495 
3496    if (!eina_strbuf_length_get(buf)) goto buf_free;
3497 
3498    ret = eina_strbuf_string_steal(buf);
3499 
3500 buf_free:
3501    eina_strbuf_free(buf);
3502    return ret;
3503 }
3504 
3505 static void
_entry_selection_callbacks_unregister(Evas_Object * obj)3506 _entry_selection_callbacks_unregister(Evas_Object *obj)
3507 {
3508    ELM_ENTRY_DATA_GET(obj, sd);
3509 
3510    edje_object_signal_callback_del_full
3511      (sd->entry_edje, "selection,start", "elm.text",
3512      _entry_selection_start_signal_cb, obj);
3513    edje_object_signal_callback_del_full
3514      (sd->entry_edje, "selection,changed", "elm.text",
3515      _entry_selection_changed_signal_cb, obj);
3516    edje_object_signal_callback_del_full
3517      (sd->entry_edje, "entry,selection,all,request",
3518      "elm.text", _entry_selection_all_signal_cb, obj);
3519    edje_object_signal_callback_del_full
3520      (sd->entry_edje, "entry,selection,none,request",
3521      "elm.text", _entry_selection_none_signal_cb, obj);
3522    edje_object_signal_callback_del_full
3523      (sd->entry_edje, "selection,cleared", "elm.text",
3524      _entry_selection_cleared_signal_cb, obj);
3525    edje_object_signal_callback_del_full
3526      (sd->entry_edje, "entry,paste,request,*", "elm.text",
3527      _entry_paste_request_signal_cb, obj);
3528    edje_object_signal_callback_del_full
3529      (sd->entry_edje, "entry,copy,notify", "elm.text",
3530      _entry_copy_notify_signal_cb, obj);
3531    edje_object_signal_callback_del_full
3532      (sd->entry_edje, "entry,cut,notify", "elm.text",
3533      _entry_cut_notify_signal_cb, obj);
3534 }
3535 
3536 static void
_entry_selection_callbacks_register(Evas_Object * obj)3537 _entry_selection_callbacks_register(Evas_Object *obj)
3538 {
3539    ELM_ENTRY_DATA_GET(obj, sd);
3540 
3541    edje_object_signal_callback_add
3542      (sd->entry_edje, "selection,start", "elm.text",
3543      _entry_selection_start_signal_cb, obj);
3544    edje_object_signal_callback_add
3545      (sd->entry_edje, "selection,changed", "elm.text",
3546      _entry_selection_changed_signal_cb, obj);
3547    edje_object_signal_callback_add
3548      (sd->entry_edje, "entry,selection,all,request",
3549      "elm.text", _entry_selection_all_signal_cb, obj);
3550    edje_object_signal_callback_add
3551      (sd->entry_edje, "entry,selection,none,request",
3552      "elm.text", _entry_selection_none_signal_cb, obj);
3553    edje_object_signal_callback_add
3554      (sd->entry_edje, "selection,cleared", "elm.text",
3555      _entry_selection_cleared_signal_cb, obj);
3556    edje_object_signal_callback_add
3557      (sd->entry_edje, "entry,paste,request,*", "elm.text",
3558      _entry_paste_request_signal_cb, obj);
3559    edje_object_signal_callback_add
3560      (sd->entry_edje, "entry,copy,notify", "elm.text",
3561      _entry_copy_notify_signal_cb, obj);
3562    edje_object_signal_callback_add
3563      (sd->entry_edje, "entry,cut,notify", "elm.text",
3564      _entry_cut_notify_signal_cb, obj);
3565 }
3566 
3567 static void
_elm_entry_resize_internal(Evas_Object * obj)3568 _elm_entry_resize_internal(Evas_Object *obj)
3569 {
3570    ELM_ENTRY_DATA_GET(obj, sd);
3571 
3572    if (!sd) return;
3573    if (sd->line_wrap)
3574      {
3575         elm_layout_sizing_eval(obj);
3576      }
3577    else if (sd->scroll)
3578      {
3579         Evas_Coord vw = 0, vh = 0;
3580 
3581         elm_interface_scrollable_content_viewport_geometry_get
3582               (obj, NULL, NULL, &vw, &vh);
3583         if (vw < sd->ent_mw) vw = sd->ent_mw;
3584         if (vh < sd->ent_mh) vh = sd->ent_mh;
3585         evas_object_resize(sd->entry_edje, vw, vh);
3586      }
3587 
3588    if (sd->hoversel) _hoversel_position(obj);
3589 }
3590 
3591 static void
_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3592 _resize_cb(void *data,
3593            Evas *e EINA_UNUSED,
3594            Evas_Object *obj EINA_UNUSED,
3595            void *event_info EINA_UNUSED)
3596 {
3597    _elm_entry_resize_internal(data);
3598 }
3599 
3600 static void
_selection_handlers_offset_calc(Evas_Object * obj,Evas_Object * handler,Evas_Coord canvasx,Evas_Coord canvasy)3601 _selection_handlers_offset_calc(Evas_Object *obj, Evas_Object *handler, Evas_Coord canvasx, Evas_Coord canvasy)
3602 {
3603    Evas_Coord ex, ey;
3604    Evas_Coord cx, cy, cw, ch;
3605    Evas_Coord hh;
3606 
3607    ELM_ENTRY_DATA_GET(obj, sd);
3608 
3609    if (!sd) return;
3610    evas_object_geometry_get(sd->entry_edje, &ex, &ey, NULL, NULL);
3611    edje_object_part_text_cursor_geometry_get(sd->entry_edje, "elm.text",
3612                                                            &cx, &cy, &cw, &ch);
3613    edje_object_size_min_calc(handler, NULL, &hh);
3614 
3615    sd->ox = canvasx - (ex + cx + (cw / 2));
3616    if (ch > hh)
3617      sd->oy = canvasy - (ey + cy + ch);
3618    else
3619      sd->oy = canvasy - (ey + cy + (ch / 2));
3620 
3621    ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
3622    sd->long_pressed = EINA_FALSE;
3623    if (_elm_config->magnifier_enable)
3624      {
3625         _magnifier_create(obj);
3626         _magnifier_show(obj);
3627         _magnifier_move(obj);
3628      }
3629 }
3630 
3631 static void
_start_handler_mouse_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3632 _start_handler_mouse_down_cb(void *data,
3633                              Evas *e EINA_UNUSED,
3634                              Evas_Object *obj EINA_UNUSED,
3635                              void *event_info)
3636 {
3637    ELM_ENTRY_DATA_GET(data, sd);
3638 
3639    if (!sd) return;
3640    Evas_Event_Mouse_Down *ev = event_info;
3641    int start_pos, end_pos, main_pos, pos;
3642 
3643    sd->start_handler_down = EINA_TRUE;
3644    start_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3645                                               EDJE_CURSOR_SELECTION_BEGIN);
3646    end_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3647                                               EDJE_CURSOR_SELECTION_END);
3648    main_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3649                                                    EDJE_CURSOR_MAIN);
3650    if (start_pos <= end_pos)
3651      {
3652         pos = start_pos;
3653         sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_BEGIN;
3654      }
3655    else
3656      {
3657         pos = end_pos;
3658         sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_END;
3659      }
3660    if (pos != main_pos)
3661      edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
3662                                           EDJE_CURSOR_MAIN, pos);
3663    _selection_handlers_offset_calc(data, sd->start_handler, ev->canvas.x, ev->canvas.y);
3664 }
3665 
3666 static void
_start_handler_mouse_up_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3667 _start_handler_mouse_up_cb(void *data,
3668                            Evas *e EINA_UNUSED,
3669                            Evas_Object *obj EINA_UNUSED,
3670                            void *event_info EINA_UNUSED)
3671 {
3672    ELM_ENTRY_DATA_GET(data, sd);
3673 
3674    if (!sd) return;
3675    sd->start_handler_down = EINA_FALSE;
3676    if (_elm_config->magnifier_enable)
3677      _magnifier_hide(data);
3678    /* Context menu should not appear, even in case of selector mode, if the
3679     * flag is false (disabled) */
3680    if ((!_elm_config->context_menu_disabled) &&
3681        (!_elm_config->desktop_entry) && (sd->long_pressed))
3682      _menu_call(data);
3683 }
3684 
3685 static void
_start_handler_mouse_move_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3686 _start_handler_mouse_move_cb(void *data,
3687                              Evas *e EINA_UNUSED,
3688                              Evas_Object *obj EINA_UNUSED,
3689                              void *event_info)
3690 {
3691    ELM_ENTRY_DATA_GET(data, sd);
3692 
3693    if (!sd) return;
3694    if (!sd->start_handler_down) return;
3695    Evas_Event_Mouse_Move *ev = event_info;
3696    Evas_Coord ex, ey;
3697    Evas_Coord cx, cy;
3698    int pos;
3699 
3700    evas_object_geometry_get(sd->entry_edje, &ex, &ey, NULL, NULL);
3701    cx = ev->cur.canvas.x - sd->ox - ex;
3702    cy = ev->cur.canvas.y - sd->oy - ey;
3703    if (cx <= 0) cx = 1;
3704 
3705    edje_object_part_text_cursor_coord_set(sd->entry_edje, "elm.text",
3706                                         sd->sel_handler_cursor, cx, cy);
3707    pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3708                                                sd->sel_handler_cursor);
3709    edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
3710                                         EDJE_CURSOR_MAIN, pos);
3711    ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
3712    sd->long_pressed = EINA_FALSE;
3713    if (_elm_config->magnifier_enable)
3714      _magnifier_move(data);
3715 }
3716 
3717 static void
_end_handler_mouse_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3718 _end_handler_mouse_down_cb(void *data,
3719                            Evas *e EINA_UNUSED,
3720                            Evas_Object *obj EINA_UNUSED,
3721                            void *event_info)
3722 {
3723    ELM_ENTRY_DATA_GET(data, sd);
3724 
3725    if (!sd) return;
3726    Evas_Event_Mouse_Down *ev = event_info;
3727    int pos, start_pos, end_pos, main_pos;
3728 
3729    sd->end_handler_down = EINA_TRUE;
3730    start_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3731                                               EDJE_CURSOR_SELECTION_BEGIN);
3732    end_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3733                                               EDJE_CURSOR_SELECTION_END);
3734    if (start_pos < end_pos)
3735      {
3736         pos = end_pos;
3737         sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_END;
3738      }
3739    else
3740      {
3741         pos = start_pos;
3742         sd->sel_handler_cursor = EDJE_CURSOR_SELECTION_BEGIN;
3743      }
3744    main_pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3745                                                    EDJE_CURSOR_MAIN);
3746    if (pos != main_pos)
3747      edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
3748                                           EDJE_CURSOR_MAIN, pos);
3749    _selection_handlers_offset_calc(data, sd->end_handler, ev->canvas.x, ev->canvas.y);
3750 }
3751 
3752 static void
_end_handler_mouse_up_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3753 _end_handler_mouse_up_cb(void *data,
3754                          Evas *e EINA_UNUSED,
3755                          Evas_Object *obj EINA_UNUSED,
3756                          void *event_info EINA_UNUSED)
3757 {
3758    ELM_ENTRY_DATA_GET(data, sd);
3759 
3760    if (!sd) return;
3761    sd->end_handler_down = EINA_FALSE;
3762    if (_elm_config->magnifier_enable)
3763      _magnifier_hide(data);
3764    /* Context menu appear was checked in case of selector start, and hence
3765     * the same should be checked at selector end as well */
3766    if ((!_elm_config->context_menu_disabled) &&
3767        (!_elm_config->desktop_entry) && (sd->long_pressed))
3768      _menu_call(data);
3769 }
3770 
3771 static void
_end_handler_mouse_move_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3772 _end_handler_mouse_move_cb(void *data,
3773                            Evas *e EINA_UNUSED,
3774                            Evas_Object *obj EINA_UNUSED,
3775                            void *event_info)
3776 {
3777    ELM_ENTRY_DATA_GET(data, sd);
3778 
3779    if (!sd) return;
3780    if (!sd->end_handler_down) return;
3781    Evas_Event_Mouse_Move *ev = event_info;
3782    Evas_Coord ex, ey;
3783    Evas_Coord cx, cy;
3784    int pos;
3785 
3786    evas_object_geometry_get(sd->entry_edje, &ex, &ey, NULL, NULL);
3787    cx = ev->cur.canvas.x - sd->ox - ex;
3788    cy = ev->cur.canvas.y - sd->oy - ey;
3789    if (cx <= 0) cx = 1;
3790 
3791    edje_object_part_text_cursor_coord_set(sd->entry_edje, "elm.text",
3792                                           sd->sel_handler_cursor, cx, cy);
3793    pos = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text",
3794                                               sd->sel_handler_cursor);
3795    edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text",
3796                                         EDJE_CURSOR_MAIN, pos);
3797    ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
3798    sd->long_pressed = EINA_FALSE;
3799    if (_elm_config->magnifier_enable)
3800      _magnifier_move(data);
3801 }
3802 
3803 static void
_entry_on_size_evaluate_signal(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)3804 _entry_on_size_evaluate_signal(void *data,
3805                                Evas_Object *obj EINA_UNUSED,
3806                                const char *emission EINA_UNUSED,
3807                                const char *source EINA_UNUSED)
3808 {
3809    ELM_ENTRY_DATA_GET(data, sd);
3810    if (!sd) return;
3811    sd->cur_changed = EINA_TRUE;
3812    elm_entry_calc_force(data);
3813 }
3814 
3815 EOLIAN static void
_elm_entry_efl_canvas_group_group_add(Eo * obj,Elm_Entry_Data * priv)3816 _elm_entry_efl_canvas_group_group_add(Eo *obj, Elm_Entry_Data *priv)
3817 {
3818    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
3819 
3820    if (!elm_widget_theme_klass_get(obj))
3821      elm_widget_theme_klass_set(obj, "entry");
3822    efl_canvas_group_add(efl_super(obj, MY_CLASS));
3823 
3824    priv->entry_edje = wd->resize_obj;
3825 
3826    priv->cnp_mode = ELM_CNP_MODE_MARKUP;
3827    priv->line_wrap = ELM_WRAP_WORD;
3828    priv->context_menu = EINA_TRUE;
3829    priv->auto_save = EINA_TRUE;
3830    priv->editable = EINA_TRUE;
3831    priv->sel_allow = _elm_config->entry_select_allow;
3832 
3833    priv->drop_format = ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE;
3834    elm_drop_target_add(obj, priv->drop_format,
3835                        _dnd_enter_cb, NULL,
3836                        _dnd_leave_cb, NULL,
3837                        _dnd_pos_cb, NULL,
3838                        _dnd_drop_cb, NULL);
3839 
3840    if (elm_widget_theme_object_set(obj, wd->resize_obj,
3841                                        elm_widget_theme_klass_get(obj),
3842                                        elm_widget_theme_element_get(obj),
3843                                        elm_widget_theme_style_get(obj)) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
3844      CRI("Failed to set layout!");
3845 
3846    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
3847    evas_object_data_set(priv->hit_rect, "_elm_leaveme", obj);
3848 
3849    Evas_Object* clip = evas_object_clip_get(priv->entry_edje);
3850    evas_object_clip_set(priv->hit_rect, clip);
3851 
3852    evas_object_smart_member_add(priv->hit_rect, obj);
3853    elm_widget_sub_object_add(obj, priv->hit_rect);
3854 
3855    /* common scroller hit rectangle setup */
3856    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
3857    evas_object_show(priv->hit_rect);
3858    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
3859 
3860    elm_interface_scrollable_objects_set(obj, priv->entry_edje, priv->hit_rect);
3861 
3862    edje_object_item_provider_set(priv->entry_edje, _item_get, obj);
3863 
3864    edje_object_text_markup_filter_callback_add
3865      (priv->entry_edje, "elm.text", _markup_filter_cb, obj);
3866 
3867    evas_object_event_callback_add
3868      (priv->entry_edje, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
3869    evas_object_event_callback_add
3870      (priv->entry_edje, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj);
3871    evas_object_event_callback_add
3872      (priv->entry_edje, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj);
3873    evas_object_event_callback_add
3874      (priv->entry_edje, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, obj);
3875 
3876    /* this code can't go in smart_resize. sizing gets wrong */
3877    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
3878 
3879    edje_object_signal_callback_add
3880      (priv->entry_edje, "entry,changed", "elm.text",
3881      _entry_changed_signal_cb, obj);
3882    edje_object_signal_callback_add
3883      (priv->entry_edje, "entry,changed,user", "elm.text",
3884      _entry_changed_user_signal_cb, obj);
3885    edje_object_signal_callback_add
3886      (priv->entry_edje, "preedit,changed", "elm.text",
3887      _entry_preedit_changed_signal_cb, obj);
3888 
3889    _entry_selection_callbacks_register(obj);
3890 
3891    edje_object_signal_callback_add
3892      (priv->entry_edje, "cursor,changed", "elm.text",
3893      _entry_cursor_changed_signal_cb, obj);
3894    edje_object_signal_callback_add
3895      (priv->entry_edje, "cursor,changed,manual", "elm.text",
3896      _entry_cursor_changed_manual_signal_cb, obj);
3897    edje_object_signal_callback_add
3898      (priv->entry_edje, "anchor,mouse,down,*", "elm.text",
3899      _entry_anchor_down_signal_cb, obj);
3900    edje_object_signal_callback_add
3901      (priv->entry_edje, "anchor,mouse,up,*", "elm.text",
3902      _entry_anchor_up_signal_cb, obj);
3903    edje_object_signal_callback_add
3904      (priv->entry_edje, "anchor,mouse,clicked,*", "elm.text",
3905      _entry_anchor_clicked_signal_cb, obj);
3906    edje_object_signal_callback_add
3907      (priv->entry_edje, "anchor,mouse,move,*", "elm.text",
3908      _entry_anchor_move_signal_cb, obj);
3909    edje_object_signal_callback_add
3910      (priv->entry_edje, "anchor,mouse,in,*", "elm.text",
3911      _entry_anchor_in_signal_cb, obj);
3912    edje_object_signal_callback_add
3913      (priv->entry_edje, "anchor,mouse,out,*", "elm.text",
3914      _entry_anchor_out_signal_cb, obj);
3915    edje_object_signal_callback_add
3916      (priv->entry_edje, "entry,key,enter", "elm.text",
3917      _entry_key_enter_signal_cb, obj);
3918    edje_object_signal_callback_add
3919      (priv->entry_edje, "entry,key,escape", "elm.text",
3920      _entry_key_escape_signal_cb, obj);
3921    edje_object_signal_callback_add
3922      (priv->entry_edje, "mouse,down,1", "elm.text",
3923      _entry_mouse_down_signal_cb, obj);
3924    edje_object_signal_callback_add
3925      (priv->entry_edje, "mouse,clicked,1", "elm.text",
3926      _entry_mouse_clicked_signal_cb, obj);
3927    edje_object_signal_callback_add
3928      (priv->entry_edje, "mouse,down,1,double", "elm.text",
3929      _entry_mouse_double_signal_cb, obj);
3930    edje_object_signal_callback_add
3931      (priv->entry_edje, "mouse,down,1,triple", "elm.text",
3932      _entry_mouse_triple_signal_cb, obj);
3933    edje_object_signal_callback_add
3934      (priv->entry_edje, "entry,undo,request", "elm.text",
3935      _entry_undo_request_signal_cb, obj);
3936    edje_object_signal_callback_add
3937      (priv->entry_edje, "entry,redo,request", "elm.text",
3938      _entry_redo_request_signal_cb, obj);
3939 
3940    elm_layout_text_set(obj, "elm.text", "");
3941 
3942    elm_object_sub_cursor_set
3943      (wd->resize_obj, obj, ELM_CURSOR_XTERM);
3944    elm_widget_can_focus_set(obj, EINA_TRUE);
3945    if (priv->sel_allow && _elm_config->desktop_entry)
3946      edje_object_part_text_select_allow_set
3947        (priv->entry_edje, "elm.text", EINA_TRUE);
3948 
3949    elm_layout_sizing_eval(obj);
3950 
3951    elm_entry_input_panel_layout_set(obj, ELM_INPUT_PANEL_LAYOUT_NORMAL);
3952    elm_entry_input_panel_enabled_set(obj, EINA_TRUE);
3953    elm_entry_prediction_allow_set(obj, EINA_TRUE);
3954    elm_entry_input_hint_set(obj, ELM_INPUT_HINT_AUTO_COMPLETE);
3955 
3956    priv->autocapital_type = (Elm_Autocapital_Type)edje_object_part_text_autocapital_type_get
3957        (priv->entry_edje, "elm.text");
3958 
3959    entries = eina_list_prepend(entries, obj);
3960 
3961    // module - find module for entry
3962    priv->api = _module_find(obj);
3963    // if found - hook in
3964    if ((priv->api) && (priv->api->obj_hook)) priv->api->obj_hook(obj);
3965 
3966    _mirrored_set(obj, efl_ui_mirrored_get(obj));
3967 
3968    // access
3969    _elm_access_object_register(obj, priv->entry_edje);
3970    _elm_access_text_set
3971      (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("Entry"));
3972    _elm_access_callback_set
3973      (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL);
3974    _elm_access_callback_set
3975      (_elm_access_info_get(obj), ELM_ACCESS_STATE, _access_state_cb, NULL);
3976 
3977    if (_elm_config->desktop_entry)
3978      priv->sel_handler_disabled = EINA_TRUE;
3979 
3980    edje_object_signal_callback_add
3981       (priv->entry_edje, "size,eval", "elm",
3982        _entry_on_size_evaluate_signal, obj);
3983 }
3984 
3985 static void
_create_selection_handlers(Evas_Object * obj,Elm_Entry_Data * sd)3986 _create_selection_handlers(Evas_Object *obj, Elm_Entry_Data *sd)
3987 {
3988    Evas_Object *handle;
3989    const char *style = elm_widget_style_get(obj);
3990 
3991    handle = edje_object_add(evas_object_evas_get(obj));
3992    sd->start_handler = handle;
3993    _elm_theme_object_set(obj, handle, "entry", "handler/start", style);
3994    evas_object_event_callback_add(handle, EVAS_CALLBACK_MOUSE_DOWN,
3995                                   _start_handler_mouse_down_cb, obj);
3996    evas_object_event_callback_add(handle, EVAS_CALLBACK_MOUSE_MOVE,
3997                                   _start_handler_mouse_move_cb, obj);
3998    evas_object_event_callback_add(handle, EVAS_CALLBACK_MOUSE_UP,
3999                                   _start_handler_mouse_up_cb, obj);
4000    evas_object_show(handle);
4001 
4002    handle = edje_object_add(evas_object_evas_get(obj));
4003    sd->end_handler = handle;
4004    _elm_theme_object_set(obj, handle, "entry", "handler/end", style);
4005    evas_object_event_callback_add(handle, EVAS_CALLBACK_MOUSE_DOWN,
4006                                   _end_handler_mouse_down_cb, obj);
4007    evas_object_event_callback_add(handle, EVAS_CALLBACK_MOUSE_MOVE,
4008                                   _end_handler_mouse_move_cb, obj);
4009    evas_object_event_callback_add(handle, EVAS_CALLBACK_MOUSE_UP,
4010                                   _end_handler_mouse_up_cb, obj);
4011    evas_object_show(handle);
4012 }
4013 
4014 EOLIAN static void
_elm_entry_efl_canvas_group_group_del(Eo * obj,Elm_Entry_Data * sd)4015 _elm_entry_efl_canvas_group_group_del(Eo *obj, Elm_Entry_Data *sd)
4016 {
4017    Elm_Entry_Context_Menu_Item *it;
4018    Elm_Entry_Item_Provider *ip;
4019    Elm_Entry_Markup_Filter *tf;
4020 
4021    if (sd->delay_write)
4022      {
4023         ELM_SAFE_FREE(sd->delay_write, ecore_timer_del);
4024         if (sd->auto_save) _save_do(obj);
4025      }
4026 
4027    edje_object_signal_callback_del_full
4028       (sd->entry_edje, "size,eval", "elm",
4029        _entry_on_size_evaluate_signal, obj);
4030 
4031    if (sd->scroll)
4032      elm_interface_scrollable_content_viewport_resize_cb_set(obj, NULL);
4033 
4034    elm_entry_anchor_hover_end(obj);
4035    elm_entry_anchor_hover_parent_set(obj, NULL);
4036 
4037    evas_event_freeze(evas_object_evas_get(obj));
4038 
4039    eina_stringshare_del(sd->file);
4040 
4041    ecore_job_del(sd->hov_deljob);
4042    if ((sd->api) && (sd->api->obj_unhook))
4043      sd->api->obj_unhook(obj);  // module - unhook
4044 
4045    evas_object_del(sd->mgf_proxy);
4046    evas_object_del(sd->mgf_bg);
4047    evas_object_del(sd->mgf_clip);
4048 
4049    entries = eina_list_remove(entries, obj);
4050    eina_stringshare_del(sd->cut_sel);
4051    eina_stringshare_del(sd->text);
4052    ecore_job_del(sd->deferred_recalc_job);
4053    if (sd->append_text_idler)
4054      {
4055         ecore_idler_del(sd->append_text_idler);
4056         ELM_SAFE_FREE(sd->append_text_left, free);
4057         sd->append_text_idler = NULL;
4058      }
4059    ecore_timer_del(sd->longpress_timer);
4060    EINA_LIST_FREE(sd->items, it)
4061      {
4062         eina_stringshare_del(it->label);
4063         eina_stringshare_del(it->icon_file);
4064         eina_stringshare_del(it->icon_group);
4065         free(it);
4066      }
4067    EINA_LIST_FREE(sd->item_providers, ip)
4068      {
4069         free(ip);
4070      }
4071    EINA_LIST_FREE(sd->markup_filters, tf)
4072      {
4073         _filter_free(tf);
4074      }
4075    ELM_SAFE_FREE(sd->delay_write, ecore_timer_del);
4076    free(sd->input_panel_imdata);
4077 
4078    if (sd->prediction_hint)
4079      {
4080         ELM_SAFE_FREE(sd->prediction_hint, free);
4081      }
4082 
4083    eina_stringshare_del(sd->anchor_hover.hover_style);
4084 
4085    evas_event_thaw(evas_object_evas_get(obj));
4086    evas_event_thaw_eval(evas_object_evas_get(obj));
4087 
4088    if (sd->start_handler)
4089      {
4090         evas_object_del(sd->start_handler);
4091         evas_object_del(sd->end_handler);
4092      }
4093 
4094    efl_canvas_group_del(efl_super(obj, MY_CLASS));
4095 }
4096 
4097 EOLIAN static void
_elm_entry_efl_gfx_entity_position_set(Eo * obj,Elm_Entry_Data * sd,Eina_Position2D pos)4098 _elm_entry_efl_gfx_entity_position_set(Eo *obj, Elm_Entry_Data *sd, Eina_Position2D pos)
4099 {
4100    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
4101      return;
4102 
4103    efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
4104    efl_gfx_entity_position_set(sd->hit_rect, pos);
4105 
4106    if (sd->hoversel) _hoversel_position(obj);
4107 
4108    if (edje_object_part_text_selection_get(sd->entry_edje, "elm.text"))
4109      _update_selection_handler(obj);
4110 }
4111 
4112 EOLIAN static void
_elm_entry_efl_gfx_entity_size_set(Eo * obj,Elm_Entry_Data * sd,Eina_Size2D sz)4113 _elm_entry_efl_gfx_entity_size_set(Eo *obj, Elm_Entry_Data *sd, Eina_Size2D sz)
4114 {
4115    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
4116      return;
4117 
4118    efl_gfx_entity_size_set(sd->hit_rect, sz);
4119    if (sd->have_selection)
4120      _update_selection_handler(obj);
4121 
4122    efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
4123 }
4124 
4125 EOLIAN static void
_elm_entry_efl_gfx_entity_visible_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool vis)4126 _elm_entry_efl_gfx_entity_visible_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool vis)
4127 {
4128    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
4129      return;
4130 
4131    efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
4132 
4133    if (sd->have_selection)
4134      {
4135         if (vis) _update_selection_handler(obj);
4136         else _hide_selection_handler(obj);
4137      }
4138 }
4139 
4140 EOLIAN static void
_elm_entry_efl_canvas_group_group_member_add(Eo * obj,Elm_Entry_Data * sd,Evas_Object * member)4141 _elm_entry_efl_canvas_group_group_member_add(Eo *obj, Elm_Entry_Data *sd, Evas_Object *member)
4142 {
4143    efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member);
4144 
4145    if (sd->hit_rect)
4146      evas_object_raise(sd->hit_rect);
4147 }
4148 
4149 EAPI Evas_Object *
elm_entry_add(Evas_Object * parent)4150 elm_entry_add(Evas_Object *parent)
4151 {
4152    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
4153    return elm_legacy_add(MY_CLASS, parent);
4154 }
4155 
4156 static void
_cb_added(void * data EINA_UNUSED,const Efl_Event * ev)4157 _cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
4158 {
4159    const Efl_Callback_Array_Item_Full *event = ev->info;
4160 
4161    ELM_ENTRY_DATA_GET(ev->object, sd);
4162    // XXX: BUG - not walking the array until a NULL entry
4163    if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
4164      sd->validators++;
4165 }
4166 
4167 static void
_cb_deleted(void * data EINA_UNUSED,const Efl_Event * ev)4168 _cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev)
4169 {
4170    const Efl_Callback_Array_Item_Full *event = ev->info;
4171 
4172    ELM_ENTRY_DATA_GET(ev->object, sd);
4173    // XXX: BUG - not walking the array until a NULL entry
4174    if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
4175      sd->validators--;
4176    return;
4177 
4178 }
4179 
4180 EOLIAN static Eo *
_elm_entry_efl_object_constructor(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED)4181 _elm_entry_efl_object_constructor(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED)
4182 {
4183    obj = efl_constructor(efl_super(obj, MY_CLASS));
4184    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
4185    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
4186    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
4187    efl_event_callback_add(obj, EFL_EVENT_CALLBACK_ADD, _cb_added, NULL);
4188    efl_event_callback_add(obj, EFL_EVENT_CALLBACK_DEL, _cb_deleted, NULL);
4189    legacy_object_focus_handle(obj);
4190 
4191    return obj;
4192 }
4193 
4194 EOLIAN static void
_elm_entry_text_style_user_push(Eo * obj,Elm_Entry_Data * sd,const char * style)4195 _elm_entry_text_style_user_push(Eo *obj, Elm_Entry_Data *sd, const char *style)
4196 {
4197    edje_object_part_text_style_user_push(sd->entry_edje, "elm.text", style);
4198    efl_ui_widget_theme_apply(obj);
4199 }
4200 
4201 EOLIAN static void
_elm_entry_text_style_user_pop(Eo * obj,Elm_Entry_Data * sd)4202 _elm_entry_text_style_user_pop(Eo *obj, Elm_Entry_Data *sd)
4203 {
4204    edje_object_part_text_style_user_pop(sd->entry_edje, "elm.text");
4205 
4206    efl_ui_widget_theme_apply(obj);
4207 }
4208 
4209 EOLIAN static const char*
_elm_entry_text_style_user_peek(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4210 _elm_entry_text_style_user_peek(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4211 {
4212    return edje_object_part_text_style_user_peek(sd->entry_edje, "elm.text");
4213 }
4214 
4215 EOLIAN static void
_elm_entry_single_line_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool single_line)4216 _elm_entry_single_line_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool single_line)
4217 {
4218    if (sd->single_line == single_line) return;
4219 
4220    sd->single_line = single_line;
4221    sd->line_wrap = ELM_WRAP_NONE;
4222    if (elm_entry_cnp_mode_get(obj) == ELM_CNP_MODE_MARKUP)
4223      elm_entry_cnp_mode_set(obj, ELM_CNP_MODE_NO_IMAGE);
4224    if (sd->single_line)
4225      {
4226         _entry_new_line_filter_init(obj);
4227         elm_entry_markup_filter_append(obj, _entry_new_line_filter_cb, NULL);
4228      }
4229    else
4230      {
4231         elm_entry_markup_filter_remove(obj, _entry_new_line_filter_cb, NULL);
4232      }
4233    efl_ui_widget_theme_apply(obj);
4234 
4235    if (sd->scroll)
4236      {
4237         if (sd->single_line)
4238            elm_interface_scrollable_policy_set(obj, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
4239         else
4240           {
4241              elm_interface_scrollable_policy_set(obj, sd->policy_h, sd->policy_v);
4242           }
4243         elm_layout_sizing_eval(obj);
4244      }
4245 }
4246 
4247 EOLIAN static Eina_Bool
_elm_entry_single_line_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4248 _elm_entry_single_line_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4249 {
4250    return sd->single_line;
4251 }
4252 
4253 EOLIAN static void
_elm_entry_password_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool password)4254 _elm_entry_password_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool password)
4255 {
4256    password = !!password;
4257 
4258    if (sd->password == password) return;
4259    sd->password = password;
4260 
4261    elm_drop_target_del(obj, sd->drop_format,
4262                        _dnd_enter_cb, NULL,
4263                        _dnd_leave_cb, NULL,
4264                        _dnd_pos_cb, NULL,
4265                        _dnd_drop_cb, NULL);
4266    if (password)
4267      {
4268         sd->single_line = EINA_TRUE;
4269         sd->line_wrap = ELM_WRAP_NONE;
4270         elm_entry_input_hint_set(obj, ((sd->input_hints & ~ELM_INPUT_HINT_AUTO_COMPLETE) | ELM_INPUT_HINT_SENSITIVE_DATA));
4271         _entry_selection_callbacks_unregister(obj);
4272         efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PASSWORD_TEXT);
4273      }
4274    else
4275      {
4276         sd->drop_format = _get_drop_format(obj);
4277         elm_drop_target_add(obj, sd->drop_format,
4278                             _dnd_enter_cb, NULL,
4279                             _dnd_leave_cb, NULL,
4280                             _dnd_pos_cb, NULL,
4281                             _dnd_drop_cb, NULL);
4282 
4283         elm_entry_input_hint_set(obj, ((sd->input_hints | ELM_INPUT_HINT_AUTO_COMPLETE) & ~ELM_INPUT_HINT_SENSITIVE_DATA));
4284         _entry_selection_callbacks_register(obj);
4285         efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
4286      }
4287 
4288    efl_ui_widget_theme_apply(obj);
4289 }
4290 
4291 EOLIAN static Eina_Bool
_elm_entry_password_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4292 _elm_entry_password_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4293 {
4294    return sd->password;
4295 }
4296 
4297 EAPI void
elm_entry_calc_force(Evas_Object * obj)4298 elm_entry_calc_force(Evas_Object *obj)
4299 {
4300    efl_layout_calc_force(obj);
4301 }
4302 
4303 EAPI void
elm_entry_entry_set(Evas_Object * obj,const char * entry)4304 elm_entry_entry_set(Evas_Object *obj,
4305                     const char *entry)
4306 {
4307    ELM_ENTRY_CHECK(obj);
4308    efl_text_set(efl_part(obj, "elm.text"), entry);
4309 }
4310 
4311 EAPI const char *
elm_entry_entry_get(const Evas_Object * obj)4312 elm_entry_entry_get(const Evas_Object *obj)
4313 {
4314    ELM_ENTRY_CHECK(obj) NULL;
4315    const char *text = NULL;
4316    text = efl_text_get(efl_part(obj, "elm.text"));
4317    return text;
4318 }
4319 
4320 EOLIAN static void
_elm_entry_entry_append(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * entry)4321 _elm_entry_entry_append(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const char *entry)
4322 {
4323    if (!entry) entry = "";
4324 
4325    sd->changed = EINA_TRUE;
4326    _entry_text_append(obj, entry, EINA_FALSE);
4327 }
4328 
4329 EOLIAN static Eina_Bool
_elm_entry_is_empty(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4330 _elm_entry_is_empty(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4331 {
4332    edje_object_part_text_cursor_copy
4333                (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN, EDJE_CURSOR_USER);
4334    edje_object_part_text_cursor_pos_set
4335                               (sd->entry_edje, "elm.text", EDJE_CURSOR_USER, 1);
4336    if (edje_object_part_text_cursor_pos_get
4337                             (sd->entry_edje, "elm.text", EDJE_CURSOR_USER) == 1)
4338      return EINA_FALSE;
4339 
4340    return EINA_TRUE;
4341 }
4342 
4343 EOLIAN static Evas_Object*
_elm_entry_textblock_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4344 _elm_entry_textblock_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4345 {
4346    return (Evas_Object *)edje_object_part_object_get
4347         (sd->entry_edje, "elm.text");
4348 }
4349 
4350 EOLIAN static void
_elm_entry_efl_layout_calc_calc_force(Eo * obj,Elm_Entry_Data * sd)4351 _elm_entry_efl_layout_calc_calc_force(Eo *obj, Elm_Entry_Data *sd)
4352 {
4353    edje_object_calc_force(sd->entry_edje);
4354    sd->changed = EINA_TRUE;
4355    elm_layout_sizing_eval(obj);
4356 }
4357 
4358 EOLIAN static const char*
_elm_entry_selection_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4359 _elm_entry_selection_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4360 {
4361    if ((sd->password)) return NULL;
4362    return edje_object_part_text_selection_get(sd->entry_edje, "elm.text");
4363 }
4364 
4365 EOLIAN static void
_elm_entry_selection_handler_disabled_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool disabled)4366 _elm_entry_selection_handler_disabled_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool disabled)
4367 {
4368    if (sd->sel_handler_disabled == disabled) return;
4369    sd->sel_handler_disabled = disabled;
4370 }
4371 
4372 EOLIAN static Eina_Bool
_elm_entry_selection_handler_disabled_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4373 _elm_entry_selection_handler_disabled_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4374 {
4375    return sd->sel_handler_disabled;
4376 }
4377 
4378 EOLIAN static void
_elm_entry_entry_insert(Eo * obj,Elm_Entry_Data * sd,const char * entry)4379 _elm_entry_entry_insert(Eo *obj, Elm_Entry_Data *sd, const char *entry)
4380 {
4381    edje_object_part_text_insert(sd->entry_edje, "elm.text", entry);
4382    sd->changed = EINA_TRUE;
4383    elm_layout_sizing_eval(obj);
4384 }
4385 
4386 EOLIAN static void
_elm_entry_line_wrap_set(Eo * obj,Elm_Entry_Data * sd,Elm_Wrap_Type wrap)4387 _elm_entry_line_wrap_set(Eo *obj, Elm_Entry_Data *sd, Elm_Wrap_Type wrap)
4388 {
4389    if (sd->line_wrap == wrap) return;
4390    sd->last_w = -1;
4391    sd->line_wrap = wrap;
4392    if (wrap == ELM_WRAP_NONE)
4393      ELM_SAFE_FREE(sd->deferred_recalc_job, ecore_job_del);
4394    efl_ui_widget_theme_apply(obj);
4395 }
4396 
4397 EOLIAN static Elm_Wrap_Type
_elm_entry_line_wrap_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4398 _elm_entry_line_wrap_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4399 {
4400    return sd->line_wrap;
4401 }
4402 
4403 EOLIAN static void
_elm_entry_editable_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool editable)4404 _elm_entry_editable_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool editable)
4405 {
4406    if (sd->editable == editable) return;
4407    sd->editable = editable;
4408    efl_ui_widget_theme_apply(obj);
4409    _elm_entry_focus_update(obj, sd);
4410 
4411    //legacy focus event emission
4412    if (efl_ui_focus_object_focus_get(obj))
4413      evas_object_smart_callback_call(obj, "focused", NULL);
4414    else
4415      evas_object_smart_callback_call(obj, "unfocused", NULL);
4416 
4417    elm_drop_target_del(obj, sd->drop_format,
4418                        _dnd_enter_cb, NULL,
4419                        _dnd_leave_cb, NULL,
4420                        _dnd_pos_cb, NULL,
4421                        _dnd_drop_cb, NULL);
4422    if (editable)
4423      {
4424         sd->drop_format = _get_drop_format(obj);
4425         elm_drop_target_add(obj, sd->drop_format,
4426                             _dnd_enter_cb, NULL,
4427                             _dnd_leave_cb, NULL,
4428                             _dnd_pos_cb, NULL,
4429                             _dnd_drop_cb, NULL);
4430      }
4431 }
4432 
4433 EOLIAN static Eina_Bool
_elm_entry_editable_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4434 _elm_entry_editable_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4435 {
4436    return sd->editable;
4437 }
4438 
4439 EOLIAN static void
_elm_entry_select_none(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4440 _elm_entry_select_none(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4441 {
4442    if ((sd->password)) return;
4443    if (sd->sel_mode)
4444      {
4445         sd->sel_mode = EINA_FALSE;
4446         if (!_elm_config->desktop_entry)
4447           edje_object_part_text_select_allow_set
4448             (sd->entry_edje, "elm.text", EINA_FALSE);
4449         edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
4450      }
4451    if (sd->have_selection)
4452      {
4453         Eina_Bool b_value = sd->have_selection;
4454         efl_event_callback_legacy_call
4455        (obj, EFL_TEXT_INTERACTIVE_EVENT_HAVE_SELECTION_CHANGED, &b_value);
4456      }
4457 
4458    sd->have_selection = EINA_FALSE;
4459    edje_object_part_text_select_none(sd->entry_edje, "elm.text");
4460 
4461    _hide_selection_handler(obj);
4462 }
4463 
4464 EOLIAN static void
_elm_entry_select_all(Eo * obj,Elm_Entry_Data * sd)4465 _elm_entry_select_all(Eo *obj, Elm_Entry_Data *sd)
4466 {
4467    if (elm_entry_is_empty(obj)) return;
4468    if ((sd->password)) return;
4469    if (sd->sel_mode)
4470      {
4471         sd->sel_mode = EINA_FALSE;
4472         if (!_elm_config->desktop_entry)
4473           edje_object_part_text_select_allow_set
4474             (sd->entry_edje, "elm.text", EINA_FALSE);
4475         edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
4476      }
4477    edje_object_part_text_select_all(sd->entry_edje, "elm.text");
4478 }
4479 
4480 EOLIAN static void
_elm_entry_select_region_set(Eo * obj,Elm_Entry_Data * sd,int start,int end)4481 _elm_entry_select_region_set(Eo *obj, Elm_Entry_Data *sd, int start, int end)
4482 {
4483    if (elm_entry_is_empty(obj)) return;
4484    if ((sd->password)) return;
4485    if (sd->sel_mode)
4486      {
4487         sd->sel_mode = EINA_FALSE;
4488         if (!_elm_config->desktop_entry)
4489           edje_object_part_text_select_allow_set
4490             (sd->entry_edje, "elm.text", EINA_FALSE);
4491         edje_object_signal_emit(sd->entry_edje, "elm,state,select,off", "elm");
4492      }
4493 
4494    /* Set have selection false to not be cleared handler in
4495       selection_cleared_signal_cb() since that callback will be called while
4496       resetting edje text. */
4497    sd->have_selection = EINA_FALSE;
4498 
4499    edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN, start);
4500    edje_object_part_text_select_begin(sd->entry_edje, "elm.text");
4501    edje_object_part_text_cursor_pos_set(sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN, end);
4502    edje_object_part_text_select_extend(sd->entry_edje, "elm.text");
4503 }
4504 
4505 EOLIAN static void
_elm_entry_select_region_get(const Eo * obj,Elm_Entry_Data * sd,int * start,int * end)4506 _elm_entry_select_region_get(const Eo *obj, Elm_Entry_Data *sd, int *start, int *end)
4507 {
4508    if (!elm_entry_selection_get(obj))
4509      {
4510         if (start) *start = -1;
4511         if (end) *end = -1;
4512         return;
4513      }
4514 
4515    if (start)
4516      *start = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", EDJE_CURSOR_SELECTION_BEGIN);
4517    if (end)
4518      *end = edje_object_part_text_cursor_pos_get(sd->entry_edje, "elm.text", EDJE_CURSOR_SELECTION_END);
4519 }
4520 
4521 EOLIAN static Eina_Bool
_elm_entry_textblock_cursor_geometry_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)4522 _elm_entry_textblock_cursor_geometry_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
4523 {
4524    edje_object_part_text_cursor_geometry_get
4525      (sd->entry_edje, "elm.text", x, y, w, h);
4526    return EINA_TRUE;
4527 }
4528 
4529 EOLIAN static Eina_Bool
_elm_entry_cursor_next(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4530 _elm_entry_cursor_next(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4531 {
4532    return edje_object_part_text_cursor_next
4533         (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4534 }
4535 
4536 EOLIAN static Eina_Bool
_elm_entry_cursor_prev(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4537 _elm_entry_cursor_prev(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4538 {
4539    return edje_object_part_text_cursor_prev
4540             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4541 }
4542 
4543 EOLIAN static Eina_Bool
_elm_entry_cursor_up(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4544 _elm_entry_cursor_up(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4545 {
4546    return edje_object_part_text_cursor_up
4547             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4548 }
4549 
4550 EOLIAN static Eina_Bool
_elm_entry_cursor_down(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4551 _elm_entry_cursor_down(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4552 {
4553    return edje_object_part_text_cursor_down
4554             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4555 }
4556 
4557 EOLIAN static void
_elm_entry_cursor_begin_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4558 _elm_entry_cursor_begin_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4559 {
4560    edje_object_part_text_cursor_begin_set
4561      (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4562 }
4563 
4564 EOLIAN static void
_elm_entry_cursor_end_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4565 _elm_entry_cursor_end_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4566 {
4567    edje_object_part_text_cursor_end_set
4568      (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4569 }
4570 
4571 EOLIAN static void
_elm_entry_cursor_line_begin_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4572 _elm_entry_cursor_line_begin_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4573 {
4574    edje_object_part_text_cursor_line_begin_set
4575      (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4576 }
4577 
4578 EOLIAN static void
_elm_entry_cursor_line_end_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4579 _elm_entry_cursor_line_end_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4580 {
4581    edje_object_part_text_cursor_line_end_set
4582      (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4583 }
4584 
4585 EOLIAN static void
_elm_entry_cursor_selection_begin(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4586 _elm_entry_cursor_selection_begin(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4587 {
4588    edje_object_part_text_select_begin(sd->entry_edje, "elm.text");
4589 }
4590 
4591 EOLIAN static void
_elm_entry_cursor_selection_end(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4592 _elm_entry_cursor_selection_end(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4593 {
4594    edje_object_part_text_select_extend(sd->entry_edje, "elm.text");
4595 }
4596 
4597 EOLIAN static Eina_Bool
_elm_entry_cursor_is_format_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4598 _elm_entry_cursor_is_format_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4599 {
4600    return edje_object_part_text_cursor_is_format_get
4601             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4602 }
4603 
4604 EOLIAN static Eina_Bool
_elm_entry_cursor_is_visible_format_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4605 _elm_entry_cursor_is_visible_format_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4606 {
4607    return edje_object_part_text_cursor_is_visible_format_get
4608             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4609 }
4610 
4611 EOLIAN static char*
_elm_entry_textblock_cursor_content_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4612 _elm_entry_textblock_cursor_content_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4613 {
4614    return edje_object_part_text_cursor_content_get
4615             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4616 }
4617 
4618 EOLIAN static void
_elm_entry_cursor_pos_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,int pos)4619 _elm_entry_cursor_pos_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, int pos)
4620 {
4621    edje_object_part_text_cursor_pos_set
4622      (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN, pos);
4623    edje_object_message_signal_process(sd->entry_edje);
4624 }
4625 
4626 EOLIAN static int
_elm_entry_cursor_pos_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4627 _elm_entry_cursor_pos_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4628 {
4629    return edje_object_part_text_cursor_pos_get
4630             (sd->entry_edje, "elm.text", EDJE_CURSOR_MAIN);
4631 }
4632 
4633 EOLIAN static void
_elm_entry_selection_cut(Eo * obj,Elm_Entry_Data * sd)4634 _elm_entry_selection_cut(Eo *obj, Elm_Entry_Data *sd)
4635 {
4636    if ((sd->password)) return;
4637    _cut_cb(obj, NULL, NULL);
4638 }
4639 
4640 EOLIAN static void
_elm_entry_selection_copy(Eo * obj,Elm_Entry_Data * sd)4641 _elm_entry_selection_copy(Eo *obj, Elm_Entry_Data *sd)
4642 {
4643    if ((sd->password)) return;
4644    _copy_cb(obj, NULL, NULL);
4645 }
4646 
4647 EOLIAN static void
_elm_entry_selection_paste(Eo * obj,Elm_Entry_Data * sd)4648 _elm_entry_selection_paste(Eo *obj, Elm_Entry_Data *sd)
4649 {
4650    if ((sd->password)) return;
4651    _paste_cb(obj, NULL, NULL);
4652 }
4653 
4654 EOLIAN static void
_elm_entry_context_menu_clear(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4655 _elm_entry_context_menu_clear(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4656 {
4657    Elm_Entry_Context_Menu_Item *it;
4658 
4659    EINA_LIST_FREE(sd->items, it)
4660      {
4661         eina_stringshare_del(it->label);
4662         eina_stringshare_del(it->icon_file);
4663         eina_stringshare_del(it->icon_group);
4664         free(it);
4665      }
4666 }
4667 
4668 EOLIAN static void
_elm_entry_context_menu_item_add(Eo * obj,Elm_Entry_Data * sd,const char * label,const char * icon_file,Elm_Icon_Type icon_type,Evas_Smart_Cb func,const void * data)4669 _elm_entry_context_menu_item_add(Eo *obj, Elm_Entry_Data *sd, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data)
4670 {
4671    Elm_Entry_Context_Menu_Item *it;
4672 
4673    it = calloc(1, sizeof(Elm_Entry_Context_Menu_Item));
4674    if (!it) return;
4675 
4676    sd->items = eina_list_append(sd->items, it);
4677    it->obj = obj;
4678    it->label = eina_stringshare_add(label);
4679    it->icon_file = eina_stringshare_add(icon_file);
4680    it->icon_type = icon_type;
4681    it->func = func;
4682    it->data = (void *)data;
4683 }
4684 
4685 EOLIAN static void
_elm_entry_context_menu_disabled_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool disabled)4686 _elm_entry_context_menu_disabled_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool disabled)
4687 {
4688    if (sd->context_menu == !disabled) return;
4689    sd->context_menu = !disabled;
4690 }
4691 
4692 EOLIAN static Eina_Bool
_elm_entry_context_menu_disabled_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)4693 _elm_entry_context_menu_disabled_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
4694 {
4695    return !sd->context_menu;
4696 }
4697 
4698 EAPI const char *
elm_entry_context_menu_item_label_get(const Elm_Entry_Context_Menu_Item * item)4699 elm_entry_context_menu_item_label_get(const Elm_Entry_Context_Menu_Item *item)
4700 {
4701    if (!item) return NULL;
4702    return item->label;
4703 }
4704 
4705 EAPI void
elm_entry_context_menu_item_icon_get(const Elm_Entry_Context_Menu_Item * item,const char ** icon_file,const char ** icon_group,Elm_Icon_Type * icon_type)4706 elm_entry_context_menu_item_icon_get(const Elm_Entry_Context_Menu_Item *item,
4707                                      const char **icon_file,
4708                                      const char **icon_group,
4709                                      Elm_Icon_Type *icon_type)
4710 {
4711    if (!item) return;
4712    if (icon_file) *icon_file = item->icon_file;
4713    if (icon_group) *icon_group = item->icon_group;
4714    if (icon_type) *icon_type = item->icon_type;
4715 }
4716 
4717 EOLIAN static void
_elm_entry_item_provider_append(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Entry_Item_Provider_Cb func,void * data)4718 _elm_entry_item_provider_append(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Entry_Item_Provider_Cb func, void *data)
4719 {
4720    Elm_Entry_Item_Provider *ip;
4721 
4722    EINA_SAFETY_ON_NULL_RETURN(func);
4723 
4724    ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
4725    if (!ip) return;
4726 
4727    ip->func = func;
4728    ip->data = data;
4729    sd->item_providers = eina_list_append(sd->item_providers, ip);
4730 }
4731 
4732 EOLIAN static void
_elm_entry_item_provider_prepend(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Entry_Item_Provider_Cb func,void * data)4733 _elm_entry_item_provider_prepend(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Entry_Item_Provider_Cb func, void *data)
4734 {
4735    Elm_Entry_Item_Provider *ip;
4736 
4737    EINA_SAFETY_ON_NULL_RETURN(func);
4738 
4739    ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
4740    if (!ip) return;
4741 
4742    ip->func = func;
4743    ip->data = data;
4744    sd->item_providers = eina_list_prepend(sd->item_providers, ip);
4745 }
4746 
4747 EOLIAN static void
_elm_entry_item_provider_remove(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Entry_Item_Provider_Cb func,void * data)4748 _elm_entry_item_provider_remove(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Entry_Item_Provider_Cb func, void *data)
4749 {
4750    Eina_List *l;
4751    Elm_Entry_Item_Provider *ip;
4752 
4753    EINA_SAFETY_ON_NULL_RETURN(func);
4754 
4755    EINA_LIST_FOREACH(sd->item_providers, l, ip)
4756      {
4757         if ((ip->func == func) && ((!data) || (ip->data == data)))
4758           {
4759              sd->item_providers = eina_list_remove_list(sd->item_providers, l);
4760              free(ip);
4761              return;
4762           }
4763      }
4764 }
4765 
4766 EOLIAN static void
_elm_entry_markup_filter_append(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Entry_Filter_Cb func,void * data)4767 _elm_entry_markup_filter_append(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Entry_Filter_Cb func, void *data)
4768 {
4769    Elm_Entry_Markup_Filter *tf;
4770 
4771    EINA_SAFETY_ON_NULL_RETURN(func);
4772 
4773    tf = _filter_new(func, data);
4774    if (!tf) return;
4775 
4776    sd->markup_filters = eina_list_append(sd->markup_filters, tf);
4777 }
4778 
4779 EOLIAN static void
_elm_entry_markup_filter_prepend(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Entry_Filter_Cb func,void * data)4780 _elm_entry_markup_filter_prepend(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Entry_Filter_Cb func, void *data)
4781 {
4782    Elm_Entry_Markup_Filter *tf;
4783 
4784    EINA_SAFETY_ON_NULL_RETURN(func);
4785 
4786    tf = _filter_new(func, data);
4787    if (!tf) return;
4788 
4789    sd->markup_filters = eina_list_prepend(sd->markup_filters, tf);
4790 }
4791 
4792 EOLIAN static void
_elm_entry_markup_filter_remove(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Entry_Filter_Cb func,void * data)4793 _elm_entry_markup_filter_remove(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Entry_Filter_Cb func, void *data)
4794 {
4795    Eina_List *l;
4796    Elm_Entry_Markup_Filter *tf;
4797 
4798    EINA_SAFETY_ON_NULL_RETURN(func);
4799 
4800    EINA_LIST_FOREACH(sd->markup_filters, l, tf)
4801      {
4802         if ((tf->func == func) && ((!data) || (tf->orig_data == data)))
4803           {
4804              sd->markup_filters = eina_list_remove_list(sd->markup_filters, l);
4805              _filter_free(tf);
4806              return;
4807           }
4808      }
4809 }
4810 
4811 EAPI char *
elm_entry_markup_to_utf8(const char * s)4812 elm_entry_markup_to_utf8(const char *s)
4813 {
4814    char *ss = _elm_util_mkup_to_text(s);
4815    if (!ss) ss = strdup("");
4816    return ss;
4817 }
4818 
4819 EAPI char *
elm_entry_utf8_to_markup(const char * s)4820 elm_entry_utf8_to_markup(const char *s)
4821 {
4822    char *ss = _elm_util_text_to_mkup(s);
4823    if (!ss) ss = strdup("");
4824    return ss;
4825 }
4826 
4827 static const char *
_text_get(const Evas_Object * obj)4828 _text_get(const Evas_Object *obj)
4829 {
4830    return elm_object_text_get(obj);
4831 }
4832 
4833 EAPI void
elm_entry_filter_limit_size(void * data,Evas_Object * entry,char ** text)4834 elm_entry_filter_limit_size(void *data,
4835                             Evas_Object *entry,
4836                             char **text)
4837 {
4838    const char *(*text_get)(const Evas_Object *);
4839    Elm_Entry_Filter_Limit_Size *lim = data;
4840    char *current, *utfstr;
4841    int len, newlen;
4842 
4843    EINA_SAFETY_ON_NULL_RETURN(data);
4844    EINA_SAFETY_ON_NULL_RETURN(entry);
4845    EINA_SAFETY_ON_NULL_RETURN(text);
4846 
4847    /* hack. I don't want to copy the entire function to work with
4848     * scrolled_entry */
4849    text_get = _text_get;
4850 
4851    current = elm_entry_markup_to_utf8(text_get(entry));
4852    utfstr = elm_entry_markup_to_utf8(*text);
4853 
4854    if (lim->max_char_count > 0)
4855      {
4856         len = evas_string_char_len_get(current);
4857         newlen = evas_string_char_len_get(utfstr);
4858         if ((len >= lim->max_char_count) && (newlen > 0))
4859           {
4860              efl_event_callback_legacy_call
4861                (entry, ELM_ENTRY_EVENT_MAXLENGTH_REACHED, NULL);
4862              ELM_SAFE_FREE(*text, free);
4863              free(current);
4864              free(utfstr);
4865              return;
4866           }
4867         if ((len + newlen) > lim->max_char_count)
4868           _chars_add_till_limit
4869             (entry, text, (lim->max_char_count - len), LENGTH_UNIT_CHAR);
4870      }
4871    else if (lim->max_byte_count > 0)
4872      {
4873         len = strlen(current);
4874         newlen = strlen(utfstr);
4875         if ((len >= lim->max_byte_count) && (newlen > 0))
4876           {
4877              efl_event_callback_legacy_call
4878                (entry, ELM_ENTRY_EVENT_MAXLENGTH_REACHED, NULL);
4879              ELM_SAFE_FREE(*text, free);
4880              free(current);
4881              free(utfstr);
4882              return;
4883           }
4884         if ((len + newlen) > lim->max_byte_count)
4885           _chars_add_till_limit
4886             (entry, text, (lim->max_byte_count - len), LENGTH_UNIT_BYTE);
4887      }
4888 
4889    free(current);
4890    free(utfstr);
4891 }
4892 
4893 EAPI void
elm_entry_filter_accept_set(void * data,Evas_Object * entry,char ** text)4894 elm_entry_filter_accept_set(void *data,
4895                             Evas_Object *entry,
4896                             char **text)
4897 {
4898    int read_idx, last_read_idx = 0, read_char;
4899    Elm_Entry_Filter_Accept_Set *as = data;
4900    Eina_Bool goes_in;
4901    Eina_Bool rejected = EINA_FALSE;
4902    const char *set;
4903    char *insert;
4904 
4905    EINA_SAFETY_ON_NULL_RETURN(data);
4906    EINA_SAFETY_ON_NULL_RETURN(text);
4907 
4908    if ((!as->accepted) && (!as->rejected))
4909      return;
4910 
4911    if (as->accepted)
4912      {
4913         set = as->accepted;
4914         goes_in = EINA_TRUE;
4915      }
4916    else
4917      {
4918         set = as->rejected;
4919         goes_in = EINA_FALSE;
4920      }
4921 
4922    insert = *text;
4923    read_idx = evas_string_char_next_get(*text, 0, &read_char);
4924    while (read_char)
4925      {
4926         int cmp_idx, cmp_char;
4927         Eina_Bool in_set = EINA_FALSE;
4928 
4929         if (read_char == '<')
4930           {
4931              while (read_char && (read_char != '>'))
4932                read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
4933 
4934              if (goes_in) in_set = EINA_TRUE;
4935              else in_set = EINA_FALSE;
4936           }
4937         else
4938           {
4939              if (read_char == '&')
4940                {
4941                   while (read_char && (read_char != ';'))
4942                     read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
4943 
4944                   if (!read_char)
4945                     {
4946                        if (goes_in) in_set = EINA_TRUE;
4947                        else in_set = EINA_FALSE;
4948                        goto inserting;
4949                     }
4950                   if (read_char == ';')
4951                     {
4952                        char *tag;
4953                        int utf8 = 0;
4954                        tag = malloc(read_idx - last_read_idx + 1);
4955                        if (tag)
4956                          {
4957                             char *markup;
4958                             strncpy(tag, (*text) + last_read_idx, read_idx - last_read_idx);
4959                             tag[read_idx - last_read_idx] = 0;
4960                             markup = elm_entry_markup_to_utf8(tag);
4961                             free(tag);
4962                             if (markup)
4963                               {
4964                                  utf8 = *markup;
4965                                  free(markup);
4966                               }
4967                             if (!utf8)
4968                               {
4969                                  in_set = EINA_FALSE;
4970                                  goto inserting;
4971                               }
4972                             read_char = utf8;
4973                          }
4974                     }
4975                }
4976 
4977              cmp_idx = evas_string_char_next_get(set, 0, &cmp_char);
4978              while (cmp_char)
4979                {
4980                   if (read_char == cmp_char)
4981                     {
4982                        in_set = EINA_TRUE;
4983                        break;
4984                     }
4985                   cmp_idx = evas_string_char_next_get(set, cmp_idx, &cmp_char);
4986                }
4987           }
4988 
4989 inserting:
4990 
4991         if (in_set == goes_in)
4992           {
4993              int size = read_idx - last_read_idx;
4994              const char *src = (*text) + last_read_idx;
4995              if (src != insert)
4996                memcpy(insert, *text + last_read_idx, size);
4997              insert += size;
4998           }
4999         else
5000           {
5001              rejected = EINA_TRUE;
5002           }
5003 
5004         if (read_char)
5005           {
5006              last_read_idx = read_idx;
5007              read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
5008           }
5009      }
5010    *insert = 0;
5011    if (rejected)
5012      efl_event_callback_legacy_call(entry, ELM_ENTRY_EVENT_REJECTED, NULL);
5013 }
5014 
5015 EOLIAN static void
_elm_entry_file_text_format_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Text_Format format)5016 _elm_entry_file_text_format_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Text_Format format)
5017 {
5018    sd->format = format;
5019 }
5020 
5021 EAPI Eina_Bool
elm_entry_file_set(Evas_Object * obj,const char * file,Elm_Text_Format format)5022 elm_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format)
5023 {
5024    Eina_Bool ret = EINA_FALSE;
5025    ELM_ENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, ret);
5026    ELM_SAFE_FREE(sd->delay_write, ecore_timer_del);
5027    if (sd->auto_save) _save_do(obj);
5028    elm_obj_entry_file_text_format_set(obj, format);
5029    sd->file_setting = EINA_TRUE;
5030    ret = efl_file_simple_load(obj, file, NULL);
5031    sd->file_setting = EINA_FALSE;
5032    return ret;
5033 }
5034 
5035 EOLIAN static void
_elm_entry_efl_file_unload(Eo * obj,Elm_Entry_Data * sd EINA_UNUSED)5036 _elm_entry_efl_file_unload(Eo *obj, Elm_Entry_Data *sd EINA_UNUSED)
5037 {
5038    elm_object_text_set(obj, "");
5039    efl_file_unload(efl_super(obj, MY_CLASS));
5040 }
5041 
5042 EOLIAN static Eina_Error
_elm_entry_efl_file_load(Eo * obj,Elm_Entry_Data * sd)5043 _elm_entry_efl_file_load(Eo *obj, Elm_Entry_Data *sd)
5044 {
5045    Eina_Error err;
5046 
5047    if (!sd->file_setting)
5048      CRI("EO methods should not be used directly on legacy objects!");
5049 
5050    if (efl_file_loaded_get(obj)) return 0;
5051    err = efl_file_load(efl_super(obj, MY_CLASS));
5052    if (err) return err;
5053    return _load_do(obj);
5054 }
5055 
5056 EOLIAN static Eina_Error
_elm_entry_efl_file_file_set(Eo * obj,Elm_Entry_Data * sd,const char * file)5057 _elm_entry_efl_file_file_set(Eo *obj, Elm_Entry_Data *sd, const char *file)
5058 {
5059    if (!sd->file_setting)
5060      CRI("EO methods should not be used directly on legacy objects!");
5061    eina_stringshare_replace(&sd->file, file);
5062    return efl_file_set(efl_super(obj, MY_CLASS), file);
5063 }
5064 
5065 EAPI void
elm_entry_file_get(const Evas_Object * obj,const char ** file,Elm_Text_Format * format)5066 elm_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format)
5067 {
5068    if (file) *file = efl_file_get(obj);
5069    if (format)
5070      {
5071         ELM_ENTRY_DATA_GET(obj, sd);
5072         if (!sd) return;
5073         *format = sd->format;
5074      }
5075 }
5076 
5077 EOLIAN static void
_elm_entry_file_save(Eo * obj,Elm_Entry_Data * sd)5078 _elm_entry_file_save(Eo *obj, Elm_Entry_Data *sd)
5079 {
5080    ELM_SAFE_FREE(sd->delay_write, ecore_timer_del);
5081    _save_do(obj);
5082    sd->delay_write = ecore_timer_add(ELM_ENTRY_DELAY_WRITE_TIME,
5083                                      _delay_write, obj);
5084 }
5085 
5086 EOLIAN static void
_elm_entry_autosave_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool auto_save)5087 _elm_entry_autosave_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool auto_save)
5088 {
5089    sd->auto_save = !!auto_save;
5090 }
5091 
5092 EOLIAN static Eina_Bool
_elm_entry_autosave_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5093 _elm_entry_autosave_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5094 {
5095    return sd->auto_save;
5096 }
5097 
5098 EINA_DEPRECATED EAPI void
elm_entry_cnp_textonly_set(Evas_Object * obj,Eina_Bool textonly)5099 elm_entry_cnp_textonly_set(Evas_Object *obj,
5100                            Eina_Bool textonly)
5101 {
5102    Elm_Cnp_Mode cnp_mode = ELM_CNP_MODE_MARKUP;
5103 
5104    ELM_ENTRY_CHECK(obj);
5105 
5106    if (textonly)
5107      cnp_mode = ELM_CNP_MODE_NO_IMAGE;
5108    elm_entry_cnp_mode_set(obj, cnp_mode);
5109 }
5110 
5111 EINA_DEPRECATED EAPI Eina_Bool
elm_entry_cnp_textonly_get(const Evas_Object * obj)5112 elm_entry_cnp_textonly_get(const Evas_Object *obj)
5113 {
5114    ELM_ENTRY_CHECK(obj) EINA_FALSE;
5115 
5116    return elm_entry_cnp_mode_get(obj) != ELM_CNP_MODE_MARKUP;
5117 }
5118 
5119 EOLIAN static void
_elm_entry_cnp_mode_set(Eo * obj,Elm_Entry_Data * sd,Elm_Cnp_Mode cnp_mode)5120 _elm_entry_cnp_mode_set(Eo *obj, Elm_Entry_Data *sd, Elm_Cnp_Mode cnp_mode)
5121 {
5122    Elm_Sel_Format format = ELM_SEL_FORMAT_MARKUP;
5123 
5124 
5125    if (sd->cnp_mode == cnp_mode) return;
5126    sd->cnp_mode = cnp_mode;
5127    if (sd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
5128      format = ELM_SEL_FORMAT_TEXT;
5129    else if (cnp_mode == ELM_CNP_MODE_MARKUP)
5130      format |= ELM_SEL_FORMAT_IMAGE;
5131 
5132    elm_drop_target_del(obj, sd->drop_format,
5133                        _dnd_enter_cb, NULL,
5134                        _dnd_leave_cb, NULL,
5135                        _dnd_pos_cb, NULL,
5136                        _dnd_drop_cb, NULL);
5137    sd->drop_format = format;
5138    elm_drop_target_add(obj, sd->drop_format,
5139                        _dnd_enter_cb, NULL,
5140                        _dnd_leave_cb, NULL,
5141                        _dnd_pos_cb, NULL,
5142                        _dnd_drop_cb, NULL);
5143 }
5144 
5145 EOLIAN static Elm_Cnp_Mode
_elm_entry_cnp_mode_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5146 _elm_entry_cnp_mode_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5147 {
5148    return sd->cnp_mode;
5149 }
5150 
5151 static void
_elm_entry_content_viewport_resize_cb(Evas_Object * obj,Evas_Coord w EINA_UNUSED,Evas_Coord h EINA_UNUSED)5152 _elm_entry_content_viewport_resize_cb(Evas_Object *obj,
5153                                       Evas_Coord w EINA_UNUSED, Evas_Coord h EINA_UNUSED)
5154 {
5155    _elm_entry_resize_internal(obj);
5156 }
5157 
5158 static void
_scroll_cb(Evas_Object * obj,void * data EINA_UNUSED)5159 _scroll_cb(Evas_Object *obj, void *data EINA_UNUSED)
5160 {
5161    ELM_ENTRY_DATA_GET(obj, sd);
5162    /* here we need to emit the signal that the elm_scroller would have done */
5163    evas_object_smart_callback_call(obj, "scroll", NULL);
5164 
5165    if (sd->have_selection)
5166      _update_selection_handler(obj);
5167 }
5168 
5169 EOLIAN static void
_elm_entry_scrollable_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool scroll)5170 _elm_entry_scrollable_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool scroll)
5171 {
5172    scroll = !!scroll;
5173    if (sd->scroll == scroll) return;
5174    sd->scroll = scroll;
5175 
5176    if (sd->scroll)
5177      {
5178         /* we now must re-theme ourselves to a scroller decoration
5179          * and move the entry looking object to be the content of the
5180          * scrollable view */
5181         elm_widget_resize_object_set(obj, NULL);
5182         elm_widget_sub_object_add(obj, sd->entry_edje);
5183 
5184         if (!sd->scr_edje)
5185           {
5186              sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
5187 
5188              elm_widget_theme_object_set
5189                (obj, sd->scr_edje, "scroller", "entry",
5190                elm_widget_style_get(obj));
5191 
5192              evas_object_size_hint_weight_set
5193                (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
5194              evas_object_size_hint_align_set
5195                (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
5196 
5197              evas_object_propagate_events_set(sd->scr_edje, EINA_TRUE);
5198           }
5199 
5200         elm_widget_resize_object_set(obj, sd->scr_edje);
5201 
5202         elm_interface_scrollable_objects_set(obj, sd->scr_edje, sd->hit_rect);
5203 
5204         elm_interface_scrollable_scroll_cb_set(obj, _scroll_cb);
5205 
5206         elm_interface_scrollable_bounce_allow_set(obj, sd->h_bounce, sd->v_bounce);
5207         if (sd->single_line)
5208            elm_interface_scrollable_policy_set(obj, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
5209         else
5210            elm_interface_scrollable_policy_set(obj, sd->policy_h, sd->policy_v);
5211         elm_interface_scrollable_content_set(obj, sd->entry_edje);
5212         elm_interface_scrollable_content_viewport_resize_cb_set(obj, _elm_entry_content_viewport_resize_cb);
5213         elm_widget_on_show_region_hook_set(obj, NULL, _show_region_hook, NULL);
5214      }
5215    else
5216      {
5217         if (sd->scr_edje)
5218           {
5219              elm_interface_scrollable_content_set(obj, NULL);
5220              evas_object_hide(sd->scr_edje);
5221           }
5222         elm_widget_resize_object_set(obj, sd->entry_edje);
5223 
5224         if (sd->scr_edje)
5225           elm_widget_sub_object_add(obj, sd->scr_edje);
5226 
5227         elm_interface_scrollable_objects_set(obj, sd->entry_edje, sd->hit_rect);
5228 
5229         elm_widget_on_show_region_hook_set(obj, NULL, NULL, NULL);
5230      }
5231    sd->last_w = -1;
5232    efl_ui_widget_theme_apply(obj);
5233 }
5234 
5235 EOLIAN static Eina_Bool
_elm_entry_scrollable_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5236 _elm_entry_scrollable_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5237 {
5238    return sd->scroll;
5239 }
5240 
5241 EOLIAN static void
_elm_entry_icon_visible_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool setting)5242 _elm_entry_icon_visible_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool setting)
5243 {
5244    if (!edje_object_part_swallow_get(sd->scr_edje, "elm.swallow.icon")) return;
5245 
5246    if (setting)
5247      edje_object_signal_emit(sd->scr_edje, "elm,action,show,icon", "elm");
5248    else
5249      edje_object_signal_emit(sd->scr_edje, "elm,action,hide,icon", "elm");
5250 
5251    elm_layout_sizing_eval(obj);
5252 }
5253 
5254 EOLIAN static void
_elm_entry_end_visible_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool setting)5255 _elm_entry_end_visible_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool setting)
5256 {
5257    if (!edje_object_part_swallow_get(sd->scr_edje, "elm.swallow.end")) return;
5258 
5259    if (setting)
5260      edje_object_signal_emit(sd->scr_edje, "elm,action,show,end", "elm");
5261    else
5262      edje_object_signal_emit(sd->scr_edje, "elm,action,hide,end", "elm");
5263 
5264    elm_layout_sizing_eval(obj);
5265 }
5266 
5267 EAPI void
elm_entry_scrollbar_policy_set(Evas_Object * obj,Elm_Scroller_Policy h,Elm_Scroller_Policy v)5268 elm_entry_scrollbar_policy_set(Evas_Object *obj,
5269                                Elm_Scroller_Policy h,
5270                                Elm_Scroller_Policy v)
5271 {
5272    ELM_ENTRY_CHECK(obj);
5273    elm_interface_scrollable_policy_set(obj, h, v);
5274 }
5275 
5276 EOLIAN static void
_elm_entry_elm_interface_scrollable_policy_set(Eo * obj,Elm_Entry_Data * sd,Elm_Scroller_Policy h,Elm_Scroller_Policy v)5277 _elm_entry_elm_interface_scrollable_policy_set(Eo *obj, Elm_Entry_Data *sd, Elm_Scroller_Policy h, Elm_Scroller_Policy v)
5278 {
5279    sd->policy_h = h;
5280    sd->policy_v = v;
5281    elm_interface_scrollable_policy_set(efl_super(obj, MY_CLASS), sd->policy_h, sd->policy_v);
5282 }
5283 
5284 EAPI void
elm_entry_bounce_set(Evas_Object * obj,Eina_Bool h_bounce,Eina_Bool v_bounce)5285 elm_entry_bounce_set(Evas_Object *obj,
5286                      Eina_Bool h_bounce,
5287                      Eina_Bool v_bounce)
5288 {
5289    ELM_ENTRY_CHECK(obj);
5290    elm_interface_scrollable_bounce_allow_set(obj, h_bounce, v_bounce);
5291 }
5292 
5293 EOLIAN static void
_elm_entry_elm_interface_scrollable_bounce_allow_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool h_bounce,Eina_Bool v_bounce)5294 _elm_entry_elm_interface_scrollable_bounce_allow_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool h_bounce, Eina_Bool v_bounce)
5295 {
5296    sd->h_bounce = h_bounce;
5297    sd->v_bounce = v_bounce;
5298    elm_interface_scrollable_bounce_allow_set(efl_super(obj, MY_CLASS), h_bounce, v_bounce);
5299 }
5300 
5301 EAPI void
elm_entry_bounce_get(const Evas_Object * obj,Eina_Bool * h_bounce,Eina_Bool * v_bounce)5302 elm_entry_bounce_get(const Evas_Object *obj,
5303                      Eina_Bool *h_bounce,
5304                      Eina_Bool *v_bounce)
5305 {
5306    ELM_ENTRY_CHECK(obj);
5307    elm_interface_scrollable_bounce_allow_get((Eo *) obj, h_bounce, v_bounce);
5308 }
5309 
5310 EOLIAN static void
_elm_entry_input_panel_layout_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Input_Panel_Layout layout)5311 _elm_entry_input_panel_layout_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Input_Panel_Layout layout)
5312 {
5313    sd->input_panel_layout = layout;
5314 
5315    edje_object_part_text_input_panel_layout_set
5316      (sd->entry_edje, "elm.text", (Edje_Input_Panel_Layout)layout);
5317 
5318    switch (layout)
5319      {
5320       case ELM_INPUT_PANEL_LAYOUT_URL:
5321       case ELM_INPUT_PANEL_LAYOUT_EMAIL:
5322       case ELM_INPUT_PANEL_LAYOUT_PASSWORD:
5323          elm_entry_autocapital_type_set(obj, ELM_AUTOCAPITAL_TYPE_NONE);
5324          break;
5325       default:
5326          elm_entry_autocapital_type_set(obj, ELM_AUTOCAPITAL_TYPE_SENTENCE);
5327          break;
5328      }
5329 
5330    if (layout == ELM_INPUT_PANEL_LAYOUT_PASSWORD)
5331      elm_entry_input_hint_set(obj, ((sd->input_hints & ~ELM_INPUT_HINT_AUTO_COMPLETE) | ELM_INPUT_HINT_SENSITIVE_DATA));
5332    else if (layout == ELM_INPUT_PANEL_LAYOUT_TERMINAL)
5333      elm_entry_input_hint_set(obj, (sd->input_hints & ~ELM_INPUT_HINT_AUTO_COMPLETE));
5334 }
5335 
5336 EOLIAN static Elm_Input_Panel_Layout
_elm_entry_input_panel_layout_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5337 _elm_entry_input_panel_layout_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5338 {
5339    return sd->input_panel_layout;
5340 }
5341 
5342 EOLIAN static void
_elm_entry_input_panel_layout_variation_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,int variation)5343 _elm_entry_input_panel_layout_variation_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, int variation)
5344 {
5345    sd->input_panel_layout_variation = variation;
5346 
5347    edje_object_part_text_input_panel_layout_variation_set
5348      (sd->entry_edje, "elm.text", variation);
5349 
5350    if (sd->input_panel_layout == ELM_INPUT_PANEL_LAYOUT_NORMAL &&
5351        variation == ELM_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
5352      elm_entry_autocapital_type_set(obj, ELM_AUTOCAPITAL_TYPE_WORD);
5353 }
5354 
5355 EOLIAN static int
_elm_entry_input_panel_layout_variation_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5356 _elm_entry_input_panel_layout_variation_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5357 {
5358    return sd->input_panel_layout_variation;
5359 }
5360 
5361 EOLIAN static void
_elm_entry_autocapital_type_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Autocapital_Type autocapital_type)5362 _elm_entry_autocapital_type_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Autocapital_Type autocapital_type)
5363 {
5364    sd->autocapital_type = autocapital_type;
5365    edje_object_part_text_autocapital_type_set
5366      (sd->entry_edje, "elm.text", (Edje_Text_Autocapital_Type)autocapital_type);
5367 }
5368 
5369 EOLIAN static Elm_Autocapital_Type
_elm_entry_autocapital_type_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5370 _elm_entry_autocapital_type_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5371 {
5372    return sd->autocapital_type;
5373 }
5374 
5375 EOLIAN static void
_elm_entry_prediction_allow_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool prediction)5376 _elm_entry_prediction_allow_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool prediction)
5377 {
5378    sd->prediction_allow = prediction;
5379    edje_object_part_text_prediction_allow_set
5380      (sd->entry_edje, "elm.text", prediction);
5381 }
5382 
5383 EOLIAN static Eina_Bool
_elm_entry_prediction_allow_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5384 _elm_entry_prediction_allow_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5385 {
5386    return sd->prediction_allow;
5387 }
5388 
5389 EOLIAN static void
_elm_entry_input_hint_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Input_Hints hints)5390 _elm_entry_input_hint_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Input_Hints hints)
5391 {
5392    sd->input_hints = hints;
5393 
5394    edje_object_part_text_input_hint_set
5395      (sd->entry_edje, "elm.text", (Edje_Input_Hints)hints);
5396 }
5397 
5398 EOLIAN static Elm_Input_Hints
_elm_entry_input_hint_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5399 _elm_entry_input_hint_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5400 {
5401    return sd->input_hints;
5402 }
5403 
5404 EOLIAN static void
_elm_entry_prediction_hint_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * prediction_hint)5405 _elm_entry_prediction_hint_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const char *prediction_hint)
5406 {
5407    if (sd->prediction_hint)
5408      free(sd->prediction_hint);
5409 
5410    sd->prediction_hint = strdup(prediction_hint);
5411 
5412    edje_object_part_text_prediction_hint_set
5413      (sd->entry_edje, "elm.text", prediction_hint);
5414 }
5415 
5416 EOLIAN static Eina_Bool
_elm_entry_prediction_hint_hash_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * key,const char * value)5417 _elm_entry_prediction_hint_hash_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const char *key, const char *value)
5418 {
5419    return edje_object_part_text_prediction_hint_hash_set
5420       (sd->entry_edje, "elm.text", key, value);
5421 }
5422 
5423 EOLIAN static Eina_Bool
_elm_entry_prediction_hint_hash_del(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * key)5424 _elm_entry_prediction_hint_hash_del(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const char *key)
5425 {
5426    return edje_object_part_text_prediction_hint_hash_del
5427       (sd->entry_edje, "elm.text", key);
5428 }
5429 
5430 EOLIAN static void
_elm_entry_imf_context_reset(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5431 _elm_entry_imf_context_reset(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5432 {
5433    edje_object_part_text_imf_context_reset(sd->entry_edje, "elm.text");
5434 }
5435 
5436 EOLIAN static void
_elm_entry_input_panel_enabled_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool enabled)5437 _elm_entry_input_panel_enabled_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool enabled)
5438 {
5439    sd->input_panel_enable = enabled;
5440    edje_object_part_text_input_panel_enabled_set
5441      (sd->entry_edje, "elm.text", enabled);
5442 }
5443 
5444 EOLIAN static Eina_Bool
_elm_entry_input_panel_enabled_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5445 _elm_entry_input_panel_enabled_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5446 {
5447    return sd->input_panel_enable;
5448 }
5449 
5450 EOLIAN static void
_elm_entry_input_panel_show(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5451 _elm_entry_input_panel_show(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5452 {
5453    edje_object_part_text_input_panel_show(sd->entry_edje, "elm.text");
5454 }
5455 
5456 EOLIAN static void
_elm_entry_input_panel_hide(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5457 _elm_entry_input_panel_hide(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5458 {
5459 
5460    edje_object_part_text_input_panel_hide(sd->entry_edje, "elm.text");
5461 }
5462 
5463 EOLIAN static void
_elm_entry_input_panel_language_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Input_Panel_Lang lang)5464 _elm_entry_input_panel_language_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Input_Panel_Lang lang)
5465 {
5466    sd->input_panel_lang = lang;
5467    edje_object_part_text_input_panel_language_set
5468      (sd->entry_edje, "elm.text", (Edje_Input_Panel_Lang)lang);
5469 }
5470 
5471 EOLIAN static Elm_Input_Panel_Lang
_elm_entry_input_panel_language_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5472 _elm_entry_input_panel_language_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5473 {
5474    return sd->input_panel_lang;
5475 }
5476 
5477 EOLIAN static void
_elm_entry_input_panel_imdata_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const void * data,int len)5478 _elm_entry_input_panel_imdata_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const void *data, int len)
5479 {
5480    free(sd->input_panel_imdata);
5481 
5482    sd->input_panel_imdata = calloc(1, len);
5483    sd->input_panel_imdata_len = len;
5484    memcpy(sd->input_panel_imdata, data, len);
5485 
5486    edje_object_part_text_input_panel_imdata_set
5487      (sd->entry_edje, "elm.text", sd->input_panel_imdata,
5488      sd->input_panel_imdata_len);
5489 }
5490 
5491 EOLIAN static void
_elm_entry_input_panel_imdata_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,void * data,int * len)5492 _elm_entry_input_panel_imdata_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, void *data, int *len)
5493 {
5494    edje_object_part_text_input_panel_imdata_get
5495      (sd->entry_edje, "elm.text", data, len);
5496 }
5497 
5498 EOLIAN static void
_elm_entry_input_panel_return_key_type_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Elm_Input_Panel_Return_Key_Type return_key_type)5499 _elm_entry_input_panel_return_key_type_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Elm_Input_Panel_Return_Key_Type return_key_type)
5500 {
5501    sd->input_panel_return_key_type = return_key_type;
5502 
5503    edje_object_part_text_input_panel_return_key_type_set
5504      (sd->entry_edje, "elm.text", (Edje_Input_Panel_Return_Key_Type)return_key_type);
5505 }
5506 
5507 EOLIAN static Elm_Input_Panel_Return_Key_Type
_elm_entry_input_panel_return_key_type_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5508 _elm_entry_input_panel_return_key_type_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5509 {
5510    return sd->input_panel_return_key_type;
5511 }
5512 
5513 EOLIAN static void
_elm_entry_input_panel_return_key_disabled_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool disabled)5514 _elm_entry_input_panel_return_key_disabled_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool disabled)
5515 {
5516    sd->input_panel_return_key_disabled = disabled;
5517 
5518    edje_object_part_text_input_panel_return_key_disabled_set
5519      (sd->entry_edje, "elm.text", disabled);
5520 }
5521 
5522 EOLIAN static Eina_Bool
_elm_entry_input_panel_return_key_disabled_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5523 _elm_entry_input_panel_return_key_disabled_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5524 {
5525    return sd->input_panel_return_key_disabled;
5526 }
5527 
5528 EOLIAN static void
_elm_entry_input_panel_return_key_autoenabled_set(Eo * obj,Elm_Entry_Data * sd,Eina_Bool enabled)5529 _elm_entry_input_panel_return_key_autoenabled_set(Eo *obj, Elm_Entry_Data *sd, Eina_Bool enabled)
5530 {
5531    sd->auto_return_key = enabled;
5532    _return_key_enabled_check(obj);
5533 }
5534 
5535 EOLIAN static void
_elm_entry_input_panel_show_on_demand_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool ondemand)5536 _elm_entry_input_panel_show_on_demand_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool ondemand)
5537 {
5538    sd->input_panel_show_on_demand = ondemand;
5539 
5540    edje_object_part_text_input_panel_show_on_demand_set
5541      (sd->entry_edje, "elm.text", ondemand);
5542 }
5543 
5544 EOLIAN static Eina_Bool
_elm_entry_input_panel_show_on_demand_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5545 _elm_entry_input_panel_show_on_demand_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5546 {
5547    return sd->input_panel_show_on_demand;
5548 }
5549 
5550 EOLIAN static void*
_elm_entry_imf_context_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5551 _elm_entry_imf_context_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5552 {
5553    if (!sd) return NULL;
5554 
5555    return edje_object_part_text_imf_context_get(sd->entry_edje, "elm.text");
5556 }
5557 
5558 /* START - ANCHOR HOVER */
5559 static void
_anchor_parent_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)5560 _anchor_parent_del_cb(void *data,
5561                       Evas *e EINA_UNUSED,
5562                       Evas_Object *obj EINA_UNUSED,
5563                       void *event_info EINA_UNUSED)
5564 {
5565    ELM_ENTRY_DATA_GET(data, sd);
5566 
5567    sd->anchor_hover.hover_parent = NULL;
5568 }
5569 
5570 EOLIAN static void
_elm_entry_anchor_hover_parent_set(Eo * obj,Elm_Entry_Data * sd,Evas_Object * parent)5571 _elm_entry_anchor_hover_parent_set(Eo *obj, Elm_Entry_Data *sd, Evas_Object *parent)
5572 {
5573    if (sd->anchor_hover.hover_parent)
5574      evas_object_event_callback_del_full
5575        (sd->anchor_hover.hover_parent, EVAS_CALLBACK_DEL,
5576        _anchor_parent_del_cb, obj);
5577    sd->anchor_hover.hover_parent = parent;
5578    if (sd->anchor_hover.hover_parent)
5579      evas_object_event_callback_add
5580        (sd->anchor_hover.hover_parent, EVAS_CALLBACK_DEL,
5581        _anchor_parent_del_cb, obj);
5582 }
5583 
5584 EOLIAN static Evas_Object*
_elm_entry_anchor_hover_parent_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5585 _elm_entry_anchor_hover_parent_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5586 {
5587    return sd->anchor_hover.hover_parent;
5588 }
5589 
5590 EOLIAN static void
_elm_entry_anchor_hover_style_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,const char * style)5591 _elm_entry_anchor_hover_style_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, const char *style)
5592 {
5593    eina_stringshare_replace(&sd->anchor_hover.hover_style, style);
5594 }
5595 
5596 EOLIAN static const char*
_elm_entry_anchor_hover_style_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5597 _elm_entry_anchor_hover_style_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5598 {
5599    return sd->anchor_hover.hover_style;
5600 }
5601 
5602 EOLIAN static void
_elm_entry_anchor_hover_end(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5603 _elm_entry_anchor_hover_end(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5604 {
5605    ELM_SAFE_FREE(sd->anchor_hover.hover, evas_object_del);
5606    ELM_SAFE_FREE(sd->anchor_hover.pop, evas_object_del);
5607 }
5608 /* END - ANCHOR HOVER */
5609 
5610 static void
_activate(Evas_Object * obj)5611 _activate(Evas_Object *obj)
5612 {
5613    ELM_ENTRY_DATA_GET(obj, sd);
5614 
5615    if (!elm_widget_disabled_get(obj) &&
5616        !evas_object_freeze_events_get(obj))
5617      {
5618         evas_object_smart_callback_call
5619           ( obj, "clicked", NULL);
5620         if (sd->editable && sd->input_panel_enable)
5621           edje_object_part_text_input_panel_show(sd->entry_edje, "elm.text");
5622      }
5623 }
5624 
5625 EOLIAN static Eina_Bool
_elm_entry_efl_ui_widget_on_access_activate(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,Efl_Ui_Activate act)5626 _elm_entry_efl_ui_widget_on_access_activate(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, Efl_Ui_Activate act)
5627 {
5628    if (act != EFL_UI_ACTIVATE_DEFAULT) return EINA_FALSE;
5629    _activate(obj);
5630 
5631    return EINA_TRUE;
5632 }
5633 
5634 EOLIAN static void
_elm_entry_select_allow_set(Eo * obj EINA_UNUSED,Elm_Entry_Data * sd,Eina_Bool allow)5635 _elm_entry_select_allow_set(Eo *obj EINA_UNUSED, Elm_Entry_Data *sd, Eina_Bool allow)
5636 {
5637    if (sd->sel_allow == allow) return;
5638    sd->sel_allow = allow;
5639 
5640    edje_object_part_text_select_allow_set(sd->entry_edje, "elm.text", allow);
5641 }
5642 
5643 EOLIAN static Eina_Bool
_elm_entry_select_allow_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd)5644 _elm_entry_select_allow_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd)
5645 {
5646    return sd->sel_allow;
5647 }
5648 
5649 static void
_elm_entry_class_constructor(Efl_Class * klass)5650 _elm_entry_class_constructor(Efl_Class *klass)
5651 {
5652    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
5653 }
5654 
5655 // ATSPI Accessibility
5656 
5657 EOLIAN static Eina_Unicode
_elm_entry_efl_access_text_character_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int offset)5658 _elm_entry_efl_access_text_character_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int offset)
5659 {
5660    char *txt;
5661    int idx = 0;
5662    Eina_Unicode ret = 0;
5663    if (offset < 0) return ret;
5664 
5665    txt = _elm_util_mkup_to_text(elm_entry_entry_get(obj));
5666    if (!txt) return ret;
5667 
5668    ret = eina_unicode_utf8_next_get(txt, &idx);
5669    while (offset--) ret = eina_unicode_utf8_next_get(txt, &idx);
5670 
5671    free(txt);
5672 
5673    if (_pd->password)
5674      ret = ENTRY_PASSWORD_MASK_CHARACTER;
5675 
5676    return ret;
5677 }
5678 
5679 EOLIAN static int
_elm_entry_efl_access_text_character_count_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED)5680 _elm_entry_efl_access_text_character_count_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED)
5681 {
5682    char *txt;
5683    int ret = -1;
5684 
5685    txt = _elm_util_mkup_to_text(elm_entry_entry_get(obj));
5686    if (!txt) return ret;
5687 
5688    ret = eina_unicode_utf8_get_len(txt);
5689    free(txt);
5690 
5691    return ret;
5692 }
5693 
5694 EOLIAN static void
_elm_entry_efl_access_text_string_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,Efl_Access_Text_Granularity granularity,int * start_offset,int * end_offset,char ** ret EFL_TRANSFER_OWNERSHIP)5695 _elm_entry_efl_access_text_string_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, Efl_Access_Text_Granularity granularity, int *start_offset, int *end_offset, char **ret EFL_TRANSFER_OWNERSHIP)
5696 {
5697    Evas_Textblock_Cursor *cur = NULL, *cur2 = NULL;
5698    Evas_Object *tblk;
5699 
5700    EINA_SAFETY_ON_NULL_RETURN(ret);
5701    *ret = NULL;
5702 
5703    tblk = elm_entry_textblock_get(obj);
5704    if (!tblk) goto fail;
5705 
5706    cur = evas_object_textblock_cursor_new(tblk);
5707    cur2 = evas_object_textblock_cursor_new(tblk);
5708    if (!cur || !cur2) goto fail;
5709 
5710    evas_textblock_cursor_pos_set(cur, *start_offset);
5711    if (evas_textblock_cursor_pos_get(cur) != *start_offset) goto fail;
5712 
5713    switch (granularity)
5714      {
5715       case EFL_ACCESS_TEXT_GRANULARITY_CHAR:
5716          break;
5717       case EFL_ACCESS_TEXT_GRANULARITY_WORD:
5718          evas_textblock_cursor_word_start(cur);
5719          break;
5720       case EFL_ACCESS_TEXT_GRANULARITY_SENTENCE:
5721          // TODO - add sentence support in textblock first
5722          break;
5723       case EFL_ACCESS_TEXT_GRANULARITY_LINE:
5724          evas_textblock_cursor_line_char_first(cur);
5725          break;
5726       case EFL_ACCESS_TEXT_GRANULARITY_PARAGRAPH:
5727          evas_textblock_cursor_paragraph_char_first(cur);
5728          break;
5729      }
5730 
5731    *start_offset = evas_textblock_cursor_pos_get(cur);
5732    evas_textblock_cursor_copy(cur, cur2);
5733 
5734    switch (granularity)
5735      {
5736       case EFL_ACCESS_TEXT_GRANULARITY_CHAR:
5737          evas_textblock_cursor_char_next(cur2);
5738          break;
5739       case EFL_ACCESS_TEXT_GRANULARITY_WORD:
5740          evas_textblock_cursor_word_end(cur2);
5741          // since word_end sets cursor position ON (before) last
5742          // char of word, we need to manually advance cursor to get
5743          // proper string from function range_text_get
5744          evas_textblock_cursor_char_next(cur2);
5745          break;
5746       case EFL_ACCESS_TEXT_GRANULARITY_SENTENCE:
5747          // TODO - add sentence support in textblock first
5748          break;
5749       case EFL_ACCESS_TEXT_GRANULARITY_LINE:
5750          evas_textblock_cursor_line_char_last(cur2);
5751          break;
5752       case EFL_ACCESS_TEXT_GRANULARITY_PARAGRAPH:
5753          evas_textblock_cursor_paragraph_char_last(cur2);
5754          break;
5755      }
5756 
5757    if (end_offset) *end_offset = evas_textblock_cursor_pos_get(cur2);
5758 
5759    *ret = evas_textblock_cursor_range_text_get(cur, cur2, EVAS_TEXTBLOCK_TEXT_PLAIN);
5760 
5761    evas_textblock_cursor_free(cur);
5762    evas_textblock_cursor_free(cur2);
5763 
5764    if (*ret && _pd->password)
5765      {
5766         int i = 0;
5767         while (*ret[i] != '\0')
5768          *ret[i++] = ENTRY_PASSWORD_MASK_CHARACTER;
5769      }
5770 
5771    return;
5772 
5773 fail:
5774    if (start_offset) *start_offset = -1;
5775    if (end_offset) *end_offset = -1;
5776    if (cur) evas_textblock_cursor_free(cur);
5777    if (cur2) evas_textblock_cursor_free(cur2);
5778    *ret = NULL;
5779 }
5780 
5781 EOLIAN static char*
_elm_entry_efl_access_text_access_text_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int start_offset,int end_offset)5782 _elm_entry_efl_access_text_access_text_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int start_offset, int end_offset)
5783 {
5784    Evas_Textblock_Cursor *cur = NULL, *cur2 = NULL;
5785    Evas_Object *tblk;
5786    char *ret = NULL;
5787 
5788    tblk = elm_entry_textblock_get(obj);
5789    if (!tblk) goto fail;
5790 
5791    cur = evas_object_textblock_cursor_new(tblk);
5792    cur2 = evas_object_textblock_cursor_new(tblk);
5793    if (!cur || !cur2) goto fail;
5794 
5795    evas_textblock_cursor_pos_set(cur, start_offset);
5796    if (evas_textblock_cursor_pos_get(cur) != start_offset) goto fail;
5797 
5798    evas_textblock_cursor_pos_set(cur2, end_offset);
5799    if (evas_textblock_cursor_pos_get(cur2) != end_offset) goto fail;
5800 
5801    ret = evas_textblock_cursor_range_text_get(cur, cur2, EVAS_TEXTBLOCK_TEXT_PLAIN);
5802 
5803    evas_textblock_cursor_free(cur);
5804    evas_textblock_cursor_free(cur2);
5805 
5806    if (ret && _pd->password)
5807      {
5808         int i = 0;
5809         while (ret[i] != '\0')
5810          ret[i++] = ENTRY_PASSWORD_MASK_CHARACTER;
5811      }
5812 
5813    return ret;
5814 
5815 fail:
5816    if (cur) evas_textblock_cursor_free(cur);
5817    if (cur2) evas_textblock_cursor_free(cur2);
5818    return NULL;
5819 }
5820 
5821 EOLIAN static int
_elm_entry_efl_access_text_caret_offset_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED)5822 _elm_entry_efl_access_text_caret_offset_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED)
5823 {
5824    return elm_entry_cursor_pos_get(obj);
5825 }
5826 
5827 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_caret_offset_set(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int offset)5828 _elm_entry_efl_access_text_caret_offset_set(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int offset)
5829 {
5830    elm_entry_cursor_pos_set(obj, offset);
5831    return EINA_TRUE;
5832 }
5833 
5834 EOLIAN static int
_elm_entry_efl_access_text_selections_count_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED)5835 _elm_entry_efl_access_text_selections_count_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED)
5836 {
5837    return elm_entry_selection_get(obj) ? 1 : 0;
5838 }
5839 
5840 EOLIAN static void
_elm_entry_efl_access_text_access_selection_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int selection_number,int * start_offset,int * end_offset)5841 _elm_entry_efl_access_text_access_selection_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int selection_number, int *start_offset, int *end_offset)
5842 {
5843    if (selection_number != 0) return;
5844 
5845    elm_obj_entry_select_region_get(obj, start_offset, end_offset);
5846 }
5847 
5848 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_access_selection_set(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int selection_number,int start_offset,int end_offset)5849 _elm_entry_efl_access_text_access_selection_set(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int selection_number, int start_offset, int end_offset)
5850 {
5851    if (selection_number != 0) return EINA_FALSE;
5852 
5853    elm_entry_select_region_set(obj, start_offset, end_offset);
5854 
5855    return EINA_TRUE;
5856 }
5857 
5858 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_selection_remove(Eo * obj,Elm_Entry_Data * pd EINA_UNUSED,int selection_number)5859 _elm_entry_efl_access_text_selection_remove(Eo *obj, Elm_Entry_Data *pd EINA_UNUSED, int selection_number)
5860 {
5861    if (selection_number != 0) return EINA_FALSE;
5862    elm_entry_select_none(obj);
5863    return EINA_TRUE;
5864 }
5865 
5866 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_selection_add(Eo * obj,Elm_Entry_Data * pd EINA_UNUSED,int start_offset,int end_offset)5867 _elm_entry_efl_access_text_selection_add(Eo *obj, Elm_Entry_Data *pd EINA_UNUSED, int start_offset, int end_offset)
5868 {
5869    elm_entry_select_region_set(obj, start_offset, end_offset);
5870 
5871    return EINA_TRUE;
5872 }
5873 
5874 EOLIAN static Eina_List*
_elm_entry_efl_access_text_bounded_ranges_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * _pd EINA_UNUSED,Eina_Bool screen_coods EINA_UNUSED,Eina_Rect rect EINA_UNUSED,Efl_Access_Text_Clip_Type xclip EINA_UNUSED,Efl_Access_Text_Clip_Type yclip EINA_UNUSED)5875 _elm_entry_efl_access_text_bounded_ranges_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *_pd EINA_UNUSED, Eina_Bool screen_coods EINA_UNUSED, Eina_Rect rect EINA_UNUSED, Efl_Access_Text_Clip_Type xclip EINA_UNUSED, Efl_Access_Text_Clip_Type yclip EINA_UNUSED)
5876 {
5877    return NULL;
5878 }
5879 
5880 EOLIAN static int
_elm_entry_efl_access_text_offset_at_point_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,Eina_Bool screen_coods,int x,int y)5881 _elm_entry_efl_access_text_offset_at_point_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, Eina_Bool screen_coods, int x, int y)
5882 {
5883    Evas_Object *txtblk;
5884    Evas_Textblock_Cursor *cur;
5885    int ret;
5886 
5887    txtblk = elm_entry_textblock_get(obj);
5888    if (!txtblk) return -1;
5889 
5890    cur = evas_object_textblock_cursor_new(txtblk);
5891    if (!cur) return -1;
5892 
5893    if (screen_coods)
5894      {
5895         int ee_x, ee_y;
5896         Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
5897         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
5898         x -= ee_x;
5899         y -= ee_y;
5900      }
5901 
5902    if (!evas_textblock_cursor_char_coord_set(cur, x, y))
5903      {
5904         evas_textblock_cursor_free(cur);
5905         return -1;
5906      }
5907 
5908    ret = evas_textblock_cursor_pos_get(cur);
5909    evas_textblock_cursor_free(cur);
5910 
5911    return ret;
5912 }
5913 
5914 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_character_extents_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int offset,Eina_Bool screen_coods,Eina_Rect * rect)5915 _elm_entry_efl_access_text_character_extents_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int offset, Eina_Bool screen_coods, Eina_Rect *rect)
5916 {
5917    Evas_Object *txtblk;
5918    Evas_Textblock_Cursor *cur;
5919    int ret;
5920 
5921    txtblk = elm_entry_textblock_get(obj);
5922    if (!txtblk) return EINA_FALSE;
5923 
5924    cur = evas_object_textblock_cursor_new(txtblk);
5925    if (!cur) return EINA_FALSE;
5926 
5927    evas_textblock_cursor_pos_set(cur, offset);
5928 
5929    ret = evas_textblock_cursor_char_geometry_get(cur, &rect->x, &rect->y, &rect->w, &rect->h);
5930    evas_textblock_cursor_free(cur);
5931 
5932    if (ret == -1) return EINA_FALSE;
5933 
5934    if (screen_coods)
5935      {
5936         int ee_x, ee_y;
5937         Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
5938         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
5939         rect->x += ee_x;
5940         rect->y += ee_y;
5941      }
5942 
5943    return EINA_TRUE;
5944 }
5945 
5946 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_range_extents_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,Eina_Bool screen_coods,int start_offset,int end_offset,Eina_Rect * rect)5947 _elm_entry_efl_access_text_range_extents_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, Eina_Bool screen_coods, int start_offset, int end_offset, Eina_Rect *rect)
5948 {
5949    Evas_Object *txtblk;
5950    Evas_Textblock_Cursor *cur1, *cur2;
5951    int ret;
5952    int x, xx, y, yy;
5953 
5954    txtblk = elm_entry_textblock_get(obj);
5955    if (!txtblk) return EINA_FALSE;
5956 
5957    cur1 = evas_object_textblock_cursor_new(txtblk);
5958    if (!cur1) return EINA_FALSE;
5959 
5960    cur2 = evas_object_textblock_cursor_new(txtblk);
5961    if (!cur2)
5962      {
5963         evas_textblock_cursor_free(cur1);
5964         return EINA_FALSE;
5965      }
5966 
5967    evas_textblock_cursor_pos_set(cur1, start_offset);
5968    evas_textblock_cursor_pos_set(cur2, end_offset);
5969 
5970    ret = evas_textblock_cursor_char_geometry_get(cur1, &x, &y, NULL, NULL);
5971    ret += evas_textblock_cursor_char_geometry_get(cur2, &xx, &yy, NULL, NULL);
5972 
5973    evas_textblock_cursor_free(cur1);
5974    evas_textblock_cursor_free(cur2);
5975 
5976    if (ret != 0) return EINA_FALSE;
5977 
5978    rect->x = x < xx ? x : xx;
5979    rect->y = y < yy ? y : yy;
5980    rect->w = abs(x - xx);
5981    rect->h = abs(y - yy);
5982 
5983    if (screen_coods)
5984      {
5985         int ee_x, ee_y;
5986         Ecore_Evas *ee= ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
5987         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
5988         rect->x += ee_x;
5989         rect->y += ee_y;
5990      }
5991 
5992    return EINA_TRUE;
5993 }
5994 
5995 static Efl_Access_Text_Attribute*
_textblock_node_format_to_atspi_text_attr(const Evas_Object_Textblock_Node_Format * format)5996 _textblock_node_format_to_atspi_text_attr(const Evas_Object_Textblock_Node_Format *format)
5997 {
5998    Efl_Access_Text_Attribute *ret = NULL;
5999    const char *txt;
6000 
6001    txt = evas_textblock_node_format_text_get(format);
6002    if (!txt) return NULL;
6003 
6004    if (txt[0] == '-') return NULL; // skip closing format
6005 
6006    if (!strncmp(txt, "+ ", 2))
6007      {
6008         const char *tmp = &txt[2];
6009 
6010         while (*tmp != '\0' && *tmp != '=') tmp++;
6011         if (*tmp++ != '=') return NULL;
6012 
6013         ret = calloc(1, sizeof(Efl_Access_Text_Attribute));
6014         if (!ret) return NULL;
6015 
6016         ret->value = eina_stringshare_add(tmp);
6017         int size = &txt[2] - tmp + 1;
6018         ret->name = eina_stringshare_add_length(&txt[2], size > 0 ? size : -size);
6019      }
6020 
6021    return ret;
6022 }
6023 
6024 EOLIAN static Eina_Bool
_elm_entry_efl_access_text_attribute_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,const char * attr_name EINA_UNUSED,int * start_offset,int * end_offset,char ** value)6025 _elm_entry_efl_access_text_attribute_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, const char *attr_name EINA_UNUSED, int *start_offset, int *end_offset, char **value)
6026 {
6027    Evas_Object *txtblk;
6028    Evas_Textblock_Cursor *cur1, *cur2;
6029    Eina_List *formats, *l;
6030    Evas_Object_Textblock_Node_Format *format;
6031    Efl_Access_Text_Attribute *attr;
6032 
6033    txtblk = elm_entry_textblock_get(obj);
6034    if (!txtblk) return EINA_FALSE;
6035 
6036    cur1 = evas_object_textblock_cursor_new(txtblk);
6037    if (!cur1) return EINA_FALSE;
6038 
6039    cur2 = evas_object_textblock_cursor_new(txtblk);
6040    if (!cur2)
6041      {
6042         evas_textblock_cursor_free(cur1);
6043         return EINA_FALSE;
6044      }
6045 
6046    evas_textblock_cursor_pos_set(cur1, *start_offset);
6047    evas_textblock_cursor_pos_set(cur2, *end_offset);
6048 
6049    formats = evas_textblock_cursor_range_formats_get(cur1, cur2);
6050 
6051    evas_textblock_cursor_free(cur1);
6052    evas_textblock_cursor_free(cur2);
6053 
6054    if (!formats) return EINA_FALSE;
6055 
6056    EINA_LIST_FOREACH(formats, l , format)
6057      {
6058         attr = _textblock_node_format_to_atspi_text_attr(format);
6059         if (!attr) continue;
6060         if (!strcmp(attr->name, attr_name))
6061           {
6062              *value = attr->value ? strdup(attr->value) : NULL;
6063              elm_atspi_text_text_attribute_free(attr);
6064              return EINA_TRUE;
6065           }
6066         elm_atspi_text_text_attribute_free(attr);
6067      }
6068 
6069    return EINA_FALSE;
6070 }
6071 
6072 EOLIAN static void
_elm_entry_efl_access_text_text_attributes_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int * start_offset,int * end_offset,Eina_List ** ret EFL_TRANSFER_OWNERSHIP)6073 _elm_entry_efl_access_text_text_attributes_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int *start_offset, int *end_offset, Eina_List **ret EFL_TRANSFER_OWNERSHIP)
6074 {
6075    Evas_Object *txtblk;
6076    Evas_Textblock_Cursor *cur1, *cur2;
6077    Eina_List *formats, *l;
6078    Evas_Object_Textblock_Node_Format *format;
6079    Efl_Access_Text_Attribute *attr;
6080 
6081    EINA_SAFETY_ON_NULL_RETURN(ret);
6082    *ret = NULL;
6083 
6084    txtblk = elm_entry_textblock_get(obj);
6085    if (!txtblk) return;
6086 
6087    cur1 = evas_object_textblock_cursor_new(txtblk);
6088    if (!cur1) return;
6089 
6090    cur2 = evas_object_textblock_cursor_new(txtblk);
6091    if (!cur2)
6092      {
6093         evas_textblock_cursor_free(cur1);
6094         return;
6095      }
6096 
6097    evas_textblock_cursor_pos_set(cur1, *start_offset);
6098    evas_textblock_cursor_pos_set(cur2, *end_offset);
6099 
6100    formats = evas_textblock_cursor_range_formats_get(cur1, cur2);
6101 
6102    evas_textblock_cursor_free(cur1);
6103    evas_textblock_cursor_free(cur2);
6104 
6105    if (!formats) return;
6106 
6107    EINA_LIST_FOREACH(formats, l , format)
6108      {
6109         attr = _textblock_node_format_to_atspi_text_attr(format);
6110         if (!attr) continue;
6111         *ret = eina_list_append(*ret, attr);
6112      }
6113 }
6114 
6115 EOLIAN static Eina_List*
_elm_entry_efl_access_text_default_attributes_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * _pd EINA_UNUSED)6116 _elm_entry_efl_access_text_default_attributes_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *_pd EINA_UNUSED)
6117 {
6118    Evas_Object *txtblk;
6119    Eina_List *ret = NULL;
6120    const Evas_Object_Textblock_Node_Format *format;
6121    Efl_Access_Text_Attribute *attr;
6122 
6123    txtblk = elm_entry_textblock_get(obj);
6124    if (!txtblk) return NULL;
6125 
6126    format = evas_textblock_node_format_first_get(txtblk);
6127    if (!format) return NULL;
6128 
6129    do
6130      {
6131         attr = _textblock_node_format_to_atspi_text_attr(format);
6132         if (!attr) continue;
6133         ret = eina_list_append(ret, attr);
6134      }
6135    while ((format = evas_textblock_node_format_next_get(format)) != NULL);
6136 
6137    return ret;
6138 }
6139 
6140 EOLIAN static Eina_Bool
_elm_entry_efl_access_editable_text_text_content_set(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,const char * content)6141 _elm_entry_efl_access_editable_text_text_content_set(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, const char *content)
6142 {
6143    elm_entry_entry_set(obj, content);
6144    return EINA_TRUE;
6145 }
6146 
6147 EOLIAN static Eina_Bool
_elm_entry_efl_access_editable_text_insert(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,const char * string,int position)6148 _elm_entry_efl_access_editable_text_insert(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, const char *string, int position)
6149 {
6150    elm_entry_cursor_pos_set(obj, position);
6151    elm_entry_entry_insert(obj, string);
6152 
6153    return EINA_TRUE;
6154 }
6155 
6156 EOLIAN static Eina_Bool
_elm_entry_efl_access_editable_text_copy(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int start,int end)6157 _elm_entry_efl_access_editable_text_copy(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int start, int end)
6158 {
6159    elm_entry_select_region_set(obj, start, end);
6160    elm_entry_selection_copy(obj);
6161 
6162    return EINA_TRUE;
6163 }
6164 
6165 EOLIAN static Eina_Bool
_elm_entry_efl_access_editable_text_delete(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int start_offset,int end_offset)6166 _elm_entry_efl_access_editable_text_delete(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int start_offset, int end_offset)
6167 {
6168    Evas_Object *txtblk;
6169    Evas_Textblock_Cursor *cur1, *cur2;
6170 
6171    txtblk = elm_entry_textblock_get(obj);
6172    if (!txtblk) return EINA_FALSE;
6173 
6174    cur1 = evas_object_textblock_cursor_new(txtblk);
6175    if (!cur1) return EINA_FALSE;
6176 
6177    cur2 = evas_object_textblock_cursor_new(txtblk);
6178    if (!cur2)
6179      {
6180         evas_textblock_cursor_free(cur1);
6181         return EINA_FALSE;
6182      }
6183 
6184    evas_textblock_cursor_pos_set(cur1, start_offset);
6185    evas_textblock_cursor_pos_set(cur2, end_offset);
6186 
6187    evas_textblock_cursor_range_delete(cur1, cur2);
6188 
6189    evas_textblock_cursor_free(cur1);
6190    evas_textblock_cursor_free(cur2);
6191 
6192    elm_entry_calc_force(obj);
6193 
6194    return EINA_TRUE;
6195 }
6196 
6197 EOLIAN static Eina_Bool
_elm_entry_efl_access_editable_text_paste(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int position)6198 _elm_entry_efl_access_editable_text_paste(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int position)
6199 {
6200    elm_entry_cursor_pos_set(obj, position);
6201    elm_entry_selection_paste(obj);
6202    return EINA_TRUE;
6203 }
6204 
6205 EOLIAN static Eina_Bool
_elm_entry_efl_access_editable_text_cut(Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED,int start,int end)6206 _elm_entry_efl_access_editable_text_cut(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED, int start, int end)
6207 {
6208    elm_entry_select_region_set(obj, start, end);
6209    elm_entry_selection_cut(obj);
6210    return EINA_TRUE;
6211 }
6212 
6213 EOLIAN static Efl_Access_State_Set
_elm_entry_efl_access_object_state_set_get(const Eo * obj,Elm_Entry_Data * _pd EINA_UNUSED)6214 _elm_entry_efl_access_object_state_set_get(const Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED)
6215 {
6216    Efl_Access_State_Set ret;
6217    ret = efl_access_object_state_set_get(efl_super(obj, ELM_ENTRY_CLASS));
6218 
6219    if (elm_entry_editable_get(obj))
6220      STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_EDITABLE);
6221 
6222    return ret;
6223 }
6224 
6225 EOLIAN static const char*
_elm_entry_efl_access_object_i18n_name_get(const Eo * obj,Elm_Entry_Data * sd)6226 _elm_entry_efl_access_object_i18n_name_get(const Eo *obj, Elm_Entry_Data *sd)
6227 {
6228    const char *name;
6229    name = efl_access_object_i18n_name_get(efl_super(obj, ELM_ENTRY_CLASS));
6230    if (name && strncmp("", name, 1)) return name;
6231 
6232    if (sd->password) return NULL;
6233 
6234    name = _elm_widget_accessible_plain_name_get(obj, elm_entry_entry_get(obj));
6235    if (name && strncmp("", name, 1)) return name;
6236 
6237    const char *ret = edje_object_part_text_get(sd->entry_edje, "elm.guide");
6238    return _elm_widget_accessible_plain_name_get(obj, ret);
6239 }
6240 
6241 static Eina_Bool
_action_activate(Evas_Object * obj,const char * params EINA_UNUSED)6242 _action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
6243 {
6244    _activate(obj);
6245    return EINA_TRUE;
6246 }
6247 
6248 EOLIAN const Efl_Access_Action_Data *
_elm_entry_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Entry_Data * sd EINA_UNUSED)6249 _elm_entry_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Entry_Data *sd EINA_UNUSED)
6250 {
6251    static Efl_Access_Action_Data atspi_actions[] = {
6252           { "activate", "activate", NULL, _action_activate },
6253           { NULL, NULL, NULL, NULL}
6254    };
6255    return &atspi_actions[0];
6256 }
6257 
6258 EOLIAN static Efl_Ui_Focus_Manager*
_elm_entry_efl_ui_widget_focus_manager_focus_manager_create(Eo * obj,Elm_Entry_Data * pd EINA_UNUSED,Efl_Ui_Focus_Object * root)6259 _elm_entry_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Elm_Entry_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
6260 {
6261    return efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj,
6262      efl_ui_focus_manager_root_set(efl_added, root)
6263    );
6264 }
6265 
6266 
6267 /* Efl.Part begin */
6268 
6269 ELM_PART_OVERRIDE(elm_entry, ELM_ENTRY, Elm_Entry_Data)
6270 ELM_PART_OVERRIDE_CONTENT_SET(elm_entry, ELM_ENTRY, Elm_Entry_Data)
6271 ELM_PART_OVERRIDE_CONTENT_UNSET(elm_entry, ELM_ENTRY, Elm_Entry_Data)
6272 ELM_PART_OVERRIDE_TEXT_SET(elm_entry, ELM_ENTRY, Elm_Entry_Data)
6273 ELM_PART_OVERRIDE_TEXT_GET(elm_entry, ELM_ENTRY, Elm_Entry_Data)
6274 ELM_PART_CONTENT_DEFAULT_GET(elm_entry, "icon")
6275 #include "elm_entry_part.eo.c"
6276 
6277 /* Efl.Part end */
6278 
6279 /* Internal EO APIs and hidden overrides */
6280 
6281 EFL_UI_LAYOUT_CONTENT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
6282 EFL_UI_LAYOUT_TEXT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
6283 
6284 #define ELM_ENTRY_EXTRA_OPS \
6285    ELM_PART_CONTENT_DEFAULT_OPS(elm_entry), \
6286    EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_entry), \
6287    EFL_UI_LAYOUT_CONTENT_ALIASES_OPS(MY_CLASS_PFX), \
6288    EFL_UI_LAYOUT_TEXT_ALIASES_OPS(MY_CLASS_PFX), \
6289    EFL_CANVAS_GROUP_CALC_OPS(elm_entry)
6290 
6291 #include "elm_entry_eo.c"
6292