efl

Форк
0
/
edje_entry.c 
5209 строк · 159.7 Кб
1
#include "edje_private.h"
2

3
#ifdef HAVE_ECORE_IMF
4
static Eina_Bool _edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
5
static void      _edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx, void *event_info);
6
static void      _edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx, void *event_info);
7
static void      _edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx, void *event);
8
static void      _edje_entry_imf_event_selection_set_cb(void *data, Ecore_IMF_Context *ctx, void *event_info);
9
static Eina_Bool _edje_entry_imf_retrieve_selection_cb(void *data, Ecore_IMF_Context *ctx, char **text);
10
#endif
11

12
typedef struct _Entry  Entry;
13
typedef struct _Sel    Sel;
14
typedef struct _Anchor Anchor;
15
typedef struct _Item_Obj Item_Obj;
16

17
static void _edje_entry_imf_cursor_location_set(Entry *en);
18
static void _edje_entry_imf_cursor_info_set(Entry *en);
19
static void _range_del_emit(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en);
20
static void _text_filter_format_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c, const char *text);
21
static void _free_entry_change_info(void *_info);
22

23
struct _Entry
24
{
25
   Edje_Real_Part        *rp;
26
   Edje                  *ed;
27
   Evas_Coord             ox, oy;
28
   Evas_Object           *cursor_bg;
29
   Evas_Object           *cursor_fg, *cursor_fg2;
30
/* CHANGE EDJE_ENTRY_NUM_CURSOR_OBJS IF YOU ADD MORE OBJECTS HERE */
31
   Evas_Textblock_Cursor *cursor;
32
   Evas_Textblock_Cursor *sel_start, *sel_end;
33
   Evas_Textblock_Cursor *cursor_user, *cursor_user_extra;
34
   Evas_Textblock_Cursor *preedit_start, *preedit_end;
35
   Ecore_Timer           *pw_timer;
36
   Eina_List             *sel;
37
   Eina_List             *anchors;
38
   Eina_List             *anchorlist;
39
   Eina_List             *itemlist;
40
   Eina_List             *seq;
41
   Item_Obj              *item_objs;
42
   char                  *selection;
43
   Edje_Input_Panel_Lang  input_panel_lang;
44
   Eina_Bool              composing : 1;
45
   Eina_Bool              selecting : 1;
46
   Eina_Bool              have_selection : 1;
47
   Eina_Bool              select_allow : 1;
48
   Eina_Bool              select_mod_start : 1;
49
   Eina_Bool              select_mod_end : 1;
50
   Eina_Bool              had_sel : 1;
51
   Eina_Bool              input_panel_enable : 1;
52
   Eina_Bool              prediction_allow : 1;
53
   Eina_Bool              anchors_updated : 1;
54
   Eina_Bool              have_link_pressed : 1;
55

56
#ifdef HAVE_ECORE_IMF
57
   Eina_Bool              have_preedit : 1;
58
   Eina_Bool              commit_cancel : 1; // For skipping useless commit
59
   Ecore_IMF_Context     *imf_context;
60
#endif
61
};
62

63
struct _Sel
64
{
65
   Evas_Textblock_Rectangle rect;
66
   Evas_Object             *obj_fg, *obj_bg, *obj, *sobj;
67
};
68

69
struct _Anchor
70
{
71
   Entry                 *en;
72
   char                  *name;
73
   Evas_Textblock_Cursor *start, *end;
74
   Eina_List             *sel;
75
   Eina_Bool              item : 1;
76
};
77

78
struct _Item_Obj
79
{
80
   EINA_INLIST;
81
   Anchor                *an;
82
   char                  *name;
83
   Evas_Object           *obj;
84
};
85

86
#ifdef HAVE_ECORE_IMF
87
static void
88
_preedit_clear(Entry *en)
89
{
90
   if (en->preedit_start)
91
     {
92
        evas_textblock_cursor_free(en->preedit_start);
93
        en->preedit_start = NULL;
94
     }
95

96
   if (en->preedit_end)
97
     {
98
        evas_textblock_cursor_free(en->preedit_end);
99
        en->preedit_end = NULL;
100
     }
101

102
   en->have_preedit = EINA_FALSE;
103
}
104

105
static void
106
_preedit_del(Entry *en)
107
{
108
   if (!en || !en->have_preedit) return;
109
   if (!en->preedit_start || !en->preedit_end) return;
110
   if (!evas_textblock_cursor_compare(en->preedit_start, en->preedit_end)) return;
111

112
   /* delete the preedit characters */
113
   evas_textblock_cursor_range_delete(en->preedit_start, en->preedit_end);
114
}
115

116
static void
117
_edje_entry_focus_in_cb(void *data, Evas_Object *o, const char *emission, const char *source EINA_UNUSED)
118
{
119
   Efl_Input_Device *seat;
120
   const char *seat_name;
121
   Edje_Real_Part *rp;
122
   Entry *en;
123
   Edje *ed;
124

125
   rp = data;
126
   if ((!rp) || (rp->type != EDJE_RP_TYPE_TEXT) ||
127
       (!rp->typedata.text)) return;
128
   if (!rp->typedata.text->entry_data) return;
129

130
   ed = _edje_fetch(o);
131
   if (!ed) return;
132

133
   en = rp->typedata.text->entry_data;
134
   if (!en || !en->imf_context) return;
135

136
   seat_name = emission + sizeof("focus,part,in,") - 1;
137
   seat = _edje_seat_get(ed, seat_name);
138

139
   if (efl_canvas_object_seat_focus_check(ed->obj, seat))
140
     {
141
        ecore_imf_context_focus_in(en->imf_context);
142
        _edje_entry_imf_cursor_info_set(en);
143
     }
144
}
145

146
static void
147
_edje_entry_focus_out_cb(void *data, Evas_Object *o EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
148
{
149
   Edje_Real_Part *rp;
150
   Entry *en;
151

152
   rp = data;
153
   if ((!rp) || (rp->type != EDJE_RP_TYPE_TEXT) ||
154
       (!rp->typedata.text)) return;
155
   if (!rp->typedata.text->entry_data) return;
156

157
   en = rp->typedata.text->entry_data;
158
   if (!en || !en->imf_context) return;
159

160
   ecore_imf_context_reset(en->imf_context);
161
   ecore_imf_context_focus_out(en->imf_context);
162
}
163

164
#endif
165

166
static void
167
_edje_focus_in(Edje *ed, Efl_Input_Device *seat)
168
{
169
#ifdef HAVE_ECORE_IMF
170
   Edje_Real_Part *rp;
171
   Entry *en;
172
#endif
173

174
   _edje_seat_emit(ed, seat, "focus,in", "");
175
#ifdef HAVE_ECORE_IMF
176
   rp = _edje_focused_part_get(ed, _edje_seat_name_get(ed, seat));
177
   if (!rp) return;
178
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
179
       (!rp->typedata.text)) return;
180
   en = rp->typedata.text->entry_data;
181
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
182
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
183
     return;
184

185
   if (!en->imf_context) return;
186

187
   ecore_imf_context_focus_in(en->imf_context);
188
   _edje_entry_imf_cursor_info_set(en);
189
#endif
190
}
191

192
static void
193
_edje_focus_in_cb(void *data, const Efl_Event *event)
194
{
195
   Efl_Input_Focus *ev = event->info;
196

197
   _edje_focus_in(data, efl_input_device_get(ev));
198
}
199

200
static void
201
_edje_focus_out(Edje *ed, Efl_Input_Device *seat)
202
{
203
#ifdef HAVE_ECORE_IMF
204
   Edje_Real_Part *rp;
205
   Entry *en;
206
#endif
207

208
   _edje_seat_emit(ed, seat, "focus,out", "");
209

210
#ifdef HAVE_ECORE_IMF
211
   rp = _edje_focused_part_get(ed, _edje_seat_name_get(ed, seat));
212
   if (!rp) return;
213
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
214
       (!rp->typedata.text)) return;
215
   en = rp->typedata.text->entry_data;
216
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
217
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
218
     return;
219

220
   if (!en->imf_context) return;
221

222
   ecore_imf_context_reset(en->imf_context);
223
   ecore_imf_context_focus_out(en->imf_context);
224
#endif
225
}
226

227
static void
228
_edje_focus_out_cb(void *data, const Efl_Event *event)
229
{
230
   Efl_Input_Focus *ev = event->info;
231

232
   _edje_focus_out(data, efl_input_device_get(ev));
233
}
234

235
static Edje_Entry_Change_Info *
236
_text_filter_markup_prepend_internal(Edje *ed, Entry *en, Evas_Textblock_Cursor *c,
237
                                     char *text,
238
                                     const char *fmtpre, const char *fmtpost,
239
                                     Eina_Bool clearsel, Eina_Bool changeinfo)
240
{
241
   Edje_Markup_Filter_Callback *cb;
242
   Eina_List *l;
243
   Eina_Bool have_sel = EINA_FALSE;
244

245
   if ((clearsel) && (en->have_selection))
246
     {
247
        _range_del_emit(ed, en->cursor, en->rp->object, en);
248
        have_sel = EINA_TRUE;
249
     }
250

251
   EINA_LIST_FOREACH(ed->markup_filter_callbacks, l, cb)
252
     {
253
        if (!strcmp(cb->part, en->rp->part->name))
254
          {
255
             cb->func(cb->data, ed->obj, cb->part, &text);
256
             if (!text) break;
257
          }
258
     }
259
#ifdef HAVE_ECORE_IMF
260
   // For skipping useless commit
261
   if (en->have_preedit && (!text || !strcmp(text, "")))
262
     en->commit_cancel = EINA_TRUE;
263
   else
264
     en->commit_cancel = EINA_FALSE;
265
#endif
266
   if (text)
267
     {
268
        Edje_Entry_Change_Info *info = NULL;
269

270
        if (changeinfo)
271
          {
272
             info = calloc(1, sizeof(*info));
273
             if (!info)
274
               {
275
                  ERR("Running very low on memory");
276
               }
277
             else
278
               {
279
                  info->insert = EINA_TRUE;
280
                  info->change.insert.content = eina_stringshare_add(text);
281
                  info->change.insert.plain_length =
282
                    eina_unicode_utf8_get_len(info->change.insert.content);
283
               }
284
          }
285
        if (info)
286
          {
287
             if (have_sel)
288
               {
289
                  info->merge = EINA_TRUE;
290
               }
291
             info->change.insert.pos =
292
                evas_textblock_cursor_pos_get(en->cursor);
293
          }
294
        if (fmtpre) _text_filter_format_prepend(ed, en, en->cursor, fmtpre);
295
        evas_object_textblock_text_markup_prepend(c, text);
296
        free(text);
297
        if (fmtpost) _text_filter_format_prepend(ed, en, en->cursor, fmtpost);
298
        return info;
299
     }
300
   return NULL;
301
}
302

303
static Edje_Entry_Change_Info *
304
_text_filter_text_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c,
305
                          const char *text,
306
                          const char *fmtpre, const char *fmtpost,
307
                          Eina_Bool clearsel, Eina_Bool changeinfo)
308
{
309
   char *text2 = NULL;
310
   Edje_Text_Insert_Filter_Callback *cb;
311
   Eina_List *l;
312

313
   EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
314

315
   if ((clearsel) && (en->have_selection))
316
     {
317
        _range_del_emit(ed, en->cursor, en->rp->object, en);
318
     }
319

320
   text2 = strdup(text);
321
   EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
322
     {
323
        if (!strcmp(cb->part, en->rp->part->name))
324
          {
325
             cb->func(cb->data, ed->obj, cb->part, EDJE_TEXT_FILTER_TEXT, &text2);
326
             if (!text2) break;
327
          }
328
     }
329
   if (text2)
330
     {
331
        char *markup_text;
332
        Edje_Entry_Change_Info *info = NULL;
333

334
        markup_text = evas_textblock_text_utf8_to_markup(NULL, text2);
335
        free(text2);
336
        if (markup_text)
337
          info = _text_filter_markup_prepend_internal(ed, en, c, markup_text,
338
                                                      fmtpre, fmtpost,
339
                                                      clearsel, changeinfo);
340
        return info;
341
     }
342
   return NULL;
343
}
344

345
static void
346
_text_filter_format_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c, const char *text)
347
{
348
   char *text2;
349
   Edje_Text_Insert_Filter_Callback *cb;
350
   Eina_List *l;
351

352
   EINA_SAFETY_ON_NULL_RETURN(text);
353
   text2 = strdup(text);
354
   EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
355
     {
356
        if (!strcmp(cb->part, en->rp->part->name))
357
          {
358
             cb->func(cb->data, ed->obj, cb->part, EDJE_TEXT_FILTER_FORMAT, &text2);
359
             if (!text2) break;
360
          }
361
     }
362
   if (text2)
363
     {
364
        char *s, *markup_text;
365
        size_t size;
366

367
        s = text2;
368
        if (*s == '+')
369
          {
370
             s++;
371
             while (*s == ' ')
372
               s++;
373
             if (!*s)
374
               {
375
                  free(text2);
376
                  return;
377
               }
378
             size = strlen(s);
379
             markup_text = (char *)malloc(size + 3);
380
             if (markup_text)
381
               {
382
                  *(markup_text) = '<';
383
                  memcpy((markup_text + 1), s, size);
384
                  *(markup_text + size + 1) = '>';
385
                  *(markup_text + size + 2) = '\0';
386
               }
387
          }
388
        else if (s[0] == '-')
389
          {
390
             s++;
391
             while (*s == ' ')
392
               s++;
393
             if (!*s)
394
               {
395
                  free(text2);
396
                  return;
397
               }
398
             size = strlen(s);
399
             markup_text = (char *)malloc(size + 4);
400
             if (markup_text)
401
               {
402
                  *(markup_text) = '<';
403
                  *(markup_text + 1) = '/';
404
                  memcpy((markup_text + 2), s, size);
405
                  *(markup_text + size + 2) = '>';
406
                  *(markup_text + size + 3) = '\0';
407
               }
408
          }
409
        else
410
          {
411
             size = strlen(s);
412
             markup_text = (char *)malloc(size + 4);
413
             if (markup_text)
414
               {
415
                  *(markup_text) = '<';
416
                  memcpy((markup_text + 1), s, size);
417
                  *(markup_text + size + 1) = '/';
418
                  *(markup_text + size + 2) = '>';
419
                  *(markup_text + size + 3) = '\0';
420
               }
421
          }
422
        free(text2);
423
        if (markup_text)
424
          _text_filter_markup_prepend_internal(ed, en, c, markup_text,
425
                                               NULL, NULL,
426
                                               EINA_FALSE, EINA_FALSE);
427
     }
428
}
429

430
static Edje_Entry_Change_Info *
431
_text_filter_markup_prepend(Edje *ed, Entry *en, Evas_Textblock_Cursor *c,
432
                            const char *text,
433
                            const char *fmtpre, const char *fmtpost,
434
                            Eina_Bool clearsel, Eina_Bool changeinfo)
435
{
436
   char *text2;
437
   Edje_Text_Insert_Filter_Callback *cb;
438
   Eina_List *l;
439

440
   EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
441

442
   if ((clearsel) && (en->have_selection))
443
     {
444
        _range_del_emit(ed, en->cursor, en->rp->object, en);
445
     }
446

447
   text2 = strdup(text);
448
   EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
449
     {
450
        if (!strcmp(cb->part, en->rp->part->name))
451
          {
452
             cb->func(cb->data, ed->obj, cb->part, EDJE_TEXT_FILTER_MARKUP, &text2);
453
             if (!text2) break;
454
          }
455
     }
456
   if (text2)
457
     {
458
        Edje_Entry_Change_Info *info;
459

460
        info = _text_filter_markup_prepend_internal(ed, en, c, text2,
461
                                                    fmtpre, fmtpost,
462
                                                    clearsel, changeinfo);
463
        return info;
464
     }
465
   return NULL;
466
}
467

468
static void
469
_curs_update_from_curs(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED, Entry *en, Evas_Coord *cx, Evas_Coord *cy)
470
{
471
   Evas_Coord cw, ch;
472
   Evas_Textblock_Cursor_Type cur_type;
473
   if (c != en->cursor) return;
474
   switch (en->rp->part->cursor_mode)
475
     {
476
      case EDJE_ENTRY_CURSOR_MODE_BEFORE:
477
        cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
478
        break;
479

480
      case EDJE_ENTRY_CURSOR_MODE_UNDER:
481
      /* no break for a reason */
482
      default:
483
        cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
484
     }
485
   evas_textblock_cursor_geometry_get(c, cx, cy, &cw, &ch, NULL, cur_type);
486
   *cx += (cw / 2);
487
   *cy += (ch / 2);
488
}
489

490
static int
491
_curs_line_last_get(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en EINA_UNUSED)
492
{
493
   Evas_Textblock_Cursor *cc;
494
   int ln;
495

496
   cc = evas_object_textblock_cursor_new(o);
497
   evas_textblock_cursor_paragraph_last(cc);
498
   ln = evas_textblock_cursor_line_geometry_get(cc, NULL, NULL, NULL, NULL);
499
   evas_textblock_cursor_free(cc);
500
   return ln;
501
}
502

503
static void
504
_curs_lin_start(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED,
505
                Entry *en EINA_UNUSED)
506
{
507
   evas_textblock_cursor_line_char_first(c);
508
}
509

510
static void
511
_curs_lin_end(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED,
512
              Entry *en EINA_UNUSED)
513
{
514
   evas_textblock_cursor_line_char_last(c);
515
}
516

517
static void
518
_curs_start(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED,
519
            Entry *en EINA_UNUSED)
520
{
521
   evas_textblock_cursor_paragraph_first(c);
522
}
523

524
static void
525
_curs_end(Evas_Textblock_Cursor *c, Evas_Object *o EINA_UNUSED, Entry *en EINA_UNUSED)
526
{
527
   evas_textblock_cursor_paragraph_last(c);
528
}
529

530
static Eina_Bool
531
_curs_jump_line(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int ln)
532
{
533
   Evas_Coord cx, cy;
534
   Evas_Coord lx, ly, lw, lh;
535
   int last = _curs_line_last_get(c, o, en);
536

537
   if (ln < 0) return EINA_FALSE;
538
   if (ln > last) return EINA_FALSE;
539

540
   _curs_update_from_curs(c, o, en, &cx, &cy);
541

542
   if (!evas_object_textblock_line_number_geometry_get(o, ln, &lx, &ly, &lw, &lh))
543
     return EINA_FALSE;
544
   if (evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
545
     return EINA_TRUE;
546
   evas_textblock_cursor_line_set(c, ln);
547
   if (cx < (lx + (lw / 2)))
548
     {
549
        if (ln == last) _curs_end(c, o, en);
550
        _curs_lin_start(c, o, en);
551
     }
552
   else
553
     {
554
        if (ln == last)
555
          _curs_end(c, o, en);
556
        else
557
          _curs_lin_end(c, o, en);
558
     }
559
   return EINA_TRUE;
560
}
561

562
static Eina_Bool
563
_curs_jump_line_by(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int by)
564
{
565
   int ln;
566

567
   ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL) + by;
568
   return _curs_jump_line(c, o, en, ln);
569
}
570

571
static Eina_Bool
572
_curs_up(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
573
{
574
   return _curs_jump_line_by(c, o, en, -1);
575
}
576

577
static Eina_Bool
578
_curs_down(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
579
{
580
   return _curs_jump_line_by(c, o, en, 1);
581
}
582

583
static void
584
_sel_start(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
585
{
586
   if (en->sel_start) return;
587
   en->sel_start = evas_object_textblock_cursor_new(o);
588
   evas_textblock_cursor_copy(c, en->sel_start);
589
   en->sel_end = evas_object_textblock_cursor_new(o);
590
   evas_textblock_cursor_copy(c, en->sel_end);
591

592
   en->have_selection = EINA_FALSE;
593
   if (en->selection)
594
     {
595
        free(en->selection);
596
        en->selection = NULL;
597
     }
598
}
599

600
static void
601
_sel_enable(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED,
602
            Evas_Object *o EINA_UNUSED, Entry *en)
603
{
604
   if (en->have_selection) return;
605
   en->have_selection = EINA_TRUE;
606
   if (en->selection)
607
     {
608
        free(en->selection);
609
        en->selection = NULL;
610
     }
611

612
   _edje_entry_imf_context_reset(en->rp);
613
   _edje_emit(ed, "selection,start", en->rp->part->name);
614
}
615

616
static void
617
_emit_sel_state(Edje *ed, Entry *en)
618
{
619
   if (!evas_textblock_cursor_compare(en->sel_start, en->sel_end))
620
     {
621
        _edje_emit(ed, "selection,reset", en->rp->part->name);
622
     }
623
   else
624
     {
625
        _edje_emit(ed, "selection,changed", en->rp->part->name);
626
     }
627
}
628

629
static void
630
_sel_extend(Edje *ed, Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
631
{
632
   if (!en->sel_end) return;
633
   _sel_enable(ed, c, o, en);
634
   if (!evas_textblock_cursor_compare(c, en->sel_end)) return;
635

636
   evas_textblock_cursor_copy(c, en->sel_end);
637

638
   _edje_entry_imf_cursor_info_set(en);
639

640
   if (en->selection)
641
     {
642
        free(en->selection);
643
        en->selection = NULL;
644
     }
645
   _emit_sel_state(ed, en);
646
}
647

648
static void
649
_sel_preextend(Edje *ed, Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
650
{
651
   if (!en->sel_end) return;
652
   _sel_enable(ed, c, o, en);
653
   if (!evas_textblock_cursor_compare(c, en->sel_start)) return;
654

655
   evas_textblock_cursor_copy(c, en->sel_start);
656

657
   _edje_entry_imf_cursor_info_set(en);
658

659
   if (en->selection)
660
     {
661
        free(en->selection);
662
        en->selection = NULL;
663
     }
664
   _emit_sel_state(ed, en);
665
}
666

667
static void
668
_sel_clear(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
669
{
670
   en->had_sel = EINA_FALSE;
671
   if (en->sel_start)
672
     {
673
        evas_textblock_cursor_free(en->sel_start);
674
        evas_textblock_cursor_free(en->sel_end);
675
        en->sel_start = NULL;
676
        en->sel_end = NULL;
677
     }
678
   if (en->selection)
679
     {
680
        free(en->selection);
681
        en->selection = NULL;
682
     }
683
   while (en->sel)
684
     {
685
        Sel *sel;
686

687
        sel = en->sel->data;
688
        if (sel->obj_bg) evas_object_del(sel->obj_bg);
689
        if (sel->obj_fg) evas_object_del(sel->obj_fg);
690
        free(sel);
691
        en->sel = eina_list_remove_list(en->sel, en->sel);
692
     }
693
   if (en->have_selection)
694
     {
695
        en->have_selection = EINA_FALSE;
696
        _edje_emit(ed, "selection,cleared", en->rp->part->name);
697
     }
698
}
699

700
static void
701
_sel_update(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en)
702
{
703
   Evas_Coord x, y;
704
   Evas_Object *smart, *clip;
705

706
   smart = evas_object_smart_parent_get(o);
707
   clip = evas_object_clip_get(o);
708
   if (!en->sel_start)
709
     return;
710

711
   evas_object_geometry_get(o, &x, &y, NULL, NULL);
712
   if (en->have_selection)
713
     {
714
        Eina_Iterator *range = NULL;
715
        Eina_List *l;
716
        Sel *sel = NULL;
717
        Evas_Textblock_Rectangle *r;
718

719
        range = evas_textblock_cursor_range_simple_geometry_get(en->sel_start,
720
                                                                en->sel_end);
721

722
        l = en->sel;
723
        EINA_ITERATOR_FOREACH(range, r)
724
          {
725
             if (!l)
726
               {
727
                  Evas_Object *ob;
728

729
                  sel = calloc(1, sizeof(Sel));
730
                  if (!sel)
731
                    {
732
                       ERR("Running very low on memory");
733
                       break;
734
                    }
735
                  en->sel = eina_list_append(en->sel, sel);
736
                  if (en->rp->part->source)
737
                    {
738
                       ob = edje_object_add(ed->base.evas);
739
                       edje_object_file_set(ob, ed->path, en->rp->part->source);
740
                       evas_object_smart_member_add(ob, smart);
741
                       evas_object_stack_below(ob, o);
742
                       evas_object_clip_set(ob, clip);
743
                       evas_object_pass_events_set(ob, EINA_TRUE);
744
                       evas_object_show(ob);
745
                       sel->obj_bg = ob;
746
                       _edje_subobj_register(ed, sel->obj_bg);
747
                    }
748

749
                  if (en->rp->part->source2)
750
                    {
751
                       ob = edje_object_add(ed->base.evas);
752
                       edje_object_file_set(ob, ed->path, en->rp->part->source2);
753
                       evas_object_smart_member_add(ob, smart);
754
                       evas_object_stack_above(ob, o);
755
                       evas_object_clip_set(ob, clip);
756
                       evas_object_pass_events_set(ob, EINA_TRUE);
757
                       evas_object_show(ob);
758
                       sel->obj_fg = ob;
759
                       _edje_subobj_register(ed, sel->obj_fg);
760
                    }
761
               }
762
             else
763
               {
764
                  sel = eina_list_data_get(l);
765
                  l = l->next;
766
               }
767
             *(&(sel->rect)) = *r;
768

769
             if (sel->obj_bg)
770
               {
771
                  evas_object_move(sel->obj_bg, x + r->x, y + r->y);
772
                  evas_object_resize(sel->obj_bg, r->w, r->h);
773
               }
774
             if (sel->obj_fg)
775
               {
776
                  evas_object_move(sel->obj_fg, x + r->x, y + r->y);
777
                  evas_object_resize(sel->obj_fg, r->w, r->h);
778
               }
779
          }
780
        eina_iterator_free(range);
781

782
        /* delete redundant selection rects */
783
        while (l)
784
          {
785
             Eina_List *temp = l->next;
786
             sel = eina_list_data_get(l);
787
             if (sel)
788
               {
789
                  if (sel->obj_bg) evas_object_del(sel->obj_bg);
790
                  if (sel->obj_fg) evas_object_del(sel->obj_fg);
791
                  free(sel);
792
               }
793
             en->sel = eina_list_remove_list(en->sel, l);
794
             l = temp;
795
          }
796
     }
797
}
798

799
static Eina_Bool
800
_edje_entry_style_tag_check(Edje_Real_Part *rp, const char *tag)
801
{
802
    if (!tag) return EINA_FALSE;
803
    const Evas_Textblock_Style *ts = NULL;
804

805
    ts = evas_object_textblock_style_user_peek(rp->object);
806
    if (!ts) ts = evas_object_textblock_style_get(rp->object);
807
    if (ts)
808
      {
809
         const char *style_str = evas_textblock_style_get(ts);
810
         if (!style_str) return EINA_FALSE;
811
         if (strstr(style_str, tag)) return EINA_TRUE;
812
      }
813

814
   return EINA_FALSE;
815
}
816

817
static void
818
_edje_anchor_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
819
{
820
   Anchor *an = data;
821
   Evas_Event_Mouse_Down *ev = event_info;
822
   Edje_Real_Part *rp = an->en->rp;
823
   char *buf, *n;
824
   size_t len;
825
   int ignored;
826
   Entry *en;
827
   Edje *ed = an->en->ed;
828

829
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
830
       (!rp->typedata.text)) return;
831
   en = rp->typedata.text->entry_data;
832
   if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
833
       (en->select_allow))
834
     return;
835

836
   ignored = rp->ignore_flags & ev->event_flags;
837
   if ((!ev->event_flags) || (!ignored))
838
     {
839
        n = an->name;
840
        if (!n) n = "";
841
        len = 200 + strlen(n);
842
        buf = alloca(len);
843
        if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
844
          snprintf(buf, len, "anchor,mouse,down,%i,%s,triple", ev->button, n);
845
        else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
846
          snprintf(buf, len, "anchor,mouse,down,%i,%s,double", ev->button, n);
847
        else
848
          snprintf(buf, len, "anchor,mouse,down,%i,%s", ev->button, n);
849
        _edje_emit(ed, buf, rp->part->name);
850

851
        /* Link Pressed effect */
852
        if (_edje_entry_style_tag_check(rp, "link_pressed="))
853
          {
854
             an->en->have_link_pressed = EINA_TRUE;
855
             evas_textblock_cursor_format_append(an->start, "<link_pressed>");
856
             evas_textblock_cursor_format_prepend(an->end, "</link_pressed>");
857
          }
858
     }
859
   ev->event_flags |= rp->mask_flags;
860
}
861

862
static void
863
_edje_anchor_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
864
{
865
   Anchor *an = data;
866
   Evas_Event_Mouse_Up *ev = event_info;
867
   Edje_Real_Part *rp = an->en->rp;
868
   char *buf, *n;
869
   size_t len;
870
   int ignored;
871
   Entry *en;
872
   Edje *ed = an->en->ed;
873

874
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
875
       (!rp->typedata.text)) return;
876

877
   en = rp->typedata.text->entry_data;
878
   ignored = rp->ignore_flags & ev->event_flags;
879
   n = an->name;
880
   if (!n) n = "";
881
   len = 200 + strlen(n);
882
   buf = alloca(len);
883
   if ((rp->part->select_mode != EDJE_ENTRY_SELECTION_MODE_EXPLICIT) ||
884
       (!en->select_allow))
885
     {
886
        if ((!ev->event_flags) || (!ignored))
887
          {
888
             snprintf(buf, len, "anchor,mouse,up,%i,%s", ev->button, n);
889
             _edje_emit(ed, buf, rp->part->name);
890
             /* Link Pressed effect */
891
             if (an->en->have_link_pressed)
892
               {
893
                  const Evas_Object_Textblock_Node_Format *node;
894
                  node = evas_textblock_node_format_first_get(rp->object);
895
                  for (; node; node = evas_textblock_node_format_next_get(node))
896
                    {
897
                        const char *text = evas_textblock_node_format_text_get(node);
898

899
                        if (text)
900
                          {
901
                             if (!strcmp(text, "+ link_pressed"))
902
                               {
903
                                  evas_textblock_node_format_remove_pair(rp->object,
904
                                           (Evas_Object_Textblock_Node_Format *)node);
905
                                  break;
906
                               }
907
                          }
908
                    }
909
               }
910
          }
911
     }
912

913
   if ((rp->still_in) && (rp->clicked_button == ev->button) && (!ignored))
914
     {
915
        snprintf(buf, len, "anchor,mouse,clicked,%i,%s", ev->button, n);
916
        _edje_emit(ed, buf, rp->part->name);
917
     }
918
   ev->event_flags |= rp->mask_flags;
919
}
920

921
static void
922
_edje_anchor_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
923
{
924
   Anchor *an = data;
925
   Evas_Event_Mouse_Move *ev = event_info;
926
   Edje_Real_Part *rp = an->en->rp;
927
   char *buf, *n;
928
   size_t len;
929
   int ignored;
930
   Entry *en;
931
   Edje *ed = an->en->ed;
932

933
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
934
       (!rp->typedata.text)) return;
935
   en = rp->typedata.text->entry_data;
936
   if ((rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT) &&
937
       (en->select_allow))
938
     return;
939

940
   ignored = rp->ignore_flags & ev->event_flags;
941
   if ((!ev->event_flags) || (!ignored))
942
     {
943
        n = an->name;
944
        if (!n) n = "";
945
        len = 200 + strlen(n);
946
        buf = alloca(len);
947
        snprintf(buf, len, "anchor,mouse,move,%s", n);
948
        _edje_emit(ed, buf, rp->part->name);
949
     }
950
   ev->event_flags |= rp->mask_flags;
951
}
952

953
static void
954
_edje_anchor_mouse_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
955
{
956
   Anchor *an = data;
957
   Evas_Event_Mouse_In *ev = event_info;
958
   Edje_Real_Part *rp = an->en->rp;
959
   Edje *ed = an->en->ed;
960
   char *buf, *n;
961
   size_t len;
962
   int ignored;
963

964
   ignored = rp->ignore_flags & ev->event_flags;
965
   if ((!ev->event_flags) || (!ignored))
966
     {
967
        /* set to allow handling in elementary, in case we have
968
         * an unwanted event propagation */
969
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
970

971
        n = an->name;
972
        if (!n) n = "";
973
        len = 200 + strlen(n);
974
        buf = alloca(len);
975
        snprintf(buf, len, "anchor,mouse,in,%s", n);
976
        _edje_emit(ed, buf, rp->part->name);
977
     }
978
   ev->event_flags |= rp->mask_flags;
979
}
980

981
static void
982
_edje_anchor_mouse_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
983
{
984
   Anchor *an = data;
985
   Evas_Event_Mouse_Out *ev = event_info;
986
   Edje_Real_Part *rp = an->en->rp;
987
   char *buf, *n;
988
   size_t len;
989
   int ignored;
990
   Edje *ed = an->en->ed;
991

992
   ignored = rp->ignore_flags & ev->event_flags;
993
   if ((!ev->event_flags) || (!ignored))
994
     {
995
        /* set to allow handling in elementary, in case we have
996
         * an unwanted event propagation */
997
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
998

999
        n = an->name;
1000
        if (!n) n = "";
1001
        len = 200 + strlen(n);
1002
        buf = alloca(len);
1003
        snprintf(buf, len, "anchor,mouse,out,%s", n);
1004
        _edje_emit(ed, buf, rp->part->name);
1005
     }
1006
   ev->event_flags |= rp->mask_flags;
1007
}
1008

1009
static void
1010
_item_obj_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1011
{
1012
   Item_Obj *io = data;
1013
   Anchor *an = io->an;
1014
   Entry *en;
1015

1016
   if (!an)
1017
     {
1018
        ERR("Failed to free item object struct. Anchor is NULL!");
1019
        return;
1020
     }
1021

1022
   en = an->en;
1023
   en->item_objs = (Item_Obj *)eina_inlist_remove(EINA_INLIST_GET(en->item_objs),
1024
                                                  EINA_INLIST_GET(io));
1025
   io->an = NULL;
1026
   free(io->name);
1027
   free(io);
1028
}
1029

1030
static Evas_Object *
1031
_item_obj_get(Anchor *an, Evas_Object *o, Evas_Object *smart, Evas_Object *clip)
1032
{
1033
   Evas_Object *obj;
1034
   Item_Obj *io;
1035
   Entry *en = an->en;
1036
   Edje *ed = en->ed;
1037

1038
   EINA_INLIST_FOREACH(en->item_objs, io)
1039
     {
1040
        if (!io->an && io->name && !strcmp(an->name ? an->name : "", io->name))
1041
          {
1042
             io->an = an;
1043
             return io->obj;
1044
          }
1045
     }
1046

1047
   io = calloc(1, sizeof(Item_Obj));
1048
   if (!io)
1049
     {
1050
        ERR("Running very low on memory");
1051
        return NULL;
1052
     }
1053

1054
   obj = ed->item_provider.func
1055
      (ed->item_provider.data, smart,
1056
       en->rp->part->name, an->name);
1057
   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _item_obj_del_cb, io);
1058
   evas_object_smart_member_add(obj, smart);
1059
   evas_object_stack_above(obj, o);
1060
   evas_object_clip_set(obj, clip);
1061
   evas_object_pass_events_set(obj, EINA_TRUE);
1062

1063
   io->an = an;
1064
   io->name = strdup(an->name ? an->name : "");
1065
   io->obj = obj;
1066
   en->item_objs = (Item_Obj *)eina_inlist_append(EINA_INLIST_GET(en->item_objs),
1067
                                                  EINA_INLIST_GET(io));
1068

1069
   return io->obj;
1070
}
1071

1072
static void
1073
_unused_item_objs_free(Entry *en)
1074
{
1075
   Item_Obj *io;
1076
   Eina_Inlist *l;
1077

1078
   EINA_INLIST_FOREACH_SAFE(en->item_objs, l, io)
1079
     {
1080
        if (!io->an)
1081
          {
1082
             if (io->obj)
1083
               {
1084
                  evas_object_event_callback_del_full(io->obj, EVAS_CALLBACK_DEL, _item_obj_del_cb, io);
1085
                  evas_object_del(io->obj);
1086
               }
1087

1088
             en->item_objs = (Item_Obj *)eina_inlist_remove(EINA_INLIST_GET(en->item_objs),
1089
                                                            EINA_INLIST_GET(io));
1090
             free(io->name);
1091
             free(io);
1092
          }
1093
     }
1094
}
1095

1096
static Eina_Bool
1097
_is_anchors_outside_viewport(Evas_Coord oxy, Evas_Coord axy, Evas_Coord awh,
1098
                                                 Evas_Coord vxy, Evas_Coord vwh)
1099
{
1100
   if (((oxy + axy + awh) < vxy) || ((oxy + axy) > vwh))
1101
     {
1102
        return EINA_TRUE;
1103
     }
1104

1105
   return EINA_FALSE;
1106
}
1107

1108
static void
1109
_anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en)
1110
{
1111
   Eina_List *l, *ll, *range = NULL;
1112
   Evas_Coord x, y, w, h;
1113
   Evas_Coord vx, vy, vw, vh;
1114
   Evas_Coord tvh, tvw;
1115
   Evas_Object *smart, *clip;
1116
   Sel *sel = NULL;
1117
   Anchor *an;
1118
   Edje *ed = en->ed;
1119

1120
   /* Better not to update anchors outside the view port. */
1121
   if (en->anchors_updated) return;
1122

1123
   smart = evas_object_smart_parent_get(o);
1124
   clip = evas_object_clip_get(o);
1125
   x = y = w = h = -1;
1126
   evas_object_geometry_get(o, &x, &y, &w, &h);
1127
   evas_output_viewport_get(en->ed->base.evas, &vx, &vy, &vw, &vh);
1128
   tvw = vx + vw;
1129
   tvh = vy + vh;
1130

1131
   EINA_LIST_FOREACH(en->anchors, l, an)
1132
     {
1133
        // for item anchors
1134
        if (an->item)
1135
          {
1136
             Evas_Coord cx, cy, cw, ch;
1137

1138
             if (!evas_textblock_cursor_format_item_geometry_get
1139
                                                (an->start, &cx, &cy, &cw, &ch))
1140
               {
1141
                  continue;
1142
               }
1143

1144
             if (_is_anchors_outside_viewport(y, cy, ch, vy, tvh) ||
1145
                           _is_anchors_outside_viewport(x, cx, cw, vx, tvw))
1146
               {
1147
                  if (an->sel)
1148
                    {
1149
                       sel = an->sel->data;
1150
                       evas_object_hide(sel->obj);
1151
                    }
1152
                  continue;
1153
               }
1154

1155
             if (!an->sel)
1156
               {
1157
                  Evas_Object *ob;
1158

1159
                  sel = calloc(1, sizeof(Sel));
1160
                  if (!sel)
1161
                    {
1162
                       ERR("Running very low on memory");
1163
                       break;
1164
                    }
1165
                  an->sel = eina_list_append(an->sel, sel);
1166
                  if (!an->sel)
1167
                    {
1168
                       ERR("Running very low on memory");
1169
                       break;
1170
                    }
1171
                  if (ed->item_provider.func)
1172
                    {
1173
                       ob = _item_obj_get(an, o, smart, clip);
1174
                       sel->obj = ob;
1175
                    }
1176
               }
1177
             /* We have only one sel per item */
1178
             sel = an->sel->data;
1179
             evas_object_move(sel->obj, x + cx, y + cy);
1180
             evas_object_resize(sel->obj, cw, ch);
1181
             evas_object_show(sel->obj);
1182
          }
1183
        // for link anchors
1184
        else
1185
          {
1186
             range =
1187
               evas_textblock_cursor_range_geometry_get(an->start, an->end);
1188
             if (eina_list_count(range) != eina_list_count(an->sel))
1189
               {
1190
                  while (an->sel)
1191
                    {
1192
                       sel = an->sel->data;
1193
                       if (sel->obj_bg) evas_object_del(sel->obj_bg);
1194
                       if (sel->obj_fg) evas_object_del(sel->obj_fg);
1195
                       if (sel->obj) evas_object_del(sel->obj);
1196
                       free(sel);
1197
                       an->sel = eina_list_remove_list(an->sel, an->sel);
1198
                    }
1199
                  if (range)
1200
                    {
1201
                       Evas_Textblock_Rectangle *r, *r_last;
1202

1203
                       r = range->data;
1204
                       r_last = eina_list_last_data_get(range);
1205
                       if (r->y != r_last->y)
1206
                         {
1207
                            /* For multiple range */
1208
                            r->h = r->y + r_last->y + r_last->h;
1209
                         }
1210
                       /* For vertically layout entry */
1211
                       if (_is_anchors_outside_viewport(y, r->y, r->h, vy, tvh))
1212
                         {
1213
                            EINA_LIST_FREE(range, r)
1214
                              free(r);
1215
                            continue;
1216
                         }
1217
                       else
1218
                         {
1219
                            /* XXX: Should consider for horizontal entry but has
1220
                             * very minimal usage. Probably we should get the min x
1221
                             * and max w for range and then decide whether it is in
1222
                             * the viewport or not. Unnecessary calculation for this
1223
                             * minimal usage. Please test with large number of anchors
1224
                             * after implementing it, if its needed to be.
1225
                             */
1226
                         }
1227
                       for (ll = range; ll; ll = eina_list_next(ll))
1228
                         {
1229
                            Evas_Object *ob;
1230

1231
                            sel = calloc(1, sizeof(Sel));
1232
                            if (!sel)
1233
                              {
1234
                                 ERR("Running very low on memory");
1235
                                 break;
1236
                              }
1237
                            an->sel = eina_list_append(an->sel, sel);
1238
                            if (en->rp->part->source5)
1239
                              {
1240
                                 ob = edje_object_add(ed->base.evas);
1241
                                 edje_object_file_set(ob, ed->path, en->rp->part->source5);
1242
                                 evas_object_smart_member_add(ob, smart);
1243
                                 evas_object_stack_below(ob, o);
1244
                                 evas_object_clip_set(ob, clip);
1245
                                 evas_object_pass_events_set(ob, EINA_TRUE);
1246
                                 sel->obj_bg = ob;
1247
                                 _edje_subobj_register(ed, sel->obj_bg);
1248
                              }
1249

1250
                            if (en->rp->part->source6)
1251
                              {
1252
                                 ob = edje_object_add(ed->base.evas);
1253
                                 edje_object_file_set(ob, ed->path, en->rp->part->source6);
1254
                                 evas_object_smart_member_add(ob, smart);
1255
                                 evas_object_stack_above(ob, o);
1256
                                 evas_object_clip_set(ob, clip);
1257
                                 evas_object_pass_events_set(ob, EINA_TRUE);
1258
                                 sel->obj_fg = ob;
1259
                                 _edje_subobj_register(ed, sel->obj_fg);
1260
                              }
1261

1262
                            ob = evas_object_rectangle_add(ed->base.evas);
1263
                            evas_object_color_set(ob, 0, 0, 0, 0);
1264
                            evas_object_smart_member_add(ob, smart);
1265
                            evas_object_stack_above(ob, o);
1266
                            evas_object_clip_set(ob, clip);
1267
                            evas_object_repeat_events_set(ob, EINA_TRUE);
1268
                            evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_DOWN, _edje_anchor_mouse_down_cb, an);
1269
                            evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_UP, _edje_anchor_mouse_up_cb, an);
1270
                            evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_MOVE, _edje_anchor_mouse_move_cb, an);
1271
                            evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_IN, _edje_anchor_mouse_in_cb, an);
1272
                            evas_object_event_callback_add(ob, EVAS_CALLBACK_MOUSE_OUT, _edje_anchor_mouse_out_cb, an);
1273
                            sel->obj = ob;
1274
                         }
1275
                    }
1276
               }
1277

1278
             EINA_LIST_FOREACH(an->sel, ll, sel)
1279
               {
1280
                  Evas_Textblock_Rectangle *r;
1281

1282
                  if (!range) break;
1283

1284
                  r = range->data;
1285
                  *(&(sel->rect)) = *r;
1286
                  if (_is_anchors_outside_viewport(y, r->y, r->h, vy, tvh) ||
1287
                      _is_anchors_outside_viewport(x, r->x, r->w, vx, tvw))
1288
                    {
1289
                       range = eina_list_remove_list(range, range);
1290
                       free(r);
1291
                       evas_object_hide(sel->obj_bg);
1292
                       evas_object_hide(sel->obj_fg);
1293
                       evas_object_hide(sel->obj);
1294
                       continue;
1295
                    }
1296

1297
                  if (sel->obj_bg)
1298
                    {
1299
                       evas_object_move(sel->obj_bg, x + r->x, y + r->y);
1300
                       evas_object_resize(sel->obj_bg, r->w, r->h);
1301
                       evas_object_show(sel->obj_bg);
1302
                    }
1303
                  if (sel->obj_fg)
1304
                    {
1305
                       evas_object_move(sel->obj_fg, x + r->x, y + r->y);
1306
                       evas_object_resize(sel->obj_fg, r->w, r->h);
1307
                       evas_object_show(sel->obj_fg);
1308
                    }
1309
                  if (sel->obj)
1310
                    {
1311
                       evas_object_move(sel->obj, x + r->x, y + r->y);
1312
                       evas_object_resize(sel->obj, r->w, r->h);
1313
                       evas_object_show(sel->obj);
1314
                    }
1315
                  range = eina_list_remove_list(range, range);
1316
                  free(r);
1317
               }
1318
          }
1319
     }
1320

1321
   _unused_item_objs_free(en);
1322
}
1323

1324
static void
1325
_anchors_update_check(Edje *ed, Edje_Real_Part *rp)
1326
{
1327
   Evas_Coord x, y, w, h;
1328
   Evas_Coord vx, vy, vw, vh;
1329
   Eina_Bool anchors_updated = EINA_FALSE;
1330
   Entry *en;
1331

1332
   en = rp->typedata.text->entry_data;
1333
   x = y = w = h = -1;
1334
   vx = vy = vw = vh = -1;
1335
   evas_object_geometry_get(rp->object, &x, &y, &w, &h);
1336
   evas_output_viewport_get(ed->base.evas, &vx, &vy, &vw, &vh);
1337
   if (((y + h) <= vy) || (y >= (vy + vh)))
1338
     anchors_updated = EINA_TRUE;
1339
   else if (((x + w) <= vx) || (x >= (vx + vw)))
1340
     anchors_updated = EINA_TRUE;
1341

1342
   if (en->anchors_updated)
1343
     en->anchors_updated = anchors_updated;
1344
   _anchors_update(en->cursor, rp->object, en);
1345
   en->anchors_updated = anchors_updated;
1346
}
1347

1348
static void
1349
_anchors_need_update(Edje_Real_Part *rp)
1350
{
1351
   Entry *en;
1352
   Eina_Bool anchors_updated;
1353

1354
   en = rp->typedata.text->entry_data;
1355
   anchors_updated = en->anchors_updated;
1356
   en->anchors_updated = EINA_FALSE;
1357
   _anchors_update(en->cursor, rp->object, en);
1358
   en->anchors_updated = anchors_updated;
1359
}
1360

1361
static void
1362
_anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
1363
{
1364
   Item_Obj *io;
1365

1366
   while (en->anchorlist)
1367
     {
1368
        free(en->anchorlist->data);
1369
        en->anchorlist = eina_list_remove_list(en->anchorlist, en->anchorlist);
1370
     }
1371
   while (en->itemlist)
1372
     {
1373
        free(en->itemlist->data);
1374
        en->itemlist = eina_list_remove_list(en->itemlist, en->itemlist);
1375
     }
1376
   while (en->anchors)
1377
     {
1378
        Anchor *an = en->anchors->data;
1379

1380
        while (an->sel)
1381
          {
1382
             Sel *sel = an->sel->data;
1383
             if (sel->obj_bg) evas_object_del(sel->obj_bg);
1384
             if (sel->obj_fg) evas_object_del(sel->obj_fg);
1385
             if (!an->item && sel->obj) evas_object_del(sel->obj);
1386
             free(sel);
1387
             an->sel = eina_list_remove_list(an->sel, an->sel);
1388
          }
1389
        evas_textblock_cursor_free(an->start);
1390
        evas_textblock_cursor_free(an->end);
1391
        free(an->name);
1392
        free(an);
1393
        en->anchors = eina_list_remove_list(en->anchors, en->anchors);
1394
     }
1395

1396
   EINA_INLIST_FOREACH(en->item_objs, io)
1397
      io->an = NULL;
1398
}
1399

1400
/* FIXME: This is horrible. It's just a copy&paste (with some adjustments)
1401
 * from textblock. I didn't want to introduce any non-API links between the
1402
 * libs so I just copied it. Should have been handled differently. */
1403
static char *
1404
_anchor_format_parse(const char *item)
1405
{
1406
   const char *start, *end;
1407
   char *tmp;
1408
   size_t len;
1409

1410
   start = strchr(item, '=');
1411
   if (!start) return NULL;
1412

1413
   start++; /* Advance after the '=' */
1414
   /* If we can find a quote as the first non-space char,
1415
    * our new delimiter is a quote, not a space. */
1416
   while (*start == ' ')
1417
     start++;
1418

1419
   if (*start == '\'')
1420
     {
1421
        start++;
1422
        end = strchr(start, '\'');
1423
        while ((end) && (end > start) && (end[-1] == '\\'))
1424
          end = strchr(end + 1, '\'');
1425
     }
1426
   else
1427
     {
1428
        end = strchr(start, ' ');
1429
        while ((end) && (end > start) && (end[-1] == '\\'))
1430
          end = strchr(end + 1, ' ');
1431
     }
1432

1433
   /* Null terminate before the spaces */
1434
   if (end) len = end - start;
1435
   else len = strlen(start);
1436

1437
   tmp = malloc(len + 1);
1438
   if (!tmp)
1439
     {
1440
        ERR("Running out of memory when allocating %lu byte string", (unsigned long)len + 1);
1441
        return NULL;
1442
     }
1443
   strncpy(tmp, start, len);
1444
   tmp[len] = '\0';
1445

1446
   return tmp;
1447
}
1448

1449
static void
1450
_anchors_get(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en)
1451
{
1452
   const Eina_List *anchors_a, *anchors_item;
1453
   Anchor *an = NULL;
1454
   _anchors_clear(c, o, en);
1455

1456
   anchors_a = evas_textblock_node_format_list_get(o, "a");
1457
   anchors_item = evas_textblock_node_format_list_get(o, "item");
1458

1459
   if (anchors_a)
1460
     {
1461
        const Evas_Object_Textblock_Node_Format *node;
1462
        const Eina_List *itr;
1463
        EINA_LIST_FOREACH(anchors_a, itr, node)
1464
          {
1465
             const char *s = evas_textblock_node_format_text_get(node);
1466
             char *p;
1467
             an = calloc(1, sizeof(Anchor));
1468
             if (!an)
1469
               {
1470
                  ERR("Running very low on memory");
1471
                  break;
1472
               }
1473

1474
             an->en = en;
1475
             p = strstr(s, "href=");
1476
             if (p)
1477
               {
1478
                  an->name = _anchor_format_parse(p);
1479
               }
1480
             en->anchors = eina_list_append(en->anchors, an);
1481
             an->start = evas_object_textblock_cursor_new(o);
1482
             an->end = evas_object_textblock_cursor_new(o);
1483
             evas_textblock_cursor_at_format_set(an->start, node);
1484
             evas_textblock_cursor_copy(an->start, an->end);
1485

1486
             /* Close the anchor, if the anchor was without text,
1487
              * free it as well */
1488
             node = evas_textblock_node_format_next_get(node);
1489
             for (; node; node = evas_textblock_node_format_next_get(node))
1490
               {
1491
                  s = evas_textblock_node_format_text_get(node);
1492
                  if ((!strcmp(s, "- a")) || (!strcmp(s, "-a")))
1493
                    break;
1494
               }
1495

1496
             if (node)
1497
               {
1498
                  evas_textblock_cursor_at_format_set(an->end, node);
1499
               }
1500
             else if (!evas_textblock_cursor_compare(an->start, an->end))
1501
               {
1502
                  free(an->name);
1503
                  evas_textblock_cursor_free(an->start);
1504
                  evas_textblock_cursor_free(an->end);
1505
                  en->anchors = eina_list_remove(en->anchors, an);
1506
                  free(an);
1507
               }
1508
             an = NULL;
1509
          }
1510
     }
1511

1512
   if (anchors_item)
1513
     {
1514
        const Evas_Object_Textblock_Node_Format *node;
1515
        const Eina_List *itr;
1516
        EINA_LIST_FOREACH(anchors_item, itr, node)
1517
          {
1518
             const char *s = evas_textblock_node_format_text_get(node);
1519
             char *p;
1520
             an = calloc(1, sizeof(Anchor));
1521
             if (!an)
1522
               {
1523
                  ERR("Running very low on memory");
1524
                  break;
1525
               }
1526

1527
             an->en = en;
1528
             an->item = 1;
1529
             p = strstr(s, "href=");
1530
             if (p)
1531
               {
1532
                  an->name = _anchor_format_parse(p);
1533
               }
1534
             en->anchors = eina_list_append(en->anchors, an);
1535
             an->start = evas_object_textblock_cursor_new(o);
1536
             an->end = evas_object_textblock_cursor_new(o);
1537
             evas_textblock_cursor_at_format_set(an->start, node);
1538
             evas_textblock_cursor_copy(an->start, an->end);
1539
             /* Although needed in textblock, don't bother with finding the end
1540
              * here cause it doesn't really matter. */
1541
          }
1542
     }
1543
}
1544

1545
static void
1546
_free_entry_change_info(void *_info)
1547
{
1548
   Edje_Entry_Change_Info *info = (Edje_Entry_Change_Info *)_info;
1549
   if (info->insert)
1550
     {
1551
        eina_stringshare_del(info->change.insert.content);
1552
     }
1553
   else
1554
     {
1555
        eina_stringshare_del(info->change.del.content);
1556
     }
1557
   free(info);
1558
}
1559

1560
static void
1561
_range_del_emit(Edje *ed, Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
1562
{
1563
   size_t start, end;
1564
   char *tmp;
1565
   Edje_Entry_Change_Info *info;
1566

1567
   start = evas_textblock_cursor_pos_get(en->sel_start);
1568
   end = evas_textblock_cursor_pos_get(en->sel_end);
1569
   if (start == end)
1570
     goto noop;
1571

1572
   info = calloc(1, sizeof(*info));
1573
   if (!info)
1574
     {
1575
        ERR("Running very low on memory");
1576
        goto noop;
1577
     }
1578
   info->insert = EINA_FALSE;
1579
   info->change.del.start = start;
1580
   info->change.del.end = end;
1581

1582
   tmp = evas_textblock_cursor_range_text_get(en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
1583
   info->change.del.content = eina_stringshare_add(tmp);
1584
   if (tmp) free(tmp);
1585
   evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1586
   _edje_emit(ed, "entry,changed", en->rp->part->name);
1587
   _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info,
1588
                   _free_entry_change_info);
1589
noop:
1590
   _sel_clear(ed, en->cursor, en->rp->object, en);
1591
}
1592

1593
//static void
1594
//_range_del(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
1595
//{
1596
//   evas_textblock_cursor_range_delete(en->sel_start, en->sel_end);
1597
//   _sel_clear(ed, en->cursor, en->rp->object, en);
1598
//}
1599

1600
static void
1601
_delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos,
1602
             Eina_Bool backspace)
1603
{
1604

1605
   if (backspace)
1606
     {
1607
        if (!evas_textblock_cursor_char_prev(c))
1608
          {
1609
             return;
1610
          }
1611
        evas_textblock_cursor_char_next(c);
1612
     }
1613
   else
1614
     {
1615
        if (!evas_textblock_cursor_char_next(c))
1616
          {
1617
             return;
1618
          }
1619
        evas_textblock_cursor_char_prev(c);
1620
     }
1621

1622
   Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1623
   if (!info)
1624
     {
1625
        ERR("Running very low on memory");
1626
        return;
1627
     }
1628
   char *tmp = NULL;
1629

1630
   info->insert = EINA_FALSE;
1631
   if (backspace)
1632
     {
1633

1634
        Evas_Textblock_Cursor *cc = evas_object_textblock_cursor_new(en->rp->object);
1635
        evas_textblock_cursor_copy(c, cc);
1636
        Eina_Bool remove_cluster = evas_textblock_cursor_at_cluster_as_single_glyph(cc,EINA_FALSE);
1637
        if (remove_cluster)
1638
          {
1639
             evas_textblock_cursor_cluster_prev(cc);
1640
          }
1641
        else
1642
          {
1643
             evas_textblock_cursor_char_prev(cc);
1644
          }
1645

1646
        info->change.del.start = evas_textblock_cursor_pos_get(cc);
1647
        info->change.del.end = pos;
1648

1649
        tmp = evas_textblock_cursor_range_text_get(c, cc, EVAS_TEXTBLOCK_TEXT_MARKUP);
1650
        evas_textblock_cursor_range_delete(c, cc);
1651
        evas_textblock_cursor_free(cc);
1652
     }
1653
   else
1654
     {
1655
        Evas_Textblock_Cursor *cc = evas_object_textblock_cursor_new(en->rp->object);
1656
        evas_textblock_cursor_copy(c, cc);
1657

1658
        Eina_Bool remove_cluster = evas_textblock_cursor_at_cluster_as_single_glyph(cc,EINA_TRUE);
1659
        if (remove_cluster)
1660
          {
1661
             evas_textblock_cursor_cluster_next(cc);
1662
          }
1663
        else
1664
          {
1665
             evas_textblock_cursor_char_next(cc);
1666
          }
1667

1668
        info->change.del.start = evas_textblock_cursor_pos_get(cc);
1669
        info->change.del.end = pos;
1670

1671
        tmp = evas_textblock_cursor_range_text_get(c, cc, EVAS_TEXTBLOCK_TEXT_MARKUP);
1672
        evas_textblock_cursor_range_delete(c, cc);
1673
        evas_textblock_cursor_free(cc);
1674
     }
1675

1676
   info->change.del.content = eina_stringshare_add(tmp);
1677
   if (tmp) free(tmp);
1678

1679
   _edje_emit(ed, "entry,changed", en->rp->part->name);
1680
   _edje_emit_full(ed, "entry,changed,user", en->rp->part->name,
1681
                   info, _free_entry_change_info);
1682
}
1683

1684
Eina_Bool
1685
_edje_entry_hide_visible_password(Edje *ed, Edje_Real_Part *rp)
1686
{
1687
   Eina_Bool int_ret = EINA_FALSE;
1688
   const Evas_Object_Textblock_Node_Format *node;
1689
   node = evas_textblock_node_format_first_get(rp->object);
1690
   for (; node; node = evas_textblock_node_format_next_get(node))
1691
     {
1692
        const char *text = evas_textblock_node_format_text_get(node);
1693
        if (text)
1694
          {
1695
             if (!strcmp(text, "+ password=off"))
1696
               {
1697
                  evas_textblock_node_format_remove_pair(rp->object,
1698
                                                         (Evas_Object_Textblock_Node_Format *)node);
1699
                  _edje_emit(ed, "entry,changed", rp->part->name);
1700
                  int_ret = EINA_TRUE;
1701
                  break;
1702
               }
1703
          }
1704
     }
1705
   _edje_entry_real_part_configure(ed, rp);
1706

1707
   return int_ret;
1708
}
1709

1710
static Eina_Bool
1711
_password_timer_cb(void *data)
1712
{
1713
   Entry *en = (Entry *)data;
1714
   _edje_entry_hide_visible_password(en->ed, en->rp);
1715
   en->pw_timer = NULL;
1716
   return ECORE_CALLBACK_CANCEL;
1717
}
1718

1719
static Eina_Bool
1720
_is_modifier(const char *key)
1721
{
1722
   if ((!strncmp(key, "Shift", 5)) ||
1723
       (!strncmp(key, "Control", 7)) ||
1724
       (!strncmp(key, "Alt", 3)) ||
1725
       (!strncmp(key, "Meta", 4)) ||
1726
       (!strncmp(key, "Super", 5)) ||
1727
       (!strncmp(key, "Hyper", 5)) ||
1728
       (!strcmp(key, "Scroll_Lock")) ||
1729
       (!strcmp(key, "Num_Lock")) ||
1730
       (!strcmp(key, "Caps_Lock")))
1731
     return EINA_TRUE;
1732
   return EINA_FALSE;
1733
}
1734

1735
static void
1736
_compose_seq_reset(Entry *en)
1737
{
1738
   char *str;
1739

1740
   EINA_LIST_FREE(en->seq, str)
1741
     eina_stringshare_del(str);
1742
   en->composing = EINA_FALSE;
1743
}
1744

1745
static void
1746
_edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1747
{
1748
   Edje *ed = data;
1749
   Evas_Event_Key_Down *ev = event_info;
1750
   Edje_Real_Part *rp;
1751
   Efl_Input_Device *seat;
1752

1753
   Entry *en;
1754
   Eina_Bool control, alt, shift;
1755
#if defined(__APPLE__) && defined(__MACH__)
1756
   Eina_Bool super, altgr;
1757
#endif
1758
   Eina_Bool multiline;
1759
   Eina_Bool cursor_changed;
1760
   int old_cur_pos;
1761

1762
   seat = efl_input_device_seat_get(ev->dev);
1763
   rp = _edje_focused_part_get(ed, _edje_seat_name_get(ed, seat));
1764

1765
   if (!rp) return;
1766
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
1767
       (!rp->typedata.text)) return;
1768
   en = rp->typedata.text->entry_data;
1769
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
1770
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
1771
     return;
1772
   if (!ev->key) return;
1773

1774
   _edje_emit(ed, "entry,keydown", rp->part->name);
1775
#ifdef HAVE_ECORE_IMF
1776
   if (en->imf_context)
1777
     {
1778
        Ecore_IMF_Event_Key_Down ecore_ev;
1779
        ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
1780
        if (!en->composing)
1781
          {
1782
             if (ecore_imf_context_filter_event(en->imf_context,
1783
                                                ECORE_IMF_EVENT_KEY_DOWN,
1784
                                                (Ecore_IMF_Event *)&ecore_ev))
1785
               {
1786
                  ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1787
                  return;
1788
               }
1789
          }
1790
     }
1791
#endif
1792

1793
   old_cur_pos = evas_textblock_cursor_pos_get(en->cursor);
1794

1795
#if defined(__APPLE__) && defined(__MACH__)
1796
   super = evas_key_modifier_is_set(ev->modifiers, "Super");
1797
   altgr = evas_key_modifier_is_set(ev->modifiers, "AltGr");
1798
#endif
1799
   control = evas_key_modifier_is_set(ev->modifiers, "Control");
1800
   alt = evas_key_modifier_is_set(ev->modifiers, "Alt");
1801
   shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
1802
   multiline = rp->part->multiline;
1803
   cursor_changed = EINA_FALSE;
1804
   if (!strcmp(ev->key, "Escape"))
1805
     {
1806
        _compose_seq_reset(en);
1807
        // dead keys here. Escape for now (should emit these)
1808
        _edje_emit(ed, "entry,key,escape", rp->part->name);
1809
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1810
     }
1811
   else if (!strcmp(ev->key, "Up") ||
1812
            (!strcmp(ev->key, "KP_Up") && !ev->string))
1813
     {
1814
        _compose_seq_reset(en);
1815
        if (multiline)
1816
          {
1817
             if (en->have_selection &&
1818
                 (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1819
               ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1820
             if (en->select_allow)
1821
               {
1822
                  if (shift)
1823
                    {
1824
                       _sel_start(en->cursor, rp->object, en);
1825
                       ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1826
                    }
1827
                  else if (en->have_selection)
1828
                    {
1829
                       if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1830
                         evas_textblock_cursor_copy(en->sel_start, en->cursor);
1831
                       else
1832
                         evas_textblock_cursor_copy(en->sel_end, en->cursor);
1833
                       _sel_clear(ed, en->cursor, rp->object, en);
1834
                    }
1835
               }
1836
             if (_curs_up(en->cursor, rp->object, en))
1837
               ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1838
             if (en->select_allow)
1839
               {
1840
                  if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1841
                  else _sel_clear(ed, en->cursor, rp->object, en);
1842
               }
1843
          }
1844
        _edje_emit(ed, "entry,key,up", rp->part->name);
1845
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1846
     }
1847
   else if (!strcmp(ev->key, "Down") ||
1848
            (!strcmp(ev->key, "KP_Down") && !ev->string))
1849
     {
1850
        _compose_seq_reset(en);
1851
        if (multiline)
1852
          {
1853
             if (en->have_selection &&
1854
                 (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1855
               ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1856
             if (en->select_allow)
1857
               {
1858
                  if (shift)
1859
                    {
1860
                       _sel_start(en->cursor, rp->object, en);
1861
                       ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1862
                    }
1863
                  else if (en->have_selection)
1864
                    {
1865
                       if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1866
                         evas_textblock_cursor_copy(en->sel_end, en->cursor);
1867
                       else
1868
                         evas_textblock_cursor_copy(en->sel_start, en->cursor);
1869
                       _sel_clear(ed, en->cursor, rp->object, en);
1870
                    }
1871
               }
1872
             if (_curs_down(en->cursor, rp->object, en))
1873
               ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1874
             if (en->select_allow)
1875
               {
1876
                  if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1877
                  else _sel_clear(ed, en->cursor, rp->object, en);
1878
               }
1879
          }
1880
        _edje_emit(ed, "entry,key,down", rp->part->name);
1881
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1882
     }
1883
   else if (!strcmp(ev->key, "Left") ||
1884
            (!strcmp(ev->key, "KP_Left") && !ev->string))
1885
     {
1886
        _compose_seq_reset(en);
1887
        if (en->have_selection &&
1888
            (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1889
          ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1890
        if (en->select_allow)
1891
          {
1892
             if (shift)
1893
               {
1894
                  _sel_start(en->cursor, rp->object, en);
1895
                  ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1896
               }
1897
             else
1898
               {
1899
                  if (en->have_selection)
1900
                    {
1901
                       if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1902
                         evas_textblock_cursor_copy(en->sel_start, en->cursor);
1903
                       else
1904
                         evas_textblock_cursor_copy(en->sel_end, en->cursor);
1905
                       _sel_clear(ed, en->cursor, rp->object, en);
1906
                    }
1907
               }
1908
          }
1909
        if (evas_textblock_cursor_cluster_prev(en->cursor))
1910
          ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1911
#if defined(__APPLE__) && defined(__MACH__)
1912
        if (altgr) evas_textblock_cursor_word_start(en->cursor);
1913
#else
1914
        /* If control is pressed, go to the start of the word */
1915
        if (control) evas_textblock_cursor_word_start(en->cursor);
1916
#endif
1917
        if (en->select_allow)
1918
          {
1919
             if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1920
             else _sel_clear(ed, en->cursor, rp->object, en);
1921
          }
1922
        _edje_emit(ed, "entry,key,left", rp->part->name);
1923
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1924
     }
1925
   else if (!strcmp(ev->key, "Right") ||
1926
            (!strcmp(ev->key, "KP_Right") && !ev->string))
1927
     {
1928
        _compose_seq_reset(en);
1929
        if (en->have_selection &&
1930
            (evas_textblock_cursor_pos_get(en->sel_start) != evas_textblock_cursor_pos_get(en->sel_end)))
1931
          ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1932
        if (en->select_allow)
1933
          {
1934
             if (shift)
1935
               {
1936
                  _sel_start(en->cursor, rp->object, en);
1937
                  ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1938
               }
1939
             else
1940
               {
1941
                  if (en->have_selection)
1942
                    {
1943
                       if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
1944
                         evas_textblock_cursor_copy(en->sel_end, en->cursor);
1945
                       else
1946
                         evas_textblock_cursor_copy(en->sel_start, en->cursor);
1947
                       _sel_clear(ed, en->cursor, rp->object, en);
1948
                    }
1949
               }
1950
          }
1951
        /* If control is pressed, go to the end of the word */
1952
#if defined(__APPLE__) && defined(__MACH__)
1953
        if (altgr) evas_textblock_cursor_word_end(en->cursor);
1954
#else
1955
        if (control) evas_textblock_cursor_word_end(en->cursor);
1956
#endif
1957
        if (evas_textblock_cursor_cluster_next(en->cursor))
1958
          ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1959
        if (en->select_allow)
1960
          {
1961
             if (shift) _sel_extend(ed, en->cursor, rp->object, en);
1962
             else _sel_clear(ed, en->cursor, rp->object, en);
1963
          }
1964
        _edje_emit(ed, "entry,key,right", rp->part->name);
1965
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
1966
     }
1967
   else if (!strcmp(ev->key, "BackSpace"))
1968
     {
1969
        _compose_seq_reset(en);
1970
        if (control && !en->have_selection)
1971
          {
1972
             // del to start of previous word
1973
             _sel_start(en->cursor, rp->object, en);
1974

1975
             evas_textblock_cursor_cluster_prev(en->cursor);
1976
             evas_textblock_cursor_word_start(en->cursor);
1977

1978
             _sel_preextend(ed, en->cursor, rp->object, en);
1979

1980
             _range_del_emit(ed, en->cursor, rp->object, en);
1981
          }
1982
        else if ((alt) && (shift))
1983
          {
1984
             // undo last action
1985
          }
1986
        else
1987
          {
1988
             if (en->have_selection)
1989
               {
1990
                  _range_del_emit(ed, en->cursor, rp->object, en);
1991
               }
1992
             else
1993
               {
1994
                  //if (evas_textblock_cursor_char_prev(en->cursor))
1995
                    {
1996
                       _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_TRUE);
1997
                    }
1998
               }
1999
          }
2000
        _sel_clear(ed, en->cursor, rp->object, en);
2001
        _anchors_get(en->cursor, rp->object, en);
2002
        _edje_emit(ed, "entry,key,backspace", rp->part->name);
2003
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2004
     }
2005
   else if ((!strcmp(ev->key, "Delete") ||
2006
             (!strcmp(ev->key, "KP_Delete") && !ev->string)) && (!shift))
2007
     {
2008
        _compose_seq_reset(en);
2009
        if (control)
2010
          {
2011
             // del to end of next word
2012
             _sel_start(en->cursor, rp->object, en);
2013

2014
             evas_textblock_cursor_word_end(en->cursor);
2015
             evas_textblock_cursor_cluster_next(en->cursor);
2016

2017
             _sel_extend(ed, en->cursor, rp->object, en);
2018

2019
             _range_del_emit(ed, en->cursor, rp->object, en);
2020
          }
2021
        else if (shift)
2022
          {
2023
             // cut
2024
          }
2025
        else
2026
          {
2027
             if (en->have_selection)
2028
               {
2029
                  _range_del_emit(ed, en->cursor, rp->object, en);
2030
               }
2031
             else
2032
               {
2033
                  _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_FALSE);
2034
               }
2035
          }
2036
        _sel_clear(ed, en->cursor, rp->object, en);
2037
        _anchors_get(en->cursor, rp->object, en);
2038
        _edje_emit(ed, "entry,key,delete", rp->part->name);
2039
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2040
     }
2041
   else if ((!alt) &&
2042
            (!strcmp(ev->key, "Home") ||
2043
             ((!strcmp(ev->key, "KP_Home")) && !ev->string)))
2044
     {
2045
        _compose_seq_reset(en);
2046
        if (en->select_allow)
2047
          {
2048
             if (shift) _sel_start(en->cursor, rp->object, en);
2049
             else _sel_clear(ed, en->cursor, rp->object, en);
2050
          }
2051
        if ((control) && (multiline))
2052
          _curs_start(en->cursor, rp->object, en);
2053
        else
2054
          _curs_lin_start(en->cursor, rp->object, en);
2055
        if (en->select_allow)
2056
          {
2057
             if (shift) _sel_extend(ed, en->cursor, rp->object, en);
2058
          }
2059
        _edje_emit(ed, "entry,key,home", rp->part->name);
2060
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
2061
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2062
     }
2063
   else if ((!alt) &&
2064
            (!strcmp(ev->key, "End") ||
2065
             ((!strcmp(ev->key, "KP_End")) && !ev->string)))
2066
     {
2067
        _compose_seq_reset(en);
2068
        if (en->select_allow)
2069
          {
2070
             if (shift) _sel_start(en->cursor, rp->object, en);
2071
             else _sel_clear(ed, en->cursor, rp->object, en);
2072
          }
2073
        if ((control) && (multiline))
2074
          _curs_end(en->cursor, rp->object, en);
2075
        else
2076
          _curs_lin_end(en->cursor, rp->object, en);
2077
        if (en->select_allow)
2078
          {
2079
             if (shift) _sel_extend(ed, en->cursor, rp->object, en);
2080
          }
2081
        _edje_emit(ed, "entry,key,end", rp->part->name);
2082
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
2083
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2084
     }
2085
#if defined(__APPLE__) && defined(__MACH__)
2086
   else if (((super) && (!shift) && (!strcmp(ev->key, "v"))) || ((shift) && (!super) && (!strcmp(ev->key, "Insert"))))
2087
#else
2088
   else if (((control) && (!shift) && (!strcmp(ev->key, "v"))) || ((shift) && (!control) && (!strcmp(ev->key, "Insert"))))
2089
#endif
2090
     {
2091
        _compose_seq_reset(en);
2092
        _edje_emit(ed, "entry,paste,request", rp->part->name);
2093
        _edje_emit(ed, "entry,paste,request,3", rp->part->name);
2094
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2095
     }
2096
#if defined(__APPLE__) && defined(__MACH__)
2097
   else if ((super) && (!strcmp(ev->key, "a")))
2098
#else
2099
   else if ((control) && (!strcmp(ev->key, "a")))
2100
#endif
2101
     {
2102
        _compose_seq_reset(en);
2103
        if (shift)
2104
          {
2105
             _edje_emit(ed, "entry,selection,none,request", rp->part->name);
2106
             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2107
          }
2108
        else
2109
          {
2110
             _edje_emit(ed, "entry,selection,all,request", rp->part->name);
2111
             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2112
          }
2113
     }
2114
#if defined(__APPLE__) && defined(__MACH__)
2115
   else if ((super) && (((!shift) && !strcmp(ev->key, "c")) || !strcmp(ev->key, "Insert")))
2116
#else
2117
   else if ((control) && (((!shift) && !strcmp(ev->key, "c")) || !strcmp(ev->key, "Insert")))
2118
#endif
2119
     {
2120
        _compose_seq_reset(en);
2121
        _edje_emit(ed, "entry,copy,notify", rp->part->name);
2122
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2123
     }
2124
#if defined(__APPLE__) && defined(__MACH__)
2125
   else if ((super) && (!shift) && ((!strcmp(ev->key, "x") || (!strcmp(ev->key, "m")))))
2126
#else
2127
   else if ((control) && (!shift) && ((!strcmp(ev->key, "x") || (!strcmp(ev->key, "m")))))
2128
#endif
2129
     {
2130
        _compose_seq_reset(en);
2131
        _edje_emit(ed, "entry,cut,notify", rp->part->name);
2132
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2133
     }
2134
   else if ((!strcmp(ev->key, "Delete") ||
2135
             (!strcmp(ev->key, "KP_Delete") && !ev->string)) && (shift))
2136
     {
2137
        _compose_seq_reset(en);
2138
        _edje_emit(ed, "entry,cut,notify", rp->part->name);
2139
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2140
     }
2141
#if defined(__APPLE__) && defined(__MACH__)
2142
   else if ((super) && (!strcmp(ev->key, "z")))
2143
#else
2144
   else if ((control) && (!strcmp(ev->key, "z")))
2145
#endif
2146
     {
2147
        _compose_seq_reset(en);
2148
        if (shift)
2149
          {
2150
             // redo
2151
             _edje_emit(ed, "entry,redo,request", rp->part->name);
2152
          }
2153
        else
2154
          {
2155
             // undo
2156
             _edje_emit(ed, "entry,undo,request", rp->part->name);
2157
          }
2158
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2159
     }
2160
#if defined(__APPLE__) && defined(__MACH__)
2161
   else if ((super) && (!shift) && (!strcmp(ev->key, "y")))
2162
#else
2163
   else if ((control) && (!shift) && (!strcmp(ev->key, "y")))
2164
#endif
2165
     {
2166
        _compose_seq_reset(en);
2167
        // redo
2168
        _edje_emit(ed, "entry,redo,request", rp->part->name);
2169
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2170
     }
2171
   //else if ((control) && (!shift) && (!strcmp(ev->key, "w")))
2172
   //{
2173
   //_compose_seq_reset(en);
2174
   //_sel_clear(ed, en->cursor, rp->object, en);
2175
   //select current word?
2176
   //ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2177
   //}
2178
   else if (!strcmp(ev->key, "Tab"))
2179
     {
2180
        _compose_seq_reset(en);
2181
        if (multiline)
2182
          {
2183
             if (shift)
2184
               {
2185
                  // remove a tab
2186
               }
2187
             else
2188
               {
2189
                  Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
2190
                  if (!info)
2191
                    {
2192
                       ERR("Running very low on memory");
2193
                    }
2194
                  else
2195
                    {
2196
                       info->insert = EINA_TRUE;
2197
                       info->change.insert.plain_length = 1;
2198

2199
                       if (en->have_selection)
2200
                         {
2201
                            _range_del_emit(ed, en->cursor, rp->object, en);
2202
                            info->merge = EINA_TRUE;
2203
                         }
2204
                       info->change.insert.pos =
2205
                         evas_textblock_cursor_pos_get(en->cursor);
2206
                       info->change.insert.content = eina_stringshare_add("<tab/>");
2207
                       _text_filter_format_prepend(ed, en, en->cursor, "tab");
2208
                       _anchors_get(en->cursor, rp->object, en);
2209
                       _edje_emit(ed, "entry,changed", rp->part->name);
2210
                       _edje_emit_full(ed, "entry,changed,user", rp->part->name,
2211
                                       info, _free_entry_change_info);
2212
                    }
2213
               }
2214
             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2215
          }
2216
        _edje_emit(ed, "entry,key,tab", rp->part->name);
2217
     }
2218
   else if ((!strcmp(ev->key, "ISO_Left_Tab")) && (multiline))
2219
     {
2220
        _compose_seq_reset(en);
2221
        // remove a tab
2222
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2223
     }
2224
   else if (!strcmp(ev->key, "Prior") ||
2225
            (!strcmp(ev->key, "KP_Prior") && !ev->string))
2226
     {
2227
        _compose_seq_reset(en);
2228
        if (en->select_allow)
2229
          {
2230
             if (shift) _sel_start(en->cursor, rp->object, en);
2231
             else _sel_clear(ed, en->cursor, rp->object, en);
2232
          }
2233
        if (!_curs_jump_line_by(en->cursor, rp->object, en, -10))
2234
          {
2235
             evas_textblock_cursor_line_set(en->cursor, 0);
2236
             _curs_lin_start(en->cursor, rp->object, en);
2237
          }
2238
        if (en->select_allow)
2239
          {
2240
             if (shift) _sel_extend(ed, en->cursor, rp->object, en);
2241
             else _sel_clear(ed, en->cursor, rp->object, en);
2242
          }
2243
        _edje_emit(ed, "entry,key,pgup", rp->part->name);
2244
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
2245
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2246
     }
2247
   else if (!strcmp(ev->key, "Next") ||
2248
            (!strcmp(ev->key, "KP_Next") && !ev->string))
2249
     {
2250
        _compose_seq_reset(en);
2251
        if (en->select_allow)
2252
          {
2253
             if (shift) _sel_start(en->cursor, rp->object, en);
2254
             else _sel_clear(ed, en->cursor, rp->object, en);
2255
          }
2256
        if (!_curs_jump_line_by(en->cursor, rp->object, en, 10))
2257
          {
2258
             int last = _curs_line_last_get(en->cursor, rp->object, en);
2259
             evas_textblock_cursor_line_set(en->cursor, last);
2260
             _curs_lin_end(en->cursor, rp->object, en);
2261
          }
2262
        if (en->select_allow)
2263
          {
2264
             if (shift) _sel_extend(ed, en->cursor, rp->object, en);
2265
             else _sel_clear(ed, en->cursor, rp->object, en);
2266
          }
2267
        _edje_emit(ed, "entry,key,pgdn", rp->part->name);
2268
        _edje_emit(ed, "cursor,changed,manual", rp->part->name);
2269
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2270
     }
2271
   else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
2272
     {
2273
        _compose_seq_reset(en);
2274
        if (multiline)
2275
          {
2276
             Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
2277
             if (!info)
2278
               {
2279
                  ERR("Running very low on memory");
2280
               }
2281
             else
2282
               {
2283
                  info->insert = EINA_TRUE;
2284
                  info->change.insert.plain_length = 1;
2285
                  if (en->have_selection)
2286
                    {
2287
                       _range_del_emit(ed, en->cursor, rp->object, en);
2288
                       info->merge = EINA_TRUE;
2289
                    }
2290

2291
                  info->change.insert.pos =
2292
                    evas_textblock_cursor_pos_get(en->cursor);
2293
                  if (shift ||
2294
                      evas_object_textblock_legacy_newline_get(rp->object))
2295
                    {
2296
                       _text_filter_format_prepend(ed, en, en->cursor, "br");
2297
                       info->change.insert.content = eina_stringshare_add("<br/>");
2298
                    }
2299
                  else
2300
                    {
2301
                       _text_filter_format_prepend(ed, en, en->cursor, "ps");
2302
                       info->change.insert.content = eina_stringshare_add("<ps/>");
2303
                    }
2304
                  _anchors_get(en->cursor, rp->object, en);
2305
                  _edje_emit(ed, "entry,changed", rp->part->name);
2306
                  _edje_emit_full(ed, "entry,changed,user", rp->part->name,
2307
                                  info, _free_entry_change_info);
2308
                  _edje_emit(ed, "cursor,changed", rp->part->name);
2309
                  cursor_changed = EINA_TRUE;
2310
               }
2311
          }
2312
        _edje_emit(ed, "entry,key,enter", rp->part->name);
2313
        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2314
     }
2315
   else
2316
     {
2317
        char *compres = NULL, *string = (char *)ev->string;
2318
        Eina_Bool free_string = EINA_FALSE;
2319
        Ecore_Compose_State state;
2320

2321
        if (control) goto end;
2322
        if (!en->composing)
2323
          {
2324
             _compose_seq_reset(en);
2325
             en->seq = eina_list_append(en->seq, eina_stringshare_add(ev->key));
2326
             state = ecore_compose_get(en->seq, &compres);
2327
             if (state == ECORE_COMPOSE_MIDDLE) en->composing = EINA_TRUE;
2328
             else en->composing = EINA_FALSE;
2329
             if (!en->composing)
2330
               {
2331
                  free(compres);
2332
                  compres = NULL;
2333
                  _compose_seq_reset(en);
2334
                  if (ev->string && (!ev->string[1]) &&
2335
                      ((ev->string[0] < 0x20) || (ev->string[0] == 0x7f)))
2336
                    goto end;
2337
               }
2338
             else
2339
               {
2340
                  free(compres);
2341
                  compres = NULL;
2342
                  goto end;
2343
               }
2344
          }
2345
        else
2346
          {
2347
             if (_is_modifier(ev->key)) goto end;
2348
             en->seq = eina_list_append(en->seq, eina_stringshare_add(ev->key));
2349
             state = ecore_compose_get(en->seq, &compres);
2350
             if (state == ECORE_COMPOSE_NONE)
2351
               {
2352
                  _compose_seq_reset(en);
2353
                  free(compres);
2354
                  compres = NULL;
2355
               }
2356
             else if (state == ECORE_COMPOSE_DONE)
2357
               {
2358
                  _compose_seq_reset(en);
2359
                  if (compres)
2360
                    {
2361
                       string = compres;
2362
                       free_string = EINA_TRUE;
2363
                    }
2364
                  compres = NULL;
2365
               }
2366
             else
2367
               {
2368
                  free(compres);
2369
                  compres = NULL;
2370
                  goto end;
2371
               }
2372
          }
2373
        if (string)
2374
          {
2375
             Edje_Entry_Change_Info *info = NULL;
2376
// if PASSWORD_SHOW_LAST mode, appending text with password=off tag
2377
             if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
2378
                 _edje_password_show_last)
2379
               {
2380
                  _edje_entry_hide_visible_password(ed, en->rp);
2381
                  info = _text_filter_text_prepend(ed, en, en->cursor, string,
2382
                                                   "+ password=off",
2383
                                                   "- password",
2384
                                                   EINA_TRUE, EINA_TRUE);
2385
                  if (info)
2386
                    {
2387
                       if (en->pw_timer)
2388
                         {
2389
                            ecore_timer_del(en->pw_timer);
2390
                            en->pw_timer = NULL;
2391
                         }
2392
                       if (_edje_password_show_last_timeout >= 0)
2393
                         en->pw_timer = ecore_timer_add
2394
                             (_edje_password_show_last_timeout,
2395
                             _password_timer_cb, en);
2396
                    }
2397
               }
2398
             else
2399
               info = _text_filter_text_prepend(ed, en, en->cursor, string,
2400
                                                NULL, NULL,
2401
                                                EINA_TRUE, EINA_TRUE);
2402
             _anchors_get(en->cursor, rp->object, en);
2403
             if (info)
2404
               {
2405
                  _edje_emit(ed, "entry,changed", rp->part->name);
2406
                  _edje_emit_full(ed, "entry,changed,user", rp->part->name,
2407
                                  info, _free_entry_change_info);
2408
                  _edje_emit(ed, "cursor,changed", rp->part->name);
2409
                  cursor_changed = EINA_TRUE;
2410
                  ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2411
               }
2412
             if (free_string) free(string);
2413
          }
2414
     }
2415
end:
2416
   if (!cursor_changed &&
2417
       (old_cur_pos != evas_textblock_cursor_pos_get(en->cursor)))
2418
     _edje_emit(ed, "cursor,changed", rp->part->name);
2419

2420
   _edje_entry_imf_cursor_info_set(en);
2421
   _edje_entry_real_part_configure(ed, rp);
2422
}
2423

2424
static void
2425
_edje_key_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2426
{
2427
   Evas_Event_Key_Up *ev = event_info;
2428
   Efl_Input_Device *seat;
2429
   Edje *ed = data;
2430
   Edje_Real_Part *rp;
2431
   Entry *en;
2432

2433
   seat = efl_input_device_seat_get(ev->dev);
2434
   rp = _edje_focused_part_get(ed, _edje_seat_name_get(ed, seat));
2435
   if (!rp) return;
2436
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2437
       (!rp->typedata.text)) return;
2438
   en = rp->typedata.text->entry_data;
2439
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2440
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_EDITABLE))
2441
     return;
2442

2443
   _edje_emit(ed, "entry,keyup", rp->part->name);
2444
#ifdef HAVE_ECORE_IMF
2445
   if (en->imf_context)
2446
     {
2447
        Ecore_IMF_Event_Key_Up ecore_ev;
2448

2449
        ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev);
2450
        if (ecore_imf_context_filter_event(en->imf_context,
2451
                                           ECORE_IMF_EVENT_KEY_UP,
2452
                                           (Ecore_IMF_Event *)&ecore_ev))
2453
          return;
2454
     }
2455
#else
2456
   (void)event_info;
2457
#endif
2458
}
2459

2460
static Evas_Textblock_Cursor *
2461
_edje_cursor_cluster_coord_set(Edje_Real_Part *rp, Evas_Coord canvasx, Evas_Coord canvasy, Evas_Coord *cx, Evas_Coord *cy)
2462
{
2463
   Entry *en;
2464
   Evas_Coord x, y, lh = 0, cly = 0;
2465
   Evas_Textblock_Cursor *line_cur;
2466
   Evas_Textblock_Cursor *tc;
2467

2468
   en = rp->typedata.text->entry_data;
2469
   tc = evas_object_textblock_cursor_new(rp->object);
2470
   evas_textblock_cursor_copy(en->cursor, tc);
2471
   evas_object_geometry_get(rp->object, &x, &y, NULL, NULL);
2472
   *cx = canvasx - x;
2473
   *cy = canvasy - y;
2474

2475
   line_cur = evas_object_textblock_cursor_new(rp->object);
2476
   evas_textblock_cursor_paragraph_last(line_cur);
2477
   evas_textblock_cursor_line_geometry_get(line_cur, NULL, &cly, NULL, &lh);
2478
   /* Consider a threshold of half the line height */
2479
   if (*cy > (cly + lh) && *cy < (cly + lh + lh / 2))
2480
     {
2481
        *cy = cly + lh - 1; // Make it inside Textblock
2482
     }
2483
   evas_textblock_cursor_paragraph_first(line_cur);
2484
   evas_textblock_cursor_line_geometry_get(line_cur, NULL, &cly, NULL, NULL);
2485

2486
   if (*cy < cly && *cy > (cly - lh / 2))
2487
     {
2488
        *cy = cly;
2489
     }
2490
   evas_textblock_cursor_free(line_cur);
2491
   /* No need to check return value if not able to set the char coord Textblock
2492
    * will take care */
2493
   evas_textblock_cursor_cluster_coord_set(en->cursor, *cx, *cy);
2494

2495
   return tc;
2496
}
2497

2498
static void
2499
_edje_part_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2500
{
2501
   Edje_Real_Part *rp = data;
2502
   Entry *en;
2503
   if (!rp) return;
2504
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2505
       (!rp->typedata.text)) return;
2506
   en = rp->typedata.text->entry_data;
2507
   if (!en) return;
2508
   _edje_entry_imf_cursor_location_set(en);
2509
}
2510

2511
static void
2512
_edje_part_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2513
{
2514
   Evas_Coord cx, cy;
2515
   Edje_Real_Part *rp = data;
2516
   Evas_Event_Mouse_Down *ev = event_info;
2517
   Entry *en;
2518
   //   Eina_Bool multiline;
2519
   Evas_Textblock_Cursor *tc = NULL;
2520
   Eina_Bool dosel = EINA_FALSE;
2521
   Eina_Bool shift;
2522

2523
   if ((!rp) || (!ev)) return;
2524
   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
2525
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2526
       (!rp->typedata.text)) return;
2527
   en = rp->typedata.text->entry_data;
2528
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2529
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2530
     return;
2531
   if ((ev->button != 1) && (ev->button != 2)) return;
2532

2533
#ifdef HAVE_ECORE_IMF
2534
   if (en->imf_context)
2535
     {
2536
        Ecore_IMF_Event_Mouse_Down ecore_ev;
2537
        ecore_imf_evas_event_mouse_down_wrap(ev, &ecore_ev);
2538
        if (ecore_imf_context_filter_event(en->imf_context,
2539
                                           ECORE_IMF_EVENT_MOUSE_DOWN,
2540
                                           (Ecore_IMF_Event *)&ecore_ev))
2541
          return;
2542
     }
2543
#endif
2544

2545
   _edje_entry_imf_context_reset(rp);
2546

2547
   shift = evas_key_modifier_is_set(ev->modifiers, "Shift");
2548
   en->select_mod_start = EINA_FALSE;
2549
   en->select_mod_end = EINA_FALSE;
2550

2551
   if (en->select_allow && ev->button != 2) dosel = EINA_TRUE;
2552
   if (dosel)
2553
     {
2554
        if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
2555
          {
2556
             if (shift)
2557
               {
2558
                  tc = evas_object_textblock_cursor_new(rp->object);
2559
                  evas_textblock_cursor_copy(en->cursor, tc);
2560
                  if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
2561
                    evas_textblock_cursor_line_char_first(en->cursor);
2562
                  else
2563
                    evas_textblock_cursor_line_char_last(en->cursor);
2564
                  _sel_extend(en->ed, en->cursor, rp->object, en);
2565
               }
2566
             else
2567
               {
2568
                  en->have_selection = EINA_FALSE;
2569
                  en->selecting = EINA_FALSE;
2570
                  _sel_clear(en->ed, en->cursor, rp->object, en);
2571
                  tc = evas_object_textblock_cursor_new(rp->object);
2572
                  evas_textblock_cursor_copy(en->cursor, tc);
2573
                  evas_textblock_cursor_line_char_first(en->cursor);
2574
                  _sel_start(en->cursor, rp->object, en);
2575
                  evas_textblock_cursor_line_char_last(en->cursor);
2576
                  _sel_extend(en->ed, en->cursor, rp->object, en);
2577
               }
2578
             goto end;
2579
          }
2580
        else if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
2581
          {
2582
             if (shift)
2583
               {
2584
                  tc = evas_object_textblock_cursor_new(rp->object);
2585
                  evas_textblock_cursor_copy(en->cursor, tc);
2586
                  if (evas_textblock_cursor_compare(en->cursor, en->sel_start) < 0)
2587
                    evas_textblock_cursor_word_start(en->cursor);
2588
                  else
2589
                    {
2590
                       evas_textblock_cursor_word_end(en->cursor);
2591
                       evas_textblock_cursor_cluster_next(en->cursor);
2592
                    }
2593
                  _sel_extend(en->ed, en->cursor, rp->object, en);
2594
               }
2595
             else
2596
               {
2597
                  en->have_selection = EINA_FALSE;
2598
                  en->selecting = EINA_FALSE;
2599
                  _sel_clear(en->ed, en->cursor, rp->object, en);
2600
                  tc = evas_object_textblock_cursor_new(rp->object);
2601
                  evas_textblock_cursor_copy(en->cursor, tc);
2602
                  evas_textblock_cursor_word_start(en->cursor);
2603
                  _sel_start(en->cursor, rp->object, en);
2604
                  evas_textblock_cursor_word_end(en->cursor);
2605
                  evas_textblock_cursor_cluster_next(en->cursor);
2606
                  _sel_extend(en->ed, en->cursor, rp->object, en);
2607
               }
2608
             goto end;
2609
          }
2610
     }
2611
   tc = _edje_cursor_cluster_coord_set(rp, ev->canvas.x, ev->canvas.y, &cx, &cy);
2612

2613
   if (dosel)
2614
     {
2615
        if ((en->have_selection) &&
2616
            (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT))
2617
          {
2618
             if (shift)
2619
               _sel_extend(en->ed, en->cursor, rp->object, en);
2620
             else
2621
               {
2622
                  Eina_List *first, *last;
2623
                  FLOAT_T sc;
2624

2625
                  first = en->sel;
2626
                  last = eina_list_last(en->sel);
2627
                  if (first && last)
2628
                    {
2629
                       Evas_Textblock_Rectangle *r1, *r2;
2630
                       Evas_Coord d, d1, d2;
2631

2632
                       r1 = first->data;
2633
                       r2 = last->data;
2634
                       d = r1->x - cx;
2635
                       d1 = d * d;
2636
                       d = (r1->y + (r1->h / 2)) - cy;
2637
                       d1 += d * d;
2638
                       d = r2->x + r2->w - 1 - cx;
2639
                       d2 = d * d;
2640
                       d = (r2->y + (r2->h / 2)) - cy;
2641
                       d2 += d * d;
2642
                       sc = DIV(en->ed->scale, en->ed->file->base_scale);
2643
                       if (EQ(sc, ZERO)) sc = DIV(_edje_scale, en->ed->file->base_scale);
2644
                       d = (Evas_Coord)MUL(FROM_INT(20), sc); // FIXME: maxing number!
2645
                       d = d * d;
2646
                       if (d1 < d2)
2647
                         {
2648
                            if (d1 <= d)
2649
                              {
2650
                                 en->select_mod_start = EINA_TRUE;
2651
                                 en->selecting = EINA_TRUE;
2652
                              }
2653
                         }
2654
                       else
2655
                         {
2656
                            if (d2 <= d)
2657
                              {
2658
                                 en->select_mod_end = EINA_TRUE;
2659
                                 en->selecting = EINA_TRUE;
2660
                              }
2661
                         }
2662
                    }
2663
               }
2664
          }
2665
        else
2666
          {
2667
             if (shift)
2668
               {
2669
                  _sel_extend(en->ed, en->cursor, rp->object, en);
2670
               }
2671
             else
2672
               {
2673
                  en->selecting = EINA_TRUE;
2674
                  _sel_clear(en->ed, en->cursor, rp->object, en);
2675
                  _sel_start(en->cursor, rp->object, en);
2676
               }
2677
          }
2678
     }
2679
end:
2680
   if (evas_textblock_cursor_compare(tc, en->cursor))
2681
     {
2682
        _edje_emit(en->ed, "cursor,changed", rp->part->name);
2683
        _edje_emit(en->ed, "cursor,changed,manual", rp->part->name);
2684
     }
2685
   evas_textblock_cursor_free(tc);
2686

2687
   _edje_entry_real_part_configure(en->ed, rp);
2688
   if (ev->button == 2)
2689
     {
2690
        _edje_emit(en->ed, "entry,paste,request", rp->part->name);
2691
        _edje_emit(en->ed, "entry,paste,request,1", rp->part->name);
2692
     }
2693
}
2694

2695
static void
2696
_edje_part_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2697
{
2698
   Evas_Coord cx, cy;
2699
   Edje_Real_Part *rp = data;
2700
   Evas_Event_Mouse_Up *ev = event_info;
2701
   Entry *en;
2702
   Evas_Textblock_Cursor *tc;
2703

2704
   if ((!ev) || (ev->button != 1)) return;
2705
   if (!rp) return;
2706
   if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) return;
2707
   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) return;
2708
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2709
       (!rp->typedata.text)) return;
2710
   en = rp->typedata.text->entry_data;
2711
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2712
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2713
     return;
2714

2715
   /* We don't check for ON_HOLD because we'd like to end selection anyway when
2716
    * mouse is up, even if it's held. */
2717

2718
#ifdef HAVE_ECORE_IMF
2719
   if (en->imf_context)
2720
     {
2721
        Ecore_IMF_Event_Mouse_Up ecore_ev;
2722
        ecore_imf_evas_event_mouse_up_wrap(ev, &ecore_ev);
2723
        if (ecore_imf_context_filter_event(en->imf_context,
2724
                                           ECORE_IMF_EVENT_MOUSE_UP,
2725
                                           (Ecore_IMF_Event *)&ecore_ev))
2726
          return;
2727
     }
2728
#endif
2729

2730
   /* cx cy are unused but needed in mouse down, please bear with it */
2731
   tc = _edje_cursor_cluster_coord_set(rp, ev->canvas.x, ev->canvas.y, &cx, &cy);
2732

2733
   if (en->select_allow)
2734
     {
2735
        if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2736
          {
2737
             if (en->had_sel)
2738
               {
2739
                  if (en->select_mod_end)
2740
                    _sel_extend(en->ed, en->cursor, rp->object, en);
2741
                  else if (en->select_mod_start)
2742
                    _sel_preextend(en->ed, en->cursor, rp->object, en);
2743
               }
2744
             else
2745
               _sel_extend(en->ed, en->cursor, rp->object, en);
2746
             //evas_textblock_cursor_copy(en->cursor, en->sel_end);
2747
          }
2748
        else
2749
          {
2750
             evas_textblock_cursor_copy(en->cursor, en->sel_end);
2751
          }
2752
     }
2753
   if (en->selecting)
2754
     {
2755
        if (en->have_selection)
2756
          en->had_sel = EINA_TRUE;
2757
        en->selecting = EINA_FALSE;
2758
     }
2759
   if (evas_textblock_cursor_compare(tc, en->cursor))
2760
     {
2761
        _edje_emit(en->ed, "cursor,changed", rp->part->name);
2762
        _edje_emit(en->ed, "cursor,changed,manual", rp->part->name);
2763
     }
2764

2765
   _edje_entry_imf_cursor_info_set(en);
2766

2767
   evas_textblock_cursor_free(tc);
2768

2769
   _edje_entry_real_part_configure(en->ed, rp);
2770
}
2771

2772
static void
2773
_edje_part_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2774
{
2775
   Evas_Coord cx, cy;
2776
   Edje_Real_Part *rp = data;
2777
   Evas_Event_Mouse_Move *ev = event_info;
2778
   Entry *en;
2779
   Evas_Coord x, y, w, h;
2780
   Evas_Textblock_Cursor *tc;
2781

2782
   if ((!rp) || (!ev)) return;
2783
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2784
       (!rp->typedata.text)) return;
2785
   en = rp->typedata.text->entry_data;
2786
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2787
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2788
     return;
2789

2790
#ifdef HAVE_ECORE_IMF
2791
   if (en->imf_context)
2792
     {
2793
        Ecore_IMF_Event_Mouse_Move ecore_ev;
2794
        ecore_imf_evas_event_mouse_move_wrap(ev, &ecore_ev);
2795
        if (ecore_imf_context_filter_event(en->imf_context,
2796
                                           ECORE_IMF_EVENT_MOUSE_MOVE,
2797
                                           (Ecore_IMF_Event *)&ecore_ev))
2798
          return;
2799
     }
2800
#endif
2801

2802
   if (en->selecting)
2803
     {
2804
        tc = evas_object_textblock_cursor_new(rp->object);
2805
        evas_textblock_cursor_copy(en->cursor, tc);
2806
        evas_object_geometry_get(rp->object, &x, &y, &w, &h);
2807
        cx = ev->cur.canvas.x - x;
2808
        cy = ev->cur.canvas.y - y;
2809
        if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, cy))
2810
          {
2811
             Evas_Coord lx, ly, lw, lh;
2812

2813
             if (evas_textblock_cursor_line_coord_set(en->cursor, cy) < 0)
2814
               {
2815
                  if (rp->part->multiline)
2816
                    _curs_end(en->cursor, rp->object, en);
2817
                  else
2818
                    {
2819
                       evas_textblock_cursor_paragraph_first(en->cursor);
2820
                       evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2821
                       if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, ly + (lh / 2)))
2822
                         _curs_end(en->cursor, rp->object, en);
2823
                    }
2824
               }
2825
             else
2826
               {
2827
                  evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh);
2828
                  if (cx <= lx)
2829
                    _curs_lin_start(en->cursor, rp->object, en);
2830
                  else
2831
                    _curs_lin_end(en->cursor, rp->object, en);
2832
               }
2833
          }
2834
        if (en->select_allow)
2835
          {
2836
             if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_EXPLICIT)
2837
               {
2838
                  if (en->had_sel)
2839
                    {
2840
                       if (en->select_mod_end)
2841
                         _sel_extend(en->ed, en->cursor, rp->object, en);
2842
                       else if (en->select_mod_start)
2843
                         _sel_preextend(en->ed, en->cursor, rp->object, en);
2844
                    }
2845
                  else
2846
                    _sel_extend(en->ed, en->cursor, rp->object, en);
2847
               }
2848
             else
2849
               {
2850
                  _sel_extend(en->ed, en->cursor, rp->object, en);
2851
               }
2852

2853
             if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) != 0)
2854
               _sel_enable(en->ed, en->cursor, rp->object, en);
2855
             if (en->have_selection)
2856
               _sel_update(en->ed, en->cursor, rp->object, en);
2857
          }
2858
        if (evas_textblock_cursor_compare(tc, en->cursor))
2859
          {
2860
             _edje_emit(en->ed, "cursor,changed", rp->part->name);
2861
             _edje_emit(en->ed, "cursor,changed,manual", rp->part->name);
2862
          }
2863
        evas_textblock_cursor_free(tc);
2864

2865
        _edje_entry_real_part_configure(en->ed, rp);
2866
     }
2867
}
2868

2869
static void
2870
_canvas_viewport_resize_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
2871
{
2872
   Edje_Real_Part *rp = data;
2873
   Entry *en;
2874
   if ((!rp)) return;
2875

2876
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2877
       (!rp->typedata.text)) return;
2878
   en = rp->typedata.text->entry_data;
2879
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
2880
                       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
2881
     return;
2882

2883
   _anchors_need_update(rp);
2884
}
2885

2886
static void
2887
_evas_focus_in_cb(void *data, const Efl_Event *event)
2888
{
2889
   Efl_Input_Focus *ev = event->info;
2890
   Evas *e = event->object;
2891
   Efl_Input_Device *seat;
2892
   Edje *ed = data;
2893

2894
   if (!ed) return;
2895

2896
   seat = efl_input_device_get(ev);
2897
   if (evas_canvas_seat_focus_get(e, seat) == ed->obj)
2898
     {
2899
        _edje_focus_in(data, seat);
2900
     }
2901
}
2902

2903
static void
2904
_evas_focus_out_cb(void *data, const Efl_Event *event)
2905
{
2906
   Efl_Input_Focus *ev = event->info;
2907
   Evas *e = event->object;
2908
   Efl_Input_Device *seat;
2909
   Edje *ed = data;
2910

2911
   if (!ed) return;
2912

2913
   seat = efl_input_device_get(ev);
2914
   if (evas_canvas_seat_focus_get(e, seat) == ed->obj)
2915
     {
2916
        _edje_focus_out(data, seat);
2917
     }
2918
}
2919

2920
/***************************************************************/
2921
void
2922
_edje_entry_init(Edje *ed)
2923
{
2924
   if (!ed->has_entries)
2925
     return;
2926
   if (ed->entries_inited)
2927
     return;
2928
   ed->entries_inited = EINA_TRUE;
2929

2930
   efl_event_callback_add(ed->obj, EFL_EVENT_FOCUS_IN, _edje_focus_in_cb, ed);
2931
   efl_event_callback_add(ed->obj, EFL_EVENT_FOCUS_OUT, _edje_focus_out_cb, ed);
2932
   evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_DOWN,
2933
                                  _edje_key_down_cb, ed);
2934
   evas_object_event_callback_add(ed->obj, EVAS_CALLBACK_KEY_UP,
2935
                                  _edje_key_up_cb, ed);
2936
   efl_event_callback_add(ed->base.evas, EFL_CANVAS_SCENE_EVENT_SCENE_FOCUS_IN,
2937
                          _evas_focus_in_cb, ed);
2938
   efl_event_callback_add(ed->base.evas, EFL_CANVAS_SCENE_EVENT_SCENE_FOCUS_OUT,
2939
                          _evas_focus_out_cb, ed);
2940
}
2941

2942
void
2943
_edje_entry_shutdown(Edje *ed)
2944
{
2945
   if ((!ed) || (!ed->has_entries))
2946
     return;
2947
   if (!ed->entries_inited)
2948
     return;
2949
   ed->entries_inited = EINA_FALSE;
2950

2951
   efl_event_callback_del(ed->obj, EFL_EVENT_FOCUS_IN, _edje_focus_in_cb, ed);
2952
   efl_event_callback_del(ed->obj, EFL_EVENT_FOCUS_OUT, _edje_focus_out_cb, ed);
2953
   evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_DOWN,
2954
                                  _edje_key_down_cb);
2955
   evas_object_event_callback_del(ed->obj, EVAS_CALLBACK_KEY_UP,
2956
                                  _edje_key_up_cb);
2957
   efl_event_callback_del(ed->base.evas, EFL_CANVAS_SCENE_EVENT_SCENE_FOCUS_IN,
2958
                          _evas_focus_in_cb, ed);
2959
   efl_event_callback_del(ed->base.evas, EFL_CANVAS_SCENE_EVENT_SCENE_FOCUS_OUT,
2960
                          _evas_focus_out_cb, ed);
2961
}
2962

2963
int
2964
_edje_entry_real_part_cursor_objs_get(Edje_Real_Part *rp, Evas_Object **cursor_objs)
2965
{
2966
   Entry *en;
2967
   int ret = 0;
2968

2969
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2970
       (!rp->typedata.text) || (!rp->typedata.text->entry_data)) return -1;
2971

2972
   en = rp->typedata.text->entry_data;
2973

2974
   if (en->cursor_bg) cursor_objs[ret++] = en->cursor_bg;
2975
   if (en->cursor_fg) cursor_objs[ret++] = en->cursor_fg;
2976
   if (en->cursor_fg2) cursor_objs[ret++] = en->cursor_fg2;
2977
   return ret;
2978
}
2979

2980
void
2981
_edje_entry_real_part_init(Edje *ed, Edje_Real_Part *rp)
2982
{
2983
   Entry *en;
2984
#ifdef HAVE_ECORE_IMF
2985
   const char *ctx_id;
2986
   const Ecore_IMF_Context_Info *ctx_info;
2987
#endif
2988

2989
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2990
       (!rp->typedata.text)) return;
2991
   en = calloc(1, sizeof(Entry));
2992
   if (!en)
2993
     {
2994
        ERR("Running very low on memory");
2995
        return;
2996
     }
2997
   rp->typedata.text->entry_data = en;
2998
   en->rp = rp;
2999
   en->ed = ed;
3000

3001
   evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOVE, _edje_part_move_cb, rp);
3002

3003
   evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_DOWN, _edje_part_mouse_down_cb, rp);
3004
   evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_UP, _edje_part_mouse_up_cb, rp);
3005
   evas_object_event_callback_add(rp->object, EVAS_CALLBACK_MOUSE_MOVE, _edje_part_mouse_move_cb, rp);
3006
   evas_event_callback_add(ed->base.evas, EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE, _canvas_viewport_resize_cb, rp);
3007

3008
   if (rp->part->select_mode == EDJE_ENTRY_SELECTION_MODE_DEFAULT)
3009
     en->select_allow = EINA_TRUE;
3010

3011
   if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
3012
     {
3013
        Edje_Part_Description_Text *txt;
3014

3015
        txt = (Edje_Part_Description_Text *)rp->chosen_description;
3016

3017
        en->select_allow = EINA_FALSE;
3018
        if (txt && edje_string_get(&txt->text.repch))
3019
          evas_object_textblock_replace_char_set(rp->object, edje_string_get(&txt->text.repch));
3020
        else
3021
          evas_object_textblock_replace_char_set(rp->object, "*");
3022
     }
3023

3024
   if (rp->part->source3)
3025
     {
3026
        en->cursor_bg = edje_object_add(ed->base.evas);
3027
        edje_object_file_set(en->cursor_bg, ed->path, rp->part->source3);
3028
        evas_object_smart_member_add(en->cursor_bg, ed->obj);
3029
        evas_object_stack_below(en->cursor_bg, rp->object);
3030
        evas_object_clip_set(en->cursor_bg, evas_object_clip_get(rp->object));
3031
        evas_object_pass_events_set(en->cursor_bg, EINA_TRUE);
3032
        _edje_subobj_register(ed, en->cursor_bg);
3033
     }
3034
   if (rp->part->source4)
3035
     {
3036
        en->cursor_fg = edje_object_add(ed->base.evas);
3037
        edje_object_file_set(en->cursor_fg, ed->path, rp->part->source4);
3038
        evas_object_smart_member_add(en->cursor_fg, ed->obj);
3039
        evas_object_stack_above(en->cursor_fg, rp->object);
3040
        evas_object_clip_set(en->cursor_fg, evas_object_clip_get(rp->object));
3041
        evas_object_pass_events_set(en->cursor_fg, EINA_TRUE);
3042
        _edje_subobj_register(ed, en->cursor_fg);
3043

3044
        /* A proxy to the main cursor. */
3045
        if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
3046
          {
3047
             en->cursor_fg2 = edje_object_add(ed->base.evas);
3048
             edje_object_file_set(en->cursor_fg2, ed->path, rp->part->source4);
3049
             evas_object_smart_member_add(en->cursor_fg2, ed->obj);
3050
             evas_object_stack_above(en->cursor_fg2, rp->object);
3051
             evas_object_clip_set(en->cursor_fg2, evas_object_clip_get(rp->object));
3052
             evas_object_pass_events_set(en->cursor_fg2, EINA_TRUE);
3053
             _edje_subobj_register(ed, en->cursor_fg2);
3054
          }
3055
     }
3056

3057
   evas_object_textblock_legacy_newline_set(rp->object, EINA_TRUE);
3058

3059
   if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
3060
     {
3061
        if (en->cursor_bg) evas_object_show(en->cursor_bg);
3062
        if (en->cursor_fg) evas_object_show(en->cursor_fg);
3063
        if (en->cursor_fg2) evas_object_show(en->cursor_fg2);
3064
        en->input_panel_enable = EINA_TRUE;
3065

3066
#ifdef HAVE_ECORE_IMF
3067
        _edje_need_imf();
3068

3069
        en->commit_cancel = EINA_FALSE;
3070

3071
        edje_object_signal_callback_add(ed->obj, "focus,part,in,*",
3072
                                        rp->part->name,
3073
                                        _edje_entry_focus_in_cb, rp);
3074
        edje_object_signal_callback_add(ed->obj, "focus,part,out,*",
3075
                                        rp->part->name,
3076
                                        _edje_entry_focus_out_cb, rp);
3077

3078
        ctx_id = ecore_imf_context_default_id_get();
3079
        if (ctx_id)
3080
          {
3081
             ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
3082
             if (!ctx_info->canvas_type ||
3083
                 strcmp(ctx_info->canvas_type, "evas") == 0)
3084
               {
3085
                  en->imf_context = ecore_imf_context_add(ctx_id);
3086
               }
3087
             else
3088
               {
3089
                  ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
3090
                  if (ctx_id)
3091
                    {
3092
                       en->imf_context = ecore_imf_context_add(ctx_id);
3093
                    }
3094
               }
3095
          }
3096
        else
3097
          en->imf_context = NULL;
3098

3099
        if (!en->imf_context) goto done;
3100

3101
        ecore_imf_context_client_window_set
3102
          (en->imf_context,
3103
          (void *)ecore_evas_window_get
3104
            (ecore_evas_ecore_evas_get(ed->base.evas)));
3105
        ecore_imf_context_client_canvas_set(en->imf_context, ed->base.evas);
3106

3107
        ecore_imf_context_retrieve_surrounding_callback_set(en->imf_context,
3108
                                                            _edje_entry_imf_retrieve_surrounding_cb, ed);
3109
        ecore_imf_context_retrieve_selection_callback_set(en->imf_context, _edje_entry_imf_retrieve_selection_cb, ed);
3110
        ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb, ed);
3111
        ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb, ed);
3112
        ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb, ed);
3113
        ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_SELECTION_SET, _edje_entry_imf_event_selection_set_cb, ed);
3114
        ecore_imf_context_input_mode_set(en->imf_context,
3115
                                         rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD ?
3116
                                         ECORE_IMF_INPUT_MODE_INVISIBLE : ECORE_IMF_INPUT_MODE_FULL);
3117

3118
        if (rp->part->multiline)
3119
          ecore_imf_context_input_hint_set(en->imf_context,
3120
                                           ecore_imf_context_input_hint_get(en->imf_context) | ECORE_IMF_INPUT_HINT_MULTILINE);
3121

3122
        if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
3123
          ecore_imf_context_input_panel_language_set(en->imf_context, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
3124
#endif
3125
     }
3126
#ifdef HAVE_ECORE_IMF
3127
done:
3128
#endif
3129
   en->cursor = (Evas_Textblock_Cursor *)evas_object_textblock_cursor_get(rp->object);
3130
}
3131

3132
void
3133
_edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part *rp)
3134
{
3135
   Entry *en;
3136

3137
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3138
       (!rp->typedata.text)) return;
3139
   en = rp->typedata.text->entry_data;
3140
   if (!en) return;
3141
   rp->typedata.text->entry_data = NULL;
3142
   _sel_clear(ed, en->cursor, rp->object, en);
3143
   _anchors_clear(en->cursor, rp->object, en);
3144
   _unused_item_objs_free(en);
3145
#ifdef HAVE_ECORE_IMF
3146
   _preedit_clear(en);
3147
#endif
3148
   evas_object_del(en->cursor_bg);
3149
   evas_object_del(en->cursor_fg);
3150
   evas_object_del(en->cursor_fg2);
3151

3152
   if (en->cursor_user)
3153
     evas_textblock_cursor_free(en->cursor_user);
3154

3155
   if (en->cursor_user_extra)
3156
     evas_textblock_cursor_free(en->cursor_user_extra);
3157

3158
   if (en->pw_timer)
3159
     {
3160
        ecore_timer_del(en->pw_timer);
3161
        en->pw_timer = NULL;
3162
     }
3163

3164
   evas_event_callback_del_full(ed->base.evas, EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE, _canvas_viewport_resize_cb, rp);
3165

3166
#ifdef HAVE_ECORE_IMF
3167
   if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
3168
     {
3169
        if (en->imf_context)
3170
          {
3171
             ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _edje_entry_imf_event_commit_cb);
3172
             ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, _edje_entry_imf_event_delete_surrounding_cb);
3173
             ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, _edje_entry_imf_event_preedit_changed_cb);
3174
             ecore_imf_context_event_callback_del(en->imf_context, ECORE_IMF_CALLBACK_SELECTION_SET, _edje_entry_imf_event_selection_set_cb);
3175

3176
             ecore_imf_context_del(en->imf_context);
3177
             en->imf_context = NULL;
3178
          }
3179

3180
        edje_object_signal_callback_del(ed->obj, "focus,part,in,*",
3181
                                        rp->part->name,
3182
                                        _edje_entry_focus_in_cb);
3183
        edje_object_signal_callback_del(ed->obj, "focus,part,out,*",
3184
                                        rp->part->name,
3185
                                        _edje_entry_focus_out_cb);
3186
     }
3187
#endif
3188
   _compose_seq_reset(en);
3189

3190
   free(en);
3191
}
3192

3193
void
3194
_edje_entry_real_part_configure(Edje *ed, Edje_Real_Part *rp)
3195
{
3196
   Evas_Coord x, y, w, h, xx, yy, ww, hh, xx2, yy2;
3197
   Entry *en;
3198
   Evas_Textblock_Cursor_Type cur_type;
3199
   Eina_Bool bidi_cursor = EINA_FALSE;
3200

3201
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3202
       (!rp->typedata.text)) return;
3203
   en = rp->typedata.text->entry_data;
3204
   if (!en) return;
3205

3206
   _sel_update(ed, en->cursor, rp->object, en);
3207
   _anchors_update_check(ed, rp);
3208
   if (rp->part->entry_mode >= EDJE_ENTRY_EDIT_MODE_EDITABLE)
3209
     {
3210
        switch (rp->part->cursor_mode)
3211
         {
3212
           case EDJE_ENTRY_CURSOR_MODE_BEFORE:
3213
              cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
3214
            break;
3215

3216
           case EDJE_ENTRY_CURSOR_MODE_UNDER:
3217
          /* no break for a reason */
3218
           default:
3219
             cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
3220
         }
3221
        x = y = w = h = -1;
3222
        xx = yy = ww = hh = -1;
3223
        evas_object_geometry_get(rp->object, &x, &y, &w, &h);
3224
        bidi_cursor = evas_textblock_cursor_geometry_bidi_get(en->cursor, &xx, &yy, &ww, &hh, &xx2, &yy2, NULL, NULL, cur_type);
3225
        if (ww < 1) ww = 1;
3226
        if (hh < 1) hh = 1;
3227
        if (en->cursor_bg)
3228
          {
3229
             int bg_w = ww;
3230

3231
             if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
3232
               edje_object_size_min_restricted_calc(en->cursor_bg, &bg_w, NULL, ww, 0);
3233

3234
             evas_object_move(en->cursor_bg, x + xx, y + yy);
3235
             evas_object_resize(en->cursor_bg, bg_w, hh);
3236
          }
3237
        if (en->cursor_fg)
3238
          {
3239
             int fg_w = ww;
3240

3241
             if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
3242
               edje_object_size_min_restricted_calc(en->cursor_fg, &fg_w, NULL, ww, 0);
3243

3244
             evas_object_move(en->cursor_fg, x + xx, y + yy);
3245

3246
             if (bidi_cursor)
3247
               {
3248
                  if (en->cursor_fg2)
3249
                    {
3250
                       evas_object_move(en->cursor_fg2, x + xx2, y + yy2 + (hh / 2));
3251
                       evas_object_resize(en->cursor_fg, fg_w, hh / 2);
3252
                       evas_object_resize(en->cursor_fg2, fg_w, hh / 2);
3253
                       evas_object_show(en->cursor_fg2);
3254
                    }
3255
               }
3256
             else
3257
               {
3258
                  evas_object_resize(en->cursor_fg, fg_w, hh);
3259
                  if (en->cursor_fg2)
3260
                    evas_object_hide(en->cursor_fg2);
3261
               }
3262
          }
3263
     }
3264
}
3265

3266
const char *
3267
_edje_entry_selection_get(Edje_Real_Part *rp)
3268
{
3269
   Entry *en;
3270

3271
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3272
       (!rp->typedata.text)) return NULL;
3273
   en = rp->typedata.text->entry_data;
3274
   if (!en) return NULL;
3275
   // get selection - convert to markup
3276
   if ((!en->selection) && (en->have_selection))
3277
     en->selection = evas_textblock_cursor_range_text_get
3278
         (en->sel_start, en->sel_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
3279
   return en->selection;
3280
}
3281

3282
const char *
3283
_edje_entry_text_get(Edje_Real_Part *rp)
3284
{
3285
   Entry *en;
3286

3287
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3288
       (!rp->typedata.text)) return NULL;
3289
   en = rp->typedata.text->entry_data;
3290
   if (!en) return NULL;
3291
   // get text - convert to markup
3292
   return evas_object_textblock_text_markup_get(rp->object);
3293
}
3294

3295
void
3296
_edje_entry_text_markup_set(Edje_Real_Part *rp, const char *text)
3297
{
3298
   Entry *en;
3299
   const char *ptext;
3300

3301
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3302
       (!rp->typedata.text)) return;
3303
   en = rp->typedata.text->entry_data;
3304
   if (!en) return;
3305
   ptext = evas_object_textblock_text_markup_get(rp->object);
3306
   // some simple "do nothing if the text is the same" logic
3307
   if (ptext == text) return;
3308
   // if prev and cur is empty
3309
   if (!ptext) ptext = "";
3310
   if (!text) text = "";
3311
   if ((!ptext[0]) && (!text[0])) return;
3312
   // same content
3313
   if (!strcmp(ptext, text)) return;
3314

3315
   _edje_entry_imf_context_reset(rp);
3316
   // set text as markup
3317
   _sel_clear(en->ed, en->cursor, rp->object, en);
3318
   evas_object_textblock_text_markup_set(rp->object, text);
3319
   _edje_entry_set_cursor_start(rp);
3320

3321
   _anchors_get(en->cursor, rp->object, en);
3322
   _edje_emit(en->ed, "entry,changed", rp->part->name);
3323
   _edje_entry_imf_cursor_info_set(en);
3324

3325
   _edje_entry_real_part_configure(en->ed, rp);
3326
#if 0
3327
   /* Don't emit cursor changed cause it didn't. It's just init to 0. */
3328
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
3329
#endif
3330
}
3331

3332
void
3333
_edje_entry_text_markup_append(Edje_Real_Part *rp, const char *text)
3334
{
3335
   Entry *en;
3336

3337
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3338
       (!rp->typedata.text)) return;
3339
   en = rp->typedata.text->entry_data;
3340
   Evas_Textblock_Cursor *end_cur;
3341
   if (!en) return;
3342
   end_cur = evas_object_textblock_cursor_new(rp->object);
3343
   evas_textblock_cursor_paragraph_last(end_cur);
3344

3345
   _text_filter_markup_prepend(en->ed, en, end_cur, text, NULL, NULL,
3346
                               EINA_TRUE, EINA_FALSE);
3347
   evas_textblock_cursor_free(end_cur);
3348

3349
   /* We are updating according to the real cursor on purpose */
3350
   _anchors_get(en->cursor, rp->object, en);
3351
   _edje_emit(en->ed, "entry,changed", rp->part->name);
3352

3353
   _edje_entry_real_part_configure(en->ed, rp);
3354
}
3355

3356
void
3357
_edje_entry_text_markup_insert(Edje_Real_Part *rp, const char *text)
3358
{
3359
   Entry *en;
3360

3361
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3362
       (!rp->typedata.text)) return;
3363
   en = rp->typedata.text->entry_data;
3364
   if (!en) return;
3365
   _edje_entry_imf_context_reset(rp);
3366

3367
   _text_filter_markup_prepend(en->ed, en, en->cursor, text, NULL, NULL,
3368
                               EINA_TRUE, EINA_FALSE);
3369
   _anchors_get(en->cursor, rp->object, en);
3370
   _edje_emit(en->ed, "entry,changed", rp->part->name);
3371
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
3372

3373
   _edje_entry_imf_cursor_info_set(en);
3374
   _edje_entry_real_part_configure(en->ed, rp);
3375
}
3376

3377
void
3378
_edje_entry_set_cursor_start(Edje_Real_Part *rp)
3379
{
3380
   Entry *en;
3381

3382
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3383
       (!rp->typedata.text)) return;
3384
   en = rp->typedata.text->entry_data;
3385
   if (!en) return;
3386
   _curs_start(en->cursor, rp->object, en);
3387

3388
   _edje_entry_imf_cursor_info_set(en);
3389
}
3390

3391
void
3392
_edje_entry_set_cursor_end(Edje_Real_Part *rp)
3393
{
3394
   Entry *en;
3395

3396
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3397
       (!rp->typedata.text)) return;
3398
   en = rp->typedata.text->entry_data;
3399
   if (!en) return;
3400
   _curs_end(en->cursor, rp->object, en);
3401

3402
   _edje_entry_imf_cursor_info_set(en);
3403
}
3404

3405
void
3406
_edje_entry_select_none(Edje_Real_Part *rp)
3407
{
3408
   Entry *en;
3409

3410
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3411
       (!rp->typedata.text)) return;
3412
   en = rp->typedata.text->entry_data;
3413
   if (!en) return;
3414
   _sel_clear(en->ed, en->cursor, rp->object, en);
3415
}
3416

3417
void
3418
_edje_entry_select_all(Edje_Real_Part *rp)
3419
{
3420
   Entry *en;
3421

3422
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3423
       (!rp->typedata.text)) return;
3424
   en = rp->typedata.text->entry_data;
3425
   if (!en) return;
3426

3427
   _edje_entry_imf_context_reset(rp);
3428

3429
   _sel_clear(en->ed, en->cursor, rp->object, en);
3430
   _curs_start(en->cursor, rp->object, en);
3431
   _edje_entry_imf_context_reset(en->rp);
3432
   _sel_start(en->cursor, rp->object, en);
3433
   _curs_end(en->cursor, rp->object, en);
3434
   _sel_extend(en->ed, en->cursor, rp->object, en);
3435

3436
   _edje_entry_real_part_configure(en->ed, rp);
3437
}
3438

3439
void
3440
_edje_entry_select_begin(Edje_Real_Part *rp)
3441
{
3442
   Entry *en;
3443

3444
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3445
       (!rp->typedata.text)) return;
3446
   en = rp->typedata.text->entry_data;
3447
   if (!en) return;
3448

3449
   _sel_clear(en->ed, en->cursor, rp->object, en);
3450
   _sel_enable(en->ed, en->cursor, rp->object, en);
3451
   _sel_start(en->cursor, rp->object, en);
3452
   _sel_extend(en->ed, en->cursor, rp->object, en);
3453

3454
   _edje_entry_real_part_configure(en->ed, rp);
3455
}
3456

3457
void
3458
_edje_entry_select_extend(Edje_Real_Part *rp)
3459
{
3460
   Entry *en;
3461

3462
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3463
       (!rp->typedata.text)) return;
3464
   en = rp->typedata.text->entry_data;
3465
   if (!en) return;
3466
   _sel_extend(en->ed, en->cursor, rp->object, en);
3467

3468
   _edje_entry_real_part_configure(en->ed, rp);
3469
}
3470

3471
const Eina_List *
3472
_edje_entry_anchor_geometry_get(Edje_Real_Part *rp, const char *anchor)
3473
{
3474
   Entry *en;
3475
   Eina_List *l;
3476
   Anchor *an;
3477

3478
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3479
       (!rp->typedata.text)) return NULL;
3480
   en = rp->typedata.text->entry_data;
3481
   if (!en) return NULL;
3482
   /* Update the anchors first in case entry is not inside the canvas
3483
    * viewport */
3484
   _anchors_need_update(rp);
3485
   EINA_LIST_FOREACH(en->anchors, l, an)
3486
     {
3487
        const char *n = an->name;
3488
        if ((an->item) || (!n)) continue;
3489
        if (!strcmp(anchor, n))
3490
          return an->sel;
3491
     }
3492
   return NULL;
3493
}
3494

3495
const Eina_List *
3496
_edje_entry_anchors_list(Edje_Real_Part *rp)
3497
{
3498
   Entry *en;
3499
   Eina_List *l, *anchors = NULL;
3500
   Anchor *an;
3501

3502
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3503
       (!rp->typedata.text)) return NULL;
3504
   en = rp->typedata.text->entry_data;
3505
   if (!en) return NULL;
3506
   /* Update the anchors first in case entry is not inside the canvas
3507
    * viewport */
3508
   _anchors_need_update(rp);
3509
   if (!en->anchorlist)
3510
     {
3511
        EINA_LIST_FOREACH(en->anchors, l, an)
3512
          {
3513
             const char *n = an->name;
3514
             if ((an->item) || (!n)) continue;
3515
             anchors = eina_list_append(anchors, strdup(n));
3516
          }
3517
        en->anchorlist = anchors;
3518
     }
3519
   return en->anchorlist;
3520
}
3521

3522
Eina_Bool
3523
_edje_entry_item_geometry_get(Edje_Real_Part *rp, const char *item, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
3524
{
3525
   Entry *en;
3526
   Eina_List *l;
3527
   Anchor *an;
3528

3529
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3530
       (!rp->typedata.text)) return EINA_FALSE;
3531
   en = rp->typedata.text->entry_data;
3532
   if (!en) return EINA_FALSE;
3533
   EINA_LIST_FOREACH(en->anchors, l, an)
3534
     {
3535
        const char *n = an->name;
3536
        if (!an->item) continue;
3537
        if (!n) n = "";
3538
        if (!strcmp(item, n))
3539
          {
3540
             evas_textblock_cursor_format_item_geometry_get(an->start, cx, cy, cw, ch);
3541
             return EINA_TRUE;
3542
          }
3543
     }
3544
   return EINA_FALSE;
3545
}
3546

3547
const Eina_List *
3548
_edje_entry_items_list(Edje_Real_Part *rp)
3549
{
3550
   Entry *en;
3551
   Eina_List *l, *items = NULL;
3552
   Anchor *an;
3553

3554
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3555
       (!rp->typedata.text)) return NULL;
3556
   en = rp->typedata.text->entry_data;
3557
   if (!en) return NULL;
3558
   /* Update the anchors first in case entry is not inside the canvas
3559
    * viewport */
3560
   _anchors_need_update(rp);
3561
   if (!en->itemlist)
3562
     {
3563
        EINA_LIST_FOREACH(en->anchors, l, an)
3564
          {
3565
             const char *n = an->name;
3566
             if (!an->item) continue;
3567
             if (!n) n = "";
3568
             items = eina_list_append(items, strdup(n));
3569
          }
3570
        en->itemlist = items;
3571
     }
3572
   return en->itemlist;
3573
}
3574

3575
void
3576
_edje_entry_cursor_geometry_get(Edje_Real_Part *rp, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_BiDi_Direction *cdir)
3577
{
3578
   Evas_Coord x, y, w, h, xx, yy, ww, hh;
3579
   Entry *en;
3580
   Evas_Textblock_Cursor_Type cur_type;
3581
   Evas_BiDi_Direction dir;
3582

3583
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3584
       (!rp->typedata.text)) return;
3585
   en = rp->typedata.text->entry_data;
3586
   if (!en) return;
3587
   switch (rp->part->cursor_mode)
3588
     {
3589
      case EDJE_ENTRY_CURSOR_MODE_BEFORE:
3590
        cur_type = EVAS_TEXTBLOCK_CURSOR_BEFORE;
3591
        break;
3592

3593
      case EDJE_ENTRY_CURSOR_MODE_UNDER:
3594
      /* no break for a reason */
3595
      default:
3596
        cur_type = EVAS_TEXTBLOCK_CURSOR_UNDER;
3597
     }
3598

3599
   x = y = w = h = -1;
3600
   xx = yy = ww = hh = -1;
3601
   evas_object_geometry_get(rp->object, &x, &y, &w, &h);
3602
   evas_textblock_cursor_geometry_get(en->cursor, &xx, &yy, &ww, &hh, &dir, cur_type);
3603
   if (ww < 1) ww = 1;
3604
   if (rp->part->cursor_mode == EDJE_ENTRY_CURSOR_MODE_BEFORE)
3605
     edje_object_size_min_restricted_calc(en->cursor_fg, &ww, NULL, ww, 0);
3606
   if (hh < 1) hh = 1;
3607
   if (cx) *cx = x + xx;
3608
   if (cy) *cy = y + yy;
3609
   if (cw) *cw = ww;
3610
   if (ch) *ch = hh;
3611
   if (cdir) *cdir = dir;
3612
}
3613

3614
void
3615
_edje_entry_user_insert(Edje_Real_Part *rp, const char *text)
3616
{
3617
   Entry *en;
3618
   Edje_Entry_Change_Info *info;
3619

3620
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3621
       (!rp->typedata.text)) return;
3622
   en = rp->typedata.text->entry_data;
3623
   if (!en) return;
3624
   _edje_entry_imf_context_reset(rp);
3625
   info = _text_filter_markup_prepend(en->ed, en, en->cursor, text, NULL, NULL,
3626
                                      EINA_TRUE, EINA_TRUE);
3627
   _anchors_get(en->cursor, rp->object, en);
3628
   if (info)
3629
     {
3630
        _edje_emit(en->ed, "entry,changed", rp->part->name);
3631
        _edje_emit_full(en->ed, "entry,changed,user", rp->part->name,
3632
                        info, _free_entry_change_info);
3633
        _edje_emit(en->ed, "cursor,changed", rp->part->name);
3634
     }
3635

3636
   _edje_entry_imf_cursor_info_set(en);
3637
   _edje_entry_real_part_configure(en->ed, rp);
3638
}
3639

3640
void
3641
_edje_entry_select_allow_set(Edje_Real_Part *rp, Eina_Bool allow)
3642
{
3643
   Entry *en;
3644

3645
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3646
       (!rp->typedata.text)) return;
3647
   en = rp->typedata.text->entry_data;
3648
   if (!en) return;
3649

3650
   en->select_allow = allow;
3651
}
3652

3653
Eina_Bool
3654
_edje_entry_select_allow_get(const Edje_Real_Part *rp)
3655
{
3656
   Entry *en;
3657

3658
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3659
       (!rp->typedata.text)) return EINA_FALSE;
3660
   en = rp->typedata.text->entry_data;
3661
   if (!en) return EINA_FALSE;
3662
   return en->select_allow;
3663
}
3664

3665
void
3666
_edje_entry_select_abort(Edje_Real_Part *rp)
3667
{
3668
   Entry *en;
3669

3670
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3671
       (!rp->typedata.text)) return;
3672
   en = rp->typedata.text->entry_data;
3673
   if (!en) return;
3674
   if (en->selecting)
3675
     {
3676
        en->selecting = EINA_FALSE;
3677

3678
        _edje_entry_imf_context_reset(rp);
3679
        _edje_entry_imf_cursor_info_set(en);
3680
        _edje_entry_real_part_configure(en->ed, rp);
3681
     }
3682
}
3683

3684
void *
3685
_edje_entry_imf_context_get(Edje_Real_Part *rp)
3686
{
3687
#ifdef HAVE_ECORE_IMF
3688
   Entry *en;
3689

3690
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3691
       (!rp->typedata.text)) return NULL;
3692
   en = rp->typedata.text->entry_data;
3693
   if (!en) return NULL;
3694

3695
   return en->imf_context;
3696
#else
3697
   return NULL;
3698
   (void)rp;
3699
#endif
3700
}
3701

3702
void
3703
_edje_entry_autocapital_type_set(Edje_Real_Part *rp, Edje_Text_Autocapital_Type autocapital_type)
3704
{
3705
#ifdef HAVE_ECORE_IMF
3706
   Entry *en;
3707

3708
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3709
       (!rp->typedata.text)) return;
3710
   en = rp->typedata.text->entry_data;
3711
   if (!en) return;
3712

3713
   if (rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD)
3714
     autocapital_type = EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3715

3716
   if (en->imf_context)
3717
     ecore_imf_context_autocapital_type_set(en->imf_context, (Ecore_IMF_Autocapital_Type)autocapital_type);
3718
#else
3719
   (void)rp;
3720
   (void)autocapital_type;
3721
#endif
3722
}
3723

3724
Edje_Text_Autocapital_Type
3725
_edje_entry_autocapital_type_get(Edje_Real_Part *rp)
3726
{
3727
#ifdef HAVE_ECORE_IMF
3728
   Entry *en;
3729

3730
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3731
       (!rp->typedata.text)) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3732
   en = rp->typedata.text->entry_data;
3733
   if (!en) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3734

3735
   if (en->imf_context)
3736
     return (Edje_Text_Autocapital_Type)ecore_imf_context_autocapital_type_get(en->imf_context);
3737
   return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3738
#else
3739
   return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
3740
   (void)rp;
3741
#endif
3742
}
3743

3744
void
3745
_edje_entry_prediction_allow_set(Edje_Real_Part *rp, Eina_Bool prediction)
3746
{
3747
   Entry *en;
3748

3749
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3750
       (!rp->typedata.text)) return;
3751
   en = rp->typedata.text->entry_data;
3752
   if (!en) return;
3753
   en->prediction_allow = prediction;
3754
#ifdef HAVE_ECORE_IMF
3755
   if (en->imf_context)
3756
     ecore_imf_context_prediction_allow_set(en->imf_context, prediction);
3757
#endif
3758
}
3759

3760
Eina_Bool
3761
_edje_entry_prediction_allow_get(Edje_Real_Part *rp)
3762
{
3763
   Entry *en;
3764

3765
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3766
       (!rp->typedata.text)) return EINA_FALSE;
3767
   en = rp->typedata.text->entry_data;
3768
   if (!en) return EINA_FALSE;
3769
   return en->prediction_allow;
3770
}
3771

3772
void
3773
_edje_entry_input_hint_set(Edje_Real_Part *rp, Edje_Input_Hints input_hints)
3774
{
3775
   Entry *en;
3776

3777
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3778
       (!rp->typedata.text)) return;
3779
   en = rp->typedata.text->entry_data;
3780
   if (!en) return;
3781
#ifdef HAVE_ECORE_IMF
3782
   if (en->imf_context)
3783
     ecore_imf_context_input_hint_set(en->imf_context, (Ecore_IMF_Input_Hints)input_hints);
3784
#else
3785
   (void)input_hints;
3786
#endif
3787
}
3788

3789
Edje_Input_Hints
3790
_edje_entry_input_hint_get(const Edje_Real_Part *rp)
3791
{
3792
   Entry *en;
3793

3794
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3795
       (!rp->typedata.text)) return EDJE_INPUT_HINT_NONE;
3796
   en = rp->typedata.text->entry_data;
3797
   if (!en) return EDJE_INPUT_HINT_NONE;
3798
#ifdef HAVE_ECORE_IMF
3799
   if (en->imf_context)
3800
     return (Edje_Input_Hints)ecore_imf_context_input_hint_get(en->imf_context);
3801
#endif
3802

3803
   return EDJE_INPUT_HINT_NONE;
3804
}
3805

3806
void
3807
_edje_entry_input_panel_enabled_set(Edje_Real_Part *rp, Eina_Bool enabled)
3808
{
3809
   Entry *en;
3810

3811
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3812
       (!rp->typedata.text)) return;
3813
   en = rp->typedata.text->entry_data;
3814
   if (!en) return;
3815
   en->input_panel_enable = enabled;
3816
#ifdef HAVE_ECORE_IMF
3817
   if (en->imf_context)
3818
     ecore_imf_context_input_panel_enabled_set(en->imf_context, enabled);
3819
#endif
3820
}
3821

3822
Eina_Bool
3823
_edje_entry_input_panel_enabled_get(Edje_Real_Part *rp)
3824
{
3825
   Entry *en;
3826

3827
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3828
       (!rp->typedata.text)) return EINA_FALSE;
3829
   en = rp->typedata.text->entry_data;
3830
   if (!en) return EINA_FALSE;
3831
   return en->input_panel_enable;
3832
}
3833

3834
void
3835
_edje_entry_input_panel_show(Edje_Real_Part *rp)
3836
{
3837
#ifdef HAVE_ECORE_IMF
3838
   Entry *en;
3839

3840
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3841
       (!rp->typedata.text)) return;
3842
   en = rp->typedata.text->entry_data;
3843
   if (!en) return;
3844
   if (en->imf_context)
3845
     ecore_imf_context_input_panel_show(en->imf_context);
3846
#else
3847
   (void)rp;
3848
#endif
3849
}
3850

3851
void
3852
_edje_entry_input_panel_hide(Edje_Real_Part *rp)
3853
{
3854
#ifdef HAVE_ECORE_IMF
3855
   Entry *en;
3856

3857
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3858
       (!rp->typedata.text)) return;
3859
   en = rp->typedata.text->entry_data;
3860
   if (!en) return;
3861
   if (en->imf_context)
3862
     ecore_imf_context_input_panel_hide(en->imf_context);
3863
#else
3864
   (void)rp;
3865
#endif
3866
}
3867

3868
void
3869
_edje_entry_input_panel_language_set(Edje_Real_Part *rp, Edje_Input_Panel_Lang lang)
3870
{
3871
   Entry *en;
3872

3873
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3874
       (!rp->typedata.text)) return;
3875
   en = rp->typedata.text->entry_data;
3876
   if (!en) return;
3877
   en->input_panel_lang = lang;
3878
#ifdef HAVE_ECORE_IMF
3879
   if (en->imf_context)
3880
     ecore_imf_context_input_panel_language_set(en->imf_context, (Ecore_IMF_Input_Panel_Lang)lang);
3881
#endif
3882
}
3883

3884
Edje_Input_Panel_Lang
3885
_edje_entry_input_panel_language_get(Edje_Real_Part *rp)
3886
{
3887
   Entry *en;
3888

3889
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3890
       (!rp->typedata.text)) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
3891
   en = rp->typedata.text->entry_data;
3892
   if (!en) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
3893
   return en->input_panel_lang;
3894
}
3895

3896
void
3897
_edje_entry_input_panel_imdata_set(Edje_Real_Part *rp, const void *data, int len)
3898
{
3899
#ifdef HAVE_ECORE_IMF
3900
   Entry *en;
3901

3902
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3903
       (!rp->typedata.text)) return;
3904
   en = rp->typedata.text->entry_data;
3905
   if (!en) return;
3906
   if (en->imf_context)
3907
     ecore_imf_context_input_panel_imdata_set(en->imf_context, data, len);
3908
#else
3909
   (void)rp;
3910
   (void)data;
3911
   (void)len;
3912
#endif
3913
}
3914

3915
void
3916
_edje_entry_input_panel_imdata_get(Edje_Real_Part *rp, void *data, int *len)
3917
{
3918
#ifdef HAVE_ECORE_IMF
3919
   Entry *en;
3920

3921
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3922
       (!rp->typedata.text)) return;
3923
   en = rp->typedata.text->entry_data;
3924
   if (!en) return;
3925
   if (en->imf_context)
3926
     ecore_imf_context_input_panel_imdata_get(en->imf_context, data, len);
3927
#else
3928
   (void)rp;
3929
   (void)data;
3930
   (void)len;
3931
#endif
3932
}
3933

3934
void
3935
_edje_entry_input_panel_return_key_type_set(Edje_Real_Part *rp, Edje_Input_Panel_Return_Key_Type return_key_type)
3936
{
3937
#ifdef HAVE_ECORE_IMF
3938
   Entry *en;
3939

3940
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3941
       (!rp->typedata.text)) return;
3942
   en = rp->typedata.text->entry_data;
3943
   if (!en) return;
3944
   if (en->imf_context)
3945
     ecore_imf_context_input_panel_return_key_type_set(en->imf_context, (Ecore_IMF_Input_Panel_Return_Key_Type)return_key_type);
3946
#else
3947
   (void)rp;
3948
   (void)return_key_type;
3949
#endif
3950
}
3951

3952
Edje_Input_Panel_Return_Key_Type
3953
_edje_entry_input_panel_return_key_type_get(Edje_Real_Part *rp)
3954
{
3955
#ifdef HAVE_ECORE_IMF
3956
   Entry *en;
3957

3958
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3959
       (!rp->typedata.text)) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3960
   en = rp->typedata.text->entry_data;
3961
   if (!en) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3962
   if (en->imf_context)
3963
     return (Edje_Input_Panel_Return_Key_Type)ecore_imf_context_input_panel_return_key_type_get(en->imf_context);
3964
   return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3965
#else
3966
   return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3967
   (void)rp;
3968
#endif
3969
}
3970

3971
void
3972
_edje_entry_input_panel_return_key_disabled_set(Edje_Real_Part *rp, Eina_Bool disabled)
3973
{
3974
#ifdef HAVE_ECORE_IMF
3975
   Entry *en;
3976

3977
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3978
       (!rp->typedata.text)) return;
3979
   en = rp->typedata.text->entry_data;
3980
   if (!en) return;
3981
   if (en->imf_context)
3982
     ecore_imf_context_input_panel_return_key_disabled_set(en->imf_context, disabled);
3983
#else
3984
   (void)rp;
3985
   (void)disabled;
3986
#endif
3987
}
3988

3989
Eina_Bool
3990
_edje_entry_input_panel_return_key_disabled_get(Edje_Real_Part *rp)
3991
{
3992
#ifdef HAVE_ECORE_IMF
3993
   Entry *en;
3994

3995
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
3996
       (!rp->typedata.text)) return EINA_FALSE;
3997
   en = rp->typedata.text->entry_data;
3998
   if (!en) return EINA_FALSE;
3999
   if (en->imf_context)
4000
     return ecore_imf_context_input_panel_return_key_disabled_get(en->imf_context);
4001
   return EINA_FALSE;
4002
#else
4003
   return EINA_FALSE;
4004
   (void)rp;
4005
#endif
4006
}
4007

4008
#ifdef HAVE_ECORE_IMF
4009
void
4010
_edje_entry_input_panel_show_on_demand_set(Edje_Real_Part *rp, Eina_Bool ondemand)
4011
#else
4012
void
4013
_edje_entry_input_panel_show_on_demand_set(Edje_Real_Part *rp, Eina_Bool ondemand EINA_UNUSED)
4014
#endif
4015
{
4016
   Entry *en;
4017

4018
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4019
       (!rp->typedata.text)) return;
4020
   en = rp->typedata.text->entry_data;
4021
   if (!en) return;
4022
#ifdef HAVE_ECORE_IMF
4023
   if (en->imf_context)
4024
     ecore_imf_context_input_panel_show_on_demand_set(en->imf_context, ondemand);
4025
#endif
4026
}
4027

4028
Eina_Bool
4029
_edje_entry_input_panel_show_on_demand_get(Edje_Real_Part *rp)
4030
{
4031
   Entry *en;
4032

4033
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4034
       (!rp->typedata.text)) return EINA_FALSE;
4035
   en = rp->typedata.text->entry_data;
4036
   if (!en) return EINA_FALSE;
4037
#ifdef HAVE_ECORE_IMF
4038
   if (en->imf_context)
4039
     {
4040
        Eina_Bool ret = ecore_imf_context_input_panel_show_on_demand_get(en->imf_context);
4041
        return ret;
4042
     }
4043
#endif
4044
   return EINA_FALSE;
4045
}
4046

4047
static Evas_Textblock_Cursor *
4048
_cursor_get(Edje_Real_Part *rp, Edje_Cursor cur)
4049
{
4050
   Entry *en;
4051

4052
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4053
       (!rp->typedata.text)) return NULL;
4054
   en = rp->typedata.text->entry_data;
4055
   if (!en) return NULL;
4056
   switch (cur)
4057
     {
4058
      case EDJE_CURSOR_MAIN:
4059
        return en->cursor;
4060

4061
      case EDJE_CURSOR_SELECTION_BEGIN:
4062
        return en->sel_start;
4063

4064
      case EDJE_CURSOR_SELECTION_END:
4065
        return en->sel_end;
4066

4067
      case EDJE_CURSOR_PREEDIT_START:
4068
        if (!en->preedit_start)
4069
          en->preedit_start = evas_object_textblock_cursor_new(rp->object);
4070
        return en->preedit_start;
4071

4072
      case EDJE_CURSOR_PREEDIT_END:
4073
        if (!en->preedit_end)
4074
          en->preedit_end = evas_object_textblock_cursor_new(rp->object);
4075
        return en->preedit_end;
4076

4077
      case EDJE_CURSOR_USER:
4078
        if (!en->cursor_user)
4079
          en->cursor_user = evas_object_textblock_cursor_new(rp->object);
4080
        return en->cursor_user;
4081

4082
      case EDJE_CURSOR_USER_EXTRA:
4083
        if (!en->cursor_user_extra)
4084
          en->cursor_user_extra = evas_object_textblock_cursor_new(rp->object);
4085
        return en->cursor_user_extra;
4086

4087
      default:
4088
        break;
4089
     }
4090
   return NULL;
4091
}
4092

4093
Eina_Bool
4094
_edje_text_cursor_next(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4095
{
4096
   Entry *en;
4097

4098
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4099
       (!rp->typedata.text)) return EINA_FALSE;
4100
   en = rp->typedata.text->entry_data;
4101
   if (!en) return EINA_FALSE;
4102

4103
   if (!c) return EINA_FALSE;
4104

4105
   _edje_entry_imf_context_reset(rp);
4106

4107
   if (!evas_textblock_cursor_cluster_next(c))
4108
     {
4109
        return EINA_FALSE;
4110
     }
4111
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4112
   _edje_entry_imf_cursor_info_set(en);
4113

4114
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4115
   _edje_entry_real_part_configure(en->ed, rp);
4116
   return EINA_TRUE;
4117
}
4118

4119
Eina_Bool
4120
_edje_entry_cursor_next(Edje_Real_Part *rp, Edje_Cursor cur)
4121
{
4122
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4123
   return _edje_text_cursor_next(rp, c);
4124
}
4125

4126

4127
Eina_Bool
4128
_edje_text_cursor_prev(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4129
{
4130
   Entry *en;
4131

4132
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4133
       (!rp->typedata.text)) return EINA_FALSE;
4134
   en = rp->typedata.text->entry_data;
4135
   if (!en) return EINA_FALSE;
4136
   if (!c) return EINA_FALSE;
4137

4138
   _edje_entry_imf_context_reset(rp);
4139

4140
   if (!evas_textblock_cursor_cluster_prev(c))
4141
     {
4142
        if (evas_textblock_cursor_paragraph_prev(c)) goto ok;
4143
        else return EINA_FALSE;
4144
     }
4145
ok:
4146
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4147

4148
   _edje_entry_imf_cursor_info_set(en);
4149

4150
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4151
   _edje_entry_real_part_configure(en->ed, rp);
4152
   return EINA_TRUE;
4153
}
4154

4155
Eina_Bool
4156
_edje_entry_cursor_prev(Edje_Real_Part *rp, Edje_Cursor cur)
4157
{
4158
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4159
   return _edje_text_cursor_prev(rp, c);
4160
}
4161

4162
Eina_Bool
4163
_edje_text_cursor_up(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4164
{
4165
   Entry *en;
4166
   Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
4167
   int ln;
4168

4169
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4170
       (!rp->typedata.text)) return EINA_FALSE;
4171
   en = rp->typedata.text->entry_data;
4172
   if (!en) return EINA_FALSE;
4173
   if (!c) return EINA_FALSE;
4174

4175
   _edje_entry_imf_context_reset(rp);
4176

4177
   ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
4178
   ln--;
4179
   if (ln < 0) return EINA_FALSE;
4180
   if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
4181
                                                       &lx, &ly, &lw, &lh))
4182
     return EINA_FALSE;
4183
   evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
4184
   if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
4185
     evas_textblock_cursor_line_char_last(c);
4186
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4187

4188
   _edje_entry_imf_cursor_info_set(en);
4189

4190
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4191
   _edje_entry_real_part_configure(en->ed, rp);
4192
   return EINA_TRUE;
4193
}
4194

4195
Eina_Bool
4196
_edje_entry_cursor_up(Edje_Real_Part *rp, Edje_Cursor cur)
4197
{
4198
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4199
   return _edje_text_cursor_up(rp, c);
4200
}
4201

4202
Eina_Bool
4203
_edje_text_cursor_down(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4204
{
4205
   Entry *en;
4206
   Evas_Coord lx, ly, lw, lh, cx, cy, cw, ch;
4207
   int ln;
4208

4209
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4210
       (!rp->typedata.text)) return EINA_FALSE;
4211
   en = rp->typedata.text->entry_data;
4212
   if (!en) return EINA_FALSE;
4213
   if (!c) return EINA_FALSE;
4214

4215
   _edje_entry_imf_context_reset(rp);
4216

4217
   ln = evas_textblock_cursor_line_geometry_get(c, NULL, NULL, NULL, NULL);
4218
   ln++;
4219
   if (!evas_object_textblock_line_number_geometry_get(rp->object, ln,
4220
                                                       &lx, &ly, &lw, &lh))
4221
     return EINA_FALSE;
4222
   evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch);
4223
   if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2)))
4224
     evas_textblock_cursor_line_char_last(c);
4225

4226
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4227

4228
   _edje_entry_imf_cursor_info_set(en);
4229
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4230
   _edje_entry_real_part_configure(en->ed, rp);
4231
   return EINA_TRUE;
4232
}
4233

4234
Eina_Bool
4235
_edje_entry_cursor_down(Edje_Real_Part *rp, Edje_Cursor cur)
4236
{
4237
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4238
   return _edje_text_cursor_down(rp, c);
4239
}
4240

4241
void
4242
_edje_text_cursor_begin(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4243
{
4244
   Entry *en;
4245
   int old_cur_pos;
4246

4247
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4248
       (!rp->typedata.text)) return;
4249
   en = rp->typedata.text->entry_data;
4250
   if (!en) return;
4251
   if (!c) return;
4252

4253
   _edje_entry_imf_context_reset(rp);
4254

4255
   old_cur_pos = evas_textblock_cursor_pos_get(c);
4256
   evas_textblock_cursor_paragraph_first(c);
4257

4258
   if (old_cur_pos == evas_textblock_cursor_pos_get(c))
4259
     return;
4260

4261
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4262

4263
   _edje_entry_imf_cursor_info_set(en);
4264
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4265
   _edje_entry_real_part_configure(en->ed, rp);
4266
}
4267

4268
void
4269
_edje_entry_cursor_begin(Edje_Real_Part *rp, Edje_Cursor cur)
4270
{
4271
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4272
   _edje_text_cursor_begin(rp, c);
4273

4274
}
4275

4276
void
4277
_edje_text_cursor_end(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4278
{
4279
   Entry *en;
4280
   int old_cur_pos;
4281

4282
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4283
       (!rp->typedata.text)) return;
4284
   en = rp->typedata.text->entry_data;
4285
   if (!en) return;
4286
   if (!c) return;
4287

4288
   _edje_entry_imf_context_reset(rp);
4289

4290
   old_cur_pos = evas_textblock_cursor_pos_get(c);
4291
   _curs_end(c, rp->object, rp->typedata.text->entry_data);
4292

4293
   if (old_cur_pos == evas_textblock_cursor_pos_get(c))
4294
     return;
4295

4296
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4297

4298
   _edje_entry_imf_cursor_info_set(en);
4299

4300
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4301
   _edje_entry_real_part_configure(en->ed, rp);
4302
}
4303
void
4304
_edje_entry_cursor_end(Edje_Real_Part *rp, Edje_Cursor cur)
4305
{
4306
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4307
   _edje_text_cursor_end(rp, c);
4308
}
4309

4310
void
4311
_edje_text_cursor_copy(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *d, Efl_Text_Cursor_Handle *c)
4312
{
4313
   Entry *en;
4314

4315
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4316
       (!rp->typedata.text)) return;
4317
   en = rp->typedata.text->entry_data;
4318
   if (!en) return;
4319
   evas_textblock_cursor_copy(c, d);
4320
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4321

4322
   _edje_entry_imf_context_reset(rp);
4323
   _edje_entry_imf_cursor_info_set(en);
4324
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4325
   _edje_entry_real_part_configure(en->ed, rp);
4326
}
4327

4328
void
4329
_edje_entry_cursor_copy(Edje_Real_Part *rp, Edje_Cursor cur, Edje_Cursor dst)
4330
{
4331
   Evas_Textblock_Cursor *c;
4332
   Evas_Textblock_Cursor *d;
4333
   c = _cursor_get(rp, cur);
4334
   if (!c) return;
4335
   d = _cursor_get(rp, dst);
4336
   if (!d) return;
4337
   _edje_text_cursor_copy(rp, d, c);
4338
}
4339

4340
void
4341
_edje_text_cursor_line_begin(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4342
{
4343
   Entry *en;
4344
   int old_cur_pos;
4345

4346
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4347
       (!rp->typedata.text)) return;
4348
   en = rp->typedata.text->entry_data;
4349
   if (!en) return;
4350
   if (!c) return;
4351
   _edje_entry_imf_context_reset(rp);
4352

4353
   old_cur_pos = evas_textblock_cursor_pos_get(c);
4354
   evas_textblock_cursor_line_char_first(c);
4355

4356
   if (old_cur_pos == evas_textblock_cursor_pos_get(c))
4357
     return;
4358

4359
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4360

4361
   _edje_entry_imf_cursor_info_set(en);
4362

4363
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4364
   _edje_entry_real_part_configure(en->ed, rp);
4365
}
4366

4367
void
4368
_edje_entry_cursor_line_begin(Edje_Real_Part *rp, Edje_Cursor cur)
4369
{
4370
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4371
   _edje_text_cursor_line_begin(rp, c);
4372
}
4373

4374
void
4375
_edje_text_cursor_line_end(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c)
4376
{
4377
   Entry *en;
4378
   int old_cur_pos;
4379

4380
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4381
       (!rp->typedata.text)) return;
4382
   en = rp->typedata.text->entry_data;
4383
   if (!en) return;
4384
   if (!c) return;
4385
   _edje_entry_imf_context_reset(rp);
4386

4387
   old_cur_pos = evas_textblock_cursor_pos_get(c);
4388
   evas_textblock_cursor_line_char_last(c);
4389

4390
   if (old_cur_pos == evas_textblock_cursor_pos_get(c))
4391
     return;
4392

4393
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4394

4395
   _edje_entry_imf_cursor_info_set(en);
4396
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4397
   _edje_entry_real_part_configure(en->ed, rp);
4398
}
4399

4400
void
4401
_edje_entry_cursor_line_end(Edje_Real_Part *rp, Edje_Cursor cur)
4402
{
4403
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4404
   _edje_text_cursor_line_end(rp, c);
4405
}
4406

4407
Eina_Bool
4408
_edje_text_cursor_coord_set(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c,
4409
                             Evas_Coord x, Evas_Coord y)
4410
{
4411
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4412
       (!rp->typedata.text)) return EINA_FALSE;
4413
   Entry *en = rp->typedata.text->entry_data;
4414
   if (!en) return EINA_FALSE;
4415
   if ((c == _cursor_get(rp, EDJE_CURSOR_SELECTION_BEGIN)) ||
4416
       (c == _cursor_get(rp, EDJE_CURSOR_SELECTION_END)))
4417
     {
4418
        if (en->have_selection)
4419
          {
4420
             if (en->selection)
4421
               {
4422
                  free(en->selection);
4423
                  en->selection = NULL;
4424
               }
4425
             _edje_emit(en->ed, "selection,changed", rp->part->name);
4426
          }
4427
     }
4428
   return evas_textblock_cursor_cluster_coord_set(c, x, y);
4429
}
4430

4431
Eina_Bool
4432
_edje_entry_cursor_coord_set(Edje_Real_Part *rp, Edje_Cursor cur,
4433
                             Evas_Coord x, Evas_Coord y)
4434
{
4435
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4436
   if (!c) return EINA_FALSE;
4437
   return _edje_text_cursor_coord_set(rp, c, x, y);
4438
}
4439

4440
Eina_Bool
4441
_edje_entry_cursor_is_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
4442
{
4443
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4444
   if (!c) return EINA_FALSE;
4445
   if (evas_textblock_cursor_is_format(c)) return EINA_TRUE;
4446
   return EINA_FALSE;
4447
}
4448

4449
Eina_Bool
4450
_edje_entry_cursor_is_visible_format_get(Edje_Real_Part *rp, Edje_Cursor cur)
4451
{
4452
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4453
   if (!c) return EINA_FALSE;
4454
   return evas_textblock_cursor_format_is_visible_get(c);
4455
}
4456

4457
char *
4458
_edje_text_cursor_content_get(Edje_Real_Part *rp EINA_UNUSED, Efl_Text_Cursor_Handle *c)
4459
{
4460
   return evas_textblock_cursor_content_get(c);
4461
}
4462

4463
char *
4464
_edje_entry_cursor_content_get(Edje_Real_Part *rp, Edje_Cursor cur)
4465
{
4466
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4467

4468
   if (!c) return NULL;
4469

4470
   return _edje_text_cursor_content_get(rp, c);
4471
}
4472

4473
void
4474
_edje_text_cursor_pos_set(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c, int pos)
4475
{
4476
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4477
       (!rp->typedata.text)) return;
4478
   Entry *en = rp->typedata.text->entry_data;
4479
   if (!en) return;
4480
   if (!c) return;
4481
   /* Abort if cursor position didn't really change */
4482
   if (evas_textblock_cursor_pos_get(c) == pos)
4483
     return;
4484

4485
   _edje_entry_imf_context_reset(rp);
4486
   evas_textblock_cursor_pos_set(c, pos);
4487
   _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data);
4488

4489
   _edje_entry_imf_cursor_info_set(en);
4490
   _edje_emit(en->ed, "cursor,changed", rp->part->name);
4491
   _edje_entry_real_part_configure(en->ed, rp);
4492
}
4493

4494
void
4495
_edje_entry_cursor_pos_set(Edje_Real_Part *rp, Edje_Cursor cur, int pos)
4496
{
4497
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4498

4499
   _edje_text_cursor_pos_set(rp, c, pos);
4500
}
4501

4502
int
4503
_edje_text_cursor_pos_get(Edje_Real_Part *rp EINA_UNUSED, Efl_Text_Cursor_Handle *c)
4504
{
4505
   return evas_textblock_cursor_pos_get(c);
4506
}
4507

4508
int
4509
_edje_entry_cursor_pos_get(Edje_Real_Part *rp, Edje_Cursor cur)
4510
{
4511
   Evas_Textblock_Cursor *c = _cursor_get(rp, cur);
4512
   if (!c) return 0;
4513
   return _edje_text_cursor_pos_get(rp, c);
4514
}
4515

4516
void
4517
_edje_entry_input_panel_layout_set(Edje_Real_Part *rp, Edje_Input_Panel_Layout layout)
4518
{
4519
#ifdef HAVE_ECORE_IMF
4520
   Entry *en;
4521

4522
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4523
       (!rp->typedata.text)) return;
4524
   en = rp->typedata.text->entry_data;
4525
   if (!en) return;
4526
   if (en->imf_context)
4527
     ecore_imf_context_input_panel_layout_set(en->imf_context, (Ecore_IMF_Input_Panel_Layout)layout);
4528
#else
4529
   (void)rp;
4530
   (void)layout;
4531
#endif
4532
}
4533

4534
Edje_Input_Panel_Layout
4535
_edje_entry_input_panel_layout_get(Edje_Real_Part *rp)
4536
{
4537
#ifdef HAVE_ECORE_IMF
4538
   Entry *en;
4539

4540
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4541
       (!rp->typedata.text)) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4542
   en = rp->typedata.text->entry_data;
4543
   if (!en) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4544
   if (en->imf_context)
4545
     return (Edje_Input_Panel_Layout)ecore_imf_context_input_panel_layout_get(en->imf_context);
4546
   return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4547
#else
4548
   return EDJE_INPUT_PANEL_LAYOUT_INVALID;
4549
   (void)rp;
4550
#endif
4551
}
4552

4553
void
4554
_edje_entry_input_panel_layout_variation_set(Edje_Real_Part *rp, int variation)
4555
{
4556
   Entry *en;
4557

4558
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4559
       (!rp->typedata.text)) return;
4560
   en = rp->typedata.text->entry_data;
4561
   if (!en) return;
4562
#ifdef HAVE_ECORE_IMF
4563
   if (en->imf_context)
4564
     ecore_imf_context_input_panel_layout_variation_set(en->imf_context, variation);
4565
#else
4566
   (void)variation;
4567
#endif
4568
}
4569

4570
int
4571
_edje_entry_input_panel_layout_variation_get(Edje_Real_Part *rp)
4572
{
4573
   Entry *en;
4574

4575
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4576
       (!rp->typedata.text)) return 0;
4577
   en = rp->typedata.text->entry_data;
4578
   if (!en) return 0;
4579
#ifdef HAVE_ECORE_IMF
4580
   if (en->imf_context)
4581
     return ecore_imf_context_input_panel_layout_variation_get(en->imf_context);
4582
#endif
4583

4584
   return 0;
4585
}
4586

4587
void
4588
_edje_entry_imf_context_reset(Edje_Real_Part *rp)
4589
{
4590
#ifdef HAVE_ECORE_IMF
4591
   Entry *en;
4592

4593
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4594
       (!rp->typedata.text)) return;
4595
   en = rp->typedata.text->entry_data;
4596
   if (!en) return;
4597
   if (en->imf_context)
4598
     ecore_imf_context_reset(en->imf_context);
4599
   if (en->commit_cancel)
4600
     en->commit_cancel = EINA_FALSE;
4601
#else
4602
   (void)rp;
4603
#endif
4604
}
4605

4606
static void
4607
_edje_entry_imf_cursor_location_set(Entry *en)
4608
{
4609
#ifdef HAVE_ECORE_IMF
4610
   Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0;
4611
   Evas_BiDi_Direction dir = 0;
4612
   if (!en || !en->rp || !en->imf_context) return;
4613

4614
   _edje_entry_cursor_geometry_get(en->rp, &cx, &cy, &cw, &ch, &dir);
4615
   ecore_imf_context_cursor_location_set(en->imf_context, cx, cy, cw, ch);
4616
   ecore_imf_context_bidi_direction_set(en->imf_context, (Ecore_IMF_BiDi_Direction)dir);
4617
#else
4618
   (void)en;
4619
#endif
4620
}
4621

4622
static void
4623
_edje_entry_imf_cursor_info_set(Entry *en)
4624
{
4625
   int cursor_pos;
4626

4627
#ifdef HAVE_ECORE_IMF
4628
   if (!en || !en->rp || !en->imf_context) return;
4629

4630
   if (en->have_selection)
4631
     {
4632
        if (evas_textblock_cursor_compare(en->sel_start, en->sel_end) < 0)
4633
          cursor_pos = evas_textblock_cursor_pos_get(en->sel_start);
4634
        else
4635
          cursor_pos = evas_textblock_cursor_pos_get(en->sel_end);
4636
     }
4637
   else
4638
     cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
4639

4640
   ecore_imf_context_cursor_position_set(en->imf_context, cursor_pos);
4641

4642
   _edje_entry_imf_cursor_location_set(en);
4643
#else
4644
   (void)en;
4645
#endif
4646
}
4647

4648
void
4649
_edje_entry_prediction_hint_set(Edje_Real_Part *rp, const char *prediction_hint)
4650
{
4651
   Entry *en;
4652

4653
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4654
       (!rp->typedata.text)) return;
4655
   en = rp->typedata.text->entry_data;
4656
   if (!en) return;
4657
#ifdef HAVE_ECORE_IMF
4658
   if (en->imf_context)
4659
     ecore_imf_context_prediction_hint_set(en->imf_context, prediction_hint);
4660
#else
4661
   (void)prediction_hint;
4662
#endif
4663
}
4664

4665
Eina_Bool
4666
_edje_entry_prediction_hint_hash_set(Edje_Real_Part *rp, const char *key, const char *value)
4667
{
4668
   Entry *en;
4669

4670
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4671
       (!rp->typedata.text)) return EINA_FALSE;
4672
   en = rp->typedata.text->entry_data;
4673
   if (!en) return EINA_FALSE;
4674
#ifdef HAVE_ECORE_IMF
4675
   if (en->imf_context)
4676
     return ecore_imf_context_prediction_hint_hash_set(en->imf_context, key, value);
4677
#else
4678
   (void)key;
4679
   (void)value;
4680
#endif
4681

4682
   return EINA_FALSE;
4683
}
4684

4685
Eina_Bool
4686
_edje_entry_prediction_hint_hash_del(Edje_Real_Part *rp, const char *key)
4687
{
4688
   Entry *en;
4689

4690
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4691
       (!rp->typedata.text)) return EINA_FALSE;
4692
   en = rp->typedata.text->entry_data;
4693
   if (!en) return EINA_FALSE;
4694
#ifdef HAVE_ECORE_IMF
4695
   if (en->imf_context)
4696
     return ecore_imf_context_prediction_hint_hash_del(en->imf_context, key);
4697
#else
4698
   (void)key;
4699
#endif
4700

4701
   return EINA_FALSE;
4702
}
4703

4704
#ifdef HAVE_ECORE_IMF
4705

4706
static Edje_Real_Part *
4707
_edje_entry_imf_default_focused_rp_get(Edje *ed)
4708
{
4709
   Eina_Stringshare *seat_name;
4710
   Efl_Input_Device *seat;
4711
   Evas *e;
4712

4713
   e = evas_object_evas_get(ed->obj);
4714
   seat = evas_default_device_get(e, EVAS_DEVICE_CLASS_SEAT);
4715
   seat_name = _edje_seat_name_get(ed, seat);
4716

4717
   return _edje_focused_part_get(ed, seat_name);
4718
}
4719

4720
static Eina_Bool
4721
_edje_entry_imf_retrieve_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text, int *cursor_pos)
4722
{
4723
   Edje *ed = data;
4724
   Edje_Real_Part *rp;
4725
   Entry *en = NULL;
4726
   const char *str;
4727
   char *plain_text;
4728

4729
   rp = _edje_entry_imf_default_focused_rp_get(ed);
4730
   if (!rp) return EINA_FALSE;
4731
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4732
       (!rp->typedata.text)) return EINA_FALSE;
4733
   else
4734
     en = rp->typedata.text->entry_data;
4735
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4736
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4737
     return EINA_FALSE;
4738

4739
   if (text)
4740
     {
4741
        str = _edje_entry_text_get(rp);
4742
        if (str)
4743
          {
4744
             plain_text = evas_textblock_text_markup_to_utf8(NULL, str);
4745

4746
             if (plain_text)
4747
               {
4748
                  if (ecore_imf_context_input_hint_get(ctx) & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
4749
                    {
4750
                       int idx = 0;
4751
                       char *itr = NULL;
4752
                       size_t len = eina_unicode_utf8_get_len(plain_text);
4753
                       char *u_text = (char *)malloc(len * sizeof(char) + 1);
4754
                       if (!u_text)
4755
                         {
4756
                            free(plain_text);
4757
                            return EINA_FALSE;
4758
                         }
4759

4760
                       itr = u_text;
4761
                       while (eina_unicode_utf8_next_get(plain_text, &idx))
4762
                         {
4763
                            *itr = '*';
4764
                            itr++;
4765
                         }
4766
                       *itr = 0;
4767

4768
                       free(plain_text);
4769
                       plain_text = strdup(u_text);
4770
                       free(u_text);
4771
                       u_text = NULL;
4772
                    }
4773

4774
                  *text = strdup(plain_text);
4775
                  free(plain_text);
4776
                  plain_text = NULL;
4777
               }
4778
             else
4779
               {
4780
                  *text = strdup("");
4781
               }
4782
          }
4783
        else
4784
          {
4785
             *text = strdup("");
4786
          }
4787
     }
4788

4789
   if (cursor_pos)
4790
     {
4791
        if (en->have_selection && en->sel_start)
4792
          *cursor_pos = evas_textblock_cursor_pos_get(en->sel_start);
4793
        else if (en->cursor)
4794
          *cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
4795
        else
4796
          *cursor_pos = 0;
4797
     }
4798

4799
   return EINA_TRUE;
4800
}
4801

4802
static void
4803
_edje_entry_imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info)
4804
{
4805
   Edje *ed = data;
4806
   Edje_Real_Part *rp;
4807
   Entry *en = NULL;
4808
   char *commit_str = event_info;
4809
   Edje_Entry_Change_Info *info = NULL;
4810

4811
   rp = _edje_entry_imf_default_focused_rp_get(ed);
4812
   if ((!rp)) return;
4813
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4814
       (!rp->typedata.text)) return;
4815
   else
4816
     en = rp->typedata.text->entry_data;
4817
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4818
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4819
     return;
4820

4821
   if (en->have_selection)
4822
     {
4823
        if (strcmp(commit_str, ""))
4824
          {
4825
             /* delete selected characters */
4826
             _range_del_emit(ed, en->cursor, rp->object, en);
4827
             _sel_clear(ed, en->cursor, rp->object, en);
4828
          }
4829
     }
4830

4831
   /* delete preedit characters */
4832
   _preedit_del(en);
4833
   _preedit_clear(en);
4834

4835
   // Skipping commit process when it is useless
4836
   if (en->commit_cancel)
4837
     {
4838
        en->commit_cancel = EINA_FALSE;
4839
        return;
4840
     }
4841

4842
   if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
4843
       _edje_password_show_last)
4844
     _edje_entry_hide_visible_password(ed, en->rp);
4845
   if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
4846
       _edje_password_show_last && (!en->preedit_start))
4847
     {
4848
        info = _text_filter_text_prepend(ed, en, en->cursor, commit_str,
4849
                                         "+ password=off", "- password",
4850
                                         EINA_TRUE, EINA_TRUE);
4851
        if (info)
4852
          {
4853
             if (en->pw_timer)
4854
               {
4855
                  ecore_timer_del(en->pw_timer);
4856
                  en->pw_timer = NULL;
4857
               }
4858
             if (_edje_password_show_last_timeout >= 0)
4859
               en->pw_timer = ecore_timer_add
4860
                   (_edje_password_show_last_timeout,
4861
                   _password_timer_cb, en);
4862
          }
4863
     }
4864
   else
4865
     {
4866
        info = _text_filter_text_prepend(ed, en, en->cursor, commit_str,
4867
                                         NULL, NULL,
4868
                                         EINA_TRUE, EINA_TRUE);
4869
     }
4870

4871
   _edje_entry_imf_cursor_info_set(en);
4872
   _anchors_get(en->cursor, rp->object, en);
4873
   if (info)
4874
     {
4875
        _edje_emit(ed, "entry,changed", rp->part->name);
4876
        _edje_emit_full(ed, "entry,changed,user", rp->part->name,
4877
                        info, _free_entry_change_info);
4878
        _edje_emit(ed, "cursor,changed", rp->part->name);
4879
     }
4880
   _edje_entry_imf_cursor_info_set(en);
4881
   _edje_entry_real_part_configure(ed, rp);
4882
}
4883

4884
static int
4885
_sort_cb(const void *a1, const void *a2)
4886
{
4887
   Ecore_IMF_Preedit_Attr *attr1 = (Ecore_IMF_Preedit_Attr *)a1;
4888
   Ecore_IMF_Preedit_Attr *attr2 = (Ecore_IMF_Preedit_Attr *)a2;
4889

4890
   EINA_SAFETY_ON_NULL_RETURN_VAL(attr1, 0);
4891
   EINA_SAFETY_ON_NULL_RETURN_VAL(attr2, 0);
4892

4893
   if (attr1->start_index < attr2->start_index) return -1;
4894
   else if (attr1->start_index == attr2->start_index) return 0;
4895
   else return 1;
4896
}
4897

4898
static void
4899
_edje_entry_imf_event_preedit_changed_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info EINA_UNUSED)
4900
{
4901
   Edje *ed = data;
4902
   Edje_Real_Part *rp;
4903
   Entry *en = NULL;
4904
   Edje_Entry_Change_Info *info = NULL;
4905
   int cursor_pos;
4906
   int preedit_start_pos, preedit_end_pos;
4907
   char *preedit_string;
4908
   char *markup_txt = NULL;
4909
   char *tagname[] = {
4910
      NULL, "preedit",
4911
      // XXX: FIXME: EFL2 - make these 2 preedit_sel's different for efl
4912
      // 2.0 and beyond. maybe use "preedit_sel", "preedit_hilight",
4913
      // See https://phab.enlightenment.org/D2980 for this issue
4914
      "preedit_sel", "preedit_sel",
4915
      "preedit_sub1", "preedit_sub2", "preedit_sub3", "preedit_sub4"
4916
   };
4917
   int i;
4918
   size_t preedit_type_size = sizeof(tagname) / sizeof(tagname[0]);
4919
   Eina_Bool preedit_end_state = EINA_FALSE;
4920
   Eina_List *attrs = NULL, *l = NULL;
4921
   Ecore_IMF_Preedit_Attr *attr;
4922
   Eina_Strbuf *buf;
4923
   Eina_Strbuf *preedit_attr_str;
4924

4925
   rp = _edje_entry_imf_default_focused_rp_get(ed);
4926
   if ((!rp)) return;
4927

4928
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
4929
       (!rp->typedata.text)) return;
4930
   else
4931
     en = rp->typedata.text->entry_data;
4932
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
4933
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
4934
     return;
4935

4936
   if (!en->imf_context) return;
4937

4938
   ecore_imf_context_preedit_string_with_attributes_get(en->imf_context,
4939
                                                        &preedit_string,
4940
                                                        &attrs, &cursor_pos);
4941
   if (!preedit_string) return;
4942

4943
   if (!strcmp(preedit_string, ""))
4944
     preedit_end_state = EINA_TRUE;
4945

4946
   if (en->have_selection && !preedit_end_state)
4947
     _range_del_emit(ed, en->cursor, rp->object, en);
4948

4949
   /* delete preedit characters */
4950
   _preedit_del(en);
4951

4952
   preedit_start_pos = evas_textblock_cursor_pos_get(en->cursor);
4953

4954
   /* insert preedit character(s) */
4955
   if (strlen(preedit_string) > 0)
4956
     {
4957
        buf = eina_strbuf_new();
4958
        if (attrs)
4959
          {
4960
             attrs = eina_list_sort(attrs, 0, EINA_COMPARE_CB(_sort_cb));
4961

4962
             EINA_LIST_FOREACH(attrs, l, attr)
4963
               {
4964
                  if (attr->preedit_type < preedit_type_size)
4965
                    {
4966
                       preedit_attr_str = eina_strbuf_new();
4967
                       if (preedit_attr_str)
4968
                         {
4969
                            eina_strbuf_append_n(preedit_attr_str, preedit_string + attr->start_index, attr->end_index - attr->start_index);
4970
                            markup_txt = evas_textblock_text_utf8_to_markup(NULL, eina_strbuf_string_get(preedit_attr_str));
4971

4972
                            if (markup_txt)
4973
                              {
4974
                                 if (tagname[attr->preedit_type])
4975
                                   eina_strbuf_append_printf(buf, "<%s>%s</%s>", tagname[attr->preedit_type], markup_txt, tagname[attr->preedit_type]);
4976
                                 else
4977
                                   eina_strbuf_append_printf(buf, "%s", markup_txt);
4978
                                 free(markup_txt);
4979
                              }
4980
                            eina_strbuf_free(preedit_attr_str);
4981
                         }
4982
                    }
4983
                  else
4984
                    eina_strbuf_append(buf, preedit_string);
4985
               }
4986
          }
4987
        else
4988
          {
4989
             eina_strbuf_append(buf, preedit_string);
4990
          }
4991

4992
        // For skipping useless commit
4993
        if (!preedit_end_state)
4994
          en->have_preedit = EINA_TRUE;
4995

4996
        if ((rp->part->entry_mode == EDJE_ENTRY_EDIT_MODE_PASSWORD) &&
4997
            _edje_password_show_last)
4998
          {
4999
             _edje_entry_hide_visible_password(ed, en->rp);
5000
             info = _text_filter_markup_prepend(ed, en, en->cursor,
5001
                                              eina_strbuf_string_get(buf),
5002
                                              "+ password=off",
5003
                                              "- password",
5004
                                              EINA_TRUE, EINA_TRUE);
5005
             if (info)
5006
               {
5007
                  if (en->pw_timer)
5008
                    {
5009
                       ecore_timer_del(en->pw_timer);
5010
                       en->pw_timer = NULL;
5011
                    }
5012
                  if (_edje_password_show_last_timeout >= 0)
5013
                    en->pw_timer = ecore_timer_add
5014
                        (_edje_password_show_last_timeout,
5015
                        _password_timer_cb, en);
5016
               }
5017
          }
5018
        else
5019
          info = _text_filter_markup_prepend(ed, en, en->cursor,
5020
                                      eina_strbuf_string_get(buf),
5021
                                      NULL, NULL,
5022
                                      EINA_TRUE, EINA_TRUE);
5023
        eina_strbuf_free(buf);
5024
     }
5025

5026
   if (!preedit_end_state)
5027
     {
5028
        /* set preedit start cursor */
5029
        if (!en->preedit_start)
5030
          en->preedit_start = evas_object_textblock_cursor_new(rp->object);
5031
        evas_textblock_cursor_copy(en->cursor, en->preedit_start);
5032

5033
        /* set preedit end cursor */
5034
        if (!en->preedit_end)
5035
          en->preedit_end = evas_object_textblock_cursor_new(rp->object);
5036
        evas_textblock_cursor_copy(en->cursor, en->preedit_end);
5037

5038
        preedit_end_pos = evas_textblock_cursor_pos_get(en->cursor);
5039

5040
        for (i = 0; i < (preedit_end_pos - preedit_start_pos); i++)
5041
          {
5042
             evas_textblock_cursor_char_prev(en->preedit_start);
5043
          }
5044

5045
        en->have_preedit = EINA_TRUE;
5046

5047
        /* set cursor position */
5048
        evas_textblock_cursor_pos_set(en->cursor, preedit_start_pos + cursor_pos);
5049
     }
5050

5051
   _edje_entry_imf_cursor_info_set(en);
5052
   _anchors_get(en->cursor, rp->object, en);
5053
   _edje_emit_full(ed, "preedit,changed", rp->part->name, info,
5054
                   _free_entry_change_info);
5055
   _edje_emit(ed, "cursor,changed", rp->part->name);
5056

5057
   /* delete attribute list */
5058
   if (attrs)
5059
     {
5060
        EINA_LIST_FREE(attrs, attr)
5061
          free(attr);
5062
     }
5063

5064
   free(preedit_string);
5065
}
5066

5067
static void
5068
_edje_entry_imf_event_delete_surrounding_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info)
5069
{
5070
   Edje *ed = data;
5071
   Edje_Real_Part *rp;
5072
   Entry *en = NULL;
5073
   Ecore_IMF_Event_Delete_Surrounding *ev = event_info;
5074
   Evas_Textblock_Cursor *del_start, *del_end;
5075
   Edje_Entry_Change_Info *info;
5076
   int cursor_pos;
5077
   int start, end;
5078
   char *tmp;
5079

5080
   rp = _edje_entry_imf_default_focused_rp_get(ed);
5081
   if ((!rp)) return;
5082
   if ((!rp) || (!ev)) return;
5083
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
5084
       (!rp->typedata.text)) return;
5085
   else
5086
     en = rp->typedata.text->entry_data;
5087
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
5088
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
5089
     return;
5090

5091
   cursor_pos = evas_textblock_cursor_pos_get(en->cursor);
5092

5093
   del_start = evas_object_textblock_cursor_new(en->rp->object);
5094
   evas_textblock_cursor_pos_set(del_start, cursor_pos + ev->offset);
5095

5096
   del_end = evas_object_textblock_cursor_new(en->rp->object);
5097
   evas_textblock_cursor_pos_set(del_end, cursor_pos + ev->offset + ev->n_chars);
5098

5099
   start = evas_textblock_cursor_pos_get(del_start);
5100
   end = evas_textblock_cursor_pos_get(del_end);
5101
   if (start == end) goto end;
5102

5103
   info = calloc(1, sizeof(*info));
5104
   if  (!info)
5105
     {
5106
        ERR("Running very low on memory");
5107
        return;
5108
     }
5109
   info->insert = EINA_FALSE;
5110
   info->change.del.start = start;
5111
   info->change.del.end = end;
5112

5113
   tmp = evas_textblock_cursor_range_text_get(del_start, del_end, EVAS_TEXTBLOCK_TEXT_MARKUP);
5114
   info->change.del.content = eina_stringshare_add(tmp);
5115
   if (tmp) free(tmp);
5116

5117
   evas_textblock_cursor_range_delete(del_start, del_end);
5118
   _anchors_get(en->cursor, rp->object, en);
5119
   _anchors_update_check(ed, rp);
5120

5121
   _edje_emit(ed, "entry,changed", en->rp->part->name);
5122
   _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info,
5123
                   _free_entry_change_info);
5124
   _edje_emit(ed, "cursor,changed", en->rp->part->name);
5125
   _edje_emit(ed, "cursor,changed,manual", en->rp->part->name);
5126

5127
   _edje_entry_imf_cursor_info_set(en);
5128
   _edje_entry_real_part_configure(ed, rp);
5129

5130
end:
5131
   evas_textblock_cursor_free(del_start);
5132
   evas_textblock_cursor_free(del_end);
5133
}
5134

5135
static void
5136
_edje_entry_imf_event_selection_set_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, void *event_info)
5137
{
5138
   Edje *ed = data;
5139
   Edje_Real_Part *rp;
5140
   Entry *en = NULL;
5141
   Ecore_IMF_Event_Selection *ev = event_info;
5142

5143
   rp = _edje_entry_imf_default_focused_rp_get(ed);
5144
   if ((!rp) || (!ev)) return;
5145
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
5146
       (!rp->typedata.text)) return;
5147
   else
5148
     en = rp->typedata.text->entry_data;
5149
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
5150
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
5151
     return;
5152

5153
   if (ev->start == ev->end)
5154
     {
5155
        _edje_entry_cursor_pos_set(rp, EDJE_CURSOR_MAIN, ev->start);
5156
     }
5157
   else
5158
     {
5159
        _sel_clear(ed, en->cursor, rp->object, en);
5160
        evas_textblock_cursor_pos_set(en->cursor, ev->start);
5161
        _sel_enable(ed, en->cursor, rp->object, en);
5162
        _sel_start(en->cursor, rp->object, en);
5163
        evas_textblock_cursor_pos_set(en->cursor, ev->end);
5164
        _sel_extend(ed, en->cursor, rp->object, en);
5165
     }
5166

5167
   _edje_entry_real_part_configure(en->ed, rp);
5168
}
5169

5170
static Eina_Bool
5171
_edje_entry_imf_retrieve_selection_cb(void *data, Ecore_IMF_Context *ctx EINA_UNUSED, char **text)
5172
{
5173
   Edje *ed = data;
5174
   Edje_Real_Part *rp;
5175
   Entry *en = NULL;
5176
   const char *selection_text = NULL;
5177

5178
   rp = _edje_entry_imf_default_focused_rp_get(ed);
5179
   if (!rp) return EINA_FALSE;
5180
   if ((rp->type != EDJE_RP_TYPE_TEXT) ||
5181
       (!rp->typedata.text)) return EINA_FALSE;
5182
   else
5183
     en = rp->typedata.text->entry_data;
5184
   if ((!en) || (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
5185
       (rp->part->entry_mode < EDJE_ENTRY_EDIT_MODE_SELECTABLE))
5186
     return EINA_FALSE;
5187

5188
   if (en->have_selection)
5189
     {
5190
        selection_text = _edje_entry_selection_get(rp);
5191

5192
        if (text)
5193
          *text = selection_text ? strdup(selection_text) : NULL;
5194

5195
        return selection_text ? EINA_TRUE : EINA_FALSE;
5196
     }
5197
   else
5198
     return EINA_FALSE;
5199
}
5200

5201
#endif
5202

5203
Evas_Textblock_Cursor *
5204
_edje_text_cursor_get(Edje_Real_Part *rp, Edje_Cursor cur)
5205
{
5206
   return _cursor_get(rp, cur);
5207
}
5208

5209
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
5210

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.