support "guide text" for entries. trivial internal + theme changes :)
[framework/uifw/elementary.git] / src / lib / elm_entry.c
1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
3 #include "elm_priv.h"
4 #include "els_scroller.h"
5
6
7 /* Maximum chunk size to be inserted to the entry at once
8  * FIXME: This size is arbitrary, should probably choose a better size.
9  * Possibly also find a way to set it to a low value for weak computers,
10  * and to a big value for better computers. */
11 #define _CHUNK_SIZE 10000
12
13 typedef struct _Mod_Api Mod_Api;
14
15 typedef struct _Widget_Data Widget_Data;
16 typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
17 typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
18 typedef struct _Elm_Entry_Markup_Filter Elm_Entry_Markup_Filter;
19
20 struct _Widget_Data
21 {
22    Evas_Object *ent, *scroller;
23    Evas_Object *hoversel;
24    Ecore_Job *deferred_recalc_job;
25    Ecore_Event_Handler *sel_notify_handler;
26    Ecore_Event_Handler *sel_clear_handler;
27    Ecore_Timer *longpress_timer;
28    Ecore_Timer *delay_write;
29    /* for deferred appending */
30    Ecore_Idler *append_text_idler;
31    char *append_text_left;
32    int append_text_position;
33    int append_text_len;
34    /* Only for clipboard */
35    const char *cut_sel;
36    const char *text;
37    const char *file;
38    Elm_Text_Format format;
39    Evas_Coord lastw, entmw, entmh;
40    Evas_Coord downx, downy;
41    Eina_List *items;
42    Eina_List *item_providers;
43    Eina_List *text_filters;
44    Eina_List *markup_filters;
45    Ecore_Job *hovdeljob;
46    Mod_Api *api; // module api if supplied
47    int cursor_pos;
48    Elm_Scroller_Policy policy_h, policy_v;
49    Elm_Wrap_Type linewrap;
50    Elm_Input_Panel_Layout input_panel_layout;
51    Elm_Autocapital_Type autocapital_type;
52    Elm_Input_Panel_Lang input_panel_lang;
53    Elm_Input_Panel_Return_Key_Type input_panel_return_key_type;
54    void *input_panel_imdata;
55    int input_panel_imdata_len;
56    struct
57      {
58         Evas_Object *hover_parent;
59         Evas_Object *pop, *hover;
60         const char *hover_style;
61      } anchor_hover;
62    Eina_Bool changed : 1;
63    Eina_Bool single_line : 1;
64    Eina_Bool password : 1;
65    Eina_Bool editable : 1;
66    Eina_Bool selection_asked : 1;
67    Eina_Bool have_selection : 1;
68    Eina_Bool selmode : 1;
69    Eina_Bool deferred_cur : 1;
70    Eina_Bool cur_changed : 1;
71    Eina_Bool disabled : 1;
72    Eina_Bool context_menu : 1;
73    Eina_Bool drag_selection_asked : 1;
74    Eina_Bool can_write : 1;
75    Eina_Bool autosave : 1;
76    Eina_Bool usedown : 1;
77    Eina_Bool scroll : 1;
78    Eina_Bool h_bounce : 1;
79    Eina_Bool v_bounce : 1;
80    Eina_Bool input_panel_enable : 1;
81    Eina_Bool prediction_allow : 1;
82    Eina_Bool input_panel_return_key_disabled : 1;
83    Eina_Bool autoreturnkey : 1;
84    Eina_Bool havetext : 1;
85    Elm_Cnp_Mode cnp_mode : 2;
86 };
87
88 struct _Elm_Entry_Context_Menu_Item
89 {
90    Evas_Object *obj;
91    const char *label;
92    const char *icon_file;
93    const char *icon_group;
94    Elm_Icon_Type icon_type;
95    Evas_Smart_Cb func;
96    void *data;
97 };
98
99 struct _Elm_Entry_Item_Provider
100 {
101    Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item);
102    void *data;
103 };
104
105 struct _Elm_Entry_Markup_Filter
106 {
107    Elm_Entry_Filter_Cb func;
108    void *data;
109 };
110
111 typedef enum _Length_Unit
112 {
113    LENGTH_UNIT_CHAR,
114    LENGTH_UNIT_BYTE,
115    LENGTH_UNIT_LAST
116 } Length_Unit;
117
118 static const char *widtype = NULL;
119
120 #ifdef HAVE_ELEMENTARY_X
121 static Eina_Bool _drag_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *);
122 #endif
123 static void _del_hook(Evas_Object *obj);
124 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
125 static void _theme_hook(Evas_Object *obj);
126 static void _disable_hook(Evas_Object *obj);
127 static void _sizing_eval(Evas_Object *obj);
128 static void _on_focus_hook(void *data, Evas_Object *obj);
129 static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
130 static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
131 static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
132 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
133 static const char *_getbase(Evas_Object *obj);
134 static void _signal_entry_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
135 static void _signal_selection_start(void *data, Evas_Object *obj, const char *emission, const char *source);
136 static void _signal_selection_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
137 static void _signal_selection_cleared(void *data, Evas_Object *obj, const char *emission, const char *source);
138 static void _signal_entry_paste_request(void *data, Evas_Object *obj, const char *emission, const char *source);
139 static void _signal_entry_copy_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
140 static void _signal_entry_cut_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
141 static void _signal_cursor_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
142 static void _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit unit);
143 static void _entry_hover_anchor_clicked(void *data, Evas_Object *obj, void *event_info);
144
145 static const char SIG_CHANGED[] = "changed";
146 static const char SIG_CHANGED_USER[] = "changed,user";
147 static const char SIG_ACTIVATED[] = "activated";
148 static const char SIG_PRESS[] = "press";
149 static const char SIG_LONGPRESSED[] = "longpressed";
150 static const char SIG_CLICKED[] = "clicked";
151 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
152 static const char SIG_CLICKED_TRIPLE[] = "clicked,triple";
153 static const char SIG_FOCUSED[] = "focused";
154 static const char SIG_UNFOCUSED[] = "unfocused";
155 static const char SIG_SELECTION_PASTE[] = "selection,paste";
156 static const char SIG_SELECTION_COPY[] = "selection,copy";
157 static const char SIG_SELECTION_CUT[] = "selection,cut";
158 static const char SIG_SELECTION_START[] = "selection,start";
159 static const char SIG_SELECTION_CHANGED[] = "selection,changed";
160 static const char SIG_SELECTION_CLEARED[] = "selection,cleared";
161 static const char SIG_CURSOR_CHANGED[] = "cursor,changed";
162 static const char SIG_CURSOR_CHANGED_MANUAL[] = "cursor,changed,manual";
163 static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
164 static const char SIG_ANCHOR_HOVER_OPENED[] = "anchor,hover,opened";
165 static const char SIG_ANCHOR_DOWN[] = "anchor,down";
166 static const char SIG_ANCHOR_UP[] = "anchor,up";
167 static const char SIG_ANCHOR_IN[] = "anchor,in";
168 static const char SIG_ANCHOR_OUT[] = "anchor,out";
169 static const char SIG_PREEDIT_CHANGED[] = "preedit,changed";
170 static const char SIG_UNDO_REQUEST[] = "undo,request";
171 static const char SIG_REDO_REQUEST[] = "redo,request";
172 static const Evas_Smart_Cb_Description _signals[] = {
173        {SIG_CHANGED, ""},
174        {SIG_ACTIVATED, ""},
175        {SIG_PRESS, ""},
176        {SIG_LONGPRESSED, ""},
177        {SIG_CLICKED, ""},
178        {SIG_CLICKED_DOUBLE, ""},
179        {SIG_CLICKED_TRIPLE, ""},
180        {SIG_FOCUSED, ""},
181        {SIG_UNFOCUSED, ""},
182        {SIG_SELECTION_PASTE, ""},
183        {SIG_SELECTION_COPY, ""},
184        {SIG_SELECTION_CUT, ""},
185        {SIG_SELECTION_START, ""},
186        {SIG_SELECTION_CHANGED, ""},
187        {SIG_SELECTION_CLEARED, ""},
188        {SIG_CURSOR_CHANGED, ""},
189        {SIG_CURSOR_CHANGED_MANUAL, ""},
190        {SIG_ANCHOR_CLICKED, ""},
191        {SIG_ANCHOR_HOVER_OPENED, ""},
192        {SIG_ANCHOR_DOWN, ""},
193        {SIG_ANCHOR_UP, ""},
194        {SIG_ANCHOR_IN, ""},
195        {SIG_ANCHOR_OUT, ""},
196        {SIG_PREEDIT_CHANGED, ""},
197        {SIG_CHANGED_USER, ""},
198        {SIG_UNDO_REQUEST, ""},
199        {SIG_REDO_REQUEST, ""},
200        {NULL, NULL}
201 };
202
203 static Eina_List *entries = NULL;
204
205 struct _Mod_Api
206 {
207    void (*obj_hook) (Evas_Object *obj);
208    void (*obj_unhook) (Evas_Object *obj);
209    void (*obj_longpress) (Evas_Object *obj);
210 };
211
212 static Mod_Api *
213 _module(Evas_Object *obj __UNUSED__)
214 {
215    static Elm_Module *m = NULL;
216    if (m) goto ok; // already found - just use
217    if (!(m = _elm_module_find_as("entry/api"))) return NULL;
218    // get module api
219    m->api = malloc(sizeof(Mod_Api));
220    if (!m->api) return NULL;
221    ((Mod_Api *)(m->api)      )->obj_hook = // called on creation
222       _elm_module_symbol_get(m, "obj_hook");
223    ((Mod_Api *)(m->api)      )->obj_unhook = // called on deletion
224       _elm_module_symbol_get(m, "obj_unhook");
225    ((Mod_Api *)(m->api)      )->obj_longpress = // called on long press menu
226       _elm_module_symbol_get(m, "obj_longpress");
227 ok: // ok - return api
228    return m->api;
229 }
230
231 static char *
232 _buf_append(char *buf, const char *str, int *len, int *alloc)
233 {
234    int len2 = strlen(str);
235    if ((*len + len2) >= *alloc)
236      {
237         char *buf2 = realloc(buf, *alloc + len2 + 512);
238         if (!buf2) return NULL;
239         buf = buf2;
240         *alloc += (512 + len2);
241      }
242    strcpy(buf + *len, str);
243    *len += len2;
244    return buf;
245 }
246
247 static char *
248 _load_file(const char *file)
249 {
250    FILE *f;
251    size_t size;
252    int alloc = 0, len = 0;
253    char *text = NULL, buf[16384 + 1];
254
255    f = fopen(file, "rb");
256    if (!f) return NULL;
257    while ((size = fread(buf, 1, sizeof(buf) - 1, f)))
258      {
259         char *tmp_text;
260         buf[size] = 0;
261         tmp_text = _buf_append(text, buf, &len, &alloc);
262         if (!tmp_text) break;
263         text = tmp_text;
264      }
265    fclose(f);
266    return text;
267 }
268
269 static char *
270 _load_plain(const char *file)
271 {
272    char *text;
273
274    text = _load_file(file);
275    if (text)
276      {
277         char *text2;
278
279         text2 = elm_entry_utf8_to_markup(text);
280         free(text);
281         return text2;
282      }
283    return NULL;
284 }
285
286 static Eina_Bool
287 _load(Evas_Object *obj)
288 {
289    Widget_Data *wd = elm_widget_data_get(obj);
290    char *text;
291    if (!wd) return EINA_FALSE;
292    if (!wd->file)
293      {
294         elm_object_text_set(obj, "");
295         return EINA_TRUE;
296      }
297    switch (wd->format)
298      {
299       case ELM_TEXT_FORMAT_PLAIN_UTF8:
300          text = _load_plain(wd->file);
301          break;
302       case ELM_TEXT_FORMAT_MARKUP_UTF8:
303          text = _load_file(wd->file);
304          break;
305       default:
306          text = NULL;
307          break;
308      }
309    if (text)
310      {
311         elm_object_text_set(obj, text);
312         free(text);
313         return EINA_TRUE;
314      }
315    else
316      {
317         elm_object_text_set(obj, "");
318         return EINA_FALSE;
319      }
320 }
321
322 static void
323 _save_markup_utf8(const char *file, const char *text)
324 {
325    FILE *f;
326
327    if ((!text) || (!text[0]))
328      {
329         ecore_file_unlink(file);
330         return;
331      }
332    f = fopen(file, "wb");
333    if (!f)
334      {
335         // FIXME: report a write error
336         return;
337      }
338    fputs(text, f); // FIXME: catch error
339    fclose(f);
340 }
341
342 static void
343 _save_plain_utf8(const char *file, const char *text)
344 {
345    char *text2;
346
347    text2 = elm_entry_markup_to_utf8(text);
348    if (!text2)
349      return;
350    _save_markup_utf8(file, text2);
351    free(text2);
352 }
353
354 static void
355 _save(Evas_Object *obj)
356 {
357    Widget_Data *wd = elm_widget_data_get(obj);
358    if (!wd) return;
359    if (!wd->file) return;
360    switch (wd->format)
361      {
362       case ELM_TEXT_FORMAT_PLAIN_UTF8:
363          _save_plain_utf8(wd->file, elm_object_text_get(obj));
364          break;
365       case ELM_TEXT_FORMAT_MARKUP_UTF8:
366          _save_markup_utf8(wd->file, elm_object_text_get(obj));
367          break;
368       default:
369          break;
370      }
371 }
372
373 static Eina_Bool
374 _delay_write(void *data)
375 {
376    Widget_Data *wd = elm_widget_data_get(data);
377    if (!wd) return ECORE_CALLBACK_CANCEL;
378    _save(data);
379    wd->delay_write = NULL;
380    return ECORE_CALLBACK_CANCEL;
381 }
382
383 static void
384 _elm_entry_update_guide(Evas_Object *obj, Eina_Bool havetext)
385 {
386    Widget_Data *wd = elm_widget_data_get(obj);
387    if (!wd) return;
388    if ((havetext) && (!wd->havetext))
389      edje_object_signal_emit(wd->ent, "elm,guide,disabled", "elm");
390    else if ((!havetext) && (wd->havetext))
391      edje_object_signal_emit(wd->ent, "elm,guide,enabled", "elm");
392    wd->havetext = havetext;
393 }
394
395 static Elm_Entry_Markup_Filter *
396 _filter_new(Elm_Entry_Filter_Cb func, void *data)
397 {
398    Elm_Entry_Markup_Filter *tf = ELM_NEW(Elm_Entry_Markup_Filter);
399    if (!tf) return NULL;
400
401    tf->func = func;
402    if (func == elm_entry_filter_limit_size)
403      {
404         Elm_Entry_Filter_Limit_Size *lim = data, *lim2;
405
406         if (!data)
407           {
408              free(tf);
409              return NULL;
410           }
411         lim2 = malloc(sizeof(Elm_Entry_Filter_Limit_Size));
412         if (!lim2)
413           {
414              free(tf);
415              return NULL;
416           }
417         memcpy(lim2, lim, sizeof(Elm_Entry_Filter_Limit_Size));
418         tf->data = lim2;
419      }
420    else if (func == elm_entry_filter_accept_set)
421      {
422         Elm_Entry_Filter_Accept_Set *as = data, *as2;
423
424         if (!data)
425           {
426              free(tf);
427              return NULL;
428           }
429         as2 = malloc(sizeof(Elm_Entry_Filter_Accept_Set));
430         if (!as2)
431           {
432              free(tf);
433              return NULL;
434           }
435         if (as->accepted)
436           as2->accepted = eina_stringshare_add(as->accepted);
437         else
438           as2->accepted = NULL;
439         if (as->rejected)
440           as2->rejected = eina_stringshare_add(as->rejected);
441         else
442           as2->rejected = NULL;
443         tf->data = as2;
444      }
445    else
446      tf->data = data;
447    return tf;
448 }
449
450 static void
451 _filter_free(Elm_Entry_Markup_Filter *tf)
452 {
453    if (tf->func == elm_entry_filter_limit_size)
454      {
455         Elm_Entry_Filter_Limit_Size *lim = tf->data;
456         if (lim) free(lim);
457      }
458    else if (tf->func == elm_entry_filter_accept_set)
459      {
460         Elm_Entry_Filter_Accept_Set *as = tf->data;
461         if (as)
462           {
463              if (as->accepted) eina_stringshare_del(as->accepted);
464              if (as->rejected) eina_stringshare_del(as->rejected);
465              free(as);
466           }
467      }
468    free(tf);
469 }
470
471 static void
472 _del_pre_hook(Evas_Object *obj)
473 {
474    Widget_Data *wd = elm_widget_data_get(obj);
475    if (!wd) return;
476    if (wd->delay_write)
477      {
478         ecore_timer_del(wd->delay_write);
479         wd->delay_write = NULL;
480         if (wd->autosave) _save(obj);
481      }
482    elm_entry_anchor_hover_end(obj);
483    elm_entry_anchor_hover_parent_set(obj, NULL);
484 }
485
486 static void
487 _del_hook(Evas_Object *obj)
488 {
489    Widget_Data *wd = elm_widget_data_get(obj);
490    Elm_Entry_Context_Menu_Item *it;
491    Elm_Entry_Item_Provider *ip;
492    Elm_Entry_Markup_Filter *tf;
493
494    evas_event_freeze(evas_object_evas_get(obj));
495
496    if (wd->file) eina_stringshare_del(wd->file);
497
498    if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
499    if ((wd->api) && (wd->api->obj_unhook)) wd->api->obj_unhook(obj); // module - unhook
500
501    entries = eina_list_remove(entries, obj);
502 #ifdef HAVE_ELEMENTARY_X
503    if (wd->sel_notify_handler)
504      ecore_event_handler_del(wd->sel_notify_handler);
505    if (wd->sel_clear_handler)
506      ecore_event_handler_del(wd->sel_clear_handler);
507 #endif
508    if (wd->cut_sel) eina_stringshare_del(wd->cut_sel);
509    if (wd->text) eina_stringshare_del(wd->text);
510    if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
511    if (wd->append_text_idler)
512      {
513         ecore_idler_del(wd->append_text_idler);
514         free(wd->append_text_left);
515         wd->append_text_left = NULL;
516         wd->append_text_idler = NULL;
517      }
518    if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
519    EINA_LIST_FREE(wd->items, it)
520      {
521         eina_stringshare_del(it->label);
522         eina_stringshare_del(it->icon_file);
523         eina_stringshare_del(it->icon_group);
524         free(it);
525      }
526    EINA_LIST_FREE(wd->item_providers, ip)
527      {
528         free(ip);
529      }
530    EINA_LIST_FREE(wd->text_filters, tf)
531      {
532         _filter_free(tf);
533      }
534    EINA_LIST_FREE(wd->markup_filters, tf)
535      {
536         _filter_free(tf);
537      }
538    if (wd->delay_write) ecore_timer_del(wd->delay_write);
539    if (wd->input_panel_imdata) free(wd->input_panel_imdata);
540
541    if (wd->anchor_hover.hover_style) eina_stringshare_del(wd->anchor_hover.hover_style);
542    evas_event_thaw(evas_object_evas_get(obj));
543    evas_event_thaw_eval(evas_object_evas_get(obj));
544    free(wd);
545 }
546
547 static void
548 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
549 {
550    Widget_Data *wd = elm_widget_data_get(obj);
551    edje_object_mirrored_set(wd->ent, rtl);
552    if (wd->anchor_hover.hover)
553       elm_widget_mirrored_set(wd->anchor_hover.hover, rtl);
554 }
555
556 static void
557 _theme_hook(Evas_Object *obj)
558 {
559    Widget_Data *wd = elm_widget_data_get(obj);
560    const char *t;
561
562    evas_event_freeze(evas_object_evas_get(obj));
563    _elm_widget_mirrored_reload(obj);
564    _mirrored_set(obj, elm_widget_mirrored_get(obj));
565
566    t = eina_stringshare_add(elm_object_text_get(obj));
567    _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
568    if (_elm_config->desktop_entry)
569      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
570    elm_object_text_set(obj, t);
571    eina_stringshare_del(t);
572    if (elm_widget_disabled_get(obj))
573      edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
574    edje_object_part_text_input_panel_layout_set(wd->ent, "elm.text", wd->input_panel_layout);
575    edje_object_part_text_autocapital_type_set(wd->ent, "elm.text", wd->autocapital_type);
576    edje_object_part_text_prediction_allow_set(wd->ent, "elm.text", wd->prediction_allow);
577    edje_object_part_text_input_panel_enabled_set(wd->ent, "elm.text", wd->input_panel_enable);
578    edje_object_part_text_input_panel_imdata_set(wd->ent, "elm.text", wd->input_panel_imdata, wd->input_panel_imdata_len);
579    edje_object_part_text_input_panel_return_key_type_set(wd->ent, "elm.text", wd->input_panel_return_key_type);
580    edje_object_part_text_input_panel_return_key_disabled_set(wd->ent, "elm.text", wd->input_panel_return_key_disabled);
581
582    if (wd->cursor_pos != 0)
583      elm_entry_cursor_pos_set(obj, wd->cursor_pos);
584    if (elm_widget_focus_get(obj))
585      edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
586    edje_object_message_signal_process(wd->ent);
587    edje_object_scale_set(wd->ent, elm_widget_scale_get(obj) * _elm_config->scale);
588    if (wd->scroll)
589      {
590         const char *str;
591         Evas_Object *edj;
592
593         elm_smart_scroller_mirrored_set(wd->scroller, elm_widget_mirrored_get(obj));
594         elm_smart_scroller_object_theme_set(obj, wd->scroller, "scroller", "entry",
595                                        elm_widget_style_get(obj));
596         edj = elm_smart_scroller_edje_object_get(wd->scroller);
597         str = edje_object_data_get(edj, "focus_highlight");
598         if ((str) && (!strcmp(str, "on")))
599           elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
600         else
601           elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
602      }
603    _sizing_eval(obj);
604    wd->havetext = !wd->havetext;
605    _elm_entry_update_guide(obj, !wd->havetext);
606    evas_event_thaw(evas_object_evas_get(obj));
607    evas_event_thaw_eval(evas_object_evas_get(obj));
608 }
609
610 static void
611 _disable_hook(Evas_Object *obj)
612 {
613    Widget_Data *wd = elm_widget_data_get(obj);
614
615    if (elm_widget_disabled_get(obj))
616      {
617         edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
618         wd->disabled = EINA_TRUE;
619      }
620    else
621      {
622         edje_object_signal_emit(wd->ent, "elm,state,enabled", "elm");
623         wd->disabled = EINA_FALSE;
624      }
625 }
626
627 static void
628 _recalc_cursor_geometry(Evas_Object *obj)
629 {
630    Widget_Data *wd = elm_widget_data_get(obj);
631    if (!wd) return;
632    evas_object_smart_callback_call(obj, SIG_CURSOR_CHANGED, NULL);
633    if (!wd->deferred_recalc_job)
634      {
635         Evas_Coord cx, cy, cw, ch;
636         edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
637                                                   &cx, &cy, &cw, &ch);
638         if (wd->cur_changed)
639           {
640              elm_widget_show_region_set(obj, cx, cy, cw, ch, EINA_FALSE);
641              wd->cur_changed = EINA_FALSE;
642           }
643      }
644    else
645      wd->deferred_cur = EINA_TRUE;
646 }
647
648 static void
649 _elm_deferred_recalc_job(void *data)
650 {
651    Widget_Data *wd = elm_widget_data_get(data);
652    Evas_Coord minh = -1, resw = -1, minw = -1, fw = 0, fh = 0;
653    if (!wd) return;
654    wd->deferred_recalc_job = NULL;
655
656    evas_object_geometry_get(wd->ent, NULL, NULL, &resw, NULL);
657    edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, resw, 0);
658    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
659    /* This is a hack to workaround the way min size hints are treated.
660     * If the minimum width is smaller than the restricted width, it means
661     * the mininmum doesn't matter. */
662    if (minw <= resw)
663      {
664         Evas_Coord ominw = -1;
665         evas_object_size_hint_min_get(data, &ominw, NULL);
666         minw = ominw;
667      }
668
669    wd->entmw = minw;
670    wd->entmh = minh;
671
672    elm_coords_finger_size_adjust(1, &fw, 1, &fh);
673    if (wd->scroll)
674      {
675         Evas_Coord vmw = 0, vmh = 0;
676
677         edje_object_size_min_calc
678            (elm_smart_scroller_edje_object_get(wd->scroller),
679                &vmw, &vmh);
680         if (wd->single_line)
681           {
682              evas_object_size_hint_min_set(data, vmw, minh + vmh);
683              evas_object_size_hint_max_set(data, -1, minh + vmh);
684           }
685         else
686           {
687              evas_object_size_hint_min_set(data, vmw, vmh);
688              evas_object_size_hint_max_set(data, -1, -1);
689           }
690      }
691    else
692      {
693         if (wd->single_line)
694           {
695              evas_object_size_hint_min_set(data, minw, minh);
696              evas_object_size_hint_max_set(data, -1, minh);
697           }
698         else
699           {
700              evas_object_size_hint_min_set(data, fw, minh);
701              evas_object_size_hint_max_set(data, -1, -1);
702           }
703      }
704
705    if (wd->deferred_cur)
706      {
707         Evas_Coord cx, cy, cw, ch;
708         edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
709                                                   &cx, &cy, &cw, &ch);
710         if (wd->cur_changed)
711           {
712              elm_widget_show_region_set(data, cx, cy, cw, ch, EINA_FALSE);
713              wd->cur_changed = EINA_FALSE;
714           }
715      }
716 }
717
718 static void
719 _sizing_eval(Evas_Object *obj)
720 {
721    Widget_Data *wd = elm_widget_data_get(obj);
722    Evas_Coord minw = -1, minh = -1;
723    Evas_Coord resw, resh;
724    if (!wd) return;
725
726    evas_object_geometry_get(obj, NULL, NULL, &resw, &resh);
727    if (wd->linewrap)
728      {
729         if ((resw == wd->lastw) && (!wd->changed)) return;
730         evas_event_freeze(evas_object_evas_get(obj));
731         wd->changed = EINA_FALSE;
732         wd->lastw = resw;
733         if (wd->scroll)
734           {
735              Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
736
737              evas_object_resize(wd->scroller, resw, resh);
738              edje_object_size_min_calc
739                 (elm_smart_scroller_edje_object_get(wd->scroller),
740                  &vmw, &vmh);
741              elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
742              edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, vw, 0);
743              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
744              /* This is a hack to workaround the way min size hints are treated.
745               * If the minimum width is smaller than the restricted width, it means
746               * the mininmum doesn't matter. */
747              if (minw <= vw)
748                {
749                   Evas_Coord ominw = -1;
750                   evas_object_size_hint_min_get(wd->ent, &ominw, NULL);
751                   minw = ominw;
752                }
753              wd->entmw = minw;
754              wd->entmh = minh;
755
756              if ((minw > 0) && (vw < minw)) vw = minw;
757              if (minh > vh) vh = minh;
758
759              if (wd->single_line) h = vmh + minh;
760              else h = vmh;
761              evas_object_resize(wd->ent, vw, vh);
762              evas_object_size_hint_min_set(obj, w, h);
763              if (wd->single_line)
764                evas_object_size_hint_max_set(obj, -1, h);
765              else
766                evas_object_size_hint_max_set(obj, -1, -1);
767           }
768         else
769           {
770              if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
771              wd->deferred_recalc_job = ecore_job_add(_elm_deferred_recalc_job, obj);
772           }
773         evas_event_thaw(evas_object_evas_get(obj));
774         evas_event_thaw_eval(evas_object_evas_get(obj));
775      }
776    else
777      {
778         if (!wd->changed) return;
779         evas_event_freeze(evas_object_evas_get(obj));
780         wd->changed = EINA_FALSE;
781         wd->lastw = resw;
782         if (wd->scroll)
783           {
784              Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
785
786              edje_object_size_min_calc(wd->ent, &minw, &minh);
787              wd->entmw = minw;
788              wd->entmh = minh;
789              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
790
791              elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
792
793              if (minw > vw) vw = minw;
794              if (minh > vh) vh = minh;
795
796              evas_object_resize(wd->ent, vw, vh);
797              edje_object_size_min_calc
798                 (elm_smart_scroller_edje_object_get(wd->scroller),
799                  &vmw, &vmh);
800              if (wd->single_line) h = vmh + minh;
801              else h = vmh;
802              evas_object_size_hint_min_set(obj, w, h);
803              if (wd->single_line)
804                evas_object_size_hint_max_set(obj, -1, h);
805              else
806                evas_object_size_hint_max_set(obj, -1, -1);
807           }
808         else
809           {
810              edje_object_size_min_calc(wd->ent, &minw, &minh);
811              wd->entmw = minw;
812              wd->entmh = minh;
813              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
814              evas_object_size_hint_min_set(obj, minw, minh);
815              if (wd->single_line)
816                evas_object_size_hint_max_set(obj, -1, minh);
817              else
818                evas_object_size_hint_max_set(obj, -1, -1);
819           }
820         evas_event_thaw(evas_object_evas_get(obj));
821         evas_event_thaw_eval(evas_object_evas_get(obj));
822      }
823
824    _recalc_cursor_geometry(obj);
825 }
826
827 static void
828 _check_enable_return_key(Evas_Object *obj)
829 {
830    Widget_Data *wd = elm_widget_data_get(obj);
831    Eina_Bool return_key_disabled = EINA_FALSE;
832    if (!wd) return;
833
834    if (!wd->autoreturnkey) return;
835
836    if (elm_entry_is_empty(obj) == EINA_TRUE)
837      return_key_disabled = EINA_TRUE;
838
839    elm_entry_input_panel_return_key_disabled_set(obj, return_key_disabled);
840 }
841
842 static void
843 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
844 {
845    Widget_Data *wd = elm_widget_data_get(obj);
846    Evas_Object *top = elm_widget_top_get(obj);
847    if (!wd) return;
848    if (!wd->editable) return;
849    if (elm_widget_focus_get(obj))
850      {
851         evas_object_focus_set(wd->ent, EINA_TRUE);
852         edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
853         if (top && wd->input_panel_enable)
854           elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
855         evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
856         _check_enable_return_key(obj);
857      }
858    else
859      {
860         edje_object_signal_emit(wd->ent, "elm,action,unfocus", "elm");
861         evas_object_focus_set(wd->ent, EINA_FALSE);
862         if (top && wd->input_panel_enable)
863           elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
864         evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
865      }
866 }
867
868 static void
869 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
870 {
871    Widget_Data *wd = elm_widget_data_get(obj);
872    Evas_Object *edje;
873    Evas_Object *prev_content;
874    if ((!wd) || (!content)) return;
875
876    if (wd->scroll)
877       edje = elm_smart_scroller_edje_object_get(wd->scroller);
878    else
879       edje = wd->ent;
880
881    if (!part || !strcmp(part, "icon"))
882      {
883         prev_content = edje_object_part_swallow_get(edje, "elm.swallow.icon");
884         edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
885      }
886    else if (!strcmp(part, "end"))
887      {
888         prev_content = edje_object_part_swallow_get(edje, "elm.swallow.end");
889         edje_object_signal_emit(edje, "elm,action,show,end", "elm");
890      }
891    else
892      prev_content = edje_object_part_swallow_get(edje, part);
893
894    if (prev_content) evas_object_del(prev_content);
895
896    evas_event_freeze(evas_object_evas_get(obj));
897    elm_widget_sub_object_add(obj, content);
898
899    if (!part || !strcmp(part, "icon"))
900      edje_object_part_swallow(edje, "elm.swallow.icon", content);
901    else if (!strcmp(part, "end"))
902      edje_object_part_swallow(edje, "elm.swallow.end", content);
903    else
904      edje_object_part_swallow(edje, part, content);
905
906    _sizing_eval(obj);
907    evas_event_thaw(evas_object_evas_get(obj));
908    evas_event_thaw_eval(evas_object_evas_get(obj));
909 }
910
911 static Evas_Object *
912 _content_unset_hook(Evas_Object *obj, const char *part)
913 {
914    Widget_Data *wd = elm_widget_data_get(obj);
915    Evas_Object *content, *edje;
916    if (!wd) return NULL;
917
918    if (wd->scroll)
919       edje = elm_smart_scroller_edje_object_get(wd->scroller);
920    else
921       edje = wd->ent;
922
923    if (!part || !strcmp(part, "icon"))
924      {
925         edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
926         content = edje_object_part_swallow_get(edje, "elm.swallow.icon");
927      }
928    else if (!strcmp(part, "end"))
929      {
930         edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
931         content = edje_object_part_swallow_get(edje, "elm.swallow.end");
932      }
933    else
934      content = edje_object_part_swallow_get(edje, part);
935
936    edje_object_part_swallow(edje, part, NULL);
937    if (!content) return NULL;
938    evas_event_freeze(evas_object_evas_get(obj));
939    elm_widget_sub_object_del(obj, content);
940    edje_object_part_unswallow(wd->ent, content);
941    _sizing_eval(obj);
942    evas_event_thaw(evas_object_evas_get(obj));
943    evas_event_thaw_eval(evas_object_evas_get(obj));
944
945    return content;
946 }
947
948 static Evas_Object *
949 _content_get_hook(const Evas_Object *obj, const char *part)
950 {
951    Widget_Data *wd = elm_widget_data_get(obj);
952    Evas_Object *content = NULL, *edje;
953    if (!wd) return NULL;
954
955    if (wd->scroll)
956       edje = elm_smart_scroller_edje_object_get(wd->scroller);
957    else
958       edje = wd->ent;
959
960    if (!edje) return NULL;
961
962    if (!part || !strcmp(part, "icon"))
963      content = edje_object_part_swallow_get(edje, "elm.swallow.icon");
964    else if (!strcmp(part, "end"))
965      content = edje_object_part_swallow_get(edje, "elm.swallow.end");
966    else
967      content = edje_object_part_swallow_get(edje, part);
968
969    return content;
970 }
971
972 static void
973 _translate_hook(Evas_Object *obj)
974 {
975    evas_object_smart_callback_call(obj, "language,changed", NULL);
976 }
977
978 static void
979 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
980 {
981    Widget_Data *wd = elm_widget_data_get(obj);
982    if (!wd) return;
983    edje_object_signal_emit(wd->ent, emission, source);
984    if (wd->scroller)
985      edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scroller),
986                              emission, source);
987 }
988
989 static void
990 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
991 {
992    Widget_Data *wd = elm_widget_data_get(obj);
993    if (!wd) return;
994    edje_object_signal_callback_add(wd->ent, emission, source, func_cb, data);
995    if (wd->scroller)
996      edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scroller),
997                                      emission, source, func_cb, data);
998 }
999
1000 static void
1001 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
1002 {
1003    Widget_Data *wd = elm_widget_data_get(obj);
1004    edje_object_signal_callback_del_full(wd->ent, emission, source, func_cb,
1005                                         data);
1006    if (wd->scroller)
1007      edje_object_signal_callback_del_full(elm_smart_scroller_edje_object_get(wd->scroller),
1008                                           emission, source, func_cb, data);
1009 }
1010
1011 static void
1012 _on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1013 {
1014    Widget_Data *wd = elm_widget_data_get(obj);
1015    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
1016 }
1017
1018 static void
1019 _focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1020 {
1021    Widget_Data *wd = elm_widget_data_get(obj);
1022    if (wd->scroll)
1023      elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
1024 }
1025
1026 static void
1027 _show_region_hook(void *data, Evas_Object *obj)
1028 {
1029    Widget_Data *wd = elm_widget_data_get(data);
1030    Evas_Coord x, y, w, h;
1031    if (!wd) return;
1032    elm_widget_show_region_get(obj, &x, &y, &w, &h);
1033    if (wd->scroll)
1034      elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
1035 }
1036
1037 static void
1038 _sub_del(void *data, Evas_Object *obj, void *event_info)
1039 {
1040    Widget_Data *wd = data;
1041    Evas_Object *sub = event_info;
1042    Evas_Object *edje;
1043
1044    if (wd->scroll)
1045       edje = elm_smart_scroller_edje_object_get(wd->scroller);
1046    else
1047       edje = wd->ent;
1048
1049    if (sub == edje_object_part_swallow_get(edje, "elm.swallow.icon"))
1050      {
1051         edje_object_part_unswallow(edje, sub);
1052         if (edje)
1053           edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
1054      }
1055    else if (sub == edje_object_part_swallow_get(edje, "elm.swallow.end"))
1056      {
1057         edje_object_part_unswallow(edje, sub);
1058         if (edje)
1059           edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
1060      }
1061    _sizing_eval(obj);
1062 }
1063
1064 static void
1065 _hoversel_position(Evas_Object *obj)
1066 {
1067    Widget_Data *wd = elm_widget_data_get(obj);
1068    Evas_Coord cx, cy, cw, ch, x, y, mw, mh;
1069    if (!wd) return;
1070
1071    cx = cy = 0;
1072    cw = ch = 1;
1073    evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
1074    if (wd->usedown)
1075      {
1076         cx = wd->downx - x;
1077         cy = wd->downy - y;
1078         cw = 1;
1079         ch = 1;
1080      }
1081    else
1082      edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
1083                                                &cx, &cy, &cw, &ch);
1084    evas_object_size_hint_min_get(wd->hoversel, &mw, &mh);
1085    if (cw < mw)
1086      {
1087         cx += (cw - mw) / 2;
1088         cw = mw;
1089      }
1090    if (ch < mh)
1091      {
1092         cy += (ch - mh) / 2;
1093         ch = mh;
1094      }
1095    evas_object_move(wd->hoversel, x + cx, y + cy);
1096    evas_object_resize(wd->hoversel, cw, ch);
1097 }
1098
1099 static void
1100 _move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1101 {
1102    Widget_Data *wd = elm_widget_data_get(data);
1103
1104    if (wd->hoversel) _hoversel_position(data);
1105 }
1106
1107 static void
1108 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1109 {
1110    Widget_Data *wd = elm_widget_data_get(data);
1111    if (!wd) return;
1112
1113    if (wd->linewrap)
1114      {
1115         _sizing_eval(data);
1116      }
1117    else if (wd->scroll)
1118      {
1119         Evas_Coord vw = 0, vh = 0;
1120
1121         elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
1122         if (vw < wd->entmw) vw = wd->entmw;
1123         if (vh < wd->entmh) vh = wd->entmh;
1124         evas_object_resize(wd->ent, vw, vh);
1125      }
1126    if (wd->hoversel) _hoversel_position(data);
1127 }
1128
1129 static void
1130 _hover_del(void *data)
1131 {
1132    Widget_Data *wd = elm_widget_data_get(data);
1133    if (!wd) return;
1134
1135    if (wd->hoversel)
1136      {
1137         evas_object_del(wd->hoversel);
1138         wd->hoversel = NULL;
1139      }
1140    wd->hovdeljob = NULL;
1141 }
1142
1143 static void
1144 _dismissed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1145 {
1146    Widget_Data *wd = elm_widget_data_get(data);
1147    if (!wd) return;
1148    wd->usedown = 0;
1149    if (wd->hoversel) evas_object_hide(wd->hoversel);
1150    if (wd->selmode)
1151      {
1152         if (!_elm_config->desktop_entry)
1153           {
1154              if (!wd->password)
1155                edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
1156           }
1157      }
1158    elm_widget_scroll_freeze_pop(data);
1159    if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
1160    wd->hovdeljob = ecore_job_add(_hover_del, data);
1161 }
1162
1163 static void
1164 _select(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1165 {
1166    Widget_Data *wd = elm_widget_data_get(data);
1167    if (!wd) return;
1168    wd->selmode = EINA_TRUE;
1169    edje_object_part_text_select_none(wd->ent, "elm.text");
1170    if (!_elm_config->desktop_entry)
1171      {
1172         if (!wd->password)
1173           edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
1174      }
1175    edje_object_signal_emit(wd->ent, "elm,state,select,on", "elm");
1176    if (!_elm_config->desktop_entry)
1177      elm_widget_scroll_hold_push(data);
1178 }
1179
1180 static char *
1181 _remove_item_tags(const char *str)
1182 {
1183    char *ret;
1184    if (!str)
1185      return NULL;
1186
1187    Eina_Strbuf *buf = eina_strbuf_new();
1188    if (!buf)
1189      return NULL;
1190
1191    if (!eina_strbuf_append(buf, str))
1192      return NULL;
1193
1194    while (EINA_TRUE)
1195      {
1196         const char *temp = eina_strbuf_string_get(buf);
1197
1198         char *startTag = NULL;
1199         char *endTag = NULL;
1200
1201         startTag = strstr(temp, "<item");
1202         if (!startTag)
1203           startTag = strstr(temp, "</item");
1204         if (startTag)
1205           endTag = strstr(startTag, ">");
1206         else
1207           break;
1208         if (!endTag || startTag > endTag)
1209           break;
1210
1211         size_t sindex = startTag - temp;
1212         size_t eindex = endTag - temp + 1;
1213         if (!eina_strbuf_remove(buf, sindex, eindex))
1214           break;
1215      }
1216    ret = eina_strbuf_string_steal(buf);
1217    eina_strbuf_free(buf);
1218    return ret;
1219 }
1220
1221 void
1222 _elm_entry_entry_paste(Evas_Object *obj, const char *entry)
1223 {
1224    Widget_Data *wd = elm_widget_data_get(obj);
1225    char *str = NULL;
1226
1227    if (wd->cnp_mode == ELM_CNP_MODE_NO_IMAGE)
1228      {
1229         str = _remove_item_tags(entry);
1230         if (!str) str = strdup(entry);
1231      }
1232    else
1233      str = strdup(entry);
1234    if (!str) str = (char *)entry;
1235
1236    edje_object_part_text_user_insert(wd->ent, "elm.text", str);
1237    if (str != entry) free(str);
1238 }
1239
1240 static void
1241 _paste(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1242 {
1243    Widget_Data *wd = elm_widget_data_get(data);
1244    if (!wd) return;
1245    evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
1246    if (wd->sel_notify_handler)
1247      {
1248 #ifdef HAVE_ELEMENTARY_X
1249         Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP;
1250         wd->selection_asked = EINA_TRUE;
1251         if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
1252           formats = ELM_SEL_FORMAT_TEXT;
1253         else if (wd->cnp_mode != ELM_CNP_MODE_NO_IMAGE)
1254           formats |= ELM_SEL_FORMAT_IMAGE;
1255         elm_cnp_selection_get(data, ELM_SEL_TYPE_CLIPBOARD, formats, NULL, NULL);
1256 #endif
1257      }
1258 }
1259
1260 static void
1261 _store_selection(Elm_Sel_Type seltype, Evas_Object *obj)
1262 {
1263    Widget_Data *wd = elm_widget_data_get(obj);
1264    const char *sel;
1265
1266    if (!wd) return;
1267    sel = edje_object_part_text_selection_get(wd->ent, "elm.text");
1268    if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
1269    elm_cnp_selection_set(obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel));
1270    if (seltype == ELM_SEL_TYPE_CLIPBOARD)
1271      eina_stringshare_replace(&wd->cut_sel, sel);
1272 }
1273
1274 static void
1275 _cut(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1276 {
1277    Widget_Data *wd = elm_widget_data_get(data);
1278
1279    /* Store it */
1280    wd->selmode = EINA_FALSE;
1281    if (!_elm_config->desktop_entry)
1282      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1283    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1284    if (!_elm_config->desktop_entry)
1285      elm_widget_scroll_hold_pop(data);
1286    _store_selection(ELM_SEL_TYPE_CLIPBOARD, data);
1287    edje_object_part_text_user_insert(wd->ent, "elm.text", "");
1288    _sizing_eval(data);
1289 }
1290
1291 static void
1292 _copy(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1293 {
1294    Widget_Data *wd = elm_widget_data_get(data);
1295    if (!wd) return;
1296    wd->selmode = EINA_FALSE;
1297    if (!_elm_config->desktop_entry)
1298      {
1299         edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1300         edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1301         elm_widget_scroll_hold_pop(data);
1302      }
1303    _store_selection(ELM_SEL_TYPE_CLIPBOARD, data);
1304    //   edje_object_part_text_select_none(wd->ent, "elm.text");
1305 }
1306
1307 static void
1308 _cancel(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1309 {
1310    Widget_Data *wd = elm_widget_data_get(data);
1311    if (!wd) return;
1312    wd->selmode = EINA_FALSE;
1313    if (!_elm_config->desktop_entry)
1314      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1315    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1316    if (!_elm_config->desktop_entry)
1317      elm_widget_scroll_hold_pop(data);
1318    edje_object_part_text_select_none(wd->ent, "elm.text");
1319 }
1320
1321 static void
1322 _item_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1323 {
1324    Elm_Entry_Context_Menu_Item *it = data;
1325    Evas_Object *obj2 = it->obj;
1326    if (it->func) it->func(it->data, obj2, NULL);
1327 }
1328
1329 static void
1330 _menu_press(Evas_Object *obj)
1331 {
1332    Widget_Data *wd = elm_widget_data_get(obj);
1333    Evas_Object *top;
1334    const Eina_List *l;
1335    const Elm_Entry_Context_Menu_Item *it;
1336    if (!wd) return;
1337    if ((wd->api) && (wd->api->obj_longpress))
1338      {
1339         wd->api->obj_longpress(obj);
1340      }
1341    else if (wd->context_menu)
1342      {
1343         const char *context_menu_orientation;
1344
1345         if (wd->hoversel) evas_object_del(wd->hoversel);
1346         else elm_widget_scroll_freeze_push(obj);
1347         wd->hoversel = elm_hoversel_add(obj);
1348         context_menu_orientation = edje_object_data_get
1349            (wd->ent, "context_menu_orientation");
1350         if ((context_menu_orientation) &&
1351             (!strcmp(context_menu_orientation, "horizontal")))
1352           elm_hoversel_horizontal_set(wd->hoversel, EINA_TRUE);
1353         elm_object_style_set(wd->hoversel, "entry");
1354         elm_widget_sub_object_add(obj, wd->hoversel);
1355         elm_object_text_set(wd->hoversel, "Text");
1356         top = elm_widget_top_get(obj);
1357         if (top) elm_hoversel_hover_parent_set(wd->hoversel, top);
1358         evas_object_smart_callback_add(wd->hoversel, "dismissed", _dismissed, obj);
1359         if (wd->have_selection)
1360           {
1361              if (!wd->password)
1362                {
1363                   if (wd->have_selection)
1364                     {
1365                        elm_hoversel_item_add(wd->hoversel, E_("Copy"), NULL, ELM_ICON_NONE,
1366                                              _copy, obj);
1367                        if (wd->editable)
1368                          elm_hoversel_item_add(wd->hoversel, E_("Cut"), NULL, ELM_ICON_NONE,
1369                                                _cut, obj);
1370                     }
1371                   elm_hoversel_item_add(wd->hoversel, E_("Cancel"), NULL, ELM_ICON_NONE,
1372                                         _cancel, obj);
1373                }
1374           }
1375         else
1376           {
1377              if (!wd->selmode)
1378                {
1379                   if (!_elm_config->desktop_entry)
1380                     {
1381                        if (!wd->password)
1382                          elm_hoversel_item_add(wd->hoversel, E_("Select"), NULL, ELM_ICON_NONE,
1383                                                _select, obj);
1384                     }
1385                   if (elm_selection_selection_has_owner())
1386                     {
1387                        if (wd->editable)
1388                          elm_hoversel_item_add(wd->hoversel, E_("Paste"), NULL, ELM_ICON_NONE,
1389                                                _paste, obj);
1390                     }
1391                }
1392           }
1393         EINA_LIST_FOREACH(wd->items, l, it)
1394           {
1395              elm_hoversel_item_add(wd->hoversel, it->label, it->icon_file,
1396                                    it->icon_type, _item_clicked, it);
1397           }
1398         if (wd->hoversel)
1399           {
1400              _hoversel_position(obj);
1401              evas_object_show(wd->hoversel);
1402              elm_hoversel_hover_begin(wd->hoversel);
1403           }
1404         if (!_elm_config->desktop_entry)
1405           {
1406              edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1407              edje_object_part_text_select_abort(wd->ent, "elm.text");
1408           }
1409      }
1410 }
1411
1412 static Eina_Bool
1413 _long_press(void *data)
1414 {
1415    Widget_Data *wd = elm_widget_data_get(data);
1416    if (!wd) return ECORE_CALLBACK_CANCEL;
1417    if (!_elm_config->desktop_entry)
1418      _menu_press(data);
1419    wd->longpress_timer = NULL;
1420    evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
1421    return ECORE_CALLBACK_CANCEL;
1422 }
1423
1424 static void
1425 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1426 {
1427    Widget_Data *wd = elm_widget_data_get(data);
1428    Evas_Event_Mouse_Down *ev = event_info;
1429    if (!wd) return;
1430    if (wd->disabled) return;
1431    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1432    wd->downx = ev->canvas.x;
1433    wd->downy = ev->canvas.y;
1434    if (ev->button == 1)
1435      {
1436         if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
1437         wd->longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
1438      }
1439 }
1440
1441 static void
1442 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1443 {
1444    Widget_Data *wd = elm_widget_data_get(data);
1445    Evas_Event_Mouse_Up *ev = event_info;
1446    if (!wd) return;
1447    if (wd->disabled) return;
1448    if (ev->button == 1)
1449      {
1450         if (wd->longpress_timer)
1451           {
1452              ecore_timer_del(wd->longpress_timer);
1453              wd->longpress_timer = NULL;
1454           }
1455      }
1456    else if ((ev->button == 3) && (!_elm_config->desktop_entry))
1457      {
1458         wd->usedown = 1;
1459         _menu_press(data);
1460      }
1461 }
1462
1463 static void
1464 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1465 {
1466    Widget_Data *wd = elm_widget_data_get(data);
1467    Evas_Event_Mouse_Move *ev = event_info;
1468    if (!wd) return;
1469    if (wd->disabled) return;
1470    if (!wd->selmode)
1471      {
1472         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1473           {
1474              if (wd->longpress_timer)
1475                {
1476                   ecore_timer_del(wd->longpress_timer);
1477                   wd->longpress_timer = NULL;
1478                }
1479           }
1480         else if (wd->longpress_timer)
1481           {
1482              Evas_Coord dx, dy;
1483
1484              dx = wd->downx - ev->cur.canvas.x;
1485              dx *= dx;
1486              dy = wd->downy - ev->cur.canvas.y;
1487              dy *= dy;
1488              if ((dx + dy) >
1489                  ((_elm_config->finger_size / 2) *
1490                   (_elm_config->finger_size / 2)))
1491                {
1492                   ecore_timer_del(wd->longpress_timer);
1493                   wd->longpress_timer = NULL;
1494                }
1495           }
1496      }
1497    else if (wd->longpress_timer)
1498      {
1499         Evas_Coord dx, dy;
1500
1501         dx = wd->downx - ev->cur.canvas.x;
1502         dx *= dx;
1503         dy = wd->downy - ev->cur.canvas.y;
1504         dy *= dy;
1505         if ((dx + dy) >
1506             ((_elm_config->finger_size / 2) *
1507              (_elm_config->finger_size / 2)))
1508           {
1509              ecore_timer_del(wd->longpress_timer);
1510              wd->longpress_timer = NULL;
1511           }
1512      }
1513 }
1514
1515 static const char *
1516 _getbase(Evas_Object *obj)
1517 {
1518    Widget_Data *wd = elm_widget_data_get(obj);
1519    if (!wd) return "base";
1520    if (wd->editable)
1521      {
1522         if (wd->password) return "base-password";
1523         else
1524           {
1525              if (wd->single_line) return "base-single";
1526              else
1527                {
1528                   switch (wd->linewrap)
1529                     {
1530                      case ELM_WRAP_CHAR:
1531                         return "base-charwrap";
1532                      case ELM_WRAP_WORD:
1533                         return "base";
1534                      case ELM_WRAP_MIXED:
1535                         return "base-mixedwrap";
1536                      case ELM_WRAP_NONE:
1537                      default:
1538                         return "base-nowrap";
1539                     }
1540                }
1541           }
1542      }
1543    else
1544      {
1545         if (wd->password) return "base-password";
1546         else
1547           {
1548              if (wd->single_line) return "base-single-noedit";
1549              else
1550                {
1551                   switch (wd->linewrap)
1552                     {
1553                      case ELM_WRAP_CHAR:
1554                         return "base-noedit-charwrap";
1555                      case ELM_WRAP_WORD:
1556                         return "base-noedit";
1557                      case ELM_WRAP_MIXED:
1558                         return "base-noedit-mixedwrap";
1559                      case ELM_WRAP_NONE:
1560                      default:
1561                         return "base-nowrap-noedit";
1562                     }
1563                }
1564           }
1565      }
1566 }
1567
1568 static void
1569 _entry_changed_common_handling(void *data, const char *event)
1570 {
1571    Widget_Data *wd = elm_widget_data_get(data);
1572    Evas_Coord minh;
1573    const char *text;
1574    if (!wd) return;
1575    evas_event_freeze(evas_object_evas_get(data));
1576    wd->changed = EINA_TRUE;
1577    /* Reset the size hints which are no more relevant.
1578     * Keep the height, this is a hack, but doesn't really matter
1579     * cause we'll re-eval in a moment. */
1580    evas_object_size_hint_min_get(data, NULL, &minh);
1581    evas_object_size_hint_min_set(data, -1, minh);
1582    _sizing_eval(data);
1583    if (wd->text) eina_stringshare_del(wd->text);
1584    wd->text = NULL;
1585    if (wd->delay_write)
1586      {
1587         ecore_timer_del(wd->delay_write);
1588         wd->delay_write = NULL;
1589      }
1590    evas_event_thaw(evas_object_evas_get(data));
1591    evas_event_thaw_eval(evas_object_evas_get(data));
1592    if ((wd->autosave) && (wd->file))
1593      wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
1594    /* callback - this could call callbacks that delete the entry... thus...
1595     * any access to wd after this could be invalid */
1596    evas_object_smart_callback_call(data, event, NULL);
1597    _check_enable_return_key(data);
1598    text = edje_object_part_text_get(wd->ent, "elm.text");
1599    if (text)
1600      {
1601         if (text[0])
1602           _elm_entry_update_guide(data, EINA_TRUE);
1603         else
1604           _elm_entry_update_guide(data, EINA_FALSE);
1605      }
1606 }
1607
1608 static void
1609 _signal_entry_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1610 {
1611    _entry_changed_common_handling(data, SIG_CHANGED);
1612 }
1613
1614 static void
1615 _signal_entry_changed_user(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1616 {
1617    Elm_Entry_Change_Info info;
1618    Edje_Entry_Change_Info *edje_info = (Edje_Entry_Change_Info *)
1619       edje_object_signal_callback_extra_data_get();
1620    if (edje_info)
1621      {
1622         memcpy(&info, edje_info, sizeof(info));
1623         evas_object_smart_callback_call(data, SIG_CHANGED_USER, &info);
1624      }
1625    else
1626      {
1627         evas_object_smart_callback_call(data, SIG_CHANGED_USER, NULL);
1628      }
1629 }
1630
1631 static void
1632 _signal_preedit_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1633 {
1634    _entry_changed_common_handling(data, SIG_PREEDIT_CHANGED);
1635 }
1636
1637 static void
1638 _signal_undo_request(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1639 {
1640    evas_object_smart_callback_call(data, SIG_UNDO_REQUEST, NULL);
1641 }
1642
1643 static void
1644 _signal_redo_request(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1645 {
1646    evas_object_smart_callback_call(data, SIG_REDO_REQUEST, NULL);
1647 }
1648
1649 static void
1650 _signal_selection_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1651 {
1652    Widget_Data *wd = elm_widget_data_get(data);
1653    const Eina_List *l;
1654    Evas_Object *entry;
1655    if (!wd) return;
1656    EINA_LIST_FOREACH(entries, l, entry)
1657      {
1658         if (entry != data) elm_entry_select_none(entry);
1659      }
1660    wd->have_selection = EINA_TRUE;
1661    evas_object_smart_callback_call(data, SIG_SELECTION_START, NULL);
1662 #ifdef HAVE_ELEMENTARY_X
1663    if (wd->sel_notify_handler)
1664      {
1665         const char *txt = elm_entry_selection_get(data);
1666         Evas_Object *top;
1667
1668         top = elm_widget_top_get(data);
1669         if (txt && top && (elm_win_xwindow_get(top)))
1670           elm_cnp_selection_set(data, ELM_SEL_TYPE_PRIMARY,
1671                                 ELM_SEL_FORMAT_MARKUP, txt, strlen(txt));
1672      }
1673 #endif
1674 }
1675
1676 static void
1677 _signal_selection_all(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1678 {
1679    Widget_Data *wd = elm_widget_data_get(data);
1680    if (!wd) return;
1681    elm_entry_select_all(data);
1682 }
1683
1684 static void
1685 _signal_selection_none(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1686 {
1687    Widget_Data *wd = elm_widget_data_get(data);
1688    if (!wd) return;
1689    elm_entry_select_none(data);
1690 }
1691
1692 static void
1693 _signal_selection_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1694 {
1695    Widget_Data *wd = elm_widget_data_get(data);
1696    if (!wd) return;
1697    wd->have_selection = EINA_TRUE;
1698    evas_object_smart_callback_call(data, SIG_SELECTION_CHANGED, NULL);
1699    _store_selection(ELM_SEL_TYPE_PRIMARY, data);
1700 }
1701
1702 static void
1703 _signal_selection_cleared(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1704 {
1705    Widget_Data *wd = elm_widget_data_get(data);
1706    if (!wd) return;
1707    if (!wd->have_selection) return;
1708    wd->have_selection = EINA_FALSE;
1709    evas_object_smart_callback_call(data, SIG_SELECTION_CLEARED, NULL);
1710    if (wd->sel_notify_handler)
1711      {
1712         if (wd->cut_sel)
1713           {
1714 #ifdef HAVE_ELEMENTARY_X
1715              Evas_Object *top;
1716
1717              top = elm_widget_top_get(data);
1718              if ((top) && (elm_win_xwindow_get(top)))
1719                elm_cnp_selection_set(data, ELM_SEL_TYPE_PRIMARY,
1720                                      ELM_SEL_FORMAT_MARKUP, wd->cut_sel,
1721                                      strlen(wd->cut_sel));
1722 #endif
1723              eina_stringshare_del(wd->cut_sel);
1724              wd->cut_sel = NULL;
1725           }
1726         else
1727           {
1728 #ifdef HAVE_ELEMENTARY_X
1729              Evas_Object *top;
1730
1731              top = elm_widget_top_get(data);
1732              if ((top) && (elm_win_xwindow_get(top)))
1733                elm_object_cnp_selection_clear(data, ELM_SEL_TYPE_PRIMARY);
1734 #endif
1735           }
1736      }
1737 }
1738
1739 static void
1740 _signal_entry_paste_request(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
1741 {
1742    Widget_Data *wd = elm_widget_data_get(data);
1743 #ifdef HAVE_ELEMENTARY_X
1744    Elm_Sel_Type type = (emission[sizeof("ntry,paste,request,")] == '1') ?
1745      ELM_SEL_TYPE_PRIMARY : ELM_SEL_TYPE_CLIPBOARD;
1746 #endif
1747
1748    if (!wd) return;
1749    if (!wd->editable) return;
1750    evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
1751    if (wd->sel_notify_handler)
1752      {
1753 #ifdef HAVE_ELEMENTARY_X
1754         Evas_Object *top;
1755
1756         top = elm_widget_top_get(data);
1757         if ((top) && (elm_win_xwindow_get(top)))
1758           {
1759              wd->selection_asked = EINA_TRUE;
1760              Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP;
1761              if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
1762                formats = ELM_SEL_FORMAT_TEXT;
1763              else if (wd->cnp_mode != ELM_CNP_MODE_NO_IMAGE)
1764                formats |= ELM_SEL_FORMAT_IMAGE;
1765              elm_cnp_selection_get(data, type, formats,
1766                                    NULL, NULL);
1767           }
1768 #endif
1769      }
1770 }
1771
1772 static void
1773 _signal_entry_copy_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1774 {
1775    evas_object_smart_callback_call(data, SIG_SELECTION_COPY, NULL);
1776    _copy(data, NULL, NULL);
1777 }
1778
1779 static void
1780 _signal_entry_cut_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1781 {
1782    evas_object_smart_callback_call(data, SIG_SELECTION_CUT, NULL);
1783    _cut(data, NULL, NULL);
1784 }
1785
1786 static void
1787 _signal_cursor_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1788 {
1789    Widget_Data *wd = elm_widget_data_get(data);
1790    if (!wd) return;
1791    wd->cursor_pos = edje_object_part_text_cursor_pos_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
1792    wd->cur_changed = EINA_TRUE;
1793    _recalc_cursor_geometry(data);
1794 }
1795
1796 static void
1797 _signal_cursor_changed_manual(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1798 {
1799    evas_object_smart_callback_call(data, SIG_CURSOR_CHANGED_MANUAL, NULL);
1800 }
1801
1802
1803 static void
1804 _signal_anchor_geoms_do_things_with(Widget_Data *wd, Elm_Entry_Anchor_Info *ei)
1805 {
1806    const Eina_List *geoms, *l;
1807    Evas_Textblock_Rectangle *r;
1808    Evas_Coord px, py, x, y;
1809
1810    geoms = edje_object_part_text_anchor_geometry_get(wd->ent, "elm.text", ei->name);
1811    if (!geoms) return;
1812
1813
1814    evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
1815    evas_pointer_canvas_xy_get(evas_object_evas_get(wd->ent), &px, &py);
1816    EINA_LIST_FOREACH(geoms, l, r)
1817      {
1818         if (((r->x + x) <= px) && ((r->y + y) <= py) &&
1819             ((r->x + x + r->w) > px) && ((r->y + y + r->h) > py))
1820           {
1821              ei->x = r->x + x;
1822              ei->y = r->y + y;
1823              ei->w = r->w;
1824              ei->h = r->h;
1825              break;
1826           }
1827      }
1828 }
1829
1830 static void
1831 _signal_anchor_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1832 {
1833    Widget_Data *wd = elm_widget_data_get(data);
1834    Elm_Entry_Anchor_Info ei;
1835    const char *p;
1836    char *p2;
1837    if (!wd) return;
1838    p = emission + sizeof("nchor,mouse,down,");
1839    ei.button = strtol(p, &p2, 10);
1840    ei.name = p2 + 1;
1841    ei.x = ei.y = ei.w = ei.h = 0;
1842
1843    _signal_anchor_geoms_do_things_with(wd, &ei);
1844
1845    if (!wd->disabled)
1846      evas_object_smart_callback_call(data, SIG_ANCHOR_DOWN, &ei);
1847 }
1848
1849 static void
1850 _signal_anchor_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1851 {
1852    Widget_Data *wd = elm_widget_data_get(data);
1853    Elm_Entry_Anchor_Info ei;
1854    const char *p;
1855    char *p2;
1856    if (!wd) return;
1857    p = emission + sizeof("nchor,mouse,up,");
1858    ei.button = strtol(p, &p2, 10);
1859    ei.name = p2 + 1;
1860    ei.x = ei.y = ei.w = ei.h = 0;
1861
1862    _signal_anchor_geoms_do_things_with(wd, &ei);
1863
1864    if (!wd->disabled)
1865      evas_object_smart_callback_call(data, SIG_ANCHOR_UP, &ei);
1866 }
1867
1868 static void
1869 _signal_anchor_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
1870 {
1871    Widget_Data *wd = elm_widget_data_get(data);
1872    Elm_Entry_Anchor_Info ei;
1873    const char *p;
1874    char *p2;
1875    if (!wd) return;
1876    p = emission + sizeof("nchor,mouse,clicked,");
1877    ei.button = strtol(p, &p2, 10);
1878    ei.name = p2 + 1;
1879    ei.x = ei.y = ei.w = ei.h = 0;
1880
1881    _signal_anchor_geoms_do_things_with(wd, &ei);
1882
1883    if (!wd->disabled)
1884      {
1885         evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
1886
1887         if (!_elm_config->desktop_entry)
1888           _entry_hover_anchor_clicked(data, data, &ei);
1889      }
1890 }
1891
1892 static void
1893 _signal_anchor_move(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1894 {
1895    Widget_Data *wd = elm_widget_data_get(data);
1896    if (!wd) return;
1897 }
1898
1899 static void
1900 _signal_anchor_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1901 {
1902    Widget_Data *wd = elm_widget_data_get(data);
1903    Elm_Entry_Anchor_Info ei;
1904    if (!wd) return;
1905    ei.name = emission + sizeof("nchor,mouse,in,");
1906    ei.button = 0;
1907    ei.x = ei.y = ei.w = ei.h = 0;
1908
1909    _signal_anchor_geoms_do_things_with(wd, &ei);
1910
1911    if (!wd->disabled)
1912      evas_object_smart_callback_call(data, SIG_ANCHOR_IN, &ei);
1913 }
1914
1915 static void
1916 _signal_anchor_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1917 {
1918    Widget_Data *wd = elm_widget_data_get(data);
1919    Elm_Entry_Anchor_Info ei;
1920    if (!wd) return;
1921    ei.name = emission + sizeof("nchor,mouse,out,");
1922    ei.button = 0;
1923    ei.x = ei.y = ei.w = ei.h = 0;
1924
1925    _signal_anchor_geoms_do_things_with(wd, &ei);
1926
1927    if (!wd->disabled)
1928      evas_object_smart_callback_call(data, SIG_ANCHOR_OUT, &ei);
1929 }
1930
1931 static void
1932 _signal_key_enter(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1933 {
1934    Widget_Data *wd = elm_widget_data_get(data);
1935    if (!wd) return;
1936    evas_object_smart_callback_call(data, SIG_ACTIVATED, NULL);
1937 }
1938
1939 static void
1940 _signal_mouse_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1941 {
1942    Widget_Data *wd = elm_widget_data_get(data);
1943    if (!wd) return;
1944    evas_object_smart_callback_call(data, SIG_PRESS, NULL);
1945 }
1946
1947 static void
1948 _signal_mouse_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1949 {
1950    Widget_Data *wd = elm_widget_data_get(data);
1951    if (!wd) return;
1952    evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
1953 }
1954
1955 static void
1956 _signal_mouse_double(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1957 {
1958    Widget_Data *wd = elm_widget_data_get(data);
1959    if (!wd) return;
1960    evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
1961 }
1962
1963 static void
1964 _signal_mouse_triple(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1965 {
1966    Widget_Data *wd = elm_widget_data_get(data);
1967    if (!wd) return;
1968    evas_object_smart_callback_call(data, SIG_CLICKED_TRIPLE, NULL);
1969 }
1970
1971 #ifdef HAVE_ELEMENTARY_X
1972 static Eina_Bool
1973 _event_selection_notify(void *data, int type __UNUSED__, void *event)
1974 {
1975    Widget_Data *wd = elm_widget_data_get(data);
1976    Ecore_X_Event_Selection_Notify *ev = event;
1977    if (!wd) return ECORE_CALLBACK_PASS_ON;
1978    if ((!wd->selection_asked) && (!wd->drag_selection_asked))
1979      return ECORE_CALLBACK_PASS_ON;
1980
1981    if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
1982        (ev->selection == ECORE_X_SELECTION_PRIMARY))
1983      {
1984         Ecore_X_Selection_Data_Text *text_data;
1985
1986         text_data = ev->data;
1987         if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
1988           {
1989              if (text_data->text)
1990                {
1991                   char *txt = _elm_util_text_to_mkup(text_data->text);
1992
1993                   if (txt)
1994                     {
1995                        elm_entry_entry_insert(data, txt);
1996                        free(txt);
1997                     }
1998                }
1999           }
2000         wd->selection_asked = EINA_FALSE;
2001      }
2002    else if (ev->selection == ECORE_X_SELECTION_XDND)
2003      {
2004         Ecore_X_Selection_Data_Text *text_data;
2005
2006         text_data = ev->data;
2007         if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
2008           {
2009              if (text_data->text)
2010                {
2011                   char *txt = _elm_util_text_to_mkup(text_data->text);
2012
2013                   if (txt)
2014                     {
2015                        /* Massive FIXME: this should be at the drag point */
2016                        elm_entry_entry_insert(data, txt);
2017                        free(txt);
2018                     }
2019                }
2020           }
2021         wd->drag_selection_asked = EINA_FALSE;
2022
2023         ecore_x_dnd_send_finished();
2024
2025      }
2026    return ECORE_CALLBACK_PASS_ON;
2027 }
2028
2029 static Eina_Bool
2030 _event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
2031 {
2032    Widget_Data *wd = elm_widget_data_get(data);
2033    Ecore_X_Event_Selection_Clear *ev = event;
2034    if (!wd) return ECORE_CALLBACK_PASS_ON;
2035    if (!wd->have_selection) return ECORE_CALLBACK_PASS_ON;
2036    if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
2037        (ev->selection == ECORE_X_SELECTION_PRIMARY))
2038      {
2039         elm_entry_select_none(data);
2040      }
2041    return ECORE_CALLBACK_PASS_ON;
2042 }
2043
2044 static Eina_Bool
2045 _drag_drop_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Selection_Data *drop)
2046 {
2047    Widget_Data *wd;
2048    Eina_Bool rv;
2049
2050    wd = elm_widget_data_get(obj);
2051    if (!wd) return EINA_FALSE;
2052    printf("Inserting at (%d,%d) %s\n",drop->x,drop->y,(char*)drop->data);
2053
2054    edje_object_part_text_cursor_copy(wd->ent, "elm.text",
2055                                      EDJE_CURSOR_MAIN,/*->*/EDJE_CURSOR_USER);
2056    rv = edje_object_part_text_cursor_coord_set(wd->ent,"elm.text",
2057                                                EDJE_CURSOR_MAIN,drop->x,drop->y);
2058    if (!rv) printf("Warning: Failed to position cursor: paste anyway\n");
2059    elm_entry_entry_insert(obj, drop->data);
2060    edje_object_part_text_cursor_copy(wd->ent, "elm.text",
2061                                      EDJE_CURSOR_USER,/*->*/EDJE_CURSOR_MAIN);
2062
2063    return EINA_TRUE;
2064 }
2065 #endif
2066
2067 static Evas_Object *
2068 _get_item(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, const char *item)
2069 {
2070    Widget_Data *wd = elm_widget_data_get(data);
2071    Evas_Object *o;
2072    Eina_List *l;
2073    Elm_Entry_Item_Provider *ip;
2074
2075    EINA_LIST_FOREACH(wd->item_providers, l, ip)
2076      {
2077         o = ip->func(ip->data, data, item);
2078         if (o) return o;
2079      }
2080    if (!strncmp(item, "file://", 7))
2081      {
2082         const char *fname = item + 7;
2083
2084         o = evas_object_image_filled_add(evas_object_evas_get(data));
2085         evas_object_image_file_set(o, fname, NULL);
2086         if (evas_object_image_load_error_get(o) == EVAS_LOAD_ERROR_NONE)
2087           {
2088              evas_object_show(o);
2089           }
2090         else
2091           {
2092              evas_object_del(o);
2093              o = edje_object_add(evas_object_evas_get(data));
2094              _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
2095           }
2096         return o;
2097      }
2098    o = edje_object_add(evas_object_evas_get(data));
2099    if (!_elm_theme_object_set(data, o, "entry", item, elm_widget_style_get(data)))
2100      _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
2101    return o;
2102 }
2103
2104 static void
2105 _text_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, Edje_Text_Filter_Type type, char **text)
2106 {
2107    Widget_Data *wd = elm_widget_data_get(data);
2108    Eina_List *l;
2109    Elm_Entry_Markup_Filter *tf;
2110
2111    if (type == EDJE_TEXT_FILTER_FORMAT)
2112      return;
2113
2114    EINA_LIST_FOREACH(wd->text_filters, l, tf)
2115      {
2116         tf->func(tf->data, data, text);
2117         if (!*text)
2118           break;
2119      }
2120 }
2121
2122 static void
2123 _markup_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, char **text)
2124 {
2125    Widget_Data *wd = elm_widget_data_get(data);
2126    Eina_List *l;
2127    Elm_Entry_Markup_Filter *tf;
2128
2129    EINA_LIST_FOREACH(wd->markup_filters, l, tf)
2130      {
2131         tf->func(tf->data, data, text);
2132         if (!*text)
2133           break;
2134      }
2135 }
2136
2137 /* This function is used to insert text by chunks in jobs */
2138 static Eina_Bool
2139 _text_append_idler(void *data)
2140 {
2141    int start;
2142    char backup;
2143    Evas_Object *obj = (Evas_Object *) data;
2144    Widget_Data *wd = elm_widget_data_get(obj);
2145    evas_event_freeze(evas_object_evas_get(obj));
2146    if (wd->text) eina_stringshare_del(wd->text);
2147    wd->text = NULL;
2148    wd->changed = EINA_TRUE;
2149
2150    start = wd->append_text_position;
2151    if (start + _CHUNK_SIZE < wd->append_text_len)
2152      {
2153         int pos = start;
2154         int tag_start, esc_start;
2155
2156         tag_start = esc_start = -1;
2157         /* Find proper markup cut place */
2158         while (pos - start < _CHUNK_SIZE)
2159           {
2160              int prev_pos = pos;
2161              Eina_Unicode tmp =
2162                 eina_unicode_utf8_get_next(wd->append_text_left, &pos);
2163              if (esc_start == -1)
2164                {
2165                   if (tmp == '<')
2166                      tag_start = prev_pos;
2167                   else if (tmp == '>')
2168                      tag_start = -1;
2169                }
2170              if (tag_start == -1)
2171                {
2172                   if (tmp == '&')
2173                      esc_start = prev_pos;
2174                   else if (tmp == ';')
2175                      esc_start = -1;
2176                }
2177           }
2178
2179         if (tag_start >= 0)
2180           {
2181              wd->append_text_position = tag_start;
2182           }
2183         else if (esc_start >= 0)
2184           {
2185              wd->append_text_position = esc_start;
2186           }
2187         else
2188           {
2189              wd->append_text_position = pos;
2190           }
2191      }
2192    else
2193      {
2194         wd->append_text_position = wd->append_text_len;
2195      }
2196
2197    backup = wd->append_text_left[wd->append_text_position];
2198    wd->append_text_left[wd->append_text_position] = '\0';
2199
2200    edje_object_part_text_append(wd->ent, "elm.text",
2201                                 wd->append_text_left + start);
2202
2203    wd->append_text_left[wd->append_text_position] = backup;
2204
2205    evas_event_thaw(evas_object_evas_get(obj));
2206    evas_event_thaw_eval(evas_object_evas_get(obj));
2207
2208    _elm_entry_update_guide(obj, EINA_TRUE);
2209    
2210    /* If there's still more to go, renew the idler, else, cleanup */
2211    if (wd->append_text_position < wd->append_text_len)
2212      {
2213         return ECORE_CALLBACK_RENEW;
2214      }
2215    else
2216      {
2217         free(wd->append_text_left);
2218         wd->append_text_left = NULL;
2219         wd->append_text_idler = NULL;
2220         return ECORE_CALLBACK_CANCEL;
2221      }
2222 }
2223
2224 static void
2225 _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit unit)
2226 {
2227    int i = 0, current_len = 0;
2228    char *new_text;
2229
2230    if (!*text) return;
2231    if (unit >= LENGTH_UNIT_LAST) return;
2232    new_text = *text;
2233    current_len = strlen(*text);
2234    while (*new_text)
2235      {
2236         int idx = 0, unit_size = 0;
2237         char *markup, *utfstr;
2238         if (*new_text == '<')
2239           {
2240              while (*(new_text + idx) != '>')
2241                {
2242                   idx++;
2243                   if (!*(new_text + idx)) break;
2244                }
2245           }
2246         else if (*new_text == '&')
2247           {
2248              while (*(new_text + idx) != ';')
2249                {
2250                   idx++;
2251                   if (!*(new_text + idx)) break;
2252                }
2253           }
2254         idx = evas_string_char_next_get(new_text, idx, NULL);
2255         markup = malloc(idx + 1);
2256         if (markup)
2257           {
2258              strncpy(markup, new_text, idx);
2259              markup[idx] = 0;
2260              utfstr = elm_entry_markup_to_utf8(markup);
2261              if (utfstr)
2262                {
2263                   if (unit == LENGTH_UNIT_BYTE)
2264                     unit_size = strlen(utfstr);
2265                   else if (unit == LENGTH_UNIT_CHAR)
2266                     unit_size = evas_string_char_len_get(utfstr);
2267                   free(utfstr);
2268                   utfstr = NULL;
2269                }
2270              free(markup);
2271              markup = NULL;
2272           }
2273         if (can_add < unit_size)
2274           {
2275              if (!i)
2276                {
2277                   evas_object_smart_callback_call(obj, "maxlength,reached", NULL);
2278                   free(*text);
2279                   *text = NULL;
2280                   return;
2281                }
2282              can_add = 0;
2283              strncpy(new_text, new_text + idx, current_len - ((new_text + idx) - *text));
2284              current_len -= idx;
2285              (*text)[current_len] = 0;
2286           }
2287         else
2288           {
2289              new_text += idx;
2290              can_add -= unit_size;
2291           }
2292         i++;
2293      }
2294    evas_object_smart_callback_call(obj, "maxlength,reached", NULL);
2295 }
2296
2297 static void
2298 _elm_entry_text_set(Evas_Object *obj, const char *item, const char *entry)
2299 {
2300    int len = 0;
2301    ELM_CHECK_WIDTYPE(obj, widtype);
2302    Widget_Data *wd = elm_widget_data_get(obj);
2303    if (!wd) return;
2304    evas_event_freeze(evas_object_evas_get(obj));
2305    if (!entry) entry = "";
2306    if (item)
2307      {
2308         if (!strcmp(item, "guide"))
2309           edje_object_part_text_set(wd->ent, "elm.guide", entry);
2310         else
2311           edje_object_part_text_set(wd->ent, item, entry);
2312         evas_event_thaw(evas_object_evas_get(obj));
2313         evas_event_thaw_eval(evas_object_evas_get(obj));
2314         return;
2315      }
2316
2317    if (wd->text) eina_stringshare_del(wd->text);
2318    wd->text = NULL;
2319    wd->changed = EINA_TRUE;
2320
2321    /* Clear currently pending job if there is one */
2322    if (wd->append_text_idler)
2323      {
2324         ecore_idler_del(wd->append_text_idler);
2325         free(wd->append_text_left);
2326         wd->append_text_left = NULL;
2327         wd->append_text_idler = NULL;
2328      }
2329
2330    len = strlen(entry);
2331    /* Split to ~_CHUNK_SIZE chunks */
2332    if (len > _CHUNK_SIZE)
2333      {
2334         wd->append_text_left = (char *) malloc(len + 1);
2335      }
2336
2337    /* If we decided to use the idler */
2338    if (wd->append_text_left)
2339      {
2340         /* Need to clear the entry first */
2341         edje_object_part_text_set(wd->ent, "elm.text", "");
2342         memcpy(wd->append_text_left, entry, len + 1);
2343         wd->append_text_position = 0;
2344         wd->append_text_len = len;
2345         wd->append_text_idler = ecore_idler_add(_text_append_idler, obj);
2346      }
2347    else
2348      {
2349         edje_object_part_text_set(wd->ent, "elm.text", entry);
2350      }
2351    if ((entry) && (entry[0]))
2352      _elm_entry_update_guide(obj, EINA_TRUE);
2353    else
2354      _elm_entry_update_guide(obj, EINA_FALSE);
2355    evas_event_thaw(evas_object_evas_get(obj));
2356    evas_event_thaw_eval(evas_object_evas_get(obj));
2357 }
2358
2359 static const char *
2360 _elm_entry_text_get(const Evas_Object *obj, const char *item)
2361 {
2362    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2363    Widget_Data *wd = elm_widget_data_get(obj);
2364    if (item && strcmp(item, "default")) return NULL;
2365    const char *text;
2366    if (!wd) return NULL;
2367    text = edje_object_part_text_get(wd->ent, "elm.text");
2368    if (!text)
2369      {
2370         ERR("text=NULL for edje %p, part 'elm.text'", wd->ent);
2371         return NULL;
2372      }
2373
2374    if (wd->append_text_len > 0)
2375      {
2376         char *tmpbuf;
2377         size_t tlen;
2378         tlen = strlen(text);
2379         tmpbuf = malloc(tlen + wd->append_text_len + 1);
2380         if (!tmpbuf)
2381           {
2382              ERR("Failed to allocate memory for entry's text %p", obj);
2383              return NULL;
2384           }
2385         memcpy(tmpbuf, text, tlen);
2386         if (wd->append_text_left)
2387           memcpy(tmpbuf + tlen, wd->append_text_left, strlen(wd->append_text_left));
2388         tmpbuf[tlen + wd->append_text_len] = '\0';
2389         eina_stringshare_replace(&wd->text, tmpbuf);
2390         free(tmpbuf);
2391      }
2392    else
2393      {
2394         eina_stringshare_replace(&wd->text, text);
2395      }
2396    return wd->text;
2397 }
2398
2399 EAPI Evas_Object *
2400 elm_entry_add(Evas_Object *parent)
2401 {
2402 #ifdef HAVE_ELEMENTARY_X
2403    Evas_Object *top;
2404 #endif
2405    Evas_Object *obj;
2406    Evas *e;
2407    Widget_Data *wd;
2408
2409    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
2410
2411    ELM_SET_WIDTYPE(widtype, "entry");
2412    elm_widget_type_set(obj, "entry");
2413    elm_widget_sub_object_add(parent, obj);
2414    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
2415    elm_widget_data_set(obj, wd);
2416    elm_widget_del_hook_set(obj, _del_hook);
2417    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
2418    elm_widget_theme_hook_set(obj, _theme_hook);
2419    elm_widget_disable_hook_set(obj, _disable_hook);
2420    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
2421    elm_widget_focus_region_hook_set(obj, _focus_region_hook);
2422    elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
2423    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
2424    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
2425    elm_object_cursor_set(obj, ELM_CURSOR_XTERM);
2426    elm_widget_can_focus_set(obj, EINA_TRUE);
2427    elm_widget_text_set_hook_set(obj, _elm_entry_text_set);
2428    elm_widget_text_get_hook_set(obj, _elm_entry_text_get);
2429    elm_widget_content_set_hook_set(obj, _content_set_hook);
2430    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
2431    elm_widget_content_get_hook_set(obj, _content_get_hook);
2432    elm_widget_translate_hook_set(obj, _translate_hook);
2433
2434    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, wd);
2435
2436    wd->linewrap     = ELM_WRAP_WORD;
2437    wd->editable     = EINA_TRUE;
2438    wd->disabled     = EINA_FALSE;
2439    wd->context_menu = EINA_TRUE;
2440    wd->autosave     = EINA_TRUE;
2441    wd->cnp_mode     = ELM_CNP_MODE_MARKUP;
2442    wd->scroll       = EINA_FALSE;
2443    wd->input_panel_imdata = NULL;
2444
2445    wd->ent = edje_object_add(e);
2446    edje_object_item_provider_set(wd->ent, _get_item, obj);
2447    edje_object_text_insert_filter_callback_add(wd->ent,"elm.text", _text_filter, obj);
2448    edje_object_text_markup_filter_callback_add(wd->ent,"elm.text", _markup_filter, obj);
2449    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOVE, _move, obj);
2450    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_DOWN,
2451                                   _mouse_down, obj);
2452    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_UP,
2453                                   _mouse_up, obj);
2454    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_MOVE,
2455                                   _mouse_move, obj);
2456    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
2457
2458    _elm_theme_object_set(obj, wd->ent, "entry", "base", "default");
2459    edje_object_signal_callback_add(wd->ent, "entry,changed", "elm.text",
2460                                    _signal_entry_changed, obj);
2461    edje_object_signal_callback_add(wd->ent, "entry,changed,user", "elm.text",
2462                                    _signal_entry_changed_user, obj);
2463    edje_object_signal_callback_add(wd->ent, "preedit,changed", "elm.text",
2464                                    _signal_preedit_changed, obj);
2465    edje_object_signal_callback_add(wd->ent, "selection,start", "elm.text",
2466                                    _signal_selection_start, obj);
2467    edje_object_signal_callback_add(wd->ent, "selection,changed", "elm.text",
2468                                    _signal_selection_changed, obj);
2469    edje_object_signal_callback_add(wd->ent, "entry,selection,all,request", "elm.text",
2470                                    _signal_selection_all, obj);
2471    edje_object_signal_callback_add(wd->ent, "entry,selection,none,request", "elm.text",
2472                                    _signal_selection_none, obj);
2473    edje_object_signal_callback_add(wd->ent, "selection,cleared", "elm.text",
2474                                    _signal_selection_cleared, obj);
2475    edje_object_signal_callback_add(wd->ent, "entry,paste,request,*", "elm.text",
2476                                    _signal_entry_paste_request, obj);
2477    edje_object_signal_callback_add(wd->ent, "entry,copy,notify", "elm.text",
2478                                    _signal_entry_copy_notify, obj);
2479    edje_object_signal_callback_add(wd->ent, "entry,cut,notify", "elm.text",
2480                                    _signal_entry_cut_notify, obj);
2481    edje_object_signal_callback_add(wd->ent, "cursor,changed", "elm.text",
2482                                    _signal_cursor_changed, obj);
2483    edje_object_signal_callback_add(wd->ent, "cursor,changed,manual", "elm.text",
2484                                    _signal_cursor_changed_manual, obj);
2485    edje_object_signal_callback_add(wd->ent, "anchor,mouse,down,*", "elm.text",
2486                                    _signal_anchor_down, obj);
2487    edje_object_signal_callback_add(wd->ent, "anchor,mouse,up,*", "elm.text",
2488                                    _signal_anchor_up, obj);
2489    edje_object_signal_callback_add(wd->ent, "anchor,mouse,clicked,*", "elm.text",
2490                                    _signal_anchor_clicked, obj);
2491    edje_object_signal_callback_add(wd->ent, "anchor,mouse,move,*", "elm.text",
2492                                    _signal_anchor_move, obj);
2493    edje_object_signal_callback_add(wd->ent, "anchor,mouse,in,*", "elm.text",
2494                                    _signal_anchor_in, obj);
2495    edje_object_signal_callback_add(wd->ent, "anchor,mouse,out,*", "elm.text",
2496                                    _signal_anchor_out, obj);
2497    edje_object_signal_callback_add(wd->ent, "entry,key,enter", "elm.text",
2498                                    _signal_key_enter, obj);
2499    edje_object_signal_callback_add(wd->ent, "mouse,down,1", "elm.text",
2500                                    _signal_mouse_down, obj);
2501    edje_object_signal_callback_add(wd->ent, "mouse,clicked,1", "elm.text",
2502                                    _signal_mouse_clicked, obj);
2503    edje_object_signal_callback_add(wd->ent, "mouse,down,1,double", "elm.text",
2504                                    _signal_mouse_double, obj);
2505    edje_object_signal_callback_add(wd->ent, "mouse,down,1,triple", "elm.text",
2506                                    _signal_mouse_triple, obj);
2507    edje_object_signal_callback_add(wd->ent, "entry,undo,request", "elm.text",
2508                                    _signal_undo_request, obj);
2509    edje_object_signal_callback_add(wd->ent, "entry,redo,request", "elm.text",
2510                                    _signal_redo_request, obj);
2511    edje_object_part_text_set(wd->ent, "elm.text", "");
2512    if (_elm_config->desktop_entry)
2513      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
2514    elm_widget_resize_object_set(obj, wd->ent);
2515    _sizing_eval(obj);
2516
2517    elm_entry_input_panel_layout_set(obj, ELM_INPUT_PANEL_LAYOUT_NORMAL);
2518    elm_entry_input_panel_enabled_set(obj, EINA_TRUE);
2519    elm_entry_prediction_allow_set(obj, EINA_TRUE);
2520
2521    wd->autocapital_type = edje_object_part_text_autocapital_type_get(wd->ent, "elm.text");
2522
2523 #ifdef HAVE_ELEMENTARY_X
2524    top = elm_widget_top_get(obj);
2525    if ((top) && (elm_win_xwindow_get(top)))
2526      {
2527         wd->sel_notify_handler =
2528            ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
2529                                    _event_selection_notify, obj);
2530         wd->sel_clear_handler =
2531            ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR,
2532                                    _event_selection_clear, obj);
2533      }
2534
2535    elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE,
2536                        _drag_drop_cb, NULL);
2537 #endif
2538
2539    entries = eina_list_prepend(entries, obj);
2540
2541    // module - find module for entry
2542    wd->api = _module(obj);
2543    // if found - hook in
2544    if ((wd->api) && (wd->api->obj_hook)) wd->api->obj_hook(obj);
2545
2546    _mirrored_set(obj, elm_widget_mirrored_get(obj));
2547    // TODO: convert Elementary to subclassing of Evas_Smart_Class
2548    // TODO: and save some bytes, making descriptions per-class and not instance!
2549    evas_object_smart_callbacks_descriptions_set(obj, _signals);
2550    return obj;
2551 }
2552
2553 EAPI void
2554 elm_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line)
2555 {
2556    ELM_CHECK_WIDTYPE(obj, widtype);
2557    Widget_Data *wd = elm_widget_data_get(obj);
2558    if (!wd) return;
2559    if (wd->single_line == single_line) return;
2560    wd->single_line = single_line;
2561    wd->linewrap = ELM_WRAP_NONE;
2562    elm_entry_cnp_mode_set(obj, ELM_CNP_MODE_NO_IMAGE);
2563    _theme_hook(obj);
2564    if (wd->scroller)
2565      {
2566         if (wd->single_line)
2567           elm_smart_scroller_policy_set(wd->scroller,
2568                                         ELM_SMART_SCROLLER_POLICY_OFF,
2569                                         ELM_SMART_SCROLLER_POLICY_OFF);
2570         else
2571           {
2572              const Elm_Scroller_Policy map[3] =
2573                {
2574                   ELM_SMART_SCROLLER_POLICY_AUTO,
2575                   ELM_SMART_SCROLLER_POLICY_ON,
2576                   ELM_SMART_SCROLLER_POLICY_OFF
2577                };
2578              elm_smart_scroller_policy_set(wd->scroller,
2579                                            map[wd->policy_h],
2580                                            map[wd->policy_v]);
2581           }
2582         _sizing_eval(obj);
2583      }
2584 }
2585
2586 EAPI Eina_Bool
2587 elm_entry_single_line_get(const Evas_Object *obj)
2588 {
2589    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2590    Widget_Data *wd = elm_widget_data_get(obj);
2591    if (!wd) return EINA_FALSE;
2592    return wd->single_line;
2593 }
2594
2595 EAPI void
2596 elm_entry_password_set(Evas_Object *obj, Eina_Bool password)
2597 {
2598    ELM_CHECK_WIDTYPE(obj, widtype);
2599    Widget_Data *wd = elm_widget_data_get(obj);
2600    if (!wd) return;
2601    if (wd->password == password) return;
2602    wd->password = password;
2603    if (password)
2604      {
2605         wd->single_line = EINA_TRUE;
2606         wd->linewrap = ELM_WRAP_NONE;
2607 #ifdef HAVE_ELEMENTARY_X
2608         elm_drop_target_del(obj);
2609 #endif
2610         edje_object_signal_callback_del_full(wd->ent, "selection,start", "elm.text",
2611                                         _signal_selection_start, obj);
2612         edje_object_signal_callback_del_full(wd->ent, "selection,changed", "elm.text",
2613                                         _signal_selection_changed, obj);
2614         edje_object_signal_callback_del_full(wd->ent, "entry,selection,all,request", "elm.text",
2615                                         _signal_selection_all, obj);
2616         edje_object_signal_callback_del_full(wd->ent, "entry,selection,none,request", "elm.text",
2617                                         _signal_selection_none, obj);
2618         edje_object_signal_callback_del_full(wd->ent, "selection,cleared", "elm.text",
2619                                         _signal_selection_cleared, obj);
2620         edje_object_signal_callback_del_full(wd->ent, "entry,paste,request,*", "elm.text",
2621                                         _signal_entry_paste_request, obj);
2622         edje_object_signal_callback_del_full(wd->ent, "entry,copy,notify", "elm.text",
2623                                         _signal_entry_copy_notify, obj);
2624         edje_object_signal_callback_del_full(wd->ent, "entry,cut,notify", "elm.text",
2625                                         _signal_entry_cut_notify, obj);
2626      }
2627    else
2628      {
2629 #ifdef HAVE_ELEMENTARY_X
2630         elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP, _drag_drop_cb, NULL);
2631 #endif
2632         edje_object_signal_callback_add(wd->ent, "selection,start", "elm.text",
2633                                         _signal_selection_start, obj);
2634         edje_object_signal_callback_add(wd->ent, "selection,changed", "elm.text",
2635                                         _signal_selection_changed, obj);
2636         edje_object_signal_callback_add(wd->ent, "entry,selection,all,request", "elm.text",
2637                                         _signal_selection_all, obj);
2638         edje_object_signal_callback_add(wd->ent, "entry,selection,none,request", "elm.text",
2639                                         _signal_selection_none, obj);
2640         edje_object_signal_callback_add(wd->ent, "selection,cleared", "elm.text",
2641                                         _signal_selection_cleared, obj);
2642         edje_object_signal_callback_add(wd->ent, "entry,paste,request,*", "elm.text",
2643                                         _signal_entry_paste_request, obj);
2644         edje_object_signal_callback_add(wd->ent, "entry,copy,notify", "elm.text",
2645                                         _signal_entry_copy_notify, obj);
2646         edje_object_signal_callback_add(wd->ent, "entry,cut,notify", "elm.text",
2647                                         _signal_entry_cut_notify, obj);
2648      }
2649    _theme_hook(obj);
2650 }
2651
2652 EAPI Eina_Bool
2653 elm_entry_password_get(const Evas_Object *obj)
2654 {
2655    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2656    Widget_Data *wd = elm_widget_data_get(obj);
2657    if (!wd) return EINA_FALSE;
2658    return wd->password;
2659 }
2660
2661 EAPI void
2662 elm_entry_entry_set(Evas_Object *obj, const char *entry)
2663 {
2664    _elm_entry_text_set(obj, NULL, entry);
2665 }
2666
2667 EAPI const char *
2668 elm_entry_entry_get(const Evas_Object *obj)
2669 {
2670    return _elm_entry_text_get(obj, NULL);
2671 }
2672
2673 EAPI void
2674 elm_entry_entry_append(Evas_Object *obj, const char *entry)
2675 {
2676    int len = 0;
2677    ELM_CHECK_WIDTYPE(obj, widtype);
2678    Widget_Data *wd = elm_widget_data_get(obj);
2679    if (!wd) return;
2680    if (!entry) entry = "";
2681    wd->changed = EINA_TRUE;
2682
2683    len = strlen(entry);
2684    if (wd->append_text_left)
2685      {
2686         char *tmpbuf;
2687         tmpbuf = realloc(wd->append_text_left, wd->append_text_len + len + 1);
2688         if (!tmpbuf)
2689           {
2690              /* Do something */
2691              return;
2692           }
2693         wd->append_text_left = tmpbuf;
2694         memcpy(wd->append_text_left + wd->append_text_len, entry, len + 1);
2695         wd->append_text_len += len;
2696      }
2697    else
2698      {
2699         /* FIXME: Add chunked appending here (like in entry_set) */
2700         edje_object_part_text_append(wd->ent, "elm.text", entry);
2701      }
2702 }
2703
2704 EAPI Eina_Bool
2705 elm_entry_is_empty(const Evas_Object *obj)
2706 {
2707    /* FIXME: until there's support for that in textblock, we just check
2708     * to see if the there is text or not. */
2709    ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
2710    Widget_Data *wd = elm_widget_data_get(obj);
2711    const Evas_Object *tb;
2712    Evas_Textblock_Cursor *cur;
2713    Eina_Bool ret;
2714    if (!wd) return EINA_TRUE;
2715    /* It's a hack until we get the support suggested above.
2716     * We just create a cursor, point it to the begining, and then
2717     * try to advance it, if it can advance, the tb is not empty,
2718     * otherwise it is. */
2719    tb = edje_object_part_object_get(wd->ent, "elm.text");
2720    cur = evas_object_textblock_cursor_new((Evas_Object *) tb); /* This is
2721                                                                   actually, ok for the time being, thsese hackish stuff will be removed
2722                                                                   once evas 1.0 is out*/
2723    evas_textblock_cursor_pos_set(cur, 0);
2724    ret = evas_textblock_cursor_char_next(cur);
2725    evas_textblock_cursor_free(cur);
2726
2727    return !ret;
2728 }
2729
2730 EAPI Evas_Object *
2731 elm_entry_textblock_get(Evas_Object *obj)
2732 {
2733    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2734    Widget_Data *wd = elm_widget_data_get(obj);
2735    if (!wd) return NULL;
2736
2737    return (Evas_Object *) edje_object_part_object_get(wd->ent, "elm.text");
2738 }
2739
2740 EAPI void
2741 elm_entry_calc_force(Evas_Object *obj)
2742 {
2743    ELM_CHECK_WIDTYPE(obj, widtype);
2744    Widget_Data *wd = elm_widget_data_get(obj);
2745    if (!wd) return;
2746
2747    edje_object_calc_force(wd->ent);
2748    wd->changed = EINA_TRUE;
2749    _sizing_eval(obj);
2750 }
2751
2752
2753 EAPI const char *
2754 elm_entry_selection_get(const Evas_Object *obj)
2755 {
2756    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2757    Widget_Data *wd = elm_widget_data_get(obj);
2758    if ((!wd) || (wd->password)) return NULL;
2759    return edje_object_part_text_selection_get(wd->ent, "elm.text");
2760 }
2761
2762 EAPI void
2763 elm_entry_entry_insert(Evas_Object *obj, const char *entry)
2764 {
2765    ELM_CHECK_WIDTYPE(obj, widtype);
2766    Widget_Data *wd = elm_widget_data_get(obj);
2767    if (!wd) return;
2768    edje_object_part_text_insert(wd->ent, "elm.text", entry);
2769    wd->changed = EINA_TRUE;
2770    _sizing_eval(obj);
2771 }
2772
2773 EAPI void
2774 elm_entry_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
2775 {
2776    ELM_CHECK_WIDTYPE(obj, widtype);
2777    Widget_Data *wd = elm_widget_data_get(obj);
2778    if (!wd) return;
2779    if (wd->linewrap == wrap) return;
2780    wd->lastw = -1;
2781    wd->linewrap = wrap;
2782    _theme_hook(obj);
2783 }
2784
2785 EAPI Elm_Wrap_Type
2786 elm_entry_line_wrap_get(const Evas_Object *obj)
2787 {
2788    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2789    Widget_Data *wd = elm_widget_data_get(obj);
2790    if (!wd) return EINA_FALSE;
2791    return wd->linewrap;
2792 }
2793
2794 EAPI void
2795 elm_entry_editable_set(Evas_Object *obj, Eina_Bool editable)
2796 {
2797    ELM_CHECK_WIDTYPE(obj, widtype);
2798    Widget_Data *wd = elm_widget_data_get(obj);
2799    if (!wd) return;
2800    if (wd->editable == editable) return;
2801    wd->editable = editable;
2802    _theme_hook(obj);
2803
2804 #ifdef HAVE_ELEMENTARY_X
2805    if (editable)
2806      elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP, _drag_drop_cb, NULL);
2807    else
2808      elm_drop_target_del(obj);
2809 #endif
2810 }
2811
2812 EAPI Eina_Bool
2813 elm_entry_editable_get(const Evas_Object *obj)
2814 {
2815    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2816    Widget_Data *wd = elm_widget_data_get(obj);
2817    if (!wd) return EINA_FALSE;
2818    return wd->editable;
2819 }
2820
2821 EAPI void
2822 elm_entry_select_none(Evas_Object *obj)
2823 {
2824    ELM_CHECK_WIDTYPE(obj, widtype);
2825    Widget_Data *wd = elm_widget_data_get(obj);
2826    if ((!wd) || (wd->password)) return;
2827    if (wd->selmode)
2828      {
2829         wd->selmode = EINA_FALSE;
2830         if (!_elm_config->desktop_entry)
2831           edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
2832         edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
2833      }
2834    wd->have_selection = EINA_FALSE;
2835    edje_object_part_text_select_none(wd->ent, "elm.text");
2836 }
2837
2838 EAPI void
2839 elm_entry_select_all(Evas_Object *obj)
2840 {
2841    ELM_CHECK_WIDTYPE(obj, widtype);
2842    Widget_Data *wd = elm_widget_data_get(obj);
2843    if ((!wd) || (wd->password)) return;
2844    if (wd->selmode)
2845      {
2846         wd->selmode = EINA_FALSE;
2847         if (!_elm_config->desktop_entry)
2848           edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
2849         edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
2850      }
2851    wd->have_selection = EINA_TRUE;
2852    edje_object_part_text_select_all(wd->ent, "elm.text");
2853 }
2854
2855 EAPI Eina_Bool
2856 elm_entry_cursor_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
2857 {
2858    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2859    Widget_Data *wd = elm_widget_data_get(obj);
2860    if (!wd) return EINA_FALSE;
2861    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
2862    return EINA_TRUE;
2863 }
2864
2865 EAPI Eina_Bool
2866 elm_entry_cursor_next(Evas_Object *obj)
2867 {
2868    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2869    Widget_Data *wd = elm_widget_data_get(obj);
2870    if (!wd) return EINA_FALSE;
2871    return edje_object_part_text_cursor_next(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2872 }
2873
2874 EAPI Eina_Bool
2875 elm_entry_cursor_prev(Evas_Object *obj)
2876 {
2877    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2878    Widget_Data *wd = elm_widget_data_get(obj);
2879    if (!wd) return EINA_FALSE;
2880    return edje_object_part_text_cursor_prev(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2881 }
2882
2883 EAPI Eina_Bool
2884 elm_entry_cursor_up(Evas_Object *obj)
2885 {
2886    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2887    Widget_Data *wd = elm_widget_data_get(obj);
2888    if (!wd) return EINA_FALSE;
2889    return edje_object_part_text_cursor_up(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2890 }
2891
2892 EAPI Eina_Bool
2893 elm_entry_cursor_down(Evas_Object *obj)
2894 {
2895    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2896    Widget_Data *wd = elm_widget_data_get(obj);
2897    if (!wd) return EINA_FALSE;
2898    return edje_object_part_text_cursor_down(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2899 }
2900
2901 EAPI void
2902 elm_entry_cursor_begin_set(Evas_Object *obj)
2903 {
2904    ELM_CHECK_WIDTYPE(obj, widtype);
2905    Widget_Data *wd = elm_widget_data_get(obj);
2906    if (!wd) return;
2907    edje_object_part_text_cursor_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2908 }
2909
2910 EAPI void
2911 elm_entry_cursor_end_set(Evas_Object *obj)
2912 {
2913    ELM_CHECK_WIDTYPE(obj, widtype);
2914    Widget_Data *wd = elm_widget_data_get(obj);
2915    if (!wd) return;
2916    edje_object_part_text_cursor_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2917 }
2918
2919 EAPI void
2920 elm_entry_cursor_line_begin_set(Evas_Object *obj)
2921 {
2922    ELM_CHECK_WIDTYPE(obj, widtype);
2923    Widget_Data *wd = elm_widget_data_get(obj);
2924    if (!wd) return;
2925    edje_object_part_text_cursor_line_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2926 }
2927
2928 EAPI void
2929 elm_entry_cursor_line_end_set(Evas_Object *obj)
2930 {
2931    ELM_CHECK_WIDTYPE(obj, widtype);
2932    Widget_Data *wd = elm_widget_data_get(obj);
2933    if (!wd) return;
2934    edje_object_part_text_cursor_line_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2935 }
2936
2937 EAPI void
2938 elm_entry_cursor_selection_begin(Evas_Object *obj)
2939 {
2940    ELM_CHECK_WIDTYPE(obj, widtype);
2941    Widget_Data *wd = elm_widget_data_get(obj);
2942    if (!wd) return;
2943    edje_object_part_text_select_begin(wd->ent, "elm.text");
2944 }
2945
2946 EAPI void
2947 elm_entry_cursor_selection_end(Evas_Object *obj)
2948 {
2949    ELM_CHECK_WIDTYPE(obj, widtype);
2950    Widget_Data *wd = elm_widget_data_get(obj);
2951    if (!wd) return;
2952    edje_object_part_text_select_extend(wd->ent, "elm.text");
2953 }
2954
2955 EAPI Eina_Bool
2956 elm_entry_cursor_is_format_get(const Evas_Object *obj)
2957 {
2958    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2959    Widget_Data *wd = elm_widget_data_get(obj);
2960    if (!wd) return EINA_FALSE;
2961    return edje_object_part_text_cursor_is_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2962 }
2963
2964 EAPI Eina_Bool
2965 elm_entry_cursor_is_visible_format_get(const Evas_Object *obj)
2966 {
2967    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2968    Widget_Data *wd = elm_widget_data_get(obj);
2969    if (!wd) return EINA_FALSE;
2970    return edje_object_part_text_cursor_is_visible_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2971 }
2972
2973 EAPI char *
2974 elm_entry_cursor_content_get(const Evas_Object *obj)
2975 {
2976    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2977    Widget_Data *wd = elm_widget_data_get(obj);
2978    if (!wd) return NULL;
2979    return edje_object_part_text_cursor_content_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2980 }
2981
2982 EAPI void
2983 elm_entry_cursor_pos_set(Evas_Object *obj, int pos)
2984 {
2985    ELM_CHECK_WIDTYPE(obj, widtype);
2986    Widget_Data *wd = elm_widget_data_get(obj);
2987    if (!wd) return;
2988    edje_object_part_text_cursor_pos_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN, pos);
2989    edje_object_message_signal_process(wd->ent);
2990 }
2991
2992 EAPI int
2993 elm_entry_cursor_pos_get(const Evas_Object *obj)
2994 {
2995    ELM_CHECK_WIDTYPE(obj, widtype) 0;
2996    Widget_Data *wd = elm_widget_data_get(obj);
2997    if (!wd) return 0;
2998    return edje_object_part_text_cursor_pos_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2999 }
3000
3001 EAPI void
3002 elm_entry_selection_cut(Evas_Object *obj)
3003 {
3004    ELM_CHECK_WIDTYPE(obj, widtype);
3005    Widget_Data *wd = elm_widget_data_get(obj);
3006    if ((!wd) || (wd->password)) return;
3007    _cut(obj, NULL, NULL);
3008 }
3009
3010 EAPI void
3011 elm_entry_selection_copy(Evas_Object *obj)
3012 {
3013    ELM_CHECK_WIDTYPE(obj, widtype);
3014    Widget_Data *wd = elm_widget_data_get(obj);
3015    if ((!wd) || (wd->password)) return;
3016    _copy(obj, NULL, NULL);
3017 }
3018
3019 EAPI void
3020 elm_entry_selection_paste(Evas_Object *obj)
3021 {
3022    ELM_CHECK_WIDTYPE(obj, widtype);
3023    Widget_Data *wd = elm_widget_data_get(obj);
3024    if ((!wd) || (wd->password)) return;
3025    _paste(obj, NULL, NULL);
3026 }
3027
3028 EAPI void
3029 elm_entry_context_menu_clear(Evas_Object *obj)
3030 {
3031    ELM_CHECK_WIDTYPE(obj, widtype);
3032    Widget_Data *wd = elm_widget_data_get(obj);
3033    Elm_Entry_Context_Menu_Item *it;
3034    if (!wd) return;
3035    EINA_LIST_FREE(wd->items, it)
3036      {
3037         eina_stringshare_del(it->label);
3038         eina_stringshare_del(it->icon_file);
3039         eina_stringshare_del(it->icon_group);
3040         free(it);
3041      }
3042 }
3043
3044 EAPI void
3045 elm_entry_context_menu_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data)
3046 {
3047    ELM_CHECK_WIDTYPE(obj, widtype);
3048    Widget_Data *wd = elm_widget_data_get(obj);
3049    Elm_Entry_Context_Menu_Item *it;
3050    if (!wd) return;
3051    it = calloc(1, sizeof(Elm_Entry_Context_Menu_Item));
3052    if (!it) return;
3053    wd->items = eina_list_append(wd->items, it);
3054    it->obj = obj;
3055    it->label = eina_stringshare_add(label);
3056    it->icon_file = eina_stringshare_add(icon_file);
3057    it->icon_type = icon_type;
3058    it->func = func;
3059    it->data = (void *)data;
3060 }
3061
3062 EAPI void
3063 elm_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3064 {
3065    ELM_CHECK_WIDTYPE(obj, widtype);
3066    Widget_Data *wd = elm_widget_data_get(obj);
3067    if (!wd) return;
3068    if (wd->context_menu == !disabled) return;
3069    wd->context_menu = !disabled;
3070 }
3071
3072 EAPI Eina_Bool
3073 elm_entry_context_menu_disabled_get(const Evas_Object *obj)
3074 {
3075    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3076    Widget_Data *wd = elm_widget_data_get(obj);
3077    if (!wd) return EINA_FALSE;
3078    return !wd->context_menu;
3079 }
3080
3081 EAPI void
3082 elm_entry_item_provider_append(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data)
3083 {
3084    ELM_CHECK_WIDTYPE(obj, widtype);
3085    Widget_Data *wd = elm_widget_data_get(obj);
3086    if (!wd) return;
3087    EINA_SAFETY_ON_NULL_RETURN(func);
3088    Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
3089    if (!ip) return;
3090    ip->func = func;
3091    ip->data = data;
3092    wd->item_providers = eina_list_append(wd->item_providers, ip);
3093 }
3094
3095 EAPI void
3096 elm_entry_item_provider_prepend(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data)
3097 {
3098    ELM_CHECK_WIDTYPE(obj, widtype);
3099    Widget_Data *wd = elm_widget_data_get(obj);
3100    if (!wd) return;
3101    EINA_SAFETY_ON_NULL_RETURN(func);
3102    Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
3103    if (!ip) return;
3104    ip->func = func;
3105    ip->data = data;
3106    wd->item_providers = eina_list_prepend(wd->item_providers, ip);
3107 }
3108
3109 EAPI void
3110 elm_entry_item_provider_remove(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data)
3111 {
3112    ELM_CHECK_WIDTYPE(obj, widtype);
3113    Widget_Data *wd = elm_widget_data_get(obj);
3114    Eina_List *l;
3115    Elm_Entry_Item_Provider *ip;
3116    if (!wd) return;
3117    EINA_SAFETY_ON_NULL_RETURN(func);
3118    EINA_LIST_FOREACH(wd->item_providers, l, ip)
3119      {
3120         if ((ip->func == func) && ((!data) || (ip->data == data)))
3121           {
3122              wd->item_providers = eina_list_remove_list(wd->item_providers, l);
3123              free(ip);
3124              return;
3125           }
3126      }
3127 }
3128
3129 EAPI void
3130 elm_entry_markup_filter_append(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data)
3131 {
3132    Widget_Data *wd;
3133    Elm_Entry_Markup_Filter *tf;
3134    ELM_CHECK_WIDTYPE(obj, widtype);
3135
3136    wd = elm_widget_data_get(obj);
3137
3138    EINA_SAFETY_ON_NULL_RETURN(func);
3139
3140    tf = _filter_new(func, data);
3141    if (!tf) return;
3142
3143    wd->markup_filters = eina_list_append(wd->markup_filters, tf);
3144 }
3145
3146 EAPI void
3147 elm_entry_markup_filter_prepend(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data)
3148 {
3149    Widget_Data *wd;
3150    Elm_Entry_Markup_Filter *tf;
3151    ELM_CHECK_WIDTYPE(obj, widtype);
3152
3153    wd = elm_widget_data_get(obj);
3154
3155    EINA_SAFETY_ON_NULL_RETURN(func);
3156
3157    tf = _filter_new(func, data);
3158    if (!tf) return;
3159
3160    wd->markup_filters = eina_list_prepend(wd->markup_filters, tf);
3161 }
3162
3163 EAPI void
3164 elm_entry_markup_filter_remove(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data)
3165 {
3166    Widget_Data *wd;
3167    Eina_List *l;
3168    Elm_Entry_Markup_Filter *tf;
3169    ELM_CHECK_WIDTYPE(obj, widtype);
3170
3171    wd = elm_widget_data_get(obj);
3172
3173    EINA_SAFETY_ON_NULL_RETURN(func);
3174
3175    EINA_LIST_FOREACH(wd->markup_filters, l, tf)
3176      {
3177         if ((tf->func == func) && ((!data) || (tf->data == data)))
3178           {
3179              wd->markup_filters = eina_list_remove_list(wd->markup_filters, l);
3180              _filter_free(tf);
3181              return;
3182           }
3183      }
3184 }
3185
3186 EAPI char *
3187 elm_entry_markup_to_utf8(const char *s)
3188 {
3189    char *ss = _elm_util_mkup_to_text(s);
3190    if (!ss) ss = strdup("");
3191    return ss;
3192 }
3193
3194 EAPI char *
3195 elm_entry_utf8_to_markup(const char *s)
3196 {
3197    char *ss = _elm_util_text_to_mkup(s);
3198    if (!ss) ss = strdup("");
3199    return ss;
3200 }
3201
3202 static const char *
3203 _text_get(const Evas_Object *obj)
3204 {
3205    return elm_object_text_get(obj);
3206 }
3207
3208 EAPI void
3209 elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text)
3210 {
3211    Elm_Entry_Filter_Limit_Size *lim = data;
3212    char *current, *utfstr;
3213    int len, newlen;
3214    const char *(*text_get)(const Evas_Object *);
3215
3216    EINA_SAFETY_ON_NULL_RETURN(data);
3217    EINA_SAFETY_ON_NULL_RETURN(entry);
3218    EINA_SAFETY_ON_NULL_RETURN(text);
3219
3220    /* hack. I don't want to copy the entire function to work with
3221     * scrolled_entry */
3222    text_get = _text_get;
3223
3224    current = elm_entry_markup_to_utf8(text_get(entry));
3225    utfstr = elm_entry_markup_to_utf8(*text);
3226
3227    if (lim->max_char_count > 0)
3228      {
3229         len = evas_string_char_len_get(current);
3230         newlen = evas_string_char_len_get(utfstr);
3231         if ((len >= lim->max_char_count) && (newlen > 0))
3232           {
3233              evas_object_smart_callback_call(entry, "maxlength,reached", NULL);
3234              free(*text);
3235              *text = NULL;
3236              free(current);
3237              free(utfstr);
3238              return;
3239           }
3240         if ((len + newlen) > lim->max_char_count)
3241           _add_chars_till_limit(entry, text, (lim->max_char_count - len), LENGTH_UNIT_CHAR);
3242      }
3243    else if (lim->max_byte_count > 0)
3244      {
3245         len = strlen(current);
3246         newlen = strlen(utfstr);
3247         if ((len >= lim->max_byte_count) && (newlen > 0))
3248           {
3249              evas_object_smart_callback_call(entry, "maxlength,reached", NULL);
3250              free(*text);
3251              *text = NULL;
3252              free(current);
3253              free(utfstr);
3254              return;
3255           }
3256         if ((len + newlen) > lim->max_byte_count)
3257           _add_chars_till_limit(entry, text, (lim->max_byte_count - len), LENGTH_UNIT_BYTE);
3258      }
3259    free(current);
3260    free(utfstr);
3261 }
3262
3263 EAPI void
3264 elm_entry_filter_accept_set(void *data, Evas_Object *entry __UNUSED__, char **text)
3265 {
3266    Elm_Entry_Filter_Accept_Set *as = data;
3267    const char *set;
3268    char *insert;
3269    Eina_Bool goes_in;
3270    int read_idx, last_read_idx = 0, read_char;
3271
3272    EINA_SAFETY_ON_NULL_RETURN(data);
3273    EINA_SAFETY_ON_NULL_RETURN(text);
3274
3275    if ((!as->accepted) && (!as->rejected))
3276      return;
3277
3278    if (as->accepted)
3279      {
3280         set = as->accepted;
3281         goes_in = EINA_TRUE;
3282      }
3283    else
3284      {
3285         set = as->rejected;
3286         goes_in = EINA_FALSE;
3287      }
3288
3289    insert = *text;
3290    read_idx = evas_string_char_next_get(*text, 0, &read_char);
3291    while (read_char)
3292      {
3293         int cmp_idx, cmp_char;
3294         Eina_Bool in_set = EINA_FALSE;
3295
3296         cmp_idx = evas_string_char_next_get(set, 0, &cmp_char);
3297         while (cmp_char)
3298           {
3299              if (read_char == cmp_char)
3300                {
3301                   in_set = EINA_TRUE;
3302                   break;
3303                }
3304              cmp_idx = evas_string_char_next_get(set, cmp_idx, &cmp_char);
3305           }
3306         if (in_set == goes_in)
3307           {
3308              int size = read_idx - last_read_idx;
3309              const char *src = (*text) + last_read_idx;
3310              if (src != insert)
3311                memcpy(insert, *text + last_read_idx, size);
3312              insert += size;
3313           }
3314         last_read_idx = read_idx;
3315         read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
3316      }
3317    *insert = 0;
3318 }
3319
3320 EAPI Eina_Bool
3321 elm_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format)
3322 {
3323    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3324    Widget_Data *wd = elm_widget_data_get(obj);
3325    if (!wd) return EINA_FALSE;
3326    if (wd->delay_write)
3327      {
3328         ecore_timer_del(wd->delay_write);
3329         wd->delay_write = NULL;
3330      }
3331    if (wd->autosave) _save(obj);
3332    eina_stringshare_replace(&wd->file, file);
3333    wd->format = format;
3334    return _load(obj);
3335 }
3336
3337 EAPI void
3338 elm_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format)
3339 {
3340    ELM_CHECK_WIDTYPE(obj, widtype);
3341    Widget_Data *wd = elm_widget_data_get(obj);
3342    if (!wd) return;
3343    if (file) *file = wd->file;
3344    if (format) *format = wd->format;
3345 }
3346
3347 EAPI void
3348 elm_entry_file_save(Evas_Object *obj)
3349 {
3350    ELM_CHECK_WIDTYPE(obj, widtype);
3351    Widget_Data *wd = elm_widget_data_get(obj);
3352    if (!wd) return;
3353    if (wd->delay_write)
3354      {
3355         ecore_timer_del(wd->delay_write);
3356         wd->delay_write = NULL;
3357      }
3358    _save(obj);
3359    wd->delay_write = ecore_timer_add(2.0, _delay_write, obj);
3360 }
3361
3362 EAPI void
3363 elm_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave)
3364 {
3365    ELM_CHECK_WIDTYPE(obj, widtype);
3366    Widget_Data *wd = elm_widget_data_get(obj);
3367    if (!wd) return;
3368    wd->autosave = !!autosave;
3369 }
3370
3371 EAPI Eina_Bool
3372 elm_entry_autosave_get(const Evas_Object *obj)
3373 {
3374    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3375    Widget_Data *wd = elm_widget_data_get(obj);
3376    if (!wd) return EINA_FALSE;
3377    return wd->autosave;
3378 }
3379
3380 EINA_DEPRECATED EAPI void
3381 elm_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly)
3382 {
3383    ELM_CHECK_WIDTYPE(obj, widtype);
3384    Elm_Cnp_Mode cnp_mode = ELM_CNP_MODE_MARKUP;
3385    if (textonly)
3386      cnp_mode = ELM_CNP_MODE_NO_IMAGE;
3387    elm_entry_cnp_mode_set(obj, cnp_mode);
3388 }
3389
3390 EINA_DEPRECATED EAPI Eina_Bool
3391 elm_entry_cnp_textonly_get(const Evas_Object *obj)
3392 {
3393    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3394    return elm_entry_cnp_mode_get(obj) != ELM_CNP_MODE_MARKUP;
3395 }
3396
3397 EAPI void
3398 elm_entry_cnp_mode_set(Evas_Object *obj, Elm_Cnp_Mode cnp_mode)
3399 {
3400    Elm_Sel_Format format = ELM_SEL_FORMAT_MARKUP;
3401    ELM_CHECK_WIDTYPE(obj, widtype);
3402    Widget_Data *wd = elm_widget_data_get(obj);
3403    if (!wd) return;
3404    if (wd->cnp_mode == cnp_mode) return;
3405    wd->cnp_mode = cnp_mode;
3406    if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
3407      format = ELM_SEL_FORMAT_TEXT;
3408    else if (cnp_mode == ELM_CNP_MODE_MARKUP) format |= ELM_SEL_FORMAT_IMAGE;
3409 #ifdef HAVE_ELEMENTARY_X
3410    elm_drop_target_add(obj, format, _drag_drop_cb, NULL);
3411 #endif
3412 }
3413
3414 EAPI Elm_Cnp_Mode
3415 elm_entry_cnp_mode_get(const Evas_Object *obj)
3416 {
3417    ELM_CHECK_WIDTYPE(obj, widtype) ELM_CNP_MODE_MARKUP;
3418    Widget_Data *wd = elm_widget_data_get(obj);
3419    if (!wd) return ELM_CNP_MODE_MARKUP;
3420    return wd->cnp_mode;
3421 }
3422
3423 EAPI void
3424 elm_entry_scrollable_set(Evas_Object *obj, Eina_Bool scroll)
3425 {
3426    ELM_CHECK_WIDTYPE(obj, widtype);
3427    Widget_Data *wd = elm_widget_data_get(obj);
3428    const Elm_Scroller_Policy map[3] =
3429      {
3430         ELM_SMART_SCROLLER_POLICY_AUTO,
3431         ELM_SMART_SCROLLER_POLICY_ON,
3432         ELM_SMART_SCROLLER_POLICY_OFF
3433      };
3434    if (!wd) return;
3435    scroll = !!scroll;
3436    if (wd->scroll == scroll) return;
3437    wd->scroll = scroll;
3438    if (wd->scroll)
3439      {
3440         if (!wd->scroller)
3441           {
3442              wd->scroller = elm_smart_scroller_add(evas_object_evas_get(obj));
3443              elm_widget_resize_object_set(obj, wd->scroller);
3444              elm_smart_scroller_widget_set(wd->scroller, obj);
3445              elm_smart_scroller_object_theme_set(obj, wd->scroller, "scroller", "entry",
3446                                                  elm_widget_style_get(obj));
3447              evas_object_size_hint_weight_set(wd->scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3448              evas_object_size_hint_align_set(wd->scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
3449              evas_object_propagate_events_set(wd->scroller, EINA_TRUE);
3450              evas_object_propagate_events_set(elm_smart_scroller_edje_object_get(wd->scroller),
3451                                               EINA_TRUE);
3452           }
3453         elm_smart_scroller_bounce_allow_set(wd->scroller, wd->h_bounce, wd->v_bounce);
3454         if (wd->single_line)
3455           elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF,
3456                                         ELM_SMART_SCROLLER_POLICY_OFF);
3457         else
3458           elm_smart_scroller_policy_set(wd->scroller, map[wd->policy_h], map[wd->policy_v]);
3459         elm_widget_sub_object_add(obj, wd->ent);
3460         elm_smart_scroller_child_set(wd->scroller, wd->ent);
3461         evas_object_show(wd->scroller);
3462         elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3463      }
3464    else
3465      {
3466         if (wd->scroller)
3467           {
3468              elm_smart_scroller_child_set(wd->scroller, NULL);
3469              evas_object_smart_member_add(wd->scroller, obj);
3470              elm_widget_sub_object_add(obj, wd->scroller);
3471              evas_object_hide(wd->scroller);
3472           }
3473         elm_widget_sub_object_del(obj, wd->ent);
3474         elm_widget_resize_object_set(obj, wd->ent);
3475         elm_widget_on_show_region_hook_set(obj, NULL, NULL);
3476      }
3477    wd->lastw = -1;
3478    _theme_hook(obj);
3479 }
3480
3481 EAPI Eina_Bool
3482 elm_entry_scrollable_get(const Evas_Object *obj)
3483 {
3484    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3485    Widget_Data *wd = elm_widget_data_get(obj);
3486    if (!wd) return EINA_FALSE;
3487    return wd->scroll;
3488 }
3489
3490 EAPI void
3491 elm_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting)
3492 {
3493    ELM_CHECK_WIDTYPE(obj, widtype);
3494    Widget_Data *wd = elm_widget_data_get(obj);
3495    Evas_Object *edje;
3496    if (!wd) return;
3497    if (wd->scroll)
3498       edje = elm_smart_scroller_edje_object_get(wd->scroller);
3499    else
3500       edje = wd->ent;
3501
3502    if ((!edje) || (!edje_object_part_swallow_get(edje, "elm.swallow.icon"))) return;
3503    if (setting)
3504      edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
3505    else
3506      edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
3507    _sizing_eval(obj);
3508 }
3509
3510 EAPI void
3511 elm_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting)
3512 {
3513    ELM_CHECK_WIDTYPE(obj, widtype);
3514    Widget_Data *wd = elm_widget_data_get(obj);
3515    Evas_Object *edje;
3516    if (!wd) return;
3517    if (wd->scroll)
3518       edje = elm_smart_scroller_edje_object_get(wd->scroller);
3519    else
3520       edje = wd->ent;
3521
3522    if ((!edje) || (!edje_object_part_swallow_get(edje, "elm.swallow.icon"))) return;
3523    if (setting)
3524      edje_object_signal_emit(edje, "elm,action,show,end", "elm");
3525    else
3526      edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
3527    _sizing_eval(obj);
3528 }
3529
3530 EAPI void
3531 elm_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v)
3532 {
3533    ELM_CHECK_WIDTYPE(obj, widtype);
3534    Widget_Data *wd = elm_widget_data_get(obj);
3535    const Elm_Scroller_Policy map[3] =
3536      {
3537         ELM_SMART_SCROLLER_POLICY_AUTO,
3538         ELM_SMART_SCROLLER_POLICY_ON,
3539         ELM_SMART_SCROLLER_POLICY_OFF
3540      };
3541    if (!wd) return;
3542    wd->policy_h = h;
3543    wd->policy_v = v;
3544    elm_smart_scroller_policy_set(wd->scroller,
3545                                  map[wd->policy_h],
3546                                  map[wd->policy_v]);
3547 }
3548
3549 EAPI void
3550 elm_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
3551 {
3552    ELM_CHECK_WIDTYPE(obj, widtype);
3553    Widget_Data *wd = elm_widget_data_get(obj);
3554    if (!wd) return;
3555    wd->h_bounce = h_bounce;
3556    wd->v_bounce = v_bounce;
3557    elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
3558 }
3559
3560 EAPI void
3561 elm_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
3562 {
3563    ELM_CHECK_WIDTYPE(obj, widtype);
3564    Widget_Data *wd = elm_widget_data_get(obj);
3565    if (!wd) return;
3566    elm_smart_scroller_bounce_allow_get(wd->scroller, h_bounce, v_bounce);
3567 }
3568
3569 EAPI void
3570 elm_entry_input_panel_layout_set(Evas_Object *obj, Elm_Input_Panel_Layout layout)
3571 {
3572    ELM_CHECK_WIDTYPE(obj, widtype);
3573    Widget_Data *wd = elm_widget_data_get(obj);
3574    if (!wd) return;
3575
3576    wd->input_panel_layout = layout;
3577
3578    edje_object_part_text_input_panel_layout_set(wd->ent, "elm.text", layout);
3579 }
3580
3581 EAPI Elm_Input_Panel_Layout
3582 elm_entry_input_panel_layout_get(const Evas_Object *obj)
3583 {
3584    ELM_CHECK_WIDTYPE(obj, widtype) ELM_INPUT_PANEL_LAYOUT_INVALID;
3585    Widget_Data *wd = elm_widget_data_get(obj);
3586    if (!wd) return ELM_INPUT_PANEL_LAYOUT_INVALID;
3587
3588    return wd->input_panel_layout;
3589 }
3590
3591 EAPI void
3592 elm_entry_autocapital_type_set(Evas_Object *obj, Elm_Autocapital_Type autocapital_type)
3593 {
3594    ELM_CHECK_WIDTYPE(obj, widtype);
3595    Widget_Data *wd = elm_widget_data_get(obj);
3596    if (!wd) return;
3597
3598    wd->autocapital_type = autocapital_type;
3599    edje_object_part_text_autocapital_type_set(wd->ent, "elm.text", autocapital_type);
3600 }
3601
3602 EAPI Elm_Autocapital_Type
3603 elm_entry_autocapital_type_get(const Evas_Object *obj)
3604 {
3605    ELM_CHECK_WIDTYPE(obj, widtype) ELM_AUTOCAPITAL_TYPE_NONE;
3606    Widget_Data *wd = elm_widget_data_get(obj);
3607    if (!wd) return ELM_AUTOCAPITAL_TYPE_NONE;
3608
3609    return wd->autocapital_type;
3610 }
3611
3612 EAPI void
3613 elm_entry_prediction_allow_set(Evas_Object *obj, Eina_Bool prediction)
3614 {
3615    ELM_CHECK_WIDTYPE(obj, widtype);
3616    Widget_Data *wd = elm_widget_data_get(obj);
3617    if (!wd) return;
3618
3619    wd->prediction_allow = prediction;
3620    edje_object_part_text_prediction_allow_set(wd->ent, "elm.text", prediction);
3621 }
3622
3623 EAPI Eina_Bool
3624 elm_entry_prediction_allow_get(const Evas_Object *obj)
3625 {
3626    ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
3627    Widget_Data *wd = elm_widget_data_get(obj);
3628    if (!wd) return EINA_TRUE;
3629
3630    return wd->prediction_allow;
3631 }
3632
3633 EAPI void
3634 elm_entry_imf_context_reset(Evas_Object *obj)
3635 {
3636    ELM_CHECK_WIDTYPE(obj, widtype);
3637    Widget_Data *wd = elm_widget_data_get(obj);
3638    if (!wd) return;
3639
3640    edje_object_part_text_imf_context_reset(wd->ent, "elm.text");
3641 }
3642
3643 EAPI void
3644 elm_entry_input_panel_enabled_set(Evas_Object *obj, Eina_Bool enabled)
3645 {
3646    ELM_CHECK_WIDTYPE(obj, widtype);
3647    Widget_Data *wd = elm_widget_data_get(obj);
3648    if (!wd) return;
3649
3650    wd->input_panel_enable = enabled;
3651    edje_object_part_text_input_panel_enabled_set(wd->ent, "elm.text", enabled);
3652 }
3653
3654 EAPI Eina_Bool
3655 elm_entry_input_panel_enabled_get(const Evas_Object *obj)
3656 {
3657    ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
3658    Widget_Data *wd = elm_widget_data_get(obj);
3659    if (!wd) return EINA_TRUE;
3660
3661    return wd->input_panel_enable;
3662 }
3663
3664 EAPI void
3665 elm_entry_input_panel_show(Evas_Object *obj)
3666 {
3667    ELM_CHECK_WIDTYPE(obj, widtype);
3668    Widget_Data *wd = elm_widget_data_get(obj);
3669    if (!wd) return;
3670
3671    edje_object_part_text_input_panel_show(wd->ent, "elm.text");
3672 }
3673
3674 EAPI void
3675 elm_entry_input_panel_hide(Evas_Object *obj)
3676 {
3677    ELM_CHECK_WIDTYPE(obj, widtype);
3678    Widget_Data *wd = elm_widget_data_get(obj);
3679    if (!wd) return;
3680
3681    edje_object_part_text_input_panel_hide(wd->ent, "elm.text");
3682 }
3683
3684 EAPI void
3685 elm_entry_input_panel_language_set(Evas_Object *obj, Elm_Input_Panel_Lang lang)
3686 {
3687    ELM_CHECK_WIDTYPE(obj, widtype);
3688    Widget_Data *wd = elm_widget_data_get(obj);
3689    if (!wd) return;
3690
3691    wd->input_panel_lang = lang;
3692    edje_object_part_text_input_panel_language_set(wd->ent, "elm.text", lang);
3693 }
3694
3695 EAPI Elm_Input_Panel_Lang
3696 elm_entry_input_panel_language_get(const Evas_Object *obj)
3697 {
3698    ELM_CHECK_WIDTYPE(obj, widtype) ELM_INPUT_PANEL_LANG_AUTOMATIC;
3699    Widget_Data *wd = elm_widget_data_get(obj);
3700    if (!wd) return ELM_INPUT_PANEL_LANG_AUTOMATIC;
3701
3702    return wd->input_panel_lang;
3703 }
3704
3705 EAPI void
3706 elm_entry_input_panel_imdata_set(Evas_Object *obj, const void *data, int len)
3707 {
3708    ELM_CHECK_WIDTYPE(obj, widtype);
3709    Widget_Data *wd = elm_widget_data_get(obj);
3710    if (!wd) return;
3711
3712    if (wd->input_panel_imdata)
3713      free(wd->input_panel_imdata);
3714
3715    wd->input_panel_imdata = calloc(1, len);
3716    wd->input_panel_imdata_len = len;
3717    memcpy(wd->input_panel_imdata, data, len);
3718
3719    edje_object_part_text_input_panel_imdata_set(wd->ent, "elm.text", wd->input_panel_imdata, wd->input_panel_imdata_len);
3720 }
3721
3722 EAPI void
3723 elm_entry_input_panel_imdata_get(const Evas_Object *obj, void *data, int *len)
3724 {
3725    ELM_CHECK_WIDTYPE(obj, widtype);
3726    Widget_Data *wd = elm_widget_data_get(obj);
3727    if (!wd) return;
3728
3729    edje_object_part_text_input_panel_imdata_get(wd->ent, "elm.text", data, len);
3730 }
3731
3732 EAPI void
3733 elm_entry_input_panel_return_key_type_set(Evas_Object *obj, Elm_Input_Panel_Return_Key_Type return_key_type)
3734 {
3735    ELM_CHECK_WIDTYPE(obj, widtype);
3736    Widget_Data *wd = elm_widget_data_get(obj);
3737    if (!wd) return;
3738
3739    wd->input_panel_return_key_type = return_key_type;
3740
3741    edje_object_part_text_input_panel_return_key_type_set(wd->ent, "elm.text", return_key_type);
3742 }
3743
3744 EAPI Elm_Input_Panel_Return_Key_Type
3745 elm_entry_input_panel_return_key_type_get(const Evas_Object *obj)
3746 {
3747    ELM_CHECK_WIDTYPE(obj, widtype) ELM_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3748    Widget_Data *wd = elm_widget_data_get(obj);
3749    if (!wd) return ELM_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3750
3751    return wd->input_panel_return_key_type;
3752 }
3753
3754 EAPI void
3755 elm_entry_input_panel_return_key_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3756 {
3757    ELM_CHECK_WIDTYPE(obj, widtype);
3758    Widget_Data *wd = elm_widget_data_get(obj);
3759    if (!wd) return;
3760
3761    wd->input_panel_return_key_disabled = disabled;
3762
3763    edje_object_part_text_input_panel_return_key_disabled_set(wd->ent, "elm.text", disabled);
3764 }
3765
3766 EAPI Eina_Bool
3767 elm_entry_input_panel_return_key_disabled_get(const Evas_Object *obj)
3768 {
3769    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3770    Widget_Data *wd = elm_widget_data_get(obj);
3771    if (!wd) return EINA_FALSE;
3772
3773    return wd->input_panel_return_key_disabled;
3774 }
3775
3776 EAPI void
3777 elm_entry_input_panel_return_key_autoenabled_set(Evas_Object *obj, Eina_Bool enabled)
3778 {
3779    ELM_CHECK_WIDTYPE(obj, widtype);
3780    Widget_Data *wd = elm_widget_data_get(obj);
3781    if (!wd) return;
3782
3783    wd->autoreturnkey = enabled;
3784    _check_enable_return_key(obj);
3785 }
3786
3787 EAPI void*
3788 elm_entry_imf_context_get(Evas_Object *obj)
3789 {
3790    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3791    Widget_Data *wd = elm_widget_data_get(obj);
3792    if (!wd) return NULL;
3793
3794    return edje_object_part_text_imf_context_get(wd->ent, "elm.text");
3795 }
3796
3797 /* START - ANCHOR HOVER */
3798 static void
3799 _parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3800 {
3801    Widget_Data *wd = elm_widget_data_get(data);
3802    if (!wd) return;
3803    wd->anchor_hover.hover_parent = NULL;
3804 }
3805
3806 EAPI void
3807 elm_entry_anchor_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
3808 {
3809    ELM_CHECK_WIDTYPE(obj, widtype);
3810    Widget_Data *wd = elm_widget_data_get(obj);
3811    if (!wd) return;
3812    if (wd->anchor_hover.hover_parent)
3813      evas_object_event_callback_del_full(wd->anchor_hover.hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
3814    wd->anchor_hover.hover_parent = parent;
3815    if (wd->anchor_hover.hover_parent)
3816      evas_object_event_callback_add(wd->anchor_hover.hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
3817 }
3818
3819 EAPI Evas_Object *
3820 elm_entry_anchor_hover_parent_get(const Evas_Object *obj)
3821 {
3822    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3823    Widget_Data *wd = elm_widget_data_get(obj);
3824    if (!wd) return NULL;
3825    return wd->anchor_hover.hover_parent;
3826 }
3827
3828 EAPI void
3829 elm_entry_anchor_hover_style_set(Evas_Object *obj, const char *style)
3830 {
3831    ELM_CHECK_WIDTYPE(obj, widtype);
3832    Widget_Data *wd = elm_widget_data_get(obj);
3833    if (!wd) return;
3834    eina_stringshare_replace(&wd->anchor_hover.hover_style, style);
3835 }
3836
3837 EAPI const char *
3838 elm_entry_anchor_hover_style_get(const Evas_Object *obj)
3839 {
3840    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3841    Widget_Data *wd = elm_widget_data_get(obj);
3842    if (!wd) return NULL;
3843    return wd->anchor_hover.hover_style;
3844 }
3845
3846 EAPI void
3847 elm_entry_anchor_hover_end(Evas_Object *obj)
3848 {
3849    ELM_CHECK_WIDTYPE(obj, widtype);
3850    Widget_Data *wd = elm_widget_data_get(obj);
3851    if (!wd) return;
3852    if (wd->anchor_hover.hover) evas_object_del(wd->anchor_hover.hover);
3853    if (wd->anchor_hover.pop) evas_object_del(wd->anchor_hover.pop);
3854    wd->anchor_hover.hover = NULL;
3855    wd->anchor_hover.pop = NULL;
3856 }
3857
3858
3859 static void
3860 _anchor_hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3861 {
3862    elm_entry_anchor_hover_end(data);
3863 }
3864
3865 static void
3866 _entry_hover_anchor_clicked(void *data, Evas_Object *obj, void *event_info)
3867 {
3868    Widget_Data *wd = elm_widget_data_get(obj);
3869    Elm_Entry_Anchor_Info *info = event_info;
3870    Evas_Object *hover_parent;
3871    Elm_Entry_Anchor_Hover_Info ei;
3872    Evas_Coord x, w, y, h, px, py;
3873    if (!wd) return;
3874
3875    ei.anchor_info = event_info;
3876
3877    wd->anchor_hover.pop = elm_icon_add(obj);
3878    evas_object_move(wd->anchor_hover.pop, info->x, info->y);
3879    evas_object_resize(wd->anchor_hover.pop, info->w, info->h);
3880
3881    wd->anchor_hover.hover = elm_hover_add(obj);
3882    elm_widget_mirrored_set(wd->anchor_hover.hover, elm_widget_mirrored_get(obj));
3883    if (wd->anchor_hover.hover_style)
3884      elm_object_style_set(wd->anchor_hover.hover, wd->anchor_hover.hover_style);
3885
3886    hover_parent = wd->anchor_hover.hover_parent;
3887    if (!hover_parent) hover_parent = obj;
3888    elm_hover_parent_set(wd->anchor_hover.hover, hover_parent);
3889    elm_hover_target_set(wd->anchor_hover.hover, wd->anchor_hover.pop);
3890    ei.hover = wd->anchor_hover.hover;
3891
3892    evas_object_geometry_get(hover_parent, &x, &y, &w, &h);
3893    ei.hover_parent.x = x;
3894    ei.hover_parent.y = y;
3895    ei.hover_parent.w = w;
3896    ei.hover_parent.h = h;
3897    px = info->x + (info->w / 2);
3898    py = info->y + (info->h / 2);
3899    ei.hover_left = 1;
3900    if (px < (x + (w / 3))) ei.hover_left = 0;
3901    ei.hover_right = 1;
3902    if (px > (x + ((w * 2) / 3))) ei.hover_right = 0;
3903    ei.hover_top = 1;
3904    if (py < (y + (h / 3))) ei.hover_top = 0;
3905    ei.hover_bottom = 1;
3906    if (py > (y + ((h * 2) / 3))) ei.hover_bottom = 0;
3907
3908    if (elm_widget_mirrored_get(wd->anchor_hover.hover))
3909      {  /* Swap right and left because they switch sides in RTL */
3910         Eina_Bool tmp = ei.hover_left;
3911         ei.hover_left = ei.hover_right;
3912         ei.hover_right = tmp;
3913      }
3914
3915    evas_object_smart_callback_call(data, SIG_ANCHOR_HOVER_OPENED, &ei);
3916    evas_object_smart_callback_add(wd->anchor_hover.hover, "clicked", _anchor_hover_clicked, data);
3917
3918    /* FIXME: Should just check if there's any callback registered to the smart
3919     * events instead.
3920     * This is used to determine if anyone cares about the hover or not. */
3921    if (!elm_object_part_content_get(wd->anchor_hover.hover, "middle") &&
3922          !elm_object_part_content_get(wd->anchor_hover.hover, "left") &&
3923          !elm_object_part_content_get(wd->anchor_hover.hover, "right") &&
3924          !elm_object_part_content_get(wd->anchor_hover.hover, "top") &&
3925          !elm_object_part_content_get(wd->anchor_hover.hover, "bottom"))
3926      {
3927         evas_object_del(wd->anchor_hover.hover);
3928      }
3929    else
3930      {
3931         evas_object_show(wd->anchor_hover.hover);
3932      }
3933 }
3934 /* END - ANCHOR HOVER */