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