Imported Upstream version 1.7.7
[platform/upstream/edje.git] / src / lib / edje_util.c
1 #include "edje_private.h"
2
3 typedef struct _Edje_Box_Layout Edje_Box_Layout;
4 struct _Edje_Box_Layout
5 {
6    EINA_RBTREE;
7    Evas_Object_Box_Layout func;
8    void                  *(*layout_data_get)(void *);
9    void                   (*layout_data_free)(void *);
10    void                  *data;
11    void                   (*free_data)(void *);
12    char                   name[];
13 };
14
15 static Eina_Hash *_edje_color_class_hash = NULL;
16 static Eina_Hash *_edje_color_class_member_hash = NULL;
17
18 static Eina_Hash *_edje_text_class_hash = NULL;
19 static Eina_Hash *_edje_text_class_member_hash = NULL;
20
21 static Eina_Rbtree *_edje_box_layout_registry = NULL;
22
23 char *_edje_fontset_append = NULL;
24 FLOAT_T _edje_scale = ZERO;
25 Eina_Bool _edje_password_show_last = EINA_FALSE;
26 FLOAT_T _edje_password_show_last_timeout = ZERO;
27 int _edje_freeze_val = 0;
28 int _edje_freeze_calc_count = 0;
29 Eina_List *_edje_freeze_calc_list = NULL;
30
31 typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data;
32 struct _Edje_List_Foreach_Data
33 {
34    Eina_List *list;
35 };
36
37 typedef struct _Edje_List_Refcount Edje_List_Refcount;
38 struct _Edje_List_Refcount
39 {
40    EINA_REFCOUNT;
41
42    Eina_List *lookup;
43 };
44
45 static Eina_Bool _edje_color_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
46 static Eina_Bool _edje_text_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
47 static void      _edje_object_image_preload_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
48 static void      _edje_object_signal_preload_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
49 static void      _edje_user_def_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__);
50 static void      _edje_table_child_remove(Edje_Real_Part *rp, Evas_Object *child);
51 static void      _edje_box_child_remove(Edje_Real_Part *rp, Evas_Object *child);
52
53 Edje_Real_Part  *_edje_real_part_recursive_get_helper(const Edje *ed, char **path);
54
55 static Edje_User_Defined *
56 _edje_user_definition_new(Edje_User_Defined_Type type, const char *part, Edje *ed)
57 {
58    Edje_User_Defined *eud;
59
60    eud = malloc(sizeof (Edje_User_Defined));
61    if (!eud) return NULL;
62
63    eud->type = type;
64    eud->part = eina_stringshare_add(part);
65    eud->ed = ed;
66    ed->user_defined = eina_list_append(ed->user_defined, eud);
67
68    return eud;
69 }
70
71 void
72 _edje_user_definition_remove(Edje_User_Defined *eud, Evas_Object *child)
73 {
74    eud->ed->user_defined = eina_list_remove(eud->ed->user_defined, eud);
75
76    if (child) evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
77    eina_stringshare_del(eud->part);
78    free(eud);
79 }
80
81 void
82 _edje_user_definition_free(Edje_User_Defined *eud)
83 {
84    Evas_Object *child = NULL;
85    Edje_Real_Part *rp;
86
87    eud->ed->user_defined = eina_list_remove(eud->ed->user_defined, eud);
88
89    switch (eud->type)
90      {
91       case EDJE_USER_SWALLOW:
92         child = eud->u.swallow.child;
93         rp = _edje_real_part_recursive_get(eud->ed, eud->part);
94         if (rp)
95           {
96              _edje_real_part_swallow_clear(rp);
97              rp->swallowed_object = NULL;
98              rp->swallow_params.min.w = 0;
99              rp->swallow_params.min.h = 0;
100              rp->swallow_params.max.w = 0;
101              rp->swallow_params.max.h = 0;
102              rp->edje->dirty = 1;
103              rp->edje->recalc_call = 1;
104 #ifdef EDJE_CALC_CACHE
105              rp->invalidate = 1;
106 #endif
107              _edje_recalc_do(rp->edje);
108           }
109         break;
110
111       case EDJE_USER_BOX_PACK:
112         child = eud->u.box.child;
113         rp = _edje_real_part_recursive_get(eud->ed, eud->part);
114         _edje_box_child_remove(rp, child);
115         break;
116
117       case EDJE_USER_TABLE_PACK:
118         child = eud->u.table.child;
119         rp = _edje_real_part_recursive_get(eud->ed, eud->part);
120         _edje_table_child_remove(rp, child);
121         break;
122
123       case EDJE_USER_STRING:
124       case EDJE_USER_DRAG_STEP:
125       case EDJE_USER_DRAG_PAGE:
126       case EDJE_USER_DRAG_VALUE:
127       case EDJE_USER_DRAG_SIZE:
128         break;
129      }
130
131    _edje_user_definition_remove(eud, child);
132 }
133
134 static void
135 _edje_user_def_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
136 {
137    Edje_User_Defined *eud = data;
138
139    _edje_user_definition_free(eud);
140 }
141
142 static void
143 _edje_class_member_direct_del(const char *class, Edje_List_Refcount *lookup, Eina_Hash *hash)
144 {
145    Eina_List *members;
146
147    members = eina_hash_find(hash, class);
148    members = eina_list_remove_list(members, lookup->lookup);
149    eina_hash_set(hash, class, members);
150    free(lookup);
151 }
152
153 static void
154 _edje_class_member_add(Edje *ed, Eina_Hash **ehash, Eina_Hash **ghash, const char *class)
155 {
156    Edje_List_Refcount *lookup;
157    Eina_List *members;
158
159    if ((!ed) || (!ehash) || (!ghash) || (!class)) return;
160
161    lookup = eina_hash_find(*ehash, class);
162    if (lookup)
163      {
164         EINA_REFCOUNT_REF(lookup);
165         return;
166      }
167
168    lookup = malloc(sizeof (Edje_List_Refcount));
169    if (!lookup) return;
170    EINA_REFCOUNT_INIT(lookup);
171
172    /* Get members list */
173    members = eina_hash_find(*ghash, class);
174
175    /* Update the member list */
176    lookup->lookup = members = eina_list_prepend(members, ed);
177
178    /* Don't loose track of members list */
179    if (!*ehash)
180      *ehash = eina_hash_string_small_new(NULL);
181    eina_hash_add(*ehash, class, lookup);
182
183    /* Reset the member list to the right pointer */
184    if (!*ghash)
185      *ghash = eina_hash_string_superfast_new(NULL);
186    eina_hash_set(*ghash, class, members);
187 }
188
189 static void
190 _edje_class_member_del(Eina_Hash **ehash, Eina_Hash **ghash, const char *class)
191 {
192    Edje_List_Refcount *lookup;
193    Eina_List *members;
194
195    if ((!ehash) || (!ghash) || (!class)) return;
196    members = eina_hash_find(*ghash, class);
197    if (!members) return;
198
199    lookup = eina_hash_find(*ehash, class);
200    if (!lookup) return;
201
202    EINA_REFCOUNT_UNREF(lookup)
203    {
204       members = eina_list_remove_list(members, lookup->lookup);
205       eina_hash_set(*ghash, class, members);
206
207       eina_hash_del(*ehash, class, lookup);
208       free(lookup);
209    }
210 }
211
212 static Eina_Bool
213 member_list_free(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
214 {
215    eina_list_free(data);
216    return EINA_TRUE;
217 }
218
219 static void
220 _edje_class_members_free(Eina_Hash **ghash)
221 {
222    if (!ghash || !*ghash) return;
223    eina_hash_foreach(*ghash, member_list_free, NULL);
224    eina_hash_free(*ghash);
225    *ghash = NULL;
226 }
227
228 /************************** API Routines **************************/
229
230 #define FASTFREEZE 1
231
232 EAPI void
233 edje_freeze(void)
234 {
235 #ifdef FASTFREEZE
236    _edje_freeze_val++;
237 #else
238 // FIXME: could just have a global freeze instead of per object
239 // above i tried.. but this broke some things. notable e17's menus. why?
240    Eina_List *l;
241    Evas_Object *data;
242
243    EINA_LIST_FOREACH(_edje_edjes, l, data)
244      edje_object_freeze(data);
245 #endif
246 }
247
248 #ifdef FASTFREEZE
249 static void
250 _edje_thaw_edje(Edje *ed)
251 {
252    unsigned int i;
253
254    for (i = 0; i < ed->table_parts_size; i++)
255      {
256         Edje_Real_Part *rp;
257
258         rp = ed->table_parts[i];
259         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
260           {
261              Edje *ed2;
262
263              ed2 = _edje_fetch(rp->swallowed_object);
264              if (ed2) _edje_thaw_edje(ed2);
265           }
266      }
267    if ((ed->recalc) && (ed->freeze <= 0)) _edje_recalc_do(ed);
268 }
269
270 #endif
271
272 EAPI void
273 edje_thaw(void)
274 {
275 #ifdef FASTFREEZE
276    _edje_freeze_val--;
277    if ((_edje_freeze_val <= 0) && (_edje_freeze_calc_count > 0))
278      {
279         Edje *ed;
280
281         _edje_freeze_calc_count = 0;
282         EINA_LIST_FREE(_edje_freeze_calc_list, ed)
283           {
284              _edje_thaw_edje(ed);
285              ed->freeze_calc = 0;
286           }
287      }
288 #else
289    Evas_Object *data;
290
291 // FIXME: could just have a global freeze instead of per object
292 // comment as above.. why?
293    Eina_List *l;
294
295    EINA_LIST_FOREACH(_edje_edjes, l, data)
296      edje_object_thaw(data);
297 #endif
298 }
299
300 EAPI void
301 edje_fontset_append_set(const char *fonts)
302 {
303    if (_edje_fontset_append)
304      free(_edje_fontset_append);
305    _edje_fontset_append = fonts ? strdup(fonts) : NULL;
306 }
307
308 EAPI const char *
309 edje_fontset_append_get(void)
310 {
311    return _edje_fontset_append;
312 }
313
314 EAPI void
315 edje_scale_set(double scale)
316 {
317    Eina_List *l;
318    Evas_Object *data;
319
320    if (_edje_scale == FROM_DOUBLE(scale)) return;
321    _edje_scale = FROM_DOUBLE(scale);
322    EINA_LIST_FOREACH(_edje_edjes, l, data)
323      edje_object_calc_force(data);
324 }
325
326 EAPI double
327 edje_scale_get(void)
328 {
329    return TO_DOUBLE(_edje_scale);
330 }
331
332 EAPI void
333 edje_password_show_last_set(Eina_Bool password_show_last)
334 {
335    if (_edje_password_show_last == password_show_last) return;
336    _edje_password_show_last = password_show_last;
337 }
338
339 EAPI void
340 edje_password_show_last_timeout_set(double password_show_last_timeout)
341 {
342    if (_edje_password_show_last_timeout == FROM_DOUBLE(password_show_last_timeout)) return;
343    _edje_password_show_last_timeout = FROM_DOUBLE(password_show_last_timeout);
344 }
345
346 EAPI Eina_Bool
347 edje_object_scale_set(Evas_Object *obj, double scale)
348 {
349    Edje *ed, *ged;
350    Evas_Object *o;
351    Eina_List *l;
352    unsigned int i;
353
354    ed = _edje_fetch(obj);
355    if (!ed) return EINA_FALSE;
356    if (ed->scale == scale) return EINA_TRUE;
357    ed->scale = FROM_DOUBLE(scale);
358    EINA_LIST_FOREACH(ed->groups, l, ged)
359      ged->scale = ed->scale;
360    EINA_LIST_FOREACH(ed->subobjs, l, o)
361      edje_object_calc_force(o);
362    for (i = 0; i < ed->table_parts_size; ++i)
363      {
364         Edje_Real_Part *ep;
365         ep = ed->table_parts[i];
366         if ((ep->part->type == EDJE_PART_TYPE_BOX)
367             || (ep->part->type == EDJE_PART_TYPE_TABLE))
368           {
369              EINA_LIST_FOREACH(ep->items, l, o)
370                edje_object_scale_set(o, scale);
371           }
372      }
373    edje_object_calc_force(obj);
374    return EINA_TRUE;
375 }
376
377 EAPI double
378 edje_object_scale_get(const Evas_Object *obj)
379 {
380    Edje *ed;
381
382    ed = _edje_fetch(obj);
383    if (!ed) return 0.0;
384    return TO_DOUBLE(ed->scale);
385 }
386
387 EAPI Eina_Bool
388 edje_object_mirrored_get(const Evas_Object *obj)
389 {
390    Edje *ed;
391
392    ed = _edje_fetch(obj);
393    if (!ed) return EINA_FALSE;
394
395    return ed->is_rtl;
396 }
397
398 void
399 _edje_object_orientation_inform(Evas_Object *obj)
400 {
401    if (edje_object_mirrored_get(obj))
402      edje_object_signal_emit(obj, "edje,state,rtl", "edje");
403    else
404      edje_object_signal_emit(obj, "edje,state,ltr", "edje");
405 }
406
407 EAPI void
408 edje_object_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
409 {
410    Edje *ed;
411    unsigned int i;
412
413    ed = _edje_fetch(obj);
414    if (!ed) return;
415    if (ed->is_rtl == rtl) return;
416
417    ed->is_rtl = rtl;
418
419    for (i = 0; i < ed->table_parts_size; i++)
420      {
421         Edje_Real_Part *ep;
422         const char *s;
423         double v;
424
425         ep = ed->table_parts[i];
426         s = ep->param1.description->state.name,
427         v = ep->param1.description->state.value;
428         _edje_part_description_apply(ed, ep, s, v, NULL, 0.0);
429         ep->chosen_description = ep->param1.description;
430      }
431    _edje_recalc_do(ed);
432
433    _edje_object_orientation_inform(obj);
434
435    return;
436 }
437
438 EAPI const char *
439 edje_object_data_get(const Evas_Object *obj, const char *key)
440 {
441    Edje *ed;
442
443    ed = _edje_fetch(obj);
444    if ((!ed) || (!key))
445      return NULL;
446    if (!ed->collection) return NULL;
447    if (!ed->collection->data) return NULL;
448    return edje_string_get(eina_hash_find(ed->collection->data, key));
449 }
450
451 EAPI int
452 edje_object_freeze(Evas_Object *obj)
453 {
454    Edje *ed;
455    unsigned int i;
456
457    ed = _edje_fetch(obj);
458    if (!ed) return 0;
459    for (i = 0; i < ed->table_parts_size; i++)
460      {
461         Edje_Real_Part *rp;
462         rp = ed->table_parts[i];
463         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
464           edje_object_freeze(rp->swallowed_object);
465      }
466    return _edje_freeze(ed);
467 }
468
469 EAPI int
470 edje_object_thaw(Evas_Object *obj)
471 {
472    Edje *ed;
473    unsigned int i;
474
475    ed = _edje_fetch(obj);
476    if (!ed) return 0;
477    for (i = 0; i < ed->table_parts_size; i++)
478      {
479         Edje_Real_Part *rp;
480
481         rp = ed->table_parts[i];
482         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
483           edje_object_thaw(rp->swallowed_object);
484      }
485    return _edje_thaw(ed);
486 }
487
488 EAPI Eina_Bool
489 edje_color_class_set(const char *color_class, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
490 {
491    Eina_List *members;
492    Edje_Color_Class *cc;
493
494    if (!color_class) return EINA_FALSE;
495
496    cc = eina_hash_find(_edje_color_class_hash, color_class);
497    if (!cc)
498      {
499         cc = calloc(1, sizeof(Edje_Color_Class));
500         if (!cc) return EINA_FALSE;
501         cc->name = eina_stringshare_add(color_class);
502         if (!cc->name)
503           {
504              free(cc);
505              return EINA_FALSE;
506           }
507         if (!_edje_color_class_hash)
508           _edje_color_class_hash = eina_hash_string_superfast_new(NULL);
509         eina_hash_add(_edje_color_class_hash, color_class, cc);
510      }
511
512    if (r < 0) r = 0;
513    else if (r > 255)
514      r = 255;
515    if (g < 0) g = 0;
516    else if (g > 255)
517      g = 255;
518    if (b < 0) b = 0;
519    else if (b > 255)
520      b = 255;
521    if (a < 0) a = 0;
522    else if (a > 255)
523      a = 255;
524    if ((cc->r == r) && (cc->g == g) &&
525        (cc->b == b) && (cc->a == a) &&
526        (cc->r2 == r2) && (cc->g2 == g2) &&
527        (cc->b2 == b2) && (cc->a2 == a2) &&
528        (cc->r3 == r3) && (cc->g3 == g3) &&
529        (cc->b3 == b3) && (cc->a3 == a3))
530      return EINA_TRUE;
531    cc->r = r;
532    cc->g = g;
533    cc->b = b;
534    cc->a = a;
535    cc->r2 = r2;
536    cc->g2 = g2;
537    cc->b2 = b2;
538    cc->a2 = a2;
539    cc->r3 = r3;
540    cc->g3 = g3;
541    cc->b3 = b3;
542    cc->a3 = a3;
543
544    members = eina_hash_find(_edje_color_class_member_hash, color_class);
545    while (members)
546      {
547         Edje *ed;
548
549         ed = eina_list_data_get(members);
550         ed->dirty = 1;
551         ed->recalc_call = 1;
552 #ifdef EDJE_CALC_CACHE
553         ed->all_part_change = 1;
554 #endif
555         _edje_recalc(ed);
556         _edje_emit(ed, "color_class,set", color_class);
557         members = eina_list_next(members);
558      }
559    return EINA_TRUE;
560 }
561
562 EAPI Eina_Bool
563 edje_color_class_get(const char *color_class, int *r, int *g, int *b, int *a, int *r2, int *g2, int *b2, int *a2, int *r3, int *g3, int *b3, int *a3)
564 {
565    Edje_Color_Class *cc;
566
567    if (!color_class)
568      cc = NULL;
569    else
570      cc = eina_hash_find(_edje_color_class_hash, color_class);
571
572    if (cc)
573      {
574 #define X(C)              if (C) \
575     *C = cc->C
576 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
577         S(r, g, b, a);
578         S(r2, g2, b2, a2);
579         S(r3, g3, b3, a3);
580 #undef S
581 #undef X
582         return EINA_TRUE;
583      }
584    else
585      {
586 #define X(C)              if (C) \
587     *C = 0
588 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
589         S(r, g, b, a);
590         S(r2, g2, b2, a2);
591         S(r3, g3, b3, a3);
592 #undef S
593 #undef X
594         return EINA_FALSE;
595      }
596 }
597
598 void
599 edje_color_class_del(const char *color_class)
600 {
601    Edje_Color_Class *cc;
602    Eina_List *members;
603
604    if (!color_class) return;
605
606    cc = eina_hash_find(_edje_color_class_hash, color_class);
607    if (!cc) return;
608
609    eina_hash_del(_edje_color_class_hash, color_class, cc);
610    eina_stringshare_del(cc->name);
611    free(cc);
612
613    members = eina_hash_find(_edje_color_class_member_hash, color_class);
614    while (members)
615      {
616         Edje *ed;
617
618         ed = eina_list_data_get(members);
619         ed->dirty = 1;
620         ed->recalc_call = 1;
621 #ifdef EDJE_CALC_CACHE
622         ed->all_part_change = 1;
623 #endif
624         _edje_recalc(ed);
625         _edje_emit(ed, "color_class,del", color_class);
626         members = eina_list_next(members);
627      }
628 }
629
630 Eina_List *
631 edje_color_class_list(void)
632 {
633    Edje_List_Foreach_Data fdata;
634
635    if (!_edje_color_class_hash) return NULL;
636    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
637    eina_hash_foreach(_edje_color_class_hash,
638                      _edje_color_class_list_foreach, &fdata);
639
640    return fdata.list;
641 }
642
643 static Eina_Bool
644 _edje_color_class_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
645 {
646    Edje_List_Foreach_Data *fd;
647
648    fd = fdata;
649    fd->list = eina_list_append(fd->list, strdup(key));
650    return EINA_TRUE;
651 }
652
653 EAPI Eina_Bool
654 edje_object_color_class_set(Evas_Object *obj, const char *color_class, int r, int g, int b, int a, int r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
655 {
656    Edje *ed;
657    Edje_Color_Class *cc;
658    unsigned int i;
659
660    ed = _edje_fetch(obj);
661    if ((!ed) || (!color_class)) return EINA_FALSE;
662    if (r < 0) r = 0;
663    else if (r > 255)
664      r = 255;
665    if (g < 0) g = 0;
666    else if (g > 255)
667      g = 255;
668    if (b < 0) b = 0;
669    else if (b > 255)
670      b = 255;
671    if (a < 0) a = 0;
672    else if (a > 255)
673      a = 255;
674    cc = eina_hash_find(ed->color_classes, color_class);
675    if (cc)
676      {
677         if ((cc->r == r) && (cc->g == g) &&
678             (cc->b == b) && (cc->a == a) &&
679             (cc->r2 == r2) && (cc->g2 == g2) &&
680             (cc->b2 == b2) && (cc->a2 == a2) &&
681             (cc->r3 == r3) && (cc->g3 == g3) &&
682             (cc->b3 == b3) && (cc->a3 == a3))
683           return EINA_TRUE;
684         cc->r = r;
685         cc->g = g;
686         cc->b = b;
687         cc->a = a;
688         cc->r2 = r2;
689         cc->g2 = g2;
690         cc->b2 = b2;
691         cc->a2 = a2;
692         cc->r3 = r3;
693         cc->g3 = g3;
694         cc->b3 = b3;
695         cc->a3 = a3;
696         ed->dirty = 1;
697         ed->recalc_call = 1;
698 #ifdef EDJE_CALC_CACHE
699         ed->all_part_change = 1;
700 #endif
701         _edje_recalc(ed);
702         return EINA_TRUE;
703      }
704
705    color_class = eina_stringshare_add(color_class);
706    if (!color_class) return EINA_FALSE;
707    cc = malloc(sizeof(Edje_Color_Class));
708    if (!cc)
709      {
710         eina_stringshare_del(color_class);
711         return EINA_FALSE;
712      }
713    cc->name = color_class;
714    cc->r = r;
715    cc->g = g;
716    cc->b = b;
717    cc->a = a;
718    cc->r2 = r2;
719    cc->g2 = g2;
720    cc->b2 = b2;
721    cc->a2 = a2;
722    cc->r3 = r3;
723    cc->g3 = g3;
724    cc->b3 = b3;
725    cc->a3 = a3;
726    eina_hash_direct_add(ed->color_classes, cc->name, cc);
727    ed->dirty = 1;
728    ed->recalc_call = 1;
729 #ifdef EDJE_CALC_CACHE
730    ed->all_part_change = 1;
731 #endif
732
733    for (i = 0; i < ed->table_parts_size; i++)
734      {
735         Edje_Real_Part *rp;
736
737         rp = ed->table_parts[i];
738         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
739           edje_object_color_class_set(rp->swallowed_object, color_class,
740                                       r, g, b, a, r2, g2, b2, a2, r3, g3, b3,
741                                       a3);
742      }
743
744    _edje_recalc(ed);
745    _edje_emit(ed, "color_class,set", color_class);
746    return EINA_TRUE;
747 }
748
749 EAPI Eina_Bool
750 edje_object_color_class_get(const Evas_Object *obj, const char *color_class, int *r, int *g, int *b, int *a, int *r2, int *g2, int *b2, int *a2, int *r3, int *g3, int *b3, int *a3)
751 {
752    Edje *ed = _edje_fetch(obj);
753    Edje_Color_Class *cc = _edje_color_class_find(ed, color_class);
754
755    if (cc)
756      {
757 #define X(C)              if (C) \
758     *C = cc->C
759 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
760         S(r, g, b, a);
761         S(r2, g2, b2, a2);
762         S(r3, g3, b3, a3);
763 #undef S
764 #undef X
765         return EINA_TRUE;
766      }
767    else
768      {
769 #define X(C)              if (C) \
770     *C = 0
771 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
772         S(r, g, b, a);
773         S(r2, g2, b2, a2);
774         S(r3, g3, b3, a3);
775 #undef S
776 #undef X
777         return EINA_FALSE;
778      }
779 }
780
781 void
782 edje_object_color_class_del(Evas_Object *obj, const char *color_class)
783 {
784    Edje *ed;
785    Edje_Color_Class *cc = NULL;
786    unsigned int i;
787
788    ed = _edje_fetch(obj);
789
790    if ((!ed) || (!color_class)) return;
791
792    eina_hash_del(ed->color_classes, color_class, cc);
793
794    for (i = 0; i < ed->table_parts_size; i++)
795      {
796         Edje_Real_Part *rp;
797
798         rp = ed->table_parts[i];
799         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
800           edje_object_color_class_del(rp->swallowed_object, color_class);
801      }
802
803    ed->dirty = 1;
804    ed->recalc_call = 1;
805 #ifdef EDJE_CALC_CACHE
806    ed->all_part_change = 1;
807 #endif
808    _edje_recalc(ed);
809    _edje_emit(ed, "color_class,del", color_class);
810 }
811
812 EAPI Eina_Bool
813 edje_text_class_set(const char *text_class, const char *font, Evas_Font_Size size)
814 {
815    Eina_List *members;
816    Edje_Text_Class *tc;
817
818    if (!text_class) return EINA_FALSE;
819    if (!font) font = "";
820
821    tc = eina_hash_find(_edje_text_class_hash, text_class);
822    /* Create new text class */
823    if (!tc)
824      {
825         tc = calloc(1, sizeof(Edje_Text_Class));
826         if (!tc) return EINA_FALSE;
827         tc->name = eina_stringshare_add(text_class);
828         if (!tc->name)
829           {
830              free(tc);
831              return EINA_FALSE;
832           }
833         if (!_edje_text_class_hash) _edje_text_class_hash = eina_hash_string_superfast_new(NULL);
834         eina_hash_add(_edje_text_class_hash, text_class, tc);
835
836         tc->font = eina_stringshare_add(font);
837         tc->size = size;
838      }
839    else
840      {
841         /* Match and the same, return */
842         if (((tc->font && font) && !strcmp(tc->font, font)) &&
843             (tc->size == size))
844           return EINA_TRUE;
845
846         /* Update the class found */
847         eina_stringshare_replace(&tc->font, font);
848         tc->size = size;
849      }
850
851    /* Tell all members of the text class to recalc */
852    members = eina_hash_find(_edje_text_class_member_hash, text_class);
853    while (members)
854      {
855         Edje *ed;
856
857         ed = eina_list_data_get(members);
858         ed->dirty = 1;
859         ed->recalc_call = 1;
860         _edje_textblock_style_all_update(ed);
861 #ifdef EDJE_CALC_CACHE
862         ed->text_part_change = 1;
863 #endif
864         _edje_recalc(ed);
865         members = eina_list_next(members);
866      }
867    return EINA_TRUE;
868 }
869
870 void
871 edje_text_class_del(const char *text_class)
872 {
873    Edje_Text_Class *tc;
874    Eina_List *members;
875
876    if (!text_class) return;
877
878    tc = eina_hash_find(_edje_text_class_hash, text_class);
879    if (!tc) return;
880
881    eina_hash_del(_edje_text_class_hash, text_class, tc);
882    eina_stringshare_del(tc->name);
883    eina_stringshare_del(tc->font);
884    free(tc);
885
886    members = eina_hash_find(_edje_text_class_member_hash, text_class);
887    while (members)
888      {
889         Edje *ed;
890
891         ed = eina_list_data_get(members);
892         ed->dirty = 1;
893         _edje_textblock_style_all_update(ed);
894 #ifdef EDJE_CALC_CACHE
895         ed->text_part_change = 1;
896 #endif
897         _edje_recalc(ed);
898         members = eina_list_next(members);
899      }
900 }
901
902 Eina_List *
903 edje_text_class_list(void)
904 {
905    Edje_List_Foreach_Data fdata;
906
907    if (!_edje_text_class_hash) return NULL;
908    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
909    eina_hash_foreach(_edje_text_class_hash,
910                      _edje_text_class_list_foreach, &fdata);
911    return fdata.list;
912 }
913
914 static Eina_Bool
915 _edje_text_class_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
916 {
917    Edje_List_Foreach_Data *fd;
918
919    fd = fdata;
920    fd->list = eina_list_append(fd->list, eina_stringshare_add(key));
921    return EINA_TRUE;
922 }
923
924 EAPI Eina_Bool
925 edje_object_text_class_set(Evas_Object *obj, const char *text_class, const char *font, Evas_Font_Size size)
926 {
927    Edje *ed;
928    Eina_List *l;
929    Edje_Text_Class *tc = NULL;
930    unsigned int i;
931
932    ed = _edje_fetch(obj);
933    if ((!ed) || (!text_class)) return EINA_FALSE;
934
935    /* for each text_class in the edje */
936    EINA_LIST_FOREACH(ed->text_classes, l, tc)
937      {
938         if ((tc->name) && (!strcmp(tc->name, text_class)))
939           {
940              /* Match and the same, return */
941              if ((tc->size == size) &&
942                  ((tc->font == font) ||
943                   (tc->font && font && !strcmp(tc->font, font))))
944                return EINA_TRUE;
945
946              /* Update new text class properties */
947              eina_stringshare_replace(&tc->font, font);
948              tc->size = size;
949              break;
950           }
951      }
952
953    if (!tc)
954      {
955         /* No matches, create a new text class */
956         tc = calloc(1, sizeof(Edje_Text_Class));
957         if (!tc) return EINA_FALSE;
958         tc->name = eina_stringshare_add(text_class);
959         if (!tc->name)
960           {
961              free(tc);
962              return EINA_FALSE;
963           }
964         tc->font = eina_stringshare_add(font);
965         tc->size = size;
966         /* Add to edje's text class list */
967         ed->text_classes = eina_list_append(ed->text_classes, tc);
968      }
969
970    for (i = 0; i < ed->table_parts_size; i++)
971      {
972         Edje_Real_Part *rp;
973
974         rp = ed->table_parts[i];
975         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
976           edje_object_text_class_set(rp->swallowed_object, text_class,
977                                      font, size);
978      }
979
980    ed->dirty = 1;
981    ed->recalc_call = 1;
982 #ifdef EDJE_CALC_CACHE
983    ed->text_part_change = 1;
984 #endif
985    _edje_textblock_style_all_update(ed);
986    _edje_recalc(ed);
987    return EINA_TRUE;
988 }
989
990 EAPI Eina_Bool
991 edje_object_part_exists(const Evas_Object *obj, const char *part)
992 {
993    Edje *ed;
994    Edje_Real_Part *rp;
995
996    ed = _edje_fetch(obj);
997    if ((!ed) || (!part)) return EINA_FALSE;
998    rp = _edje_real_part_recursive_get(ed, part);
999    if (!rp) return EINA_FALSE;
1000    return EINA_TRUE;
1001 }
1002
1003 EAPI const Evas_Object *
1004 edje_object_part_object_get(const Evas_Object *obj, const char *part)
1005 {
1006    Edje *ed;
1007    Edje_Real_Part *rp;
1008
1009    ed = _edje_fetch(obj);
1010    if ((!ed) || (!part)) return NULL;
1011
1012    /* Need to recalc before providing the object. */
1013    _edje_recalc_do(ed);
1014
1015    rp = _edje_real_part_recursive_get(ed, part);
1016    if (!rp) return NULL;
1017    return rp->object;
1018 }
1019
1020 EAPI Eina_Bool
1021 edje_object_part_geometry_get(const Evas_Object *obj, const char *part, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1022 {
1023    Edje *ed;
1024    Edje_Real_Part *rp;
1025
1026    ed = _edje_fetch(obj);
1027    if ((!ed) || (!part))
1028      {
1029         if (x) *x = 0;
1030         if (y) *y = 0;
1031         if (w) *w = 0;
1032         if (h) *h = 0;
1033         return EINA_FALSE;
1034      }
1035
1036    /* Need to recalc before providing the object. */
1037    _edje_recalc_do(ed);
1038
1039    rp = _edje_real_part_recursive_get(ed, part);
1040    if (!rp)
1041      {
1042         if (x) *x = 0;
1043         if (y) *y = 0;
1044         if (w) *w = 0;
1045         if (h) *h = 0;
1046         return EINA_FALSE;
1047      }
1048    if (x) *x = rp->x;
1049    if (y) *y = rp->y;
1050    if (w) *w = rp->w;
1051    if (h) *h = rp->h;
1052    return EINA_TRUE;
1053 }
1054
1055 EAPI void
1056 edje_object_item_provider_set(Evas_Object *obj, Edje_Item_Provider_Cb func, void *data)
1057 {
1058    Edje *ed;
1059
1060    ed = _edje_fetch(obj);
1061    if (!ed) return;
1062    ed->item_provider.func = func;
1063    ed->item_provider.data = data;
1064 }
1065
1066 /* FIXDOC: New Function */
1067 EAPI void
1068 edje_object_text_change_cb_set(Evas_Object *obj, Edje_Text_Change_Cb func, void *data)
1069 {
1070    Edje *ed;
1071    unsigned int i;
1072
1073    ed = _edje_fetch(obj);
1074    if (!ed) return;
1075    ed->text_change.func = func;
1076    ed->text_change.data = data;
1077
1078    for (i = 0; i < ed->table_parts_size; i++)
1079      {
1080         Edje_Real_Part *rp;
1081
1082         rp = ed->table_parts[i];
1083         if ((rp->part->type == EDJE_PART_TYPE_GROUP) && (rp->swallowed_object))
1084           edje_object_text_change_cb_set(rp->swallowed_object, func, data);
1085      }
1086 }
1087
1088 Eina_Bool
1089 _edje_object_part_text_raw_set(Evas_Object *obj, Edje_Real_Part *rp, const char *part, const char *text)
1090 {
1091    if ((!rp->text.text) && (!text))
1092      return EINA_TRUE;  /* nothing to do, no error */
1093    if ((rp->text.text) && (text) &&
1094        (!strcmp(rp->text.text, text)))
1095      return EINA_TRUE;  /* nothing to do, no error */
1096    if (rp->text.text)
1097      {
1098         eina_stringshare_del(rp->text.text);
1099         rp->text.text = NULL;
1100      }
1101    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1102      _edje_entry_text_markup_set(rp, text);
1103    else
1104    if (text)
1105      rp->text.text = eina_stringshare_add(text);
1106    rp->edje->dirty = 1;
1107    rp->edje->recalc_call = 1;
1108    rp->edje->recalc_hints = 1;
1109 #ifdef EDJE_CALC_CACHE
1110    rp->invalidate = 1;
1111 #endif
1112    _edje_recalc(rp->edje);
1113    if (rp->edje->text_change.func)
1114      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
1115    return EINA_TRUE;
1116 }
1117
1118 Eina_Bool
1119 _edje_object_part_text_raw_append(Evas_Object *obj, Edje_Real_Part *rp, const char *part, const char *text)
1120 {
1121    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1122      _edje_entry_text_markup_append(rp, text);
1123    else if (text)
1124      {
1125         if (rp->text.text)
1126           {
1127              char *new = NULL;
1128              int len_added = strlen(text);
1129              int len_old = strlen(rp->text.text);
1130              new = malloc(len_old + len_added + 1);
1131              memcpy(new, rp->text.text, len_old);
1132              memcpy(new + len_old, text, len_added);
1133              new[len_old + len_added] = '\0';
1134              eina_stringshare_replace(&rp->text.text, new);
1135              free(new);
1136           }
1137         else
1138           {
1139              eina_stringshare_replace(&rp->text.text, text);
1140           }
1141      }
1142    rp->edje->dirty = 1;
1143    rp->edje->recalc_call = 1;
1144 #ifdef EDJE_CALC_CACHE
1145    rp->invalidate = 1;
1146 #endif
1147    _edje_recalc(rp->edje);
1148    if (rp->edje->text_change.func)
1149      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
1150    return EINA_TRUE;
1151 }
1152
1153 EAPI void
1154 edje_object_part_text_style_user_push(Evas_Object *obj, const char *part,
1155                                       const char *style)
1156 {
1157    Edje *ed;
1158    Edje_Real_Part *rp;
1159    Evas_Textblock_Style *ts;
1160
1161    ed = _edje_fetch(obj);
1162    if ((!ed) || (!part) || (!style)) return;
1163    rp = _edje_real_part_recursive_get(ed, part);
1164    if (!rp) return;
1165    if (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) return;
1166
1167    ts = evas_textblock_style_new();
1168    evas_textblock_style_set(ts, style);
1169    evas_object_textblock_style_user_push(rp->object, ts);
1170    evas_textblock_style_free(ts);
1171    ed->recalc_hints = 1;
1172 #ifdef EDJE_CALC_CACHE
1173    rp->invalidate = 1;
1174 #endif
1175    _edje_recalc(ed);
1176 }
1177
1178 EAPI void
1179 edje_object_part_text_style_user_pop(Evas_Object *obj, const char *part)
1180 {
1181    Edje *ed;
1182    Edje_Real_Part *rp;
1183
1184    ed = _edje_fetch(obj);
1185    if ((!ed) || (!part)) return;
1186    rp = _edje_real_part_recursive_get(ed, part);
1187    if (!rp) return;
1188    if (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) return;
1189
1190    evas_object_textblock_style_user_pop(rp->object);
1191    ed->recalc_hints = 1;
1192 #ifdef EDJE_CALC_CACHE
1193    rp->invalidate = 1;
1194 #endif
1195    _edje_recalc(ed);
1196 }
1197
1198 EAPI const char *
1199 edje_object_part_text_style_user_peek(const Evas_Object *obj, const char *part)
1200 {
1201    Edje *ed;
1202    Edje_Real_Part *rp;
1203    const Evas_Textblock_Style *ts;
1204
1205    ed = _edje_fetch(obj);
1206    if ((!ed) || (!part)) return NULL;
1207    rp = _edje_real_part_recursive_get(ed, part);
1208    if (!rp) return NULL;
1209    if (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) return NULL;
1210
1211    ts = evas_object_textblock_style_user_peek(rp->object);
1212    if (ts)
1213      return evas_textblock_style_get(ts);
1214    else
1215      return NULL;
1216 }
1217
1218 static void
1219 _edje_user_define_string(Edje *ed, const char *part, const char *raw_text)
1220 {
1221    /* NOTE: This one is tricky, text is referenced in rp->text.text for the life of the
1222       rp. So on edje_object_file_set, we should first ref it, before destroying the old
1223       layout. */
1224    Edje_User_Defined *eud;
1225    Eina_List *l;
1226
1227    EINA_LIST_FOREACH(ed->user_defined, l, eud)
1228      if (eud->type == EDJE_USER_STRING && !strcmp(eud->part, part))
1229        {
1230           if (!raw_text)
1231             {
1232                _edje_user_definition_free(eud);
1233                return;
1234             }
1235           eud->u.string.text = raw_text;
1236           return;
1237        }
1238
1239    eud = _edje_user_definition_new(EDJE_USER_STRING, part, ed);
1240    if (!eud) return;
1241    eud->u.string.text = raw_text;
1242 }
1243
1244 EAPI Eina_Bool
1245 edje_object_part_text_set(Evas_Object *obj, const char *part, const char *text)
1246 {
1247    Edje *ed;
1248    Edje_Real_Part *rp;
1249    Eina_Bool r;
1250
1251    ed = _edje_fetch(obj);
1252    if ((!ed) || (!part)) return EINA_FALSE;
1253    rp = _edje_real_part_recursive_get(ed, part);
1254    if (!rp) return EINA_FALSE;
1255    if ((rp->part->type != EDJE_PART_TYPE_TEXT) &&
1256        (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return EINA_FALSE;
1257    r = _edje_object_part_text_raw_set(obj, rp, part, text);
1258    _edje_user_define_string(ed, part, rp->text.text);
1259    return r;
1260 }
1261
1262 EAPI const char *
1263 edje_object_part_text_get(const Evas_Object *obj, const char *part)
1264 {
1265    Edje *ed;
1266    Edje_Real_Part *rp;
1267
1268    ed = _edje_fetch(obj);
1269    if ((!ed) || (!part)) return NULL;
1270
1271    /* Need to recalc before providing the object. */
1272    _edje_recalc_do(ed);
1273
1274    rp = _edje_real_part_recursive_get(ed, part);
1275    if (!rp) return NULL;
1276    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1277      return _edje_entry_text_get(rp);
1278    else
1279      {
1280         if (rp->part->type == EDJE_PART_TYPE_TEXT) return rp->text.text;
1281         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1282           return evas_object_textblock_text_markup_get(rp->object);
1283      }
1284    return NULL;
1285 }
1286
1287 EAPI Eina_Bool
1288 edje_object_part_text_escaped_set(Evas_Object *obj, const char *part, const char *text)
1289 {
1290    Edje *ed;
1291    Edje_Real_Part *rp;
1292    Eina_Bool ret;
1293
1294    ed = _edje_fetch(obj);
1295    if ((!ed) || (!part)) return EINA_FALSE;
1296    rp = _edje_real_part_recursive_get(ed, part);
1297    if (!rp) return EINA_FALSE;
1298    if ((rp->part->type == EDJE_PART_TYPE_TEXT) && (text))
1299      {
1300         Eina_Strbuf *sbuf;
1301         char *esc_start = NULL, *esc_end = NULL;
1302         char *s, *p;
1303
1304         sbuf = eina_strbuf_new();
1305         p = (char *)text;
1306         s = p;
1307         for (;; )
1308           {
1309              if ((*p == 0) || (esc_end) || (esc_start))
1310                {
1311                   if (esc_end)
1312                     {
1313                        const char *escape;
1314
1315                        escape = evas_textblock_escape_string_range_get
1316                            (esc_start, esc_end + 1);
1317                        if (escape) eina_strbuf_append(sbuf, escape);
1318                        esc_start = esc_end = NULL;
1319                     }
1320                   else if (*p == 0)
1321                     {
1322                        if (!s) s = esc_start;  /* This would happen when there is & that isn't escaped */
1323                        eina_strbuf_append_length(sbuf, s, p - s);
1324                        s = NULL;
1325                     }
1326                   if (*p == 0)
1327                     break;
1328                }
1329
1330              if (*p == '&')
1331                {
1332                   if (!s) s = esc_start;  /* This would happen when there is & that isn't escaped */
1333                   esc_start = p;
1334                   esc_end = NULL;
1335                   eina_strbuf_append_length(sbuf, s, p - s);
1336                   s = NULL;
1337                }
1338              else if (*p == ';')
1339                {
1340                   if (esc_start)
1341                     {
1342                        esc_end = p;
1343                        s = p + 1;
1344                     }
1345                }
1346              p++;
1347           }
1348         ret = _edje_object_part_text_raw_set
1349             (obj, rp, part, eina_strbuf_string_get(sbuf));
1350         _edje_user_define_string(ed, part, rp->text.text);
1351         eina_strbuf_free(sbuf);
1352         return ret;
1353      }
1354    if (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) return EINA_FALSE;
1355    ret = _edje_object_part_text_raw_set(obj, rp, part, text);
1356    _edje_user_define_string(ed, part, rp->text.text);
1357    return ret;
1358 }
1359
1360 char *
1361 _edje_text_escape(const char *text)
1362 {
1363    Eina_Strbuf *txt;
1364    char *ret;
1365    const char *text_end;
1366    size_t text_len;
1367
1368    if (!text) return NULL;
1369
1370    txt = eina_strbuf_new();
1371    text_len = strlen(text);
1372
1373    text_end = text + text_len;
1374    while (text < text_end)
1375      {
1376         int advance;
1377         const char *escaped = evas_textblock_string_escape_get(text, &advance);
1378         if (!escaped)
1379           {
1380              eina_strbuf_append_char(txt, text[0]);
1381              advance = 1;
1382           }
1383         else
1384           eina_strbuf_append(txt, escaped);
1385
1386         text += advance;
1387      }
1388
1389    ret = eina_strbuf_string_steal(txt);
1390    eina_strbuf_free(txt);
1391    return ret;
1392 }
1393
1394 char *
1395 _edje_text_unescape(const char *text)
1396 {
1397    Eina_Strbuf *txt;
1398    char *ret;
1399    const char *text_end, *last, *escape_start;
1400    size_t text_len;
1401
1402    if (!text) return NULL;
1403
1404    txt = eina_strbuf_new();
1405    text_len = strlen(text);
1406
1407    text_end = text + text_len;
1408    last = text;
1409    escape_start = NULL;
1410    for (; text < text_end; text++)
1411      {
1412         if (*text == '&')
1413           {
1414              size_t len;
1415              const char *str;
1416
1417              if (last)
1418                {
1419                   len = text - last;
1420                   str = last;
1421                }
1422              else
1423                {
1424                   len = text - escape_start;
1425                   str = escape_start;
1426                }
1427
1428              if (len > 0)
1429                eina_strbuf_append_n(txt, str, len);
1430
1431              escape_start = text;
1432              last = NULL;
1433           }
1434         else if ((*text == ';') && (escape_start))
1435           {
1436              size_t len;
1437              const char *str = evas_textblock_escape_string_range_get(escape_start, text);
1438
1439              if (str)
1440                len = strlen(str);
1441              else
1442                {
1443                   str = escape_start;
1444                   len = text + 1 - escape_start;
1445                }
1446
1447              eina_strbuf_append_n(txt, str, len);
1448
1449              escape_start = NULL;
1450              last = text + 1;
1451           }
1452      }
1453
1454    if (!last && escape_start)
1455      last = escape_start;
1456
1457    if (last && (text > last))
1458      {
1459         size_t len = text - last;
1460         eina_strbuf_append_n(txt, last, len);
1461      }
1462
1463    ret = eina_strbuf_string_steal(txt);
1464    eina_strbuf_free(txt);
1465    return ret;
1466 }
1467
1468 EAPI Eina_Bool
1469 edje_object_part_text_unescaped_set(Evas_Object *obj, const char *part, const char *text_to_escape)
1470 {
1471    Edje *ed;
1472    Edje_Real_Part *rp;
1473    Eina_Bool ret = EINA_FALSE;
1474
1475    ed = _edje_fetch(obj);
1476    if ((!ed) || (!part)) return ret;
1477    rp = _edje_real_part_recursive_get(ed, part);
1478    if (!rp) return ret;
1479    if (rp->part->type == EDJE_PART_TYPE_TEXT)
1480      ret = _edje_object_part_text_raw_set(obj, rp, part, text_to_escape);
1481    else if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1482      {
1483         char *text = _edje_text_escape(text_to_escape);
1484
1485         ret = _edje_object_part_text_raw_set(obj, rp, part, text);
1486         free(text);
1487      }
1488    _edje_user_define_string(ed, part, rp->text.text);
1489    return ret;
1490 }
1491
1492 EAPI char *
1493 edje_object_part_text_unescaped_get(const Evas_Object *obj, const char *part)
1494 {
1495    Edje *ed;
1496    Edje_Real_Part *rp;
1497
1498    ed = _edje_fetch(obj);
1499    if ((!ed) || (!part)) return NULL;
1500
1501    /* Need to recalc before providing the object. */
1502    _edje_recalc_do(ed);
1503
1504    rp = _edje_real_part_recursive_get(ed, part);
1505    if (!rp) return NULL;
1506    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1507      {
1508         const char *t = _edje_entry_text_get(rp);
1509         return _edje_text_unescape(t);
1510      }
1511    else
1512      {
1513         if (rp->part->type == EDJE_PART_TYPE_TEXT) return strdup(rp->text.text);
1514         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1515           {
1516              const char *t = evas_object_textblock_text_markup_get(rp->object);
1517              return _edje_text_unescape(t);
1518           }
1519      }
1520    return NULL;
1521 }
1522
1523 EAPI const char *
1524 edje_object_part_text_selection_get(const Evas_Object *obj, const char *part)
1525 {
1526    Edje *ed;
1527    Edje_Real_Part *rp;
1528
1529    ed = _edje_fetch(obj);
1530    if ((!ed) || (!part)) return NULL;
1531    rp = _edje_real_part_recursive_get(ed, part);
1532    if (!rp) return NULL;
1533    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1534      return _edje_entry_selection_get(rp);
1535    return NULL;
1536 }
1537
1538 EAPI void
1539 edje_object_part_text_select_none(const Evas_Object *obj, const char *part)
1540 {
1541    Edje *ed;
1542    Edje_Real_Part *rp;
1543
1544    ed = _edje_fetch(obj);
1545    if ((!ed) || (!part)) return;
1546    rp = _edje_real_part_recursive_get(ed, part);
1547    if (!rp) return;
1548    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1549      _edje_entry_select_none(rp);
1550 }
1551
1552 EAPI void
1553 edje_object_part_text_select_all(const Evas_Object *obj, const char *part)
1554 {
1555    Edje *ed;
1556    Edje_Real_Part *rp;
1557
1558    ed = _edje_fetch(obj);
1559    if ((!ed) || (!part)) return;
1560    rp = _edje_real_part_recursive_get(ed, part);
1561    if (!rp) return;
1562    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1563      _edje_entry_select_all(rp);
1564 }
1565
1566 EAPI void
1567 edje_object_part_text_insert(Evas_Object *obj, const char *part, const char *text)
1568 {
1569    Edje *ed;
1570    Edje_Real_Part *rp;
1571
1572    ed = _edje_fetch(obj);
1573    if ((!ed) || (!part)) return;
1574    rp = _edje_real_part_recursive_get(ed, part);
1575    if (!rp) return;
1576    if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return;
1577    if (rp->part->entry_mode <= EDJE_ENTRY_EDIT_MODE_NONE) return;
1578    _edje_entry_text_markup_insert(rp, text);
1579    rp->edje->dirty = 1;
1580    rp->edje->recalc_call = 1;
1581    rp->edje->recalc_hints = 1;
1582 #ifdef EDJE_CALC_CACHE
1583    rp->invalidate = 1;
1584 #endif
1585    _edje_recalc(rp->edje);
1586    if (rp->edje->text_change.func)
1587      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
1588 }
1589
1590 EAPI void
1591 edje_object_part_text_append(Evas_Object *obj, const char *part, const char *text)
1592 {
1593    Edje *ed;
1594    Edje_Real_Part *rp;
1595
1596    ed = _edje_fetch(obj);
1597    if ((!ed) || (!part)) return;
1598    rp = _edje_real_part_recursive_get(ed, part);
1599    if (!rp) return;
1600    if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return;
1601    _edje_object_part_text_raw_append(obj, rp, part, text);
1602    rp->edje->dirty = 1;
1603    rp->edje->recalc_call = 1;
1604    rp->edje->recalc_hints = 1;
1605 #ifdef EDJE_CALC_CACHE
1606    rp->invalidate = 1;
1607 #endif
1608    _edje_recalc(rp->edje);
1609    if (rp->edje->text_change.func)
1610      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
1611 }
1612
1613 EAPI const Eina_List *
1614 edje_object_part_text_anchor_list_get(const Evas_Object *obj, const char *part)
1615 {
1616    Edje *ed;
1617    Edje_Real_Part *rp;
1618
1619    ed = _edje_fetch(obj);
1620    if ((!ed) || (!part)) return NULL;
1621    rp = _edje_real_part_recursive_get(ed, part);
1622    if (!rp) return NULL;
1623    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1624      return _edje_entry_anchors_list(rp);
1625    return NULL;
1626 }
1627
1628 EAPI const Eina_List *
1629 edje_object_part_text_anchor_geometry_get(const Evas_Object *obj, const char *part, const char *anchor)
1630 {
1631    Edje *ed;
1632    Edje_Real_Part *rp;
1633
1634    ed = _edje_fetch(obj);
1635    if ((!ed) || (!part)) return NULL;
1636    rp = _edje_real_part_recursive_get(ed, part);
1637    if (!rp) return NULL;
1638    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1639      return _edje_entry_anchor_geometry_get(rp, anchor);
1640    return NULL;
1641 }
1642
1643 EAPI const Eina_List *
1644 edje_object_part_text_item_list_get(const Evas_Object *obj, const char *part)
1645 {
1646    Edje *ed;
1647    Edje_Real_Part *rp;
1648
1649    ed = _edje_fetch(obj);
1650    if ((!ed) || (!part)) return NULL;
1651    rp = _edje_real_part_recursive_get(ed, part);
1652    if (!rp) return NULL;
1653    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1654      return _edje_entry_items_list(rp);
1655    return NULL;
1656 }
1657
1658 EAPI Eina_Bool
1659 edje_object_part_text_item_geometry_get(const Evas_Object *obj, const char *part, const char *item, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
1660 {
1661    Edje *ed;
1662    Edje_Real_Part *rp;
1663
1664    ed = _edje_fetch(obj);
1665    if ((!ed) || (!part)) return EINA_FALSE;
1666    rp = _edje_real_part_recursive_get(ed, part);
1667    if (!rp) return EINA_FALSE;
1668    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1669      return _edje_entry_item_geometry_get(rp, item, cx, cy, cw, ch);
1670    return EINA_FALSE;
1671 }
1672
1673 EAPI void
1674 edje_object_part_text_cursor_geometry_get(const Evas_Object *obj, const char *part, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1675 {
1676    Edje *ed;
1677    Edje_Real_Part *rp;
1678
1679    ed = _edje_fetch(obj);
1680    if (x) *x = 0;
1681    if (y) *y = 0;
1682    if (w) *w = 0;
1683    if (h) *h = 0;
1684    if ((!ed) || (!part)) return;
1685    rp = _edje_real_part_recursive_get(ed, part);
1686    if (!rp) return;
1687    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1688      {
1689         _edje_entry_cursor_geometry_get(rp, x, y, w, h);
1690         if (x) *x -= rp->edje->x;
1691         if (y) *y -= rp->edje->y;
1692      }
1693 }
1694
1695 EAPI void
1696 edje_object_part_text_user_insert(const Evas_Object *obj, const char *part, const char *text)
1697 {
1698    Edje *ed;
1699    Edje_Real_Part *rp;
1700
1701    ed = _edje_fetch(obj);
1702    if ((!ed) || (!part)) return;
1703    rp = _edje_real_part_recursive_get(ed, part);
1704    if (!rp) return;
1705    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1706      _edje_entry_user_insert(rp, text);
1707 }
1708
1709 EAPI void
1710 edje_object_part_text_select_allow_set(const Evas_Object *obj, const char *part, Eina_Bool allow)
1711 {
1712    Edje *ed;
1713    Edje_Real_Part *rp;
1714
1715    ed = _edje_fetch(obj);
1716    if ((!ed) || (!part)) return;
1717    rp = _edje_real_part_recursive_get(ed, part);
1718    if (!rp) return;
1719    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1720      _edje_entry_select_allow_set(rp, allow);
1721 }
1722
1723 EAPI void
1724 edje_object_part_text_select_abort(const Evas_Object *obj, const char *part)
1725 {
1726    Edje *ed;
1727    Edje_Real_Part *rp;
1728
1729    ed = _edje_fetch(obj);
1730    if ((!ed) || (!part)) return;
1731    rp = _edje_real_part_recursive_get(ed, part);
1732    if (!rp) return;
1733    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1734      _edje_entry_select_abort(rp);
1735 }
1736
1737 EAPI void
1738 edje_object_part_text_select_begin(const Evas_Object *obj, const char *part)
1739 {
1740    Edje *ed;
1741    Edje_Real_Part *rp;
1742
1743    ed = _edje_fetch(obj);
1744    if ((!ed) || (!part)) return;
1745    rp = _edje_real_part_recursive_get(ed, part);
1746    if (!rp) return;
1747    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1748      _edje_entry_select_begin(rp);
1749 }
1750
1751 EAPI void
1752 edje_object_part_text_select_extend(const Evas_Object *obj, const char *part)
1753 {
1754    Edje *ed;
1755    Edje_Real_Part *rp;
1756
1757    ed = _edje_fetch(obj);
1758    if ((!ed) || (!part)) return;
1759    rp = _edje_real_part_recursive_get(ed, part);
1760    if (!rp) return;
1761    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1762      _edje_entry_select_extend(rp);
1763 }
1764
1765 EAPI void *
1766 edje_object_part_text_imf_context_get(const Evas_Object *obj, const char *part)
1767 {
1768    Edje *ed;
1769    Edje_Real_Part *rp;
1770
1771    ed = _edje_fetch(obj);
1772    if ((!ed) || (!part)) return NULL;
1773
1774    rp = _edje_real_part_recursive_get(ed, (char *)part);
1775    if (!rp) return NULL;
1776
1777    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1778      return _edje_entry_imf_context_get(rp);
1779    else
1780      return NULL;
1781 }
1782
1783 EAPI Eina_Bool
1784 edje_object_part_text_cursor_next(Evas_Object *obj, const char *part, Edje_Cursor cur)
1785 {
1786    Edje *ed;
1787    Edje_Real_Part *rp;
1788
1789    ed = _edje_fetch(obj);
1790    if ((!ed) || (!part)) return EINA_FALSE;
1791    rp = _edje_real_part_recursive_get(ed, part);
1792    if (!rp) return EINA_FALSE;
1793    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1794      {
1795         return _edje_entry_cursor_next(rp, cur);
1796      }
1797    return EINA_FALSE;
1798 }
1799
1800 EAPI Eina_Bool
1801 edje_object_part_text_cursor_prev(Evas_Object *obj, const char *part, Edje_Cursor cur)
1802 {
1803    Edje *ed;
1804    Edje_Real_Part *rp;
1805
1806    ed = _edje_fetch(obj);
1807    if ((!ed) || (!part)) return EINA_FALSE;
1808    rp = _edje_real_part_recursive_get(ed, part);
1809    if (!rp) return EINA_FALSE;
1810    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1811      {
1812         return _edje_entry_cursor_prev(rp, cur);
1813      }
1814    return EINA_FALSE;
1815 }
1816
1817 EAPI Eina_Bool
1818 edje_object_part_text_cursor_up(Evas_Object *obj, const char *part, Edje_Cursor cur)
1819 {
1820    Edje *ed;
1821    Edje_Real_Part *rp;
1822
1823    ed = _edje_fetch(obj);
1824    if ((!ed) || (!part)) return EINA_FALSE;
1825    rp = _edje_real_part_recursive_get(ed, part);
1826    if (!rp) return EINA_FALSE;
1827    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1828      {
1829         return _edje_entry_cursor_up(rp, cur);
1830      }
1831    return EINA_FALSE;
1832 }
1833
1834 EAPI Eina_Bool
1835 edje_object_part_text_cursor_down(Evas_Object *obj, const char *part, Edje_Cursor cur)
1836 {
1837    Edje *ed;
1838    Edje_Real_Part *rp;
1839
1840    ed = _edje_fetch(obj);
1841    if ((!ed) || (!part)) return EINA_FALSE;
1842    rp = _edje_real_part_recursive_get(ed, part);
1843    if (!rp) return EINA_FALSE;
1844    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1845      {
1846         return _edje_entry_cursor_down(rp, cur);
1847      }
1848    return EINA_FALSE;
1849 }
1850
1851 EAPI void
1852 edje_object_part_text_cursor_begin_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1853 {
1854    Edje *ed;
1855    Edje_Real_Part *rp;
1856
1857    ed = _edje_fetch(obj);
1858    if ((!ed) || (!part)) return;
1859    rp = _edje_real_part_recursive_get(ed, part);
1860    if (!rp) return;
1861    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1862      {
1863         _edje_entry_cursor_begin(rp, cur);
1864      }
1865 }
1866
1867 EAPI void
1868 edje_object_part_text_cursor_end_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1869 {
1870    Edje *ed;
1871    Edje_Real_Part *rp;
1872
1873    ed = _edje_fetch(obj);
1874    if ((!ed) || (!part)) return;
1875    rp = _edje_real_part_recursive_get(ed, part);
1876    if (!rp) return;
1877    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1878      {
1879         _edje_entry_cursor_end(rp, cur);
1880      }
1881 }
1882
1883 EAPI void
1884 edje_object_part_text_cursor_copy(Evas_Object *obj, const char *part, Edje_Cursor src, Edje_Cursor dst)
1885 {
1886    Edje *ed;
1887    Edje_Real_Part *rp;
1888
1889    ed = _edje_fetch(obj);
1890    if ((!ed) || (!part)) return;
1891    rp = _edje_real_part_recursive_get(ed, part);
1892    if (!rp) return;
1893    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1894      {
1895         _edje_entry_cursor_copy(rp, src, dst);
1896      }
1897 }
1898
1899 EAPI void
1900 edje_object_part_text_cursor_line_begin_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1901 {
1902    Edje *ed;
1903    Edje_Real_Part *rp;
1904
1905    ed = _edje_fetch(obj);
1906    if ((!ed) || (!part)) return;
1907    rp = _edje_real_part_recursive_get(ed, part);
1908    if (!rp) return;
1909    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1910      {
1911         _edje_entry_cursor_line_begin(rp, cur);
1912      }
1913 }
1914
1915 EAPI void
1916 edje_object_part_text_cursor_line_end_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1917 {
1918    Edje *ed;
1919    Edje_Real_Part *rp;
1920
1921    ed = _edje_fetch(obj);
1922    if ((!ed) || (!part)) return;
1923    rp = _edje_real_part_recursive_get(ed, part);
1924    if (!rp) return;
1925    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1926      {
1927         _edje_entry_cursor_line_end(rp, cur);
1928      }
1929 }
1930
1931 EAPI Eina_Bool
1932 edje_object_part_text_cursor_coord_set(Evas_Object *obj, const char *part,
1933                                        Edje_Cursor cur, Evas_Coord x, Evas_Coord y)
1934 {
1935    Edje *ed;
1936    Edje_Real_Part *rp;
1937
1938    ed = _edje_fetch(obj);
1939    if ((!ed) || (!part)) return EINA_FALSE;
1940    rp = _edje_real_part_recursive_get(ed, part);
1941    if (!rp) return EINA_FALSE;
1942    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1943      {
1944         return _edje_entry_cursor_coord_set(rp, cur, x, y);
1945      }
1946    return EINA_FALSE;
1947 }
1948
1949 EAPI Eina_Bool
1950 edje_object_part_text_cursor_is_format_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1951 {
1952    Edje *ed;
1953    Edje_Real_Part *rp;
1954
1955    ed = _edje_fetch(obj);
1956    if ((!ed) || (!part)) return EINA_FALSE;
1957    rp = _edje_real_part_recursive_get(ed, part);
1958    if (!rp) return EINA_FALSE;
1959    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1960      {
1961         return _edje_entry_cursor_is_format_get(rp, cur);
1962      }
1963    return EINA_FALSE;
1964 }
1965
1966 EAPI Eina_Bool
1967 edje_object_part_text_cursor_is_visible_format_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1968 {
1969    Edje *ed;
1970    Edje_Real_Part *rp;
1971
1972    ed = _edje_fetch(obj);
1973    if ((!ed) || (!part)) return 0;
1974    rp = _edje_real_part_recursive_get(ed, part);
1975    if (!rp) return 0;
1976    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1977      {
1978         return _edje_entry_cursor_is_visible_format_get(rp, cur);
1979      }
1980    return 0;
1981 }
1982
1983 EAPI char *
1984 edje_object_part_text_cursor_content_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1985 {
1986    Edje *ed;
1987    Edje_Real_Part *rp;
1988
1989    ed = _edje_fetch(obj);
1990    if ((!ed) || (!part)) return NULL;
1991    rp = _edje_real_part_recursive_get(ed, part);
1992    if (!rp) return NULL;
1993    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1994      {
1995         return _edje_entry_cursor_content_get(rp, cur);
1996      }
1997    return NULL;
1998 }
1999
2000 EAPI void
2001 edje_object_part_text_cursor_pos_set(Evas_Object *obj, const char *part, Edje_Cursor cur, int pos)
2002 {
2003    Edje *ed;
2004    Edje_Real_Part *rp;
2005
2006    ed = _edje_fetch(obj);
2007    if ((!ed) || (!part)) return;
2008    rp = _edje_real_part_recursive_get(ed, part);
2009    if (!rp) return;
2010    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2011      {
2012         _edje_entry_cursor_pos_set(rp, cur, pos);
2013      }
2014 }
2015
2016 EAPI int
2017 edje_object_part_text_cursor_pos_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
2018 {
2019    Edje *ed;
2020    Edje_Real_Part *rp;
2021
2022    ed = _edje_fetch(obj);
2023    if ((!ed) || (!part)) return 0;
2024    rp = _edje_real_part_recursive_get(ed, part);
2025    if (!rp) return 0;
2026    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2027      {
2028         return _edje_entry_cursor_pos_get(rp, cur);
2029      }
2030    return 0;
2031 }
2032
2033 EAPI void
2034 edje_object_part_text_imf_context_reset(const Evas_Object *obj, const char *part)
2035 {
2036    Edje *ed;
2037    Edje_Real_Part *rp;
2038
2039    ed = _edje_fetch(obj);
2040    if ((!ed) || (!part)) return;
2041    rp = _edje_real_part_recursive_get(ed, part);
2042    if (!rp) return;
2043    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2044      {
2045         _edje_entry_imf_context_reset(rp);
2046      }
2047 }
2048
2049 EAPI void
2050 edje_object_part_text_input_panel_layout_set(Evas_Object *obj, const char *part, Edje_Input_Panel_Layout layout)
2051 {
2052    Edje *ed;
2053    Edje_Real_Part *rp;
2054
2055    ed = _edje_fetch(obj);
2056    if ((!ed) || (!part)) return;
2057    rp = _edje_real_part_recursive_get(ed, part);
2058    if (!rp) return;
2059    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2060      {
2061         _edje_entry_input_panel_layout_set(rp, layout);
2062      }
2063 }
2064
2065 EAPI Edje_Input_Panel_Layout
2066 edje_object_part_text_input_panel_layout_get(const Evas_Object *obj, const char *part)
2067 {
2068    Edje *ed;
2069    Edje_Real_Part *rp;
2070
2071    ed = _edje_fetch(obj);
2072    if ((!ed) || (!part)) return EDJE_INPUT_PANEL_LAYOUT_INVALID;
2073    rp = _edje_real_part_recursive_get(ed, part);
2074    if (!rp) return EINA_FALSE;
2075    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2076      {
2077         return _edje_entry_input_panel_layout_get(rp);
2078      }
2079    return EDJE_INPUT_PANEL_LAYOUT_INVALID;
2080 }
2081
2082 EAPI void
2083 edje_object_part_text_autocapital_type_set(Evas_Object *obj, const char *part, Edje_Text_Autocapital_Type autocapital_type)
2084 {
2085    Edje *ed;
2086    Edje_Real_Part *rp;
2087
2088    ed = _edje_fetch(obj);
2089    if ((!ed) || (!part)) return;
2090    rp = _edje_real_part_recursive_get(ed, part);
2091    if (!rp) return;
2092    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2093      {
2094         _edje_entry_autocapital_type_set(rp, autocapital_type);
2095      }
2096 }
2097
2098 EAPI Edje_Text_Autocapital_Type
2099 edje_object_part_text_autocapital_type_get(const Evas_Object *obj, const char *part)
2100 {
2101    Edje *ed;
2102    Edje_Real_Part *rp;
2103
2104    ed = _edje_fetch(obj);
2105    if ((!ed) || (!part)) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2106    rp = _edje_real_part_recursive_get(ed, part);
2107    if (!rp) return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2108    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2109      {
2110         return _edje_entry_autocapital_type_get(rp);
2111      }
2112    return EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2113 }
2114
2115 EAPI void
2116 edje_object_part_text_prediction_allow_set(Evas_Object *obj, const char *part, Eina_Bool prediction)
2117 {
2118    Edje *ed;
2119    Edje_Real_Part *rp;
2120
2121    ed = _edje_fetch(obj);
2122    if ((!ed) || (!part)) return;
2123    rp = _edje_real_part_recursive_get(ed, part);
2124    if (!rp) return;
2125    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2126      {
2127         _edje_entry_prediction_allow_set(rp, prediction);
2128      }
2129 }
2130
2131 EAPI Eina_Bool
2132 edje_object_part_text_prediction_allow_get(const Evas_Object *obj, const char *part)
2133 {
2134    Edje *ed;
2135    Edje_Real_Part *rp;
2136
2137    ed = _edje_fetch(obj);
2138    if ((!ed) || (!part)) return EINA_FALSE;
2139    rp = _edje_real_part_recursive_get(ed, part);
2140    if (!rp) return EINA_FALSE;
2141    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2142      {
2143         return _edje_entry_prediction_allow_get(rp);
2144      }
2145    return EINA_FALSE;
2146 }
2147
2148 EAPI void
2149 edje_object_part_text_input_panel_enabled_set(Evas_Object *obj, const char *part, Eina_Bool enabled)
2150 {
2151    Edje *ed;
2152    Edje_Real_Part *rp;
2153
2154    ed = _edje_fetch(obj);
2155    if ((!ed) || (!part)) return;
2156    rp = _edje_real_part_recursive_get(ed, part);
2157    if (!rp) return;
2158    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2159      {
2160         _edje_entry_input_panel_enabled_set(rp, enabled);
2161      }
2162 }
2163
2164 EAPI Eina_Bool
2165 edje_object_part_text_input_panel_enabled_get(const Evas_Object *obj, const char *part)
2166 {
2167    Edje *ed;
2168    Edje_Real_Part *rp;
2169
2170    ed = _edje_fetch(obj);
2171    if ((!ed) || (!part)) return EINA_FALSE;
2172    rp = _edje_real_part_recursive_get(ed, part);
2173    if (!rp) return EINA_FALSE;
2174    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2175      {
2176         return _edje_entry_input_panel_enabled_get(rp);
2177      }
2178    return EINA_FALSE;
2179 }
2180
2181 EAPI void
2182 edje_object_part_text_input_panel_show(const Evas_Object *obj, const char *part)
2183 {
2184    Edje *ed;
2185    Edje_Real_Part *rp;
2186
2187    ed = _edje_fetch(obj);
2188    if ((!ed) || (!part)) return;
2189    rp = _edje_real_part_recursive_get(ed, part);
2190    if (!rp) return;
2191    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2192      _edje_entry_input_panel_show(rp);
2193 }
2194
2195 EAPI void
2196 edje_object_part_text_input_panel_hide(const Evas_Object *obj, const char *part)
2197 {
2198    Edje *ed;
2199    Edje_Real_Part *rp;
2200
2201    ed = _edje_fetch(obj);
2202    if ((!ed) || (!part)) return;
2203    rp = _edje_real_part_recursive_get(ed, part);
2204    if (!rp) return;
2205    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2206      _edje_entry_input_panel_hide(rp);
2207 }
2208
2209 EAPI void
2210 edje_object_part_text_input_panel_language_set(Evas_Object *obj, const char *part, Edje_Input_Panel_Lang lang)
2211 {
2212    Edje *ed;
2213    Edje_Real_Part *rp;
2214
2215    ed = _edje_fetch(obj);
2216    if ((!ed) || (!part)) return;
2217    rp = _edje_real_part_recursive_get(ed, part);
2218    if (!rp) return;
2219    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2220      {
2221         _edje_entry_input_panel_language_set(rp, lang);
2222      }
2223 }
2224
2225 EAPI Edje_Input_Panel_Lang
2226 edje_object_part_text_input_panel_language_get(const Evas_Object *obj, const char *part)
2227 {
2228    Edje *ed;
2229    Edje_Real_Part *rp;
2230
2231    ed = _edje_fetch(obj);
2232    if ((!ed) || (!part)) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
2233    rp = _edje_real_part_recursive_get(ed, part);
2234    if (!rp) return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
2235    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2236      {
2237         return _edje_entry_input_panel_language_get(rp);
2238      }
2239    return EDJE_INPUT_PANEL_LANG_AUTOMATIC;
2240 }
2241
2242 EAPI void
2243 edje_object_part_text_input_panel_imdata_set(Evas_Object *obj, const char *part, const void *data, int len)
2244 {
2245    Edje *ed;
2246    Edje_Real_Part *rp;
2247
2248    ed = _edje_fetch(obj);
2249    if ((!ed) || (!part)) return;
2250    rp = _edje_real_part_recursive_get(ed, part);
2251    if (!rp) return;
2252    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2253      {
2254         _edje_entry_input_panel_imdata_set(rp, data, len);
2255      }
2256 }
2257
2258 EAPI void
2259 edje_object_part_text_input_panel_imdata_get(const Evas_Object *obj, const char *part, void *data, int *len)
2260 {
2261    Edje *ed;
2262    Edje_Real_Part *rp;
2263
2264    ed = _edje_fetch(obj);
2265    if ((!ed) || (!part)) return;
2266    rp = _edje_real_part_recursive_get(ed, part);
2267    if (!rp) return;
2268    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2269      {
2270         _edje_entry_input_panel_imdata_get(rp, data, len);
2271      }
2272 }
2273
2274 EAPI void
2275 edje_object_part_text_input_panel_return_key_type_set(Evas_Object *obj, const char *part, Edje_Input_Panel_Return_Key_Type return_key_type)
2276 {
2277    Edje *ed;
2278    Edje_Real_Part *rp;
2279
2280    ed = _edje_fetch(obj);
2281    if ((!ed) || (!part)) return;
2282    rp = _edje_real_part_recursive_get(ed, part);
2283    if (!rp) return;
2284    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2285      {
2286         _edje_entry_input_panel_return_key_type_set(rp, return_key_type);
2287      }
2288 }
2289
2290 EAPI Edje_Input_Panel_Return_Key_Type
2291 edje_object_part_text_input_panel_return_key_type_get(const Evas_Object *obj, const char *part)
2292 {
2293    Edje *ed;
2294    Edje_Real_Part *rp;
2295
2296    ed = _edje_fetch(obj);
2297    if ((!ed) || (!part)) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2298    rp = _edje_real_part_recursive_get(ed, part);
2299    if (!rp) return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2300    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2301      {
2302         return _edje_entry_input_panel_return_key_type_get(rp);
2303      }
2304    return EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
2305 }
2306
2307 EAPI void
2308 edje_object_part_text_input_panel_return_key_disabled_set(Evas_Object *obj, const char *part, Eina_Bool disabled)
2309 {
2310    Edje *ed;
2311    Edje_Real_Part *rp;
2312
2313    ed = _edje_fetch(obj);
2314    if ((!ed) || (!part)) return;
2315    rp = _edje_real_part_recursive_get(ed, part);
2316    if (!rp) return;
2317    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2318      {
2319         _edje_entry_input_panel_return_key_disabled_set(rp, disabled);
2320      }
2321 }
2322
2323 EAPI Eina_Bool
2324 edje_object_part_text_input_panel_return_key_disabled_get(const Evas_Object *obj, const char *part)
2325 {
2326    Edje *ed;
2327    Edje_Real_Part *rp;
2328
2329    ed = _edje_fetch(obj);
2330    if ((!ed) || (!part)) return EINA_FALSE;
2331    rp = _edje_real_part_recursive_get(ed, part);
2332    if (!rp) return EINA_FALSE;
2333    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2334      {
2335         return _edje_entry_input_panel_return_key_disabled_get(rp);
2336      }
2337    return EINA_FALSE;
2338 }
2339
2340 EAPI void
2341 edje_object_text_insert_filter_callback_add(Evas_Object *obj, const char *part, Edje_Text_Filter_Cb func, void *data)
2342 {
2343    Edje *ed;
2344    Edje_Text_Insert_Filter_Callback *cb;
2345
2346    ed = _edje_fetch(obj);
2347    if ((!ed) || (!part)) return;
2348    cb = calloc(1, sizeof(Edje_Text_Insert_Filter_Callback));
2349    cb->part = eina_stringshare_add(part);
2350    cb->func = func;
2351    cb->data = (void *)data;
2352    ed->text_insert_filter_callbacks =
2353      eina_list_append(ed->text_insert_filter_callbacks, cb);
2354 }
2355
2356 EAPI void *
2357 edje_object_text_insert_filter_callback_del(Evas_Object *obj, const char *part, Edje_Text_Filter_Cb func)
2358 {
2359    Edje *ed;
2360    Edje_Text_Insert_Filter_Callback *cb;
2361    Eina_List *l;
2362
2363    ed = _edje_fetch(obj);
2364    if ((!ed) || (!part)) return NULL;
2365    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
2366      {
2367         if ((!strcmp(cb->part, part)) && (cb->func == func))
2368           {
2369              void *data = cb->data;
2370              ed->text_insert_filter_callbacks =
2371                eina_list_remove_list(ed->text_insert_filter_callbacks, l);
2372              eina_stringshare_del(cb->part);
2373              free(cb);
2374              return data;
2375           }
2376      }
2377    return NULL;
2378 }
2379
2380 EAPI void *
2381 edje_object_text_insert_filter_callback_del_full(Evas_Object *obj, const char *part, Edje_Text_Filter_Cb func, void *data)
2382 {
2383    Edje *ed;
2384    Edje_Text_Insert_Filter_Callback *cb;
2385    Eina_List *l;
2386
2387    ed = _edje_fetch(obj);
2388    if ((!ed) || (!part)) return NULL;
2389    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
2390      {
2391         if ((!strcmp(cb->part, part)) && (cb->func == func) &&
2392             (cb->data == data))
2393           {
2394              void *tmp = cb->data;
2395              ed->text_insert_filter_callbacks =
2396                eina_list_remove_list(ed->text_insert_filter_callbacks, l);
2397              eina_stringshare_del(cb->part);
2398              free(cb);
2399              return tmp;
2400           }
2401      }
2402    return NULL;
2403 }
2404
2405 EAPI void
2406 edje_object_text_markup_filter_callback_add(Evas_Object *obj, const char *part, Edje_Markup_Filter_Cb func, void *data)
2407 {
2408    Edje *ed;
2409    Edje_Markup_Filter_Callback *cb;
2410
2411    ed = _edje_fetch(obj);
2412    if ((!ed) || (!part)) return;
2413    cb = calloc(1, sizeof(Edje_Markup_Filter_Callback));
2414    cb->part = eina_stringshare_add(part);
2415    cb->func = func;
2416    cb->data = (void *)data;
2417    ed->markup_filter_callbacks =
2418      eina_list_append(ed->markup_filter_callbacks, cb);
2419 }
2420
2421 EAPI void *
2422 edje_object_text_markup_filter_callback_del(Evas_Object *obj, const char *part, Edje_Markup_Filter_Cb func)
2423 {
2424    Edje *ed;
2425    Edje_Markup_Filter_Callback *cb;
2426    Eina_List *l;
2427
2428    ed = _edje_fetch(obj);
2429    if ((!ed) || (!part)) return NULL;
2430    EINA_LIST_FOREACH(ed->markup_filter_callbacks, l, cb)
2431      {
2432         if ((!strcmp(cb->part, part)) && (cb->func == func))
2433           {
2434              void *data = cb->data;
2435              ed->markup_filter_callbacks =
2436                eina_list_remove_list(ed->markup_filter_callbacks, l);
2437              eina_stringshare_del(cb->part);
2438              free(cb);
2439              return data;
2440           }
2441      }
2442    return NULL;
2443 }
2444
2445 EAPI void *
2446 edje_object_text_markup_filter_callback_del_full(Evas_Object *obj, const char *part, Edje_Markup_Filter_Cb func, void *data)
2447 {
2448    Edje *ed;
2449    Edje_Markup_Filter_Callback *cb;
2450    Eina_List *l;
2451
2452    ed = _edje_fetch(obj);
2453    if ((!ed) || (!part)) return NULL;
2454    EINA_LIST_FOREACH(ed->markup_filter_callbacks, l, cb)
2455      {
2456         if ((!strcmp(cb->part, part)) && (cb->func == func) &&
2457             (cb->data == data))
2458           {
2459              void *tmp = cb->data;
2460              ed->markup_filter_callbacks =
2461                eina_list_remove_list(ed->markup_filter_callbacks, l);
2462              eina_stringshare_del(cb->part);
2463              free(cb);
2464              return tmp;
2465           }
2466      }
2467    return NULL;
2468 }
2469
2470 EAPI Eina_Bool
2471 edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_swallow)
2472 {
2473    Edje *ed;
2474    Edje_Real_Part *rp;
2475    Edje_User_Defined *eud = NULL;
2476
2477    ed = _edje_fetch(obj);
2478    if ((!ed) || (!part)) return EINA_FALSE;
2479
2480    /* Need to recalc before providing the object. */
2481    // XXX: I guess this is not required, removing for testing purposes
2482    // XXX: uncomment if you see glitches in e17 or others.
2483    // XXX: by Gustavo, January 21th 2009.
2484    // XXX: I got a backtrace with over 30000 calls without this,
2485    // XXX: only with 32px shelves. The problem is probably somewhere else,
2486    // XXX: but until it's found, leave this here.
2487    // XXX: by Sachiel, January 21th 2009, 19:30 UTC
2488    _edje_recalc_do(ed);
2489
2490    rp = evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
2491    if (rp)
2492      {
2493         /* The object is already swallowed somewhere, unswallow it first */
2494         edje_object_part_unswallow(rp->edje->obj, obj_swallow);
2495      }
2496
2497    rp = _edje_real_part_recursive_get(ed, part);
2498    if (!rp)
2499      {
2500         DBG("cannot swallow part %s: part not exist!", part);
2501         return EINA_FALSE;
2502      }
2503    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
2504      {
2505         ERR("cannot swallow part %s: not swallow type!", rp->part->name);
2506         return EINA_FALSE;
2507      }
2508    _edje_real_part_swallow(rp, obj_swallow, EINA_TRUE);
2509
2510    if (rp->swallowed_object)
2511      {
2512         if (!eud)
2513           {
2514              eud = _edje_user_definition_new(EDJE_USER_SWALLOW, part, ed);
2515              evas_object_event_callback_add(obj_swallow, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
2516           }
2517         else ed->user_defined = eina_list_append(ed->user_defined, eud);
2518
2519         if (eud)
2520           {
2521              eud->u.swallow.child = obj_swallow;
2522           }
2523      }
2524
2525    return EINA_TRUE;
2526 }
2527
2528 static void
2529 _recalc_extern_parent(Evas_Object *obj)
2530 {
2531    Evas_Object *parent;
2532    Edje *ed;
2533
2534    parent = evas_object_smart_parent_get(obj);
2535    ed = _edje_fetch(parent);
2536
2537    ed->dirty = 1;
2538    ed->recalc_call = 1; // ZZZ: ???
2539    _edje_recalc(ed);
2540 }
2541
2542 EAPI void
2543 edje_extern_object_min_size_set(Evas_Object *obj, Evas_Coord minw, Evas_Coord minh)
2544 {
2545    Edje_Real_Part *rp;
2546
2547    evas_object_size_hint_min_set(obj, minw, minh);
2548    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
2549    if (rp)
2550      {
2551         rp->swallow_params.min.w = minw;
2552         rp->swallow_params.min.h = minh;
2553
2554         _recalc_extern_parent(obj);
2555      }
2556 }
2557
2558 EAPI void
2559 edje_extern_object_max_size_set(Evas_Object *obj, Evas_Coord maxw, Evas_Coord maxh)
2560 {
2561    Edje_Real_Part *rp;
2562
2563    evas_object_size_hint_max_set(obj, maxw, maxh);
2564    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
2565    if (rp)
2566      {
2567         rp->swallow_params.max.w = maxw;
2568         rp->swallow_params.max.h = maxh;
2569
2570         _recalc_extern_parent(obj);
2571      }
2572 }
2573
2574 EAPI void
2575 edje_extern_object_aspect_set(Evas_Object *obj, Edje_Aspect_Control aspect, Evas_Coord aw, Evas_Coord ah)
2576 {
2577    Edje_Real_Part *rp;
2578    Evas_Aspect_Control asp;
2579
2580    asp = EVAS_ASPECT_CONTROL_NONE;
2581    switch (aspect)
2582      {
2583       case EDJE_ASPECT_CONTROL_NONE: asp = EVAS_ASPECT_CONTROL_NONE; break;
2584
2585       case EDJE_ASPECT_CONTROL_NEITHER: asp = EVAS_ASPECT_CONTROL_NEITHER; break;
2586
2587       case EDJE_ASPECT_CONTROL_HORIZONTAL: asp = EVAS_ASPECT_CONTROL_HORIZONTAL; break;
2588
2589       case EDJE_ASPECT_CONTROL_VERTICAL: asp = EVAS_ASPECT_CONTROL_VERTICAL; break;
2590
2591       case EDJE_ASPECT_CONTROL_BOTH: asp = EVAS_ASPECT_CONTROL_BOTH; break;
2592
2593       default: break;
2594      }
2595    if (aw < 1) aw = 1;
2596    if (ah < 1) ah = 1;
2597    evas_object_size_hint_aspect_set(obj, asp, aw, ah);
2598    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
2599    if (rp)
2600      {
2601         rp->swallow_params.aspect.mode = aspect;
2602         rp->swallow_params.aspect.w = aw;
2603         rp->swallow_params.aspect.h = ah;
2604         _recalc_extern_parent(obj);
2605      }
2606 }
2607
2608 struct edje_box_layout_builtin
2609 {
2610    const char            *name;
2611    Evas_Object_Box_Layout cb;
2612 };
2613
2614 static Evas_Object_Box_Layout
2615 _edje_box_layout_builtin_find(const char *name)
2616 {
2617    const struct edje_box_layout_builtin _edje_box_layout_builtin[] = {
2618       {"horizontal", evas_object_box_layout_horizontal},
2619       {"horizontal_flow", evas_object_box_layout_flow_horizontal},
2620       {"horizontal_homogeneous", evas_object_box_layout_homogeneous_horizontal},
2621       {"horizontal_max", evas_object_box_layout_homogeneous_max_size_horizontal},
2622       {"stack", evas_object_box_layout_stack},
2623       {"vertical", evas_object_box_layout_vertical},
2624       {"vertical_flow", evas_object_box_layout_flow_vertical},
2625       {"vertical_homogeneous", evas_object_box_layout_homogeneous_vertical},
2626       {"vertical_max", evas_object_box_layout_homogeneous_max_size_vertical},
2627       {NULL, NULL}
2628    };
2629    const struct edje_box_layout_builtin *base;
2630
2631    switch (name[0])
2632      {
2633       case 'h':
2634         base = _edje_box_layout_builtin + 0;
2635         break;
2636
2637       case 's':
2638         base = _edje_box_layout_builtin + 4;
2639         break;
2640
2641       case 'v':
2642         base = _edje_box_layout_builtin + 5;
2643         break;
2644
2645       default:
2646         return NULL;
2647      }
2648
2649    for (; (base->name) && (base->name[0] == name[0]); base++)
2650      if (strcmp(base->name, name) == 0)
2651        return base->cb;
2652
2653    return NULL;
2654 }
2655
2656 static Eina_Rbtree_Direction
2657 _edje_box_layout_external_node_cmp(const Eina_Rbtree *left, const Eina_Rbtree *right, __UNUSED__ void *data)
2658 {
2659    Edje_Box_Layout *l = (Edje_Box_Layout *)left;
2660    Edje_Box_Layout *r = (Edje_Box_Layout *)right;
2661
2662    if (strcmp(l->name, r->name) < 0)
2663      return EINA_RBTREE_RIGHT;
2664    else
2665      return EINA_RBTREE_LEFT;
2666 }
2667
2668 static int
2669 _edje_box_layout_external_find_cmp(const Eina_Rbtree *node, const void *key, __UNUSED__ int length, __UNUSED__ void *data)
2670 {
2671    Edje_Box_Layout *l = (Edje_Box_Layout *)node;
2672    return strcmp(key, l->name);
2673 }
2674
2675 static Edje_Box_Layout *
2676 _edje_box_layout_external_find(const char *name)
2677 {
2678    return (Edje_Box_Layout *)eina_rbtree_inline_lookup
2679             (_edje_box_layout_registry, name, 0, _edje_box_layout_external_find_cmp,
2680             NULL);
2681 }
2682
2683 Eina_Bool
2684 _edje_box_layout_find(const char *name, Evas_Object_Box_Layout *cb, void **data, void(**free_data) (void *data))
2685 {
2686    const Edje_Box_Layout *l;
2687
2688    if (!name) return EINA_FALSE;
2689
2690    *cb = _edje_box_layout_builtin_find(name);
2691    if (*cb)
2692      {
2693         *free_data = NULL;
2694         *data = NULL;
2695         return EINA_TRUE;
2696      }
2697
2698    l = _edje_box_layout_external_find(name);
2699    if (!l) return EINA_FALSE;
2700
2701    *cb = l->func;
2702    *free_data = l->layout_data_free;
2703    if (l->layout_data_get)
2704      *data = l->layout_data_get(l->data);
2705    else
2706      *data = NULL;
2707
2708    return EINA_TRUE;
2709 }
2710
2711 static void
2712 _edje_box_layout_external_free(Eina_Rbtree *node, __UNUSED__ void *data)
2713 {
2714    Edje_Box_Layout *l = (Edje_Box_Layout *)node;
2715
2716    if (l->data && l->free_data)
2717      l->free_data(l->data);
2718    free(l);
2719 }
2720
2721 static Edje_Box_Layout *
2722 _edje_box_layout_external_new(const char *name, Evas_Object_Box_Layout func, void *(*layout_data_get)(void *), void (*layout_data_free)(void *), void (*free_data)(void *), void *data)
2723 {
2724    Edje_Box_Layout *l;
2725    size_t name_len;
2726
2727    name_len = strlen(name) + 1;
2728    l = malloc(sizeof(Edje_Box_Layout) + name_len);
2729    if (!l) return NULL;
2730
2731    l->func = func;
2732    l->layout_data_get = layout_data_get;
2733    l->layout_data_free = layout_data_free;
2734    l->free_data = free_data;
2735    l->data = data;
2736
2737    memcpy(l->name, name, name_len);
2738
2739    return l;
2740 }
2741
2742 EAPI void
2743 edje_box_layout_register(const char *name, Evas_Object_Box_Layout func, void *(*layout_data_get)(void *), void (*layout_data_free)(void *), void (*free_data)(void *), void *data)
2744 {
2745    Edje_Box_Layout *l;
2746
2747    if (!name) return;
2748
2749    if (_edje_box_layout_builtin_find(name))
2750      {
2751         ERR("Cannot register layout '%s': would override builtin!",
2752             name);
2753
2754         if (data && free_data) free_data(data);
2755         return;
2756      }
2757
2758    l = _edje_box_layout_external_find(name);
2759    if (!l)
2760      {
2761         if (!func)
2762           {
2763              if (data && free_data) free_data(data);
2764              return;
2765           }
2766
2767         l = _edje_box_layout_external_new
2768             (name, func, layout_data_get, layout_data_free, free_data, data);
2769         if (!l)
2770           return;
2771
2772         _edje_box_layout_registry = eina_rbtree_inline_insert
2773             (_edje_box_layout_registry, (Eina_Rbtree *)l,
2774             _edje_box_layout_external_node_cmp, NULL);
2775      }
2776    else
2777      {
2778         if (func)
2779           {
2780              if (l->data && l->free_data) l->free_data(l->data);
2781
2782              l->func = func;
2783              l->layout_data_get = layout_data_get;
2784              l->layout_data_free = layout_data_free;
2785              l->free_data = free_data;
2786              l->data = data;
2787           }
2788         else
2789           {
2790              if (data && free_data) free_data(data);
2791
2792              _edje_box_layout_registry = eina_rbtree_inline_remove
2793                  (_edje_box_layout_registry, (Eina_Rbtree *)l,
2794                  _edje_box_layout_external_node_cmp, NULL);
2795              _edje_box_layout_external_free((Eina_Rbtree *)l, NULL);
2796           }
2797      }
2798 }
2799
2800 EAPI void
2801 edje_object_part_unswallow(Evas_Object *obj, Evas_Object *obj_swallow)
2802 {
2803    Edje_Real_Part *rp;
2804
2805    if (!obj_swallow) return;
2806
2807    rp = (Edje_Real_Part *)evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
2808    if (!rp)
2809      return;
2810    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
2811      {
2812         ERR("cannot unswallow part %s: not swallow type!", rp->part->name);
2813         return;
2814      }
2815
2816    if (rp->swallowed_object == obj_swallow)
2817      {
2818         Edje_User_Defined *eud;
2819         Eina_List *l;
2820
2821         if (obj)
2822           {
2823              Edje *ed;
2824
2825              ed = _edje_fetch(obj);
2826              if (!ed && obj)
2827                {
2828                   ERR("edje_object_part_unswallow called on a non Edje object ('%s').",
2829                       evas_object_type_get(obj));
2830                }
2831              else
2832                {
2833                   EINA_LIST_FOREACH(ed->user_defined, l, eud)
2834                     if (eud->type == EDJE_USER_SWALLOW && eud->u.swallow.child == obj_swallow)
2835                       {
2836                          _edje_user_definition_free(eud);
2837                          return;
2838                       }
2839                }
2840           }
2841
2842         _edje_real_part_swallow_clear(rp);
2843         rp->swallowed_object = NULL;
2844         rp->swallow_params.min.w = 0;
2845         rp->swallow_params.min.h = 0;
2846         rp->swallow_params.max.w = 0;
2847         rp->swallow_params.max.h = 0;
2848         rp->edje->dirty = 1;
2849         rp->edje->recalc_call = 1;
2850 #ifdef EDJE_CALC_CACHE
2851         rp->invalidate = 1;
2852 #endif
2853         _edje_recalc_do(rp->edje);
2854         return;
2855      }
2856 }
2857
2858 EAPI Evas_Object *
2859 edje_object_part_swallow_get(const Evas_Object *obj, const char *part)
2860 {
2861    Edje *ed;
2862    Edje_Real_Part *rp;
2863
2864    ed = _edje_fetch(obj);
2865    if ((!ed) || (!part)) return NULL;
2866
2867    /* Need to recalc before providing the object. */
2868    _edje_recalc_do(ed);
2869
2870    rp = _edje_real_part_recursive_get(ed, part);
2871    if (!rp) return NULL;
2872    return rp->swallowed_object;
2873 }
2874
2875 EAPI void
2876 edje_object_size_min_get(const Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
2877 {
2878    Edje *ed;
2879
2880    ed = _edje_fetch(obj);
2881    if ((!ed) || (!ed->collection))
2882      {
2883         if (minw) *minw = 0;
2884         if (minh) *minh = 0;
2885         return;
2886      }
2887    if (minw) *minw = ed->collection->prop.min.w;
2888    if (minh) *minh = ed->collection->prop.min.h;
2889 }
2890
2891 EAPI void
2892 edje_object_size_max_get(const Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *maxh)
2893 {
2894    Edje *ed;
2895
2896    ed = _edje_fetch(obj);
2897    if ((!ed) || (!ed->collection))
2898      {
2899         if (maxw) *maxw = 0;
2900         if (maxh) *maxh = 0;
2901         return;
2902      }
2903
2904    /* Need to recalc before providing the object. */
2905    _edje_recalc_do(ed);
2906
2907    if (ed->collection->prop.max.w == 0)
2908      {
2909         /* XXX TODO: convert maxw to 0, fix things that break. */
2910         if (maxw) *maxw = EDJE_INF_MAX_W;
2911      }
2912    else
2913      {
2914         if (maxw) *maxw = ed->collection->prop.max.w;
2915      }
2916    if (ed->collection->prop.max.h == 0)
2917      {
2918         /* XXX TODO: convert maxh to 0, fix things that break. */
2919         if (maxh) *maxh = EDJE_INF_MAX_H;
2920      }
2921    else
2922      {
2923         if (maxh) *maxh = ed->collection->prop.max.h;
2924      }
2925 }
2926
2927 EAPI void
2928 edje_object_calc_force(Evas_Object *obj)
2929 {
2930    Edje *ed;
2931    int pf, pf2;
2932
2933    ed = _edje_fetch(obj);
2934    if (!ed) return;
2935    ed->dirty = 1;
2936 #ifdef EDJE_CALC_CACHE
2937    ed->all_part_change = 1;
2938 #endif
2939
2940    pf2 = _edje_freeze_val;
2941    pf = ed->freeze;
2942
2943    _edje_freeze_val = 0;
2944    ed->freeze = 0;
2945
2946    _edje_recalc_do(ed);
2947
2948    ed->freeze = pf;
2949    _edje_freeze_val = pf2;
2950 }
2951
2952 EAPI void
2953 edje_object_size_min_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
2954 {
2955    edje_object_size_min_restricted_calc(obj, minw, minh, 0, 0);
2956 }
2957
2958 EAPI Eina_Bool
2959 edje_object_parts_extends_calc(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
2960 {
2961    Edje *ed;
2962    Evas_Coord xx1 = INT_MAX, yy1 = INT_MAX;
2963    Evas_Coord xx2 = 0, yy2 = 0;
2964    unsigned int i;
2965
2966    ed = _edje_fetch(obj);
2967    if (!ed)
2968      {
2969         if (x) *x = 0;
2970         if (y) *y = 0;
2971         if (w) *w = 0;
2972         if (h) *h = 0;
2973         return EINA_FALSE;
2974      }
2975
2976    ed->calc_only = 1;
2977
2978    /* Need to recalc before providing the object. */
2979    ed->dirty = 1;
2980    _edje_recalc_do(ed);
2981
2982    for (i = 0; i < ed->table_parts_size; i++)
2983      {
2984         Edje_Real_Part *rp;
2985         Evas_Coord rpx1, rpy1;
2986         Evas_Coord rpx2, rpy2;
2987
2988         rp = ed->table_parts[i];
2989
2990         rpx1 = rp->x;
2991         rpy1 = rp->y;
2992         rpx2 = rpx1 + rp->w;
2993         rpy2 = rpy1 + rp->h;
2994
2995         if (xx1 > rpx1) xx1 = rpx1;
2996         if (yy1 > rpy1) yy1 = rpy1;
2997         if (xx2 < rpx2) xx2 = rpx2;
2998         if (yy2 < rpy2) yy2 = rpy2;
2999      }
3000
3001    ed->calc_only = 0;
3002
3003    if (x) *x = xx1;
3004    if (y) *y = yy1;
3005    if (w) *w = xx2 - xx1;
3006    if (h) *h = yy2 - yy1;
3007
3008    return EINA_TRUE;
3009 }
3010
3011 EAPI void
3012 edje_object_size_min_restricted_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord restrictedw, Evas_Coord restrictedh)
3013 {
3014    Edje *ed;
3015    Evas_Coord pw, ph;
3016    int maxw, maxh;
3017    int okw, okh;
3018    int reset_maxwh;
3019    Edje_Real_Part *pep = NULL;
3020    Eina_Bool has_non_fixed_tb = EINA_FALSE;
3021
3022    ed = _edje_fetch(obj);
3023    if ((!ed) || (!ed->collection))
3024      {
3025         if (minw) *minw = restrictedw;
3026         if (minh) *minh = restrictedh;
3027         return;
3028      }
3029    reset_maxwh = 1;
3030    ed->calc_only = 1;
3031    pw = ed->w;
3032    ph = ed->h;
3033
3034 again:
3035    ed->w = restrictedw;
3036    ed->h = restrictedh;
3037
3038    maxw = 0;
3039    maxh = 0;
3040
3041    do
3042      {
3043         unsigned int i;
3044
3045         okw = okh = 0;
3046         ed->dirty = 1;
3047 #ifdef EDJE_CALC_CACHE
3048         ed->all_part_change = 1;
3049 #endif
3050         _edje_recalc_do(ed);
3051         if (reset_maxwh)
3052           {
3053              maxw = 0;
3054              maxh = 0;
3055           }
3056         pep = NULL;
3057         has_non_fixed_tb = EINA_FALSE;
3058         for (i = 0; i < ed->table_parts_size; i++)
3059           {
3060              Edje_Real_Part *ep;
3061              int w, h;
3062              int didw;
3063
3064              ep = ed->table_parts[i];
3065              w = ep->w - ep->req.w;
3066              h = ep->h - ep->req.h;
3067              didw = 0;
3068              if (ep->chosen_description)
3069                {
3070                   if (!ep->chosen_description->fixed.w)
3071                     {
3072                        if ((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK))
3073                          {
3074                             Evas_Coord tb_mw;
3075                             evas_object_textblock_size_formatted_get(ep->object,
3076                                                                      &tb_mw, NULL);
3077                             tb_mw -= ep->req.w;
3078                             if (tb_mw > w)
3079                               {
3080                                  w = tb_mw;
3081                               }
3082                             has_non_fixed_tb = EINA_TRUE;
3083                          }
3084                        if (w > maxw)
3085                          {
3086                             maxw = w;
3087                             okw = 1;
3088                             pep = ep;
3089                             didw = 1;
3090                          }
3091                     }
3092                   if (!ep->chosen_description->fixed.h)
3093                     {
3094                        if (!((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) &&
3095                              (!((Edje_Part_Description_Text *)ep->chosen_description)->text.min_x) &&
3096                              (didw)))
3097                          {
3098                             if (h > maxh)
3099                               {
3100                                  maxh = h;
3101                                  okh = 1;
3102                                  pep = ep;
3103                               }
3104                          }
3105
3106                        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
3107                          {
3108                             has_non_fixed_tb = EINA_TRUE;
3109                          }
3110                     }
3111                }
3112           }
3113         if (okw)
3114           {
3115              ed->w += maxw;
3116              if (ed->w < restrictedw) ed->w = restrictedw;
3117           }
3118         if (okh)
3119           {
3120              ed->h += maxh;
3121              if (ed->h < restrictedh) ed->h = restrictedh;
3122           }
3123         if ((ed->w > 4000) || (ed->h > 4000))
3124           {
3125              /* Only print it if we have a non-fixed textblock.
3126               * We should possibly avoid all of this if in this case, but in
3127               * the meanwhile, just doing this. */
3128              if (!has_non_fixed_tb)
3129                {
3130                   if (pep)
3131                     ERR("file %s, group %s has a non-fixed part '%s'. Adding 'fixed: 1 1;' to source EDC may help. Continuing discarding faulty part.",
3132                         ed->path, ed->group, pep->part->name);
3133                   else
3134                     ERR("file %s, group %s overflowed 4000x4000 with minimum size of %dx%d. Continuing discarding faulty parts.",
3135                         ed->path, ed->group, ed->w, ed->h);
3136                }
3137
3138              if (reset_maxwh)
3139                {
3140                   reset_maxwh = 0;
3141                   goto again;
3142                }
3143           }
3144      }
3145    while (okw || okh);
3146    ed->min.w = ed->w;
3147    ed->min.h = ed->h;
3148
3149    if (minw) *minw = ed->min.w;
3150    if (minh) *minh = ed->min.h;
3151
3152    ed->w = pw;
3153    ed->h = ph;
3154    ed->dirty = 1;
3155 #ifdef EDJE_CALC_CACHE
3156    ed->all_part_change = 1;
3157 #endif
3158    _edje_recalc(ed);
3159    ed->calc_only = 0;
3160 }
3161
3162 /* FIXME: Correctly return other states */
3163 EAPI const char *
3164 edje_object_part_state_get(const Evas_Object *obj, const char *part, double *val_ret)
3165 {
3166    Edje *ed;
3167    Edje_Real_Part *rp;
3168
3169    ed = _edje_fetch(obj);
3170    if ((!ed) || (!part))
3171      {
3172         if (val_ret) *val_ret = 0;
3173         return "";
3174      }
3175
3176    /* Need to recalc before providing the object. */
3177    _edje_recalc_do(ed);
3178
3179    rp = _edje_real_part_recursive_get(ed, part);
3180    if (!rp)
3181      {
3182         if (val_ret) *val_ret = 0;
3183         INF("part not found");
3184         return "";
3185      }
3186    if (rp->chosen_description)
3187      {
3188         if (val_ret) *val_ret = rp->chosen_description->state.value;
3189         if (rp->chosen_description->state.name)
3190           return rp->chosen_description->state.name;
3191         return "default";
3192      }
3193    else
3194      {
3195         if (rp->param1.description)
3196           {
3197              if (val_ret) *val_ret = rp->param1.description->state.value;
3198              if (rp->param1.description->state.name)
3199                return rp->param1.description->state.name;
3200              return "default";
3201           }
3202      }
3203    if (val_ret) *val_ret = 0;
3204    return "";
3205 }
3206
3207 EAPI Edje_Drag_Dir
3208 edje_object_part_drag_dir_get(const Evas_Object *obj, const char *part)
3209 {
3210    Edje *ed;
3211    Edje_Real_Part *rp;
3212
3213    ed = _edje_fetch(obj);
3214    if ((!ed) || (!part)) return EDJE_DRAG_DIR_NONE;
3215
3216    /* Need to recalc before providing the object. */
3217    _edje_recalc_do(ed);
3218
3219    rp = _edje_real_part_recursive_get(ed, part);
3220    if (!rp) return EDJE_DRAG_DIR_NONE;
3221    if ((rp->part->dragable.x) && (rp->part->dragable.y)) return EDJE_DRAG_DIR_XY;
3222    else if (rp->part->dragable.x)
3223      return EDJE_DRAG_DIR_X;
3224    else if (rp->part->dragable.y)
3225      return EDJE_DRAG_DIR_Y;
3226    return EDJE_DRAG_DIR_NONE;
3227 }
3228
3229 EAPI Eina_Bool
3230 edje_object_part_drag_value_set(Evas_Object *obj, const char *part, double dx, double dy)
3231 {
3232    Edje *ed;
3233    Edje_Real_Part *rp;
3234    Edje_User_Defined *eud;
3235    Eina_List *l;
3236
3237    ed = _edje_fetch(obj);
3238    if ((!ed) || (!part)) return EINA_FALSE;
3239    rp = _edje_real_part_recursive_get(ed, part);
3240    if (!rp) return EINA_FALSE;
3241    if (!rp->drag) return EINA_FALSE;
3242    if (rp->drag->down.count > 0) return EINA_FALSE;
3243
3244    EINA_LIST_FOREACH(ed->user_defined, l, eud)
3245      if (eud->type == EDJE_USER_DRAG_VALUE && !strcmp(part, eud->part))
3246        {
3247           eud->u.drag_position.x = dx;
3248           eud->u.drag_position.y = dy;
3249           break;
3250        }
3251    if (!eud)
3252      {
3253         eud = _edje_user_definition_new(EDJE_USER_DRAG_VALUE, part, ed);
3254         if (eud)
3255           {
3256              eud->u.drag_position.x = dx;
3257              eud->u.drag_position.y = dy;
3258           }
3259      }
3260
3261    if (rp->part->dragable.confine_id != -1)
3262      {
3263         dx = CLAMP(dx, 0.0, 1.0);
3264         dy = CLAMP(dy, 0.0, 1.0);
3265      }
3266    if (rp->part->dragable.x < 0) dx = 1.0 - dx;
3267    if (rp->part->dragable.y < 0) dy = 1.0 - dy;
3268    if ((rp->drag->val.x == FROM_DOUBLE(dx)) && (rp->drag->val.y == FROM_DOUBLE(dy))) return EINA_TRUE;
3269    rp->drag->val.x = FROM_DOUBLE(dx);
3270    rp->drag->val.y = FROM_DOUBLE(dy);
3271 #ifdef EDJE_CALC_CACHE
3272    rp->invalidate = 1;
3273 #endif
3274    _edje_dragable_pos_set(rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
3275    _edje_emit(rp->edje, "drag,set", rp->part->name);
3276    return EINA_TRUE;
3277 }
3278
3279 /* FIXME: Should this be x and y instead of dx/dy? */
3280 EAPI Eina_Bool
3281 edje_object_part_drag_value_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
3282 {
3283    Edje *ed;
3284    Edje_Real_Part *rp;
3285    double ddx, ddy;
3286
3287    ed = _edje_fetch(obj);
3288    if ((!ed) || (!part))
3289      {
3290         if (dx) *dx = 0;
3291         if (dy) *dy = 0;
3292         return EINA_FALSE;
3293      }
3294
3295    /* Need to recalc before providing the object. */
3296    _edje_recalc_do(ed);
3297
3298    rp = _edje_real_part_recursive_get(ed, part);
3299    if (!rp || !rp->drag)
3300      {
3301         if (dx) *dx = 0;
3302         if (dy) *dy = 0;
3303         return EINA_FALSE;
3304      }
3305    ddx = TO_DOUBLE(rp->drag->val.x);
3306    ddy = TO_DOUBLE(rp->drag->val.y);
3307    if (rp->part->dragable.x < 0) ddx = 1.0 - ddx;
3308    if (rp->part->dragable.y < 0) ddy = 1.0 - ddy;
3309    if (dx) *dx = ddx;
3310    if (dy) *dy = ddy;
3311    return EINA_TRUE;
3312 }
3313
3314 EAPI Eina_Bool
3315 edje_object_part_drag_size_set(Evas_Object *obj, const char *part, double dw, double dh)
3316 {
3317    Edje *ed;
3318    Edje_Real_Part *rp;
3319    Edje_User_Defined *eud;
3320    Eina_List *l;
3321
3322    ed = _edje_fetch(obj);
3323    if ((!ed) || (!part)) return EINA_FALSE;
3324    rp = _edje_real_part_recursive_get(ed, part);
3325    if (!rp) return EINA_FALSE;
3326    if (!rp->drag) return EINA_FALSE;
3327
3328    EINA_LIST_FOREACH(ed->user_defined, l, eud)
3329      if (eud->type == EDJE_USER_DRAG_SIZE && !strcmp(part, eud->part))
3330        {
3331           eud->u.drag_size.w = dw;
3332           eud->u.drag_size.h = dh;
3333           break;
3334        }
3335    if (!eud)
3336      {
3337         eud = _edje_user_definition_new(EDJE_USER_DRAG_SIZE, part, ed);
3338         if (eud)
3339           {
3340              eud->u.drag_size.w = dw;
3341              eud->u.drag_size.h = dh;
3342           }
3343      }
3344
3345    if (dw < 0.0) dw = 0.0;
3346    else if (dw > 1.0)
3347      dw = 1.0;
3348    if (dh < 0.0) dh = 0.0;
3349    else if (dh > 1.0)
3350      dh = 1.0;
3351    if ((rp->drag->size.x == FROM_DOUBLE(dw)) && (rp->drag->size.y == FROM_DOUBLE(dh))) return EINA_TRUE;
3352    rp->drag->size.x = FROM_DOUBLE(dw);
3353    rp->drag->size.y = FROM_DOUBLE(dh);
3354    rp->edje->dirty = 1;
3355    rp->edje->recalc_call = 1;
3356 #ifdef EDJE_CALC_CACHE
3357    rp->invalidate = 1;
3358 #endif
3359    _edje_recalc(rp->edje);
3360    return EINA_TRUE;
3361 }
3362
3363 EAPI Eina_Bool
3364 edje_object_part_drag_size_get(const Evas_Object *obj, const char *part, double *dw, double *dh)
3365 {
3366    Edje *ed;
3367    Edje_Real_Part *rp;
3368
3369    ed = _edje_fetch(obj);
3370    if ((!ed) || (!part))
3371      {
3372         if (dw) *dw = 0;
3373         if (dh) *dh = 0;
3374         return EINA_FALSE;
3375      }
3376
3377    /* Need to recalc before providing the object. */
3378    _edje_recalc_do(ed);
3379
3380    rp = _edje_real_part_recursive_get(ed, part);
3381    if (!rp || !rp->drag)
3382      {
3383         if (dw) *dw = 0;
3384         if (dh) *dh = 0;
3385         return EINA_FALSE;
3386      }
3387    if (dw) *dw = TO_DOUBLE(rp->drag->size.x);
3388    if (dh) *dh = TO_DOUBLE(rp->drag->size.y);
3389    return EINA_TRUE;
3390 }
3391
3392 EAPI Eina_Bool
3393 edje_object_part_drag_step_set(Evas_Object *obj, const char *part, double dx, double dy)
3394 {
3395    Edje *ed;
3396    Edje_Real_Part *rp;
3397    Edje_User_Defined *eud;
3398    Eina_List *l;
3399
3400    ed = _edje_fetch(obj);
3401    if ((!ed) || (!part)) return EINA_FALSE;
3402    rp = _edje_real_part_recursive_get(ed, part);
3403    if (!rp) return EINA_FALSE;
3404    if (!rp->drag) return EINA_FALSE;
3405
3406    EINA_LIST_FOREACH(ed->user_defined, l, eud)
3407      if (eud->type == EDJE_USER_DRAG_STEP && !strcmp(part, eud->part))
3408        {
3409           eud->u.drag_position.x = dx;
3410           eud->u.drag_position.y = dy;
3411           break;
3412        }
3413    if (!eud)
3414      {
3415         eud = _edje_user_definition_new(EDJE_USER_DRAG_STEP, part, ed);
3416         if (eud)
3417           {
3418              eud->u.drag_position.x = dx;
3419              eud->u.drag_position.y = dy;
3420           }
3421      }
3422
3423    if (dx < 0.0) dx = 0.0;
3424    else if (dx > 1.0)
3425      dx = 1.0;
3426    if (dy < 0.0) dy = 0.0;
3427    else if (dy > 1.0)
3428      dy = 1.0;
3429    rp->drag->step.x = FROM_DOUBLE(dx);
3430    rp->drag->step.y = FROM_DOUBLE(dy);
3431 #ifdef EDJE_CALC_CACHE
3432    rp->invalidate = 1;
3433 #endif
3434    return EINA_TRUE;
3435 }
3436
3437 EAPI Eina_Bool
3438 edje_object_part_drag_step_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
3439 {
3440    Edje *ed;
3441    Edje_Real_Part *rp;
3442
3443    ed = _edje_fetch(obj);
3444    if ((!ed) || (!part))
3445      {
3446         if (dx) *dx = 0;
3447         if (dy) *dy = 0;
3448         return EINA_FALSE;
3449      }
3450
3451    /* Need to recalc before providing the object. */
3452    _edje_recalc_do(ed);
3453
3454    rp = _edje_real_part_recursive_get(ed, part);
3455    if (!rp || !rp->drag)
3456      {
3457         if (dx) *dx = 0;
3458         if (dy) *dy = 0;
3459         return EINA_FALSE;
3460      }
3461    if (dx) *dx = TO_DOUBLE(rp->drag->step.x);
3462    if (dy) *dy = TO_DOUBLE(rp->drag->step.y);
3463    return EINA_TRUE;
3464 }
3465
3466 EAPI Eina_Bool
3467 edje_object_part_drag_page_set(Evas_Object *obj, const char *part, double dx, double dy)
3468 {
3469    Edje *ed;
3470    Edje_Real_Part *rp;
3471    Edje_User_Defined *eud;
3472    Eina_List *l;
3473
3474    ed = _edje_fetch(obj);
3475    if ((!ed) || (!part)) return EINA_FALSE;
3476    rp = _edje_real_part_recursive_get(ed, part);
3477    if (!rp) return EINA_FALSE;
3478    if (!rp->drag) return EINA_FALSE;
3479
3480    EINA_LIST_FOREACH(ed->user_defined, l, eud)
3481      if (eud->type == EDJE_USER_DRAG_PAGE && !strcmp(part, eud->part))
3482        {
3483           eud->u.drag_position.x = dx;
3484           eud->u.drag_position.y = dy;
3485           break;
3486        }
3487    if (!eud)
3488      {
3489         eud = _edje_user_definition_new(EDJE_USER_DRAG_PAGE, part, ed);
3490         if (eud)
3491           {
3492              eud->u.drag_position.x = dx;
3493              eud->u.drag_position.y = dy;
3494           }
3495      }
3496
3497    if (dx < 0.0) dx = 0.0;
3498    else if (dx > 1.0)
3499      dx = 1.0;
3500    if (dy < 0.0) dy = 0.0;
3501    else if (dy > 1.0)
3502      dy = 1.0;
3503    rp->drag->page.x = FROM_DOUBLE(dx);
3504    rp->drag->page.y = FROM_DOUBLE(dy);
3505 #ifdef EDJE_CALC_CACHE
3506    rp->invalidate = 1;
3507 #endif
3508    return EINA_TRUE;
3509 }
3510
3511 EAPI Eina_Bool
3512 edje_object_part_drag_page_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
3513 {
3514    Edje *ed;
3515    Edje_Real_Part *rp;
3516
3517    ed = _edje_fetch(obj);
3518    if ((!ed) || (!part))
3519      {
3520         if (dx) *dx = 0;
3521         if (dy) *dy = 0;
3522         return EINA_FALSE;
3523      }
3524
3525    /* Need to recalc before providing the object. */
3526    _edje_recalc_do(ed);
3527
3528    rp = _edje_real_part_recursive_get(ed, part);
3529    if (!rp || !rp->drag)
3530      {
3531         if (dx) *dx = 0;
3532         if (dy) *dy = 0;
3533         return EINA_FALSE;
3534      }
3535    if (dx) *dx = TO_DOUBLE(rp->drag->page.x);
3536    if (dy) *dy = TO_DOUBLE(rp->drag->page.y);
3537    return EINA_TRUE;
3538 }
3539
3540 EAPI Eina_Bool
3541 edje_object_part_drag_step(Evas_Object *obj, const char *part, double dx, double dy)
3542 {
3543    Edje *ed;
3544    Edje_Real_Part *rp;
3545    FLOAT_T px, py;
3546    Edje_User_Defined *eud;
3547    Eina_List *l;
3548
3549    ed = _edje_fetch(obj);
3550    if ((!ed) || (!part)) return EINA_FALSE;
3551    rp = _edje_real_part_recursive_get(ed, part);
3552    if (!rp) return EINA_FALSE;
3553    if (!rp->drag) return EINA_FALSE;
3554    if (rp->drag->down.count > 0) return EINA_FALSE;
3555
3556    EINA_LIST_FOREACH(ed->user_defined, l, eud)
3557      if (eud->type == EDJE_USER_DRAG_STEP && !strcmp(part, eud->part))
3558        {
3559           eud->u.drag_position.x = dx;
3560           eud->u.drag_position.y = dy;
3561           break;
3562        }
3563    if (!eud)
3564      {
3565         eud = _edje_user_definition_new(EDJE_USER_DRAG_STEP, part, ed);
3566         if (eud)
3567           {
3568              eud->u.drag_position.x = dx;
3569              eud->u.drag_position.y = dy;
3570           }
3571      }
3572
3573    px = rp->drag->val.x;
3574    py = rp->drag->val.y;
3575    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx),
3576                                  MUL(rp->drag->step.x, rp->part->dragable.x)));
3577    rp->drag->val.y = ADD(py, MUL(FROM_DOUBLE(dy),
3578                                  MUL(rp->drag->step.y, rp->part->dragable.y)));
3579    rp->drag->val.x = CLAMP(rp->drag->val.x, ZERO, FROM_DOUBLE(1.0));
3580    rp->drag->val.y = CLAMP(rp->drag->val.y, ZERO, FROM_DOUBLE(1.0));
3581    if ((px == rp->drag->val.x) && (py == rp->drag->val.y)) return EINA_TRUE;
3582 #ifdef EDJE_CALC_CACHE
3583    rp->invalidate = 1;
3584 #endif
3585    _edje_dragable_pos_set(rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
3586    _edje_emit(rp->edje, "drag,step", rp->part->name);
3587    return EINA_TRUE;
3588 }
3589
3590 EAPI Eina_Bool
3591 edje_object_part_drag_page(Evas_Object *obj, const char *part, double dx, double dy)
3592 {
3593    Edje *ed;
3594    Edje_Real_Part *rp;
3595    FLOAT_T px, py;
3596    Edje_User_Defined *eud;
3597    Eina_List *l;
3598
3599    ed = _edje_fetch(obj);
3600    if ((!ed) || (!part)) return EINA_FALSE;
3601    rp = _edje_real_part_recursive_get(ed, part);
3602    if (!rp) return EINA_FALSE;
3603    if (!rp->drag) return EINA_FALSE;
3604    if (rp->drag->down.count > 0) return EINA_FALSE;
3605
3606    EINA_LIST_FOREACH(ed->user_defined, l, eud)
3607      if (eud->type == EDJE_USER_DRAG_PAGE && !strcmp(part, eud->part))
3608        {
3609           eud->u.drag_position.x = dx;
3610           eud->u.drag_position.y = dy;
3611           break;
3612        }
3613    if (!eud)
3614      {
3615         eud = _edje_user_definition_new(EDJE_USER_DRAG_PAGE, part, ed);
3616         if (eud)
3617           {
3618              eud->u.drag_position.x = dx;
3619              eud->u.drag_position.y = dy;
3620           }
3621      }
3622
3623    px = rp->drag->val.x;
3624    py = rp->drag->val.y;
3625    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx), MUL(rp->drag->page.x, rp->part->dragable.x)));
3626    rp->drag->val.y = ADD(py, MUL(FROM_DOUBLE(dy), MUL(rp->drag->page.y, rp->part->dragable.y)));
3627    rp->drag->val.x = CLAMP(rp->drag->val.x, ZERO, FROM_DOUBLE(1.0));
3628    rp->drag->val.y = CLAMP(rp->drag->val.y, ZERO, FROM_DOUBLE(1.0));
3629    if ((px == rp->drag->val.x) && (py == rp->drag->val.y)) return EINA_TRUE;
3630 #ifdef EDJE_CALC_CACHE
3631    rp->invalidate = 1;
3632 #endif
3633    _edje_dragable_pos_set(rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
3634    _edje_emit(rp->edje, "drag,page", rp->part->name);
3635    return EINA_TRUE;
3636 }
3637
3638 void
3639 _edje_box_init(void)
3640 {
3641 }
3642
3643 void
3644 _edje_box_shutdown(void)
3645 {
3646    if (!_edje_box_layout_registry)
3647      return;
3648
3649    eina_rbtree_delete
3650      (_edje_box_layout_registry, _edje_box_layout_external_free, NULL);
3651    _edje_box_layout_registry = NULL;
3652 }
3653
3654 EAPI Eina_Bool
3655 edje_object_part_box_append(Evas_Object *obj, const char *part, Evas_Object *child)
3656 {
3657    Edje *ed;
3658    Edje_Real_Part *rp;
3659    Eina_Bool r;
3660
3661    ed = _edje_fetch(obj);
3662    if ((!ed) || (!part) || (!child)) return EINA_FALSE;
3663
3664    rp = _edje_real_part_recursive_get(ed, part);
3665    if (!rp) return EINA_FALSE;
3666    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
3667
3668    r = _edje_real_part_box_append(rp, child);
3669
3670    if (r)
3671      {
3672         Edje_User_Defined *eud;
3673
3674         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
3675         if (!eud) return r;
3676         eud->u.box.child = child;
3677         eud->u.box.index = -1;
3678
3679         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
3680      }
3681    return r;
3682 }
3683
3684 EAPI Eina_Bool
3685 edje_object_part_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child)
3686 {
3687    Edje *ed;
3688    Edje_Real_Part *rp;
3689    Eina_Bool r;
3690
3691    ed = _edje_fetch(obj);
3692    if ((!ed) || (!part)) return EINA_FALSE;
3693
3694    rp = _edje_real_part_recursive_get(ed, part);
3695    if (!rp) return EINA_FALSE;
3696    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
3697
3698    r = _edje_real_part_box_prepend(rp, child);
3699
3700    if (r)
3701      {
3702         Edje_User_Defined *eud;
3703
3704         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
3705         if (!eud) return r;
3706         eud->u.box.child = child;
3707
3708         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
3709      }
3710    return r;
3711 }
3712
3713 EAPI Eina_Bool
3714 edje_object_part_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference)
3715 {
3716    Edje *ed;
3717    Edje_Real_Part *rp;
3718    Eina_Bool r;
3719
3720    ed = _edje_fetch(obj);
3721    if ((!ed) || (!part)) return EINA_FALSE;
3722
3723    rp = _edje_real_part_recursive_get(ed, part);
3724    if (!rp) return EINA_FALSE;
3725    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
3726
3727    r = _edje_real_part_box_insert_before(rp, child, reference);
3728
3729    if (r)
3730      {
3731         Edje_User_Defined *eud;
3732
3733         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
3734         if (!eud) return r;
3735         eud->u.box.child = child;
3736
3737         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
3738      }
3739    return r;
3740 }
3741
3742 EAPI Eina_Bool
3743 edje_object_part_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos)
3744 {
3745    Edje *ed;
3746    Edje_Real_Part *rp;
3747    Eina_Bool r;
3748
3749    ed = _edje_fetch(obj);
3750    if ((!ed) || (!part)) return EINA_FALSE;
3751
3752    rp = _edje_real_part_recursive_get(ed, part);
3753    if (!rp) return EINA_FALSE;
3754    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
3755
3756    r = _edje_real_part_box_insert_at(rp, child, pos);
3757
3758    if (r)
3759      {
3760         Edje_User_Defined *eud;
3761
3762         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
3763         if (!eud) return r;
3764         eud->u.box.child = child;
3765
3766         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
3767      }
3768    return r;
3769 }
3770
3771 EAPI Evas_Object *
3772 edje_object_part_box_remove(Evas_Object *obj, const char *part, Evas_Object *child)
3773 {
3774    Edje *ed;
3775    Edje_Real_Part *rp;
3776    Evas_Object *r;
3777
3778    ed = _edje_fetch(obj);
3779    if ((!ed) || (!part)) return NULL;
3780
3781    rp = _edje_real_part_recursive_get(ed, part);
3782    if (!rp) return NULL;
3783    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
3784
3785    r = _edje_real_part_box_remove(rp, child);
3786
3787    if (r)
3788      {
3789         Edje_User_Defined *eud;
3790         Eina_List *l;
3791
3792         EINA_LIST_FOREACH(ed->user_defined, l, eud)
3793           if (eud->type == EDJE_USER_BOX_PACK && eud->u.box.child == child && !strcmp(eud->part, part))
3794             {
3795                _edje_user_definition_free(eud);
3796                return r;
3797             }
3798      }
3799    return r;
3800 }
3801
3802 EAPI Evas_Object *
3803 edje_object_part_box_remove_at(Evas_Object *obj, const char *part, unsigned int pos)
3804 {
3805    Edje *ed;
3806    Edje_Real_Part *rp;
3807    Evas_Object *r;
3808
3809    ed = _edje_fetch(obj);
3810    if ((!ed) || (!part)) return NULL;
3811
3812    rp = _edje_real_part_recursive_get(ed, part);
3813    if (!rp) return NULL;
3814    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
3815
3816    r = _edje_real_part_box_remove_at(rp, pos);
3817
3818    if (r)
3819      {
3820         Edje_User_Defined *eud;
3821         Eina_List *l;
3822
3823         EINA_LIST_FOREACH(ed->user_defined, l, eud)
3824           if (eud->type == EDJE_USER_BOX_PACK && eud->u.box.child == r && !strcmp(eud->part, part))
3825             {
3826                _edje_user_definition_free(eud);
3827                return r;
3828             }
3829      }
3830    return r;
3831 }
3832
3833 EAPI Eina_Bool
3834 edje_object_part_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear)
3835 {
3836    Edje *ed;
3837    Edje_Real_Part *rp;
3838    Eina_Bool r;
3839
3840    ed = _edje_fetch(obj);
3841    if ((!ed) || (!part)) return EINA_FALSE;
3842
3843    rp = _edje_real_part_recursive_get(ed, part);
3844    if (!rp) return EINA_FALSE;
3845    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
3846
3847    r = _edje_real_part_box_remove_all(rp, clear);
3848    if (r)
3849      {
3850         Edje_User_Defined *eud;
3851         Eina_List *ll, *l;
3852
3853         EINA_LIST_FOREACH_SAFE(ed->user_defined, l, ll, eud)
3854           if (eud->type == EDJE_USER_BOX_PACK && !strcmp(eud->part, part))
3855             {
3856                _edje_user_definition_free(eud);
3857                return r;
3858             }
3859      }
3860    return r;
3861 }
3862
3863 EAPI Eina_List *
3864 edje_object_access_part_list_get(const Evas_Object *obj)
3865 {
3866    Edje *ed;
3867    Eina_List *access_parts = NULL;
3868
3869    ed = _edje_fetch(obj);
3870    if ((!ed)) return NULL;
3871
3872    unsigned int i;
3873    for (i = 0; i < ed->table_parts_size; i++)
3874      {
3875         Edje_Real_Part *rp;
3876         rp = ed->table_parts[i];
3877         if (rp->part->access)
3878           access_parts = eina_list_append(access_parts, rp->part->name);
3879      }
3880
3881    return access_parts;
3882 }
3883
3884 static void
3885 _edje_box_child_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
3886 {
3887    Edje_Real_Part *rp = data;
3888
3889    rp->edje->dirty = 1;
3890    rp->edje->recalc_call = 1;
3891 #ifdef EDJE_CALC_CACHE
3892    rp->invalidate = 1;
3893 #endif
3894    _edje_recalc(rp->edje);
3895 }
3896
3897 static void
3898 _edje_box_child_add(Edje_Real_Part *rp, Evas_Object *child)
3899 {
3900    evas_object_event_callback_add
3901      (child, EVAS_CALLBACK_DEL, _edje_box_child_del_cb, rp);
3902
3903    rp->edje->dirty = 1;
3904    rp->edje->recalc_call = 1;
3905 #ifdef EDJE_CALC_CACHE
3906    rp->invalidate = 1;
3907 #endif
3908    _edje_recalc(rp->edje);
3909 }
3910
3911 static void
3912 _edje_box_child_remove(Edje_Real_Part *rp, Evas_Object *child)
3913 {
3914    evas_object_event_callback_del_full
3915      (child, EVAS_CALLBACK_DEL, _edje_box_child_del_cb, rp);
3916
3917    rp->edje->dirty = 1;
3918    rp->edje->recalc_call = 1;
3919 #ifdef EDJE_CALC_CACHE
3920    rp->invalidate = 1;
3921 #endif
3922    _edje_recalc(rp->edje);
3923 }
3924
3925 Eina_Bool
3926 _edje_real_part_box_append(Edje_Real_Part *rp, Evas_Object *child_obj)
3927 {
3928    Evas_Object_Box_Option *opt;
3929
3930    opt = evas_object_box_append(rp->object, child_obj);
3931    if (!opt) return EINA_FALSE;
3932
3933    if (!_edje_box_layout_add_child(rp, child_obj))
3934      {
3935         evas_object_box_remove(rp->object, child_obj);
3936         return EINA_FALSE;
3937      }
3938
3939    _edje_box_child_add(rp, child_obj);
3940
3941    return EINA_TRUE;
3942 }
3943
3944 Eina_Bool
3945 _edje_real_part_box_prepend(Edje_Real_Part *rp, Evas_Object *child_obj)
3946 {
3947    Evas_Object_Box_Option *opt;
3948
3949    opt = evas_object_box_prepend(rp->object, child_obj);
3950    if (!opt) return EINA_FALSE;
3951
3952    if (!_edje_box_layout_add_child(rp, child_obj))
3953      {
3954         evas_object_box_remove(rp->object, child_obj);
3955         return EINA_FALSE;
3956      }
3957
3958    _edje_box_child_add(rp, child_obj);
3959
3960    return EINA_TRUE;
3961 }
3962
3963 Eina_Bool
3964 _edje_real_part_box_insert_before(Edje_Real_Part *rp, Evas_Object *child_obj, const Evas_Object *ref)
3965 {
3966    Evas_Object_Box_Option *opt;
3967
3968    opt = evas_object_box_insert_before(rp->object, child_obj, ref);
3969    if (!opt) return EINA_FALSE;
3970
3971    if (!_edje_box_layout_add_child(rp, child_obj))
3972      {
3973         evas_object_box_remove(rp->object, child_obj);
3974         return EINA_FALSE;
3975      }
3976
3977    _edje_box_child_add(rp, child_obj);
3978
3979    return EINA_TRUE;
3980 }
3981
3982 Eina_Bool
3983 _edje_real_part_box_insert_at(Edje_Real_Part *rp, Evas_Object *child_obj, unsigned int pos)
3984 {
3985    Evas_Object_Box_Option *opt;
3986
3987    opt = evas_object_box_insert_at(rp->object, child_obj, pos);
3988    if (!opt) return EINA_FALSE;
3989
3990    if (!_edje_box_layout_add_child(rp, child_obj))
3991      {
3992         evas_object_box_remove(rp->object, child_obj);
3993         return EINA_FALSE;
3994      }
3995
3996    _edje_box_child_add(rp, child_obj);
3997
3998    return EINA_TRUE;
3999 }
4000
4001 Evas_Object *
4002 _edje_real_part_box_remove(Edje_Real_Part *rp, Evas_Object *child_obj)
4003 {
4004    if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
4005    if (!evas_object_box_remove(rp->object, child_obj)) return NULL;
4006    _edje_box_layout_remove_child(rp, child_obj);
4007    _edje_box_child_remove(rp, child_obj);
4008    return child_obj;
4009 }
4010
4011 Evas_Object *
4012 _edje_real_part_box_remove_at(Edje_Real_Part *rp, unsigned int pos)
4013 {
4014    Evas_Object_Box_Option *opt;
4015    Evas_Object_Box_Data *priv;
4016    Evas_Object *child_obj;
4017
4018    priv = evas_object_smart_data_get(rp->object);
4019    opt = eina_list_nth(priv->children, pos);
4020    if (!opt) return NULL;
4021    child_obj = opt->obj;
4022    if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
4023    if (!evas_object_box_remove_at(rp->object, pos)) return NULL;
4024    _edje_box_layout_remove_child(rp, child_obj);
4025    _edje_box_child_remove(rp, child_obj);
4026    return child_obj;
4027 }
4028
4029 Eina_Bool
4030 _edje_real_part_box_remove_all(Edje_Real_Part *rp, Eina_Bool clear)
4031 {
4032    Eina_List *children;
4033    int i = 0;
4034
4035    children = evas_object_box_children_get(rp->object);
4036    while (children)
4037      {
4038         Evas_Object *child_obj = children->data;
4039         if (evas_object_data_get(child_obj, "\377 edje.box_item"))
4040           i++;
4041         else
4042           {
4043              _edje_box_layout_remove_child(rp, child_obj);
4044              _edje_box_child_remove(rp, child_obj);
4045              if (!evas_object_box_remove_at(rp->object, i))
4046                return EINA_FALSE;
4047              if (clear)
4048                evas_object_del(child_obj);
4049           }
4050         children = eina_list_remove_list(children, children);
4051      }
4052    return EINA_TRUE;
4053 }
4054
4055 static void
4056 _edje_table_child_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child, void *einfo __UNUSED__)
4057 {
4058    Edje_User_Defined *eud;
4059    Eina_List *l;
4060    Edje_Real_Part *rp = data;
4061
4062    EINA_LIST_FOREACH(rp->edje->user_defined, l, eud)
4063      if (rp->part->type == EDJE_PART_TYPE_BOX)
4064        {
4065           if (eud->type == EDJE_USER_BOX_PACK &&
4066               eud->u.box.child == child &&
4067               !strcmp(rp->part->name, eud->part))
4068             {
4069                _edje_user_definition_free(eud);
4070                break;
4071             }
4072        }
4073      else if (rp->part->type == EDJE_PART_TYPE_TABLE)
4074        {
4075           if (eud->type == EDJE_USER_TABLE_PACK &&
4076               eud->u.table.child == child &&
4077               !strcmp(rp->part->name, eud->part))
4078             {
4079                _edje_user_definition_free(eud);
4080                break;
4081             }
4082        }
4083
4084    rp->edje->dirty = 1;
4085    rp->edje->recalc_call = 1;
4086 #ifdef EDJE_CALC_CACHE
4087    rp->invalidate = 1;
4088 #endif
4089    _edje_recalc(rp->edje);
4090 }
4091
4092 static void
4093 _edje_table_child_add(Edje_Real_Part *rp, Evas_Object *child)
4094 {
4095    evas_object_event_callback_add
4096      (child, EVAS_CALLBACK_DEL, _edje_table_child_del_cb, rp);
4097
4098    rp->edje->dirty = 1;
4099    rp->edje->recalc_call = 1;
4100 #ifdef EDJE_CALC_CACHE
4101    rp->invalidate = 1;
4102 #endif
4103    _edje_recalc(rp->edje);
4104 }
4105
4106 static void
4107 _edje_table_child_remove(Edje_Real_Part *rp, Evas_Object *child)
4108 {
4109    evas_object_event_callback_del_full
4110      (child, EVAS_CALLBACK_DEL, _edje_table_child_del_cb, rp);
4111
4112    rp->edje->dirty = 1;
4113    rp->edje->recalc_call = 1;
4114 #ifdef EDJE_CALC_CACHE
4115    rp->invalidate = 1;
4116 #endif
4117    _edje_recalc(rp->edje);
4118 }
4119
4120 EAPI Evas_Object *
4121 edje_object_part_table_child_get(const Evas_Object *obj, const char *part, unsigned int col, unsigned int row)
4122 {
4123    Edje *ed;
4124    Edje_Real_Part *rp;
4125
4126    ed = _edje_fetch(obj);
4127    if ((!ed) || (!part)) return NULL;
4128
4129    rp = _edje_real_part_recursive_get(ed, part);
4130    if (!rp) return NULL;
4131    if (rp->part->type != EDJE_PART_TYPE_TABLE) return NULL;
4132
4133    return evas_object_table_child_get(rp->object, col, row);
4134 }
4135
4136 EAPI Eina_Bool
4137 edje_object_part_table_pack(Evas_Object *obj, const char *part, Evas_Object *child_obj, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
4138 {
4139    Edje *ed;
4140    Edje_Real_Part *rp;
4141    Edje_User_Defined *eud;
4142    Eina_Bool r;
4143
4144    ed = _edje_fetch(obj);
4145    if ((!ed) || (!part)) return EINA_FALSE;
4146
4147    rp = _edje_real_part_recursive_get(ed, part);
4148    if (!rp) return EINA_FALSE;
4149    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
4150
4151    r = _edje_real_part_table_pack(rp, child_obj, col, row, colspan, rowspan);
4152    if (r)
4153      {
4154         eud = _edje_user_definition_new(EDJE_USER_TABLE_PACK, part, ed);
4155         if (!eud) return r;
4156
4157         eud->u.table.child = child_obj;
4158         eud->u.table.col = col;
4159         eud->u.table.row = row;
4160         eud->u.table.colspan = colspan;
4161         eud->u.table.rowspan = rowspan;
4162
4163         evas_object_event_callback_add(child_obj, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
4164      }
4165    return r;
4166 }
4167
4168 EAPI Eina_Bool
4169 edje_object_part_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child_obj)
4170 {
4171    Edje *ed;
4172    Edje_Real_Part *rp;
4173    Eina_Bool r;
4174
4175    ed = _edje_fetch(obj);
4176    if ((!ed) || (!part)) return EINA_FALSE;
4177
4178    rp = _edje_real_part_recursive_get(ed, part);
4179    if (!rp) return EINA_FALSE;
4180    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
4181
4182    r = _edje_real_part_table_unpack(rp, child_obj);
4183
4184    if (r)
4185      {
4186         Edje_User_Defined *eud;
4187         Eina_List *l;
4188
4189         EINA_LIST_FOREACH(ed->user_defined, l, eud)
4190           if (eud->type == EDJE_USER_TABLE_PACK &&
4191               eud->u.table.child == child_obj &&
4192               !strcmp(part, eud->part))
4193             {
4194                _edje_user_definition_free(eud);
4195                break;
4196             }
4197      }
4198
4199    return r;
4200 }
4201
4202 EAPI Eina_Bool
4203 edje_object_part_table_col_row_size_get(const Evas_Object *obj, const char *part, int *cols, int *rows)
4204 {
4205    Edje *ed;
4206    Edje_Real_Part *rp;
4207
4208    ed = _edje_fetch(obj);
4209    if ((!ed) || (!part)) return EINA_FALSE;
4210
4211    rp = _edje_real_part_recursive_get(ed, part);
4212    if (!rp) return EINA_FALSE;
4213    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
4214
4215    evas_object_table_col_row_size_get(rp->object, cols, rows);
4216    return EINA_TRUE;
4217 }
4218
4219 EAPI Eina_Bool
4220 edje_object_part_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear)
4221 {
4222    Edje *ed;
4223    Edje_Real_Part *rp;
4224
4225    ed = _edje_fetch(obj);
4226    if ((!ed) || (!part)) return EINA_FALSE;
4227
4228    rp = _edje_real_part_recursive_get(ed, part);
4229    if (!rp) return EINA_FALSE;
4230    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
4231
4232    _edje_real_part_table_clear(rp, clear);
4233    return EINA_TRUE;
4234 }
4235
4236 static void
4237 _edje_perspective_obj_del(void *data, __UNUSED__ Evas *e, __UNUSED__ Evas_Object *obj, __UNUSED__ void *event_info)
4238 {
4239    Edje_Perspective *ps = data;
4240    Evas_Object *o;
4241
4242    EINA_LIST_FREE(ps->users, o)
4243      {
4244         Edje *ed;
4245
4246         ed = evas_object_smart_data_get(o);
4247         if (!ed) continue;
4248         ed->persp = NULL;
4249         ed->dirty = 1;
4250         ed->recalc_call = 1;
4251         _edje_recalc_do(ed);
4252      }
4253    free(ps);
4254 }
4255
4256 EAPI Edje_Perspective *
4257 edje_perspective_new(Evas *e)
4258 {
4259    Edje_Perspective *ps;
4260    Evas_Coord vx, vy, vw, vh;
4261
4262    if (!e) return NULL;
4263    ps = calloc(1, sizeof(Edje_Perspective));
4264    ps->obj = evas_object_rectangle_add(e);
4265    evas_object_data_set(ps->obj, "_edje_perspective", ps);
4266    evas_object_event_callback_add(ps->obj, EVAS_CALLBACK_DEL, _edje_perspective_obj_del, ps);
4267    evas_output_viewport_get(e, &vx, &vy, &vw, &vh);
4268    ps->e = e;
4269    ps->px = vx + (vw / 2);
4270    ps->py = vy + (vh / 2);
4271    ps->z0 = 0;
4272    ps->foc = 1000;
4273    return ps;
4274 }
4275
4276 EAPI void
4277 edje_perspective_free(Edje_Perspective *ps)
4278 {
4279    if (!ps) return;
4280    evas_object_del(ps->obj);
4281 }
4282
4283 EAPI void
4284 edje_perspective_set(Edje_Perspective *ps, Evas_Coord px, Evas_Coord py, Evas_Coord z0, Evas_Coord foc)
4285 {
4286    Eina_List *l;
4287    Evas_Object *o;
4288
4289    if (!ps) return;
4290    if ((ps->px == px) && (ps->py == py) && (ps->z0 == z0) && (ps->foc == foc)) return;
4291    ps->px = px;
4292    ps->py = py;
4293    ps->z0 = z0;
4294    ps->foc = foc;
4295    EINA_LIST_FOREACH(ps->users, l, o)
4296      {
4297         Edje *ed;
4298
4299         ed = evas_object_smart_data_get(o);
4300         if (!ed) continue;
4301         if (!ed->persp)
4302           {
4303              ed->dirty = 1;
4304              ed->recalc_call = 1;
4305              _edje_recalc_do(ed);
4306           }
4307      }
4308    if (ps->global)
4309      {
4310         EINA_LIST_FOREACH(_edje_edjes, l, o)
4311           {
4312              Edje *ed;
4313
4314              ed = evas_object_smart_data_get(o);
4315              if (!ed) continue;
4316              if (!ed->persp)
4317                {
4318                   ed->dirty = 1;
4319                   ed->recalc_call = 1;
4320                   _edje_recalc_do(ed);
4321                }
4322           }
4323      }
4324 }
4325
4326 EAPI void
4327 edje_perspective_global_set(Edje_Perspective *ps, Eina_Bool global)
4328 {
4329    Evas_Object *o;
4330    Eina_List *l;
4331
4332    if (!ps) return;
4333    if (ps->global == global) return;
4334    if (global)
4335      {
4336         o = evas_object_name_find(evas_object_evas_get(ps->obj),
4337                                   "_edje_perspective");
4338         if (o) evas_object_name_set(o, NULL);
4339         evas_object_name_set(ps->obj, "_edje_perspective");
4340      }
4341    else
4342      evas_object_name_set(ps->obj, NULL);
4343    ps->global = global;
4344    EINA_LIST_FOREACH(_edje_edjes, l, o)
4345      {
4346         Edje *ed;
4347
4348         ed = evas_object_smart_data_get(o);
4349         if (!ed) continue;
4350         if (!ed->persp)
4351           {
4352              ed->dirty = 1;
4353              ed->recalc_call = 1;
4354              _edje_recalc_do(ed);
4355           }
4356      }
4357 }
4358
4359 EAPI Eina_Bool
4360 edje_perspective_global_get(const Edje_Perspective *ps)
4361 {
4362    if (!ps) return EINA_FALSE;
4363    return ps->global;
4364 }
4365
4366 EAPI const Edje_Perspective *
4367 edje_evas_global_perspective_get(const Evas *e)
4368 {
4369    Evas_Object *obj;
4370
4371    if (!e) return NULL;
4372    obj = evas_object_name_find(e, "_edje_perspective");
4373    if (!obj) return NULL;
4374    return evas_object_data_get(obj, "_edje_perspective");
4375 }
4376
4377 EAPI void
4378 edje_object_perspective_set(Evas_Object *obj, Edje_Perspective *ps)
4379 {
4380    Edje *ed;
4381
4382    ed = evas_object_smart_data_get(obj);
4383    if (!ed) return;
4384    if (ed->persp == ps) return;
4385    if (ed->persp != ps)
4386      {
4387         if (ed->persp)
4388           ed->persp->users = eina_list_remove(ed->persp->users, obj);
4389      }
4390    ed->persp = ps;
4391    if (ps) ps->users = eina_list_append(ps->users, obj);
4392    ed->dirty = 1;
4393    ed->recalc_call = 1;
4394    _edje_recalc_do(ed);
4395 }
4396
4397 EAPI const Edje_Perspective *
4398 edje_object_perspective_get(const Evas_Object *obj)
4399 {
4400    Edje *ed;
4401
4402    ed = evas_object_smart_data_get(obj);
4403    if (!ed) return NULL;
4404    return ed->persp;
4405 }
4406
4407 #define EDJE_PRELOAD_EMISSION "preload,done"
4408 #define EDJE_PRELOAD_SOURCE   NULL
4409
4410 EAPI Eina_Bool
4411 edje_object_preload(Evas_Object *obj, Eina_Bool cancel)
4412 {
4413    Edje *ed;
4414    int count;
4415    unsigned int i;
4416
4417    ed = _edje_fetch(obj);
4418    if (!ed) return EINA_FALSE;
4419
4420    _edje_recalc_do(ed);
4421
4422    for (i = 0, count = 0; i < ed->table_parts_size; i++)
4423      {
4424         Edje_Real_Part *rp;
4425         Edje_Part *ep;
4426
4427         rp = ed->table_parts[i];
4428         ep = rp->part;
4429
4430         if (ep->type == EDJE_PART_TYPE_IMAGE ||
4431             (ep->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object))
4432           count++;
4433      }
4434
4435    ed->preload_count = count;
4436
4437    if (count > 0)
4438      {
4439         for (i = 0; i < ed->table_parts_size; i++)
4440           {
4441              Edje_Real_Part *rp;
4442              Edje_Part *ep;
4443
4444              rp = ed->table_parts[i];
4445              ep = rp->part;
4446
4447              if (ep->type == EDJE_PART_TYPE_IMAGE)
4448                {
4449                   const char *file = NULL;
4450                   const char *key = NULL;
4451
4452                   evas_object_event_callback_del_full(rp->object, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
4453
4454                   evas_object_image_file_get(rp->object, &file, &key);
4455                   if (!file && !key)
4456                     {
4457                        ed->preload_count--;
4458                     }
4459                   else
4460                     {
4461                        evas_object_event_callback_add(rp->object, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
4462                        evas_object_image_preload(rp->object, cancel);
4463                     }
4464                   count--;
4465                }
4466              else if (ep->type == EDJE_PART_TYPE_GROUP)
4467                {
4468                   if (rp->swallowed_object)
4469                     {
4470                        char *tmp;
4471
4472                        if (rp->part->name)
4473                          {
4474                             tmp = alloca(strlen(rp->part->name) + 2);
4475                             sprintf(tmp, "%s:", rp->part->name);
4476
4477                             edje_object_signal_callback_del(obj, EDJE_PRELOAD_EMISSION, tmp, _edje_object_signal_preload_cb);
4478                             edje_object_signal_callback_add(obj, EDJE_PRELOAD_EMISSION, tmp, _edje_object_signal_preload_cb, ed);
4479                             edje_object_preload(rp->swallowed_object, cancel);
4480                          }
4481                        else
4482                          {
4483                             ed->preload_count--;
4484                          }
4485
4486                        count--;
4487                     }
4488                }
4489           }
4490      }
4491    else
4492      {
4493         _edje_emit(ed, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE);
4494      }
4495
4496    return EINA_TRUE;
4497 }
4498
4499 EAPI void
4500 edje_object_update_hints_set(Evas_Object *obj, Eina_Bool update)
4501 {
4502    Edje *ed;
4503
4504    ed = _edje_fetch(obj);
4505    if (!ed) return;
4506    if (ed->update_hints == !!update) return;
4507
4508    ed->update_hints = !!update;
4509    if (update)
4510      {
4511         ed->recalc_hints = 1;
4512         _edje_recalc(ed);
4513      }
4514 }
4515
4516 EAPI Eina_Bool
4517 edje_object_update_hints_get(Evas_Object *obj)
4518 {
4519    Edje *ed;
4520
4521    ed = _edje_fetch(obj);
4522    if (!ed) return EINA_FALSE;
4523
4524    return ed->update_hints;
4525 }
4526
4527 Eina_Bool
4528 _edje_real_part_table_pack(Edje_Real_Part *rp, Evas_Object *child_obj, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
4529 {
4530    Eina_Bool ret =
4531      evas_object_table_pack(rp->object, child_obj, col, row, colspan, rowspan);
4532
4533    _edje_table_child_add(rp, child_obj);
4534
4535    return ret;
4536 }
4537
4538 Eina_Bool
4539 _edje_real_part_table_unpack(Edje_Real_Part *rp, Evas_Object *child_obj)
4540 {
4541    Eina_Bool ret = evas_object_table_unpack(rp->object, child_obj);
4542
4543    if (ret)
4544      _edje_table_child_remove(rp, child_obj);
4545
4546    return ret;
4547 }
4548
4549 void
4550 _edje_real_part_table_clear(Edje_Real_Part *rp, Eina_Bool clear)
4551 {
4552    Eina_List *children;
4553
4554    children = evas_object_table_children_get(rp->object);
4555    while (children)
4556      {
4557         Evas_Object *child_obj = children->data;
4558
4559         _edje_table_child_remove(rp, child_obj);
4560         if (!evas_object_data_get(child_obj, "\377 edje.table_item"))
4561           {
4562              evas_object_table_unpack(rp->object, child_obj);
4563              if (clear)
4564                evas_object_del(child_obj);
4565           }
4566         children = eina_list_remove_list(children, children);
4567      }
4568 }
4569
4570 Edje_Real_Part *
4571 _edje_real_part_recursive_get(const Edje *ed, const char *part)
4572 {
4573    Edje_Real_Part *rp;
4574    char **path;
4575
4576    path = eina_str_split(part, EDJE_PART_PATH_SEPARATOR_STRING, 0);
4577    if (!path) return NULL;
4578
4579    rp = _edje_real_part_recursive_get_helper(ed, path);
4580
4581    free(*path);
4582    free(path);
4583    return rp;
4584 }
4585
4586 Evas_Object *
4587 _edje_children_get(Edje_Real_Part *rp, const char *partid)
4588 {
4589    Evas_Object *child;
4590    Eina_List *l;
4591    long int v;
4592    char *p;
4593
4594    if (!partid) return NULL;
4595
4596    switch (rp->part->type)
4597      {
4598       case EDJE_PART_TYPE_EXTERNAL:
4599         return _edje_external_content_get(rp->swallowed_object, partid);
4600
4601       case EDJE_PART_TYPE_BOX:
4602         l = evas_object_box_children_get(rp->object);
4603         break;
4604
4605       case EDJE_PART_TYPE_TABLE:
4606         l = evas_object_table_children_get(rp->object);
4607         break;
4608
4609       default:
4610         return NULL;
4611      }
4612
4613    v = strtol(partid, &p, 10);
4614    if ((*p == '\0') && (v >= 0))
4615      {
4616         child = eina_list_nth(l, v);
4617      }
4618    else
4619      {
4620         Evas_Object *cur;
4621         child = NULL;
4622         EINA_LIST_FREE(l, cur)
4623           {
4624              const char *name = evas_object_name_get(cur);
4625              if ((name) && (!strcmp(name, partid)))
4626                {
4627                   child = cur;
4628                   break;
4629                }
4630           }
4631      }
4632    eina_list_free(l);
4633
4634    return child;
4635 }
4636
4637 /* rebuild alternative path */
4638 char *
4639 _edje_merge_path(const char *alias, char *const *path)
4640 {
4641    char *tmp;
4642    unsigned int length = 1;
4643    unsigned int alias_length;
4644    unsigned int i;
4645
4646    if (!alias) return NULL;
4647
4648    alias_length = strlen(alias);
4649
4650    for (i = 0; path[i]; i++)
4651      length += strlen(path[i]) + 1;
4652
4653    tmp = malloc(sizeof (char) * (length + alias_length + 2));
4654    memcpy(tmp, alias, alias_length);
4655    tmp[alias_length] = '\0';
4656
4657    for (i = 0; path[i]; i++)
4658      {
4659         strcat(tmp, EDJE_PART_PATH_SEPARATOR_STRING);
4660         strcat(tmp, path[i]);
4661      }
4662
4663    return tmp;
4664 }
4665
4666 Edje_Real_Part *
4667 _edje_real_part_recursive_get_helper(const Edje *ed, char **path)
4668 {
4669    Edje_Real_Part *rp;
4670    Evas_Object *child;
4671    char *idx = NULL;
4672
4673    if (!path[0])
4674      return NULL;
4675
4676    if (ed->collection && ed->collection->alias)
4677      {
4678         char *alias;
4679
4680         alias = _edje_merge_path(eina_hash_find(ed->collection->alias, path[0]), path + 1);
4681         if (alias)
4682           {
4683              rp = _edje_real_part_recursive_get(ed, alias);
4684              free(alias);
4685              return rp;
4686           }
4687      }
4688
4689    //printf("  lookup: %s on %s\n", path[0], ed->parent ? ed->parent : "-");
4690    idx = strchr(path[0], EDJE_PART_PATH_SEPARATOR_INDEXL);
4691    if (idx)
4692      {
4693         char *end;
4694
4695         end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
4696         if (end)
4697           {
4698              *end = '\0';
4699              *idx = '\0';
4700              idx++;
4701           }
4702      }
4703
4704    rp = _edje_real_part_get(ed, path[0]);
4705    if (!path[1] && !idx) return rp;
4706    if (!rp) return NULL;
4707
4708    switch (rp->part->type)
4709      {
4710       case EDJE_PART_TYPE_GROUP:
4711         if (!rp->swallowed_object) return NULL;
4712         ed = _edje_fetch(rp->swallowed_object);
4713         if (!ed) return NULL;
4714         path++;
4715         return _edje_real_part_recursive_get_helper(ed, path);
4716
4717       case EDJE_PART_TYPE_BOX:
4718       case EDJE_PART_TYPE_TABLE:
4719       case EDJE_PART_TYPE_EXTERNAL:
4720         if (!idx) return rp;
4721         path++;
4722
4723         child = _edje_children_get(rp, idx);
4724
4725         ed = _edje_fetch(child);
4726
4727         if (!ed) return NULL;
4728         return _edje_real_part_recursive_get_helper(ed, path);
4729
4730       default:
4731         return NULL;
4732      }
4733 }
4734
4735 /* Private Routines */
4736 Edje_Real_Part *
4737 _edje_real_part_get(const Edje *ed, const char *part)
4738 {
4739    unsigned int i;
4740
4741    if (!part) return NULL;
4742
4743    for (i = 0; i < ed->table_parts_size; i++)
4744      {
4745         Edje_Real_Part *rp;
4746
4747         rp = ed->table_parts[i];
4748         if ((rp->part->name) && (!strcmp(rp->part->name, part))) return rp;
4749      }
4750    return NULL;
4751 }
4752
4753 Edje_Color_Class *
4754 _edje_color_class_find(Edje *ed, const char *color_class)
4755 {
4756    Edje_Color_Class *cc = NULL;
4757
4758    if ((!ed) || (!color_class)) return NULL;
4759
4760    /* first look through the object scope */
4761    cc = eina_hash_find(ed->color_classes, color_class);
4762    if (cc) return cc;
4763
4764    /* next look through the global scope */
4765    cc = eina_hash_find(_edje_color_class_hash, color_class);
4766    if (cc) return cc;
4767
4768    /* finally, look through the file scope */
4769    cc = eina_hash_find(ed->file->color_hash, color_class);
4770    if (cc) return cc;
4771
4772    return NULL;
4773 }
4774
4775 void
4776 _edje_color_class_member_add(Edje *ed, const char *color_class)
4777 {
4778    _edje_class_member_add(ed, &ed->members.color_class, &_edje_color_class_member_hash, color_class);
4779 }
4780
4781 void
4782 _edje_color_class_member_direct_del(const char *color_class, void *l)
4783 {
4784    _edje_class_member_direct_del(color_class, l, _edje_color_class_member_hash);
4785 }
4786
4787 void
4788 _edje_color_class_member_del(Edje *ed, const char *color_class)
4789 {
4790    if ((!ed) || (!color_class)) return;
4791
4792    _edje_class_member_del(&ed->members.color_class, &_edje_color_class_member_hash, color_class);
4793 }
4794
4795 void
4796 _edje_color_class_members_free(void)
4797 {
4798    if (!_edje_color_class_member_hash) return;
4799    eina_hash_foreach(_edje_color_class_member_hash, member_list_free, NULL);
4800    eina_hash_free(_edje_color_class_member_hash);
4801    _edje_color_class_member_hash = NULL;
4802 }
4803
4804 static Eina_Bool
4805 color_class_hash_list_free(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
4806 {
4807    Edje_Color_Class *cc;
4808
4809    cc = data;
4810    if (cc->name) eina_stringshare_del(cc->name);
4811    free(cc);
4812    return EINA_TRUE;
4813 }
4814
4815 void
4816 _edje_color_class_hash_free(void)
4817 {
4818    if (!_edje_color_class_hash) return;
4819    eina_hash_foreach(_edje_color_class_hash, color_class_hash_list_free, NULL);
4820    eina_hash_free(_edje_color_class_hash);
4821    _edje_color_class_hash = NULL;
4822 }
4823
4824 void
4825 _edje_color_class_on_del(Edje *ed, Edje_Part *ep)
4826 {
4827    unsigned int i;
4828
4829    if ((ep->default_desc) && (ep->default_desc->color_class))
4830      _edje_color_class_member_del(ed, ep->default_desc->color_class);
4831
4832    for (i = 0; i < ep->other.desc_count; ++i)
4833      if (ep->other.desc[i]->color_class)
4834        _edje_color_class_member_del(ed, ep->other.desc[i]->color_class);
4835 }
4836
4837 Edje_Text_Class *
4838 _edje_text_class_find(Edje *ed, const char *text_class)
4839 {
4840    Eina_List *l;
4841    Edje_Text_Class *tc;
4842
4843    if ((!ed) || (!text_class)) return NULL;
4844    EINA_LIST_FOREACH(ed->text_classes, l, tc)
4845      if ((tc->name) && (!strcmp(text_class, tc->name))) return tc;
4846    return eina_hash_find(_edje_text_class_hash, text_class);
4847 }
4848
4849 void
4850 _edje_text_class_member_direct_del(const char *text_class,
4851                                    void *l)
4852 {
4853    _edje_class_member_direct_del(text_class, l, _edje_text_class_member_hash);
4854 }
4855
4856 void
4857 _edje_text_class_member_add(Edje *ed, const char *text_class)
4858 {
4859    _edje_class_member_add(ed, &ed->members.text_class, &_edje_text_class_member_hash, text_class);
4860 }
4861
4862 void
4863 _edje_text_class_member_del(Edje *ed, const char *text_class)
4864 {
4865    if ((!ed) || (!text_class)) return;
4866
4867    _edje_class_member_del(&ed->members.text_class, &_edje_text_class_member_hash, text_class);
4868 }
4869
4870 void
4871 _edje_text_class_members_free(void)
4872 {
4873    _edje_class_members_free(&_edje_text_class_member_hash);
4874 }
4875
4876 static Eina_Bool
4877 text_class_hash_list_free(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
4878 {
4879    Edje_Text_Class *tc;
4880
4881    tc = data;
4882    if (tc->name) eina_stringshare_del(tc->name);
4883    if (tc->font) eina_stringshare_del(tc->font);
4884    free(tc);
4885    return EINA_TRUE;
4886 }
4887
4888 void
4889 _edje_text_class_hash_free(void)
4890 {
4891    if (!_edje_text_class_hash) return;
4892    eina_hash_foreach(_edje_text_class_hash, text_class_hash_list_free, NULL);
4893    eina_hash_free(_edje_text_class_hash);
4894    _edje_text_class_hash = NULL;
4895 }
4896
4897 Edje *
4898 _edje_fetch(const Evas_Object *obj)
4899 {
4900    Edje *ed;
4901
4902    if (!evas_object_smart_type_check(obj, "edje"))
4903      return NULL;
4904    ed = evas_object_smart_data_get(obj);
4905    if ((ed) && (ed->delete_me)) return NULL;
4906    return ed;
4907 }
4908
4909 int
4910 _edje_freeze(Edje *ed)
4911 {
4912    ed->freeze++;
4913 //   printf("FREEZE %i\n", ed->freeze);
4914    return ed->freeze;
4915 }
4916
4917 int
4918 _edje_thaw(Edje *ed)
4919 {
4920    ed->freeze--;
4921    if (ed->freeze < 0)
4922      {
4923 //      printf("-------------########### OVER THAW\n");
4924         ed->freeze = 0;
4925      }
4926    if ((ed->freeze == 0) && (ed->recalc))
4927      {
4928 //      printf("thaw recalc\n");
4929         _edje_recalc(ed);
4930      }
4931    return ed->freeze;
4932 }
4933
4934 int
4935 _edje_block(Edje *ed)
4936 {
4937    _edje_ref(ed);
4938    ed->block++;
4939    return ed->block;
4940 }
4941
4942 int
4943 _edje_unblock(Edje *ed)
4944 {
4945    int ret = 0;
4946
4947    if (!ed) return ret;
4948
4949    ed->block--;
4950    if (ed->block == 0) ed->block_break = 0;
4951    ret = ed->block;
4952    _edje_unref(ed);
4953    return ret;
4954 }
4955
4956 int
4957 _edje_block_break(Edje *ed)
4958 {
4959    if (ed->block_break) return 1;
4960    return 0;
4961 }
4962
4963 void
4964 _edje_block_violate(Edje *ed)
4965 {
4966    if (ed->block > 0) ed->block_break = 1;
4967 }
4968
4969 void
4970 _edje_object_part_swallow_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
4971 {
4972    Edje_Real_Part *rp;
4973    Edje_User_Defined *eud;
4974    Eina_List *l;
4975
4976    rp = data;
4977
4978    EINA_LIST_FOREACH(rp->edje->user_defined, l, eud)
4979      if (eud->type == EDJE_USER_SWALLOW && eud->u.swallow.child == obj)
4980        {
4981           _edje_user_definition_free(eud);
4982           break;
4983        }
4984
4985    return;
4986 }
4987
4988 static void
4989 _edje_real_part_swallow_hints_update(Edje_Real_Part *rp)
4990 {
4991    const char *type;
4992
4993    type = evas_object_type_get(rp->swallowed_object);
4994
4995    rp->swallow_params.min.w = 0;
4996    rp->swallow_params.min.h = 0;
4997    rp->swallow_params.max.w = -1;
4998    rp->swallow_params.max.h = -1;
4999    if ((type) && (!strcmp(type, "edje")))
5000      {
5001         Evas_Coord w, h;
5002
5003 #if 0
5004         edje_object_size_min_get(rp->swallowed_object, &w, &h);
5005         rp->swallow_params.min.w = w;
5006         rp->swallow_params.min.h = h;
5007 #endif
5008         edje_object_size_max_get(rp->swallowed_object, &w, &h);
5009         rp->swallow_params.max.w = w;
5010         rp->swallow_params.max.h = h;
5011      }
5012    else if ((type) && ((!strcmp(type, "text")) || (!strcmp(type, "polygon")) ||
5013                        (!strcmp(type, "line"))))
5014      {
5015         Evas_Coord w, h;
5016
5017         evas_object_geometry_get(rp->swallowed_object, NULL, NULL, &w, &h);
5018 #if 0
5019         rp->swallow_params.min.w = w;
5020         rp->swallow_params.min.h = h;
5021 #endif
5022         rp->swallow_params.max.w = w;
5023         rp->swallow_params.max.h = h;
5024      }
5025    {
5026       Evas_Coord w1, h1, w2, h2, aw, ah;
5027       Evas_Aspect_Control am;
5028
5029       evas_object_size_hint_min_get(rp->swallowed_object, &w1, &h1);
5030       evas_object_size_hint_max_get(rp->swallowed_object, &w2, &h2);
5031       evas_object_size_hint_aspect_get(rp->swallowed_object, &am, &aw, &ah);
5032       rp->swallow_params.min.w = w1;
5033       rp->swallow_params.min.h = h1;
5034       if (w2 > 0) rp->swallow_params.max.w = w2;
5035       if (h2 > 0) rp->swallow_params.max.h = h2;
5036       switch (am)
5037         {
5038          case EVAS_ASPECT_CONTROL_NONE:
5039            rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_NONE;
5040            break;
5041
5042          case EVAS_ASPECT_CONTROL_NEITHER:
5043            rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_NEITHER;
5044            break;
5045
5046          case EVAS_ASPECT_CONTROL_HORIZONTAL:
5047            rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_HORIZONTAL;
5048            break;
5049
5050          case EVAS_ASPECT_CONTROL_VERTICAL:
5051            rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_VERTICAL;
5052            break;
5053
5054          case EVAS_ASPECT_CONTROL_BOTH:
5055            rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_BOTH;
5056            break;
5057
5058          default:
5059            break;
5060         }
5061       rp->swallow_params.aspect.w = aw;
5062       rp->swallow_params.aspect.h = ah;
5063       evas_object_data_set(rp->swallowed_object, "\377 edje.swallowing_part", rp);
5064    }
5065
5066 #ifdef EDJE_CALC_CACHE
5067    rp->invalidate = 1;
5068 #endif
5069 }
5070
5071 void
5072 _edje_object_part_swallow_changed_hints_cb(void *data, __UNUSED__ Evas *e, __UNUSED__ Evas_Object *obj, __UNUSED__ void *event_info)
5073 {
5074    Edje_Real_Part *rp;
5075
5076    rp = data;
5077    _edje_real_part_swallow_hints_update(rp);
5078    rp->edje->dirty = 1;
5079    rp->edje->recalc_call = 1;
5080    _edje_recalc(rp->edje);
5081    return;
5082 }
5083
5084 void
5085 _edje_real_part_swallow(Edje_Real_Part *rp,
5086                         Evas_Object *obj_swallow,
5087                         Eina_Bool hints_update)
5088 {
5089    if (rp->swallowed_object)
5090      {
5091         if (rp->swallowed_object != obj_swallow)
5092           {
5093              edje_object_part_unswallow(rp->edje->obj, rp->swallowed_object);
5094           }
5095         else
5096           {
5097              if (hints_update)
5098                _edje_real_part_swallow_hints_update(rp);
5099              rp->edje->dirty = 1;
5100              rp->edje->recalc_call = 1;
5101              rp->edje->recalc_hints = 1;
5102              _edje_recalc(rp->edje);
5103              return;
5104           }
5105      }
5106 #ifdef EDJE_CALC_CACHE
5107    rp->invalidate = 1;
5108 #endif
5109    if (!obj_swallow) return;
5110    rp->swallowed_object = obj_swallow;
5111    evas_object_smart_member_add(rp->swallowed_object, rp->edje->obj);
5112    if (rp->clip_to)
5113      evas_object_clip_set(rp->swallowed_object, rp->clip_to->object);
5114    else evas_object_clip_set(rp->swallowed_object, rp->edje->base.clipper);
5115    evas_object_stack_above(rp->swallowed_object, rp->object);
5116    evas_object_event_callback_add(rp->swallowed_object,
5117                                   EVAS_CALLBACK_DEL,
5118                                   _edje_object_part_swallow_free_cb,
5119                                   rp);
5120    evas_object_event_callback_add(rp->swallowed_object,
5121                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
5122                                   _edje_object_part_swallow_changed_hints_cb,
5123                                   rp);
5124
5125    if (hints_update)
5126      _edje_real_part_swallow_hints_update(rp);
5127
5128    if (rp->part->mouse_events)
5129      {
5130         _edje_callbacks_add(obj_swallow, rp->edje, rp);
5131         if (rp->part->repeat_events)
5132           evas_object_repeat_events_set(obj_swallow, 1);
5133         if (rp->part->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
5134           evas_object_pointer_mode_set(obj_swallow, rp->part->pointer_mode);
5135         evas_object_pass_events_set(obj_swallow, 0);
5136      }
5137    else
5138      evas_object_pass_events_set(obj_swallow, 1);
5139    _edje_callbacks_focus_add(rp->swallowed_object, rp->edje, rp);
5140
5141    if (rp->part->precise_is_inside)
5142      evas_object_precise_is_inside_set(obj_swallow, 1);
5143
5144    rp->edje->dirty = 1;
5145    rp->edje->recalc_call = 1;
5146    rp->edje->recalc_hints = 1;
5147    _edje_recalc(rp->edje);
5148 }
5149
5150 void
5151 _edje_real_part_swallow_clear(Edje_Real_Part *rp)
5152 {
5153    evas_object_smart_member_del(rp->swallowed_object);
5154    evas_object_event_callback_del_full(rp->swallowed_object,
5155                                        EVAS_CALLBACK_DEL,
5156                                        _edje_object_part_swallow_free_cb,
5157                                        rp);
5158    evas_object_event_callback_del_full(rp->swallowed_object,
5159                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
5160                                        _edje_object_part_swallow_changed_hints_cb,
5161                                        rp);
5162    evas_object_clip_unset(rp->swallowed_object);
5163    evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
5164    if (rp->part->mouse_events)
5165      _edje_callbacks_del(rp->swallowed_object, rp->edje);
5166    _edje_callbacks_focus_del(rp->swallowed_object, rp->edje);
5167    rp->swallowed_object = NULL;
5168 }
5169
5170 static void
5171 _edje_object_preload(Edje *ed)
5172 {
5173    ed->preload_count--;
5174    if (!ed->preload_count)
5175      _edje_emit(ed, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE);
5176 }
5177
5178 static void
5179 _edje_object_image_preload_cb(void *data, __UNUSED__ Evas *e, Evas_Object *obj, __UNUSED__ void *event_info)
5180 {
5181    Edje *ed = data;
5182
5183    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
5184    _edje_object_preload(ed);
5185 }
5186
5187 static void
5188 _edje_object_signal_preload_cb(void *data, Evas_Object *obj, __UNUSED__ const char *emission, __UNUSED__ const char *source)
5189 {
5190    Edje *ed = data;
5191
5192    edje_object_signal_callback_del(obj, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE, _edje_object_signal_preload_cb);
5193    _edje_object_preload(ed);
5194 }
5195
5196 /**
5197  * @internal
5198  *
5199  * for edje_cc
5200  */
5201 EAPI void
5202 _edje_program_remove(Edje_Part_Collection *edc, Edje_Program *p)
5203 {
5204    Edje_Program ***array;
5205    unsigned int *count;
5206    unsigned int i;
5207
5208    if (!p->signal && !p->source)
5209      {
5210         array = &edc->programs.nocmp;
5211         count = &edc->programs.nocmp_count;
5212      }
5213    else if (p->signal && !strpbrk(p->signal, "*?[\\")
5214             && p->source && !strpbrk(p->source, "*?[\\"))
5215      {
5216         array = &edc->programs.strcmp;
5217         count = &edc->programs.strcmp_count;
5218      }
5219    else if (p->signal && edje_program_is_strncmp(p->signal)
5220             && p->source && edje_program_is_strncmp(p->source))
5221      {
5222         array = &edc->programs.strncmp;
5223         count = &edc->programs.strncmp_count;
5224      }
5225    else if (p->signal && edje_program_is_strrncmp(p->signal)
5226             && p->source && edje_program_is_strrncmp(p->source))
5227      {
5228         array = &edc->programs.strrncmp;
5229         count = &edc->programs.strrncmp_count;
5230      }
5231    else
5232      {
5233         array = &edc->programs.fnmatch;
5234         count = &edc->programs.fnmatch_count;
5235      }
5236
5237    for (i = 0; i < *count; ++i)
5238      if ((*array)[i] == p)
5239        {
5240           memmove(*array + i, *array + i + 1, sizeof (Edje_Program *) * (*count - i - 1));
5241           (*count)--;
5242           break;
5243        }
5244 }
5245
5246 /**
5247  * @internal
5248  *
5249  * for edje_cc
5250  */
5251 EAPI void
5252 _edje_program_insert(Edje_Part_Collection *edc, Edje_Program *p)
5253 {
5254    Edje_Program ***array;
5255    unsigned int *count;
5256
5257    if (!p->signal && !p->source)
5258      {
5259         array = &edc->programs.nocmp;
5260         count = &edc->programs.nocmp_count;
5261      }
5262    else if (p->signal && !strpbrk(p->signal, "*?[\\")
5263             && p->source && !strpbrk(p->source, "*?[\\"))
5264      {
5265         array = &edc->programs.strcmp;
5266         count = &edc->programs.strcmp_count;
5267      }
5268    else if (p->signal && edje_program_is_strncmp(p->signal)
5269             && p->source && edje_program_is_strncmp(p->source))
5270      {
5271         array = &edc->programs.strncmp;
5272         count = &edc->programs.strncmp_count;
5273      }
5274    else if (p->signal && edje_program_is_strrncmp(p->signal)
5275             && p->source && edje_program_is_strrncmp(p->source))
5276      {
5277         array = &edc->programs.strrncmp;
5278         count = &edc->programs.strrncmp_count;
5279      }
5280    else
5281      {
5282         array = &edc->programs.fnmatch;
5283         count = &edc->programs.fnmatch_count;
5284      }
5285
5286    *array = realloc(*array, sizeof (Edje_Program *) * (*count + 1));
5287    (*array)[(*count)++] = p;
5288 }
5289
5290 const char *
5291 edje_string_get(const Edje_String *es)
5292 {
5293    /* FIXME: Handle localization here */
5294    if (!es) return NULL;
5295    return es->str;
5296 }
5297
5298 const char *
5299 edje_string_id_get(const Edje_String *es)
5300 {
5301    /* FIXME: Handle localization here */
5302    if (!es) return NULL;
5303    return es->str;
5304 }
5305
5306 static void
5307 _cb_subobj_del(void *data, __UNUSED__ Evas *e, Evas_Object *obj, __UNUSED__ void *event_info)
5308 {
5309    Edje *ed = data;
5310    _edje_subobj_unregister(ed, obj);
5311 }
5312
5313 void
5314 _edje_subobj_register(Edje *ed, Evas_Object *ob)
5315 {
5316    ed->subobjs = eina_list_append(ed->subobjs, ob);
5317    evas_object_event_callback_add(ob, EVAS_CALLBACK_DEL,
5318                                   _cb_subobj_del, ed);
5319 }
5320
5321 void
5322 _edje_subobj_unregister(Edje *ed, Evas_Object *obj)
5323 {
5324    ed->subobjs = eina_list_remove(ed->subobjs, obj);
5325    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
5326                                        _cb_subobj_del, ed);
5327 }
5328
5329 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/