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