update for beta release
[framework/uifw/e17.git] / src / bin / e_editable.c
1 #include "e.h"
2
3 #define E_EDITABLE_CURSOR_MARGIN 5
4
5 #define E_EDITABLE_BLOCK_SIZE 128
6 #define E_EDITABLE_SIZE_TO_ALLOC(length) \
7    (((length) + (E_EDITABLE_BLOCK_SIZE - 1)) / E_EDITABLE_BLOCK_SIZE) * E_EDITABLE_BLOCK_SIZE
8
9 typedef struct _E_Editable_Smart_Data E_Editable_Smart_Data;
10
11 struct _E_Editable_Smart_Data
12 {
13    Evas_Object *clip_object;
14    Evas_Object *event_object;
15    Evas_Object *text_object;
16    Evas_Object *cursor_object;
17    Evas_Object *selection_object;
18
19    int cursor_pos;
20    int cursor_visible;
21    int selection_pos;
22    int selection_visible;
23    int password_mode;
24
25    char *text;
26    int char_length;
27    int unicode_length;
28    int allocated_length;
29
30    int cursor_width;
31    int selection_on_fg;
32    int average_char_w;
33    int average_char_h;
34 };
35
36 /* local subsystem functions */
37 static int _e_editable_text_insert(Evas_Object *editable, int pos, const char *text);
38 static int _e_editable_text_delete(Evas_Object *editable, int start, int end);
39 static void _e_editable_cursor_update(Evas_Object *editable);
40 static void _e_editable_selection_update(Evas_Object *editable);
41 static void _e_editable_text_update(Evas_Object *editable);
42 static void _e_editable_text_position_update(Evas_Object *editable, Evas_Coord real_w);
43 static int _e_editable_char_geometry_get_from_pos(Evas_Object *editable, int utf_pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch);
44
45 static void _e_editable_smart_add(Evas_Object *object);
46 static void _e_editable_smart_del(Evas_Object *object);
47 static void _e_editable_smart_move(Evas_Object *object, Evas_Coord x, Evas_Coord y);
48 static void _e_editable_smart_resize(Evas_Object *object, Evas_Coord w, Evas_Coord h);
49 static void _e_editable_smart_show(Evas_Object *object);
50 static void _e_editable_smart_hide(Evas_Object *object);
51 static void _e_editable_color_set(Evas_Object *object, int r, int g, int b, int a);
52 static void _e_editable_clip_set(Evas_Object *object, Evas_Object *clip);
53 static void _e_editable_clip_unset(Evas_Object *object);
54
55 /* local subsystem globals */
56 static Evas_Smart *_e_editable_smart = NULL;
57 static int _e_editable_smart_use = 0;
58
59 /* externally accessible functions */
60
61 /**
62  * Creates a new editable object. An editable object is an evas smart object in
63  * which the user can type some single-line text, select it and delete it.
64  *
65  * @param evas The evas where to add the editable object
66  * @return Returns the new editable object
67  */
68 EAPI Evas_Object *
69 e_editable_add(Evas *evas)
70 {
71    if (!_e_editable_smart)
72      {
73         static const Evas_Smart_Class sc =
74           {
75              "e_editable",
76                EVAS_SMART_CLASS_VERSION,
77                _e_editable_smart_add,
78                _e_editable_smart_del,
79                _e_editable_smart_move,
80                _e_editable_smart_resize,
81                _e_editable_smart_show,
82                _e_editable_smart_hide,
83                _e_editable_color_set,
84                _e_editable_clip_set,
85                _e_editable_clip_unset,
86                NULL,
87                NULL,
88                NULL,
89                NULL,
90                NULL,
91                NULL,
92                NULL
93           };
94         _e_editable_smart = evas_smart_class_new(&sc);
95         _e_editable_smart_use = 0;
96      }
97
98    return evas_object_smart_add(evas, _e_editable_smart);
99 }
100
101 /**
102  * Sets the theme group to be used by the editable object.
103  * This function has to be called, or the cursor and the selection won't be
104  * visible.
105  *
106  * @param editable an editable object
107  * @param category the theme category to use for the editable object
108  * @param group the theme group to use for the editable object
109  */
110 EAPI void
111 e_editable_theme_set(Evas_Object *editable, const char *category, const char *group)
112 {
113    E_Editable_Smart_Data *sd;
114    char *obj_group;
115    const char *data;
116
117    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
118      return;
119    if ((!category) || (!group)) return;
120    obj_group = alloca(strlen(group) + strlen("/selection") + 1);
121
122    /* Gets the theme for the text object */
123    sprintf(obj_group, "%s/text", group);
124    e_theme_edje_object_set(sd->text_object, category, obj_group);
125    sd->average_char_w = -1;
126    sd->average_char_h = -1;
127
128    /* Gets the theme for the cursor */
129    sprintf(obj_group, "%s/cursor", group);
130    e_theme_edje_object_set(sd->cursor_object, category, obj_group);
131
132    edje_object_size_min_get(sd->cursor_object, &sd->cursor_width, NULL);
133    if (sd->cursor_width < 1) sd->cursor_width = 1;
134
135    /* Gets the theme for the selection */
136    sprintf(obj_group, "%s/selection", group);
137    e_theme_edje_object_set(sd->selection_object, category, obj_group);
138
139    data = edje_object_data_get(sd->selection_object, "on_foreground");
140    if ((data) && (strcmp(data, "1") == 0))
141      {
142         sd->selection_on_fg = 1;
143         evas_object_stack_above(sd->selection_object, sd->text_object);
144      }
145    else
146      {
147         sd->selection_on_fg = 0;
148         evas_object_stack_below(sd->selection_object, sd->text_object);
149      }
150
151    _e_editable_text_update(editable);
152    _e_editable_cursor_update(editable);
153 }
154
155 /**
156  * Sets whether or not the editable object is in password mode. In password
157  * mode, the editable object displays '*' instead of the characters
158  *
159  * @param editable an editable object
160  * @param password_mode 1 to turn on the password mode of the editable object,
161  * 0 to turn it off
162  */
163 EAPI void
164 e_editable_password_set(Evas_Object *editable, int password_mode)
165 {
166    E_Editable_Smart_Data *sd;
167
168    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
169      return;
170    if (sd->password_mode == password_mode) return;
171
172    sd->password_mode = password_mode;
173    _e_editable_text_update(editable);
174    _e_editable_cursor_update(editable);
175 }
176
177 /**
178  * Gets whether or not the editable is in password mode
179  *
180  * @param editable an editable object
181  * @return Returns 1 if the editable object is in the password mode, 0 otherwise
182  */
183 EAPI int
184 e_editable_password_get(Evas_Object *editable)
185 {
186    E_Editable_Smart_Data *sd;
187
188    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
189      return 0;
190    return sd->password_mode;
191 }
192
193 /**
194  * Sets the text of the editable object
195  *
196  * @param editable an editable object
197  * @param text the text to set
198  */
199 EAPI void
200 e_editable_text_set(Evas_Object *editable, const char *text)
201 {
202    E_Editable_Smart_Data *sd;
203
204    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
205      return;
206
207    if (sd->password_mode) memset(sd->text, 0, sd->char_length);
208    free(sd->text);
209    sd->text = NULL;
210    sd->char_length = 0;
211    sd->unicode_length = 0;
212    sd->allocated_length = -1;
213
214    if (_e_editable_text_insert(editable, 0, text) <= 0)
215      {
216         sd->text = malloc((E_EDITABLE_BLOCK_SIZE + 1) * sizeof(char));
217         sd->text[0] = '\0';
218         sd->char_length = 0;
219         sd->unicode_length = 0;
220         sd->allocated_length = E_EDITABLE_BLOCK_SIZE;
221         _e_editable_text_update(editable);
222      }
223
224    sd->cursor_pos = sd->unicode_length;
225    sd->selection_pos = sd->unicode_length;
226    _e_editable_cursor_update(editable);
227 }
228
229 /**
230  * Gets the entire text of the editable object
231  *
232  * @param editable an editable object
233  * @return Returns the entire text of the editable object
234  */
235 EAPI const char *
236 e_editable_text_get(Evas_Object *editable)
237 {
238    E_Editable_Smart_Data *sd;
239
240    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
241      return NULL;
242    return sd->text;
243 }
244
245 /**
246  * Gets a range of the text of the editable object, from position @a start to
247  * position @a end
248  *
249  * @param editable an editable object
250  * @param start the start position of the text range to get
251  * @param end the end position of the text range to get
252  * @return Returns the range of text. The returned string will have to be freed
253  */
254 EAPI char *
255 e_editable_text_range_get(Evas_Object *editable, int start, int end)
256 {
257    E_Editable_Smart_Data *sd;
258    char *range;
259    int start_id = 0, end_id = 0, i;
260
261    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
262      return NULL;
263
264    start = E_CLAMP(start, 0, sd->unicode_length);
265    end = E_CLAMP(end, 0, sd->unicode_length);
266    if (end <= start) return NULL;
267
268    for (i = 0; i < end; i++)
269      {
270         end_id = evas_string_char_next_get(sd->text, end_id, NULL);
271         if (i < start) start_id = end_id;
272      }
273
274    if (end_id <= start_id) return NULL;
275
276    range = malloc((end_id - start_id + 1) * sizeof(char));
277    strncpy(range, &sd->text[start_id], end_id - start_id);
278    range[end_id - start_id] = '\0';
279
280    return range;
281 }
282
283 /**
284  * Gets the unicode length of the text of the editable object. The unicode
285  * length is not always the length returned by strlen() since a UTF-8 char can
286  * take several bytes
287  *
288  * @param editable an editable object
289  * @return Returns the unicode length of the text of the editable object
290  */
291 EAPI int
292 e_editable_text_length_get(Evas_Object *editable)
293 {
294    E_Editable_Smart_Data *sd;
295
296    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
297      return 0;
298    return sd->unicode_length;
299 }
300
301 /**
302  * Inserts some text at the given position in the editable object
303  *
304  * @param editable the editable object in which the text should be inserted
305  * @param pos the position where to insert the text
306  * @param text the text to insert
307  * @return Returns 1 if the text has been modified, 0 otherwise
308  */
309 EAPI int
310 e_editable_insert(Evas_Object *editable, int pos, const char *text)
311 {
312    E_Editable_Smart_Data *sd;
313    int unicode_length;
314
315    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
316      return 0;
317
318    unicode_length = _e_editable_text_insert(editable, pos, text);
319    if (unicode_length <= 0) return 0;
320
321    if (sd->cursor_pos >= pos)
322      e_editable_cursor_pos_set(editable, sd->cursor_pos + unicode_length);
323    if (sd->selection_pos >= pos)
324      e_editable_selection_pos_set(editable, sd->selection_pos + unicode_length);
325
326    _e_editable_text_position_update(editable, -1);
327    return 1;
328 }
329
330 /**
331  * Deletes the text of the editable object, between position "start" and
332  * position "end"
333  *
334  * @param editable the editable object in which the text should be deleted
335  * @param start the position of the first char to delete
336  * @param end the position of the last char to delete
337  * @return Returns 1 if the text has been modified, 0 otherwise
338  */
339 EAPI int
340 e_editable_delete(Evas_Object *editable, int start, int end)
341 {
342    E_Editable_Smart_Data *sd;
343    int unicode_length;
344
345    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
346      return 0;
347
348    unicode_length = _e_editable_text_delete(editable, start, end);
349    if (unicode_length <= 0) return 0;
350
351    if (sd->cursor_pos > end)
352      e_editable_cursor_pos_set(editable, sd->cursor_pos - unicode_length);
353    else if (sd->cursor_pos > start)
354      e_editable_cursor_pos_set(editable, start);
355
356    if (sd->selection_pos > end)
357      e_editable_selection_pos_set(editable, sd->selection_pos - unicode_length);
358    else if (sd->selection_pos > start)
359      e_editable_selection_pos_set(editable, start);
360
361    _e_editable_text_position_update(editable, -1);
362    return 1;
363 }
364
365 /**
366  * Moves the cursor of the editable object to the given position
367  *
368  * @param editable an editable object
369  * @param pos the position where to move the cursor
370  */
371 EAPI void
372 e_editable_cursor_pos_set(Evas_Object *editable, int pos)
373 {
374    E_Editable_Smart_Data *sd;
375
376    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
377      return;
378
379    pos = E_CLAMP(pos, 0, sd->unicode_length);
380    if ((sd->cursor_pos == pos)) return;
381
382    sd->cursor_pos = pos;
383    _e_editable_cursor_update(editable);
384 }
385
386 /**
387  * Gets the position of the cursor of the editable object
388  *
389  * @param editable an editable object
390  * @return Returns the position of the cursor of the editable object
391  */
392 EAPI int
393 e_editable_cursor_pos_get(Evas_Object *editable)
394 {
395    E_Editable_Smart_Data *sd;
396
397    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
398      return 0;
399    return sd->cursor_pos;
400 }
401
402 /**
403  * Gets the geometry of the cursor of the editable object
404  *
405  * @param editable an editable object
406  * @param cx the x of the cursor
407  * @param cy the y of the cursor
408  * @param cw the width of the cursor
409  * @param ch the height of the cursor
410  */
411 EAPI void
412 e_editable_cursor_geometry_get(Evas_Object *editable, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
413 {
414    E_Editable_Smart_Data *sd;
415
416    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
417      return;
418
419    evas_object_geometry_get(sd->cursor_object, cx, cy, cw, ch);
420 }
421
422 /**
423  * Moves the cursor to the start of the editable object
424  *
425  * @param editable an editable object
426  */
427 EAPI void
428 e_editable_cursor_move_to_start(Evas_Object *editable)
429 {
430    if (!editable)
431      return;
432    e_editable_cursor_pos_set(editable, 0);
433 }
434
435 /**
436  * Moves the cursor to the end of the editable object
437  *
438  * @param editable an editable object
439  */
440 EAPI void
441 e_editable_cursor_move_to_end(Evas_Object *editable)
442 {
443    E_Editable_Smart_Data *sd;
444
445    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
446      return;
447    e_editable_cursor_pos_set(editable, sd->unicode_length);
448 }
449
450 /**
451  * Moves the cursor backward by one character offset
452  *
453  * @param editable an editable object
454  */
455 EAPI void
456 e_editable_cursor_move_left(Evas_Object *editable)
457 {
458    E_Editable_Smart_Data *sd;
459
460    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
461      return;
462    e_editable_cursor_pos_set(editable, sd->cursor_pos - 1);
463 }
464
465 /**
466  * Moves the cursor forward by one character offset
467  *
468  * @param editable an editable object
469  */
470 EAPI void
471 e_editable_cursor_move_right(Evas_Object *editable)
472 {
473    E_Editable_Smart_Data *sd;
474
475    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
476      return;
477    e_editable_cursor_pos_set(editable, sd->cursor_pos + 1);
478 }
479
480 /**
481  * Shows the cursor of the editable object
482  *
483  * @param editable the editable object whose cursor should be shown
484  */
485 EAPI void
486 e_editable_cursor_show(Evas_Object *editable)
487 {
488    E_Editable_Smart_Data *sd;
489
490    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
491      return;
492    if (sd->cursor_visible) return;
493
494    sd->cursor_visible = 1;
495    if (evas_object_visible_get(editable))
496      {
497         evas_object_show(sd->cursor_object);
498         edje_object_signal_emit(sd->cursor_object, "e,action,show,cursor", "e");
499      }
500 }
501
502 /**
503  * Hides the cursor of the editable object
504  *
505  * @param editable the editable object whose cursor should be hidden
506  */
507 EAPI void
508 e_editable_cursor_hide(Evas_Object *editable)
509 {
510    E_Editable_Smart_Data *sd;
511
512    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
513      return;
514    if (!sd->cursor_visible) return;
515
516    sd->cursor_visible = 0;
517    evas_object_hide(sd->cursor_object);
518 }
519
520 /**
521  * Moves the selection bound of the editable object to the given position
522  *
523  * @param editable an editable object
524  * @param pos the position where to move the selection bound
525  */
526 EAPI void
527 e_editable_selection_pos_set(Evas_Object *editable, int pos)
528 {
529    E_Editable_Smart_Data *sd;
530
531    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
532      return;
533
534    pos = E_CLAMP(pos, 0, sd->unicode_length);
535    if (sd->selection_pos == pos) return;
536
537    sd->selection_pos = pos;
538    _e_editable_selection_update(editable);
539 }
540
541 /**
542  * Gets the position of the selection bound of the editable object
543  *
544  * @param editable an editable object
545  * @return Returns the position of the selection bound of the editable object
546  */
547 EAPI int
548 e_editable_selection_pos_get(Evas_Object *editable)
549 {
550    E_Editable_Smart_Data *sd;
551
552    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
553      return 0;
554    return sd->selection_pos;
555 }
556
557 /**
558  * Moves the selection bound to the start of the editable object
559  *
560  * @param editable an editable object
561  */
562 EAPI void
563 e_editable_selection_move_to_start(Evas_Object *editable)
564 {
565    if (!editable)
566      return;
567    e_editable_selection_pos_set(editable, 0);
568 }
569
570 /**
571  * Moves the selection bound to the end of the editable object
572  *
573  * @param editable an editable object
574  */
575 EAPI void
576 e_editable_selection_move_to_end(Evas_Object *editable)
577 {
578    E_Editable_Smart_Data *sd;
579
580    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
581      return;
582    e_editable_selection_pos_set(editable, sd->unicode_length);
583 }
584
585 /**
586  * Moves the selection bound backward by one character offset
587  *
588  * @param editable an editable object
589  */
590 EAPI void
591 e_editable_selection_move_left(Evas_Object *editable)
592 {
593    E_Editable_Smart_Data *sd;
594
595    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
596      return;
597    e_editable_selection_pos_set(editable, sd->selection_pos - 1);
598 }
599
600 /**
601  * Moves the selection bound forward by one character offset
602  *
603  * @param editable an editable object
604  */
605 EAPI void
606 e_editable_selection_move_right(Evas_Object *editable)
607 {
608    E_Editable_Smart_Data *sd;
609
610    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
611      return;
612    e_editable_selection_pos_set(editable, sd->selection_pos + 1);
613 }
614
615 /**
616  * Selects all the text of the editable object. The selection bound will be
617  * moved to the start of the editable object and the cursor will be moved to
618  * the end
619  *
620  * @param editable an editable object
621  */
622 EAPI void
623 e_editable_select_all(Evas_Object *editable)
624 {
625    if (!editable) return;
626    e_editable_selection_move_to_start(editable);
627    e_editable_cursor_move_to_end(editable);
628 }
629
630 /**
631  * Unselects all the text of the editable object. The selection bound will be
632  * moved to the cursor position
633  *
634  * @param editable an editable object
635  */
636 EAPI void
637 e_editable_unselect_all(Evas_Object *editable)
638 {
639    E_Editable_Smart_Data *sd;
640
641    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
642      return;
643    e_editable_selection_pos_set(editable, sd->cursor_pos);
644 }
645
646 /**
647  * Selects the word at the provided character index
648  */
649 EAPI void
650 e_editable_select_word(Evas_Object *editable, int index)
651 {
652    E_Editable_Smart_Data *sd;
653    int spos = 0, epos = -1, i = 0, pos = 0;
654
655    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
656      return;
657    if ((index < 0) || (index >= sd->unicode_length)) return;
658
659    while (i < sd->char_length)
660      {
661         if (sd->text[i] == ' ')
662           {
663              if (pos < index) spos = pos + 1;
664              else if (pos > index)
665                {
666                   epos = pos;
667                   break;
668                }
669           }
670         i = evas_string_char_next_get(sd->text, i, NULL);
671         pos++;
672      }
673    if (epos == -1) epos = pos;
674    e_editable_selection_pos_set(editable, spos);
675    e_editable_cursor_pos_set(editable, epos);
676 }
677
678 /**
679  * Shows the selection of the editable object
680  *
681  * @param editable an editable object
682  */
683 EAPI void
684 e_editable_selection_show(Evas_Object *editable)
685 {
686    E_Editable_Smart_Data *sd;
687
688    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
689      return;
690    if (sd->selection_visible) return;
691    sd->selection_visible = 1;
692    if ((evas_object_visible_get(editable)) &&
693        (sd->cursor_pos != sd->selection_pos))
694      evas_object_show(sd->selection_object);
695 }
696
697 /**
698  * Hides the selection of the editable object
699  *
700  * @param editable an editable object
701  */
702 EAPI void
703 e_editable_selection_hide(Evas_Object *editable)
704 {
705    E_Editable_Smart_Data *sd;
706
707    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
708      return;
709    if (!sd->selection_visible) return;
710    sd->selection_visible = 0;
711    evas_object_hide(sd->selection_object);
712 }
713
714 /**
715  * Gets the cursor position at the coords ( @a x, @a y ). It's used to know
716  * where to place the cursor or the selection bound on mouse evevents.
717  *
718  * @param editable an editable object
719  * @param x the x coord, relative to the editable object
720  * @param y the y coord, relative to the editable object
721  * @return Returns the position where to place the cursor according to the
722  * given coords
723  */
724 EAPI int
725 e_editable_pos_get_from_coords(Evas_Object *editable, Evas_Coord x, Evas_Coord y)
726 {
727    E_Editable_Smart_Data *sd;
728    const Evas_Object *text_obj;
729    Evas_Coord ox, oy;
730    Evas_Coord tx, ty, tw, th;
731    Evas_Coord cx, cw;
732    Evas_Coord canvas_x, canvas_y;
733    int index, pos, i, j;
734    const char *text;
735
736    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
737      return 0;
738    if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text")))
739      return 0;
740
741    evas_object_geometry_get(editable, &ox, &oy, NULL, NULL);
742    evas_object_geometry_get(text_obj, &tx, &ty, &tw, &th);
743    canvas_x = ox + x;
744    canvas_y = oy + y;
745
746    if ((canvas_y < ty) || (canvas_x < tx))
747      pos = 0;
748    else if ((canvas_y > (ty + th)) || (canvas_x > (tx + tw)))
749      pos = sd->unicode_length;
750    else
751      {
752         index = evas_object_text_char_coords_get(text_obj,
753                                                  canvas_x - tx, canvas_y - ty,
754                                                  &cx, NULL, &cw, NULL);
755         text = evas_object_text_text_get(text_obj);
756         if ((index >= 0) && (text))
757           {
758              if ((canvas_x - tx) > (cx + (cw / 2))) index++;
759
760              i = 0;
761              j = -1;
762              pos = 0;
763              while ((i < index) && (j != i))
764                {
765                   pos++;
766                   j = i;
767                   i = evas_string_char_next_get(text, i, NULL);
768                }
769              if (pos > sd->unicode_length) pos = sd->unicode_length;
770           }
771         else pos = 0;
772      }
773    return pos;
774 }
775
776 /**
777  * A utility function to get the average size of a character written inside
778  * the editable object
779  *
780  * @param editable an editable object
781  * @param w the location where to store the average width of a character
782  * @param h the location where to store the average height of a character
783  */
784 EAPI void
785 e_editable_char_size_get(Evas_Object *editable, int *w, int *h)
786 {
787    int tw = 0, th = 0;
788    Evas *evas;
789    const Evas_Object *text_obj;
790    Evas_Object *obj;
791    E_Editable_Smart_Data *sd;
792    char *text = "Tout est bon dans l'abricot sauf le noyau!"
793                 "Wakey wakey! Eggs and Bakey!";
794    const char *font, *font_source;
795    Evas_Text_Style_Type style;
796    int font_size;
797
798    if (w) *w = 0;
799    if (h) *h = 0;
800    if ((!editable) || (!(evas = evas_object_evas_get(editable))))
801      return;
802    if (!(sd = evas_object_smart_data_get(editable))) return;
803    if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text")))
804      return;
805
806    if ((sd->average_char_w <= 0) || (sd->average_char_h <= 0))
807      {
808         font_source = evas_object_text_font_source_get(text_obj);
809         evas_object_text_font_get(text_obj, &font, &font_size);
810         style = evas_object_text_style_get(text_obj);
811
812         obj = evas_object_text_add(evas);
813         evas_object_scale_set(obj, edje_scale_get());
814         evas_object_text_font_source_set(obj, font_source);
815         evas_object_text_font_set(obj, font, font_size);
816         evas_object_text_style_set(obj, style);
817         evas_object_text_text_set(obj, text);
818         evas_object_geometry_get(obj, NULL, NULL, &tw, &th);
819         evas_object_del(obj);
820         sd->average_char_w = (tw / strlen(text));
821         sd->average_char_h = th;
822      }
823    if (w) *w = sd->average_char_w;
824    if (h) *h = sd->average_char_h;
825 }
826
827 EAPI void
828 e_editable_enable(Evas_Object *editable)
829 {
830    E_Editable_Smart_Data *sd;
831
832    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
833      return;
834
835    edje_object_signal_emit(sd->text_object, "e,state,enabled", "e");
836 }
837
838 EAPI void
839 e_editable_disable(Evas_Object *editable)
840 {
841    E_Editable_Smart_Data *sd;
842
843    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
844      return;
845
846    edje_object_signal_emit(sd->text_object, "e,state,disabled", "e");
847 }
848 /* Private functions */
849
850 /* A utility function to insert some text inside the editable object.
851  * It doesn't update the position of the cursor, nor the selection... */
852 static int
853 _e_editable_text_insert(Evas_Object *editable, int pos, const char *text)
854 {
855    E_Editable_Smart_Data *sd;
856    int char_length = -1, unicode_length = -1;
857    int prev_char_length, new_char_length, new_unicode_length;
858    int index = 0, i = 0;
859
860    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
861      return 0;
862    if ((!text) || (*text == '\0')) return 0;
863
864    if (pos < 0) pos = 0;
865    else if (pos > sd->unicode_length)
866      pos = sd->unicode_length;
867
868    for (i = 0; i != char_length; i = evas_string_char_next_get(text, i, NULL))
869      {
870         char_length = i;
871         unicode_length++;
872      }
873
874    for (i = 0; i < pos; i++)
875      index = evas_string_char_next_get(sd->text, index, NULL);
876
877    if ((unicode_length <= 0) || (char_length <= 0)) return 0;
878
879    prev_char_length = sd->char_length;
880    new_char_length = sd->char_length + char_length;
881    new_unicode_length = sd->unicode_length + unicode_length;
882
883    if (new_char_length > sd->allocated_length)
884      {
885         int new_allocated_length = E_EDITABLE_SIZE_TO_ALLOC(new_char_length);
886         char *old = sd->text;
887
888         if (sd->password_mode)
889           {
890              /* security -- copy contents into new buffer, and overwrite old contents */
891              sd->text = malloc(new_allocated_length + 1);
892              if (!sd->text)
893                {
894                   sd->text = old;
895                   return 0;
896                }
897              if (old)
898                {
899                   memcpy(sd->text, old, prev_char_length + 1);
900                   memset(old, 0, prev_char_length);
901                   free(old);
902                }
903           }
904         else
905           {
906              sd->text = realloc(sd->text, new_allocated_length + 1);
907              if (!sd->text)
908                {
909                   sd->text = old;
910                   return 0;
911                }
912           }
913         sd->allocated_length = new_allocated_length;
914      }
915    sd->unicode_length = new_unicode_length;
916    sd->char_length = new_char_length;
917
918    if (prev_char_length > index)
919      memmove(&sd->text[index + char_length], &sd->text[index], prev_char_length - index);
920    strncpy(&sd->text[index], text, char_length);
921    sd->text[sd->char_length] = '\0';
922
923    _e_editable_text_update(editable);
924    return unicode_length;
925 }
926
927 /* A utility function to delete a range of text from the editable object.
928  * It doesn't update the position of the cursor, nor the selection... */
929 static int
930 _e_editable_text_delete(Evas_Object *editable, int start, int end)
931 {
932    E_Editable_Smart_Data *sd;
933    int start_id = 0, end_id = 0, i = 0;
934
935    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
936      return 0;
937
938    start = E_CLAMP(start, 0, sd->unicode_length);
939    end = E_CLAMP(end, 0, sd->unicode_length);
940    if (end <= start) return 0;
941
942    for (i = 0; i < end; i++)
943      {
944         end_id = evas_string_char_next_get(sd->text, end_id, NULL);
945         if (i < start) start_id = end_id;
946      }
947
948    if (end_id <= start_id) return 0;
949
950    memmove(&sd->text[start_id], &sd->text[end_id], sd->char_length - end_id);
951    sd->char_length -= (end_id - start_id);
952    sd->unicode_length -= (end - start);
953    sd->text[sd->char_length] = '\0';
954
955    _e_editable_text_update(editable);
956
957    return (end - start);
958 }
959
960 /* Updates the position of the cursor
961  * It also updates automatically the text position and the selection */
962 static void
963 _e_editable_cursor_update(Evas_Object *editable)
964 {
965    E_Editable_Smart_Data *sd;
966    const Evas_Object *text_obj;
967    Evas_Coord tx, ty;
968    Evas_Coord cx, cy, ch;
969
970    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
971      return;
972    if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text")))
973      return;
974
975    evas_object_geometry_get(text_obj, &tx, &ty, NULL, NULL);
976    _e_editable_char_geometry_get_from_pos(editable, sd->cursor_pos,
977                                           &cx, &cy, NULL, &ch);
978
979    evas_object_move(sd->cursor_object, tx + cx, ty + cy);
980    evas_object_resize(sd->cursor_object, sd->cursor_width, ch);
981
982    if (sd->cursor_visible && evas_object_visible_get(editable))
983      {
984         evas_object_show(sd->cursor_object);
985         edje_object_signal_emit(sd->cursor_object, "e,action,show,cursor", "e");
986      }
987
988    _e_editable_selection_update(editable);
989    _e_editable_text_position_update(editable, -1);
990 }
991
992 /* Updates the selection of the editable object */
993 static void
994 _e_editable_selection_update(Evas_Object *editable)
995 {
996    E_Editable_Smart_Data *sd;
997    const Evas_Object *text_obj;
998    Evas_Coord tx, ty;
999    Evas_Coord cx, cy;
1000    Evas_Coord sx, sy, sw, sh;
1001    int start_pos, end_pos;
1002
1003    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
1004      return;
1005    if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text")))
1006      return;
1007
1008    if ((sd->cursor_pos == sd->selection_pos) || (!sd->selection_visible))
1009      evas_object_hide(sd->selection_object);
1010    else
1011      {
1012         evas_object_geometry_get(text_obj, &tx, &ty, NULL, NULL);
1013         start_pos = (sd->cursor_pos <= sd->selection_pos) ?
1014           sd->cursor_pos : sd->selection_pos;
1015         end_pos = (sd->cursor_pos >= sd->selection_pos) ?
1016           sd->cursor_pos : sd->selection_pos;
1017
1018         _e_editable_char_geometry_get_from_pos(editable, start_pos,
1019                                                &cx, &cy, NULL, NULL);
1020         sx = tx + cx;
1021         sy = ty + cy;
1022
1023         _e_editable_char_geometry_get_from_pos(editable, end_pos,
1024                                                &cx, NULL, NULL, &sh);
1025         sw = tx + cx - sx;
1026
1027         evas_object_move(sd->selection_object, sx, sy);
1028         evas_object_resize(sd->selection_object, sw, sh);
1029         evas_object_show(sd->selection_object);
1030      }
1031 }
1032
1033 /* Updates the text of the text object of the editable object 
1034  * (it fills it with '*' if the editable is in password mode)
1035  * It does not update the position of the text */
1036 static void
1037 _e_editable_text_update(Evas_Object *editable)
1038 {
1039    E_Editable_Smart_Data *sd;
1040    Evas_Coord minw, minh;
1041
1042    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
1043      return;
1044
1045    if (sd->password_mode)
1046      {
1047         char *text;
1048
1049         text = malloc((sd->unicode_length + 1) * sizeof(char));
1050         memset(text, '*', sd->unicode_length * sizeof(char));
1051         text[sd->unicode_length] = '\0';
1052         edje_object_part_text_set(sd->text_object, "e.text.text", text);
1053         free(text);
1054      }
1055    else
1056      edje_object_part_text_set(sd->text_object, "e.text.text", sd->text);
1057
1058    edje_object_size_min_calc(sd->text_object, &minw, &minh);
1059    evas_object_resize(sd->text_object, minw, minh);
1060 }
1061
1062 /* Updates the position of the text object according to the position of the
1063  * cursor (we make sure the cursor is visible) */
1064 static void
1065 _e_editable_text_position_update(Evas_Object *editable, Evas_Coord real_w)
1066 {
1067    E_Editable_Smart_Data *sd;
1068    Evas_Coord ox, oy, ow;
1069    Evas_Coord tx, ty, tw;
1070    Evas_Coord cx, cy, cw;
1071    Evas_Coord sx, sy;
1072    Evas_Coord offset_x = 0;
1073
1074    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
1075      return;
1076
1077    evas_object_geometry_get(editable, &ox, &oy, &ow, NULL);
1078    if (real_w >= 0) ow = real_w;
1079    evas_object_geometry_get(sd->text_object, &tx, &ty, &tw, NULL);
1080    evas_object_geometry_get(sd->cursor_object, &cx, &cy, &cw, NULL);
1081    evas_object_geometry_get(sd->selection_object, &sx, &sy, NULL, NULL);
1082
1083    if (tw <= ow)
1084      offset_x = ox - tx;
1085    else if (cx < (ox + E_EDITABLE_CURSOR_MARGIN))
1086      offset_x = ox + E_EDITABLE_CURSOR_MARGIN - cx;
1087    else if ((cx + cw + E_EDITABLE_CURSOR_MARGIN) > (ox + ow))
1088      offset_x = (ox + ow) - (cx + cw + E_EDITABLE_CURSOR_MARGIN);
1089
1090    if (tw > ow)
1091      {
1092         if ((tx + offset_x) > ox)
1093           offset_x = ox - tx;
1094         else if ((tx + tw + offset_x) < (ox + ow))
1095           offset_x = (ox + ow) - (tx + tw);
1096      }
1097
1098    if (offset_x != 0)
1099      {
1100         evas_object_move(sd->text_object, tx + offset_x, ty);
1101         evas_object_move(sd->cursor_object, cx + offset_x, cy);
1102         evas_object_move(sd->selection_object, sx + offset_x, sy);
1103      }
1104 }
1105
1106 /* Gets the geometry of the char according to its utf-8 pos */
1107 static int
1108 _e_editable_char_geometry_get_from_pos(Evas_Object *editable, int utf_pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
1109 {
1110    E_Editable_Smart_Data *sd;
1111    const Evas_Object *text_obj;
1112    const char *text;
1113    Evas_Coord x, w;
1114    int index = 0, i, last_pos, ret;
1115
1116    if (cx) *cx = 0;
1117    if (cy) *cy = 0;
1118    if (cw) *cw = 0;
1119    if (ch) *ch = 0;
1120
1121    if ((!editable) || (!(sd = evas_object_smart_data_get(editable))))
1122      return 0;
1123    if (!(text_obj = edje_object_part_object_get(sd->text_object, "e.text.text")))
1124      return 0;
1125
1126    text = evas_object_text_text_get(text_obj);
1127    if ((!text) || (sd->unicode_length <= 0) || (utf_pos <= 0))
1128      {
1129         e_editable_char_size_get(editable, cw, ch);
1130         return 1;
1131      }
1132    else
1133      {
1134         if (utf_pos >= sd->unicode_length)
1135           {
1136             utf_pos = sd->unicode_length - 1;
1137             last_pos = 1;
1138           }
1139         else
1140           last_pos = 0;
1141
1142         for (i = 0; i < utf_pos; i++)
1143           index = evas_string_char_next_get(text, index, NULL);
1144
1145         ret = evas_object_text_char_pos_get(text_obj, index, &x, cy, &w, ch);
1146         if (cx) *cx = x - 1 + (last_pos ? w : 0);
1147         if (cw) *cw = last_pos ? 1 : w;
1148         return ret;
1149      }
1150 }
1151
1152 /* Editable object's smart methods */
1153
1154 static void
1155 _e_editable_smart_add(Evas_Object *object)
1156 {
1157    Evas *evas;
1158    E_Editable_Smart_Data *sd;
1159    Evas_Coord ox, oy;
1160
1161    if ((!object) || !(evas = evas_object_evas_get(object)))
1162      return;
1163
1164    sd = malloc(sizeof(E_Editable_Smart_Data));
1165    if (!sd) return;
1166
1167    _e_editable_smart_use++;
1168    evas_object_smart_data_set(object, sd);
1169    evas_object_geometry_get(object, &ox, &oy, NULL, NULL);
1170
1171    sd->text = malloc((E_EDITABLE_BLOCK_SIZE + 1) * sizeof(char));
1172    sd->text[0] = '\0';
1173    sd->char_length = 0;
1174    sd->unicode_length = 0;
1175    sd->allocated_length = E_EDITABLE_BLOCK_SIZE;
1176
1177    sd->cursor_width = 1;
1178    sd->selection_on_fg = 0;
1179    sd->average_char_w = -1;
1180    sd->average_char_h = -1;
1181
1182    sd->cursor_pos = 0;
1183    sd->cursor_visible = 1;
1184    sd->selection_pos = 0;
1185    sd->selection_visible = 1;
1186    sd->password_mode = 0;
1187
1188    sd->clip_object = evas_object_rectangle_add(evas);
1189    evas_object_move(sd->clip_object, ox, oy);
1190    evas_object_smart_member_add(sd->clip_object, object);
1191
1192    sd->event_object = evas_object_rectangle_add(evas);
1193    evas_object_color_set(sd->event_object, 0, 0, 0, 0);
1194    evas_object_clip_set(sd->event_object, sd->clip_object);
1195    evas_object_move(sd->event_object, ox, oy);
1196    evas_object_smart_member_add(sd->event_object, object);
1197
1198    sd->text_object = edje_object_add(evas);
1199    evas_object_pass_events_set(sd->text_object, 1);
1200    evas_object_clip_set(sd->text_object, sd->clip_object);
1201    evas_object_move(sd->text_object, ox, oy);
1202    evas_object_smart_member_add(sd->text_object, object);
1203
1204    sd->selection_object = edje_object_add(evas);
1205    evas_object_pass_events_set(sd->selection_object, 1);
1206    evas_object_clip_set(sd->selection_object, sd->clip_object);
1207    evas_object_move(sd->selection_object, ox, oy);
1208    evas_object_smart_member_add(sd->selection_object, object);
1209
1210    sd->cursor_object = edje_object_add(evas);
1211    evas_object_pass_events_set(sd->cursor_object, 1);
1212    evas_object_clip_set(sd->cursor_object, sd->clip_object);
1213    evas_object_move(sd->cursor_object, ox, oy);
1214    evas_object_smart_member_add(sd->cursor_object, object);
1215
1216    _e_editable_cursor_update(object);
1217 }
1218
1219 /* Deletes the editable */
1220 static void
1221 _e_editable_smart_del(Evas_Object *object)
1222 {
1223    E_Editable_Smart_Data *sd;
1224
1225    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1226      return;
1227
1228    evas_object_del(sd->clip_object);
1229    evas_object_del(sd->event_object);
1230    evas_object_del(sd->text_object);
1231    evas_object_del(sd->cursor_object);
1232    evas_object_del(sd->selection_object);
1233    /* Security - clear out memory that contained a password */
1234    if (sd->password_mode) memset(sd->text, 0, sd->char_length);
1235    free(sd->text);
1236    free(sd);
1237
1238    _e_editable_smart_use--;
1239    if (_e_editable_smart_use <= 0)
1240      {
1241         evas_smart_free(_e_editable_smart);
1242         _e_editable_smart = NULL;
1243      }
1244 }
1245
1246 /* Moves the editable object */
1247 static void
1248 _e_editable_smart_move(Evas_Object *object, Evas_Coord x, Evas_Coord y)
1249 {
1250    E_Editable_Smart_Data *sd;
1251    Evas_Coord prev_x, prev_y;
1252    Evas_Coord ox, oy;
1253
1254    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1255      return;
1256
1257    evas_object_geometry_get(object, &prev_x, &prev_y, NULL, NULL);
1258    evas_object_move(sd->clip_object, x, y);
1259    evas_object_move(sd->event_object, x, y);
1260    evas_object_geometry_get(sd->text_object, &ox, &oy, NULL, NULL);
1261    evas_object_move(sd->text_object, ox + (x - prev_x), oy + (y - prev_y));
1262    evas_object_geometry_get(sd->cursor_object, &ox, &oy, NULL, NULL);
1263    evas_object_move(sd->cursor_object, ox + (x - prev_x), oy + (y - prev_y));
1264    evas_object_geometry_get(sd->selection_object, &ox, &oy, NULL, NULL);
1265    evas_object_move(sd->selection_object, ox + (x - prev_x), oy + (y - prev_y));
1266 }
1267
1268 /* Resizes the editable object */
1269 static void
1270 _e_editable_smart_resize(Evas_Object *object, Evas_Coord w, Evas_Coord h)
1271 {
1272    E_Editable_Smart_Data *sd;
1273
1274    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1275      return;
1276
1277    evas_object_resize(sd->clip_object, w, h);
1278    evas_object_resize(sd->event_object, w, h);
1279    _e_editable_text_position_update(object, w);
1280 }
1281
1282 /* Shows the editable object */
1283 static void
1284 _e_editable_smart_show(Evas_Object *object)
1285 {
1286    E_Editable_Smart_Data *sd;
1287
1288    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1289      return;
1290
1291    evas_object_show(sd->clip_object);
1292    evas_object_show(sd->event_object);
1293    evas_object_show(sd->text_object);
1294
1295    if (sd->cursor_visible)
1296      {
1297         evas_object_show(sd->cursor_object);
1298         edje_object_signal_emit(sd->cursor_object, "e,action,show,cursor", "e");
1299      }
1300
1301    if ((sd->selection_visible) && (sd->cursor_pos != sd->selection_pos))
1302      evas_object_show(sd->selection_object);
1303 }
1304
1305 /* Hides the editable object */
1306 static void
1307 _e_editable_smart_hide(Evas_Object *object)
1308 {
1309    E_Editable_Smart_Data *sd;
1310
1311    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1312      return;
1313
1314    evas_object_hide(sd->clip_object);
1315    evas_object_hide(sd->event_object);
1316    evas_object_hide(sd->text_object);
1317    evas_object_hide(sd->cursor_object);
1318    evas_object_hide(sd->selection_object);
1319 }
1320
1321 /* Changes the color of the editable object */
1322 static void
1323 _e_editable_color_set(Evas_Object *object, int r, int g, int b, int a)
1324 {
1325    E_Editable_Smart_Data *sd;
1326
1327    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1328      return;
1329    evas_object_color_set(sd->clip_object, r, g, b, a);
1330 }
1331
1332 /* Clips the editable object against "clip" */
1333 static void
1334 _e_editable_clip_set(Evas_Object *object, Evas_Object *clip)
1335 {
1336    E_Editable_Smart_Data *sd;
1337
1338    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1339      return;
1340    evas_object_clip_set(sd->clip_object, clip);
1341 }
1342
1343 /* Unclips the editable object */
1344 static void
1345 _e_editable_clip_unset(Evas_Object *object)
1346 {
1347    E_Editable_Smart_Data *sd;
1348
1349    if ((!object) || (!(sd = evas_object_smart_data_get(object))))
1350      return;
1351    evas_object_clip_unset(sd->clip_object);
1352 }