aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/lib/edje_entry.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/lib/edje_entry.c')
-rw-r--r--libraries/edje/src/lib/edje_entry.c3110
1 files changed, 3110 insertions, 0 deletions
diff --git a/libraries/edje/src/lib/edje_entry.c b/libraries/edje/src/lib/edje_entry.c
new file mode 100644
index 0000000..e25397a
--- /dev/null
+++ b/libraries/edje/src/lib/edje_entry.c
@@ -0,0 +1,3110 @@
1#include "edje_private.h"
2
3#ifdef HAVE_ECORE_IMF
4static Eina_Bool _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
5static Eina_Bool _edje_entry_imf_event_commit_cb(void *data, int type, void *event);
6static Eina_Bool _edje_entry_imf_event_preedit_changed_cb(void *data, int type, void *event);
7static Eina_Bool _edje_entry_imf_event_delete_surrounding_cb(void *data, int type, void *event);
8#endif
9
10typedef struct _Entry Entry;
11typedef struct _Sel Sel;
12typedef struct _Anchor Anchor;
13
14static void _edje_entry_imf_cursor_info_set(Entry *en);
15static void _edje_entry_imf_context_reset(Entry *en);
16
17struct _Entry
18{
19 Edje_Real_Part *rp;
20 Evas_Object *cursor_bg;
21 Evas_Object *cursor_fg;
22 Evas_Textblock_Cursor *cursor;
23 Evas_Textblock_Cursor *sel_start, *sel_end;
24 Evas_Textblock_Cursor *cursor_user, *cursor_user_extra;
25 Evas_Textblock_Cursor *preedit_start, *preedit_end;
26 Ecore_Timer *pw_timer;
27 Eina_List *sel;
28 Eina_List *anchors;
29 Eina_List *anchorlist;
30 Eina_List *itemlist;
31 char *selection;
32 Eina_Bool selecting : 1;
33 Eina_Bool have_selection : 1;
34 Eina_Bool select_allow : 1;
35 Eina_Bool select_mod_start : 1;
36 Eina_Bool select_mod_end : 1;
37 Eina_Bool had_sel : 1;
38
39#ifdef HAVE_ECORE_IMF
40 Eina_Bool have_preedit : 1;
41 Ecore_IMF_Context *imf_context;
42
43 Ecore_Event_Handler *imf_ee_handler_commit;
44 Ecore_Event_Handler *imf_ee_handler_delete;
45 Ecore_Event_Handler *imf_ee_handler_changed;
46#endif
47};
48
49struct _Sel
50{
51 Evas_Textblock_Rectangle rect;
52 Evas_Object *obj_fg, *obj_bg, *obj, *sobj;
53};
54
55struct _Anchor
56{
57 Entry *en;
58 char *name;
59 Evas_Textblock_Cursor *start, *end;
60 Eina_List *sel;
61 Eina_Bool item : 1;
62};
63
64#ifdef HAVE_ECORE_IMF
65static void
66_preedit_clear(Entry *en)
67{
68 if (en->preedit_start)
69 {
70 evas_textblock_cursor_free(en->preedit_start);
71 en->preedit_start = NULL;
72 }
73
74 if (en->preedit_end)
75 {
76 evas_textblock_cursor_free(en->preedit_end);
77 en->preedit_end = NULL;
78 }
79
80 en->have_preedit = EINA_FALSE;
81}
82
83static void
84_preedit_del(Entry *en)
85{
86 if (!en || !en->have_preedit) return;
87 if (!en->preedit_start || !en->preedit_end) return;
88 if (!evas_textblock_cursor_compare(en->preedit_start, en->preedit_end)) return;
89
90 /* delete the preedit characters */
91 evas_textblock_cursor_range_delete(en->preedit_start, en->preedit_end);
92}
93
94static void
95_edje_entry_focus_in_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
96{
97 Edje_Real_Part *rp;
98 Entry *en;
99
100 rp = data;
101 if (!rp || !rp->entry_data || !rp->edje || !rp->edje->obj) return;
102
103 en = rp->entry_data;
104 if (!en || !en->imf_context) return;
105
106 if (evas_object_focus_get(rp->edje->obj))
107 {
108 ecore_imf_context_reset(en->imf_context);
109 ecore_imf_context_focus_in(en->imf_context);
110 _edje_entry_imf_cursor_info_set(en);
111 }
112}
113
114static void
115_edje_entry_focus_out_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
116{
117 Edje_Real_Part *rp;
118 Entry *en;
119
120 rp = data;
121 if (!rp || !rp->entry_data) return;
122
123 en = rp->entry_data;
124 if (!en || !en->imf_context) return;
125
126 ecore_imf_context_reset(en->imf_context);
127 _edje_entry_imf_cursor_info_set(en);
128 ecore_imf_context_focus_out(en->imf_context);
129}
130#endif
131
132static void
133_edje_focus_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
134{
135 Edje *ed = data;
136#ifdef HAVE_ECORE_IMF
137 Edje_Real_Part *rp;
138 Entry *en;
139#endif
140
141 _edje_emit(ed, "focus,in", "");
142#ifdef HAVE_ECORE_IMF
143 rp = ed->focused_part;
144 if (!rp) return;
145
146 en = rp->entry_data;
147 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
148 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
149 return;
150
151 if (!en->imf_context) return;
152
153 ecore_imf_context_reset(en->imf_context);
154 ecore_imf_context_focus_in(en->imf_context);
155 _edje_entry_imf_cursor_info_set(en);
156#endif
157}
158
159static void
160_edje_focus_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
161{
162 Edje *ed = data;
163#ifdef HAVE_ECORE_IMF
164 Edje_Real_Part *rp = ed->focused_part;
165 Entry *en;
166#endif
167
168 _edje_emit(ed, "focus,out", "");
169
170#ifdef HAVE_ECORE_IMF
171 if (!rp) return;
172 en = rp->entry_data;
173 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
174 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
175 return;
176
177 if (!en->imf_context) return;
178
179 ecore_imf_context_reset(en->imf_context);
180 _edje_entry_imf_cursor_info_set(en);
181 ecore_imf_context_focus_out(en->imf_context);
182#endif
183}
184
185static void
186_text_filter_text_prepend(Entry *en, Evas_Textblock_Cursor *c, const char *text)
187{
188 char *text2;
189 Edje_Text_Insert_Filter_Callback *cb;
190 Eina_List *l;
191
192 text2 = strdup(text);
193 EINA_LIST_FOREACH(en->rp->edje->text_insert_filter_callbacks, l, cb)
194 {
195 if (!strcmp(cb->part, en->rp->part->name))
196 {
197 cb->func(cb->data, en->rp->edje->obj, cb->part, EDJE_TEXT_FILTER_TEXT, &text2);
198 if (!text2) break;
199 }
200 }
201 if (text2)
202 {
203 evas_textblock_cursor_text_prepend(c, text2);
204 free(text2);
205 }
206}
207
208static void
209_text_filter_format_prepend(Entry *en, Evas_Textblock_Cursor *c, const char *text)
210{
211 char *text2;
212 Edje_Text_Insert_Filter_Callback *cb;
213 Eina_List *l;
214
215 text2 = strdup(text);
216 EINA_LIST_FOREACH(en->rp->edje->text_insert_filter_callbacks, l, cb)
217 {
218 if (!strcmp(cb->part, en->rp->part->name))
219 {
220 cb->func(cb->data, en->rp->edje->obj, cb->part, EDJE_TEXT_FILTER_FORMAT, &text2);
221 if (!text2) break;
222 }
223 }
224 if (text2)
225 {
226 evas_textblock_cursor_format_prepend(c, text2);
227 free(text2);
228 }
229}
230
231static void
232_text_filter_markup_prepend(Entry *en, Evas_Textblock_Cursor *c, const char *text)
233{
234 char *text2;
235 Edje_Text_Insert_Filter_Callback *cb;
236 Eina_List *l;
237
238 text2 = strdup(text);
239 EINA_LIST_FOREACH(en->rp->edje->text_insert_filter_callbacks, l, cb)
240 {
241 if (!strcmp(cb->part, en->rp->part->name))
242 {
243 cb->func(cb->data, en->rp->edje->obj, cb->part, EDJE_TEXT_FILTER_MARKUP, &text2);
244 if (!text2) break;
245 }
246 }
247 if (text2)
248 {
249 evas_object_textblock_text_markup_prepend(c, text2);
250 free(text2);
251 }
252}
253
254static void
255_curs_update_from_curs(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__, Entry *en, Evas_Coord *cx, Evas_Coord *cy)
256{
257 Evas_Coord cw, ch;
258 Evas_Textblock_Cursor_Type cur_type;
259 if (c != en->cursor) return;
260 switch (en->rp->part->cursor_mode)
261 {
262 case EDJE_ENTRY_CURSOR_MODE_BEFORE:
263 cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
264 break;
265 case EDJE_ENTRY_CURSOR_MODE_UNDER:
266 /* no break for a resaon */
267 default:
268 cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
269 }
270 evas_textblock_cursor_geometry_get(c, cx, cy, &cw, &ch, NULL, cur_type);
271 *cx += (cw / 2);
272 *cy += (ch / 2);
273}
274
275static void
276_curs_back(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
277 Entry *en __UNUSED__)
278{
279 evas_textblock_cursor_char_prev(c);
280}
281
282static void
283_curs_next(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
284 Entry *en __UNUSED__)
285{
286 evas_textblock_cursor_char_next(c);
287}
288
289static int
290_curs_line_last_get(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o, Entry *en __UNUSED__)
291{
292 Evas_Textblock_Cursor *cc;
293 int ln;
294
295 cc = evas_object_textblock_cursor_new(o);
296 evas_textblock_cursor_paragraph_last(cc);
297 ln = evas_textblock_cursor_line_geometry_get(cc, NULL, NULL, NULL, NULL);
298 evas_textblock_cursor_free(cc);
299 return ln;
300}
301
302static void
303_curs_lin_start(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
304 Entry *en __UNUSED__)
305{
306 evas_textblock_cursor_line_char_first(c);
307}
308
309static void
310_curs_lin_end(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
311 Entry *en __UNUSED__)
312{
313 evas_textblock_cursor_line_char_last(c);
314}
315
316static void
317_curs_start(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__,
318 Entry *en __UNUSED__)
319{
320 evas_textblock_cursor_paragraph_first(c);
321}
322
323static void
324_curs_end(Evas_Textblock_Cursor *c, Evas_Object *o __UNUSED__, Entry *en __UNUSED__)
325{
326 evas_textblock_cursor_paragraph_last(c);
327}
328
329static void
330_curs_jump_line(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int ln)
331{
332 Evas_Coord cx, cy;
333 Evas_Coord lx, ly, lw, lh;
334 int last = _curs_line_last_get(c, o, en);
335
336 if (ln < 0) ln = 0;
337 else
338 {
339 if (ln > last) ln = last;
340 }
341
342 _curs_update_from_curs(c, o, en, &cx, &cy);
343
344 if (!evas_object_textblock_line_number_geometry_get(o, ln, &lx, &ly, &lw, &lh))
345 return;
346 if (evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
347 return;
348 evas_textblock_cursor_line_set(c, ln);
349 if (cx < (lx + (lw / 2)))
350 {
351 if (ln == last) _curs_end(c, o, en);
352 _curs_lin_start(c, o, en);
353 }
354 else
355 {
356 if (ln == last)
357 _curs_end(c, o, en);
358 else
359 _curs_lin_end(c, o, en);
360 }
361}
362
363static void
364_curs_jump_line_by(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int by)
365{
366 int ln;
367
368 ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL) + by;
369 _curs_jump_line(c, o, en, ln);
370}
371
372static void
373_curs_up(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
374{
375 _curs_jump_line_by(c, o, en, -1);
376}
377
378static void
379_curs_down(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
380{
381 _curs_jump_line_by(c, o, en, 1);
382}
383
384static void
385_sel_start(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
386{
387 if (en->sel_start) return;
388 en->sel_start = evas_object_textblock_cursor_new(o);
389 evas_textblock_cursor_copy(c, en->sel_start);
390 en->sel_end = evas_object_textblock_cursor_new(o);
391 evas_textblock_cursor_copy(c, en->sel_end);
392
393 en->have_selection = EINA_FALSE;
394 if (en->selection)
395 {
396 free(en->selection);
397 en->selection = NULL;
398 }
399}
400
401static void
402_sel_enable(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
403{
404 if (en->have_selection) return;
405 en->have_selection = EINA_TRUE;
406 if (en->selection)
407 {
408 free(en->selection);
409 en->selection = NULL;
410 }
411 _edje_emit(en->rp->edje, "selection,start", en->rp->part->name);
412}
413
414static void
415_sel_extend(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
416{
417 if (!en->sel_end) return;
418 _sel_enable(c, o, en);
419 if (!evas_textblock_cursor_compare(c, en->sel_end)) return;
420 evas_textblock_cursor_copy(c, en->sel_end);
421 if (en->selection)
422 {
423 free(en->selection);
424 en->selection = NULL;
425 }
426 _edje_emit(en->rp->edje, "selection,changed", en->rp->part->name);
427 _edje_entry_imf_context_reset(en);
428}
429
430static void
431_sel_preextend(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
432{
433 if (!en->sel_end) return;
434 _sel_enable(c, o, en);
435 if (!evas_textblock_cursor_compare(c, en->sel_start)) return;
436 evas_textblock_cursor_copy(c, en->sel_start);
437 if (en->selection)
438 {
439 free(en->selection);
440 en->selection = NULL;
441 }
442 _edje_emit(en->rp->edje, "selection,changed", en->rp->part->name);
443 _edje_entry_imf_context_reset(en);
444}
445
446static void
447_sel_clear(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
448{
449 en->had_sel = EINA_FALSE;
450 if (en->sel_start)
451 {
452 evas_textblock_cursor_free(en->sel_start);
453 evas_textblock_cursor_free(en->sel_end);
454 en->sel_start = NULL;
455 en->sel_end = NULL;
456 }
457 if (en->selection)
458 {
459 free(en->selection);
460 en->selection = NULL;
461 }
462 while (en->sel)
463 {
464 Sel *sel;
465
466 sel = en->sel->data;
467 if (sel->obj_bg) evas_object_del(sel->obj_bg);
468 if (sel->obj_fg) evas_object_del(sel->obj_fg);
469 free(sel);
470 en->sel = eina_list_remove_list(en->sel, en->sel);
471 }
472 if (en->have_selection)
473 {
474 en->have_selection = EINA_FALSE;
475 _edje_emit(en->rp->edje, "selection,cleared", en->rp->part->name);
476 }
477}
478
479static void
480_sel_update(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o, Entry *en)
481{
482 Eina_List *range = NULL, *l;
483 Sel *sel;
484 Evas_Coord x, y, w, h;
485 Evas_Object *smart, *clip;
486
487 smart = evas_object_smart_parent_get(o);
488 clip = evas_object_clip_get(o);
489 if (en->sel_start)
490 range = evas_textblock_cursor_range_geometry_get(en->sel_start, en->sel_end);
491 else
492 return;
493 if (eina_list_count(range) != eina_list_count(en->sel))
494 {
495 while (en->sel)
496 {
497 sel = en->sel->data;
498 if (sel->obj_bg) evas_object_del(sel->obj_bg);
499 if (sel->obj_fg) evas_object_del(sel->obj_fg);
500 free(sel);
501 en->sel = eina_list_remove_list(en->sel, en->sel);
502 }
503 if (en->have_selection)
504 {
505 for (l = range; l; l = eina_list_next(l))
506 {
507 Evas_Object *ob;
508
509 sel = calloc(1, sizeof(Sel));
510 en->sel = eina_list_append(en->sel, sel);
511 ob = edje_object_add(en->rp->edje->base.evas);
512 edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source);
513 evas_object_smart_member_add(ob, smart);
514 evas_object_stack_below(ob, o);
515 evas_object_clip_set(ob, clip);
516 evas_object_pass_events_set(ob, EINA_TRUE);
517 evas_object_show(ob);
518 sel->obj_bg = ob;
519 _edje_subobj_register(en->rp->edje, sel->obj_bg);
520
521 ob = edje_object_add(en->rp->edje->base.evas);
522 edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source2);
523 evas_object_smart_member_add(ob, smart);
524 evas_object_stack_above(ob, o);
525 evas_object_clip_set(ob, clip);
526 evas_object_pass_events_set(ob, EINA_TRUE);
527 evas_object_show(ob);
528 sel->obj_fg = ob;
529 _edje_subobj_register(en->rp->edje, sel->obj_fg);
530 }
531 }
532 }
533 x = y = w = h = -1;
534 evas_object_geometry_get(o, &x, &y, &w, &h);
535 if (en->have_selection)
536 {
537 EINA_LIST_FOREACH(en->sel, l, sel)
538 {
539 Evas_Textblock_Rectangle *r;
540
541 r = range->data;
542 if (sel->obj_bg)
543 {
544 evas_object_move(sel->obj_bg, x + r->x, y + r->y);
545 evas_object_resize(sel->obj_bg, r->w, r->h);
546 }
547 if (sel->obj_fg)
548 {
549 evas_object_move(sel->obj_fg, x + r->x, y + r->y);
550 evas_object_resize(sel->obj_fg, r->w, r->h);
551 }
552 *(&(sel->rect)) = *r;
553 range = eina_list_remove_list(range, range);
554 free(r);
555 }
556 }
557 else
558 {
559 while (range)
560 {
561 free(range->data);
562 range = eina_list_remove_list(range, range);
563 }
564 }
565}
566
567static void
568_edje_anchor_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
569{
570 Anchor *an = data;
571 Evas_Event_Mouse_Down *ev = event_info;
572 Edje_Real_Part *rp = an->en->rp;
573 char *buf, *n;
574 size_t len;
575 int ignored;
576 Entry *en;
577
578 en = rp->entry_data;
579 if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
580 (en->select_allow))
581 return;
582 ignored = rp->part->ignore_flags & ev->event_flags;
583 if ((!ev->event_flags) || (!ignored))
584 {
585 n = an->name;
586 if (!n) n = "";
587 len = 200 + strlen(n);
588 buf = alloca(len);
589 if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
590 snprintf(buf, len, "anchor,mouse,down,%i,%s,triple", ev->button, n);
591 else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
592 snprintf(buf, len, "anchor,mouse,down,%i,%s,double", ev->button, n);
593 else
594 snprintf(buf, len, "anchor,mouse,down,%i,%s", ev->button, n);
595 _edje_emit(rp->edje, buf, rp->part->name);
596 }
597}
598
599static void
600_edje_anchor_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
601{
602 Anchor *an = data;
603 Evas_Event_Mouse_Up *ev = event_info;
604 Edje_Real_Part *rp = an->en->rp;
605 char *buf, *n;
606 size_t len;
607 int ignored;
608 Entry *en;
609
610 en = rp->entry_data;
611 ignored = rp->part->ignore_flags & ev->event_flags;
612 if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
613 (en->select_allow))
614 return;
615 n = an->name;
616 if (!n) n = "";
617 len = 200 + strlen(n);
618 buf = alloca(len);
619 if ((!ev->event_flags) || (!ignored))
620 {
621 snprintf(buf, len, "anchor,mouse,up,%i,%s", ev->button, n);
622 _edje_emit(rp->edje, buf, rp->part->name);
623 }
624 if ((rp->still_in) && (rp->clicked_button == ev->button) && (!ignored))
625 {
626 snprintf(buf, len, "anchor,mouse,clicked,%i,%s", ev->button, n);
627 _edje_emit(rp->edje, buf, rp->part->name);
628 }
629}
630
631static void
632_edje_anchor_mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
633{
634 Anchor *an = data;
635 Evas_Event_Mouse_Move *ev = event_info;
636 Edje_Real_Part *rp = an->en->rp;
637 char *buf, *n;
638 size_t len;
639 int ignored;
640 Entry *en;
641
642 en = rp->entry_data;
643 if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
644 (en->select_allow))
645 return;
646 ignored = rp->part->ignore_flags & ev->event_flags;
647 if ((!ev->event_flags) || (!ignored))
648 {
649 n = an->name;
650 if (!n) n = "";
651 len = 200 + strlen(n);
652 buf = alloca(len);
653 snprintf(buf, len, "anchor,mouse,move,%s", n);
654 _edje_emit(rp->edje, buf, rp->part->name);
655 }
656}
657
658static void
659_edje_anchor_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
660{
661 Anchor *an = data;
662 Evas_Event_Mouse_In *ev = event_info;
663 Edje_Real_Part *rp = an->en->rp;
664 char *buf, *n;
665 size_t len;
666 int ignored;
667
668 ignored = rp->part->ignore_flags & ev->event_flags;
669 if ((!ev->event_flags) || (!ignored))
670 {
671 n = an->name;
672 if (!n) n = "";
673 len = 200 + strlen(n);
674 buf = alloca(len);
675 snprintf(buf, len, "anchor,mouse,in,%s", n);
676 _edje_emit(rp->edje, buf, rp->part->name);
677 }
678}
679
680static void
681_edje_anchor_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
682{
683 Anchor *an = data;
684 Evas_Event_Mouse_Out *ev = event_info;
685 Edje_Real_Part *rp = an->en->rp;
686 char *buf, *n;
687 size_t len;
688 int ignored;
689
690 ignored = rp->part->ignore_flags & ev->event_flags;
691 if ((!ev->event_flags) || (!ignored))
692 {
693 n = an->name;
694 if (!n) n = "";
695 len = 200 + strlen(n);
696 buf = alloca(len);
697 snprintf(buf, len, "anchor,mouse,out,%s", n);
698 _edje_emit(rp->edje, buf, rp->part->name);
699 }
700}
701
702static void
703_anchors_update(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o, Entry *en)
704{
705 Eina_List *l, *ll, *range = NULL;
706 Evas_Coord x, y, w, h;
707 Evas_Object *smart, *clip;
708 Sel *sel;
709 Anchor *an;
710
711 smart = evas_object_smart_parent_get(o);
712 clip = evas_object_clip_get(o);
713 x = y = w = h = -1;
714 evas_object_geometry_get(o, &x, &y, &w, &h);
715 EINA_LIST_FOREACH(en->anchors, l, an)
716 {
717 // for item anchors
718 if (an->item)
719 {
720 Evas_Object *ob;
721
722 if (!an->sel)
723 {
724 while (an->sel)
725 {
726 sel = an->sel->data;
727 if (sel->obj_bg) evas_object_del(sel->obj_bg);
728 if (sel->obj_fg) evas_object_del(sel->obj_fg);
729 if (sel->obj) evas_object_del(sel->obj);
730 free(sel);
731 an->sel = eina_list_remove_list(an->sel, an->sel);
732 }
733
734 sel = calloc(1, sizeof(Sel));
735 an->sel = eina_list_append(an->sel, sel);
736
737 if (en->rp->edje->item_provider.func)
738 {
739 ob = en->rp->edje->item_provider.func
740 (en->rp->edje->item_provider.data, smart,
741 en->rp->part->name, an->name);
742 evas_object_smart_member_add(ob, smart);
743 evas_object_stack_above(ob, o);
744 evas_object_clip_set(ob, clip);
745 evas_object_pass_events_set(ob, EINA_TRUE);
746 evas_object_show(ob);
747 sel->obj = ob;
748 }
749 }
750 }
751 // for link anchors
752 else
753 {
754 range =
755 evas_textblock_cursor_range_geometry_get(an->start, an->end);
756 if (eina_list_count(range) != eina_list_count(an->sel))
757 {
758 while (an->sel)
759 {
760 sel = an->sel->data;
761 if (sel->obj_bg) evas_object_del(sel->obj_bg);
762 if (sel->obj_fg) evas_object_del(sel->obj_fg);
763 if (sel->obj) evas_object_del(sel->obj);
764 free(sel);
765 an->sel = eina_list_remove_list(an->sel, an->sel);
766 }
767 for (ll = range; ll; ll = eina_list_next(ll))
768 {
769 Evas_Object *ob;
770
771 sel = calloc(1, sizeof(Sel));
772 an->sel = eina_list_append(an->sel, sel);
773 ob = edje_object_add(en->rp->edje->base.evas);
774 edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source5);
775 evas_object_smart_member_add(ob, smart);
776 evas_object_stack_below(ob, o);
777 evas_object_clip_set(ob, clip);
778 evas_object_pass_events_set(ob, EINA_TRUE);
779 evas_object_show(ob);
780 sel->obj_bg = ob;
781 _edje_subobj_register(en->rp->edje, sel->obj_bg);
782
783 ob = edje_object_add(en->rp->edje->base.evas);
784 edje_object_file_set(ob, en->rp->edje->path, en->rp->part->source6);
785 evas_object_smart_member_add(ob, smart);
786 evas_object_stack_above(ob, o);
787 evas_object_clip_set(ob, clip);
788 evas_object_pass_events_set(ob, EINA_TRUE);
789 evas_object_show(ob);
790 sel->obj_fg = ob;
791 _edje_subobj_register(en->rp->edje, sel->obj_fg);
792
793 ob = evas_object_rectangle_add(en->rp->edje->base.evas);
794 evas_object_color_set(ob, 0, 0, 0, 0);
795 evas_object_smart_member_add(ob, smart);
796 evas_object_stack_above(ob, o);
797 evas_object_clip_set(ob, clip);
798 evas_object_repeat_events_set(ob, EINA_TRUE);
799 evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_DOWN, _edje_anchor_mouse_down_cb, an);
800 evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_UP, _edje_anchor_mouse_up_cb, an);
801 evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_MOVE, _edje_anchor_mouse_move_cb, an);
802 evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_IN, _edje_anchor_mouse_in_cb, an);
803 evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_OUT, _edje_anchor_mouse_out_cb, an);
804 evas_object_show(ob);
805 sel->obj = ob;
806 }
807 }
808 }
809 EINA_LIST_FOREACH(an->sel, ll, sel)
810 {
811 if (an->item)
812 {
813 Evas_Coord cx, cy, cw, ch;
814
815 if (!evas_textblock_cursor_format_item_geometry_get
816 (an->start, &cx, &cy, &cw, &ch))
817 continue;
818 evas_object_move(sel->obj, x + cx, y + cy);
819 evas_object_resize(sel->obj, cw, ch);
820 }
821 else
822 {
823 Evas_Textblock_Rectangle *r;
824
825 r = range->data;
826 *(&(sel->rect)) = *r;
827 if (sel->obj_bg)
828 {
829 evas_object_move(sel->obj_bg, x + r->x, y + r->y);
830 evas_object_resize(sel->obj_bg, r->w, r->h);
831 }
832 if (sel->obj_fg)
833 {
834 evas_object_move(sel->obj_fg, x + r->x, y + r->y);
835 evas_object_resize(sel->obj_fg, r->w, r->h);
836 }
837 if (sel->obj)
838 {
839 evas_object_move(sel->obj, x + r->x, y + r->y);
840 evas_object_resize(sel->obj, r->w, r->h);
841 }
842 range = eina_list_remove_list(range, range);
843 free(r);
844 }
845 }
846 }
847}
848
849static void
850_anchors_clear(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
851{
852 while (en->anchorlist)
853 {
854 free(en->anchorlist->data);
855 en->anchorlist = eina_list_remove_list(en->anchorlist, en->anchorlist);
856 }
857 while (en->itemlist)
858 {
859 free(en->itemlist->data);
860 en->itemlist = eina_list_remove_list(en->itemlist, en->itemlist);
861 }
862 while (en->anchors)
863 {
864 Anchor *an = en->anchors->data;
865
866 evas_textblock_cursor_free(an->start);
867 evas_textblock_cursor_free(an->end);
868 while (an->sel)
869 {
870 Sel *sel = an->sel->data;
871 if (sel->obj_bg) evas_object_del(sel->obj_bg);
872 if (sel->obj_fg) evas_object_del(sel->obj_fg);
873 if (sel->obj) evas_object_del(sel->obj);
874 free(sel);
875 an->sel = eina_list_remove_list(an->sel, an->sel);
876 }
877 free(an->name);
878 free(an);
879 en->anchors = eina_list_remove_list(en->anchors, en->anchors);
880 }
881}
882
883static void
884_anchors_get(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
885{
886 const Eina_List *anchors_a, *anchors_item;
887 Anchor *an = NULL;
888 _anchors_clear(c, o, en);
889
890 anchors_a = evas_textblock_node_format_list_get(o, "a");
891 anchors_item = evas_textblock_node_format_list_get(o, "item");
892
893 if (anchors_a)
894 {
895 const Evas_Object_Textblock_Node_Format *node;
896 const Eina_List *itr;
897 EINA_LIST_FOREACH(anchors_a, itr, node)
898 {
899 const char *s = evas_textblock_node_format_text_get(node);
900 char *p;
901 an = calloc(1, sizeof(Anchor));
902 if (!an)
903 break;
904
905 an->en = en;
906 p = strstr(s, "href=");
907 if (p)
908 {
909 an->name = strdup(p + 5);
910 }
911 en->anchors = eina_list_append(en->anchors, an);
912 an->start = evas_object_textblock_cursor_new(o);
913 an->end = evas_object_textblock_cursor_new(o);
914 evas_textblock_cursor_at_format_set(an->start, node);
915 evas_textblock_cursor_copy(an->start, an->end);
916
917 /* Close the anchor, if the anchor was without text,
918 * free it as well */
919 node = evas_textblock_node_format_next_get(node);
920 for (; node; node = evas_textblock_node_format_next_get(node))
921 {
922 s = evas_textblock_node_format_text_get(node);
923 if ((!strcmp(s, "- a")) || (!strcmp(s, "-a")))
924 break;
925 }
926
927 if (node)
928 {
929 evas_textblock_cursor_at_format_set(an->end, node);
930 }
931 else if (!evas_textblock_cursor_compare(an->start, an->end))
932 {
933 if (an->name) free(an->name);
934 evas_textblock_cursor_free(an->start);
935 evas_textblock_cursor_free(an->end);
936 en->anchors = eina_list_remove(en->anchors, an);
937 free(an);
938 }
939 an = NULL;
940 }
941 }
942
943 if (anchors_item)
944 {
945 const Evas_Object_Textblock_Node_Format *node;
946 const Eina_List *itr;
947 EINA_LIST_FOREACH(anchors_item, itr, node)
948 {
949 const char *s = evas_textblock_node_format_text_get(node);
950 char *p;
951 an = calloc(1, sizeof(Anchor));
952 if (!an)
953 break;
954
955 an->en = en;
956 an->item = 1;
957 p = strstr(s, "href=");
958 if (p)
959 {
960 an->name = strdup(p + 5);
961 }
962 en->anchors = eina_list_append(en->anchors, an);
963 an->start = evas_object_textblock_cursor_new(o);
964 an->end = evas_object_textblock_cursor_new(o);
965 evas_textblock_cursor_at_format_set(an->start, node);
966 evas_textblock_cursor_copy(an->start, an->end);
967 /* Although needed in textblock, don't bother with finding the end
968 * here cause it doesn't really matter. */
969 }
970 }
971}
972
973static void
974_free_entry_change_info(void *_info)
975{
976 Edje_Entry_Change_Info *info = (Edje_Entry_Change_Info *) _info;
977 if (info->insert)
978 {
979 eina_stringshare_del(info->change.insert.content);
980 }
981 else
982 {
983 eina_stringshare_del(info->change.del.content);
984 }
985 free(info);
986}
987
988static void
989_range_del_emit(Edje *ed, Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
990{
991 size_t start, end;
992 char *tmp;
993 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
994 info->insert = EINA_FALSE;
995 start = evas_textblock_cursor_pos_get(en->sel_start);
996 end = evas_textblock_cursor_pos_get(en->sel_end);
997 info->change.del.start = start;
998 info->change.del.end = end;
999
1000 tmp = evas_textblock_cursor_range_text_get(en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
1001 info->change.del.content = eina_stringshare_add(tmp);
1002 if (tmp) free(tmp);
1003 evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1004 _edje_emit(ed, "entry,changed", en->rp->part->name);
1005 _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info,
1006 _free_entry_change_info);
1007}
1008
1009static void
1010_range_del(Evas_Textblock_Cursor *c __UNUSED__, Evas_Object *o __UNUSED__, Entry *en)
1011{
1012 evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1013}
1014
1015static void
1016_delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos,
1017 Eina_Bool backspace)
1018{
1019 if (!evas_textblock_cursor_char_next(c))
1020 {
1021 return;
1022 }
1023 evas_textblock_cursor_char_prev(c);
1024
1025 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1026 char *tmp = evas_textblock_cursor_content_get(c);
1027
1028 info->insert = EINA_FALSE;
1029 if (backspace)
1030 {
1031 info->change.del.start = pos - 1;
1032 info->change.del.end = pos;
1033 }
1034 else
1035 {
1036 info->change.del.start = pos + 1;
1037 info->change.del.end = pos;
1038 }
1039
1040 info->change.del.content = eina_stringshare_add(tmp);
1041 if (tmp) free(tmp);
1042
1043 evas_textblock_cursor_char_delete(c);
1044 _edje_emit(ed, "entry,changed", en->rp->part->name);
1045 _edje_emit_full(ed, "entry,changed,user", en->rp->part->name,
1046 info, _free_entry_change_info);
1047}
1048
1049static void
1050_edje_entry_hide_visible_password(Edje_Real_Part *rp)
1051{
1052 const Evas_Object_Textblock_Node_Format *node;
1053 node = evas_textblock_node_format_first_get(rp->object);
1054 for (; node; node = evas_textblock_node_format_next_get(node))
1055 {
1056 const char *text = evas_textblock_node_format_text_get(node);
1057 if (text)
1058 {
1059 if (!strcmp(text, "+ password=off"))
1060 {
1061 evas_textblock_node_format_remove_pair(rp->object,
1062 (Evas_Object_Textblock_Node_Format *) node);
1063 break;
1064 }
1065 }
1066 }
1067 _edje_entry_real_part_configure(rp);
1068 _edje_emit(rp->edje, "entry,changed", rp->part->name);
1069}
1070
1071static Eina_Bool
1072_password_timer_cb(void *data)
1073{
1074 Entry *en = (Entry *)data;
1075 _edje_entry_hide_visible_password(en->rp);
1076 en->pw_timer = NULL;
1077 return ECORE_CALLBACK_CANCEL;
1078}
1079
1080static void
1081_edje_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1082{
1083 Edje *ed = data;
1084 Evas_Event_Key_Down *ev = event_info;
1085 Edje_Real_Part *rp = ed->focused_part;
1086 Entry *en;
1087 Eina_Bool control, alt, shift;
1088 Eina_Bool multiline;
1089 Eina_Bool cursor_changed;
1090 int old_cur_pos;
1091 if (!rp) return;
1092 en = rp->entry_data;
1093 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1094 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1095 return;
1096 if (!ev->key) return;
1097
1098#ifdef HAVE_ECORE_IMF
1099 if (en->imf_context)
1100 {
1101 Ecore_IMF_Event_Key_Down ecore_ev;
1102 ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
1103 if (ecore_imf_context_filter_event(en->imf_context,
1104 ECORE_IMF_EVENT_KEY_DOWN,
1105 (Ecore_IMF_Event *)&ecore_ev))
1106 return;
1107 }
1108#endif
1109
1110 old_cur_pos = evas_textblock_cursor_pos_get(en->cursor);
1111
1112 control = evas_key_modifier_is_set(ev->modifiers, "Control");
1113 alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
1114 shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
1115 multiline = rp->part->multiline;
1116 cursor_changed = EINA_FALSE;
1117 if (!strcmp(ev->key, "Escape"))
1118 {
1119 // dead keys here. Escape for now (should emit these)
1120 _edje_emit(ed, "entry,key,escape", rp->part->name);
1121 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1122 }
1123 else if (!strcmp(ev->key, "Up") || !strcmp(ev->key, "KP_Up"))
1124 {
1125 if (multiline)
1126 {
1127 if (en->select_allow)
1128 {
1129 if (shift) _sel_start(en->cursor, rp->object, en);
1130 else _sel_clear(en->cursor, rp->object, en);
1131 }
1132 _curs_up(en->cursor, rp->object, en);
1133 if (en->select_allow)
1134 {
1135 if (shift) _sel_extend(en->cursor, rp->object, en);
1136 }
1137 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1138 }
1139 _sel_clear(en->cursor, rp->object, en);
1140 _edje_emit(ed, "entry,key,up", rp->part->name);
1141 }
1142 else if (!strcmp(ev->key, "Down") || !strcmp(ev->key, "KP_Down"))
1143 {
1144 if (multiline)
1145 {
1146 if (en->select_allow)
1147 {
1148 if (shift) _sel_start(en->cursor, rp->object, en);
1149 else _sel_clear(en->cursor, rp->object, en);
1150 }
1151 _curs_down(en->cursor, rp->object, en);
1152 if (en->select_allow)
1153 {
1154 if (shift) _sel_extend(en->cursor, rp->object, en);
1155 }
1156 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1157 }
1158 _sel_clear(en->cursor, rp->object, en);
1159 _edje_emit(ed, "entry,key,down", rp->part->name);
1160 }
1161 else if (!strcmp(ev->key, "Left") || !strcmp(ev->key, "KP_Left"))
1162 {
1163 if (en->select_allow)
1164 {
1165 if (shift) _sel_start(en->cursor, rp->object, en);
1166 else _sel_clear(en->cursor, rp->object, en);
1167 }
1168 _curs_back(en->cursor, rp->object, en);
1169 if (en->select_allow)
1170 {
1171 if (shift) _sel_extend(en->cursor, rp->object, en);
1172 }
1173 _sel_clear(en->cursor, rp->object, en);
1174 _edje_emit(ed, "entry,key,left", rp->part->name);
1175 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1176 }
1177 else if (!strcmp(ev->key, "Right") || !strcmp(ev->key, "KP_Right"))
1178 {
1179 if (en->select_allow)
1180 {
1181 if (shift) _sel_start(en->cursor, rp->object, en);
1182 else _sel_clear(en->cursor, rp->object, en);
1183 }
1184 _curs_next(en->cursor, rp->object, en);
1185 if (en->select_allow)
1186 {
1187 if (shift) _sel_extend(en->cursor, rp->object, en);
1188 }
1189 _sel_clear(en->cursor, rp->object, en);
1190 _edje_emit(ed, "entry,key,right", rp->part->name);
1191 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1192 }
1193 else if (!strcmp(ev->key, "BackSpace"))
1194 {
1195 if (control)
1196 {
1197 // del to start of previous word
1198 }
1199 else if ((alt) && (shift))
1200 {
1201 // undo last action
1202 }
1203 else
1204 {
1205 if (en->have_selection)
1206 {
1207 _range_del_emit(ed, en->cursor, rp->object, en);
1208 }
1209 else
1210 {
1211 if (evas_textblock_cursor_char_prev(en->cursor))
1212 {
1213 _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_TRUE);
1214 }
1215 }
1216 }
1217 _sel_clear(en->cursor, rp->object, en);
1218 _anchors_get(en->cursor, rp->object, en);
1219 _edje_emit(ed, "entry,key,backspace", rp->part->name);
1220 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1221 }
1222 else if (!strcmp(ev->key, "Delete") || !strcmp(ev->key, "KP_Delete"))
1223 {
1224 if (control)
1225 {
1226 // del to end of next word
1227 }
1228 else if (shift)
1229 {
1230 // cut
1231 }
1232 else
1233 {
1234 if (en->have_selection)
1235 {
1236 _range_del_emit(ed, en->cursor, rp->object, en);
1237 }
1238 else
1239 {
1240 _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_FALSE);
1241 }
1242 }
1243 _sel_clear(en->cursor, rp->object, en);
1244 _anchors_get(en->cursor, rp->object, en);
1245 _edje_emit(ed, "entry,key,delete", rp->part->name);
1246 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1247 }
1248 else if (!strcmp(ev->key, "Home") || !strcmp(ev->key, "KP_Home"))
1249 {
1250 if (en->select_allow)
1251 {
1252 if (shift) _sel_start(en->cursor, rp->object, en);
1253 else _sel_clear(en->cursor, rp->object, en);
1254 }
1255 if ((control) && (multiline))
1256 _curs_start(en->cursor, rp->object, en);
1257 else
1258 _curs_lin_start(en->cursor, rp->object, en);
1259 if (en->select_allow)
1260 {
1261 if (shift) _sel_extend(en->cursor, rp->object, en);
1262 }
1263 _edje_emit(ed, "entry,key,home", rp->part->name);
1264 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1265 }
1266 else if (!strcmp(ev->key, "End") || !strcmp(ev->key, "KP_End"))
1267 {
1268 if (en->select_allow)
1269 {
1270 if (shift) _sel_start(en->cursor, rp->object, en);
1271 else _sel_clear(en->cursor, rp->object, en);
1272 }
1273 if ((control) && (multiline))
1274 _curs_end(en->cursor, rp->object, en);
1275 else
1276 _curs_lin_end(en->cursor, rp->object, en);
1277 if (en->select_allow)
1278 {
1279 if (shift) _sel_extend(en->cursor, rp->object, en);
1280 }
1281 _edje_emit(ed, "entry,key,end", rp->part->name);
1282 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1283 }
1284 else if (!strcmp(ev->key, "Shift_L") || !strcmp(ev->key, "Shift_R"))
1285 {
1286 return;
1287 }
1288 else if ((control) && (!strcmp(ev->key, "v")))
1289 {
1290 _edje_emit(ed, "entry,paste,request", rp->part->name);
1291 _edje_emit(ed, "entry,paste,request,3", rp->part->name);
1292 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1293 }
1294 else if ((control) && (!strcmp(ev->key, "a")))
1295 {
1296 _edje_emit(ed, "entry,selection,all,request", rp->part->name);
1297 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1298 }
1299 else if ((control) && (!strcmp(ev->key, "A")))
1300 {
1301 _edje_emit(ed, "entry,selection,none,request", rp->part->name);
1302 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1303 }
1304 else if ((control) && ((!strcmp(ev->key, "c") || (!strcmp(ev->key, "Insert")))))
1305 {
1306 // FIXME: copy - save selection
1307 _edje_emit(ed, "entry,copy,notify", rp->part->name);
1308 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1309 }
1310 else if ((control) && ((!strcmp(ev->key, "x") || (!strcmp(ev->key, "m")))))
1311 {
1312 // FIXME: cut - save selection, delete seletion
1313 _edje_emit(ed, "entry,cut,notify", rp->part->name);
1314 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1315 }
1316 else if ((control) && (!strcmp(ev->key, "z")))
1317 {
1318 if (shift)
1319 {
1320 // redo
1321 _edje_emit(ed, "entry,redo,request", rp->part->name);
1322 }
1323 else
1324 {
1325 // undo
1326 _edje_emit(ed, "entry,undo,request", rp->part->name);
1327 }
1328 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1329 }
1330 else if ((control) && (!strcmp(ev->key, "y")))
1331 {
1332 // redo
1333 _edje_emit(ed, "entry,redo,request", rp->part->name);
1334 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1335 }
1336 else if ((control) && (!strcmp(ev->key, "w")))
1337 {
1338 _sel_clear(en->cursor, rp->object, en);
1339 // select current word
1340 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1341 }
1342 else if (!strcmp(ev->key, "Tab"))
1343 {
1344 if (multiline)
1345 {
1346 if (shift)
1347 {
1348 // remove a tab
1349 }
1350 else
1351 {
1352 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1353 info->insert = EINA_TRUE;
1354 info->change.insert.plain_length = 1;
1355
1356 if (en->have_selection)
1357 {
1358 _range_del_emit(ed, en->cursor, rp->object, en);
1359 info->merge = EINA_TRUE;
1360 }
1361 _sel_clear(en->cursor, rp->object, en);
1362 info->change.insert.pos =
1363 evas_textblock_cursor_pos_get(en->cursor);
1364 info->change.insert.content = eina_stringshare_add("<\t>");
1365 //yy
1366// evas_textblock_cursor_format_prepend(en->cursor, "\t");
1367 _text_filter_format_prepend(en, en->cursor, "\t");
1368 _anchors_get(en->cursor, rp->object, en);
1369 _edje_emit(ed, "entry,changed", rp->part->name);
1370 _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1371 info, _free_entry_change_info);
1372 }
1373 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1374 }
1375 _edje_emit(ed, "entry,key,tab", rp->part->name);
1376 }
1377 else if ((!strcmp(ev->key, "ISO_Left_Tab")) && (multiline))
1378 {
1379 // remove a tab
1380 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1381 }
1382 else if (!strcmp(ev->key, "Prior") || !strcmp(ev->key, "KP_Prior"))
1383 {
1384 if (en->select_allow)
1385 {
1386 if (shift) _sel_start(en->cursor, rp->object, en);
1387 else _sel_clear(en->cursor, rp->object, en);
1388 }
1389 _curs_jump_line_by(en->cursor, rp->object, en, -10);
1390 if (en->select_allow)
1391 {
1392 if (shift) _sel_extend(en->cursor, rp->object, en);
1393 }
1394 _sel_clear(en->cursor, rp->object, en);
1395 _edje_emit(ed, "entry,key,pgup", rp->part->name);
1396 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1397 }
1398 else if (!strcmp(ev->key, "Next") || !strcmp(ev->key, "KP_Next"))
1399 {
1400 if (en->select_allow)
1401 {
1402 if (shift) _sel_start(en->cursor, rp->object, en);
1403 else _sel_clear(en->cursor, rp->object, en);
1404 }
1405 _curs_jump_line_by(en->cursor, rp->object, en, 10);
1406 if (en->select_allow)
1407 {
1408 if (shift) _sel_extend(en->cursor, rp->object, en);
1409 }
1410 _sel_clear(en->cursor, rp->object, en);
1411 _edje_emit(ed, "entry,key,pgdn", rp->part->name);
1412 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1413 }
1414 else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
1415 {
1416 if (multiline)
1417 {
1418 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1419 info->insert = EINA_TRUE;
1420 info->change.insert.plain_length = 1;
1421 if (en->have_selection)
1422 {
1423 _range_del_emit(ed, en->cursor, rp->object, en);
1424 info->merge = EINA_TRUE;
1425 }
1426 _sel_clear(en->cursor, rp->object, en);
1427
1428 info->change.insert.pos =
1429 evas_textblock_cursor_pos_get(en->cursor);
1430 if (shift)
1431 {
1432 //yy
1433// evas_textblock_cursor_format_prepend(en->cursor, "\n");
1434 _text_filter_format_prepend(en, en->cursor, "\n");
1435 info->change.insert.content = eina_stringshare_add("<\n>");
1436 }
1437 else
1438 {
1439 //yy
1440// evas_textblock_cursor_format_prepend(en->cursor, "ps");
1441 _text_filter_format_prepend(en, en->cursor, "ps");
1442 info->change.insert.content = eina_stringshare_add("<ps>");
1443 }
1444 _anchors_get(en->cursor, rp->object, en);
1445 _edje_emit(ed, "entry,changed", rp->part->name);
1446 _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1447 info, _free_entry_change_info);
1448 _edje_emit(ed, "cursor,changed", rp->part->name);
1449 cursor_changed = EINA_TRUE;
1450 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1451 }
1452 _edje_emit(ed, "entry,key,enter", rp->part->name);
1453 }
1454 else
1455 {
1456 if (ev->string)
1457 {
1458 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1459 info->insert = EINA_TRUE;
1460 info->change.insert.plain_length = 1;
1461 info->change.insert.content = eina_stringshare_add(ev->string);
1462
1463 if (en->have_selection)
1464 {
1465 _range_del_emit(ed, en->cursor, rp->object, en);
1466 info->merge = EINA_TRUE;
1467 }
1468 _sel_clear(en->cursor, rp->object, en);
1469
1470 info->change.insert.pos =
1471 evas_textblock_cursor_pos_get(en->cursor);
1472 // if PASSWORD_SHOW_LAST mode, appending text with password=off tag
1473 if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
1474 _edje_password_show_last)
1475 {
1476 _edje_entry_hide_visible_password(en->rp);
1477 _text_filter_format_prepend(en, en->cursor, "+ password=off");
1478 _text_filter_text_prepend(en, en->cursor, ev->string);
1479 _text_filter_format_prepend(en, en->cursor, "- password");
1480 if (en->pw_timer)
1481 {
1482 ecore_timer_del(en->pw_timer);
1483 en->pw_timer = NULL;
1484 }
1485 en->pw_timer = ecore_timer_add(_edje_password_show_last_timeout,
1486 _password_timer_cb, en);
1487 }
1488 else
1489 _text_filter_text_prepend(en, en->cursor, ev->string);
1490 _anchors_get(en->cursor, rp->object, en);
1491 _edje_emit(ed, "entry,changed", rp->part->name);
1492 _edje_emit_full(ed, "entry,changed,user", rp->part->name,
1493 info, _free_entry_change_info);
1494 _edje_emit(ed, "cursor,changed", rp->part->name);
1495 cursor_changed = EINA_TRUE;
1496 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1497 }
1498 }
1499 if (!cursor_changed && (old_cur_pos != evas_textblock_cursor_pos_get(en->cursor)))
1500 _edje_emit(ed, "cursor,changed", rp->part->name);
1501
1502 _edje_entry_imf_context_reset(en);
1503 _edje_entry_imf_cursor_info_set(en);
1504 _edje_entry_real_part_configure(rp);
1505}
1506
1507static void
1508_edje_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1509{
1510 Edje *ed = data;
1511 Edje_Real_Part *rp = ed->focused_part;
1512 Entry *en;
1513
1514 if (!rp) return;
1515 en = rp->entry_data;
1516 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1517 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1518 return;
1519
1520#ifdef HAVE_ECORE_IMF
1521 if (en->imf_context)
1522 {
1523 Evas_Event_Key_Up *ev = event_info;
1524 Ecore_IMF_Event_Key_Up ecore_ev;
1525
1526 ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev);
1527 if (ecore_imf_context_filter_event(en->imf_context,
1528 ECORE_IMF_EVENT_KEY_UP,
1529 (Ecore_IMF_Event *)&ecore_ev))
1530 return;
1531 }
1532#else
1533 (void) event_info;
1534#endif
1535}
1536
1537static void
1538_edje_part_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1539{
1540 Edje_Real_Part *rp = data;
1541 Entry *en;
1542 if (!rp) return;
1543 en = rp->entry_data;
1544 if (!en) return;
1545 _edje_entry_imf_cursor_info_set(en);
1546}
1547
1548static void
1549_edje_part_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1550{
1551 Evas_Coord cx, cy;
1552 Edje_Real_Part *rp = data;
1553 Evas_Event_Mouse_Down *ev = event_info;
1554 Entry *en;
1555 Evas_Coord x, y, w, h;
1556 // Eina_Bool multiline;
1557 Evas_Textblock_Cursor *tc;
1558 Eina_Bool dosel = EINA_FALSE;
1559 if (!rp) return;
1560 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1561 en = rp->entry_data;
1562 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1563 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
1564 return;
1565 if ((ev->button != 1) && (ev->button != 2)) return;
1566
1567#ifdef HAVE_ECORE_IMF
1568 if (en->imf_context)
1569 {
1570 Ecore_IMF_Event_Mouse_Down ecore_ev;
1571 ecore_imf_evas_event_mouse_down_wrap(ev, &ecore_ev);
1572 if (ecore_imf_context_filter_event(en->imf_context,
1573 ECORE_IMF_EVENT_MOUSE_DOWN,
1574 (Ecore_IMF_Event *)&ecore_ev))
1575 return;
1576 }
1577#endif
1578
1579 en->select_mod_start = EINA_FALSE;
1580 en->select_mod_end = EINA_FALSE;
1581 if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
1582 dosel = EINA_TRUE;
1583 else if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
1584 {
1585 if (en->select_allow) dosel = EINA_TRUE;
1586 }
1587 if (ev->button == 2) dosel = EINA_FALSE;
1588 if (dosel)
1589 {
1590 // double click -> select word
1591 // triple click -> select line
1592 }
1593 tc = evas_object_textblock_cursor_new(rp->object);
1594 evas_textblock_cursor_copy(en->cursor, tc);
1595 // multiline = rp->part->multiline;
1596 evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1597 cx = ev->canvas.x - x;
1598 cy = ev->canvas.y - y;
1599 if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
1600 {
1601 Evas_Coord lx, ly, lw, lh;
1602 int line;
1603
1604 line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
1605 if (line == -1)
1606 {
1607 if (rp->part->multiline)
1608 _curs_end(en->cursor, rp->object, en);
1609 else
1610 {
1611 evas_textblock_cursor_paragraph_first(en->cursor);
1612 evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1613 if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
1614 _curs_end(en->cursor, rp->object, en);
1615 }
1616 }
1617 else
1618 {
1619 int lnum;
1620
1621 lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1622 if (lnum < 0)
1623 {
1624 _curs_lin_start(en->cursor, rp->object, en);
1625 }
1626 else
1627 {
1628 if (cx <= lx)
1629 _curs_lin_start(en->cursor, rp->object, en);
1630 else
1631 _curs_lin_end(en->cursor, rp->object, en);
1632 }
1633 }
1634 }
1635 if (dosel)
1636 {
1637 if ((en->have_selection) &&
1638 (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT))
1639 {
1640 Eina_List *first, *last;
1641 FLOAT_T sc;
1642
1643 first = en->sel;
1644 last = eina_list_last(en->sel);
1645 if (first && last)
1646 {
1647 Evas_Textblock_Rectangle *r1, *r2;
1648 Evas_Coord d, d1, d2;
1649
1650 r1 = first->data;
1651 r2 = last->data;
1652 d = r1->x - cx;
1653 d1 = d * d;
1654 d = (r1->y + (r1->h / 2)) - cy;
1655 d1 += d * d;
1656 d = r2->x + r2->w - 1 - cx;
1657 d2 = d * d;
1658 d = (r2->y + (r2->h / 2)) - cy;
1659 d2 += d * d;
1660 sc = rp->edje->scale;
1661 if (sc == ZERO) sc = _edje_scale;
1662 d = (Evas_Coord)MUL(FROM_INT(20), sc); // FIXME: maxing number!
1663 d = d * d;
1664 if (d1 < d2)
1665 {
1666 if (d1 <= d)
1667 {
1668 en->select_mod_start = EINA_TRUE;
1669 en->selecting = EINA_TRUE;
1670 }
1671 }
1672 else
1673 {
1674 if (d2 <= d)
1675 {
1676 en->select_mod_end = EINA_TRUE;
1677 en->selecting = EINA_TRUE;
1678 }
1679 }
1680 }
1681 }
1682 else
1683 {
1684 en->selecting = EINA_TRUE;
1685 _sel_clear(en->cursor, rp->object, en);
1686 if (en->select_allow)
1687 {
1688 _sel_start(en->cursor, rp->object, en);
1689 }
1690 }
1691 }
1692 if (evas_textblock_cursor_compare(tc, en->cursor))
1693 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
1694 evas_textblock_cursor_free(tc);
1695
1696 _edje_entry_imf_context_reset(en);
1697 _edje_entry_imf_cursor_info_set(en);
1698
1699 _edje_entry_real_part_configure(rp);
1700 if (ev->button == 2)
1701 {
1702 _edje_emit(rp->edje, "entry,paste,request", rp->part->name);
1703 _edje_emit(rp->edje, "entry,paste,request,1", rp->part->name);
1704 }
1705}
1706
1707static void
1708_edje_part_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1709{
1710 Evas_Coord cx, cy;
1711 Edje_Real_Part *rp = data;
1712 Evas_Event_Mouse_Up *ev = event_info;
1713 Entry *en;
1714 Evas_Coord x, y, w, h;
1715 Evas_Textblock_Cursor *tc;
1716 if (ev->button != 1) return;
1717 if (!rp) return;
1718 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1719 en = rp->entry_data;
1720 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1721 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
1722 return;
1723
1724#ifdef HAVE_ECORE_IMF
1725 if (en->imf_context)
1726 {
1727 Ecore_IMF_Event_Mouse_Up ecore_ev;
1728 ecore_imf_evas_event_mouse_up_wrap(ev, &ecore_ev);
1729 if (ecore_imf_context_filter_event(en->imf_context,
1730 ECORE_IMF_EVENT_MOUSE_UP,
1731 (Ecore_IMF_Event *)&ecore_ev))
1732 return;
1733 }
1734#endif
1735
1736 tc = evas_object_textblock_cursor_new(rp->object);
1737 evas_textblock_cursor_copy(en->cursor, tc);
1738 evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1739 cx = ev->canvas.x - x;
1740 cy = ev->canvas.y - y;
1741 if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
1742 {
1743 Evas_Coord lx, ly, lw, lh;
1744 int line;
1745
1746 line = evas_textblock_cursor_line_coord_set(en->cursor, cy);
1747 if (line == -1)
1748 {
1749 if (rp->part->multiline)
1750 _curs_end(en->cursor, rp->object, en);
1751 else
1752 {
1753 evas_textblock_cursor_paragraph_first(en->cursor);
1754 evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1755 if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
1756 _curs_end(en->cursor, rp->object, en);
1757 }
1758 }
1759 else
1760 {
1761 int lnum;
1762
1763 lnum = evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1764 if (lnum < 0)
1765 {
1766 _curs_lin_start(en->cursor, rp->object, en);
1767 }
1768 else
1769 {
1770 if (cx <= lx)
1771 _curs_lin_start(en->cursor, rp->object, en);
1772 else
1773 _curs_lin_end(en->cursor, rp->object, en);
1774 }
1775 }
1776 }
1777 if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
1778 {
1779 if (en->select_allow)
1780 {
1781 if (en->had_sel)
1782 {
1783 if (en->select_mod_end)
1784 _sel_extend(en->cursor, rp->object, en);
1785 else if (en->select_mod_start)
1786 _sel_preextend(en->cursor, rp->object, en);
1787 }
1788 else
1789 _sel_extend(en->cursor, rp->object, en);
1790 //evas_textblock_cursor_copy(en->cursor, en->sel_end);
1791 }
1792 }
1793 else
1794 evas_textblock_cursor_copy(en->cursor, en->sel_end);
1795 if (en->selecting)
1796 {
1797 if (en->have_selection)
1798 en->had_sel = EINA_TRUE;
1799 en->selecting = EINA_FALSE;
1800 }
1801 if (evas_textblock_cursor_compare(tc, en->cursor))
1802 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
1803 evas_textblock_cursor_free(tc);
1804
1805 _edje_entry_imf_context_reset(en);
1806 _edje_entry_imf_cursor_info_set(en);
1807 _edje_entry_real_part_configure(rp);
1808}
1809
1810static void
1811_edje_part_mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1812{
1813 Evas_Coord cx, cy;
1814 Edje_Real_Part *rp = data;
1815 Evas_Event_Mouse_Move *ev = event_info;
1816 Entry *en;
1817 Evas_Coord x, y, w, h;
1818 Evas_Textblock_Cursor *tc;
1819 if (!rp) return;
1820 en = rp->entry_data;
1821 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1822 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
1823 return;
1824
1825#ifdef HAVE_ECORE_IMF
1826 if (en->imf_context)
1827 {
1828 Ecore_IMF_Event_Mouse_Move ecore_ev;
1829 ecore_imf_evas_event_mouse_move_wrap(ev, &ecore_ev);
1830 if (ecore_imf_context_filter_event(en->imf_context,
1831 ECORE_IMF_EVENT_MOUSE_MOVE,
1832 (Ecore_IMF_Event *)&ecore_ev))
1833 return;
1834 }
1835#endif
1836
1837 if (en->selecting)
1838 {
1839 tc = evas_object_textblock_cursor_new(rp->object);
1840 evas_textblock_cursor_copy(en->cursor, tc);
1841 evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1842 cx = ev->cur.canvas.x - x;
1843 cy = ev->cur.canvas.y - y;
1844 if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy))
1845 {
1846 Evas_Coord lx, ly, lw, lh;
1847
1848 if (evas_textblock_cursor_line_coord_set(en->cursor, cy) < 0)
1849 {
1850 if (rp->part->multiline)
1851 _curs_end(en->cursor, rp->object, en);
1852 else
1853 {
1854 evas_textblock_cursor_paragraph_first(en->cursor);
1855 evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1856 if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2)))
1857 _curs_end(en->cursor, rp->object, en);
1858 }
1859 }
1860 else
1861 {
1862 evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
1863 if (cx <= lx)
1864 _curs_lin_start(en->cursor, rp->object, en);
1865 else
1866 _curs_lin_end(en->cursor, rp->object, en);
1867 }
1868 }
1869 if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
1870 {
1871 if (en->select_allow)
1872 {
1873 if (en->had_sel)
1874 {
1875 if (en->select_mod_end)
1876 _sel_extend(en->cursor, rp->object, en);
1877 else if (en->select_mod_start)
1878 _sel_preextend(en->cursor, rp->object, en);
1879 }
1880 else
1881 _sel_extend(en->cursor, rp->object, en);
1882 }
1883 }
1884 else
1885 {
1886 _sel_extend(en->cursor, rp->object, en);
1887 }
1888 if (en->select_allow)
1889 {
1890 if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) != 0)
1891 _sel_enable(en->cursor, rp->object, en);
1892 if (en->have_selection)
1893 _sel_update(en->cursor, rp->object, en);
1894 }
1895 if (evas_textblock_cursor_compare(tc, en->cursor))
1896 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
1897 evas_textblock_cursor_free(tc);
1898
1899 _edje_entry_imf_context_reset(en);
1900 _edje_entry_imf_cursor_info_set(en);
1901
1902 _edje_entry_real_part_configure(rp);
1903 }
1904}
1905
1906static void
1907_evas_focus_in_cb(void *data, Evas *e, __UNUSED__ void *event_info)
1908{
1909 Edje *ed = (Edje *)data;
1910
1911 if (evas_focus_get(e) == ed->obj)
1912 {
1913 _edje_focus_in_cb(data, NULL, NULL, NULL);
1914 }
1915}
1916
1917static void
1918_evas_focus_out_cb(void *data, Evas *e, __UNUSED__ void *event_info)
1919{
1920 Edje *ed = (Edje *)data;
1921
1922 if (evas_focus_get(e) == ed->obj)
1923 {
1924 _edje_focus_out_cb(data, NULL, NULL, NULL);
1925 }
1926}
1927
1928/***************************************************************/
1929void
1930_edje_entry_init(Edje *ed)
1931{
1932 if (!ed->has_entries)
1933 return;
1934 if (ed->entries_inited)
1935 return;
1936 ed->entries_inited = EINA_TRUE;
1937
1938 evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb, ed);
1939 evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb, ed);
1940 evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb, ed);
1941 evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb, ed);
1942 evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed);
1943 evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed);
1944}
1945
1946void
1947_edje_entry_shutdown(Edje *ed)
1948{
1949 if (!ed->has_entries)
1950 return;
1951 if (!ed->entries_inited)
1952 return;
1953 ed->entries_inited = EINA_FALSE;
1954
1955 evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_IN, _edje_focus_in_cb);
1956 evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_FOCUS_OUT, _edje_focus_out_cb);
1957 evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN, _edje_key_down_cb);
1958 evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP, _edje_key_up_cb);
1959 if (evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _evas_focus_in_cb, ed) != ed)
1960 ERR("could not unregister EVAS_CALLBACK_FOCUS_IN");
1961 if (evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, _evas_focus_out_cb, ed) != ed)
1962 ERR("could not unregister EVAS_CALLBACK_FOCUS_OUT");
1963}
1964
1965void
1966_edje_entry_real_part_init(Edje_Real_Part *rp)
1967{
1968 Entry *en;
1969#ifdef HAVE_ECORE_IMF
1970 const char *ctx_id;
1971 const Ecore_IMF_Context_Info *ctx_info;
1972#endif
1973
1974 en = calloc(1, sizeof(Entry));
1975 if (!en) return;
1976 rp->entry_data = en;
1977 en->rp = rp;
1978
1979 evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOVE, _edje_part_move_cb, rp);
1980
1981 evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_DOWN, _edje_part_mouse_down_cb, rp);
1982 evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_UP, _edje_part_mouse_up_cb, rp);
1983 evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_MOVE, _edje_part_mouse_move_cb, rp);
1984
1985 if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
1986 en->select_allow = EINA_TRUE;
1987
1988 if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
1989 {
1990 Edje_Part_Description_Text *txt;
1991
1992 txt = (Edje_Part_Description_Text *)rp->chosen_description;
1993
1994 en->select_allow = EINA_FALSE;
1995 if (txt && edje_string_get(&txt->text.repch))
1996 evas_object_textblock_replace_char_set(rp->object, edje_string_get(&txt->text.repch));
1997 else
1998 evas_object_textblock_replace_char_set(rp->object, "*");
1999 }
2000
2001 en->cursor_bg = edje_object_add(rp->edje->base.evas);
2002 edje_object_file_set(en->cursor_bg, rp->edje->path, rp->part->source3);
2003 evas_object_smart_member_add(en->cursor_bg, rp->edje->obj);
2004 evas_object_stack_below(en->cursor_bg, rp->object);
2005 evas_object_clip_set(en->cursor_bg, evas_object_clip_get(rp->object));
2006 evas_object_pass_events_set(en->cursor_bg, EINA_TRUE);
2007 _edje_subobj_register(en->rp->edje, en->cursor_bg);
2008
2009 en->cursor_fg = edje_object_add(rp->edje->base.evas);
2010 edje_object_file_set(en->cursor_fg, rp->edje->path, rp->part->source4);
2011 evas_object_smart_member_add(en->cursor_fg, rp->edje->obj);
2012 evas_object_stack_above(en->cursor_fg, rp->object);
2013 evas_object_clip_set(en->cursor_fg, evas_object_clip_get(rp->object));
2014 evas_object_pass_events_set(en->cursor_fg, EINA_TRUE);
2015 _edje_subobj_register(en->rp->edje, en->cursor_fg);
2016
2017 if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2018 {
2019 evas_object_show(en->cursor_bg);
2020 evas_object_show(en->cursor_fg);
2021#ifdef HAVE_ECORE_IMF
2022 ecore_imf_init();
2023
2024 edje_object_signal_callback_add(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb, rp);
2025 edje_object_signal_callback_add(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb, rp);
2026
2027 ctx_id = ecore_imf_context_default_id_get();
2028 if (ctx_id)
2029 {
2030 ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
2031 if (!ctx_info->canvas_type ||
2032 strcmp(ctx_info->canvas_type, "evas") == 0)
2033 {
2034 en->imf_context = ecore_imf_context_add(ctx_id);
2035 }
2036 else
2037 {
2038 ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
2039 if (ctx_id)
2040 {
2041 en->imf_context = ecore_imf_context_add(ctx_id);
2042 }
2043 }
2044 }
2045 else
2046 en->imf_context = NULL;
2047
2048 if (!en->imf_context) goto done;
2049
2050 ecore_imf_context_client_window_set
2051 (en->imf_context,
2052 (void *)ecore_evas_window_get
2053 (ecore_evas_ecore_evas_get(rp->edje->base.evas)));
2054 ecore_imf_context_client_canvas_set(en->imf_context, rp->edje->base.evas);
2055
2056 ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context,
2057 _edje_entry_imf_retrieve_surrounding_cb, rp->edje);
2058 en->imf_ee_handler_commit = ecore_event_handler_add(ECORE_IMF_EVENT_COMMIT, _edje_entry_imf_event_commit_cb, rp->edje);
2059 en->imf_ee_handler_delete = ecore_event_handler_add(ECORE_IMF_EVENT_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb, rp->edje);
2060 en->imf_ee_handler_changed = ecore_event_handler_add(ECORE_IMF_EVENT_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb, rp->edje);
2061 ecore_imf_context_input_mode_set(en->imf_context,
2062 rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD ?
2063 ECORE_IMF_INPUT_MODE_INVISIBLE : ECORE_IMF_INPUT_MODE_FULL);
2064#endif
2065 }
2066#ifdef HAVE_ECORE_IMF
2067done:
2068#endif
2069 en->cursor = (Evas_Textblock_Cursor *)evas_object_textblock_cursor_get(rp->object);
2070}
2071
2072void
2073_edje_entry_real_part_shutdown(Edje_Real_Part *rp)
2074{
2075 Entry *en = rp->entry_data;
2076 if (!en) return;
2077 rp->entry_data = NULL;
2078 _sel_clear(en->cursor, rp->object, en);
2079 _anchors_clear(en->cursor, rp->object, en);
2080#ifdef HAVE_ECORE_IMF
2081 _preedit_clear(en);
2082#endif
2083 evas_object_del(en->cursor_bg);
2084 evas_object_del(en->cursor_fg);
2085
2086 if (en->pw_timer)
2087 {
2088 ecore_timer_del(en->pw_timer);
2089 en->pw_timer = NULL;
2090 }
2091
2092#ifdef HAVE_ECORE_IMF
2093 if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
2094 {
2095 if (en->imf_context)
2096 {
2097 if (en->imf_ee_handler_commit)
2098 {
2099 ecore_event_handler_del(en->imf_ee_handler_commit);
2100 en->imf_ee_handler_commit = NULL;
2101 }
2102
2103 if (en->imf_ee_handler_delete)
2104 {
2105 ecore_event_handler_del(en->imf_ee_handler_delete);
2106 en->imf_ee_handler_delete = NULL;
2107 }
2108
2109 if (en->imf_ee_handler_changed)
2110 {
2111 ecore_event_handler_del(en->imf_ee_handler_changed);
2112 en->imf_ee_handler_changed = NULL;
2113 }
2114
2115 ecore_imf_context_del(en->imf_context);
2116 en->imf_context = NULL;
2117 }
2118
2119 edje_object_signal_callback_del(rp->edje->obj, "focus,part,in", rp->part->name, _edje_entry_focus_in_cb);
2120 edje_object_signal_callback_del(rp->edje->obj, "focus,part,out", rp->part->name, _edje_entry_focus_out_cb);
2121 ecore_imf_shutdown();
2122 }
2123#endif
2124
2125 free(en);
2126}
2127
2128void
2129_edje_entry_real_part_configure(Edje_Real_Part *rp)
2130{
2131 Evas_Coord x, y, w, h, xx, yy, ww, hh;
2132 Entry *en = rp->entry_data;
2133 Evas_Textblock_Cursor_Type cur_type;
2134 if (!en) return;
2135 switch (rp->part->cursor_mode)
2136 {
2137 case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2138 cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2139 break;
2140 case EDJE_ENTRY_CURSOR_MODE_UNDER:
2141 /* no break for a resaon */
2142 default:
2143 cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2144 }
2145
2146 _sel_update(en->cursor, rp->object, en);
2147 _anchors_update(en->cursor, rp->object, en);
2148 x = y = w = h = -1;
2149 xx = yy = ww = hh = -1;
2150 evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2151 evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
2152 if (ww < 1) ww = 1;
2153 if (hh < 1) hh = 1;
2154 if (en->cursor_bg)
2155 {
2156 evas_object_move(en->cursor_bg, x + xx, y + yy);
2157 evas_object_resize(en->cursor_bg, ww, hh);
2158 }
2159 if (en->cursor_fg)
2160 {
2161 evas_object_move(en->cursor_fg, x + xx, y + yy);
2162 evas_object_resize(en->cursor_fg, ww, hh);
2163 }
2164}
2165
2166const char *
2167_edje_entry_selection_get(Edje_Real_Part *rp)
2168{
2169 Entry *en = rp->entry_data;
2170 if (!en) return NULL;
2171 // get selection - convert to markup
2172 if ((!en->selection) && (en->have_selection))
2173 en->selection = evas_textblock_cursor_range_text_get
2174 (en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
2175 return en->selection;
2176}
2177
2178const char *
2179_edje_entry_text_get(Edje_Real_Part *rp)
2180{
2181 Entry *en = rp->entry_data;
2182 if (!en) return NULL;
2183 // get text - convert to markup
2184 return evas_object_textblock_text_markup_get(rp->object);
2185}
2186
2187void
2188_edje_entry_text_markup_set(Edje_Real_Part *rp, const char *text)
2189{
2190 Entry *en = rp->entry_data;
2191 if (!en) return;
2192
2193 // set text as markup
2194 _sel_clear(en->cursor, rp->object, en);
2195 evas_object_textblock_text_markup_set(rp->object, text);
2196 _edje_entry_set_cursor_start(rp);
2197
2198 _anchors_get(en->cursor, rp->object, en);
2199 _edje_emit(rp->edje, "entry,changed", rp->part->name);
2200 _edje_entry_imf_cursor_info_set(en);
2201#if 0
2202 /* Don't emit cursor changed cause it didn't. It's just init to 0. */
2203 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2204#endif
2205}
2206
2207void
2208_edje_entry_text_markup_append(Edje_Real_Part *rp, const char *text)
2209{
2210 Entry *en = rp->entry_data;
2211 Evas_Textblock_Cursor *end_cur;
2212 if (!en) return;
2213 end_cur = evas_object_textblock_cursor_new(rp->object);
2214 evas_textblock_cursor_paragraph_last(end_cur);
2215
2216 _text_filter_markup_prepend(en, end_cur, text);
2217 evas_textblock_cursor_free(end_cur);
2218
2219 /* We are updating according to the real cursor on purpose */
2220 _anchors_get(en->cursor, rp->object, en);
2221 _edje_emit(rp->edje, "entry,changed", rp->part->name);
2222
2223 _edje_entry_real_part_configure(rp);
2224}
2225
2226void
2227_edje_entry_text_markup_insert(Edje_Real_Part *rp, const char *text)
2228{
2229 Entry *en = rp->entry_data;
2230 if (!en) return;
2231 // prepend markup @ cursor pos
2232 if (en->have_selection)
2233 _range_del(en->cursor, rp->object, en);
2234 _sel_clear(en->cursor, rp->object, en);
2235 //xx
2236// evas_object_textblock_text_markup_prepend(en->cursor, text);
2237 _text_filter_markup_prepend(en, en->cursor, text);
2238 _anchors_get(en->cursor, rp->object, en);
2239 _edje_emit(rp->edje, "entry,changed", rp->part->name);
2240 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2241
2242 _edje_entry_imf_context_reset(en);
2243 _edje_entry_imf_cursor_info_set(en);
2244
2245 _edje_entry_real_part_configure(rp);
2246}
2247
2248void
2249_edje_entry_set_cursor_start(Edje_Real_Part *rp)
2250{
2251 Entry *en = rp->entry_data;
2252 if (!en) return;
2253 _curs_start(en->cursor, rp->object, en);
2254
2255 _edje_entry_imf_cursor_info_set(en);
2256}
2257
2258void
2259_edje_entry_set_cursor_end(Edje_Real_Part *rp)
2260{
2261 Entry *en = rp->entry_data;
2262 if (!en) return;
2263 _curs_end(en->cursor, rp->object, en);
2264
2265 _edje_entry_imf_cursor_info_set(en);
2266}
2267
2268void
2269_edje_entry_select_none(Edje_Real_Part *rp)
2270{
2271 Entry *en = rp->entry_data;
2272 if (!en) return;
2273 _sel_clear(en->cursor, rp->object, en);
2274}
2275
2276void
2277_edje_entry_select_all(Edje_Real_Part *rp)
2278{
2279 Entry *en = rp->entry_data;
2280 if (!en) return;
2281 _sel_clear(en->cursor, rp->object, en);
2282 _curs_start(en->cursor, rp->object, en);
2283 _sel_enable(en->cursor, rp->object, en);
2284 _sel_start(en->cursor, rp->object, en);
2285 _curs_end(en->cursor, rp->object, en);
2286 _sel_extend(en->cursor, rp->object, en);
2287
2288 _edje_entry_imf_context_reset(en);
2289 _edje_entry_imf_cursor_info_set(en);
2290 _edje_entry_real_part_configure(rp);
2291}
2292
2293void
2294_edje_entry_select_begin(Edje_Real_Part *rp)
2295{
2296 Entry *en = rp->entry_data;
2297 if (!en) return;
2298 _sel_clear(en->cursor, rp->object, en);
2299 _sel_enable(en->cursor, rp->object, en);
2300 _sel_start(en->cursor, rp->object, en);
2301 _sel_extend(en->cursor, rp->object, en);
2302
2303 _edje_entry_imf_context_reset(en);
2304 _edje_entry_imf_cursor_info_set(en);
2305
2306 _edje_entry_real_part_configure(rp);
2307}
2308
2309void
2310_edje_entry_select_extend(Edje_Real_Part *rp)
2311{
2312 Entry *en = rp->entry_data;
2313 if (!en) return;
2314 _sel_extend(en->cursor, rp->object, en);
2315
2316 _edje_entry_imf_context_reset(en);
2317 _edje_entry_imf_cursor_info_set(en);
2318
2319 _edje_entry_real_part_configure(rp);
2320}
2321
2322const Eina_List *
2323_edje_entry_anchor_geometry_get(Edje_Real_Part *rp, const char *anchor)
2324{
2325 Entry *en = rp->entry_data;
2326 Eina_List *l;
2327 Anchor *an;
2328
2329 if (!en) return NULL;
2330 EINA_LIST_FOREACH(en->anchors, l, an)
2331 {
2332 if (an->item) continue;
2333 if (!strcmp(anchor, an->name))
2334 return an->sel;
2335 }
2336 return NULL;
2337}
2338
2339const Eina_List *
2340_edje_entry_anchors_list(Edje_Real_Part *rp)
2341{
2342 Entry *en = rp->entry_data;
2343 Eina_List *l, *anchors = NULL;
2344 Anchor *an;
2345
2346 if (!en) return NULL;
2347 if (!en->anchorlist)
2348 {
2349 EINA_LIST_FOREACH(en->anchors, l, an)
2350 {
2351 const char *n = an->name;
2352 if (an->item) continue;
2353 if (!n) n = "";
2354 anchors = eina_list_append(anchors, strdup(n));
2355 }
2356 en->anchorlist = anchors;
2357 }
2358 return en->anchorlist;
2359}
2360
2361Eina_Bool
2362_edje_entry_item_geometry_get(Edje_Real_Part *rp, const char *item, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
2363{
2364 Entry *en = rp->entry_data;
2365 Eina_List *l;
2366 Anchor *an;
2367
2368 if (!en) return EINA_FALSE;
2369 EINA_LIST_FOREACH(en->anchors, l, an)
2370 {
2371 if (an->item) continue;
2372 if (!strcmp(item, an->name))
2373 {
2374 evas_textblock_cursor_format_item_geometry_get(an->start, cx, cy, cw, ch);
2375 return EINA_TRUE;
2376 }
2377 }
2378 return EINA_FALSE;
2379}
2380
2381const Eina_List *
2382_edje_entry_items_list(Edje_Real_Part *rp)
2383{
2384 Entry *en = rp->entry_data;
2385 Eina_List *l, *items = NULL;
2386 Anchor *an;
2387
2388 if (!en) return NULL;
2389 if (!en->itemlist)
2390 {
2391 EINA_LIST_FOREACH(en->anchors, l, an)
2392 {
2393 const char *n = an->name;
2394 if (an->item) continue;
2395 if (!n) n = "";
2396 items = eina_list_append(items, strdup(n));
2397 }
2398 en->itemlist = items;
2399 }
2400 return en->itemlist;
2401}
2402
2403void
2404_edje_entry_cursor_geometry_get(Edje_Real_Part *rp, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
2405{
2406 Evas_Coord x, y, w, h, xx, yy, ww, hh;
2407 Entry *en = rp->entry_data;
2408 Evas_Textblock_Cursor_Type cur_type;
2409 if (!en) return;
2410 switch (rp->part->cursor_mode)
2411 {
2412 case EDJE_ENTRY_CURSOR_MODE_BEFORE:
2413 cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
2414 break;
2415 case EDJE_ENTRY_CURSOR_MODE_UNDER:
2416 /* no break for a resaon */
2417 default:
2418 cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
2419 }
2420
2421 x = y = w = h = -1;
2422 xx = yy = ww = hh = -1;
2423 evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2424 evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, NULL, cur_type);
2425 if (ww < 1) ww = 1;
2426 if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
2427 edje_object_size_min_restricted_calc(en->cursor_fg, &ww, NULL, ww, 0);
2428 if (hh < 1) hh = 1;
2429 if (cx) *cx = x + xx;
2430 if (cy) *cy = y + yy;
2431 if (cw) *cw = ww;
2432 if (ch) *ch = hh;
2433}
2434
2435void
2436_edje_entry_select_allow_set(Edje_Real_Part *rp, Eina_Bool allow)
2437{
2438 Entry *en = rp->entry_data;
2439 if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
2440 return;
2441 en->select_allow = allow;
2442}
2443
2444Eina_Bool
2445_edje_entry_select_allow_get(const Edje_Real_Part *rp)
2446{
2447 const Entry *en = rp->entry_data;
2448 return en->select_allow;
2449}
2450
2451void
2452_edje_entry_select_abort(Edje_Real_Part *rp)
2453{
2454 Entry *en = rp->entry_data;
2455 if (en->selecting)
2456 {
2457 en->selecting = EINA_FALSE;
2458
2459 _edje_entry_imf_context_reset(en);
2460 _edje_entry_imf_cursor_info_set(en);
2461 _edje_entry_real_part_configure(rp);
2462 }
2463}
2464
2465void
2466_edje_entry_autocapital_type_set(Edje_Real_Part *rp, Edje_Text_Autocapital_Type autocapital_type)
2467{
2468 Entry *en = rp->entry_data;
2469 if (!en) return;
2470
2471 if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
2472 autocapital_type = EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2473
2474#ifdef HAVE_ECORE_IMF
2475 if (en->imf_context)
2476 ecore_imf_context_autocapital_type_set(en->imf_context, autocapital_type);
2477#endif
2478}
2479
2480Edje_Text_Autocapital_Type
2481_edje_entry_autocapital_type_get(Edje_Real_Part *rp)
2482{
2483 Entry *en = rp->entry_data;
2484 if (!en) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2485
2486#ifdef HAVE_ECORE_IMF
2487 if (en->imf_context)
2488 return ecore_imf_context_autocapital_type_get(en->imf_context);
2489#endif
2490
2491 return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2492}
2493
2494void
2495_edje_entry_input_panel_enabled_set(Edje_Real_Part *rp, Eina_Bool enabled)
2496{
2497 Entry *en = rp->entry_data;
2498
2499 if (!en) return;
2500#ifdef HAVE_ECORE_IMF
2501 if (en->imf_context)
2502 ecore_imf_context_input_panel_enabled_set(en->imf_context, enabled);
2503#else
2504 (void) enabled;
2505#endif
2506}
2507
2508Eina_Bool
2509_edje_entry_input_panel_enabled_get(Edje_Real_Part *rp)
2510{
2511 Entry *en = rp->entry_data;
2512 if (!en) return EINA_FALSE;
2513#ifdef HAVE_ECORE_IMF
2514 if (en->imf_context)
2515 return ecore_imf_context_input_panel_enabled_get(en->imf_context);
2516#endif
2517
2518 return EINA_FALSE;
2519}
2520
2521static Evas_Textblock_Cursor *
2522_cursor_get(Edje_Real_Part *rp, Edje_Cursor cur)
2523{
2524 Entry *en = rp->entry_data;
2525 if (!en) return NULL;
2526
2527 switch (cur)
2528 {
2529 case EDJE_CURSOR_MAIN:
2530 return en->cursor;
2531 case EDJE_CURSOR_SELECTION_BEGIN:
2532 return en->sel_start;
2533 case EDJE_CURSOR_SELECTION_END:
2534 return en->sel_end;
2535 case EDJE_CURSOR_PREEDIT_START:
2536 if (!en->preedit_start)
2537 en->preedit_start = evas_object_textblock_cursor_new(rp->object);
2538 return en->preedit_start;
2539 case EDJE_CURSOR_PREEDIT_END:
2540 if (!en->preedit_end)
2541 en->preedit_end = evas_object_textblock_cursor_new(rp->object);
2542 return en->preedit_end;
2543 case EDJE_CURSOR_USER:
2544 if (!en->cursor_user)
2545 en->cursor_user = evas_object_textblock_cursor_new(rp->object);
2546 return en->cursor_user;
2547 case EDJE_CURSOR_USER_EXTRA:
2548 if (!en->cursor_user_extra)
2549 en->cursor_user_extra = evas_object_textblock_cursor_new(rp->object);
2550 return en->cursor_user_extra;
2551 default:
2552 break;
2553 }
2554 return NULL;
2555}
2556
2557Eina_Bool
2558_edje_entry_cursor_next(Edje_Real_Part *rp, Edje_Cursor cur)
2559{
2560 Entry *en = rp->entry_data;
2561 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2562 if (!c) return EINA_FALSE;
2563 if (!evas_textblock_cursor_char_next(c))
2564 {
2565 return EINA_FALSE;
2566 }
2567 _sel_update(c, rp->object, rp->entry_data);
2568
2569 _edje_entry_imf_context_reset(en);
2570 _edje_entry_imf_cursor_info_set(en);
2571
2572 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2573 _edje_entry_real_part_configure(rp);
2574 return EINA_TRUE;
2575}
2576
2577Eina_Bool
2578_edje_entry_cursor_prev(Edje_Real_Part *rp, Edje_Cursor cur)
2579{
2580 Entry *en = rp->entry_data;
2581 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2582 if (!c) return EINA_FALSE;
2583 if (!evas_textblock_cursor_char_prev(c))
2584 {
2585 if (evas_textblock_cursor_paragraph_prev(c)) goto ok;
2586 else return EINA_FALSE;
2587 }
2588ok:
2589 _sel_update(c, rp->object, rp->entry_data);
2590
2591 _edje_entry_imf_context_reset(en);
2592 _edje_entry_imf_cursor_info_set(en);
2593
2594 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2595 _edje_entry_real_part_configure(rp);
2596 return EINA_TRUE;
2597}
2598
2599Eina_Bool
2600_edje_entry_cursor_up(Edje_Real_Part *rp, Edje_Cursor cur)
2601{
2602 Entry *en = rp->entry_data;
2603 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2604 Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
2605 int ln;
2606 if (!c) return EINA_FALSE;
2607 ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
2608 ln--;
2609 if (ln < 0) return EINA_FALSE;
2610 if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
2611 &lx, &ly, &lw, &lh))
2612 return EINA_FALSE;
2613 evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
2614 if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
2615 {
2616 if (cx < (lx + (lw / 2)))
2617 evas_textblock_cursor_line_char_last(c);
2618 else
2619 evas_textblock_cursor_line_char_last(c);
2620 }
2621 _sel_update(c, rp->object, rp->entry_data);
2622
2623 _edje_entry_imf_context_reset(en);
2624 _edje_entry_imf_cursor_info_set(en);
2625
2626 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2627 _edje_entry_real_part_configure(rp);
2628 return EINA_TRUE;
2629}
2630
2631Eina_Bool
2632_edje_entry_cursor_down(Edje_Real_Part *rp, Edje_Cursor cur)
2633{
2634 Entry *en = rp->entry_data;
2635 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2636 Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
2637 int ln;
2638 if (!c) return EINA_FALSE;
2639 ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
2640 ln++;
2641 if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
2642 &lx, &ly, &lw, &lh))
2643 return EINA_FALSE;
2644 evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
2645 if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2)))
2646 {
2647 if (cx < (lx + (lw / 2)))
2648 evas_textblock_cursor_line_char_last(c);
2649 else
2650 evas_textblock_cursor_line_char_last(c);
2651 }
2652 _sel_update(c, rp->object, rp->entry_data);
2653
2654 _edje_entry_imf_context_reset(en);
2655 _edje_entry_imf_cursor_info_set(en);
2656 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2657 _edje_entry_real_part_configure(rp);
2658 return EINA_TRUE;
2659}
2660
2661void
2662_edje_entry_cursor_begin(Edje_Real_Part *rp, Edje_Cursor cur)
2663{
2664 Entry *en = rp->entry_data;
2665 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2666 if (!c) return;
2667 evas_textblock_cursor_paragraph_first(c);
2668 _sel_update(c, rp->object, rp->entry_data);
2669
2670 _edje_entry_imf_context_reset(en);
2671 _edje_entry_imf_cursor_info_set(en);
2672 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2673 _edje_entry_real_part_configure(rp);
2674}
2675
2676void
2677_edje_entry_cursor_end(Edje_Real_Part *rp, Edje_Cursor cur)
2678{
2679 Entry *en = rp->entry_data;
2680 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2681 if (!c) return;
2682 _curs_end(c, rp->object, rp->entry_data);
2683 _sel_update(c, rp->object, rp->entry_data);
2684
2685 _edje_entry_imf_context_reset(en);
2686 _edje_entry_imf_cursor_info_set(en);
2687
2688 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2689 _edje_entry_real_part_configure(rp);
2690}
2691
2692void
2693_edje_entry_cursor_copy(Edje_Real_Part *rp, Edje_Cursor cur, Edje_Cursor dst)
2694{
2695 Entry *en = rp->entry_data;
2696 Evas_Textblock_Cursor *c;
2697 Evas_Textblock_Cursor *d;
2698
2699 c = _cursor_get(rp, cur);
2700 if (!c) return;
2701 d = _cursor_get(rp, dst);
2702 if (!d) return;
2703 evas_textblock_cursor_copy(c, d);
2704 _sel_update(c, rp->object, rp->entry_data);
2705
2706 _edje_entry_imf_context_reset(en);
2707 _edje_entry_imf_cursor_info_set(en);
2708 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2709 _edje_entry_real_part_configure(rp);
2710}
2711
2712void
2713_edje_entry_cursor_line_begin(Edje_Real_Part *rp, Edje_Cursor cur)
2714{
2715 Entry *en = rp->entry_data;
2716 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2717 if (!c) return;
2718 evas_textblock_cursor_line_char_first(c);
2719 _sel_update(c, rp->object, rp->entry_data);
2720
2721 _edje_entry_imf_context_reset(en);
2722 _edje_entry_imf_cursor_info_set(en);
2723
2724 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2725 _edje_entry_real_part_configure(rp);
2726}
2727
2728void
2729_edje_entry_cursor_line_end(Edje_Real_Part *rp, Edje_Cursor cur)
2730{
2731 Entry *en = rp->entry_data;
2732 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2733 if (!c) return;
2734 evas_textblock_cursor_line_char_last(c);
2735 _sel_update(c, rp->object, rp->entry_data);
2736
2737 _edje_entry_imf_context_reset(en);
2738 _edje_entry_imf_cursor_info_set(en);
2739 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2740 _edje_entry_real_part_configure(rp);
2741}
2742
2743Eina_Bool
2744_edje_entry_cursor_coord_set(Edje_Real_Part *rp, Edje_Cursor cur,
2745 Evas_Coord x, Evas_Coord y)
2746{
2747 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2748 if (!c) return EINA_FALSE;
2749 return evas_textblock_cursor_char_coord_set(c, x, y);
2750}
2751
2752Eina_Bool
2753_edje_entry_cursor_is_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
2754{
2755 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2756 if (!c) return EINA_FALSE;
2757 if (evas_textblock_cursor_is_format(c)) return EINA_TRUE;
2758 return EINA_FALSE;
2759}
2760
2761Eina_Bool
2762_edje_entry_cursor_is_visible_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
2763{
2764 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2765 if (!c) return EINA_FALSE;
2766 return evas_textblock_cursor_format_is_visible_get(c);
2767}
2768
2769const char *
2770_edje_entry_cursor_content_get(Edje_Real_Part *rp, Edje_Cursor cur)
2771{
2772 static char *s = NULL;
2773 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2774
2775 if (!c) return NULL;
2776 if (s)
2777 {
2778 free(s);
2779 s = NULL;
2780 }
2781
2782 s = evas_textblock_cursor_content_get(c);
2783 return s;
2784}
2785
2786void
2787_edje_entry_cursor_pos_set(Edje_Real_Part *rp, Edje_Cursor cur, int pos)
2788{
2789 Entry *en = rp->entry_data;
2790 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2791 if (!c) return;
2792 /* Abort if cursor position didn't really change */
2793 if (evas_textblock_cursor_pos_get(c) == pos)
2794 return;
2795
2796 evas_textblock_cursor_pos_set(c, pos);
2797 _sel_update(c, rp->object, rp->entry_data);
2798
2799 _edje_entry_imf_context_reset(en);
2800 _edje_entry_imf_cursor_info_set(en);
2801 _edje_emit(rp->edje, "cursor,changed", rp->part->name);
2802 _edje_entry_real_part_configure(rp);
2803}
2804
2805int
2806_edje_entry_cursor_pos_get(Edje_Real_Part *rp, Edje_Cursor cur)
2807{
2808 Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
2809 if (!c) return 0;
2810 return evas_textblock_cursor_pos_get(c);
2811}
2812
2813void
2814_edje_entry_input_panel_layout_set(Edje_Real_Part *rp, Edje_Input_Panel_Layout layout)
2815{
2816 Entry *en = rp->entry_data;
2817 if (!en) return;
2818#ifdef HAVE_ECORE_IMF
2819 if (en->imf_context)
2820 ecore_imf_context_input_panel_layout_set(en->imf_context, layout);
2821#else
2822 (void) layout;
2823#endif
2824}
2825
2826Edje_Input_Panel_Layout
2827_edje_entry_input_panel_layout_get(Edje_Real_Part *rp)
2828{
2829 Entry *en = rp->entry_data;
2830 if (!en) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
2831#ifdef HAVE_ECORE_IMF
2832 if (en->imf_context)
2833 return ecore_imf_context_input_panel_layout_get(en->imf_context);
2834#endif
2835
2836 return EDJE_INPUT_PANEL_LAYOUT_INVALID;
2837}
2838
2839static void
2840_edje_entry_imf_context_reset(Entry *en)
2841{
2842#ifdef HAVE_ECORE_IMF
2843 if (en->imf_context)
2844 ecore_imf_context_reset(en->imf_context);
2845#else
2846 (void) en;
2847#endif
2848}
2849
2850static void
2851_edje_entry_imf_cursor_info_set(Entry *en)
2852{
2853#ifdef HAVE_ECORE_IMF
2854 Evas_Coord cx, cy, cw, ch;
2855 if (!en || !en->rp || !en->imf_context) return;
2856
2857 _edje_entry_cursor_geometry_get(en->rp, &cx, &cy, &cw, &ch);
2858
2859 ecore_imf_context_cursor_position_set(en->imf_context,
2860 evas_textblock_cursor_pos_get(en->cursor));
2861 ecore_imf_context_cursor_location_set(en->imf_context, cx, cy, cw, ch);
2862#else
2863 (void) en;
2864#endif
2865}
2866
2867#ifdef HAVE_ECORE_IMF
2868static Eina_Bool
2869_edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx __UNUSED__, char **text, int *cursor_pos)
2870{
2871 Edje *ed = data;
2872 Edje_Real_Part *rp = ed->focused_part;
2873 Entry *en;
2874 const char *str;
2875
2876 if (!rp) return EINA_FALSE;
2877 en = rp->entry_data;
2878 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2879 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2880 return EINA_FALSE;
2881
2882 if (text)
2883 {
2884 str = _edje_entry_text_get(rp);
2885 *text = str ? strdup(str) : strdup("");
2886 }
2887
2888 if (cursor_pos)
2889 *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
2890
2891 return EINA_TRUE;
2892}
2893
2894static Eina_Bool
2895_edje_entry_imf_event_commit_cb(void *data, int type __UNUSED__, void *event)
2896{
2897 Edje *ed = data;
2898 Edje_Real_Part *rp = ed->focused_part;
2899 Entry *en;
2900 Ecore_IMF_Event_Commit *ev = event;
2901 Evas_Textblock_Cursor *tc;
2902 Eina_Bool cursor_move = EINA_FALSE;
2903
2904 if ((!rp) || (!ev) || (!ev->str)) return ECORE_CALLBACK_PASS_ON;
2905
2906 en = rp->entry_data;
2907 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2908 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2909 return ECORE_CALLBACK_PASS_ON;
2910
2911 if (!en->imf_context) return ECORE_CALLBACK_PASS_ON;
2912 if (en->imf_context != ev->ctx) return ECORE_CALLBACK_PASS_ON;
2913
2914 if (en->have_selection)
2915 {
2916 if (strcmp(ev->str, ""))
2917 {
2918 /* delete selected characters */
2919 _range_del(en->cursor, rp->object, en);
2920 _sel_clear(en->cursor, rp->object, en);
2921 }
2922 }
2923
2924 tc = evas_object_textblock_cursor_new(rp->object);
2925
2926 /* calculate the cursor position to insert commit string */
2927 if (en->preedit_start)
2928 evas_textblock_cursor_copy(en->preedit_start, tc);
2929 else
2930 evas_textblock_cursor_copy(en->cursor, tc);
2931
2932#ifdef HAVE_ECORE_IMF
2933 /* delete preedit characters */
2934 _preedit_del(en);
2935 _preedit_clear(en);
2936#endif
2937
2938 if (evas_textblock_cursor_compare(en->cursor, tc))
2939 cursor_move = EINA_TRUE;
2940 if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
2941 _edje_password_show_last)
2942 _edje_entry_hide_visible_password(en->rp);
2943 if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
2944 _edje_password_show_last && (!en->preedit_start))
2945 {
2946 _text_filter_format_prepend(en, tc, "+ password=off");
2947 _text_filter_markup_prepend(en, tc, ev->str);
2948 _text_filter_format_prepend(en, tc, "- password");
2949 if (en->pw_timer)
2950 {
2951 ecore_timer_del(en->pw_timer);
2952 en->pw_timer = NULL;
2953 }
2954 en->pw_timer = ecore_timer_add(_edje_password_show_last_timeout,
2955 _password_timer_cb, en);
2956 }
2957 else
2958 _text_filter_text_prepend(en, tc, ev->str);
2959
2960 if (!cursor_move)
2961 {
2962 /* move cursor to the end of commit string */
2963 evas_textblock_cursor_copy(tc, en->cursor);
2964 }
2965
2966 evas_textblock_cursor_free(tc);
2967
2968 _edje_entry_imf_cursor_info_set(en);
2969 _anchors_get(en->cursor, rp->object, en);
2970 _edje_emit(rp->edje, "entry,changed", rp->part->name);
2971 _edje_emit(ed, "entry,changed,user", rp->part->name);
2972 _edje_emit(ed, "cursor,changed", rp->part->name);
2973
2974 return ECORE_CALLBACK_DONE;
2975}
2976
2977static Eina_Bool
2978_edje_entry_imf_event_preedit_changed_cb(void *data, int type __UNUSED__, void *event)
2979{
2980 Edje *ed = data;
2981 Edje_Real_Part *rp = ed->focused_part;
2982 Entry *en;
2983 Ecore_IMF_Event_Preedit_Changed *ev = event;
2984 int cursor_pos;
2985 int preedit_start_pos, preedit_end_pos;
2986 char *preedit_string;
2987 int i;
2988 Eina_Bool preedit_end_state = EINA_FALSE;
2989
2990 if ((!rp) || (!ev)) return ECORE_CALLBACK_PASS_ON;
2991
2992 en = rp->entry_data;
2993 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2994 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2995 return ECORE_CALLBACK_PASS_ON;
2996
2997 if (!en->imf_context) return ECORE_CALLBACK_PASS_ON;
2998
2999 if (en->imf_context != ev->ctx) return ECORE_CALLBACK_PASS_ON;
3000
3001 ecore_imf_context_preedit_string_get(en->imf_context, &preedit_string, &cursor_pos);
3002 if (!preedit_string) return ECORE_CALLBACK_PASS_ON;
3003
3004 if (!strcmp(preedit_string, ""))
3005 preedit_end_state = EINA_TRUE;
3006
3007 if (en->have_selection && !preedit_end_state)
3008 {
3009 /* delete selected characters */
3010 _range_del(en->cursor, rp->object, en);
3011 _sel_clear(en->cursor, rp->object, en);
3012 }
3013
3014 /* delete preedit characters */
3015 _preedit_del(en);
3016
3017 preedit_start_pos = evas_textblock_cursor_pos_get(en->cursor);
3018
3019 /* insert preedit character(s) */
3020 if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
3021 _edje_password_show_last)
3022 {
3023 _text_filter_format_prepend(en, en->cursor, "+ password=off");
3024 _text_filter_markup_prepend(en, en->cursor, preedit_string);
3025 _text_filter_format_prepend(en, en->cursor, "- password");
3026 if (en->pw_timer)
3027 {
3028 ecore_timer_del(en->pw_timer);
3029 en->pw_timer = NULL;
3030 }
3031 en->pw_timer = ecore_timer_add(_edje_password_show_last_timeout,
3032 _password_timer_cb, en);
3033 }
3034 else
3035 {
3036 _text_filter_markup_prepend(en, en->cursor, preedit_string);
3037 }
3038
3039 if (!preedit_end_state)
3040 {
3041 /* set preedit start cursor */
3042 if (!en->preedit_start)
3043 en->preedit_start = evas_object_textblock_cursor_new(rp->object);
3044 evas_textblock_cursor_copy(en->cursor, en->preedit_start);
3045
3046 /* set preedit end cursor */
3047 if (!en->preedit_end)
3048 en->preedit_end = evas_object_textblock_cursor_new(rp->object);
3049 evas_textblock_cursor_copy(en->cursor, en->preedit_end);
3050
3051 preedit_end_pos = evas_textblock_cursor_pos_get(en->cursor);
3052
3053 for (i = 0; i < (preedit_end_pos - preedit_start_pos); i++)
3054 {
3055 evas_textblock_cursor_char_prev(en->preedit_start);
3056 }
3057
3058 en->have_preedit = EINA_TRUE;
3059
3060 /* set cursor position */
3061 evas_textblock_cursor_pos_set(en->cursor, preedit_start_pos + cursor_pos);
3062 }
3063
3064 _edje_entry_imf_cursor_info_set(en);
3065 _anchors_get(en->cursor, rp->object, en);
3066 _edje_emit(rp->edje, "preedit,changed", rp->part->name);
3067 _edje_emit(ed, "cursor,changed", rp->part->name);
3068
3069 free(preedit_string);
3070
3071 return ECORE_CALLBACK_DONE;
3072}
3073
3074static Eina_Bool
3075_edje_entry_imf_event_delete_surrounding_cb(void *data, int type __UNUSED__, void *event)
3076{
3077 Edje *ed = data;
3078 Edje_Real_Part *rp = ed->focused_part;
3079 Entry *en;
3080 Ecore_IMF_Event_Delete_Surrounding *ev = event;
3081 Evas_Textblock_Cursor *del_start, *del_end;
3082 int cursor_pos;
3083
3084 if ((!rp) || (!ev)) return ECORE_CALLBACK_PASS_ON;
3085 en = rp->entry_data;
3086 if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3087 (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
3088 return ECORE_CALLBACK_PASS_ON;
3089
3090 if (!en->imf_context) return ECORE_CALLBACK_PASS_ON;
3091 if (en->imf_context != ev->ctx) return ECORE_CALLBACK_PASS_ON;
3092
3093 cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
3094
3095 del_start = evas_object_textblock_cursor_new(en->rp->object);
3096 evas_textblock_cursor_pos_set(del_start, cursor_pos + ev->offset);
3097
3098 del_end = evas_object_textblock_cursor_new(en->rp->object);
3099 evas_textblock_cursor_pos_set(del_end, cursor_pos + ev->offset + ev->n_chars);
3100
3101 evas_textblock_cursor_range_delete(del_start, del_end);
3102
3103 evas_textblock_cursor_free(del_start);
3104 evas_textblock_cursor_free(del_end);
3105
3106 return ECORE_CALLBACK_DONE;
3107}
3108#endif
3109
3110/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/