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