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