[entry] merge upstream content_{set,get} features
[framework/uifw/elementary.git] / src / lib / elm_entry.c
1 #include <Elementary.h>
2 #include <Elementary_Cursor.h>
3 #include "elm_priv.h"
4 #include "elm_module_priv.h"
5
6 /**
7  * @defgroup Entry Entry
8  *
9  * An entry is a convenience widget which shows
10  * a box that the user can enter text into.  Unlike a
11  * @ref Scrolled_Entry widget, entries DO NOT scroll with user
12  * input.  Entry widgets are capable of expanding past the
13  * boundaries of the window, thus resizing the window to its
14  * own length.
15  *
16  * You can also insert "items" in the entry with:
17  *
18  * \<item size=16x16 vsize=full href=emoticon/haha\>\</item\>
19  *
20  * for example. sizing can be set bu size=WxH, relsize=WxH or absize=WxH with
21  * vsize=ascent or vsize=full. the href=NAME sets the item name. Entry
22  * supports a list of emoticon names by default. These are:
23  *
24  * - emoticon/angry
25  * - emoticon/angry-shout
26  * - emoticon/crazy-laugh
27  * - emoticon/evil-laugh
28  * - emoticon/evil
29  * - emoticon/goggle-smile
30  * - emoticon/grumpy
31  * - emoticon/grumpy-smile
32  * - emoticon/guilty
33  * - emoticon/guilty-smile
34  * - emoticon/haha
35  * - emoticon/half-smile
36  * - emoticon/happy-panting
37  * - emoticon/happy
38  * - emoticon/indifferent
39  * - emoticon/kiss
40  * - emoticon/knowing-grin
41  * - emoticon/laugh
42  * - emoticon/little-bit-sorry
43  * - emoticon/love-lots
44  * - emoticon/love
45  * - emoticon/minimal-smile
46  * - emoticon/not-happy
47  * - emoticon/not-impressed
48  * - emoticon/omg
49  * - emoticon/opensmile
50  * - emoticon/smile
51  * - emoticon/sorry
52  * - emoticon/squint-laugh
53  * - emoticon/surprised
54  * - emoticon/suspicious
55  * - emoticon/tongue-dangling
56  * - emoticon/tongue-poke
57  * - emoticon/uh
58  * - emoticon/unhappy
59  * - emoticon/very-sorry
60  * - emoticon/what
61  * - emoticon/wink
62  * - emoticon/worried
63  * - emoticon/wtf
64  *
65  * These are built-in currently, but you can add your own item provieer that
66  * can create inlined objects in the text and fill the space allocated to the
67  * item with a custom object of your own.
68  *
69  * See the entry test for some more examples of use of this.
70  *
71  * Entries have functions to load a text file, display it,
72  * allowing editing of it and saving of changes back to the file loaded.
73  * Changes are written back to the original file after a short delay.
74  * The file to load and save to is specified by elm_entry_file_set().
75  *
76  * Signals that you can add callbacks for are:
77  *
78  * "changed" - The text within the entry was changed
79  * "activated" - The entry has had editing finished and changes are to be committed
80                  (generally when enter key is pressed)
81  * "press" - The entry has been clicked
82  * "longpressed" - The entry has been clicked for a couple seconds
83  * "clicked" - The entry has been clicked
84  * "clicked,double" - The entry has been double clicked
85  * "focused" - The entry has received focus
86  * "unfocused" - The entry has lost focus
87  * "selection,paste" - A paste action has occurred
88  * "selection,copy" - A copy action has occurred
89  * "selection,cut" - A cut action has occurred
90  * "selection,start" - A selection has begun
91  * "selection,changed" - The selection has changed
92  * "selection,cleared" - The selection has been cleared
93  * "cursor,changed" - The cursor has changed
94  * "anchor,clicked" - The anchor has been clicked
95  * "preedit,changed" - The preedit string has changed
96  */
97
98 /* Maximum chunk size to be inserted to the entry at once
99  * FIXME: This size is arbitrary, should probably choose a better size.
100  * Possibly also find a way to set it to a low value for weak computers,
101  * and to a big value for better computers. */
102 #define _CHUNK_SIZE 10000
103
104 typedef struct _Mod_Api Mod_Api;
105
106 typedef struct _Widget_Data Widget_Data;
107 typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
108 typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
109 typedef struct _Elm_Entry_Text_Filter Elm_Entry_Text_Filter;
110
111 struct _Widget_Data
112 {
113    Evas_Object *ent, *scroller, *end, *icon;
114    Evas_Object *bg;
115    Evas_Object *hoversel;
116    Evas_Object *hover;
117    Evas_Object *layout;
118    Evas_Object *list;
119    Evas_Object *mgf_proxy;
120    Evas_Object *mgf_clip;
121    Evas_Object *mgf_bg;
122    Evas_Coord mgf_height;
123    float mgf_scale;
124    int mgf_type;
125    Ecore_Job *deferred_recalc_job;
126    Ecore_Event_Handler *sel_notify_handler;
127    Ecore_Event_Handler *sel_clear_handler;
128    Ecore_Timer *delay_write;
129    /* for deferred appending */
130    Ecore_Idler *append_text_idler;
131    char *append_text_left;
132    int append_text_position;
133    int append_text_len;
134    /* Only for clipboard */
135    const char *cut_sel;
136    const char *text;
137    const char *password_text;
138    Evas_Coord wrap_w;
139    const char *file;
140    Elm_Text_Format format;
141    Evas_Coord lastw, entmw, entmh;
142    Evas_Coord downx, downy;
143    Evas_Coord cx, cy, cw, ch;
144    Eina_List *items;
145    Eina_List *item_providers;
146    Eina_List *text_filters;
147    Eina_List *match_list;
148    Ecore_Job *matchlist_job;
149    int matchlist_threshold;
150    Ecore_Job *hovdeljob;
151    Mod_Api *api; // module api if supplied
152    int cursor_pos;
153    Elm_Scroller_Policy policy_h, policy_v;
154    Elm_Wrap_Type linewrap;
155    Elm_Input_Panel_Layout input_panel_layout;
156    Eina_Bool changed : 1;
157    Eina_Bool single_line : 1;
158    Eina_Bool password : 1;
159    Eina_Bool editable : 1;
160    Eina_Bool selection_asked : 1;
161    Eina_Bool have_selection : 1;
162    Eina_Bool selmode : 1;
163    Eina_Bool deferred_cur : 1;
164    Eina_Bool cur_changed : 1;
165    Eina_Bool disabled : 1;
166    Eina_Bool double_clicked : 1;
167    Eina_Bool long_pressed : 1;
168    Eina_Bool context_menu : 1;
169    Eina_Bool drag_selection_asked : 1;
170    Eina_Bool bgcolor : 1;
171    Eina_Bool can_write : 1;
172    Eina_Bool autosave : 1;
173    Eina_Bool textonly : 1;
174    Eina_Bool usedown : 1;
175    Eina_Bool scroll : 1;
176    Eina_Bool autoreturnkey : 1;
177    Eina_Bool input_panel_enable : 1;
178    Eina_Bool autocapital : 1;
179    Eina_Bool autoperiod : 1;
180    Eina_Bool matchlist_list_clicked : 1;
181    Eina_Bool matchlist_case_sensitive : 1;
182 };
183
184 struct _Elm_Entry_Context_Menu_Item
185 {
186    Evas_Object *obj;
187    const char *label;
188    const char *icon_file;
189    const char *icon_group;
190    Elm_Icon_Type icon_type;
191    Evas_Smart_Cb func;
192    void *data;
193 };
194
195 struct _Elm_Entry_Item_Provider
196 {
197    Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item);
198    void *data;
199 };
200
201 struct _Elm_Entry_Text_Filter
202 {
203    void (*func) (void *data, Evas_Object *entry, char **text);
204    void *data;
205 };
206
207 typedef enum _Length_Unit
208 {
209    LENGTH_UNIT_CHAR,
210    LENGTH_UNIT_BYTE,
211    LENGTH_UNIT_LAST
212 } Length_Unit;
213
214 static const char *widtype = NULL;
215 // start for cbhm
216 static Evas_Object *cnpwidgetdata = NULL;
217 // end for cbhm
218
219 #ifdef HAVE_ELEMENTARY_X
220 static Eina_Bool _drag_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *);
221 #endif
222 static void _del_hook(Evas_Object *obj);
223 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
224 static void _theme_hook(Evas_Object *obj);
225 static void _disable_hook(Evas_Object *obj);
226 static void _sizing_eval(Evas_Object *obj);
227 static void _on_focus_hook(void *data, Evas_Object *obj);
228 static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
229 static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
230 static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
231 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
232 static const char *_getbase(Evas_Object *obj);
233 static void _signal_entry_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
234 static void _signal_selection_start(void *data, Evas_Object *obj, const char *emission, const char *source);
235 static void _signal_selection_end(void *data, Evas_Object *obj, const char *emission, const char *source);
236 static void _signal_selection_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
237 static void _signal_selection_cleared(void *data, Evas_Object *obj, const char *emission, const char *source);
238 static void _signal_handler_move_start(void *data, Evas_Object *obj, const char *emission, const char *source);
239 static void _signal_handler_move_end(void *data, Evas_Object *obj, const char *emission, const char *source);
240 static void _signal_handler_moving(void *data, Evas_Object *obj, const char *emission, const char *source);
241 static void _signal_entry_paste_request(void *data, Evas_Object *obj, const char *emission, const char *source);
242 static void _signal_entry_copy_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
243 static void _signal_entry_cut_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
244 static void _signal_cursor_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
245 static void _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit unit);
246 static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag);
247 static int _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag);
248 static int _entry_length_get(Evas_Object *obj);
249 static void _magnifier_create(void *data);
250 static void _magnifier_show(void *data);
251 static void _magnifier_hide(void *data);
252 static void _magnifier_move(void *data);
253
254 static const char SIG_CHANGED[] = "changed";
255 static const char SIG_ACTIVATED[] = "activated";
256 static const char SIG_PRESS[] = "press";
257 static const char SIG_LONGPRESSED[] = "longpressed";
258 static const char SIG_CLICKED[] = "clicked";
259 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
260 static const char SIG_FOCUSED[] = "focused";
261 static const char SIG_UNFOCUSED[] = "unfocused";
262 static const char SIG_SELECTION_PASTE[] = "selection,paste";
263 static const char SIG_SELECTION_COPY[] = "selection,copy";
264 static const char SIG_SELECTION_CUT[] = "selection,cut";
265 static const char SIG_SELECTION_START[] = "selection,start";
266 static const char SIG_SELECTION_CHANGED[] = "selection,changed";
267 static const char SIG_SELECTION_CLEARED[] = "selection,cleared";
268 static const char SIG_CURSOR_CHANGED[] = "cursor,changed";
269 static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
270 static const char SIG_MATCHLIST_CLICKED[] = "matchlist,clicked";
271 static const char SIG_PREEDIT_CHANGED[] = "preedit,changed";
272 static const Evas_Smart_Cb_Description _signals[] = {
273   {SIG_CHANGED, ""},
274   {SIG_ACTIVATED, ""},
275   {SIG_PRESS, ""},
276   {SIG_LONGPRESSED, ""},
277   {SIG_CLICKED, ""},
278   {SIG_CLICKED_DOUBLE, ""},
279   {SIG_FOCUSED, ""},
280   {SIG_UNFOCUSED, ""},
281   {SIG_SELECTION_PASTE, ""},
282   {SIG_SELECTION_COPY, ""},
283   {SIG_SELECTION_CUT, ""},
284   {SIG_SELECTION_START, ""},
285   {SIG_SELECTION_CHANGED, ""},
286   {SIG_SELECTION_CLEARED, ""},
287   {SIG_CURSOR_CHANGED, ""},
288   {SIG_ANCHOR_CLICKED, ""},
289   {SIG_PREEDIT_CHANGED, ""},
290   {SIG_MATCHLIST_CLICKED, ""},
291   {NULL, NULL}
292 };
293
294 typedef enum _Elm_Entry_Magnifier_Type
295 {
296    _ENTRY_MAGNIFIER_FIXEDSIZE = 0,
297    _ENTRY_MAGNIFIER_FILLWIDTH,
298    _ENTRY_MAGNIFIER_CIRCULAR,
299 } Elm_Entry_Magnifier_Type;
300
301
302 static Eina_List *entries = NULL;
303
304 struct _Mod_Api
305 {
306    void (*obj_hook) (Evas_Object *obj);
307    void (*obj_unhook) (Evas_Object *obj);
308    void (*obj_longpress) (Evas_Object *obj);
309    void (*obj_hidemenu) (Evas_Object *obj);
310    void (*obj_mouseup) (Evas_Object *obj);
311 };
312
313 static Mod_Api *
314 _module(Evas_Object *obj __UNUSED__)
315 {
316    static Elm_Module *m = NULL;
317    if (m) goto ok; // already found - just use
318    if (!(m = _elm_module_find_as("entry/api"))) return NULL;
319    // get module api
320    m->api = malloc(sizeof(Mod_Api));
321    if (!m->api) return NULL;
322    ((Mod_Api *)(m->api)      )->obj_hook = // called on creation
323       _elm_module_symbol_get(m, "obj_hook");
324    ((Mod_Api *)(m->api)      )->obj_unhook = // called on deletion
325       _elm_module_symbol_get(m, "obj_unhook");
326    ((Mod_Api *)(m->api)      )->obj_longpress = // called on long press menu
327       _elm_module_symbol_get(m, "obj_longpress");
328    ((Mod_Api *)(m->api)      )->obj_hidemenu = // called on hide menu
329       _elm_module_symbol_get(m, "obj_hidemenu");
330    ((Mod_Api *)(m->api)      )->obj_mouseup = // called on mouseup
331       _elm_module_symbol_get(m, "obj_mouseup");
332 ok: // ok - return api
333    return m->api;
334 }
335
336 static char *
337 _buf_append(char *buf, const char *str, int *len, int *alloc)
338 {
339    int len2 = strlen(str);
340    if ((*len + len2) >= *alloc)
341      {
342         char *buf2 = realloc(buf, *alloc + len2 + 512);
343         if (!buf2) return NULL;
344         buf = buf2;
345         *alloc += (512 + len2);
346      }
347    strcpy(buf + *len, str);
348    *len += len2;
349    return buf;
350 }
351
352 static char *
353 _load_file(const char *file)
354 {
355    FILE *f;
356    size_t size;
357    int alloc = 0, len = 0;
358    char *text = NULL, buf[16384 + 1];
359
360    f = fopen(file, "rb");
361    if (!f) return NULL;
362    while ((size = fread(buf, 1, sizeof(buf) - 1, f)))
363      {
364         char *tmp_text;
365         buf[size] = 0;
366         tmp_text = _buf_append(text, buf, &len, &alloc);
367         if (!tmp_text) break;
368         text = tmp_text;
369      }
370    fclose(f);
371    return text;
372 }
373
374 static char *
375 _load_plain(const char *file)
376 {
377    char *text;
378
379    text = _load_file(file);
380    if (text)
381      {
382         char *text2;
383
384         text2 = elm_entry_utf8_to_markup(text);
385         free(text);
386         return text2;
387      }
388    return NULL;
389 }
390
391 static void
392 _load(Evas_Object *obj)
393 {
394    Widget_Data *wd = elm_widget_data_get(obj);
395    char *text;
396    if (!wd) return;
397    if (!wd->file)
398      {
399         elm_entry_entry_set(obj, "");
400         return;
401      }
402    switch (wd->format)
403      {
404       case ELM_TEXT_FORMAT_PLAIN_UTF8:
405          text = _load_plain(wd->file);
406          break;
407       case ELM_TEXT_FORMAT_MARKUP_UTF8:
408          text = _load_file(wd->file);
409          break;
410       default:
411          text = NULL;
412          break;
413      }
414    if (text)
415      {
416         elm_entry_entry_set(obj, text);
417         free(text);
418      }
419    else
420      elm_entry_entry_set(obj, "");
421 }
422
423 static void
424 _save_markup_utf8(const char *file, const char *text)
425 {
426    FILE *f;
427
428    if ((!text) || (!text[0]))
429      {
430         ecore_file_unlink(file);
431         return;
432      }
433    f = fopen(file, "wb");
434    if (!f)
435      {
436         // FIXME: report a write error
437         return;
438      }
439    fputs(text, f); // FIXME: catch error
440    fclose(f);
441 }
442
443 static void
444 _save_plain_utf8(const char *file, const char *text)
445 {
446    char *text2;
447
448    text2 = elm_entry_markup_to_utf8(text);
449    if (!text2)
450      return;
451    _save_markup_utf8(file, text2);
452    free(text2);
453 }
454
455 static void
456 _save(Evas_Object *obj)
457 {
458    Widget_Data *wd = elm_widget_data_get(obj);
459    if (!wd) return;
460    if (!wd->file) return;
461    switch (wd->format)
462      {
463       case ELM_TEXT_FORMAT_PLAIN_UTF8:
464          _save_plain_utf8(wd->file, elm_entry_entry_get(obj));
465          break;
466       case ELM_TEXT_FORMAT_MARKUP_UTF8:
467          _save_markup_utf8(wd->file, elm_entry_entry_get(obj));
468          break;
469       default:
470          break;
471      }
472 }
473
474 static Eina_Bool
475 _delay_write(void *data)
476 {
477    Widget_Data *wd = elm_widget_data_get(data);
478    if (!wd) return ECORE_CALLBACK_CANCEL;
479    _save(data);
480    wd->delay_write = NULL;
481    return ECORE_CALLBACK_CANCEL;
482 }
483
484 static Elm_Entry_Text_Filter *
485 _filter_new(void (*func) (void *data, Evas_Object *entry, char **text), void *data)
486 {
487    Elm_Entry_Text_Filter *tf = ELM_NEW(Elm_Entry_Text_Filter);
488    if (!tf) return NULL;
489
490    tf->func = func;
491    if (func == elm_entry_filter_limit_size)
492      {
493         Elm_Entry_Filter_Limit_Size *lim = data, *lim2;
494
495         if (!data)
496           {
497              free(tf);
498              return NULL;
499           }
500         lim2 = malloc(sizeof(Elm_Entry_Filter_Limit_Size));
501         if (!lim2)
502           {
503              free(tf);
504              return NULL;
505           }
506         memcpy(lim2, lim, sizeof(Elm_Entry_Filter_Limit_Size));
507         tf->data = lim2;
508      }
509    else if (func == elm_entry_filter_accept_set)
510      {
511         Elm_Entry_Filter_Accept_Set *as = data, *as2;
512
513         if (!data)
514           {
515              free(tf);
516              return NULL;
517           }
518         as2 = malloc(sizeof(Elm_Entry_Filter_Accept_Set));
519         if (!as2)
520           {
521              free(tf);
522              return NULL;
523           }
524         if (as->accepted)
525           as2->accepted = eina_stringshare_add(as->accepted);
526         else
527           as2->accepted = NULL;
528         if (as->rejected)
529           as2->rejected = eina_stringshare_add(as->rejected);
530         else
531           as2->rejected = NULL;
532         tf->data = as2;
533      }
534    else
535      tf->data = data;
536    return tf;
537 }
538
539 static void
540 _filter_free(Elm_Entry_Text_Filter *tf)
541 {
542    if (tf->func == elm_entry_filter_limit_size)
543      {
544         Elm_Entry_Filter_Limit_Size *lim = tf->data;
545         if (lim) free(lim);
546      }
547    else if (tf->func == elm_entry_filter_accept_set)
548      {
549         Elm_Entry_Filter_Accept_Set *as = tf->data;
550         if (as)
551           {
552              if (as->accepted) eina_stringshare_del(as->accepted);
553              if (as->rejected) eina_stringshare_del(as->rejected);
554              free(as);
555           }
556      }
557    free(tf);
558 }
559
560 static void
561 _del_pre_hook(Evas_Object *obj)
562 {
563    Widget_Data *wd = elm_widget_data_get(obj);
564    if (!wd) return;
565    if (wd->delay_write)
566      {
567         ecore_timer_del(wd->delay_write);
568         wd->delay_write = NULL;
569         if (wd->autosave) _save(obj);
570      }
571 }
572
573 static void
574 _del_hook(Evas_Object *obj)
575 {
576    Widget_Data *wd = elm_widget_data_get(obj);
577    Elm_Entry_Context_Menu_Item *it;
578    Elm_Entry_Item_Provider *ip;
579    Elm_Entry_Text_Filter *tf;
580
581    if (wd->file) eina_stringshare_del(wd->file);
582
583    if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
584    if ((wd->api) && (wd->api->obj_unhook)) wd->api->obj_unhook(obj); // module - unhook
585
586    entries = eina_list_remove(entries, obj);
587 #ifdef HAVE_ELEMENTARY_X
588    if (wd->sel_notify_handler)
589      ecore_event_handler_del(wd->sel_notify_handler);
590    if (wd->sel_clear_handler)
591      ecore_event_handler_del(wd->sel_clear_handler);
592 #endif
593    if (wd->cut_sel) eina_stringshare_del(wd->cut_sel);
594    if (wd->text) eina_stringshare_del(wd->text);
595    if (wd->password_text) eina_stringshare_del(wd->password_text);
596    if (wd->bg) evas_object_del(wd->bg);
597    if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
598    if (wd->append_text_idler)
599      {
600         ecore_idler_del(wd->append_text_idler);
601         free(wd->append_text_left);
602         wd->append_text_left = NULL;
603         wd->append_text_idler = NULL;
604      }
605    if (wd->matchlist_job) ecore_job_del(wd->matchlist_job);
606    if (wd->mgf_proxy) evas_object_del(wd->mgf_proxy);
607    if (wd->mgf_bg) evas_object_del(wd->mgf_bg);
608    if (wd->mgf_clip) evas_object_del(wd->mgf_clip);
609
610    EINA_LIST_FREE(wd->items, it)
611      {
612         eina_stringshare_del(it->label);
613         eina_stringshare_del(it->icon_file);
614         eina_stringshare_del(it->icon_group);
615         free(it);
616      }
617    EINA_LIST_FREE(wd->item_providers, ip)
618      {
619         free(ip);
620      }
621    EINA_LIST_FREE(wd->text_filters, tf)
622      {
623         _filter_free(tf);
624      }
625    if (wd->delay_write) ecore_timer_del(wd->delay_write);
626    free(wd);
627 }
628
629 static void
630 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
631 {
632    Widget_Data *wd = elm_widget_data_get(obj);
633    edje_object_mirrored_set(wd->ent, rtl);
634 }
635
636 static void
637 _theme_hook(Evas_Object *obj)
638 {
639    Widget_Data *wd = elm_widget_data_get(obj);
640    const char *t;
641    Ecore_IMF_Context *ic;
642    _elm_widget_mirrored_reload(obj);
643    _mirrored_set(obj, elm_widget_mirrored_get(obj));
644
645    t = eina_stringshare_add(elm_entry_entry_get(obj));
646    _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
647    if (_elm_config->desktop_entry)
648      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
649    elm_entry_entry_set(obj, t);
650    eina_stringshare_del(t);
651    if (elm_widget_disabled_get(obj))
652      edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
653    edje_object_part_text_input_panel_enabled_set(wd->ent, "elm.text", wd->input_panel_enable);
654    elm_entry_cursor_pos_set(obj, wd->cursor_pos);
655    if (elm_widget_focus_get(obj))
656      edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
657    edje_object_message_signal_process(wd->ent);
658    edje_object_scale_set(wd->ent, elm_widget_scale_get(obj) * _elm_config->scale);
659    elm_smart_scroller_mirrored_set(wd->scroller, elm_widget_mirrored_get(obj));
660    elm_smart_scroller_object_theme_set(obj, wd->scroller, "scroller", "entry",
661                                        elm_widget_style_get(obj));
662    if (wd->scroll)
663      {
664         const char *str;
665         Evas_Object *edj;
666
667         edj = elm_smart_scroller_edje_object_get(wd->scroller);
668         str = edje_object_data_get(edj, "focus_highlight");
669         if ((str) && (!strcmp(str, "on")))
670            elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
671         else
672            elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
673      }
674
675    if (wd->password)
676      {
677         edje_object_part_text_autoperiod_set(wd->ent, "elm.text", EINA_FALSE);
678         edje_object_part_text_autocapitalization_set(wd->ent, "elm.text", EINA_FALSE);
679      }
680    else
681      {
682         edje_object_part_text_autoperiod_set(wd->ent, "elm.text", wd->autoperiod);
683         edje_object_part_text_autocapitalization_set(wd->ent, "elm.text", wd->autocapital);
684      }
685
686    ic = edje_object_part_text_imf_context_get(wd->ent, "elm.text");
687    if (ic)
688      {
689         ecore_imf_context_input_panel_layout_set(ic, (Ecore_IMF_Input_Panel_Layout)wd->input_panel_layout);
690      }
691
692    _sizing_eval(obj);
693 }
694
695 static void
696 _disable_hook(Evas_Object *obj)
697 {
698    Widget_Data *wd = elm_widget_data_get(obj);
699
700    if (elm_widget_disabled_get(obj))
701      {
702         edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
703         wd->disabled = EINA_TRUE;
704      }
705    else
706      {
707         edje_object_signal_emit(wd->ent, "elm,state,enabled", "elm");
708         wd->disabled = EINA_FALSE;
709      }
710 }
711
712 static void
713 _recalc_cursor_geometry(Evas_Object *obj)
714 {
715    Widget_Data *wd = elm_widget_data_get(obj);
716    if (!wd) return;
717    evas_object_smart_callback_call(obj, SIG_CURSOR_CHANGED, NULL);
718    if (!elm_object_focus_get(obj)) return;
719    if (!wd->deferred_recalc_job)
720      {
721         Evas_Coord cx, cy, cw, ch;
722         edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
723               &cx, &cy, &cw, &ch);
724         if (wd->cur_changed)
725           {
726              elm_widget_show_region_set(obj, cx, cy, cw, ch, EINA_FALSE);
727              wd->cur_changed = EINA_FALSE;
728           }
729      }
730    else
731       wd->deferred_cur = EINA_TRUE;
732 }
733
734 static void
735 _elm_win_recalc_job(void *data)
736 {
737    Widget_Data *wd = elm_widget_data_get(data);
738    Evas_Coord minh = -1, resw = -1, minw = -1, fw = 0, fh = 0;
739    if (!wd) return;
740    wd->deferred_recalc_job = NULL;
741
742    evas_object_geometry_get(wd->ent, NULL, NULL, &resw, NULL);
743    edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, resw, 0);
744    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
745    wd->entmw = minw;
746    wd->entmh = minh;
747    /* This is a hack to workaround the way min size hints are treated.
748     * If the minimum width is smaller than the restricted width, it means
749     * the mininmum doesn't matter. */
750    if (minw <= resw)
751      {
752         Evas_Coord ominw = -1;
753         evas_object_size_hint_min_get(data, &ominw, NULL);
754         minw = ominw;
755      }
756
757    elm_coords_finger_size_adjust(1, &fw, 1, &fh);
758    if (wd->scroll)
759      {
760         Evas_Coord vmw = 0, vmh = 0;
761
762         edje_object_size_min_calc
763            (elm_smart_scroller_edje_object_get(wd->scroller),
764                &vmw, &vmh);
765         if (wd->single_line)
766           {
767              evas_object_size_hint_min_set(data, vmw, minh + vmh);
768              evas_object_size_hint_max_set(data, -1, minh + vmh);
769           }
770         else
771           {
772              evas_object_size_hint_min_set(data, vmw, vmh);
773              evas_object_size_hint_max_set(data, -1, -1);
774           }
775      }
776    else
777      {
778         if (wd->single_line)
779           {
780              evas_object_size_hint_min_set(data, minw, minh);
781              evas_object_size_hint_max_set(data, -1, minh);
782           }
783         else
784           {
785              evas_object_size_hint_min_set(data, fw, minh);
786              evas_object_size_hint_max_set(data, -1, -1);
787           }
788      }
789
790    if ((wd->deferred_cur) && (elm_object_focus_get(data)))
791      {
792         Evas_Coord cx, cy, cw, ch;
793         edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
794                                                   &cx, &cy, &cw, &ch);
795         if (wd->cur_changed)
796           {
797              elm_widget_show_region_set(data, cx, cy, cw, ch, EINA_FALSE);
798              wd->cur_changed = EINA_FALSE;
799           }
800      }
801 }
802
803 static void
804 _sizing_eval(Evas_Object *obj)
805 {
806    Widget_Data *wd = elm_widget_data_get(obj);
807    Evas_Coord minw = -1, minh = -1;
808    Evas_Coord resw, resh;
809    if (!wd) return;
810
811    evas_object_geometry_get(obj, NULL, NULL, &resw, &resh);
812    if (wd->linewrap)
813      {
814         if ((resw == wd->lastw) && (!wd->changed)) return;
815         wd->changed = EINA_FALSE;
816         wd->lastw = resw;
817         if (wd->scroll)
818           {
819              Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
820
821              evas_object_resize(wd->scroller, resw, resh);
822              edje_object_size_min_calc
823                 (elm_smart_scroller_edje_object_get(wd->scroller),
824                     &vmw, &vmh);
825              elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
826              edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, vw, 0);
827              wd->entmw = minw;
828              wd->entmh = minh;
829              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
830
831              if ((minw > 0) && (vw < minw)) vw = minw;
832              if (minh > vh) vh = minh;
833
834              if (wd->single_line) h = vmh + minh;
835              else h = vmh;
836              evas_object_resize(wd->ent, vw, vh);
837              evas_object_size_hint_min_get(obj, &w, NULL);
838              evas_object_size_hint_min_set(obj, w, h);
839              if (wd->single_line)
840                 evas_object_size_hint_max_set(obj, -1, h);
841              else
842                 evas_object_size_hint_max_set(obj, -1, -1);
843           }
844         else
845           {
846              if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
847              wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
848           }
849      }
850    else
851      {
852         if (!wd->changed) return;
853         wd->changed = EINA_FALSE;
854         wd->lastw = resw;
855         if (wd->scroll)
856           {
857              Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
858
859              edje_object_size_min_calc(wd->ent, &minw, &minh);
860              wd->entmw = minw;
861              wd->entmh = minh;
862              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
863
864              elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
865
866              if ((minw > 0) && (vw < minw)) vw = minw;
867              if (minh > 0) vh = minh;
868
869              evas_object_resize(wd->ent, vw, vh);
870              edje_object_size_min_calc
871                 (elm_smart_scroller_edje_object_get(wd->scroller),
872                     &vmw, &vmh);
873              if (wd->single_line) h = vmh + minh;
874              else h = vmh;
875              evas_object_size_hint_min_get(obj, &w, NULL);
876              evas_object_size_hint_min_set(obj, w, h);
877              if (wd->single_line)
878                 evas_object_size_hint_max_set(obj, -1, h);
879              else
880                 evas_object_size_hint_max_set(obj, -1, -1);
881           }
882         else
883           {
884              edje_object_size_min_calc(wd->ent, &minw, &minh);
885              wd->entmw = minw;
886              wd->entmh = minh;
887              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
888              evas_object_size_hint_min_set(obj, minw, minh);
889              if (wd->single_line)
890                 evas_object_size_hint_max_set(obj, -1, minh);
891              else
892                 evas_object_size_hint_max_set(obj, -1, -1);
893           }
894      }
895
896    _recalc_cursor_geometry(obj);
897 }
898
899 static void
900 _check_enable_returnkey(Evas_Object *obj)
901 {
902    Widget_Data *wd = elm_widget_data_get(obj);
903    if (!wd) return;
904
905    Ecore_IMF_Context *ic = elm_entry_imf_context_get(obj);
906    if (!ic) return;
907
908    if (!wd->autoreturnkey) return;
909
910    if (_entry_length_get(obj) == 0)
911      {
912         ecore_imf_context_input_panel_key_disabled_set(ic, ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, ECORE_IMF_INPUT_PANEL_KEY_ENTER, EINA_TRUE);
913      }
914    else
915      {
916         ecore_imf_context_input_panel_key_disabled_set(ic, ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, ECORE_IMF_INPUT_PANEL_KEY_ENTER, EINA_FALSE);
917      }
918 }
919
920 static void
921 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
922 {
923    Widget_Data *wd = elm_widget_data_get(obj);
924    Evas_Object *top = elm_widget_top_get(obj);
925    if (!wd) return;
926    if (elm_widget_focus_get(obj))
927      {
928         printf("[Elm_entry::Focused] obj : %p\n", obj);
929         evas_object_focus_set(wd->ent, EINA_TRUE);
930         edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
931         if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
932         evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
933         _check_enable_returnkey(obj);
934         wd->mgf_type = _ENTRY_MAGNIFIER_FIXEDSIZE;
935      }
936    else
937      {
938         printf("[Elm_entry::Unfocused] obj : %p\n", obj);
939         edje_object_signal_emit(wd->ent, "elm,action,unfocus", "elm");
940         evas_object_focus_set(wd->ent, EINA_FALSE);
941         if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
942         evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
943
944         if ((wd->api) && (wd->api->obj_hidemenu))
945           {
946              wd->api->obj_hidemenu(obj);
947           }
948      }
949 }
950
951
952 static void
953 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
954 {
955    Widget_Data *wd = elm_widget_data_get(obj);
956    Evas_Object *edje;
957    if ((!wd) || (!content)) return;
958
959    edje = elm_smart_scroller_edje_object_get(wd->scroller);
960    if (!strcmp(part, "elm.swallow.icon"))
961      {
962         if (wd->icon)
963           evas_object_del(wd->icon);
964         wd->icon = content;
965         edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
966      }
967    else if (!strcmp(part, "elm.swallow.end"))
968      {
969         if (wd->end)
970           evas_object_del(wd->end);
971         wd->end = content;
972         edje_object_signal_emit(edje, "elm,action,show,end", "elm");
973      }
974    evas_event_freeze(evas_object_evas_get(obj));
975    elm_widget_sub_object_add(obj, content);
976    edje_object_part_swallow(edje, part, content);
977    _sizing_eval(obj);
978    evas_event_thaw(evas_object_evas_get(obj));
979    evas_event_thaw_eval(evas_object_evas_get(obj));
980 }
981
982 static Evas_Object *
983 _content_unset_hook(Evas_Object *obj, const char *part)
984 {
985    Widget_Data *wd = elm_widget_data_get(obj);
986    Evas_Object *content, *edje;
987    if (!wd) return NULL;
988
989    edje = elm_smart_scroller_edje_object_get(wd->scroller);
990    if (!strcmp(part, "elm.swallow.icon"))
991      {
992         wd->icon = NULL;
993         edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
994      }
995    else if (!strcmp(part, "elm.swallow.end"))
996      {
997         wd->end = NULL;
998         edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
999      }
1000
1001    content = edje_object_part_swallow_get(edje, part);
1002    edje_object_part_swallow(edje, part, NULL);
1003    if (!content) return NULL;
1004    evas_event_freeze(evas_object_evas_get(obj));
1005    elm_widget_sub_object_del(obj, content);
1006    edje_object_part_unswallow(wd->ent, content);
1007    _sizing_eval(obj);
1008    evas_event_thaw(evas_object_evas_get(obj));
1009    evas_event_thaw_eval(evas_object_evas_get(obj));
1010
1011    return content;
1012 }
1013
1014 static Evas_Object *
1015 _content_get_hook(const Evas_Object *obj, const char *part)
1016 {
1017    Widget_Data *wd = elm_widget_data_get(obj);
1018    Evas_Object *content = NULL, *edje;
1019    if (!wd) return NULL;
1020
1021    if (!strcmp(part, "elm.swallow.icon"))
1022      return wd->icon;
1023    if (!strcmp(part, "elm.swallow.end"))
1024      return wd->end;
1025
1026    edje = elm_smart_scroller_edje_object_get(wd->scroller);
1027    if (edje)
1028      content = edje_object_part_swallow_get(edje, part);
1029    return content;
1030 }
1031
1032
1033 static void
1034 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
1035 {
1036    Widget_Data *wd = elm_widget_data_get(obj);
1037    if (!wd) return;
1038    edje_object_signal_emit(wd->ent, emission, source);
1039    if (wd->scroller)
1040       edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scroller),
1041                               emission, source);
1042 }
1043
1044 static void
1045 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
1046 {
1047    Widget_Data *wd = elm_widget_data_get(obj);
1048    if (!wd) return;
1049    edje_object_signal_callback_add(wd->ent, emission, source, func_cb, data);
1050    if (wd->scroller)
1051       edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scroller),
1052                                       emission, source, func_cb, data);
1053 }
1054
1055 static void
1056 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
1057 {
1058    Widget_Data *wd = elm_widget_data_get(obj);
1059    edje_object_signal_callback_del_full(wd->ent, emission, source, func_cb,
1060                                         data);
1061    if (wd->scroller)
1062       edje_object_signal_callback_del_full(elm_smart_scroller_edje_object_get(wd->scroller),
1063                                            emission, source, func_cb, data);
1064 }
1065
1066 static void
1067 _on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1068 {
1069    Widget_Data *wd = elm_widget_data_get(obj);
1070    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
1071 }
1072
1073 static void
1074 _focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1075 {
1076    Widget_Data *wd = elm_widget_data_get(obj);
1077    if (wd->scroll)
1078       elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
1079 }
1080
1081 static void
1082 _show_region_hook(void *data, Evas_Object *obj)
1083 {
1084    Widget_Data *wd = elm_widget_data_get(data);
1085    Evas_Coord x, y, w, h;
1086    if (!wd) return;
1087    elm_widget_show_region_get(obj, &x, &y, &w, &h);
1088    if (wd->scroll)
1089      elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
1090 }
1091
1092 static void
1093 _sub_del(void *data, Evas_Object *obj, void *event_info)
1094 {
1095    Widget_Data *wd = data;
1096    Evas_Object *sub = event_info;
1097    Evas_Object *edje;
1098
1099    edje = elm_smart_scroller_edje_object_get(wd->scroller);
1100    if (sub == wd->icon)
1101      {
1102         wd->icon = NULL;
1103         if (edje)
1104           edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
1105      }
1106    else if (sub == wd->end)
1107      {
1108         wd->end = NULL;
1109         if (edje)
1110           edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
1111      }
1112    _sizing_eval(obj);
1113 }
1114
1115 static void
1116 _hoversel_position(Evas_Object *obj)
1117 {
1118    Widget_Data *wd = elm_widget_data_get(obj);
1119    Evas_Coord cx, cy, cw, ch, x, y, mw, mh;
1120    if (!wd) return;
1121
1122    cx = cy = 0;
1123    cw = ch = 1;
1124    evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
1125    if (wd->usedown)
1126      {
1127         cx = wd->downx - x;
1128         cy = wd->downy - y;
1129         cw = 1;
1130         ch = 1;
1131      }
1132    else
1133      edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
1134                                                &cx, &cy, &cw, &ch);
1135    evas_object_size_hint_min_get(wd->hoversel, &mw, &mh);
1136    if (cw < mw)
1137      {
1138         cx += (cw - mw) / 2;
1139         cw = mw;
1140      }
1141    if (ch < mh)
1142      {
1143         cy += (ch - mh) / 2;
1144         ch = mh;
1145      }
1146    evas_object_move(wd->hoversel, x + cx, y + cy);
1147    evas_object_resize(wd->hoversel, cw, ch);
1148 }
1149
1150 static void
1151 _move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1152 {
1153    Widget_Data *wd = elm_widget_data_get(data);
1154
1155    if (wd->hoversel) _hoversel_position(data);
1156 }
1157
1158 static void
1159 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1160 {
1161    Widget_Data *wd = elm_widget_data_get(data);
1162    if (!wd) return;
1163
1164    if (wd->linewrap)
1165      {
1166         _sizing_eval(data);
1167      }
1168    else if (wd->scroll)
1169      {
1170         Evas_Coord vw = 0, vh = 0;
1171
1172         elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
1173         if (vw < wd->entmw) vw = wd->entmw;
1174         if (vh < wd->entmh) vh = wd->entmh;
1175         evas_object_resize(wd->ent, vw, vh);
1176      }
1177    if (wd->hoversel) _hoversel_position(data);
1178 }
1179
1180 static void
1181 _hover_del(void *data)
1182 {
1183    Widget_Data *wd = elm_widget_data_get(data);
1184    if (!wd) return;
1185
1186    if (wd->hoversel)
1187      {
1188         evas_object_del(wd->hoversel);
1189         wd->hoversel = NULL;
1190      }
1191    wd->hovdeljob = NULL;
1192 }
1193
1194 static void
1195 _dismissed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1196 {
1197    Widget_Data *wd = elm_widget_data_get(data);
1198    if (!wd) return;
1199    wd->usedown = 0;
1200    if (wd->hoversel) evas_object_hide(wd->hoversel);
1201    if (wd->selmode)
1202      {
1203         if (!_elm_config->desktop_entry)
1204           {
1205              if (!wd->password)
1206                edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
1207           }
1208      }
1209    elm_widget_scroll_freeze_pop(data);
1210    if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
1211    wd->hovdeljob = ecore_job_add(_hover_del, data);
1212 }
1213
1214 static void
1215 _selectall(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1216 {
1217    Widget_Data *wd = elm_widget_data_get(data);
1218    if (!wd) return;
1219    wd->selmode = EINA_TRUE;
1220    edje_object_part_text_select_none(wd->ent, "elm.text");
1221    edje_object_signal_emit(wd->ent, "elm,state,select,on", "elm");
1222    edje_object_part_text_select_all(wd->ent, "elm.text");
1223    elm_object_scroll_freeze_pop(data);
1224 }
1225
1226 static void
1227 _select(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1228 {
1229    Widget_Data *wd = elm_widget_data_get(data);
1230    if (!wd) return;
1231    wd->selmode = EINA_TRUE;
1232    edje_object_part_text_select_none(wd->ent, "elm.text");
1233    if (!_elm_config->desktop_entry)
1234      {
1235         if (!wd->password)
1236           edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
1237      }
1238    edje_object_signal_emit(wd->ent, "elm,state,select,on", "elm");
1239    if (!_elm_config->desktop_entry)
1240       elm_object_scroll_freeze_pop(data);
1241       //elm_widget_scroll_hold_push(data);
1242 }
1243
1244 static void
1245 _paste(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1246 {
1247    Widget_Data *wd = elm_widget_data_get(data);
1248    if (!wd) return;
1249    evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
1250    if (wd->sel_notify_handler)
1251      {
1252 #ifdef HAVE_ELEMENTARY_X
1253         Elm_Sel_Format formats;
1254         wd->selection_asked = EINA_TRUE;
1255         formats = ELM_SEL_FORMAT_MARKUP;
1256         if (!wd->textonly)
1257           formats |= ELM_SEL_FORMAT_IMAGE;
1258         elm_selection_get(ELM_SEL_CLIPBOARD, formats, data, NULL, NULL);
1259 #endif
1260      }
1261 }
1262
1263 static void
1264 _store_selection(Elm_Sel_Type seltype, Evas_Object *obj)
1265 {
1266    Widget_Data *wd = elm_widget_data_get(obj);
1267    const char *sel;
1268    char *sel_str;
1269
1270    if (!wd) return;
1271    sel = edje_object_part_text_selection_get(wd->ent, "elm.text");
1272    sel_str = strdup(sel);
1273    if (!sel_str)
1274      return;
1275    if (wd->textonly)
1276      {
1277         while (EINA_TRUE)
1278           {
1279              char *startTag = NULL;
1280              char *endTag = NULL;
1281
1282              startTag = strstr(sel_str, "<item");
1283              if (!startTag)
1284                startTag = strstr(sel_str, "</item");
1285              if (startTag)
1286                endTag = strstr(startTag, ">");
1287              else
1288                break;
1289              if (!endTag || startTag > endTag)
1290                break;
1291
1292              size_t sindex = startTag - sel_str;
1293              size_t eindex = endTag - sel_str + 1;
1294
1295              Eina_Strbuf *buf = eina_strbuf_new();
1296              if (buf)
1297                {
1298                   eina_strbuf_append(buf, sel_str);
1299                   eina_strbuf_remove(buf, sindex, eindex);
1300                   sel_str = eina_strbuf_string_steal(buf);
1301                   eina_strbuf_free(buf);
1302                }
1303           }
1304      }
1305    elm_selection_set(seltype, obj, ELM_SEL_FORMAT_MARKUP, sel_str);
1306    if (seltype == ELM_SEL_CLIPBOARD)
1307      eina_stringshare_replace(&wd->cut_sel, sel_str);
1308    free(sel_str);
1309 }
1310
1311 static void
1312 _cut(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1313 {
1314    Widget_Data *wd = elm_widget_data_get(data);
1315
1316    /* Store it */
1317    wd->selmode = EINA_FALSE;
1318    if (!_elm_config->desktop_entry)
1319      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1320    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1321    if (!_elm_config->desktop_entry)
1322      elm_widget_scroll_hold_pop(data);
1323    _store_selection(ELM_SEL_CLIPBOARD, data);
1324    edje_object_part_text_insert(wd->ent, "elm.text", "");
1325    edje_object_part_text_select_none(wd->ent, "elm.text");
1326 }
1327
1328 static void
1329 _copy(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1330 {
1331    Widget_Data *wd = elm_widget_data_get(data);
1332    if (!wd) return;
1333    wd->selmode = EINA_TRUE;
1334    if (!_elm_config->desktop_entry)
1335      {
1336         edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1337         elm_widget_scroll_hold_pop(data);
1338      }
1339    _store_selection(ELM_SEL_CLIPBOARD, data);
1340 }
1341
1342 static void
1343 _cancel(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1344 {
1345    Widget_Data *wd = elm_widget_data_get(data);
1346    if (!wd) return;
1347    wd->selmode = EINA_FALSE;
1348    if (!_elm_config->desktop_entry)
1349      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1350    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1351    if (!_elm_config->desktop_entry)
1352      elm_widget_scroll_hold_pop(data);
1353    edje_object_part_text_select_none(wd->ent, "elm.text");
1354 }
1355
1356 static void
1357 _clipboard_menu(void *data, Evas_Object *obj, void *event_info __UNUSED__)
1358 {
1359    Widget_Data *wd = elm_widget_data_get(data);
1360    if (!wd) return;
1361
1362    // start for cbhm
1363 #ifdef HAVE_ELEMENTARY_X
1364    ecore_x_selection_secondary_set(elm_win_xwindow_get(obj), "",1);
1365 #endif
1366    cnpwidgetdata = data;
1367    elm_cbhm_helper_init(obj);
1368    if (elm_entry_cnp_textonly_get(obj))
1369      elm_cbhm_send_raw_data("show0");
1370    else
1371      elm_cbhm_send_raw_data("show1");
1372    // end for cbhm
1373 }
1374
1375 // start for cbhm
1376 static void
1377 _cnpinit(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1378 {
1379    Widget_Data *wd = elm_widget_data_get(data);
1380    if (!wd) return;
1381    cnpwidgetdata = data;
1382 }
1383 // end for cbhm
1384
1385
1386 static void
1387 _item_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1388 {
1389    Elm_Entry_Context_Menu_Item *it = data;
1390    Evas_Object *obj2 = it->obj;
1391    if (it->func) it->func(it->data, obj2, NULL);
1392 }
1393
1394 static void
1395 _menu_press(Evas_Object *obj)
1396 {
1397    Widget_Data *wd = elm_widget_data_get(obj);
1398    Evas_Object *top;
1399    const Eina_List *l;
1400    const Elm_Entry_Context_Menu_Item *it;
1401    if (!wd) return;
1402    if ((wd->api) && (wd->api->obj_longpress))
1403      {
1404         wd->api->obj_longpress(obj);
1405      }
1406    else if (wd->context_menu)
1407      {
1408         const char *context_menu_orientation;
1409
1410         if (wd->hoversel) evas_object_del(wd->hoversel);
1411         else elm_widget_scroll_freeze_push(obj);
1412         wd->hoversel = elm_hoversel_add(obj);
1413         context_menu_orientation = edje_object_data_get
1414            (wd->ent, "context_menu_orientation");
1415         if ((context_menu_orientation) &&
1416             (!strcmp(context_menu_orientation, "horizontal")))
1417           elm_hoversel_horizontal_set(wd->hoversel, EINA_TRUE);
1418         elm_object_style_set(wd->hoversel, "entry");
1419         elm_widget_sub_object_add(obj, wd->hoversel);
1420         elm_object_text_set(wd->hoversel, "Text");
1421         top = elm_widget_top_get(obj);
1422         if (top) elm_hoversel_hover_parent_set(wd->hoversel, top);
1423         evas_object_smart_callback_add(wd->hoversel, "dismissed", _dismissed, obj);
1424         if (!wd->selmode)
1425           {
1426              if (!wd->password)
1427                elm_hoversel_item_add(wd->hoversel, E_("Select"), NULL, ELM_ICON_NONE,
1428                                      _select, obj);
1429              if (1) // need way to detect if someone has a selection
1430                {
1431                   if (wd->editable)
1432                     elm_hoversel_item_add(wd->hoversel, E_("Paste"), NULL, ELM_ICON_NONE,
1433                                           _paste, obj);
1434                }
1435         // start for cbhm
1436              if ((!wd->password) && (wd->editable))
1437                elm_hoversel_item_add(wd->hoversel, E_("More"), NULL, ELM_ICON_NONE,
1438                                      _clipboard_menu, obj);
1439         // end for cbhm
1440           }
1441         else
1442           {
1443              if (!wd->password)
1444                {
1445                   if (wd->have_selection)
1446                     {
1447                        elm_hoversel_item_add(wd->hoversel, E_("Copy"), NULL, ELM_ICON_NONE,
1448                                              _copy, obj);
1449                        if (wd->editable)
1450                          elm_hoversel_item_add(wd->hoversel, E_("Cut"), NULL, ELM_ICON_NONE,
1451                                                _cut, obj);
1452                     }
1453                   elm_hoversel_item_add(wd->hoversel, E_("Cancel"), NULL, ELM_ICON_NONE,
1454                                         _cancel, obj);
1455         // start for cbhm
1456                   if (wd->editable)
1457                     elm_hoversel_item_add(wd->hoversel, E_("More"), NULL, ELM_ICON_NONE,
1458                                           _clipboard_menu, obj);
1459         // end for cbhm
1460                }
1461           }
1462         EINA_LIST_FOREACH(wd->items, l, it)
1463           {
1464              elm_hoversel_item_add(wd->hoversel, it->label, it->icon_file,
1465                                    it->icon_type, _item_clicked, it);
1466           }
1467         if (wd->hoversel)
1468           {
1469              _hoversel_position(obj);
1470              evas_object_show(wd->hoversel);
1471              elm_hoversel_hover_begin(wd->hoversel);
1472           }
1473         if (!_elm_config->desktop_entry)
1474           {
1475              edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1476              edje_object_part_text_select_abort(wd->ent, "elm.text");
1477           }
1478      }
1479 }
1480
1481 static void
1482 _magnifier_hide(void *data)
1483 {
1484    Widget_Data *wd = elm_widget_data_get(data);
1485    if (!wd) return;
1486
1487    evas_object_hide(wd->mgf_bg);
1488    evas_object_hide(wd->mgf_clip);
1489
1490    if (wd->scroll)
1491      elm_smart_scroller_freeze_set(wd->scroller, EINA_FALSE);
1492 }
1493
1494 static void
1495 _magnifier_show(void *data)
1496 {
1497    Widget_Data *wd = elm_widget_data_get(data);
1498    if (!wd) return;
1499
1500    evas_object_show(wd->mgf_bg);
1501    evas_object_show(wd->mgf_clip);
1502 }
1503
1504 static void
1505 _magnifier_move(void *data)
1506 {
1507    Widget_Data *wd = elm_widget_data_get(data);
1508    if (!wd) return;
1509
1510    Evas_Coord x, y, w, h, fs;
1511    Evas_Coord cx, cy, cw, ch, ox, oy;
1512
1513    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", &cx, &cy, &cw, &ch);
1514
1515    if (wd->scroll)
1516      {
1517         evas_object_geometry_get(wd->scroller, &x, &y, &w, &h);
1518         elm_smart_scroller_child_pos_get(wd->scroller, &ox, &oy);
1519         cx -= ox;
1520         cy -= oy;
1521      }
1522    else
1523      evas_object_geometry_get(data, &x, &y, &w, &h);
1524
1525    ox = oy = 0;
1526    fs = elm_finger_size_get();
1527
1528    if ((cy + y) - wd->mgf_height - fs < 0)
1529      oy = -1 * ((cy + y) - wd->mgf_height - fs);
1530
1531    if (wd->mgf_type == _ENTRY_MAGNIFIER_FIXEDSIZE)
1532      evas_object_move(wd->mgf_bg, (cx + x + cw/2) + ox, (cy + y) - wd->mgf_height - fs + oy);
1533    else if (wd->mgf_type == _ENTRY_MAGNIFIER_FILLWIDTH)
1534      evas_object_move(wd->mgf_bg, x, (cy + y) - wd->mgf_height - fs + oy);
1535    else
1536      return;
1537
1538    evas_object_move(wd->mgf_proxy, (1 - wd->mgf_scale) * cx + x + ox, (1 - wd->mgf_scale) * cy + y - wd->mgf_height/2 - ch/2 - fs + oy);
1539 }
1540
1541 static void
1542 _magnifier_create(void *data)
1543 {
1544    Widget_Data *wd = elm_widget_data_get(data);
1545    Evas_Coord x, y, w, h, mw, mh;
1546    const char* key_data = NULL;
1547
1548    if (!wd) return;
1549
1550    if (wd->mgf_proxy)
1551      {
1552         evas_object_image_source_unset(wd->mgf_proxy);
1553         evas_object_color_set(wd->mgf_proxy, 255, 255, 255, 0);
1554         evas_object_hide(wd->mgf_proxy);
1555         evas_object_clip_unset(wd->mgf_proxy);
1556         evas_object_del(wd->mgf_proxy);
1557      }
1558    if (wd->mgf_bg) evas_object_del(wd->mgf_bg);
1559    if (wd->mgf_clip) evas_object_del(wd->mgf_clip);
1560
1561    if (wd->scroll)
1562      evas_object_geometry_get(wd->scroller, &x, &y, &w, &h);
1563    else
1564      evas_object_geometry_get(data, &x, &y, &w, &h);
1565
1566    if ((w <= 0) || (h <= 0))
1567      return;
1568
1569    wd->mgf_bg = edje_object_add(evas_object_evas_get(data));
1570
1571    if (wd->mgf_type == _ENTRY_MAGNIFIER_FIXEDSIZE)
1572      _elm_theme_object_set(data, wd->mgf_bg, "entry", "magnifier", "fixed-size");
1573    else if (wd->mgf_type == _ENTRY_MAGNIFIER_FILLWIDTH)
1574      _elm_theme_object_set(data, wd->mgf_bg, "entry", "magnifier", "fill-width");
1575    else
1576      return;
1577
1578    wd->mgf_clip = evas_object_rectangle_add(evas_object_evas_get(data));
1579    evas_object_color_set(wd->mgf_clip, 255, 255, 255, 255);
1580    edje_object_part_swallow(wd->mgf_bg, "swallow", wd->mgf_clip);
1581
1582    key_data = edje_object_data_get(wd->mgf_bg, "height");
1583    if (key_data) wd->mgf_height = atoi(key_data);
1584    key_data = edje_object_data_get(wd->mgf_bg, "scale");
1585    if (key_data) wd->mgf_scale = atof(key_data);
1586
1587    if (wd->mgf_type == _ENTRY_MAGNIFIER_FILLWIDTH)
1588      evas_object_resize(wd->mgf_bg, w, wd->mgf_height);
1589
1590    if (wd->scroll)
1591      {
1592         elm_smart_scroller_freeze_set(wd->scroller, EINA_TRUE);
1593         wd->mgf_proxy = evas_object_image_add(evas_object_evas_get(wd->scroller));
1594         evas_object_image_source_set(wd->mgf_proxy, wd->scroller);
1595      }
1596    else
1597      {
1598         wd->mgf_proxy = evas_object_image_add(evas_object_evas_get(data));
1599         evas_object_image_source_set(wd->mgf_proxy, data);
1600      }
1601
1602    mw = (Evas_Coord)((float)w * wd->mgf_scale);
1603    mh = (Evas_Coord)((float)h * wd->mgf_scale);
1604    if ((mw <= 0) || (mh <= 0))
1605      return;
1606
1607    evas_object_resize(wd->mgf_proxy, mw, mh);
1608    evas_object_image_fill_set(wd->mgf_proxy, 0, 0, mw, mh);
1609    evas_object_color_set(wd->mgf_proxy, 255, 255, 255, 255);
1610    evas_object_pass_events_set(wd->mgf_proxy, EINA_TRUE);
1611    evas_object_show(wd->mgf_proxy);
1612    evas_object_clip_set(wd->mgf_proxy, wd->mgf_clip);
1613
1614    evas_object_layer_set(wd->mgf_bg, EVAS_LAYER_MAX);
1615    evas_object_layer_set(wd->mgf_proxy, EVAS_LAYER_MAX);
1616 }
1617
1618 static Eina_Bool
1619 _signal_long_pressed(void *data)
1620 {
1621    Widget_Data *wd = elm_widget_data_get(data);
1622    if (!wd) return ECORE_CALLBACK_CANCEL;
1623
1624    wd->long_pressed = EINA_TRUE;
1625
1626    _cancel(data, NULL, NULL);
1627
1628    _magnifier_create(data);
1629    _magnifier_move(data);
1630    _magnifier_show(data);
1631    elm_object_scroll_freeze_push(data);
1632
1633    evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
1634    return ECORE_CALLBACK_CANCEL;
1635 }
1636
1637 static void
1638 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1639 {
1640    Widget_Data *wd = elm_widget_data_get(data);
1641    Evas_Event_Mouse_Down *ev = event_info;
1642    if (!wd) return;
1643    if (wd->disabled) return;
1644    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1645    wd->downx = ev->canvas.x;
1646    wd->downy = ev->canvas.y;
1647    wd->long_pressed = EINA_FALSE;
1648 }
1649
1650 static void
1651 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1652 {
1653    Widget_Data *wd = elm_widget_data_get(data);
1654    Evas_Event_Mouse_Up *ev = event_info;
1655    if (!wd) return;
1656    if (wd->disabled) return;
1657    if (ev->button == 1)
1658      {
1659         if (!wd->double_clicked)
1660           {
1661              if ((wd->api) && (wd->api->obj_mouseup))
1662                wd->api->obj_mouseup(data);
1663           }
1664         _magnifier_hide(data);
1665         elm_object_scroll_freeze_pop(data);
1666
1667         if (wd->long_pressed)
1668           _menu_press(data);
1669      }
1670    else if (ev->button == 3)
1671      {
1672         wd->usedown = 1;
1673         _menu_press(data);
1674      }
1675 }
1676
1677 static void
1678 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1679 {
1680    Widget_Data *wd = elm_widget_data_get(data);
1681    Evas_Event_Mouse_Move *ev = event_info;
1682    if (!wd) return;
1683    if (wd->disabled) return;
1684
1685    if (ev->buttons == 1)
1686      {
1687         if (wd->long_pressed)
1688           {
1689              _magnifier_show(data);
1690              _magnifier_move(data);
1691           }
1692      }
1693 }
1694
1695 static const char *
1696 _getbase(Evas_Object *obj)
1697 {
1698    Widget_Data *wd = elm_widget_data_get(obj);
1699    if (!wd) return "base";
1700    if (wd->editable)
1701      {
1702         if (wd->password) return "base-password";
1703         else
1704           {
1705              if (wd->single_line) return "base-single";
1706              else
1707                {
1708                   switch (wd->linewrap)
1709                     {
1710                      case ELM_WRAP_CHAR:
1711                         return "base-charwrap";
1712                      case ELM_WRAP_WORD:
1713                         return "base";
1714                      case ELM_WRAP_MIXED:
1715                         return "base-mixedwrap";
1716                      case ELM_WRAP_NONE:
1717                      default:
1718                         return "base-nowrap";
1719                     }
1720                }
1721           }
1722      }
1723    else
1724      {
1725         if (wd->password) return "base-password";
1726         else
1727           {
1728              if (wd->single_line) return "base-single-noedit";
1729              else
1730                {
1731                   switch (wd->linewrap)
1732                     {
1733                      case ELM_WRAP_CHAR:
1734                         return "base-noedit-charwrap";
1735                      case ELM_WRAP_WORD:
1736                         return "base-noedit";
1737                      case ELM_WRAP_MIXED:
1738                         return "base-noedit-mixedwrap";
1739                      case ELM_WRAP_NONE:
1740                      default:
1741                         return "base-nowrap-noedit";
1742                     }
1743                }
1744           }
1745      }
1746    return "base";
1747 }
1748
1749
1750 static int
1751 _entry_length_get(Evas_Object *obj)
1752 {
1753    int len;
1754    const char *str = elm_entry_entry_get(obj);
1755    if (!str) return 0;
1756
1757    char *plain_str = _elm_util_mkup_to_text(str);
1758    if (!plain_str) return 0;
1759
1760    len = strlen(plain_str);
1761    free(plain_str);
1762
1763    return len;
1764 }
1765
1766 #ifndef HAVE_STRCASESTR
1767 char* _strcasestr(const char *s, const char *find)
1768 {
1769    char c, sc;
1770    size_t len;
1771
1772    if ((c = *find++) != 0) {
1773       c = tolower((unsigned char) c);
1774       len = strlen(find);
1775       do {
1776          do {
1777             if( (sc = *s++) == 0)
1778                return NULL;
1779          } while ((char)tolower((unsigned char)sc) != c);
1780       } while (strncasecmp(s, find, len) != 0);
1781       s--;
1782    }
1783    return ((char*) s);
1784 }
1785 #endif
1786
1787 static void
1788 _matchlist_show(void *data)
1789 {
1790    Widget_Data *wd = elm_widget_data_get(data);
1791    const char *text = NULL;
1792    int textlen = 0;
1793    char *str_list = NULL, *str_result = NULL;
1794    char *str_mkup = NULL, *str_front = NULL, *str_mid = NULL;
1795
1796    Eina_List *l;
1797    Eina_Bool textfound = EINA_FALSE;
1798
1799    if (!wd) return;
1800    if (elm_widget_disabled_get(data)) return;
1801
1802    wd->matchlist_job = NULL;
1803
1804    if (wd->matchlist_list_clicked)
1805      {
1806         evas_object_hide(wd->hover);
1807         wd->matchlist_list_clicked = EINA_FALSE;
1808         return;
1809      }
1810    text = elm_entry_entry_get(data);
1811    if (text == NULL)
1812      return;
1813    textlen = strlen(text);
1814
1815    if (textlen < wd->matchlist_threshold)
1816      {
1817         evas_object_hide(wd->hover);
1818         return;
1819      }
1820
1821    evas_object_hide(wd->hover);
1822
1823    if (wd->match_list)
1824      {
1825         elm_list_clear(wd->list);
1826         EINA_LIST_FOREACH(wd->match_list, l, str_list)
1827           {
1828              if (wd->matchlist_case_sensitive)
1829                str_result = strstr(str_list, text);
1830              else
1831 #ifdef HAVE_STRCASESTR
1832                 str_result = strcasestr(str_list, text);
1833 #else
1834                 str_result = _strcasestr(str_list, text);
1835 #endif
1836
1837              if (str_result)
1838                {
1839                   str_mkup = malloc(strlen(str_list) + 16);
1840                   if (str_mkup == NULL) return;
1841
1842                   textlen = strlen(str_list) - strlen(str_result);
1843                   str_front = malloc(textlen + 1);
1844                   if (str_front == NULL) return;
1845
1846                   memset(str_front, 0, textlen + 1);
1847                   strncpy(str_front, str_list, textlen);
1848
1849                   textlen = strlen(text);
1850                   str_mid = malloc(textlen + 1);
1851                   if (str_mid == NULL) return;
1852
1853                   memset(str_mid, 0, textlen + 1);
1854                   strncpy(str_mid, str_list + strlen(str_front), textlen);
1855
1856                   sprintf(str_mkup, "%s<match>%s</match>%s", str_front, str_mid, str_result + strlen(text));
1857
1858                   elm_list_item_append(wd->list, str_mkup, NULL, NULL, NULL, NULL);
1859
1860                   if (str_mkup) free(str_mkup);
1861                   if (str_front) free(str_front);
1862                   if (str_mid) free(str_mid);
1863
1864                   textfound=EINA_TRUE;
1865                }
1866           }
1867      }
1868    else
1869      return;
1870
1871    if (textfound)
1872      {
1873         elm_list_go(wd->list);
1874         evas_object_show(wd->hover);
1875         evas_object_raise(wd->hover);
1876      }
1877 }
1878
1879 static void _matchlist_list_clicked( void *data, Evas_Object *obj, void *event_info )
1880 {
1881    Elm_List_Item *it = (Elm_List_Item *) elm_list_selected_item_get(obj);
1882    Widget_Data *wd = elm_widget_data_get(data);
1883    if ((it == NULL) || (wd == NULL))
1884      return;
1885
1886    const char *text = elm_list_item_label_get(it);
1887    evas_object_smart_callback_call((Evas_Object *)data, "selected", (void *)text);
1888    if (wd->match_list)
1889      {
1890         if (text != NULL)
1891           {
1892              elm_entry_entry_set(data, elm_entry_markup_to_utf8(text));
1893              elm_entry_cursor_end_set(data);
1894              wd->matchlist_list_clicked = EINA_TRUE;
1895
1896              evas_object_smart_callback_call(data, SIG_MATCHLIST_CLICKED, elm_entry_markup_to_utf8(text));
1897           }
1898      }
1899    elm_widget_focus_set(data, EINA_TRUE);
1900 }
1901
1902 static void
1903 _entry_changed_common_handling(void *data, const char *event)
1904 {
1905    Widget_Data *wd = elm_widget_data_get(data);
1906    Evas_Coord minw, minh;
1907    if (!wd) return;
1908    wd->changed = EINA_TRUE;
1909    /* Reset the size hints which are no more relevant.
1910     * Keep the height, this is a hack, but doesn't really matter
1911     * cause we'll re-eval in a moment. */
1912    if (wd->scroll)
1913      {
1914         evas_object_size_hint_min_get(data, &minw, &minh);
1915         evas_object_size_hint_min_set(data, minw, minh);
1916      }
1917    else
1918      {
1919         evas_object_size_hint_min_get(data, NULL, &minh);
1920         evas_object_size_hint_min_set(data, -1, minh);
1921      }
1922
1923    _sizing_eval(data);
1924    if (wd->text) eina_stringshare_del(wd->text);
1925    wd->text = NULL;
1926    if (wd->password_text) eina_stringshare_del(wd->password_text);
1927    wd->password_text = NULL;
1928    _check_enable_returnkey(data);
1929    evas_object_smart_callback_call(data, event, NULL);
1930    if (wd->delay_write)
1931      {
1932         ecore_timer_del(wd->delay_write);
1933         wd->delay_write = NULL;
1934      }
1935
1936    if ((wd->single_line) && (wd->match_list))
1937      {
1938         if (wd->matchlist_job) ecore_job_del(wd->matchlist_job);
1939         wd->matchlist_job = ecore_job_add(_matchlist_show, data);
1940      }
1941    if ((!wd->autosave) || (!wd->file)) return;
1942    wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
1943 }
1944
1945 static void
1946 _signal_entry_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1947 {
1948    Widget_Data *wd = elm_widget_data_get(data);
1949    if (!wd) return;
1950
1951    _entry_changed_common_handling(data, SIG_CHANGED);
1952
1953    if ((wd->api) && (wd->api->obj_hidemenu))
1954      wd->api->obj_hidemenu(data);
1955 }
1956
1957 static void
1958 _signal_preedit_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1959 {
1960    Widget_Data *wd = elm_widget_data_get(data);
1961    if (!wd) return;
1962
1963    _entry_changed_common_handling(data, SIG_PREEDIT_CHANGED);
1964
1965    if ((wd->api) && (wd->api->obj_hidemenu))
1966      wd->api->obj_hidemenu(data);
1967 }
1968
1969 static void
1970 _signal_handler_move_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1971 {
1972    Widget_Data *wd = elm_widget_data_get(data);
1973    if (!wd) return;
1974
1975    elm_object_scroll_freeze_push(data);
1976
1977    if ((wd->api) && (wd->api->obj_hidemenu))
1978      wd->api->obj_hidemenu(data);
1979
1980    _magnifier_create(data);
1981    _magnifier_move(data);
1982    _magnifier_show(data);
1983 }
1984
1985 static void
1986 _signal_handler_move_end(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1987 {
1988    Widget_Data *wd = elm_widget_data_get(data);
1989    if (!wd) return;
1990
1991    elm_object_scroll_freeze_pop(data);
1992
1993    if (wd->have_selection)
1994      {
1995         _magnifier_hide(data);
1996         _menu_press(data);
1997      }
1998 }
1999
2000 static void
2001 _signal_handler_moving(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2002 {
2003    _magnifier_move(data);
2004    _magnifier_show(data);
2005 }
2006
2007 static Evas_Object *
2008 _viewport_obj_get(Evas_Object *data)
2009 {
2010    Widget_Data *wd = elm_widget_data_get(data);
2011    if (!wd) return NULL;
2012
2013    if(!data || !strlen(elm_widget_type_get(data)))
2014      return NULL;
2015
2016    Evas_Coord x, y, w, h;
2017    x = y = w = h = -1;
2018
2019    if (wd->scroll)
2020      {
2021         //evas_object_geometry_get(wd->scroller, &x, &y, &w, &h);
2022         //printf(">>> wd->scroller (%d, %d, %d, %d) \n", x, y, w, h);
2023         return wd->scroller;
2024      }
2025
2026    Evas_Object *parent_obj = data;
2027
2028    while(parent_obj = elm_widget_parent_get(parent_obj))
2029      {
2030         //evas_object_geometry_get(parent_obj, &x, &y, &w, &h);
2031         //printf(">>> %s (%d, %d, %d, %d) \n", elm_widget_type_get(parent_obj), x, y, w, h);
2032         if (!strcmp(elm_widget_type_get(parent_obj), "scroller") ||
2033             !strcmp(elm_widget_type_get(parent_obj), "genlist"))
2034           return parent_obj;
2035      }
2036
2037    return NULL;
2038 }
2039
2040 static void
2041 _signal_selection_end(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2042 {
2043    _magnifier_hide(data);
2044    _menu_press(data);
2045 }
2046
2047 static void
2048 _signal_selection_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2049 {
2050    Widget_Data *wd = elm_widget_data_get(data);
2051    const Eina_List *l;
2052    Evas_Object *entry;
2053    if (!wd) return;
2054    EINA_LIST_FOREACH(entries, l, entry)
2055      {
2056         if (entry != data) elm_entry_select_none(entry);
2057      }
2058    wd->have_selection = EINA_TRUE;
2059    wd->selmode = EINA_TRUE;
2060    evas_object_smart_callback_call(data, SIG_SELECTION_START, NULL);
2061 #ifdef HAVE_ELEMENTARY_X
2062    if (wd->sel_notify_handler)
2063      {
2064         const char *txt = elm_entry_selection_get(data);
2065         Evas_Object *top;
2066
2067         top = elm_widget_top_get(data);
2068         if ((top) && (elm_win_xwindow_get(top)))
2069           elm_selection_set(ELM_SEL_PRIMARY, data, ELM_SEL_FORMAT_MARKUP, txt);
2070      }
2071 #endif
2072
2073    if (!_elm_config->desktop_entry)
2074      edje_object_part_text_viewport_object_set(wd->ent, "elm.text", _viewport_obj_get(data));
2075 }
2076
2077 static void
2078 _signal_magnifier_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2079 {
2080    Evas_Coord cx, cy, cw, ch;
2081    Widget_Data *wd = elm_widget_data_get(data);
2082    if (!wd) return;
2083
2084    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", &cx, &cy, &cw, &ch);
2085    if (!wd->deferred_recalc_job)
2086      elm_widget_show_region_set(data, cx, cy, cw, ch, EINA_FALSE);
2087    else
2088      {
2089         wd->deferred_cur = EINA_TRUE;
2090         wd->cx = cx;
2091         wd->cy = cy;
2092         wd->cw = cw;
2093         wd->ch = ch + elm_finger_size_get();
2094      }
2095 }
2096
2097 static void
2098 _signal_selection_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2099 {
2100    Evas_Coord cx, cy, cw, ch;
2101    Widget_Data *wd = elm_widget_data_get(data);
2102    if (!wd) return;
2103    wd->have_selection = EINA_TRUE;
2104    wd->selmode = EINA_TRUE;
2105    evas_object_smart_callback_call(data, SIG_SELECTION_CHANGED, NULL);
2106    elm_selection_set(ELM_SEL_PRIMARY, obj, ELM_SEL_FORMAT_MARKUP,
2107                      elm_entry_selection_get(data));
2108
2109    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", &cx, &cy, &cw, &ch);
2110    if (!wd->deferred_recalc_job)
2111      elm_widget_show_region_set(data, cx, cy, cw, ch + elm_finger_size_get(), EINA_FALSE);
2112    else
2113      {
2114         wd->deferred_cur = EINA_TRUE;
2115         wd->cx = cx;
2116         wd->cy = cy;
2117         wd->cw = cw;
2118         wd->ch = ch + elm_finger_size_get();
2119      }
2120 }
2121
2122 static void
2123 _signal_selection_cleared(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2124 {
2125    Widget_Data *wd = elm_widget_data_get(data);
2126    if (!wd) return;
2127    if (!wd->have_selection) return;
2128    wd->have_selection = EINA_FALSE;
2129    wd->selmode = EINA_FALSE;
2130    evas_object_smart_callback_call(data, SIG_SELECTION_CLEARED, NULL);
2131    if (wd->sel_notify_handler)
2132      {
2133         if (wd->cut_sel)
2134           {
2135 #ifdef HAVE_ELEMENTARY_X
2136              Evas_Object *top;
2137
2138              top = elm_widget_top_get(data);
2139              if ((top) && (elm_win_xwindow_get(top)))
2140                elm_selection_set(ELM_SEL_PRIMARY, data, ELM_SEL_FORMAT_MARKUP,
2141                                  wd->cut_sel);
2142 #endif
2143              eina_stringshare_del(wd->cut_sel);
2144              wd->cut_sel = NULL;
2145           }
2146         else
2147           {
2148 #ifdef HAVE_ELEMENTARY_X
2149              Evas_Object *top;
2150
2151              top = elm_widget_top_get(data);
2152              if ((top) && (elm_win_xwindow_get(top)))
2153                elm_selection_clear(ELM_SEL_PRIMARY, data);
2154 #endif
2155           }
2156      }
2157
2158    if ((wd->api) && (wd->api->obj_hidemenu))
2159      {
2160         wd->api->obj_hidemenu(data);
2161      }
2162 }
2163
2164 static void
2165 _signal_entry_paste_request(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2166 {
2167    Widget_Data *wd = elm_widget_data_get(data);
2168    if (!wd) return;
2169    evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
2170    if (wd->sel_notify_handler)
2171      {
2172 #ifdef HAVE_ELEMENTARY_X
2173         Evas_Object *top;
2174
2175         top = elm_widget_top_get(data);
2176         if ((top) && (elm_win_xwindow_get(top)))
2177           {
2178              wd->selection_asked = EINA_TRUE;
2179              elm_selection_get(ELM_SEL_CLIPBOARD, ELM_SEL_FORMAT_MARKUP, data,
2180                                NULL, NULL);
2181           }
2182 #endif
2183      }
2184 }
2185
2186 static void
2187 _signal_entry_copy_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2188 {
2189    Widget_Data *wd = elm_widget_data_get(data);
2190    if (!wd) return;
2191    evas_object_smart_callback_call(data, SIG_SELECTION_COPY, NULL);
2192    elm_selection_set(ELM_SEL_CLIPBOARD, obj, ELM_SEL_FORMAT_MARKUP,
2193                      elm_entry_selection_get(data));
2194 }
2195
2196 static void
2197 _signal_entry_cut_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2198 {
2199    Widget_Data *wd = elm_widget_data_get(data);
2200    if (!wd) return;
2201    evas_object_smart_callback_call(data, SIG_SELECTION_CUT, NULL);
2202    elm_selection_set(ELM_SEL_CLIPBOARD, obj, ELM_SEL_FORMAT_MARKUP,
2203                      elm_entry_selection_get(data));
2204    edje_object_part_text_insert(wd->ent, "elm.text", "");
2205    wd->changed = EINA_TRUE;
2206    _sizing_eval(data);
2207 }
2208
2209 static void
2210 _signal_cursor_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2211 {
2212    Widget_Data *wd = elm_widget_data_get(data);
2213    if (!wd) return;
2214    wd->cursor_pos = edje_object_part_text_cursor_pos_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2215    wd->cur_changed = EINA_TRUE;
2216    _recalc_cursor_geometry(data);
2217 }
2218
2219 static void
2220 _signal_anchor_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2221 {
2222    Widget_Data *wd = elm_widget_data_get(data);
2223    if (!wd) return;
2224 }
2225
2226 static void
2227 _signal_anchor_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2228 {
2229    Widget_Data *wd = elm_widget_data_get(data);
2230    if (!wd) return;
2231 }
2232
2233 static void
2234 _signal_anchor_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
2235 {
2236    Widget_Data *wd = elm_widget_data_get(data);
2237    Elm_Entry_Anchor_Info ei;
2238    char *buf2, *p, *p2, *n;
2239    if (!wd) return;
2240    p = strrchr(emission, ',');
2241    if (p)
2242      {
2243         const Eina_List *geoms;
2244
2245         n = p + 1;
2246         p2 = p -1;
2247         while (p2 >= emission)
2248           {
2249              if (*p2 == ',') break;
2250              p2--;
2251           }
2252         p2++;
2253         buf2 = alloca(5 + p - p2);
2254         strncpy(buf2, p2, p - p2);
2255         buf2[p - p2] = 0;
2256         ei.name = n;
2257         ei.button = atoi(buf2);
2258         ei.x = ei.y = ei.w = ei.h = 0;
2259         geoms =
2260            edje_object_part_text_anchor_geometry_get(wd->ent, "elm.text", ei.name);
2261         if (geoms)
2262           {
2263              Evas_Textblock_Rectangle *r;
2264              const Eina_List *l;
2265              Evas_Coord px, py, x, y;
2266
2267              evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
2268              evas_pointer_canvas_xy_get(evas_object_evas_get(wd->ent), &px, &py);
2269              EINA_LIST_FOREACH(geoms, l, r)
2270                {
2271                   if (((r->x + x) <= px) && ((r->y + y) <= py) &&
2272                       ((r->x + x + r->w) > px) && ((r->y + y + r->h) > py))
2273                     {
2274                        ei.x = r->x + x;
2275                        ei.y = r->y + y;
2276                        ei.w = r->w;
2277                        ei.h = r->h;
2278                        break;
2279                     }
2280                }
2281           }
2282         if (!wd->disabled)
2283           evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
2284      }
2285 }
2286
2287 static void
2288 _signal_anchor_move(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2289 {
2290    Widget_Data *wd = elm_widget_data_get(data);
2291    if (!wd) return;
2292 }
2293
2294 static void
2295 _signal_anchor_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2296 {
2297    Widget_Data *wd = elm_widget_data_get(data);
2298    if (!wd) return;
2299 }
2300
2301 static void
2302 _signal_anchor_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2303 {
2304    Widget_Data *wd = elm_widget_data_get(data);
2305    if (!wd) return;
2306 }
2307
2308 static void
2309 _signal_key_enter(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2310 {
2311    Widget_Data *wd = elm_widget_data_get(data);
2312    if (!wd) return;
2313    evas_object_smart_callback_call(data, SIG_ACTIVATED, NULL);
2314 }
2315
2316 static void
2317 _signal_mouse_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2318 {
2319    Widget_Data *wd = elm_widget_data_get(data);
2320    if (!wd) return;
2321    wd->double_clicked = EINA_FALSE;
2322    evas_object_smart_callback_call(data, SIG_PRESS, NULL);
2323
2324    if ((wd->api) && (wd->api->obj_hidemenu))
2325      wd->api->obj_hidemenu(data);
2326 }
2327
2328 static void
2329 _signal_mouse_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2330 {
2331    Widget_Data *wd = elm_widget_data_get(data);
2332    if (!wd) return;
2333    evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
2334
2335    if (!_elm_config->desktop_entry && !wd->double_clicked)
2336      _cancel(data, NULL, NULL);
2337 }
2338
2339 static void
2340 _signal_mouse_double(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2341 {
2342    Widget_Data *wd = elm_widget_data_get(data);
2343    if (!wd) return;
2344    wd->double_clicked = EINA_TRUE;
2345    evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
2346 }
2347
2348 #ifdef HAVE_ELEMENTARY_X
2349 static Eina_Bool
2350 _event_selection_notify(void *data, int type __UNUSED__, void *event)
2351 {
2352    Widget_Data *wd = elm_widget_data_get(data);
2353    Ecore_X_Event_Selection_Notify *ev = event;
2354    if (!wd) return ECORE_CALLBACK_PASS_ON;
2355    if ((!wd->selection_asked) && (!wd->drag_selection_asked))
2356      return ECORE_CALLBACK_PASS_ON;
2357
2358    if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
2359        (ev->selection == ECORE_X_SELECTION_PRIMARY))
2360      {
2361         Ecore_X_Selection_Data_Text *text_data;
2362
2363         text_data = ev->data;
2364         if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
2365           {
2366              if (text_data->text)
2367                {
2368                   char *txt = _elm_util_text_to_mkup(text_data->text);
2369
2370                   if (txt)
2371                     {
2372                        elm_entry_entry_insert(data, txt);
2373                        free(txt);
2374                     }
2375                }
2376           }
2377         wd->selection_asked = EINA_FALSE;
2378      }
2379    else if (ev->selection == ECORE_X_SELECTION_XDND)
2380      {
2381         Ecore_X_Selection_Data_Text *text_data;
2382
2383         text_data = ev->data;
2384         if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
2385           {
2386              if (text_data->text)
2387                {
2388                   char *txt = _elm_util_text_to_mkup(text_data->text);
2389
2390                   if (txt)
2391                     {
2392                        /* Massive FIXME: this should be at the drag point */
2393                        elm_entry_entry_insert(data, txt);
2394                        free(txt);
2395                     }
2396                }
2397           }
2398         wd->drag_selection_asked = EINA_FALSE;
2399
2400         ecore_x_dnd_send_finished();
2401
2402      }
2403    return ECORE_CALLBACK_PASS_ON;
2404 }
2405
2406 static Eina_Bool
2407 _event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
2408 {
2409 /*
2410    Widget_Data *wd = elm_widget_data_get(data);
2411    Ecore_X_Event_Selection_Clear *ev = event;
2412    if (!wd) return ECORE_CALLBACK_PASS_ON;
2413    if (!wd->have_selection) return ECORE_CALLBACK_PASS_ON;
2414    if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
2415        (ev->selection == ECORE_X_SELECTION_PRIMARY))
2416      {
2417         elm_entry_select_none(data);
2418      }
2419    return 1; */
2420
2421    // start for cbhm
2422    Evas_Object *top = elm_widget_top_get(data);
2423    Ecore_X_Event_Selection_Clear *ev = event;
2424
2425    if (!top)
2426       return ECORE_CALLBACK_PASS_ON;
2427
2428    if (ev->selection != ECORE_X_SELECTION_SECONDARY)
2429      {
2430         return ECORE_CALLBACK_PASS_ON;
2431      }
2432
2433    if (cnpwidgetdata == data)
2434      {
2435         evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
2436         elm_selection_get(ELM_SEL_SECONDARY,ELM_SEL_FORMAT_MARKUP,data,NULL,NULL);
2437      }
2438
2439    // end for cbhm
2440    return ECORE_CALLBACK_PASS_ON;
2441 }
2442
2443 static Eina_Bool
2444 _drag_drop_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Selection_Data *drop)
2445 {
2446    Widget_Data *wd;
2447    Eina_Bool rv;
2448
2449    wd = elm_widget_data_get(obj);
2450    if (!wd) return EINA_FALSE;
2451    printf("Inserting at (%d,%d) %s\n",drop->x,drop->y,(char*)drop->data);
2452
2453    edje_object_part_text_cursor_copy(wd->ent, "elm.text",
2454                                      EDJE_CURSOR_MAIN,/*->*/EDJE_CURSOR_USER);
2455    rv = edje_object_part_text_cursor_coord_set(wd->ent,"elm.text",
2456                                                EDJE_CURSOR_MAIN,drop->x,drop->y);
2457    if (!rv) printf("Warning: Failed to position cursor: paste anyway\n");
2458    elm_entry_entry_insert(obj, drop->data);
2459    edje_object_part_text_cursor_copy(wd->ent, "elm.text",
2460                                      EDJE_CURSOR_USER,/*->*/EDJE_CURSOR_MAIN);
2461
2462    return EINA_TRUE;
2463 }
2464 #endif
2465
2466 static Evas_Object *
2467 _get_item(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, const char *item)
2468 {
2469    Widget_Data *wd = elm_widget_data_get(data);
2470    Evas_Object *o;
2471    Eina_List *l;
2472    Elm_Entry_Item_Provider *ip;
2473
2474    EINA_LIST_FOREACH(wd->item_providers, l, ip)
2475      {
2476         o = ip->func(ip->data, data, item);
2477         if (o) return o;
2478      }
2479    if (!strncmp(item, "file://", 7))
2480      {
2481         const char *fname = item + 7;
2482
2483         o = evas_object_image_filled_add(evas_object_evas_get(data));
2484         evas_object_image_file_set(o, fname, NULL);
2485         if (evas_object_image_load_error_get(o) == EVAS_LOAD_ERROR_NONE)
2486           {
2487              evas_object_show(o);
2488           }
2489         else
2490           {
2491              evas_object_del(o);
2492              o = edje_object_add(evas_object_evas_get(data));
2493              _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
2494           }
2495         return o;
2496      }
2497    o = edje_object_add(evas_object_evas_get(data));
2498    if (!_elm_theme_object_set(data, o, "entry", item, elm_widget_style_get(data)))
2499      _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
2500    return o;
2501 }
2502
2503 static int
2504 _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag)
2505 {
2506    const char *srcstring = NULL;
2507    Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
2508    char *curlocater, *replocater;
2509    char *starttag, *endtag;
2510    int tagtxtlen = 0, insertflag = 0;
2511
2512    srcstring = eina_strbuf_string_get(srcbuf);
2513    curlocater = strstr(srcstring, key);
2514
2515    if (!curlocater || !srcstring)
2516      {
2517        insertflag = 1;
2518      }
2519    else
2520      {
2521        do
2522          {
2523            starttag = strchr(srcstring, '<');
2524            endtag = strchr(srcstring, '>');
2525            tagtxtlen = endtag - starttag;
2526            if (tagtxtlen <= 0) tagtxtlen = 0;
2527            if (starttag < curlocater && curlocater < endtag) break;
2528            if (endtag != NULL && endtag+1 != NULL)
2529              srcstring = endtag+1;
2530            else
2531              break;
2532          } while (strlen(srcstring) > 1);
2533
2534        if (starttag && endtag && tagtxtlen > strlen(key))
2535          {
2536            repbuf = eina_strbuf_new();
2537            diffbuf = eina_strbuf_new();
2538            eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
2539            srcstring = eina_strbuf_string_get(repbuf);
2540            curlocater = strstr(srcstring, key);
2541
2542            if (curlocater != NULL)
2543              {
2544                replocater = curlocater + strlen(key) + 1;
2545
2546                while ((*replocater) && (*replocater != ' ') && (*replocater != '>'))
2547                  replocater++;
2548
2549                if (replocater-curlocater > strlen(key)+1)
2550                  {
2551                    eina_strbuf_append_n(diffbuf, curlocater, replocater-curlocater+1);
2552                  }
2553                else
2554                  insertflag = 1;
2555              }
2556            else
2557              {
2558                insertflag = 1;
2559              }
2560            eina_strbuf_reset(repbuf);
2561          }
2562        else
2563          {
2564            insertflag = 1;
2565          }
2566      }
2567
2568    if (repbuf == NULL) repbuf = eina_strbuf_new();
2569    if (diffbuf == NULL) diffbuf = eina_strbuf_new();
2570
2571    if (insertflag)
2572      {
2573        eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
2574        eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
2575      }
2576    else
2577      {
2578         if (deleteflag)
2579           {
2580             eina_strbuf_prepend(diffbuf, "<");
2581             eina_strbuf_append(diffbuf, ">");
2582             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
2583           }
2584         else
2585           {
2586             eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
2587             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
2588           }
2589      }
2590
2591    if (repbuf) eina_strbuf_free(repbuf);
2592    if (diffbuf) eina_strbuf_free(diffbuf);
2593
2594    return 0;
2595 }
2596
2597 static int
2598 _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag)
2599 {
2600    Eina_Strbuf *sharebuf = NULL;
2601
2602    sharebuf = eina_strbuf_new();
2603    eina_strbuf_append(sharebuf, *srcstring);
2604    _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
2605    eina_stringshare_del(*srcstring);
2606    *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
2607    eina_strbuf_free(sharebuf);
2608
2609    return 0;
2610 }
2611
2612 static void
2613 _text_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, Edje_Text_Filter_Type type, char **text)
2614 {
2615    Widget_Data *wd = elm_widget_data_get(data);
2616    Eina_List *l;
2617    Elm_Entry_Text_Filter *tf;
2618
2619    if (type == EDJE_TEXT_FILTER_FORMAT)
2620      return;
2621
2622    EINA_LIST_FOREACH(wd->text_filters, l, tf)
2623      {
2624         tf->func(tf->data, data, text);
2625         if (!*text)
2626           break;
2627      }
2628 }
2629
2630 /* This function is used to insert text by chunks in jobs */
2631 static Eina_Bool
2632 _text_append_idler(void *data)
2633 {
2634    int start;
2635    char backup;
2636    Evas_Object *obj = (Evas_Object *) data;
2637    Widget_Data *wd = elm_widget_data_get(obj);
2638    if (wd->text) eina_stringshare_del(wd->text);
2639    wd->text = NULL;
2640    if (wd->password_text) eina_stringshare_del(wd->password_text);
2641    wd->password_text = NULL;
2642    wd->changed = EINA_TRUE;
2643
2644    start = wd->append_text_position;
2645    if (start + _CHUNK_SIZE < wd->append_text_len)
2646      {
2647         int pos = start;
2648         int tag_start, esc_start;
2649
2650         tag_start = esc_start = -1;
2651         /* Find proper markup cut place */
2652         while (pos - start < _CHUNK_SIZE)
2653           {
2654              int prev_pos = pos;
2655              Eina_Unicode tmp =
2656                 eina_unicode_utf8_get_next(wd->append_text_left, &pos);
2657              if (esc_start == -1)
2658                {
2659                   if (tmp == '<')
2660                      tag_start = prev_pos;
2661                   else if (tmp == '>')
2662                      tag_start = -1;
2663                }
2664              else if (tag_start == -1)
2665                {
2666                   if (tmp == '&')
2667                      esc_start = prev_pos;
2668                   else if (tmp == ';')
2669                      esc_start = -1;
2670                }
2671           }
2672
2673         if (tag_start >= 0)
2674           {
2675              wd->append_text_position = tag_start;
2676           }
2677         else if (esc_start >= 0)
2678           {
2679              wd->append_text_position = esc_start;
2680           }
2681         else
2682           {
2683              wd->append_text_position = pos;
2684           }
2685      }
2686    else
2687      {
2688         wd->append_text_position = wd->append_text_len;
2689      }
2690
2691    backup = wd->append_text_left[wd->append_text_position];
2692    wd->append_text_left[wd->append_text_position] = '\0';
2693
2694    edje_object_part_text_append(wd->ent, "elm.text",
2695          wd->append_text_left + start);
2696
2697    wd->append_text_left[wd->append_text_position] = backup;
2698
2699    /* If there's still more to go, renew the idler, else, cleanup */
2700    if (wd->append_text_position < wd->append_text_len)
2701      {
2702         return ECORE_CALLBACK_RENEW;
2703      }
2704    else
2705      {
2706         free(wd->append_text_left);
2707         wd->append_text_left = NULL;
2708         wd->append_text_idler = NULL;
2709         return ECORE_CALLBACK_CANCEL;
2710      }
2711 }
2712
2713 static void
2714 _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit unit)
2715 {
2716    int i = 0, unit_size;
2717    int current_len = strlen(*text);
2718    char *new_text = *text;
2719    if (unit >= LENGTH_UNIT_LAST) return;
2720    while (*new_text)
2721      {
2722         if (*new_text == '<')
2723           {
2724              while (*new_text != '>')
2725                {
2726                   new_text++;
2727                   if (!*new_text) break;
2728                }
2729              new_text++;
2730           }
2731         else
2732           {
2733              int index = 0;
2734              if (*new_text == '&')
2735                {
2736                   while (*(new_text + index) != ';')
2737                     {
2738                        index++;
2739                        if (!*(new_text + index)) break;
2740                     }
2741                }
2742              char *markup;
2743              index = evas_string_char_next_get(new_text, index, NULL);
2744              markup = malloc(index + 1);
2745              strncpy(markup, new_text, index);
2746              markup[index] = 0;
2747              if (unit == LENGTH_UNIT_BYTE)
2748                unit_size = strlen(elm_entry_markup_to_utf8(markup));
2749              else if (unit == LENGTH_UNIT_CHAR)
2750                unit_size = evas_string_char_len_get(elm_entry_markup_to_utf8(markup));
2751              if (markup)
2752                {
2753                   free(markup);
2754                   markup = NULL;
2755                }
2756              if (can_add < unit_size)
2757                {
2758                   if (!i)
2759                     {
2760                        evas_object_smart_callback_call(obj, "maxlength,reached", NULL);
2761                        free(*text);
2762                        *text = NULL;
2763                        return;
2764                     }
2765                   can_add = 0;
2766                   strncpy(new_text, new_text + index, current_len - ((new_text + index) - *text));
2767                   current_len -= index;
2768                   (*text)[current_len] = 0;
2769                }
2770              else
2771                {
2772                   new_text += index;
2773                   can_add -= unit_size;
2774                }
2775              i++;
2776           }
2777      }
2778    evas_object_smart_callback_call(obj, "maxlength,reached", NULL);
2779 }
2780
2781 static void
2782 _elm_entry_text_set(Evas_Object *obj, const char *item, const char *entry)
2783 {
2784    int len = 0;
2785    ELM_CHECK_WIDTYPE(obj, widtype);
2786    if (item && strcmp(item, "default")) return;
2787    Widget_Data *wd = elm_widget_data_get(obj);
2788    if (!wd) return;
2789    if (!entry) entry = "";
2790    if (wd->text) eina_stringshare_del(wd->text);
2791    wd->text = NULL;
2792    if (wd->password_text) eina_stringshare_del(wd->password_text);
2793    wd->password_text = NULL;
2794    wd->changed = EINA_TRUE;
2795
2796    /* Clear currently pending job if there is one */
2797    if (wd->append_text_idler)
2798      {
2799         ecore_idler_del(wd->append_text_idler);
2800         free(wd->append_text_left);
2801         wd->append_text_left = NULL;
2802         wd->append_text_idler = NULL;
2803      }
2804
2805    len = strlen(entry);
2806    /* Split to ~_CHUNK_SIZE chunks */
2807    if (len > _CHUNK_SIZE)
2808      {
2809         wd->append_text_left = (char *) malloc(len + 1);
2810      }
2811
2812    /* If we decided to use the idler */
2813    if (wd->append_text_left)
2814      {
2815         /* Need to clear the entry first */
2816         edje_object_part_text_set(wd->ent, "elm.text", "");
2817         memcpy(wd->append_text_left, entry, len + 1);
2818         wd->append_text_position = 0;
2819         wd->append_text_len = len;
2820         wd->append_text_idler = ecore_idler_add(_text_append_idler, obj);
2821      }
2822    else
2823      {
2824         edje_object_part_text_set(wd->ent, "elm.text", entry);
2825      }
2826 }
2827
2828 static const char *
2829 _elm_entry_text_get(const Evas_Object *obj, const char *item)
2830 {
2831    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2832    Widget_Data *wd = elm_widget_data_get(obj);
2833    if (item && strcmp(item, "default")) return NULL;
2834    const char *text;
2835    if (!wd) return NULL;
2836    if (wd->password)
2837      {
2838         if(wd->password_text) return wd->password_text;
2839      }
2840    else if (wd->text) 
2841      {
2842         return wd->text;
2843      }
2844    text = edje_object_part_text_get(wd->ent, "elm.text");
2845    if (!text)
2846      {
2847         ERR("text=NULL for edje %p, part 'elm.text'", wd->ent);
2848         return NULL;
2849      }
2850    eina_stringshare_replace(&wd->text, text);
2851    if (wd->password)
2852      {
2853         const char *pw_text;
2854         pw_text = elm_entry_markup_to_utf8(wd->text);
2855         if (pw_text)
2856           {
2857              eina_stringshare_replace(&wd->password_text, pw_text);
2858              free(pw_text);
2859              return wd->password_text;
2860           }
2861      }
2862    return wd->text;
2863 }
2864
2865 /**
2866  * This adds an entry to @p parent object.
2867  *
2868  * @param parent The parent object
2869  * @return The new object or NULL if it cannot be created
2870  *
2871  * @ingroup Entry
2872  */
2873 EAPI Evas_Object *
2874 elm_entry_add(Evas_Object *parent)
2875 {
2876    Evas_Object *obj, *top;
2877    Evas *e;
2878    Widget_Data *wd;
2879
2880    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
2881
2882    ELM_SET_WIDTYPE(widtype, "entry");
2883    elm_widget_type_set(obj, "entry");
2884    elm_widget_sub_object_add(parent, obj);
2885    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
2886    elm_widget_data_set(obj, wd);
2887    elm_widget_del_hook_set(obj, _del_hook);
2888    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
2889    elm_widget_theme_hook_set(obj, _theme_hook);
2890    elm_widget_disable_hook_set(obj, _disable_hook);
2891    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
2892    elm_widget_focus_region_hook_set(obj, _focus_region_hook);
2893    elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
2894    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
2895    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
2896    elm_object_cursor_set(obj, ELM_CURSOR_XTERM);
2897    elm_widget_can_focus_set(obj, EINA_TRUE);
2898    elm_widget_highlight_ignore_set(obj, EINA_TRUE);
2899    elm_widget_text_set_hook_set(obj, _elm_entry_text_set);
2900    elm_widget_text_get_hook_set(obj, _elm_entry_text_get);
2901    elm_widget_content_set_hook_set(obj, _content_set_hook);
2902    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
2903    elm_widget_content_get_hook_set(obj, _content_get_hook);
2904
2905    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, wd);
2906    wd->scroller = elm_smart_scroller_add(e);
2907    elm_widget_sub_object_add(obj, wd->scroller);
2908    elm_smart_scroller_widget_set(wd->scroller, obj);
2909    elm_smart_scroller_object_theme_set(obj, wd->scroller, "scroller", "entry",
2910                                        elm_widget_style_get(obj));
2911    evas_object_size_hint_weight_set(wd->scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2912    evas_object_size_hint_align_set(wd->scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
2913    elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_FALSE, EINA_FALSE);
2914    elm_smart_scroller_propagate_events_set(wd->scroller, EINA_TRUE);
2915
2916    wd->linewrap     = ELM_WRAP_WORD;
2917    wd->editable     = EINA_TRUE;
2918    wd->disabled     = EINA_FALSE;
2919    wd->context_menu = EINA_TRUE;
2920    wd->autosave     = EINA_TRUE;
2921    wd->textonly     = EINA_FALSE;
2922    wd->autoperiod   = EINA_TRUE;
2923
2924    wd->ent = edje_object_add(e);
2925    elm_widget_sub_object_add(obj, wd->ent);
2926    edje_object_item_provider_set(wd->ent, _get_item, obj);
2927    edje_object_text_insert_filter_callback_add(wd->ent,"elm.text", _text_filter, obj);
2928    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOVE, _move, obj);
2929    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_DOWN,
2930                                   _mouse_down, obj);
2931    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_UP,
2932                                   _mouse_up, obj);
2933    evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_MOVE,
2934                                   _mouse_move, obj);
2935    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
2936
2937    _elm_theme_object_set(obj, wd->ent, "entry", "base", "default");
2938    edje_object_signal_callback_add(wd->ent, "entry,changed", "elm.text",
2939                                    _signal_entry_changed, obj);
2940    edje_object_signal_callback_add(wd->ent, "preedit,changed", "elm.text",
2941                                    _signal_preedit_changed, obj);
2942    edje_object_signal_callback_add(wd->ent, "handler,move,start", "elm.text",
2943                                    _signal_handler_move_start, obj);
2944    edje_object_signal_callback_add(wd->ent, "handler,move,end", "elm.text",
2945                                    _signal_handler_move_end, obj);
2946    edje_object_signal_callback_add(wd->ent, "handler,moving", "elm.text",
2947                                    _signal_handler_moving, obj);
2948    edje_object_signal_callback_add(wd->ent, "selection,start", "elm.text",
2949                                    _signal_selection_start, obj);
2950    edje_object_signal_callback_add(wd->ent, "selection,end", "elm.text",
2951                                    _signal_selection_end, obj);
2952    edje_object_signal_callback_add(wd->ent, "long,pressed", "elm.text",
2953                                    _signal_long_pressed, obj);
2954    edje_object_signal_callback_add(wd->ent, "magnifier,changed", "elm.text",
2955                                    _signal_magnifier_changed, obj);
2956    edje_object_signal_callback_add(wd->ent, "selection,changed", "elm.text",
2957                                    _signal_selection_changed, obj);
2958    edje_object_signal_callback_add(wd->ent, "selection,cleared", "elm.text",
2959                                    _signal_selection_cleared, obj);
2960    edje_object_signal_callback_add(wd->ent, "entry,paste,request", "elm.text",
2961                                    _signal_entry_paste_request, obj);
2962    edje_object_signal_callback_add(wd->ent, "entry,copy,notify", "elm.text",
2963                                    _signal_entry_copy_notify, obj);
2964    edje_object_signal_callback_add(wd->ent, "entry,cut,notify", "elm.text",
2965                                    _signal_entry_cut_notify, obj);
2966    edje_object_signal_callback_add(wd->ent, "cursor,changed", "elm.text",
2967                                    _signal_cursor_changed, obj);
2968    edje_object_signal_callback_add(wd->ent, "anchor,mouse,down,*", "elm.text",
2969                                    _signal_anchor_down, obj);
2970    edje_object_signal_callback_add(wd->ent, "anchor,mouse,up,*", "elm.text",
2971                                    _signal_anchor_up, obj);
2972    edje_object_signal_callback_add(wd->ent, "anchor,mouse,clicked,*", "elm.text",
2973                                    _signal_anchor_clicked, obj);
2974    edje_object_signal_callback_add(wd->ent, "anchor,mouse,move,*", "elm.text",
2975                                    _signal_anchor_move, obj);
2976    edje_object_signal_callback_add(wd->ent, "anchor,mouse,in,*", "elm.text",
2977                                    _signal_anchor_in, obj);
2978    edje_object_signal_callback_add(wd->ent, "anchor,mouse,out,*", "elm.text",
2979                                    _signal_anchor_out, obj);
2980    edje_object_signal_callback_add(wd->ent, "entry,key,enter", "elm.text",
2981                                    _signal_key_enter, obj);
2982    edje_object_signal_callback_add(wd->ent, "mouse,down,1", "elm.text",
2983                                    _signal_mouse_down, obj);
2984    edje_object_signal_callback_add(wd->ent, "mouse,clicked,1", "elm.text",
2985                                    _signal_mouse_clicked, obj);
2986    edje_object_signal_callback_add(wd->ent, "mouse,down,1,double", "elm.text",
2987                                    _signal_mouse_double, obj);
2988    edje_object_part_text_set(wd->ent, "elm.text", "");
2989    if (_elm_config->desktop_entry)
2990      edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
2991    elm_widget_resize_object_set(obj, wd->ent);
2992    _sizing_eval(obj);
2993
2994    wd->input_panel_enable = edje_object_part_text_input_panel_enabled_get(wd->ent, "elm.text");
2995
2996 #ifdef HAVE_ELEMENTARY_X
2997    top = elm_widget_top_get(obj);
2998    if ((top) && (elm_win_xwindow_get(top)))
2999      {
3000         wd->sel_notify_handler =
3001            ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
3002                                    _event_selection_notify, obj);
3003         wd->sel_clear_handler =
3004            ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR,
3005                                    _event_selection_clear, obj);
3006      }
3007
3008    elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE,
3009                        _drag_drop_cb, NULL);
3010 #endif
3011
3012    entries = eina_list_prepend(entries, obj);
3013
3014    // module - find module for entry
3015    wd->api = _module(obj);
3016    // if found - hook in
3017    if ((wd->api) && (wd->api->obj_hook)) wd->api->obj_hook(obj);
3018
3019    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3020    // TODO: convert Elementary to subclassing of Evas_Smart_Class
3021    // TODO: and save some bytes, making descriptions per-class and not instance!
3022    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3023    return obj;
3024 }
3025
3026 EAPI void elm_entry_extension_module_data_get(Evas_Object *obj,Elm_Entry_Extension_data *ext_mod)
3027 {
3028    ELM_CHECK_WIDTYPE(obj, widtype);
3029    Widget_Data *wd = elm_widget_data_get(obj);
3030    if (!wd) return;
3031    ext_mod->cancel = _cancel;
3032    ext_mod->copy = _copy;
3033    ext_mod->cut = _cut;
3034    ext_mod->paste = _paste;
3035    ext_mod->select = _select;
3036    ext_mod->selectall = _selectall;
3037    ext_mod->ent = wd->ent;
3038    ext_mod->viewport_obj = _viewport_obj_get(obj);
3039    ext_mod->items = wd->items;
3040    ext_mod->editable = wd->editable;
3041    ext_mod->have_selection = wd->have_selection;
3042    ext_mod->password = wd->password;
3043    ext_mod->selmode = wd->selmode;
3044    ext_mod->cnpinit = _cnpinit;
3045    ext_mod->context_menu = wd->context_menu;
3046    ext_mod->textonly = wd->textonly;
3047 }
3048
3049 /**
3050  * This sets the entry object not to line wrap.  All input will
3051  * be on a single line, and the entry box will extend with user input.
3052  *
3053  * @param obj The entry object
3054  * @param single_line If true, the text in the entry
3055  * will be on a single line.
3056  *
3057  * @ingroup Entry
3058  */
3059 EAPI void
3060 elm_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line)
3061 {
3062    ELM_CHECK_WIDTYPE(obj, widtype);
3063    Widget_Data *wd = elm_widget_data_get(obj);
3064    if (!wd) return;
3065    if (wd->single_line == single_line) return;
3066    wd->single_line = single_line;
3067    wd->linewrap = ELM_WRAP_NONE;
3068    elm_entry_cnp_textonly_set(obj, EINA_TRUE);
3069    _theme_hook(obj);
3070    if (wd->scroller)
3071      {
3072         if (wd->single_line)
3073           {
3074              elm_smart_scroller_policy_set(wd->scroller,
3075                                            ELM_SMART_SCROLLER_POLICY_OFF,
3076                                            ELM_SMART_SCROLLER_POLICY_OFF);
3077              elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_FALSE, EINA_FALSE);
3078           }
3079         else
3080           {
3081              const Elm_Scroller_Policy map[3] =
3082                {
3083                   ELM_SMART_SCROLLER_POLICY_AUTO,
3084                   ELM_SMART_SCROLLER_POLICY_ON,
3085                   ELM_SMART_SCROLLER_POLICY_OFF
3086                };
3087              elm_smart_scroller_policy_set(wd->scroller,
3088                                            map[wd->policy_h],
3089                                            map[wd->policy_v]);
3090              elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_FALSE, EINA_FALSE);
3091           }
3092         _sizing_eval(obj);
3093      }
3094 }
3095
3096 /**
3097  * This returns true if the entry has been set to single line mode.
3098  * See also elm_entry_single_line_set().
3099  *
3100  * @param obj The entry object
3101  * @return single_line If true, the text in the entry is set to display
3102  * on a single line.
3103  *
3104  * @ingroup Entry
3105  */
3106 EAPI Eina_Bool
3107 elm_entry_single_line_get(const Evas_Object *obj)
3108 {
3109    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3110    Widget_Data *wd = elm_widget_data_get(obj);
3111    if (!wd) return EINA_FALSE;
3112    return wd->single_line;
3113 }
3114
3115 /**
3116  * This sets the entry object to password mode.  All text entered
3117  * and/or displayed within the widget will be replaced with asterisks (*).
3118  *
3119  * @param obj The entry object
3120  * @param password If true, password mode is enabled.
3121  *
3122  * @ingroup Entry
3123  */
3124 EAPI void
3125 elm_entry_password_set(Evas_Object *obj, Eina_Bool password)
3126 {
3127    ELM_CHECK_WIDTYPE(obj, widtype);
3128    Widget_Data *wd = elm_widget_data_get(obj);
3129    if (!wd) return;
3130    if (wd->password == password) return;
3131    wd->password = password;
3132    wd->single_line = EINA_TRUE;
3133    wd->linewrap = ELM_WRAP_NONE;
3134    _theme_hook(obj);
3135 }
3136
3137 /**
3138  * This returns whether password mode is enabled.
3139  * See also elm_entry_password_set().
3140  *
3141  * @param obj The entry object
3142  * @return If true, the entry is set to display all characters
3143  * as asterisks (*).
3144  *
3145  * @ingroup Entry
3146  */
3147 EAPI Eina_Bool
3148 elm_entry_password_get(const Evas_Object *obj)
3149 {
3150    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3151    Widget_Data *wd = elm_widget_data_get(obj);
3152    if (!wd) return EINA_FALSE;
3153    return wd->password;
3154 }
3155
3156 /**
3157  * This sets the text displayed within the entry to @p entry.
3158  *
3159  * @param obj The entry object
3160  * @param entry The text to be displayed
3161  *
3162  * @ingroup Entry
3163  */
3164 EAPI void
3165 elm_entry_entry_set(Evas_Object *obj, const char *entry)
3166 {
3167    _elm_entry_text_set(obj, NULL, entry);
3168 }
3169
3170 /**
3171  * This appends @p entry to the text of the entry.
3172  *
3173  * @param obj The entry object
3174  * @param entry The text to be displayed
3175  *
3176  * @ingroup Entry
3177  */
3178 EAPI void
3179 elm_entry_entry_append(Evas_Object *obj, const char *entry)
3180 {
3181    int len = 0;
3182    ELM_CHECK_WIDTYPE(obj, widtype);
3183    Widget_Data *wd = elm_widget_data_get(obj);
3184    if (!wd) return;
3185    if (!entry) entry = "";
3186    wd->changed = EINA_TRUE;
3187
3188    len = strlen(entry);
3189    if (wd->append_text_left)
3190      {
3191         char *tmpbuf;
3192         tmpbuf = realloc(wd->append_text_left, wd->append_text_len + len + 1);
3193         if (!tmpbuf)
3194           {
3195              /* Do something */
3196              return;
3197           }
3198         wd->append_text_left = tmpbuf;
3199         memcpy(wd->append_text_left + wd->append_text_len, entry, len + 1);
3200         wd->append_text_len += len;
3201      }
3202    else
3203      {
3204         /* FIXME: Add chunked appending here (like in entry_set) */
3205         edje_object_part_text_append(wd->ent, "elm.text", entry);
3206      }
3207 }
3208
3209 /**
3210  * This returns the text currently shown in object @p entry.
3211  * See also elm_entry_entry_set().
3212  *
3213  * @param obj The entry object
3214  * @return The currently displayed text or NULL on failure
3215  *
3216  * @ingroup Entry
3217  */
3218 EAPI const char *
3219 elm_entry_entry_get(const Evas_Object *obj)
3220 {
3221    return _elm_entry_text_get(obj, NULL);
3222 }
3223
3224 /**
3225  * This returns EINA_TRUE if the entry is empty/there was an error
3226  * and EINA_FALSE if it is not empty.
3227  *
3228  * @param obj The entry object
3229  * @return If the entry is empty or not.
3230  *
3231  * @ingroup Entry
3232  */
3233 EAPI Eina_Bool
3234 elm_entry_is_empty(const Evas_Object *obj)
3235 {
3236    /* FIXME: until there's support for that in textblock, we just check
3237     * to see if the there is text or not. */
3238    ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
3239    Widget_Data *wd = elm_widget_data_get(obj);
3240    const Evas_Object *tb;
3241    //Evas_Textblock_Cursor *cur;
3242    Eina_Bool ret;
3243    if (!wd) return EINA_TRUE;
3244
3245 #if 0
3246    /* It's a hack until we get the support suggested above.
3247     * We just create a cursor, point it to the begining, and then
3248     * try to advance it, if it can advance, the tb is not empty,
3249     * otherwise it is. */
3250    tb = edje_object_part_object_get(wd->ent, "elm.text");
3251    cur = evas_object_textblock_cursor_new((Evas_Object *) tb); /* This is
3252                                                                   actually, ok for the time being, thsese hackish stuff will be removed
3253                                                                   once evas 1.0 is out*/
3254    evas_textblock_cursor_pos_set(cur, 0);
3255    ret = evas_textblock_cursor_char_next(cur);
3256    evas_textblock_cursor_free(cur);
3257
3258    return !ret;
3259 #endif
3260
3261    char *str = elm_entry_markup_to_utf8(elm_entry_entry_get(obj));
3262    if (!str) return EINA_TRUE;
3263
3264    ret = (strlen(str) == 0);
3265
3266    return ret;
3267 }
3268
3269 /**
3270  * This returns all selected text within the entry.
3271  *
3272  * @param obj The entry object
3273  * @return The selected text within the entry or NULL on failure
3274  *
3275  * @ingroup Entry
3276  */
3277 EAPI const char *
3278 elm_entry_selection_get(const Evas_Object *obj)
3279 {
3280    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3281    Widget_Data *wd = elm_widget_data_get(obj);
3282    if (!wd) return NULL;
3283    return edje_object_part_text_selection_get(wd->ent, "elm.text");
3284 }
3285
3286 /**
3287  * This inserts text in @p entry where the current cursor position.
3288  *
3289  * This inserts text at the cursor position is as if it was typed
3290  * by the user (note this also allows markup which a user
3291  * can't just "type" as it would be converted to escaped text, so this
3292  * call can be used to insert things like emoticon items or bold push/pop
3293  * tags, other font and color change tags etc.)
3294  *
3295  * @param obj The entry object
3296  * @param entry The text to insert
3297  *
3298  * @ingroup Entry
3299  */
3300 EAPI void
3301 elm_entry_entry_insert(Evas_Object *obj, const char *entry)
3302 {
3303    ELM_CHECK_WIDTYPE(obj, widtype);
3304    Widget_Data *wd = elm_widget_data_get(obj);
3305    if (!wd) return;
3306    edje_object_part_text_insert(wd->ent, "elm.text", entry);
3307    // start for cbhm
3308 #ifdef HAVE_ELEMENTARY_X
3309    if (cnpwidgetdata == obj)
3310       ecore_x_selection_secondary_set(elm_win_xwindow_get(obj), "",1);
3311 #endif
3312    // end for cbhm
3313    wd->changed = EINA_TRUE;
3314    _sizing_eval(obj);
3315 }
3316
3317 /**
3318  * This enables word line wrapping in the entry object.  It is the opposite
3319  * of elm_entry_single_line_set().  Additionally, setting this disables
3320  * character line wrapping.
3321  *
3322  * @param obj The entry object
3323  * @param wrap If true, the entry will be wrapped once it reaches the end
3324  * of the object. Wrapping will occur at the end of the word before the end of the
3325  * object.
3326  *
3327  * @ingroup Entry
3328  */
3329 EAPI void
3330 elm_entry_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
3331 {
3332    ELM_CHECK_WIDTYPE(obj, widtype);
3333    Widget_Data *wd = elm_widget_data_get(obj);
3334    if (!wd) return;
3335    if (wd->linewrap == wrap) return;
3336    wd->lastw = -1;
3337    wd->linewrap = wrap;
3338    _theme_hook(obj);
3339 }
3340
3341 /**
3342  * Get the wrapping behavior of the entry.
3343  * See also elm_entry_line_wrap_set().
3344  *
3345  * @param obj The entry object
3346  * @return Wrap type
3347  *
3348  * @ingroup Entry
3349  */
3350 EAPI Elm_Wrap_Type
3351 elm_entry_line_wrap_get(const Evas_Object *obj)
3352 {
3353    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3354    Widget_Data *wd = elm_widget_data_get(obj);
3355    if (!wd) return EINA_FALSE;
3356    return wd->linewrap;
3357 }
3358
3359 /**
3360  * This sets the editable attribute of the entry.
3361  *
3362  * @param obj The entry object
3363  * @param editable If true, the entry will be editable by the user.
3364  * If false, it will be set to the disabled state.
3365  *
3366  * @ingroup Entry
3367  */
3368 EAPI void
3369 elm_entry_editable_set(Evas_Object *obj, Eina_Bool editable)
3370 {
3371    ELM_CHECK_WIDTYPE(obj, widtype);
3372    Widget_Data *wd = elm_widget_data_get(obj);
3373    if (!wd) return;
3374    if (wd->editable == editable) return;
3375    wd->editable = editable;
3376    _theme_hook(obj);
3377
3378 #ifdef HAVE_ELEMENTARY_X
3379    if (editable)
3380      elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP, _drag_drop_cb, NULL);
3381    else
3382      elm_drop_target_del(obj);
3383 #endif
3384 }
3385
3386 /**
3387  * This gets the editable attribute of the entry.
3388  * See also elm_entry_editable_set().
3389  *
3390  * @param obj The entry object
3391  * @return If true, the entry is editable by the user.
3392  * If false, it is not editable by the user
3393  *
3394  * @ingroup Entry
3395  */
3396 EAPI Eina_Bool
3397 elm_entry_editable_get(const Evas_Object *obj)
3398 {
3399    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3400    Widget_Data *wd = elm_widget_data_get(obj);
3401    if (!wd) return EINA_FALSE;
3402    return wd->editable;
3403 }
3404
3405 /**
3406  * This drops any existing text selection within the entry.
3407  *
3408  * @param obj The entry object
3409  *
3410  * @ingroup Entry
3411  */
3412 EAPI void
3413 elm_entry_select_none(Evas_Object *obj)
3414 {
3415    ELM_CHECK_WIDTYPE(obj, widtype);
3416    Widget_Data *wd = elm_widget_data_get(obj);
3417    if (!wd) return;
3418    if (wd->selmode)
3419      {
3420         wd->selmode = EINA_FALSE;
3421         if (!_elm_config->desktop_entry)
3422           edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
3423         edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
3424      }
3425    wd->have_selection = EINA_FALSE;
3426    edje_object_part_text_select_none(wd->ent, "elm.text");
3427 }
3428
3429 /**
3430  * This selects all text within the entry.
3431  *
3432  * @param obj The entry object
3433  *
3434  * @ingroup Entry
3435  */
3436 EAPI void
3437 elm_entry_select_all(Evas_Object *obj)
3438 {
3439    ELM_CHECK_WIDTYPE(obj, widtype);
3440    Widget_Data *wd = elm_widget_data_get(obj);
3441    if (!wd) return;
3442    if (wd->selmode)
3443      {
3444         wd->selmode = EINA_FALSE;
3445         if (!_elm_config->desktop_entry)
3446           edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
3447         edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
3448      }
3449    wd->have_selection = EINA_TRUE;
3450    edje_object_part_text_select_all(wd->ent, "elm.text");
3451 }
3452
3453 /**
3454  * This function returns the geometry of the cursor.
3455  *
3456  * It's useful if you want to draw something on the cursor (or where it is),
3457  * or for example in the case of scrolled entry where you want to show the
3458  * cursor.
3459  *
3460  * @param obj The entry object
3461  * @param x returned geometry
3462  * @param y returned geometry
3463  * @param w returned geometry
3464  * @param h returned geometry
3465  * @return EINA_TRUE upon success, EINA_FALSE upon failure
3466  *
3467  * @ingroup Entry
3468  */
3469 EAPI Eina_Bool
3470 elm_entry_cursor_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3471 {
3472    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3473    Widget_Data *wd = elm_widget_data_get(obj);
3474    if (!wd) return EINA_FALSE;
3475    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
3476    return EINA_TRUE;
3477 }
3478
3479 /**
3480  * This moves the cursor one place to the right within the entry.
3481  *
3482  * @param obj The entry object
3483  * @return EINA_TRUE upon success, EINA_FALSE upon failure
3484  *
3485  * @ingroup Entry
3486  */
3487 EAPI Eina_Bool
3488 elm_entry_cursor_next(Evas_Object *obj)
3489 {
3490    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3491    Widget_Data *wd = elm_widget_data_get(obj);
3492    if (!wd) return EINA_FALSE;
3493    return edje_object_part_text_cursor_next(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3494 }
3495
3496 /**
3497  * This moves the cursor one place to the left within the entry.
3498  *
3499  * @param obj The entry object
3500  * @return EINA_TRUE upon success, EINA_FALSE upon failure
3501  *
3502  * @ingroup Entry
3503  */
3504 EAPI Eina_Bool
3505 elm_entry_cursor_prev(Evas_Object *obj)
3506 {
3507    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3508    Widget_Data *wd = elm_widget_data_get(obj);
3509    if (!wd) return EINA_FALSE;
3510    return edje_object_part_text_cursor_prev(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3511 }
3512
3513 /**
3514  * This moves the cursor one line up within the entry.
3515  *
3516  * @param obj The entry object
3517  * @return EINA_TRUE upon success, EINA_FALSE upon failure
3518  *
3519  * @ingroup Entry
3520  */
3521 EAPI Eina_Bool
3522 elm_entry_cursor_up(Evas_Object *obj)
3523 {
3524    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3525    Widget_Data *wd = elm_widget_data_get(obj);
3526    if (!wd) return EINA_FALSE;
3527    return edje_object_part_text_cursor_up(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3528 }
3529
3530 /**
3531  * This moves the cursor one line down within the entry.
3532  *
3533  * @param obj The entry object
3534  * @return EINA_TRUE upon success, EINA_FALSE upon failure
3535  *
3536  * @ingroup Entry
3537  */
3538 EAPI Eina_Bool
3539 elm_entry_cursor_down(Evas_Object *obj)
3540 {
3541    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3542    Widget_Data *wd = elm_widget_data_get(obj);
3543    if (!wd) return EINA_FALSE;
3544    return edje_object_part_text_cursor_down(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3545 }
3546
3547 /**
3548  * This moves the cursor to the beginning of the entry.
3549  *
3550  * @param obj The entry object
3551  *
3552  * @ingroup Entry
3553  */
3554 EAPI void
3555 elm_entry_cursor_begin_set(Evas_Object *obj)
3556 {
3557    ELM_CHECK_WIDTYPE(obj, widtype);
3558    Widget_Data *wd = elm_widget_data_get(obj);
3559    if (!wd) return;
3560    edje_object_part_text_cursor_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3561 }
3562
3563 /**
3564  * This moves the cursor to the end of the entry.
3565  *
3566  * @param obj The entry object
3567  *
3568  * @ingroup Entry
3569  */
3570 EAPI void
3571 elm_entry_cursor_end_set(Evas_Object *obj)
3572 {
3573    ELM_CHECK_WIDTYPE(obj, widtype);
3574    Widget_Data *wd = elm_widget_data_get(obj);
3575    if (!wd) return;
3576    int x, y, w, h;
3577    edje_object_part_text_cursor_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3578    if (wd->scroll)
3579      {
3580         elm_widget_show_region_get(wd->ent, &x, &y, &w, &h);
3581         elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
3582      }
3583 }
3584
3585 /**
3586  * This moves the cursor to the beginning of the current line.
3587  *
3588  * @param obj The entry object
3589  *
3590  * @ingroup Entry
3591  */
3592 EAPI void
3593 elm_entry_cursor_line_begin_set(Evas_Object *obj)
3594 {
3595    ELM_CHECK_WIDTYPE(obj, widtype);
3596    Widget_Data *wd = elm_widget_data_get(obj);
3597    if (!wd) return;
3598    edje_object_part_text_cursor_line_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3599 }
3600
3601 /**
3602  * This moves the cursor to the end of the current line.
3603  *
3604  * @param obj The entry object
3605  *
3606  * @ingroup Entry
3607  */
3608 EAPI void
3609 elm_entry_cursor_line_end_set(Evas_Object *obj)
3610 {
3611    ELM_CHECK_WIDTYPE(obj, widtype);
3612    Widget_Data *wd = elm_widget_data_get(obj);
3613    if (!wd) return;
3614    edje_object_part_text_cursor_line_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3615 }
3616
3617 /**
3618  * This begins a selection within the entry as though
3619  * the user were holding down the mouse button to make a selection.
3620  *
3621  * @param obj The entry object
3622  *
3623  * @ingroup Entry
3624  */
3625 EAPI void
3626 elm_entry_cursor_selection_begin(Evas_Object *obj)
3627 {
3628    ELM_CHECK_WIDTYPE(obj, widtype);
3629    Widget_Data *wd = elm_widget_data_get(obj);
3630    if (!wd) return;
3631    edje_object_part_text_select_begin(wd->ent, "elm.text");
3632 }
3633
3634 /**
3635  * This ends a selection within the entry as though
3636  * the user had just released the mouse button while making a selection.
3637  *
3638  * @param obj The entry object
3639  *
3640  * @ingroup Entry
3641  */
3642 EAPI void
3643 elm_entry_cursor_selection_end(Evas_Object *obj)
3644 {
3645    ELM_CHECK_WIDTYPE(obj, widtype);
3646    Widget_Data *wd = elm_widget_data_get(obj);
3647    if (!wd) return;
3648    edje_object_part_text_select_extend(wd->ent, "elm.text");
3649 }
3650
3651 /**
3652  * TODO: fill this in
3653  *
3654  * @param obj The entry object
3655  * @return TODO: fill this in
3656  *
3657  * @ingroup Entry
3658  */
3659 EAPI Eina_Bool
3660 elm_entry_cursor_is_format_get(const Evas_Object *obj)
3661 {
3662    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3663    Widget_Data *wd = elm_widget_data_get(obj);
3664    if (!wd) return EINA_FALSE;
3665    return edje_object_part_text_cursor_is_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3666 }
3667
3668 /**
3669  * This returns whether the cursor is visible.
3670  *
3671  * @param obj The entry object
3672  * @return If true, the cursor is visible.
3673  *
3674  * @ingroup Entry
3675  */
3676 EAPI Eina_Bool
3677 elm_entry_cursor_is_visible_format_get(const Evas_Object *obj)
3678 {
3679    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3680    Widget_Data *wd = elm_widget_data_get(obj);
3681    if (!wd) return EINA_FALSE;
3682    return edje_object_part_text_cursor_is_visible_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3683 }
3684
3685 /**
3686  * TODO: fill this in
3687  *
3688  * @param obj The entry object
3689  * @return TODO: fill this in
3690  *
3691  * @ingroup Entry
3692  */
3693 EAPI const char *
3694 elm_entry_cursor_content_get(const Evas_Object *obj)
3695 {
3696    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3697    Widget_Data *wd = elm_widget_data_get(obj);
3698    if (!wd) return NULL;
3699    return edje_object_part_text_cursor_content_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3700 }
3701
3702 /**
3703  * Sets the cursor position in the entry to the given value
3704  *
3705  * @param obj The entry object
3706  * @param pos The position of the cursor
3707  *
3708  * @ingroup Entry
3709  */
3710 EAPI void
3711 elm_entry_cursor_pos_set(Evas_Object *obj, int pos)
3712 {
3713    ELM_CHECK_WIDTYPE(obj, widtype);
3714    Widget_Data *wd = elm_widget_data_get(obj);
3715    if (!wd) return;
3716    edje_object_part_text_cursor_pos_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN, pos);
3717    edje_object_message_signal_process(wd->ent);
3718 }
3719
3720 /**
3721  * Retrieves the current position of the cursor in the entry
3722  *
3723  * @param obj The entry object
3724  * @return The cursor position
3725  *
3726  * @ingroup Entry
3727  */
3728 EAPI int
3729 elm_entry_cursor_pos_get(const Evas_Object *obj)
3730 {
3731    ELM_CHECK_WIDTYPE(obj, widtype) 0;
3732    Widget_Data *wd = elm_widget_data_get(obj);
3733    if (!wd) return 0;
3734    return edje_object_part_text_cursor_pos_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
3735 }
3736
3737 /**
3738  * This executes a "cut" action on the selected text in the entry.
3739  *
3740  * @param obj The entry object
3741  *
3742  * @ingroup Entry
3743  */
3744 EAPI void
3745 elm_entry_selection_cut(Evas_Object *obj)
3746 {
3747    ELM_CHECK_WIDTYPE(obj, widtype);
3748    Widget_Data *wd = elm_widget_data_get(obj);
3749    if (!wd) return;
3750    _cut(obj, NULL, NULL);
3751 }
3752
3753 /**
3754  * This executes a "copy" action on the selected text in the entry.
3755  *
3756  * @param obj The entry object
3757  *
3758  * @ingroup Entry
3759  */
3760 EAPI void
3761 elm_entry_selection_copy(Evas_Object *obj)
3762 {
3763    ELM_CHECK_WIDTYPE(obj, widtype);
3764    Widget_Data *wd = elm_widget_data_get(obj);
3765    if (!wd) return;
3766    _copy(obj, NULL, NULL);
3767 }
3768
3769 /**
3770  * This executes a "paste" action in the entry.
3771  *
3772  * @param obj The entry object
3773  *
3774  * @ingroup Entry
3775  */
3776 EAPI void
3777 elm_entry_selection_paste(Evas_Object *obj)
3778 {
3779    ELM_CHECK_WIDTYPE(obj, widtype);
3780    Widget_Data *wd = elm_widget_data_get(obj);
3781    if (!wd) return;
3782    _paste(obj, NULL, NULL);
3783 }
3784
3785 /**
3786  * This clears and frees the items in a entry's contextual (right click) menu.
3787  *
3788  * @param obj The entry object
3789  *
3790  * @ingroup Entry
3791  */
3792 EAPI void
3793 elm_entry_context_menu_clear(Evas_Object *obj)
3794 {
3795    ELM_CHECK_WIDTYPE(obj, widtype);
3796    Widget_Data *wd = elm_widget_data_get(obj);
3797    Elm_Entry_Context_Menu_Item *it;
3798    if (!wd) return;
3799    EINA_LIST_FREE(wd->items, it)
3800      {
3801         eina_stringshare_del(it->label);
3802         eina_stringshare_del(it->icon_file);
3803         eina_stringshare_del(it->icon_group);
3804         free(it);
3805      }
3806 }
3807
3808 /**
3809  * This adds an item to the entry's contextual menu.
3810  *
3811  * @param obj The entry object
3812  * @param label The item's text label
3813  * @param icon_file The item's icon file
3814  * @param icon_type The item's icon type
3815  * @param func The callback to execute when the item is clicked
3816  * @param data The data to associate with the item for related functions
3817  *
3818  * @ingroup Entry
3819  */
3820 EAPI void
3821 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)
3822 {
3823    ELM_CHECK_WIDTYPE(obj, widtype);
3824    Widget_Data *wd = elm_widget_data_get(obj);
3825    Elm_Entry_Context_Menu_Item *it;
3826    if (!wd) return;
3827    it = calloc(1, sizeof(Elm_Entry_Context_Menu_Item));
3828    if (!it) return;
3829    wd->items = eina_list_append(wd->items, it);
3830    it->obj = obj;
3831    it->label = eina_stringshare_add(label);
3832    it->icon_file = eina_stringshare_add(icon_file);
3833    it->icon_type = icon_type;
3834    it->func = func;
3835    it->data = (void *)data;
3836 }
3837
3838 /**
3839  * This disables the entry's contextual (right click) menu.
3840  *
3841  * @param obj The entry object
3842  * @param disabled If true, the menu is disabled
3843  *
3844  * @ingroup Entry
3845  */
3846 EAPI void
3847 elm_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3848 {
3849    ELM_CHECK_WIDTYPE(obj, widtype);
3850    Widget_Data *wd = elm_widget_data_get(obj);
3851    if (!wd) return;
3852    if (wd->context_menu == !disabled) return;
3853    wd->context_menu = !disabled;
3854 }
3855
3856 /**
3857  * This returns whether the entry's contextual (right click) menu is disabled.
3858  *
3859  * @param obj The entry object
3860  * @return If true, the menu is disabled
3861  *
3862  * @ingroup Entry
3863  */
3864 EAPI Eina_Bool
3865 elm_entry_context_menu_disabled_get(const Evas_Object *obj)
3866 {
3867    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3868    Widget_Data *wd = elm_widget_data_get(obj);
3869    if (!wd) return EINA_FALSE;
3870    return !wd->context_menu;
3871 }
3872
3873 /**
3874  * This appends a custom item provider to the list for that entry
3875  *
3876  * This appends the given callback. The list is walked from beginning to end
3877  * with each function called given the item href string in the text. If the
3878  * function returns an object handle other than NULL (it should create an
3879  * and object to do this), then this object is used to replace that item. If
3880  * not the next provider is called until one provides an item object, or the
3881  * default provider in entry does.
3882  *
3883  * @param obj The entry object
3884  * @param func The function called to provide the item object
3885  * @param data The data passed to @p func
3886  *
3887  * @ingroup Entry
3888  */
3889 EAPI void
3890 elm_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
3891 {
3892    ELM_CHECK_WIDTYPE(obj, widtype);
3893    Widget_Data *wd = elm_widget_data_get(obj);
3894    if (!wd) return;
3895    EINA_SAFETY_ON_NULL_RETURN(func);
3896    Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
3897    if (!ip) return;
3898    ip->func = func;
3899    ip->data = data;
3900    wd->item_providers = eina_list_append(wd->item_providers, ip);
3901 }
3902
3903 /**
3904  * This prepends a custom item provider to the list for that entry
3905  *
3906  * This prepends the given callback. See elm_entry_item_provider_append() for
3907  * more information
3908  *
3909  * @param obj The entry object
3910  * @param func The function called to provide the item object
3911  * @param data The data passed to @p func
3912  *
3913  * @ingroup Entry
3914  */
3915 EAPI void
3916 elm_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
3917 {
3918    ELM_CHECK_WIDTYPE(obj, widtype);
3919    Widget_Data *wd = elm_widget_data_get(obj);
3920    if (!wd) return;
3921    EINA_SAFETY_ON_NULL_RETURN(func);
3922    Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
3923    if (!ip) return;
3924    ip->func = func;
3925    ip->data = data;
3926    wd->item_providers = eina_list_prepend(wd->item_providers, ip);
3927 }
3928
3929 /**
3930  * This removes a custom item provider to the list for that entry
3931  *
3932  * This removes the given callback. See elm_entry_item_provider_append() for
3933  * more information
3934  *
3935  * @param obj The entry object
3936  * @param func The function called to provide the item object
3937  * @param data The data passed to @p func
3938  *
3939  * @ingroup Entry
3940  */
3941 EAPI void
3942 elm_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
3943 {
3944    ELM_CHECK_WIDTYPE(obj, widtype);
3945    Widget_Data *wd = elm_widget_data_get(obj);
3946    Eina_List *l;
3947    Elm_Entry_Item_Provider *ip;
3948    if (!wd) return;
3949    EINA_SAFETY_ON_NULL_RETURN(func);
3950    EINA_LIST_FOREACH(wd->item_providers, l, ip)
3951      {
3952         if ((ip->func == func) && ((!data) || (ip->data == data)))
3953           {
3954              wd->item_providers = eina_list_remove_list(wd->item_providers, l);
3955              free(ip);
3956              return;
3957           }
3958      }
3959 }
3960
3961 /**
3962  * Append a filter function for text inserted in the entry
3963  *
3964  * Append the given callback to the list. This functions will be called
3965  * whenever any text is inserted into the entry, with the text to be inserted
3966  * as a parameter. The callback function is free to alter the text in any way
3967  * it wants, but it must remember to free the given pointer and update it.
3968  * If the new text is to be discarded, the function can free it and set it text
3969  * parameter to NULL. This will also prevent any following filters from being
3970  * called.
3971  *
3972  * @param obj The entry object
3973  * @param func The function to use as text filter
3974  * @param data User data to pass to @p func
3975  *
3976  * @ingroup Entry
3977  */
3978 EAPI void
3979 elm_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
3980 {
3981    Widget_Data *wd;
3982    Elm_Entry_Text_Filter *tf;
3983    ELM_CHECK_WIDTYPE(obj, widtype);
3984
3985    wd = elm_widget_data_get(obj);
3986
3987    EINA_SAFETY_ON_NULL_RETURN(func);
3988
3989    tf = _filter_new(func, data);
3990    if (!tf) return;
3991
3992    wd->text_filters = eina_list_append(wd->text_filters, tf);
3993 }
3994
3995 /**
3996  * Prepend a filter function for text insdrted in the entry
3997  *
3998  * Prepend the given callback to the list. See elm_entry_text_filter_append()
3999  * for more information
4000  *
4001  * @param obj The entry object
4002  * @param func The function to use as text filter
4003  * @param data User data to pass to @p func
4004  *
4005  * @ingroup Entry
4006  */
4007 EAPI void
4008 elm_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
4009 {
4010    Widget_Data *wd;
4011    Elm_Entry_Text_Filter *tf;
4012    ELM_CHECK_WIDTYPE(obj, widtype);
4013
4014    wd = elm_widget_data_get(obj);
4015
4016    EINA_SAFETY_ON_NULL_RETURN(func);
4017
4018    tf = _filter_new(func, data);
4019    if (!tf) return;
4020
4021    wd->text_filters = eina_list_prepend(wd->text_filters, tf);
4022 }
4023
4024 /**
4025  * Remove a filter from the list
4026  *
4027  * Removes the given callback from the filter list. See elm_entry_text_filter_append()
4028  * for more information.
4029  *
4030  * @param obj The entry object
4031  * @param func The filter function to remove
4032  * @param data The user data passed when adding the function
4033  *
4034  * @ingroup Entry
4035  */
4036 EAPI void
4037 elm_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
4038 {
4039    Widget_Data *wd;
4040    Eina_List *l;
4041    Elm_Entry_Text_Filter *tf;
4042    ELM_CHECK_WIDTYPE(obj, widtype);
4043
4044    wd = elm_widget_data_get(obj);
4045
4046    EINA_SAFETY_ON_NULL_RETURN(func);
4047
4048    EINA_LIST_FOREACH(wd->text_filters, l, tf)
4049      {
4050         if ((tf->func == func) && ((!data) || (tf->data == data)))
4051           {
4052              wd->text_filters = eina_list_remove_list(wd->text_filters, l);
4053              _filter_free(tf);
4054              return;
4055           }
4056      }
4057 }
4058
4059 /**
4060  * This converts a markup (HTML-like) string into UTF-8.
4061  * Returning string is obtained with malloc.
4062  * After use the returned string, it should be freed.
4063  *
4064  * @param s The string (in markup) to be converted
4065  * @return The converted string (in UTF-8). It should be freed.
4066  *
4067  * @ingroup Entry
4068  */
4069 EAPI char *
4070 elm_entry_markup_to_utf8(const char *s)
4071 {
4072    char *ss = _elm_util_mkup_to_text(s);
4073    if (!ss) ss = strdup("");
4074    return ss;
4075 }
4076
4077 /**
4078  * This converts a UTF-8 string into markup (HTML-like).
4079  * Returning string is obtained with malloc.
4080  * After use the returned string, it should be freed.
4081  *
4082  * @param s The string (in UTF-8) to be converted
4083  * @return The converted string (in markup). It should be freed.
4084  *
4085  * @ingroup Entry
4086  */
4087 EAPI char *
4088 elm_entry_utf8_to_markup(const char *s)
4089 {
4090    char *ss = _elm_util_text_to_mkup(s);
4091    if (!ss) ss = strdup("");
4092    return ss;
4093 }
4094
4095 /**
4096  * Filter inserted text based on user defined character and byte limits
4097  *
4098  * Add this filter to an entry to limit the characters that it will accept
4099  * based the the contents of the provided Elm_Entry_Filter_Limit_Size.
4100  * The funtion works on the UTF-8 representation of the string, converting
4101  * it from the set markup, thus not accounting for any format in it.
4102  *
4103  * The user must create an Elm_Entry_Filter_Limit_Size structure and pass
4104  * it as data when setting the filter. In it it's possible to set limits
4105  * by character count or bytes (any of them is disabled if 0), and both can
4106  * be set at the same time. In that case, it first checks for characters,
4107  * then bytes.
4108  *
4109  * The function will cut the inserted text in order to allow only the first
4110  * number of characters that are still allowed. The cut is made in
4111  * characters, even when limiting by bytes, in order to always contain
4112  * valid ones and avoid half unicode characters making it in.
4113  *
4114  * @ingroup Entry
4115  */
4116 EAPI void
4117 elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text)
4118 {
4119    Elm_Entry_Filter_Limit_Size *lim = data;
4120    char *current;
4121    int len, newlen;
4122    const char *(*text_get)(const Evas_Object *);
4123    const char *widget_type;
4124
4125    EINA_SAFETY_ON_NULL_RETURN(data);
4126    EINA_SAFETY_ON_NULL_RETURN(entry);
4127    EINA_SAFETY_ON_NULL_RETURN(text);
4128
4129    /* hack. I don't want to copy the entire function to work with
4130     * scrolled_entry */
4131    widget_type = elm_widget_type_get(entry);
4132    if (!strcmp(widget_type, "entry"))
4133      text_get = elm_entry_entry_get;
4134    else /* huh? */
4135      return;
4136
4137    current = elm_entry_markup_to_utf8(text_get(entry));
4138
4139    if (lim->max_char_count > 0)
4140      {
4141         len = evas_string_char_len_get(current);
4142         if (len >= lim->max_char_count)
4143           {
4144              evas_object_smart_callback_call(entry, "maxlength,reached", NULL);
4145              free(*text);
4146              free(current);
4147              *text = NULL;
4148              return;
4149           }
4150         newlen = evas_string_char_len_get(elm_entry_markup_to_utf8(*text));
4151         if ((len + newlen) > lim->max_char_count)
4152           _add_chars_till_limit(entry, text, (lim->max_char_count - len), LENGTH_UNIT_CHAR);
4153      }
4154    else if (lim->max_byte_count > 0)
4155      {
4156         len = strlen(current);
4157         if (len >= lim->max_byte_count)
4158           {
4159              evas_object_smart_callback_call(entry, "maxlength,reached", NULL);
4160              free(*text);
4161              free(current);
4162              *text = NULL;
4163              return;
4164           }
4165         newlen = strlen(elm_entry_markup_to_utf8(*text));
4166         if ((len + newlen) > lim->max_byte_count)
4167           _add_chars_till_limit(entry, text, (lim->max_byte_count - len), LENGTH_UNIT_BYTE);
4168      }
4169    free(current);
4170 }
4171
4172 /**
4173  * Filter inserted text based on accepted or rejected sets of characters
4174  *
4175  * Add this filter to an entry to restrict the set of accepted characters
4176  * based on the sets in the provided Elm_Entry_Filter_Accept_Set.
4177  * This structure contains both accepted and rejected sets, but they are
4178  * mutually exclusive. If accepted is set, it will be used, otherwise it
4179  * goes on to the rejected set.
4180  */
4181 EAPI void
4182 elm_entry_filter_accept_set(void *data, Evas_Object *entry __UNUSED__, char **text)
4183 {
4184    Elm_Entry_Filter_Accept_Set *as = data;
4185    const char *set;
4186    char *insert;
4187    Eina_Bool goes_in;
4188    int read_idx, last_read_idx = 0, read_char;
4189
4190    EINA_SAFETY_ON_NULL_RETURN(data);
4191    EINA_SAFETY_ON_NULL_RETURN(text);
4192
4193    if ((!as->accepted) && (!as->rejected))
4194      return;
4195
4196    if (as->accepted)
4197      {
4198         set = as->accepted;
4199         goes_in = EINA_TRUE;
4200      }
4201    else
4202      {
4203         set = as->rejected;
4204         goes_in = EINA_FALSE;
4205      }
4206
4207    insert = *text;
4208    read_idx = evas_string_char_next_get(*text, 0, &read_char);
4209    while (read_char)
4210      {
4211         int cmp_idx, cmp_char;
4212         Eina_Bool in_set = EINA_FALSE;
4213
4214         cmp_idx = evas_string_char_next_get(set, 0, &cmp_char);
4215         while (cmp_char)
4216           {
4217              if (read_char == cmp_char)
4218                {
4219                   in_set = EINA_TRUE;
4220                   break;
4221                }
4222              cmp_idx = evas_string_char_next_get(set, cmp_idx, &cmp_char);
4223           }
4224         if (in_set == goes_in)
4225           {
4226              int size = read_idx - last_read_idx;
4227              const char *src = (*text) + last_read_idx;
4228              if (src != insert)
4229                memcpy(insert, *text + last_read_idx, size);
4230              insert += size;
4231           }
4232         last_read_idx = read_idx;
4233         read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
4234      }
4235    *insert = 0;
4236 }
4237
4238 /**
4239  * This sets the file (and implicitly loads it) for the text to display and
4240  * then edit. All changes are written back to the file after a short delay if
4241  * the entry object is set to autosave.
4242  *
4243  * @param obj The entry object
4244  * @param file The path to the file to load and save
4245  * @param format The file format
4246  *
4247  * @ingroup Entry
4248  */
4249 EAPI void
4250 elm_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format)
4251 {
4252    ELM_CHECK_WIDTYPE(obj, widtype);
4253    Widget_Data *wd = elm_widget_data_get(obj);
4254    if (!wd) return;
4255    if (wd->delay_write)
4256      {
4257         ecore_timer_del(wd->delay_write);
4258         wd->delay_write = NULL;
4259      }
4260    if (wd->autosave) _save(obj);
4261    eina_stringshare_replace(&wd->file, file);
4262    wd->format = format;
4263    _load(obj);
4264 }
4265
4266 /**
4267  * Gets the file to load and save and the file format
4268  *
4269  * @param obj The entry object
4270  * @param file The path to the file to load and save
4271  * @param format The file format
4272  *
4273  * @ingroup Entry
4274  */
4275 EAPI void
4276 elm_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format)
4277 {
4278    ELM_CHECK_WIDTYPE(obj, widtype);
4279    Widget_Data *wd = elm_widget_data_get(obj);
4280    if (!wd) return;
4281    if (file) *file = wd->file;
4282    if (format) *format = wd->format;
4283 }
4284
4285 /**
4286  * This function writes any changes made to the file set with
4287  * elm_entry_file_set()
4288  *
4289  * @param obj The entry object
4290  *
4291  * @ingroup Entry
4292  */
4293 EAPI void
4294 elm_entry_file_save(Evas_Object *obj)
4295 {
4296    ELM_CHECK_WIDTYPE(obj, widtype);
4297    Widget_Data *wd = elm_widget_data_get(obj);
4298    if (!wd) return;
4299    if (wd->delay_write)
4300      {
4301         ecore_timer_del(wd->delay_write);
4302         wd->delay_write = NULL;
4303      }
4304    _save(obj);
4305    wd->delay_write = ecore_timer_add(2.0, _delay_write, obj);
4306 }
4307
4308 /**
4309  * This sets the entry object to 'autosave' the loaded text file or not.
4310  *
4311  * @param obj The entry object
4312  * @param autosave Autosave the loaded file or not
4313  *
4314  * @ingroup Entry
4315  */
4316 EAPI void
4317 elm_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave)
4318 {
4319    ELM_CHECK_WIDTYPE(obj, widtype);
4320    Widget_Data *wd = elm_widget_data_get(obj);
4321    if (!wd) return;
4322    wd->autosave = !!autosave;
4323 }
4324
4325 /**
4326  * This gets the entry object's 'autosave' status.
4327  *
4328  * @param obj The entry object
4329  * @return Autosave the loaded file or not
4330  *
4331  * @ingroup Entry
4332  */
4333 EAPI Eina_Bool
4334 elm_entry_autosave_get(const Evas_Object *obj)
4335 {
4336    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4337    Widget_Data *wd = elm_widget_data_get(obj);
4338    if (!wd) return EINA_FALSE;
4339    return wd->autosave;
4340 }
4341
4342 /**
4343  * Control pasting of text and images for the widget.
4344  *
4345  * Normally the entry allows both text and images to be pasted.  By setting
4346  * textonly to be true, this prevents images from being pasted.
4347  *
4348  * Note this only changes the behaviour of text.
4349  *
4350  * @param obj The entry object
4351  * @param textonly paste mode - EINA_TRUE is text only, EINA_FALSE is text+image+other.
4352  *
4353  * @ingroup Entry
4354  */
4355 EAPI void
4356 elm_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly)
4357 {
4358    Elm_Sel_Format format = ELM_SEL_FORMAT_MARKUP;
4359    ELM_CHECK_WIDTYPE(obj, widtype);
4360    Widget_Data *wd = elm_widget_data_get(obj);
4361    if (!wd) return;
4362    textonly = !!textonly;
4363    if (wd->textonly == textonly) return;
4364    wd->textonly = !!textonly;
4365    if (!textonly) format |= ELM_SEL_FORMAT_IMAGE;
4366 #ifdef HAVE_ELEMENTARY_X
4367    elm_drop_target_add(obj, format, _drag_drop_cb, NULL);
4368 #endif
4369 }
4370
4371 /**
4372  * Getting elm_entry text paste/drop mode.
4373  *
4374  * In textonly mode, only text may be pasted or dropped into the widget.
4375  *
4376  * @param obj The entry object
4377  * @return If the widget only accepts text from pastes.
4378  *
4379  * @ingroup Entry
4380  */
4381 EAPI Eina_Bool
4382 elm_entry_cnp_textonly_get(const Evas_Object *obj)
4383 {
4384    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4385    Widget_Data *wd = elm_widget_data_get(obj);
4386    if (!wd) return EINA_FALSE;
4387    return wd->textonly;
4388 }
4389
4390 /**
4391  * Enable or disable scrolling in entry
4392  *
4393  * Normally the entry is not scrollable unless you enable it with this call.
4394  *
4395  * @param obj The entry object
4396  * @param scroll EINA_TRUE if it is to be scrollable, EINA_FALSE otherwise
4397  *
4398  * @ingroup Entry
4399  */
4400 EAPI void
4401 elm_entry_scrollable_set(Evas_Object *obj, Eina_Bool scroll)
4402 {
4403    ELM_CHECK_WIDTYPE(obj, widtype);
4404    Widget_Data *wd = elm_widget_data_get(obj);
4405    if (!wd) return;
4406    scroll = !!scroll;
4407    if (wd->scroll == scroll) return;
4408    wd->scroll = scroll;
4409    if (wd->scroll)
4410      {
4411         elm_widget_sub_object_del(obj, wd->scroller);
4412         elm_widget_resize_object_set(obj, wd->scroller);
4413         elm_widget_sub_object_add(obj, wd->ent);
4414         elm_smart_scroller_child_set(wd->scroller, wd->ent);
4415         evas_object_show(wd->scroller);
4416         elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
4417         if (wd->single_line)
4418           {
4419              elm_smart_scroller_policy_set(wd->scroller,
4420                                            ELM_SMART_SCROLLER_POLICY_OFF,
4421                                            ELM_SMART_SCROLLER_POLICY_OFF);
4422              elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_FALSE, EINA_FALSE);
4423           }
4424         else
4425           {
4426              const Elm_Scroller_Policy map[3] =
4427                {
4428                   ELM_SMART_SCROLLER_POLICY_AUTO,
4429                   ELM_SMART_SCROLLER_POLICY_ON,
4430                   ELM_SMART_SCROLLER_POLICY_OFF
4431                };
4432              elm_smart_scroller_policy_set(wd->scroller,
4433                                            map[wd->policy_h],
4434                                            map[wd->policy_v]);
4435              elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_FALSE, EINA_FALSE);
4436           }
4437      }
4438    else
4439      {
4440         elm_smart_scroller_child_set(wd->scroller, NULL);
4441         elm_widget_sub_object_del(obj, wd->ent);
4442         elm_widget_resize_object_set(obj, wd->ent);
4443         evas_object_smart_member_add(wd->scroller, obj);
4444         elm_widget_sub_object_add(obj, wd->scroller);
4445         evas_object_hide(wd->scroller);
4446         elm_widget_on_show_region_hook_set(obj, NULL, NULL);
4447      }
4448    wd->lastw = -1;
4449    _theme_hook(obj);
4450 }
4451
4452 /**
4453  * Get the scrollable state of the entry
4454  *
4455  * Normally the entry is not scrollable. This gets the scrollable state
4456  * of the entry. See elm_entry_scrollable_set() for more information.
4457  *
4458  * @param obj The entry object
4459  * @return The scrollable state
4460  *
4461  * @ingroup Entry
4462  */
4463 EAPI Eina_Bool
4464 elm_entry_scrollable_get(const Evas_Object *obj)
4465 {
4466    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4467    Widget_Data *wd = elm_widget_data_get(obj);
4468    if (!wd) return EINA_FALSE;
4469    return wd->scroll;
4470 }
4471
4472 /**
4473  * This sets a widget to be displayed to the left of a scrolled entry.
4474  *
4475  * @param obj The scrolled entry object
4476  * @param icon The widget to display on the left side of the scrolled
4477  * entry.
4478  *
4479  * @note A previously set widget will be destroyed.
4480  * @note If the object being set does not have minimum size hints set,
4481  * it won't get properly displayed.
4482  *
4483  * @ingroup Entry
4484  * @see elm_entry_end_set
4485  */
4486 EAPI void
4487 elm_entry_icon_set(Evas_Object *obj, Evas_Object *icon)
4488 {
4489    ELM_CHECK_WIDTYPE(obj, widtype);
4490    Widget_Data *wd = elm_widget_data_get(obj);
4491    Evas_Object *edje;
4492    if (!wd) return;
4493    EINA_SAFETY_ON_NULL_RETURN(icon);
4494    if (wd->icon == icon) return;
4495    if (wd->icon) evas_object_del(wd->icon);
4496    wd->icon = icon;
4497    edje = elm_smart_scroller_edje_object_get(wd->scroller);
4498    if (!edje) return;
4499    edje_object_part_swallow(edje, "elm.swallow.icon", wd->icon);
4500    edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
4501    _sizing_eval(obj);
4502 }
4503
4504 /**
4505  * Gets the leftmost widget of the scrolled entry. This object is
4506  * owned by the scrolled entry and should not be modified.
4507  *
4508  * @param obj The scrolled entry object
4509  * @return the left widget inside the scroller
4510  *
4511  * @ingroup Entry
4512  */
4513 EAPI Evas_Object *
4514 elm_entry_icon_get(const Evas_Object *obj)
4515 {
4516    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4517    Widget_Data *wd = elm_widget_data_get(obj);
4518    if (!wd) return NULL;
4519    return wd->icon;
4520 }
4521
4522 /**
4523  * Unset the leftmost widget of the scrolled entry, unparenting and
4524  * returning it.
4525  *
4526  * @param obj The scrolled entry object
4527  * @return the previously set icon sub-object of this entry, on
4528  * success.
4529  *
4530  * @see elm_entry_icon_set()
4531  *
4532  * @ingroup Entry
4533  */
4534 EAPI Evas_Object *
4535 elm_entry_icon_unset(Evas_Object *obj)
4536 {
4537    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4538    Widget_Data *wd = elm_widget_data_get(obj);
4539    Evas_Object *ret = NULL;
4540    if (!wd) return NULL;
4541    if (wd->icon)
4542      {
4543         Evas_Object *edje = elm_smart_scroller_edje_object_get(wd->scroller);
4544         if (!edje) return NULL;
4545         ret = wd->icon;
4546         edje_object_part_unswallow(edje, wd->icon);
4547         edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
4548         wd->icon = NULL;
4549         _sizing_eval(obj);
4550      }
4551    return ret;
4552 }
4553
4554 /**
4555  * Sets the visibility of the left-side widget of the scrolled entry,
4556  * set by @elm_entry_icon_set().
4557  *
4558  * @param obj The scrolled entry object
4559  * @param setting EINA_TRUE if the object should be displayed,
4560  * EINA_FALSE if not.
4561  *
4562  * @ingroup Entry
4563  */
4564 EAPI void
4565 elm_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting)
4566 {
4567    ELM_CHECK_WIDTYPE(obj, widtype);
4568    Widget_Data *wd = elm_widget_data_get(obj);
4569    if ((!wd) || (!wd->icon)) return;
4570    if (setting)
4571       evas_object_hide(wd->icon);
4572    else
4573       evas_object_show(wd->icon);
4574    _sizing_eval(obj);
4575 }
4576
4577 /**
4578  * This sets a widget to be displayed to the end of a scrolled entry.
4579  *
4580  * @param obj The scrolled entry object
4581  * @param end The widget to display on the right side of the scrolled
4582  * entry.
4583  *
4584  * @note A previously set widget will be destroyed.
4585  * @note If the object being set does not have minimum size hints set,
4586  * it won't get properly displayed.
4587  *
4588  * @ingroup Entry
4589  * @see elm_entry_icon_set
4590  */
4591 EAPI void
4592 elm_entry_end_set(Evas_Object *obj, Evas_Object *end)
4593 {
4594    ELM_CHECK_WIDTYPE(obj, widtype);
4595    Widget_Data *wd = elm_widget_data_get(obj);
4596    Evas_Object *edje;
4597    if (!wd) return;
4598    EINA_SAFETY_ON_NULL_RETURN(end);
4599    if (wd->end == end) return;
4600    if (wd->end) evas_object_del(wd->end);
4601    wd->end = end;
4602    edje = elm_smart_scroller_edje_object_get(wd->scroller);
4603    if (!edje) return;
4604    edje_object_part_swallow(edje, "elm.swallow.end", wd->end);
4605    edje_object_signal_emit(edje, "elm,action,show,end", "elm");
4606    _sizing_eval(obj);
4607 }
4608
4609 /**
4610  * Gets the endmost widget of the scrolled entry. This object is owned
4611  * by the scrolled entry and should not be modified.
4612  *
4613  * @param obj The scrolled entry object
4614  * @return the right widget inside the scroller
4615  *
4616  * @ingroup Entry
4617  */
4618 EAPI Evas_Object *
4619 elm_entry_end_get(const Evas_Object *obj)
4620 {
4621    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4622    Widget_Data *wd = elm_widget_data_get(obj);
4623    if (!wd) return NULL;
4624    return wd->end;
4625 }
4626
4627 /**
4628  * Unset the endmost widget of the scrolled entry, unparenting and
4629  * returning it.
4630  *
4631  * @param obj The scrolled entry object
4632  * @return the previously set icon sub-object of this entry, on
4633  * success.
4634  *
4635  * @see elm_entry_icon_set()
4636  *
4637  * @ingroup Entry
4638  */
4639 EAPI Evas_Object *
4640 elm_entry_end_unset(Evas_Object *obj)
4641 {
4642    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4643    Widget_Data *wd = elm_widget_data_get(obj);
4644    Evas_Object *ret = NULL;
4645    if (!wd) return NULL;
4646    if (wd->end)
4647      {
4648         Evas_Object *edje = elm_smart_scroller_edje_object_get(wd->scroller);
4649         if (!edje) return NULL;
4650         ret = wd->end;
4651         edje_object_part_unswallow(edje, wd->end);
4652         edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
4653         wd->end = NULL;
4654         _sizing_eval(obj);
4655      }
4656    return ret;
4657 }
4658
4659 /**
4660  * Sets the visibility of the end widget of the scrolled entry, set by
4661  * @elm_entry_end_set().
4662  *
4663  * @param obj The scrolled entry object
4664  * @param setting EINA_TRUE if the object should be displayed,
4665  * EINA_FALSE if not.
4666  *
4667  * @ingroup Entry
4668  */
4669 EAPI void
4670 elm_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting)
4671 {
4672    ELM_CHECK_WIDTYPE(obj, widtype);
4673    Widget_Data *wd = elm_widget_data_get(obj);
4674    if ((!wd) || (!wd->end)) return;
4675    if (setting)
4676       evas_object_hide(wd->end);
4677    else
4678       evas_object_show(wd->end);
4679    _sizing_eval(obj);
4680 }
4681
4682 /**
4683  * This sets the scrolled entry's scrollbar policy (ie. enabling/disabling them).
4684  *
4685  * @param obj The scrolled entry object
4686  * @param h The horizontal scrollbar policy to apply
4687  * @param v The vertical scrollbar policy to apply
4688  *
4689  * @ingroup Entry
4690  */
4691 EAPI void
4692 elm_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v)
4693 {
4694    ELM_CHECK_WIDTYPE(obj, widtype);
4695    Widget_Data *wd = elm_widget_data_get(obj);
4696    const Elm_Scroller_Policy map[3] =
4697      {
4698         ELM_SMART_SCROLLER_POLICY_AUTO,
4699         ELM_SMART_SCROLLER_POLICY_ON,
4700         ELM_SMART_SCROLLER_POLICY_OFF
4701      };
4702    if (!wd) return;
4703    wd->policy_h = h;
4704    wd->policy_v = v;
4705    elm_smart_scroller_policy_set(wd->scroller,
4706                                  map[wd->policy_h],
4707                                  map[wd->policy_v]);
4708 }
4709
4710 /**
4711  * This enables/disables bouncing within the entry.
4712  *
4713  * @param obj The scrolled entry object
4714  * @param h The horizontal bounce state
4715  * @param v The vertical bounce state
4716  *
4717  * @ingroup Entry
4718  */
4719 EAPI void
4720 elm_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
4721 {
4722    ELM_CHECK_WIDTYPE(obj, widtype);
4723    Widget_Data *wd = elm_widget_data_get(obj);
4724    if (!wd) return;
4725    elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
4726 }
4727
4728 /**
4729  * Get the bounce mode
4730  *
4731  * @param obj The Entry object
4732  * @param h_bounce Allow bounce horizontally
4733  * @param v_bounce Allow bounce vertically
4734  *
4735  * @ingroup Entry
4736  */
4737 EAPI void
4738 elm_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
4739 {
4740    ELM_CHECK_WIDTYPE(obj, widtype);
4741    Widget_Data *wd = elm_widget_data_get(obj);
4742    if (!wd) return;
4743    elm_smart_scroller_bounce_allow_get(wd->scroller, h_bounce, v_bounce);
4744 }
4745
4746 EINA_DEPRECATED EAPI void
4747 elm_entry_line_char_wrap_set(Evas_Object *obj, Eina_Bool wrap)
4748 {
4749    if (wrap) elm_entry_line_wrap_set(obj, ELM_WRAP_CHAR);
4750 }
4751
4752 /**
4753  * Set background color of the entry
4754  *
4755  * @param obj The entry object
4756  * @param r Red property background color of The entry object
4757  * @param g Green property background color of The entry object
4758  * @param b Blue property background color of The entry object
4759  * @param a Alpha property background alpha of The entry object
4760  * @ingroup Entry
4761  */
4762 EAPI void
4763 elm_entry_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
4764 {
4765    ELM_CHECK_WIDTYPE(obj, widtype);
4766    Widget_Data *wd = elm_widget_data_get(obj);
4767    evas_object_color_set(wd->bg, r, g, b, a);
4768
4769    if (wd->bgcolor == EINA_FALSE)
4770      {
4771        wd->bgcolor = 1;
4772        edje_object_part_swallow(wd->ent, "entry.swallow.background", wd->bg);
4773      }
4774 }
4775
4776 /**
4777  * Set whether entry should support auto capitalization
4778  *
4779  * @param obj The entry object
4780  * @param on If true, entry suports auto capitalization.
4781  *
4782  * @ingroup Entry
4783  */
4784 EAPI void
4785 elm_entry_autocapitalization_set(Evas_Object *obj, Eina_Bool autocap)
4786 {
4787    ELM_CHECK_WIDTYPE(obj, widtype);
4788    Widget_Data *wd = elm_widget_data_get(obj);
4789    if (!wd) return;
4790
4791    if (wd->password)
4792      wd->autocapital = EINA_FALSE;
4793    else
4794      wd->autocapital = autocap;
4795
4796    if (wd->input_panel_layout == ELM_INPUT_PANEL_LAYOUT_URL ||
4797        wd->input_panel_layout == ELM_INPUT_PANEL_LAYOUT_EMAIL)
4798      wd->autocapital = EINA_FALSE;
4799
4800    edje_object_part_text_autocapitalization_set(wd->ent, "elm.text", wd->autocapital);
4801 }
4802
4803 /**
4804  * Set whether entry should support auto period
4805  *
4806  * @param obj The entry object
4807  * @param on If true, entry suports auto period.
4808  *
4809  * @ingroup Entry
4810  */
4811 EAPI void
4812 elm_entry_autoperiod_set(Evas_Object *obj, Eina_Bool autoperiod)
4813 {
4814    ELM_CHECK_WIDTYPE(obj, widtype);
4815    Widget_Data *wd = elm_widget_data_get(obj);
4816    if (!wd) return;
4817
4818    if (wd->password)
4819      wd->autoperiod = EINA_FALSE;
4820    else
4821      wd->autoperiod = autoperiod;
4822
4823    if (wd->input_panel_layout == ELM_INPUT_PANEL_LAYOUT_URL ||
4824        wd->input_panel_layout == ELM_INPUT_PANEL_LAYOUT_EMAIL)
4825      wd->autoperiod = EINA_FALSE;
4826
4827    edje_object_part_text_autoperiod_set(wd->ent, "elm.text", wd->autoperiod);
4828 }
4829
4830 /**
4831  * Set whether entry should enable the return key on soft keyboard automatically
4832  *
4833  * @param obj The entry object
4834  * @param on If true, entry enables the return key on soft keyboard automatically.
4835  *
4836  * @ingroup Entry
4837  */
4838 EAPI void
4839 elm_entry_autoenable_returnkey_set(Evas_Object *obj, Eina_Bool on)
4840 {
4841    ELM_CHECK_WIDTYPE(obj, widtype);
4842    Widget_Data *wd = elm_widget_data_get(obj);
4843    if (!wd) return;
4844
4845    wd->autoreturnkey = on;
4846    _check_enable_returnkey(obj);
4847 }
4848
4849 /**
4850  * This sets the attribute to show the input panel automatically.
4851  *
4852  * @param obj The entry object
4853  * @param enabled If true, the input panel is appeared when entry is clicked or has a focus
4854  *
4855  * @ingroup Entry
4856  */
4857 EAPI void
4858 elm_entry_input_panel_enabled_set(Evas_Object *obj, Eina_Bool enabled)
4859 {
4860    ELM_CHECK_WIDTYPE(obj, widtype);
4861    Widget_Data *wd = elm_widget_data_get(obj);
4862    if (!wd) return;
4863
4864    wd->input_panel_enable = enabled;
4865    edje_object_part_text_input_panel_enabled_set(wd->ent, "elm.text", enabled);
4866 }
4867
4868 /**
4869  * Set the input panel layout of the entry
4870  *
4871  * @param obj The entry object
4872  * @param layout the layout to set
4873  *
4874  * @ingroup Entry
4875  */
4876 EAPI void
4877 elm_entry_input_panel_layout_set(Evas_Object *obj, Elm_Input_Panel_Layout layout)
4878 {
4879    ELM_CHECK_WIDTYPE(obj, widtype);
4880    Widget_Data *wd = elm_widget_data_get(obj);
4881    if (!wd) return;
4882
4883    Ecore_IMF_Context *ic = elm_entry_imf_context_get(obj);
4884    if (!ic) return;
4885
4886    wd->input_panel_layout = layout;
4887
4888    ecore_imf_context_input_panel_layout_set(ic, (Ecore_IMF_Input_Panel_Layout)layout);
4889 }
4890
4891 /**
4892  * Get the input method context in the entry widget
4893  *
4894  * @param obj The entry object
4895  * @return The input method context
4896  *
4897  * @ingroup Entry
4898  */
4899 EAPI Ecore_IMF_Context *elm_entry_imf_context_get(Evas_Object *obj)
4900 {
4901    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4902    Widget_Data *wd = elm_widget_data_get(obj);
4903    if (!wd || !wd->ent) return NULL;
4904
4905    return edje_object_part_text_imf_context_get(wd->ent, "elm.text");
4906 }
4907
4908 EAPI void
4909 elm_entry_matchlist_set(Evas_Object *obj, Eina_List *match_list, Eina_Bool case_sensitive)
4910 {
4911    Widget_Data *wd = elm_widget_data_get(obj);
4912    if (!wd) return;
4913
4914    if (match_list)
4915      {
4916         Evas_Coord max_w = 9999, max_h = 9999;
4917         const char* key_data = NULL;
4918
4919         wd->matchlist_threshold = 1;
4920         wd->hover = elm_hover_add(elm_widget_parent_get(obj));
4921         elm_hover_parent_set(wd->hover, elm_widget_parent_get(obj));
4922         elm_hover_target_set(wd->hover, obj);
4923         elm_object_style_set(wd->hover, "matchlist");
4924
4925         wd->layout = elm_layout_add(wd->hover);
4926         elm_layout_theme_set(wd->layout, "entry", "matchlist", "default");
4927         wd->list = elm_list_add(wd->layout);
4928         evas_object_size_hint_weight_set(wd->list, EVAS_HINT_EXPAND, 0.0);
4929         evas_object_size_hint_align_set(wd->list, EVAS_HINT_FILL, EVAS_HINT_FILL);
4930         elm_list_mode_set(wd->list, ELM_LIST_EXPAND);
4931         elm_object_style_set(wd->list, "matchlist");
4932
4933         key_data = edje_object_data_get(elm_layout_edje_get(wd->layout), "max_width");
4934         if (key_data) max_w = atoi(key_data);
4935         key_data = edje_object_data_get(elm_layout_edje_get(wd->layout), "max_height");
4936         if (key_data) max_h = atoi(key_data);
4937
4938         elm_list_go(wd->list);
4939         evas_object_size_hint_max_set(wd->list, max_w, max_h);
4940         evas_object_smart_callback_add(wd->list, "selected", _matchlist_list_clicked, obj);
4941         elm_layout_content_set(wd->layout, "elm.swallow.content", wd->list);
4942         elm_hover_content_set(wd->hover, "bottom", wd->layout);
4943
4944         wd->match_list = match_list;
4945      }
4946    else
4947      {
4948         if (wd->hover)
4949           evas_object_del(wd->hover);
4950
4951         wd->match_list = NULL;
4952      }
4953
4954    wd->matchlist_case_sensitive = case_sensitive;
4955 }
4956
4957 /**
4958  * Set the magnifier style of the entry
4959  *
4960  * @param obj The entry object
4961  * @param type the magnifier style to set
4962  *
4963  * @ingroup Entry
4964  */
4965 EAPI void
4966 elm_entry_magnifier_type_set(Evas_Object *obj, int type)
4967 {
4968    ELM_CHECK_WIDTYPE(obj, widtype);
4969    Widget_Data *wd = elm_widget_data_get(obj);
4970    if (!wd) return;
4971
4972    wd->mgf_type = type;
4973    _magnifier_create(obj);
4974 }
4975
4976 /**
4977  * Set wrap width of the entry
4978  *
4979  * @param obj The entry object
4980  * @param w The wrap width in pixels at a minimum where words need to wrap
4981  * @ingroup Entry
4982  */
4983 EAPI void
4984 elm_entry_wrap_width_set(Evas_Object *obj, Evas_Coord w)
4985 {
4986    Widget_Data *wd = elm_widget_data_get(obj);
4987    if (!wd) return;
4988    if (wd->wrap_w == w) return;
4989    wd->wrap_w = w;
4990    _sizing_eval(obj);
4991 }
4992
4993 /**
4994  * get wrap width of the entry
4995  *
4996  * @param obj The entry object
4997  * @return The wrap width in pixels at a minimum where words need to wrap
4998  * @ingroup Entry
4999  */
5000 EAPI Evas_Coord
5001 elm_entry_wrap_width_get(const Evas_Object *obj)
5002 {
5003    Widget_Data *wd = elm_widget_data_get(obj);
5004    if (!wd) return;
5005    return wd->wrap_w;
5006 }
5007
5008 /**
5009  * Set the font size on the entry object
5010  *
5011  * @param obj The entry object
5012  * @param size font size
5013  *
5014  * @ingroup Entry
5015  */
5016 EAPI void
5017 elm_entry_fontsize_set(Evas_Object *obj, int fontsize)
5018 {
5019    ELM_CHECK_WIDTYPE(obj, widtype);
5020    Widget_Data *wd = elm_widget_data_get(obj);
5021    Eina_Strbuf *fontbuf = NULL;
5022    int removeflag = 0;
5023    const char *t;
5024
5025    if (!wd) return;
5026    t = eina_stringshare_add(elm_entry_entry_get(obj));
5027    fontbuf = eina_strbuf_new();
5028    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
5029
5030    if (fontsize == 0) removeflag = 1; // remove fontsize tag
5031
5032    if (_stringshare_key_value_replace(&t, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
5033      {
5034        elm_entry_entry_set(obj, t);
5035        wd->changed = 1;
5036        _sizing_eval(obj);
5037      }
5038    eina_strbuf_free(fontbuf);
5039    eina_stringshare_del(t);
5040 }
5041
5042 /**
5043  * Set the text color on the entry object
5044  *
5045  * @param obj The entry object
5046  * @param r Red property background color of The entry object
5047  * @param g Green property background color of The entry object
5048  * @param b Blue property background color of The entry object
5049  * @param a Alpha property background alpha of The entry object
5050  *
5051  * @ingroup Entry
5052  */
5053 EAPI void
5054 elm_entry_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
5055 {
5056    ELM_CHECK_WIDTYPE(obj, widtype);
5057    Widget_Data *wd = elm_widget_data_get(obj);
5058    Eina_Strbuf *colorbuf = NULL;
5059    const char *t;
5060    int len;
5061
5062    if (!wd) return;
5063    t = eina_stringshare_add(elm_entry_entry_get(obj));
5064    len = strlen(t);
5065    if (len <= 0) return;
5066    colorbuf = eina_strbuf_new();
5067    eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
5068
5069    if (_stringshare_key_value_replace(&t, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
5070      {
5071        elm_entry_entry_set(obj, t);
5072        wd->changed = 1;
5073        _sizing_eval(obj);
5074      }
5075    eina_strbuf_free(colorbuf);
5076    eina_stringshare_del(t);
5077 }
5078
5079 /**
5080  * Set the text align on the entry object
5081  *
5082  * @param obj The entry object
5083  * @param align align mode
5084  *
5085  * @ingroup Entry
5086  */
5087 EAPI void
5088 elm_entry_text_align_set(Evas_Object *obj, const char *alignmode)
5089 {
5090    ELM_CHECK_WIDTYPE(obj, widtype);
5091    Widget_Data *wd = elm_widget_data_get(obj);
5092    int len;
5093    const char *t;
5094
5095    if (!wd) return;
5096    t = eina_stringshare_add(elm_entry_entry_get(obj));
5097    len = strlen(t);
5098    if (len <= 0) return;
5099
5100    if (_stringshare_key_value_replace(&t, "align", alignmode, 0) == 0)
5101      elm_entry_entry_set(obj, t);
5102
5103    wd->changed = 1;
5104    _sizing_eval(obj);
5105    eina_stringshare_del(t);
5106 }