From: Vincent Torri <vtorri@univ-evry.fr>
[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 int _edje_freeze_val = 0;
26 int _edje_freeze_calc_count = 0;
27 Eina_List *_edje_freeze_calc_list = NULL;
28
29 typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data;
30 struct _Edje_List_Foreach_Data
31 {
32    Eina_List *list;
33 };
34
35 static Eina_Bool _edje_color_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
36 static Eina_Bool _edje_text_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
37 static void _edje_object_image_preload_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
38 static void _edje_object_signal_preload_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
39
40 Edje_Real_Part *_edje_real_part_recursive_get_helper(const Edje *ed, char **path);
41
42 /************************** API Routines **************************/
43
44 #define FASTFREEZE 1
45
46 EAPI void
47 edje_freeze(void)
48 {
49 #ifdef FASTFREEZE
50    _edje_freeze_val++;
51    INF("fr ++ ->%i", _edje_freeze_val);
52 #else
53 // FIXME: could just have a global freeze instead of per object
54 // above i tried.. but this broke some things. notable e17's menus. why?
55    Eina_List *l;
56    Evas_Object *data;
57
58    EINA_LIST_FOREACH(_edje_edjes, l, data)
59      edje_object_freeze(data);
60 #endif
61 }
62
63 #ifdef FASTFREEZE
64 static void
65 _edje_thaw_edje(Edje *ed)
66 {
67    unsigned int i;
68
69    for (i = 0; i < ed->table_parts_size; i++)
70      {
71         Edje_Real_Part *rp;
72
73         rp = ed->table_parts[i];
74         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
75           {
76              Edje *ed2;
77
78              ed2 = _edje_fetch(rp->swallowed_object);
79              if (ed2) _edje_thaw_edje(ed2);
80           }
81      }
82    if ((ed->recalc) && (ed->freeze <= 0)) _edje_recalc_do(ed);
83 }
84 #endif
85
86 EAPI void
87 edje_thaw(void)
88 {
89 #ifdef FASTFREEZE
90    _edje_freeze_val--;
91    INF("fr -- ->%i", _edje_freeze_val);
92    if ((_edje_freeze_val <= 0) && (_edje_freeze_calc_count > 0))
93      {
94         Edje *ed;
95
96         _edje_freeze_calc_count = 0;
97         EINA_LIST_FREE(_edje_freeze_calc_list, ed)
98           {
99              _edje_thaw_edje(ed);
100              ed->freeze_calc = 0;
101           }
102      }
103 #else
104   Evas_Object *data;
105
106 // FIXME: could just have a global freeze instead of per object
107 // comment as above.. why?
108    Eina_List *l;
109
110    EINA_LIST_FOREACH(_edje_edjes, l, data)
111      edje_object_thaw(data);
112 #endif
113 }
114
115 EAPI void
116 edje_fontset_append_set(const char *fonts)
117 {
118    if (_edje_fontset_append)
119      free(_edje_fontset_append);
120    _edje_fontset_append = fonts ? strdup(fonts) : NULL;
121 }
122
123 EAPI const char *
124 edje_fontset_append_get(void)
125 {
126    return _edje_fontset_append;
127 }
128
129 EAPI void
130 edje_scale_set(double scale)
131 {
132    Eina_List *l;
133    Evas_Object *data;
134
135    if (_edje_scale == FROM_DOUBLE(scale)) return;
136    _edje_scale = FROM_DOUBLE(scale);
137    EINA_LIST_FOREACH(_edje_edjes, l, data)
138      edje_object_calc_force(data);
139 }
140
141 EAPI double
142 edje_scale_get(void)
143 {
144   return TO_DOUBLE(_edje_scale);
145 }
146
147 EAPI Eina_Bool
148 edje_object_scale_set(Evas_Object *obj, double scale)
149 {
150    Edje *ed;
151
152    ed = _edje_fetch(obj);
153    if (!ed) return EINA_FALSE;
154    if (ed->scale == scale) return EINA_TRUE;
155    ed->scale = FROM_DOUBLE(scale);
156    edje_object_calc_force(obj);
157    return EINA_TRUE;
158 }
159
160 EAPI double
161 edje_object_scale_get(const Evas_Object *obj)
162 {
163    Edje *ed;
164
165    ed = _edje_fetch(obj);
166    if (!ed) return 0.0;
167    return TO_DOUBLE(ed->scale);
168 }
169
170 EAPI Eina_Bool
171 edje_object_mirrored_get(const Evas_Object *obj)
172 {
173    Edje *ed;
174
175    ed = _edje_fetch(obj);
176    if (!ed) return EINA_FALSE;
177
178    return ed->is_rtl;
179 }
180
181 void
182 _edje_object_orientation_inform(Evas_Object *obj)
183 {
184    if (edje_object_mirrored_get(obj))
185      edje_object_signal_emit(obj, "edje,state,rtl", "edje");
186    else
187      edje_object_signal_emit(obj, "edje,state,ltr", "edje");
188 }
189
190 EAPI void
191 edje_object_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
192 {
193    Edje *ed;
194    unsigned int i;
195
196    ed = _edje_fetch(obj);
197    if (!ed) return;
198    if (ed->is_rtl == rtl) return;
199
200    ed->is_rtl = rtl;
201
202    for (i = 0 ; i < ed->table_parts_size ; i++)
203      {
204         Edje_Real_Part *ep;
205         const char *s;
206         double v;
207
208         ep = ed->table_parts[i];
209         s = ep->param1.description->state.name,
210         v = ep->param1.description->state.value;
211         _edje_part_description_apply(ed, ep, s, v , NULL, 0.0);
212         ep->chosen_description = ep->param1.description;
213      }
214    _edje_recalc_do(ed);
215
216    _edje_object_orientation_inform(obj);
217
218    return;
219 }
220
221 EAPI const char *
222 edje_object_data_get(const Evas_Object *obj, const char *key)
223 {
224    Edje *ed;
225
226    ed = _edje_fetch(obj);
227    if ((!ed) || (!key))
228      return NULL;
229    if (!ed->collection) return NULL;
230    if (!ed->collection->data) return NULL;
231    return edje_string_get(eina_hash_find(ed->collection->data, key));
232 }
233
234 EAPI int
235 edje_object_freeze(Evas_Object *obj)
236 {
237    Edje *ed;
238    unsigned int i;
239
240    ed = _edje_fetch(obj);
241    if (!ed) return 0;
242    for (i = 0; i < ed->table_parts_size; i++)
243      {
244         Edje_Real_Part *rp;
245         rp = ed->table_parts[i];
246         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
247           edje_object_freeze(rp->swallowed_object);
248      }
249    return _edje_freeze(ed);
250 }
251
252 EAPI int
253 edje_object_thaw(Evas_Object *obj)
254 {
255    Edje *ed;
256    unsigned int i;
257
258    ed = _edje_fetch(obj);
259    if (!ed) return 0;
260    for (i = 0; i < ed->table_parts_size; i++)
261      {
262         Edje_Real_Part *rp;
263
264         rp = ed->table_parts[i];
265         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
266           edje_object_thaw(rp->swallowed_object);
267      }
268    return _edje_thaw(ed);
269 }
270
271 EAPI Eina_Bool
272 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)
273 {
274    Eina_List *members;
275    Edje_Color_Class *cc;
276
277    if (!color_class) return EINA_FALSE;
278
279    cc = eina_hash_find(_edje_color_class_hash, color_class);
280    if (!cc)
281      {
282         cc = calloc(1, sizeof(Edje_Color_Class));
283         if (!cc) return EINA_FALSE;
284         cc->name = eina_stringshare_add(color_class);
285         if (!cc->name)
286           {
287              free(cc);
288              return EINA_FALSE;
289           }
290         if (!_edje_color_class_hash)
291           _edje_color_class_hash = eina_hash_string_superfast_new(NULL);
292         eina_hash_add(_edje_color_class_hash, color_class, cc);
293      }
294
295    if (r < 0)        r = 0;
296    else if (r > 255) r = 255;
297    if (g < 0)        g = 0;
298    else if (g > 255) g = 255;
299    if (b < 0)        b = 0;
300    else if (b > 255) b = 255;
301    if (a < 0)        a = 0;
302    else if (a > 255) a = 255;
303    if ((cc->r == r) && (cc->g == g) &&
304        (cc->b == b) && (cc->a == a) &&
305        (cc->r2 == r2) && (cc->g2 == g2) &&
306        (cc->b2 == b2) && (cc->a2 == a2) &&
307        (cc->r3 == r3) && (cc->g3 == g3) &&
308        (cc->b3 == b3) && (cc->a3 == a3))
309      return EINA_TRUE;
310    cc->r = r;
311    cc->g = g;
312    cc->b = b;
313    cc->a = a;
314    cc->r2 = r2;
315    cc->g2 = g2;
316    cc->b2 = b2;
317    cc->a2 = a2;
318    cc->r3 = r3;
319    cc->g3 = g3;
320    cc->b3 = b3;
321    cc->a3 = a3;
322
323    members = eina_hash_find(_edje_color_class_member_hash, color_class);
324    while (members)
325      {
326         Edje *ed;
327
328         ed = eina_list_data_get(members);
329         ed->dirty = 1;
330 #ifdef EDJE_CALC_CACHE
331         ed->all_part_change = 1;
332 #endif
333         _edje_recalc(ed);
334         _edje_emit(ed, "color_class,set", color_class);
335         members = eina_list_next(members);
336      }
337    return EINA_TRUE;
338 }
339
340 EAPI Eina_Bool
341 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)
342 {
343    Edje_Color_Class *cc;
344
345    if (!color_class)
346      cc = NULL;
347    else
348      cc = eina_hash_find(_edje_color_class_hash, color_class);
349
350    if (cc)
351      {
352 #define X(C) if (C) *C = cc->C
353 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
354         S(r, g, b, a);
355         S(r2, g2, b2, a2);
356         S(r3, g3, b3, a3);
357 #undef S
358 #undef X
359         return EINA_TRUE;
360      }
361    else
362      {
363 #define X(C) if (C) *C = 0
364 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
365         S(r, g, b, a);
366         S(r2, g2, b2, a2);
367         S(r3, g3, b3, a3);
368 #undef S
369 #undef X
370         return EINA_FALSE;
371      }
372 }
373
374 void
375 edje_color_class_del(const char *color_class)
376 {
377    Edje_Color_Class *cc;
378    Eina_List *members;
379
380    if (!color_class) return;
381
382    cc = eina_hash_find(_edje_color_class_hash, color_class);
383    if (!cc) return;
384
385    eina_hash_del(_edje_color_class_hash, color_class, cc);
386    eina_stringshare_del(cc->name);
387    free(cc);
388
389    members = eina_hash_find(_edje_color_class_member_hash, color_class);
390    while (members)
391      {
392         Edje *ed;
393
394         ed = eina_list_data_get(members);
395         ed->dirty = 1;
396 #ifdef EDJE_CALC_CACHE
397         ed->all_part_change = 1;
398 #endif
399         _edje_recalc(ed);
400         _edje_emit(ed, "color_class,del", color_class);
401         members = eina_list_next(members);
402      }
403 }
404
405 Eina_List *
406 edje_color_class_list(void)
407 {
408    Edje_List_Foreach_Data fdata;
409
410    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
411    eina_hash_foreach(_edje_color_class_member_hash,
412                      _edje_color_class_list_foreach, &fdata);
413
414    return fdata.list;
415 }
416
417 static Eina_Bool
418 _edje_color_class_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
419 {
420    Edje_List_Foreach_Data *fd;
421
422    fd = fdata;
423    fd->list = eina_list_append(fd->list, strdup(key));
424    return EINA_TRUE;
425 }
426
427 EAPI Eina_Bool
428 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)
429 {
430    Edje *ed;
431    Eina_List *l;
432    Edje_Color_Class *cc;
433    unsigned int i;
434
435    ed = _edje_fetch(obj);
436    if ((!ed) || (!color_class)) return EINA_FALSE;
437    if (r < 0)        r = 0;
438    else if (r > 255) r = 255;
439    if (g < 0)        g = 0;
440    else if (g > 255) g = 255;
441    if (b < 0)        b = 0;
442    else if (b > 255) b = 255;
443    if (a < 0)        a = 0;
444    else if (a > 255) a = 255;
445    color_class = eina_stringshare_add(color_class);
446    if (!color_class) return EINA_FALSE;
447    EINA_LIST_FOREACH(ed->color_classes, l, cc)
448      {
449         if (cc->name == color_class)
450           {
451              eina_stringshare_del(color_class);
452
453              if ((cc->r == r) && (cc->g == g) &&
454                  (cc->b == b) && (cc->a == a) &&
455                  (cc->r2 == r2) && (cc->g2 == g2) &&
456                  (cc->b2 == b2) && (cc->a2 == a2) &&
457                  (cc->r3 == r3) && (cc->g3 == g3) &&
458                  (cc->b3 == b3) && (cc->a3 == a3))
459                return EINA_TRUE;
460              cc->r = r;
461              cc->g = g;
462              cc->b = b;
463              cc->a = a;
464              cc->r2 = r2;
465              cc->g2 = g2;
466              cc->b2 = b2;
467              cc->a2 = a2;
468              cc->r3 = r3;
469              cc->g3 = g3;
470              cc->b3 = b3;
471              cc->a3 = a3;
472              ed->dirty = 1;
473 #ifdef EDJE_CALC_CACHE
474              ed->all_part_change = 1;
475 #endif
476              _edje_recalc(ed);
477              return EINA_TRUE;
478           }
479      }
480    cc = malloc(sizeof(Edje_Color_Class));
481    if (!cc)
482      {
483         eina_stringshare_del(color_class);
484         return EINA_FALSE;
485      }
486    cc->name = color_class;
487    cc->r = r;
488    cc->g = g;
489    cc->b = b;
490    cc->a = a;
491    cc->r2 = r2;
492    cc->g2 = g2;
493    cc->b2 = b2;
494    cc->a2 = a2;
495    cc->r3 = r3;
496    cc->g3 = g3;
497    cc->b3 = b3;
498    cc->a3 = a3;
499    ed->color_classes = eina_list_append(ed->color_classes, cc);
500    ed->dirty = 1;
501 #ifdef EDJE_CALC_CACHE
502    ed->all_part_change = 1;
503 #endif
504
505    for (i = 0; i < ed->table_parts_size; i++)
506      {
507         Edje_Real_Part *rp;
508
509         rp = ed->table_parts[i];
510         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
511           edje_object_color_class_set(rp->swallowed_object, color_class,
512                                       r, g, b, a, r2, g2, b2, a2, r3, g3, b3,
513                                       a3);
514      }
515
516    _edje_recalc(ed);
517    _edje_emit(ed, "color_class,set", color_class);
518    return EINA_TRUE;
519 }
520
521 EAPI Eina_Bool
522 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)
523 {
524    Edje *ed = _edje_fetch(obj);
525    Edje_Color_Class *cc = _edje_color_class_find(ed, color_class);
526
527    if (cc)
528      {
529 #define X(C) if (C) *C = cc->C
530 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
531         S(r, g, b, a);
532         S(r2, g2, b2, a2);
533         S(r3, g3, b3, a3);
534 #undef S
535 #undef X
536         return EINA_TRUE;
537      }
538    else
539      {
540 #define X(C) if (C) *C = 0
541 #define S(_r, _g, _b, _a) X(_r); X(_g); X(_b); X(_a)
542         S(r, g, b, a);
543         S(r2, g2, b2, a2);
544         S(r3, g3, b3, a3);
545 #undef S
546 #undef X
547         return EINA_FALSE;
548      }
549 }
550
551 void
552 edje_object_color_class_del(Evas_Object *obj, const char *color_class)
553 {
554    Edje *ed;
555    Eina_List *l;
556    Edje_Color_Class *cc = NULL;
557    unsigned int i;
558
559    if (!color_class) return;
560
561    ed = _edje_fetch(obj);
562    EINA_LIST_FOREACH(ed->color_classes, l, cc)
563      {
564         if (!strcmp(cc->name, color_class))
565           {
566              ed->color_classes = eina_list_remove(ed->color_classes, cc);
567              eina_stringshare_del(cc->name);
568              free(cc);
569              return;
570           }
571      }
572
573    for (i = 0; i < ed->table_parts_size; i++)
574      {
575         Edje_Real_Part *rp;
576
577         rp = ed->table_parts[i];
578         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
579           edje_object_color_class_del(rp->swallowed_object, color_class);
580      }
581
582    ed->dirty = 1;
583 #ifdef EDJE_CALC_CACHE
584    ed->all_part_change = 1;
585 #endif
586    _edje_recalc(ed);
587    _edje_emit(ed, "color_class,del", color_class);
588 }
589
590 EAPI Eina_Bool
591 edje_text_class_set(const char *text_class, const char *font, Evas_Font_Size size)
592 {
593    Eina_List *members;
594    Edje_Text_Class *tc;
595
596    if (!text_class) return EINA_FALSE;
597    if (!font) font = "";
598
599    tc = eina_hash_find(_edje_text_class_hash, text_class);
600    /* Create new text class */
601    if (!tc)
602      {
603         tc = calloc(1, sizeof(Edje_Text_Class));
604         if (!tc) return EINA_FALSE;
605         tc->name = eina_stringshare_add(text_class);
606         if (!tc->name)
607           {
608              free(tc);
609              return EINA_FALSE;
610           }
611         if (!_edje_text_class_hash) _edje_text_class_hash = eina_hash_string_superfast_new(NULL);
612         eina_hash_add(_edje_text_class_hash, text_class, tc);
613
614         tc->font = eina_stringshare_add(font);
615         tc->size = size;
616         return EINA_FALSE;
617      }
618
619    /* If the class found is the same just return */
620    if ((tc->size == size) && (tc->font) && (!strcmp(tc->font, font)))
621      return EINA_TRUE;
622
623    /* Update the class found */
624    eina_stringshare_del(tc->font);
625    tc->font = eina_stringshare_add(font);
626    if (!tc->font)
627      {
628         eina_hash_del(_edje_text_class_hash, text_class, tc);
629         free(tc);
630         return EINA_FALSE;
631      }
632    tc->size = size;
633
634    /* Tell all members of the text class to recalc */
635    members = eina_hash_find(_edje_text_class_member_hash, text_class);
636    while (members)
637      {
638         Edje *ed;
639
640         ed = eina_list_data_get(members);
641         ed->dirty = 1;
642         _edje_textblock_style_all_update(ed);
643 #ifdef EDJE_CALC_CACHE
644         ed->text_part_change = 1;
645 #endif
646         _edje_recalc(ed);
647         members = eina_list_next(members);
648      }
649    return EINA_TRUE;
650 }
651
652 void
653 edje_text_class_del(const char *text_class)
654 {
655    Edje_Text_Class *tc;
656    Eina_List *members;
657
658    if (!text_class) return;
659
660    tc = eina_hash_find(_edje_text_class_hash, text_class);
661    if (!tc) return;
662
663    eina_hash_del(_edje_text_class_hash, text_class, tc);
664    eina_stringshare_del(tc->name);
665    eina_stringshare_del(tc->font);
666    free(tc);
667
668    members = eina_hash_find(_edje_text_class_member_hash, text_class);
669    while (members)
670      {
671         Edje *ed;
672
673         ed = eina_list_data_get(members);
674         ed->dirty = 1;
675         _edje_textblock_style_all_update(ed);
676 #ifdef EDJE_CALC_CACHE
677         ed->text_part_change = 1;
678 #endif
679         _edje_recalc(ed);
680         members = eina_list_next(members);
681      }
682 }
683
684 Eina_List *
685 edje_text_class_list(void)
686 {
687    Edje_List_Foreach_Data fdata;
688
689    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
690    eina_hash_foreach(_edje_text_class_member_hash,
691                      _edje_text_class_list_foreach, &fdata);
692    return fdata.list;
693 }
694
695 static Eina_Bool
696 _edje_text_class_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
697 {
698    Edje_List_Foreach_Data *fd;
699
700    fd = fdata;
701    fd->list = eina_list_append(fd->list, eina_stringshare_add(key));
702    return EINA_TRUE;
703 }
704
705 EAPI Eina_Bool
706 edje_object_text_class_set(Evas_Object *obj, const char *text_class, const char *font, Evas_Font_Size size)
707 {
708    Edje *ed;
709    Eina_List *l;
710    Edje_Text_Class *tc;
711    unsigned int i;
712
713    ed = _edje_fetch(obj);
714    if ((!ed) || (!text_class)) return EINA_FALSE;
715
716    /* for each text_class in the edje */
717    EINA_LIST_FOREACH(ed->text_classes, l, tc)
718      {
719         if ((tc->name) && (!strcmp(tc->name, text_class)))
720           {
721              /* Match and the same, return */
722              if ((tc->font) && (font) && (!strcmp(tc->font, font)) &&
723                  (tc->size == size))
724                return EINA_TRUE;
725
726              /* No font but size is the same, return */
727              if ((!tc->font) && (!font) && (tc->size == size)) return EINA_TRUE;
728
729              /* Update new text class properties */
730              if (tc->font) eina_stringshare_del(tc->font);
731              if (font) tc->font = eina_stringshare_add(font);
732              else tc->font = NULL;
733              tc->size = size;
734
735              /* Update edje */
736              ed->dirty = 1;
737 #ifdef EDJE_CALC_CACHE
738              ed->text_part_change = 1;
739 #endif
740              _edje_recalc(ed);
741              return EINA_TRUE;
742           }
743      }
744
745    /* No matches, create a new text class */
746    tc = calloc(1, sizeof(Edje_Text_Class));
747    if (!tc) return EINA_FALSE;
748    tc->name = eina_stringshare_add(text_class);
749    if (!tc->name)
750      {
751         free(tc);
752         return EINA_FALSE;
753      }
754    if (font) tc->font = eina_stringshare_add(font);
755    else tc->font = NULL;
756    tc->size = size;
757
758    for (i = 0; i < ed->table_parts_size; i++)
759      {
760         Edje_Real_Part *rp;
761
762         rp = ed->table_parts[i];
763         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
764           edje_object_text_class_set(rp->swallowed_object, text_class,
765                                      font, size);
766      }
767
768    /* Add to edje's text class list */
769    ed->text_classes = eina_list_append(ed->text_classes, tc);
770    ed->dirty = 1;
771 #ifdef EDJE_CALC_CACHE
772    ed->text_part_change = 1;
773 #endif
774    _edje_textblock_style_all_update(ed);
775    _edje_recalc(ed);
776    return EINA_TRUE;
777 }
778
779 EAPI Eina_Bool
780 edje_object_part_exists(const Evas_Object *obj, const char *part)
781 {
782    Edje *ed;
783    Edje_Real_Part *rp;
784
785    ed = _edje_fetch(obj);
786    if ((!ed) || (!part)) return EINA_FALSE;
787    rp = _edje_real_part_recursive_get(ed, (char *)part);
788    if (!rp) return EINA_FALSE;
789    return EINA_TRUE;
790 }
791
792 EAPI const Evas_Object *
793 edje_object_part_object_get(const Evas_Object *obj, const char *part)
794 {
795    Edje *ed;
796    Edje_Real_Part *rp;
797
798    ed = _edje_fetch(obj);
799    if ((!ed) || (!part)) return NULL;
800
801    /* Need to recalc before providing the object. */
802    _edje_recalc_do(ed);
803
804    rp = _edje_real_part_recursive_get(ed, (char *)part);
805    if (!rp) return NULL;
806    return rp->object;
807 }
808
809 EAPI Eina_Bool
810 edje_object_part_geometry_get(const Evas_Object *obj, const char *part, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h )
811 {
812    Edje *ed;
813    Edje_Real_Part *rp;
814
815    ed = _edje_fetch(obj);
816    if ((!ed) || (!part))
817      {
818         if (x) *x = 0;
819         if (y) *y = 0;
820         if (w) *w = 0;
821         if (h) *h = 0;
822         return EINA_FALSE;
823      }
824
825    /* Need to recalc before providing the object. */
826    _edje_recalc_do(ed);
827
828    rp = _edje_real_part_recursive_get(ed, (char *)part);
829    if (!rp)
830      {
831         if (x) *x = 0;
832         if (y) *y = 0;
833         if (w) *w = 0;
834         if (h) *h = 0;
835         return EINA_FALSE;
836      }
837    if (x) *x = rp->x;
838    if (y) *y = rp->y;
839    if (w) *w = rp->w;
840    if (h) *h = rp->h;
841    return EINA_TRUE;
842 }
843
844 EAPI void
845 edje_object_item_provider_set(Evas_Object *obj, Edje_Item_Provider_Cb func, void *data)
846 {
847    Edje *ed;
848
849    ed = _edje_fetch(obj);
850    if (!ed) return;
851    ed->item_provider.func = func;
852    ed->item_provider.data = data;
853 }
854
855 /* FIXDOC: New Function */
856 EAPI void
857 edje_object_text_change_cb_set(Evas_Object *obj, Edje_Text_Change_Cb func, void *data)
858 {
859    Edje *ed;
860    unsigned int i;
861
862    ed = _edje_fetch(obj);
863    if (!ed) return;
864    ed->text_change.func = func;
865    ed->text_change.data = data;
866
867    for (i = 0; i < ed->table_parts_size; i++)
868      {
869         Edje_Real_Part *rp;
870
871         rp = ed->table_parts[i];
872         if ((rp->part->type == EDJE_PART_TYPE_GROUP) && (rp->swallowed_object))
873            edje_object_text_change_cb_set(rp->swallowed_object, func, data);
874      }
875 }
876
877 Eina_Bool
878 _edje_object_part_text_raw_set(Evas_Object *obj, Edje_Real_Part *rp, const char *part, const char *text)
879 {
880    if ((!rp->text.text) && (!text))
881      return EINA_FALSE;
882    if ((rp->text.text) && (text) &&
883        (!strcmp(rp->text.text, text)))
884      return EINA_FALSE;
885    if (rp->text.text)
886      {
887         eina_stringshare_del(rp->text.text);
888         rp->text.text = NULL;
889      }
890    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
891      _edje_entry_text_markup_set(rp, text);
892    else
893      if (text) rp->text.text = eina_stringshare_add(text);
894    rp->edje->dirty = 1;
895 #ifdef EDJE_CALC_CACHE
896    rp->invalidate = 1;
897 #endif
898    _edje_recalc(rp->edje);
899    if (rp->edje->text_change.func)
900      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
901    return EINA_TRUE;
902 }
903
904 Eina_Bool
905 _edje_object_part_text_raw_append(Evas_Object *obj, Edje_Real_Part *rp, const char *part, const char *text)
906 {
907    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
908      _edje_entry_text_markup_append(rp, text);
909    else if (text)
910      {
911         if (rp->text.text)
912           {
913              char *new = NULL;
914              int len_added = strlen(text);
915              int len_old = strlen(rp->text.text);
916              new = malloc(len_old + len_added + 1);
917              memcpy(new, rp->text.text, len_old);
918              memcpy(new + len_old, text, len_added);
919              new[len_old + len_added] = '\0';
920              eina_stringshare_replace(&rp->text.text, new);
921              free(new);
922           }
923         else
924           {
925              eina_stringshare_replace(&rp->text.text, text);
926           }
927      }
928    rp->edje->dirty = 1;
929 #ifdef EDJE_CALC_CACHE
930    rp->invalidate = 1;
931 #endif
932    _edje_recalc(rp->edje);
933    if (rp->edje->text_change.func)
934      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
935    return EINA_TRUE;
936 }
937
938 /** Sets the text for an object part
939  * @param obj A valid Evas Object handle
940  * @param part The part name
941  * @param text The text string
942  */
943 EAPI Eina_Bool
944 edje_object_part_text_set(Evas_Object *obj, const char *part, const char *text)
945 {
946    Edje *ed;
947    Edje_Real_Part *rp;
948
949    ed = _edje_fetch(obj);
950    if ((!ed) || (!part)) return EINA_FALSE;
951    rp = _edje_real_part_recursive_get(ed, (char *)part);
952    if (!rp) return EINA_FALSE;
953    if ((rp->part->type != EDJE_PART_TYPE_TEXT) &&
954        (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return EINA_FALSE;
955    return _edje_object_part_text_raw_set(obj, rp, part, text);
956 }
957
958 EAPI const char *
959 edje_object_part_text_get(const Evas_Object *obj, const char *part)
960 {
961    Edje *ed;
962    Edje_Real_Part *rp;
963
964    ed = _edje_fetch(obj);
965    if ((!ed) || (!part)) return NULL;
966
967    /* Need to recalc before providing the object. */
968    _edje_recalc_do(ed);
969
970    rp = _edje_real_part_recursive_get(ed, (char *)part);
971    if (!rp) return NULL;
972    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
973      return _edje_entry_text_get(rp);
974    else
975      {
976         if (rp->part->type == EDJE_PART_TYPE_TEXT) return rp->text.text;
977         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
978           return evas_object_textblock_text_markup_get(rp->object);
979      }
980    return NULL;
981 }
982
983 char *
984 _edje_text_escape(const char *text)
985 {
986    Eina_Strbuf *txt;
987    char *ret;
988    const char *text_end;
989    size_t text_len;
990
991    if (!text) return NULL;
992
993    txt = eina_strbuf_new();
994    text_len = strlen(text);
995
996    text_end = text + text_len;
997    while (text < text_end)
998      {
999         int advance;
1000         const char *escaped = evas_textblock_string_escape_get(text, &advance);
1001         if (!escaped)
1002           {
1003              eina_strbuf_append_char(txt, text[0]);
1004              advance = 1;
1005           }
1006         else
1007           eina_strbuf_append(txt, escaped);
1008
1009         text += advance;
1010      }
1011
1012    ret = eina_strbuf_string_steal(txt);
1013    eina_strbuf_free(txt);
1014    return ret;
1015 }
1016
1017 char *
1018 _edje_text_unescape(const char *text)
1019 {
1020    Eina_Strbuf *txt;
1021    char *ret;
1022    const char *text_end, *last, *escape_start;
1023    size_t text_len;
1024
1025    if (!text) return NULL;
1026
1027    txt = eina_strbuf_new();
1028    text_len = strlen(text);
1029
1030    text_end = text + text_len;
1031    last = text;
1032    escape_start = NULL;
1033    for (; text < text_end; text++)
1034      {
1035         if (*text == '&')
1036           {
1037              size_t len;
1038              const char *str;
1039
1040              if (last)
1041                {
1042                   len = text - last;
1043                   str = last;
1044                }
1045              else
1046                {
1047                   len = text - escape_start;
1048                   str = escape_start;
1049                }
1050
1051              if (len > 0)
1052                eina_strbuf_append_n(txt, str, len);
1053
1054              escape_start = text;
1055              last = NULL;
1056           }
1057         else if ((*text == ';') && (escape_start))
1058           {
1059              size_t len;
1060              const char *str = evas_textblock_escape_string_range_get(escape_start, text);
1061
1062              if (str)
1063                len = strlen(str);
1064              else
1065                {
1066                   str = escape_start;
1067                   len = text + 1 - escape_start;
1068                }
1069
1070              eina_strbuf_append_n(txt, str, len);
1071
1072              escape_start = NULL;
1073              last = text + 1;
1074           }
1075      }
1076
1077    if (!last && escape_start)
1078      last = escape_start;
1079
1080    if (last && (text > last))
1081      {
1082         size_t len = text - last;
1083         eina_strbuf_append_n(txt, last, len);
1084      }
1085
1086    ret = eina_strbuf_string_steal(txt);
1087    eina_strbuf_free(txt);
1088    return ret;
1089 }
1090
1091 EAPI Eina_Bool
1092 edje_object_part_text_unescaped_set(Evas_Object *obj, const char *part, const char *text_to_escape)
1093 {
1094    Edje *ed;
1095    Edje_Real_Part *rp;
1096    Eina_Bool ret = EINA_FALSE;
1097
1098    ed = _edje_fetch(obj);
1099    if ((!ed) || (!part)) return ret;
1100    rp = _edje_real_part_recursive_get(ed, part);
1101    if (!rp) return ret;
1102    if (rp->part->type == EDJE_PART_TYPE_TEXT)
1103      ret = _edje_object_part_text_raw_set(obj, rp, part, text_to_escape);
1104    else if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1105      {
1106         char *text = _edje_text_escape(text_to_escape);
1107
1108         ret = _edje_object_part_text_raw_set(obj, rp, part, text);
1109         free(text);
1110      }
1111    return ret;
1112 }
1113
1114 EAPI char *
1115 edje_object_part_text_unescaped_get(const Evas_Object *obj, const char *part)
1116 {
1117    Edje *ed;
1118    Edje_Real_Part *rp;
1119
1120    ed = _edje_fetch(obj);
1121    if ((!ed) || (!part)) return NULL;
1122
1123    /* Need to recalc before providing the object. */
1124    _edje_recalc_do(ed);
1125
1126    rp = _edje_real_part_recursive_get(ed, (char *)part);
1127    if (!rp) return NULL;
1128    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1129      {
1130         const char *t = _edje_entry_text_get(rp);
1131         return _edje_text_unescape(t);
1132      }
1133    else
1134      {
1135         if (rp->part->type == EDJE_PART_TYPE_TEXT) return strdup(rp->text.text);
1136         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1137           {
1138              const char *t = evas_object_textblock_text_markup_get(rp->object);
1139              return _edje_text_unescape(t);
1140           }
1141      }
1142    return NULL;
1143 }
1144
1145 EAPI const char *
1146 edje_object_part_text_selection_get(const Evas_Object *obj, const char *part)
1147 {
1148    Edje *ed;
1149    Edje_Real_Part *rp;
1150
1151    ed = _edje_fetch(obj);
1152    if ((!ed) || (!part)) return NULL;
1153    rp = _edje_real_part_recursive_get(ed, (char *)part);
1154    if (!rp) return NULL;
1155    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1156      return _edje_entry_selection_get(rp);
1157    return NULL;
1158 }
1159
1160 EAPI void
1161 edje_object_part_text_select_none(const Evas_Object *obj, const char *part)
1162 {
1163    Edje *ed;
1164    Edje_Real_Part *rp;
1165
1166    ed = _edje_fetch(obj);
1167    if ((!ed) || (!part)) return;
1168    rp = _edje_real_part_recursive_get(ed, (char *)part);
1169    if (!rp) return;
1170    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1171      _edje_entry_select_none(rp);
1172 }
1173
1174 EAPI void
1175 edje_object_part_text_select_all(const Evas_Object *obj, const char *part)
1176 {
1177    Edje *ed;
1178    Edje_Real_Part *rp;
1179
1180    ed = _edje_fetch(obj);
1181    if ((!ed) || (!part)) return;
1182    rp = _edje_real_part_recursive_get(ed, (char *)part);
1183    if (!rp) return;
1184    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1185      _edje_entry_select_all(rp);
1186 }
1187
1188 EAPI void
1189 edje_object_part_text_insert(Evas_Object *obj, const char *part, const char *text)
1190 {
1191    Edje *ed;
1192    Edje_Real_Part *rp;
1193
1194    ed = _edje_fetch(obj);
1195    if ((!ed) || (!part)) return;
1196    rp = _edje_real_part_recursive_get(ed, (char *)part);
1197    if (!rp) return;
1198    if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return;
1199    if (rp->part->entry_mode <= EDJE_ENTRY_EDIT_MODE_NONE) return;
1200    _edje_entry_text_markup_insert(rp, text);
1201    rp->edje->dirty = 1;
1202 #ifdef EDJE_CALC_CACHE
1203    rp->invalidate = 1;
1204 #endif
1205    _edje_recalc(rp->edje);
1206    if (rp->edje->text_change.func)
1207      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
1208 }
1209
1210 EAPI void
1211 edje_object_part_text_append(Evas_Object *obj, const char *part, const char *text)
1212 {
1213    Edje *ed;
1214    Edje_Real_Part *rp;
1215
1216    ed = _edje_fetch(obj);
1217    if ((!ed) || (!part)) return;
1218    rp = _edje_real_part_recursive_get(ed, (char *)part);
1219    if (!rp) return;
1220    if ((rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return;
1221    _edje_object_part_text_raw_append(obj, rp, part, text);
1222    rp->edje->dirty = 1;
1223 #ifdef EDJE_CALC_CACHE
1224    rp->invalidate = 1;
1225 #endif
1226    _edje_recalc(rp->edje);
1227    if (rp->edje->text_change.func)
1228      rp->edje->text_change.func(rp->edje->text_change.data, obj, part);
1229 }
1230
1231 EAPI const Eina_List *
1232 edje_object_part_text_anchor_list_get(const Evas_Object *obj, const char *part)
1233 {
1234    Edje *ed;
1235    Edje_Real_Part *rp;
1236
1237    ed = _edje_fetch(obj);
1238    if ((!ed) || (!part)) return NULL;
1239    rp = _edje_real_part_recursive_get(ed, (char *)part);
1240    if (!rp) return NULL;
1241    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1242      return _edje_entry_anchors_list(rp);
1243    return NULL;
1244 }
1245
1246 EAPI const Eina_List *
1247 edje_object_part_text_anchor_geometry_get(const Evas_Object *obj, const char *part, const char *anchor)
1248 {
1249    Edje *ed;
1250    Edje_Real_Part *rp;
1251
1252    ed = _edje_fetch(obj);
1253    if ((!ed) || (!part)) return NULL;
1254    rp = _edje_real_part_recursive_get(ed, (char *)part);
1255    if (!rp) return NULL;
1256    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1257      return _edje_entry_anchor_geometry_get(rp, anchor);
1258    return NULL;
1259 }
1260
1261 EAPI const Eina_List *
1262 edje_object_part_text_item_list_get(const Evas_Object *obj, const char *part)
1263 {
1264    Edje *ed;
1265    Edje_Real_Part *rp;
1266
1267    ed = _edje_fetch(obj);
1268    if ((!ed) || (!part)) return NULL;
1269    rp = _edje_real_part_recursive_get(ed, (char *)part);
1270    if (!rp) return NULL;
1271    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1272      return _edje_entry_items_list(rp);
1273    return NULL;
1274 }
1275
1276 EAPI Eina_Bool
1277 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)
1278 {
1279    Edje *ed;
1280    Edje_Real_Part *rp;
1281
1282    ed = _edje_fetch(obj);
1283    if ((!ed) || (!part)) return EINA_FALSE;
1284    rp = _edje_real_part_recursive_get(ed, (char *)part);
1285    if (!rp) return EINA_FALSE;
1286    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1287      return _edje_entry_item_geometry_get(rp, item, cx, cy, cw, ch);
1288    return EINA_FALSE;
1289 }
1290
1291 EAPI void
1292 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)
1293 {
1294    Edje *ed;
1295    Edje_Real_Part *rp;
1296
1297    ed = _edje_fetch(obj);
1298    if (x) *x = 0;
1299    if (y) *y = 0;
1300    if (w) *w = 0;
1301    if (h) *h = 0;
1302    if ((!ed) || (!part)) return;
1303    rp = _edje_real_part_recursive_get(ed, (char *)part);
1304    if (!rp) return;
1305    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1306      {
1307         _edje_entry_cursor_geometry_get(rp, x, y, w, h);
1308         if (x) *x -= rp->edje->x;
1309         if (y) *y -= rp->edje->y;
1310      }
1311    return;
1312 }
1313
1314 EAPI void
1315 edje_object_part_text_select_allow_set(const Evas_Object *obj, const char *part, Eina_Bool allow)
1316 {
1317    Edje *ed;
1318    Edje_Real_Part *rp;
1319
1320    ed = _edje_fetch(obj);
1321    if ((!ed) || (!part)) return;
1322    rp = _edje_real_part_recursive_get(ed, (char *)part);
1323    if (!rp) return;
1324    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1325      _edje_entry_select_allow_set(rp, allow);
1326 }
1327
1328 EAPI void
1329 edje_object_part_text_select_abort(const Evas_Object *obj, const char *part)
1330 {
1331    Edje *ed;
1332    Edje_Real_Part *rp;
1333
1334    ed = _edje_fetch(obj);
1335    if ((!ed) || (!part)) return;
1336    rp = _edje_real_part_recursive_get(ed, (char *)part);
1337    if (!rp) return;
1338    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1339      _edje_entry_select_abort(rp);
1340 }
1341
1342 EAPI void
1343 edje_object_part_text_select_begin(const Evas_Object *obj, const char *part)
1344 {
1345    Edje *ed;
1346    Edje_Real_Part *rp;
1347
1348    ed = _edje_fetch(obj);
1349    if ((!ed) || (!part)) return;
1350    rp = _edje_real_part_recursive_get(ed, (char *)part);
1351    if (!rp) return;
1352    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1353      _edje_entry_select_begin(rp);
1354 }
1355
1356 EAPI void
1357 edje_object_part_text_select_extend(const Evas_Object *obj, const char *part)
1358 {
1359    Edje *ed;
1360    Edje_Real_Part *rp;
1361
1362    ed = _edje_fetch(obj);
1363    if ((!ed) || (!part)) return;
1364    rp = _edje_real_part_recursive_get(ed, (char *)part);
1365    if (!rp) return;
1366    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1367      _edje_entry_select_extend(rp);
1368 }
1369
1370 EAPI Eina_Bool
1371 edje_object_part_text_cursor_next(Evas_Object *obj, const char *part, Edje_Cursor cur)
1372 {
1373    Edje *ed;
1374    Edje_Real_Part *rp;
1375
1376    ed = _edje_fetch(obj);
1377    if ((!ed) || (!part)) return EINA_FALSE;
1378    rp = _edje_real_part_recursive_get(ed, (char *)part);
1379    if (!rp) return EINA_FALSE;
1380    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1381      {
1382         return _edje_entry_cursor_next(rp, cur);
1383      }
1384    return EINA_FALSE;
1385 }
1386
1387 EAPI Eina_Bool
1388 edje_object_part_text_cursor_prev(Evas_Object *obj, const char *part, Edje_Cursor cur)
1389 {
1390    Edje *ed;
1391    Edje_Real_Part *rp;
1392
1393    ed = _edje_fetch(obj);
1394    if ((!ed) || (!part)) return EINA_FALSE;
1395    rp = _edje_real_part_recursive_get(ed, (char *)part);
1396    if (!rp) return EINA_FALSE;
1397    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1398      {
1399         return _edje_entry_cursor_prev(rp, cur);
1400      }
1401    return EINA_FALSE;
1402 }
1403
1404 EAPI Eina_Bool
1405 edje_object_part_text_cursor_up(Evas_Object *obj, const char *part, Edje_Cursor cur)
1406 {
1407    Edje *ed;
1408    Edje_Real_Part *rp;
1409
1410    ed = _edje_fetch(obj);
1411    if ((!ed) || (!part)) return EINA_FALSE;
1412    rp = _edje_real_part_recursive_get(ed, (char *)part);
1413    if (!rp) return EINA_FALSE;
1414    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1415      {
1416         return _edje_entry_cursor_up(rp, cur);
1417      }
1418    return EINA_FALSE;
1419 }
1420
1421 EAPI Eina_Bool
1422 edje_object_part_text_cursor_down(Evas_Object *obj, const char *part, Edje_Cursor cur)
1423 {
1424    Edje *ed;
1425    Edje_Real_Part *rp;
1426
1427    ed = _edje_fetch(obj);
1428    if ((!ed) || (!part)) return EINA_FALSE;
1429    rp = _edje_real_part_recursive_get(ed, (char *)part);
1430    if (!rp) return EINA_FALSE;
1431    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1432      {
1433         return _edje_entry_cursor_down(rp, cur);
1434      }
1435    return EINA_FALSE;
1436 }
1437
1438 EAPI void
1439 edje_object_part_text_cursor_begin_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1440 {
1441    Edje *ed;
1442    Edje_Real_Part *rp;
1443
1444    ed = _edje_fetch(obj);
1445    if ((!ed) || (!part)) return;
1446    rp = _edje_real_part_recursive_get(ed, (char *)part);
1447    if (!rp) return;
1448    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1449      {
1450         _edje_entry_cursor_begin(rp, cur);
1451      }
1452 }
1453
1454 EAPI void
1455 edje_object_part_text_cursor_end_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1456 {
1457    Edje *ed;
1458    Edje_Real_Part *rp;
1459
1460    ed = _edje_fetch(obj);
1461    if ((!ed) || (!part)) return;
1462    rp = _edje_real_part_recursive_get(ed, (char *)part);
1463    if (!rp) return;
1464    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1465      {
1466         _edje_entry_cursor_end(rp, cur);
1467      }
1468 }
1469
1470 EAPI void
1471 edje_object_part_text_cursor_copy(Evas_Object *obj, const char *part, Edje_Cursor src, Edje_Cursor dst)
1472 {
1473    Edje *ed;
1474    Edje_Real_Part *rp;
1475
1476    ed = _edje_fetch(obj);
1477    if ((!ed) || (!part)) return;
1478    rp = _edje_real_part_recursive_get(ed, (char *)part);
1479    if (!rp) return;
1480    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1481      {
1482         _edje_entry_cursor_copy(rp, src, dst);
1483      }
1484 }
1485
1486 EAPI void
1487 edje_object_part_text_cursor_line_begin_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1488 {
1489    Edje *ed;
1490    Edje_Real_Part *rp;
1491
1492    ed = _edje_fetch(obj);
1493    if ((!ed) || (!part)) return;
1494    rp = _edje_real_part_recursive_get(ed, (char *)part);
1495    if (!rp) return;
1496    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1497      {
1498         _edje_entry_cursor_line_begin(rp, cur);
1499      }
1500 }
1501
1502 EAPI void
1503 edje_object_part_text_cursor_line_end_set(Evas_Object *obj, const char *part, Edje_Cursor cur)
1504 {
1505    Edje *ed;
1506    Edje_Real_Part *rp;
1507
1508    ed = _edje_fetch(obj);
1509    if ((!ed) || (!part)) return;
1510    rp = _edje_real_part_recursive_get(ed, (char *)part);
1511    if (!rp) return;
1512    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1513      {
1514         _edje_entry_cursor_line_end(rp, cur);
1515      }
1516 }
1517
1518 EAPI Eina_Bool
1519 edje_object_part_text_cursor_coord_set(Evas_Object *obj, const char *part,
1520                 Edje_Cursor cur, Evas_Coord x, Evas_Coord y)
1521 {
1522  Edje *ed;
1523    Edje_Real_Part *rp;
1524
1525    ed = _edje_fetch(obj);
1526    if ((!ed) || (!part)) return EINA_FALSE;
1527    rp = _edje_real_part_recursive_get(ed, (char *)part);
1528    if (!rp) return EINA_FALSE;
1529    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1530      {
1531         return _edje_entry_cursor_coord_set(rp, cur, x, y);
1532      }
1533    return EINA_FALSE;
1534 }
1535
1536 EAPI Eina_Bool
1537 edje_object_part_text_cursor_is_format_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1538 {
1539    Edje *ed;
1540    Edje_Real_Part *rp;
1541
1542    ed = _edje_fetch(obj);
1543    if ((!ed) || (!part)) return EINA_FALSE;
1544    rp = _edje_real_part_recursive_get(ed, (char *)part);
1545    if (!rp) return EINA_FALSE;
1546    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1547      {
1548         return _edje_entry_cursor_is_format_get(rp, cur);
1549      }
1550    return EINA_FALSE;
1551 }
1552
1553 EAPI Eina_Bool
1554 edje_object_part_text_cursor_is_visible_format_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1555 {
1556    Edje *ed;
1557    Edje_Real_Part *rp;
1558
1559    ed = _edje_fetch(obj);
1560    if ((!ed) || (!part)) return 0;
1561    rp = _edje_real_part_recursive_get(ed, (char *)part);
1562    if (!rp) return 0;
1563    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1564      {
1565         return _edje_entry_cursor_is_visible_format_get(rp, cur);
1566      }
1567    return 0;
1568 }
1569
1570 EAPI const char *
1571 edje_object_part_text_cursor_content_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1572 {
1573    Edje *ed;
1574    Edje_Real_Part *rp;
1575
1576    ed = _edje_fetch(obj);
1577    if ((!ed) || (!part)) return NULL;
1578    rp = _edje_real_part_recursive_get(ed, part);
1579    if (!rp) return NULL;
1580    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1581      {
1582         return _edje_entry_cursor_content_get(rp, cur);
1583      }
1584    return NULL;
1585 }
1586
1587 EAPI void
1588 edje_object_part_text_cursor_pos_set(Evas_Object *obj, const char *part, Edje_Cursor cur, int pos)
1589 {
1590    Edje *ed;
1591    Edje_Real_Part *rp;
1592
1593    ed = _edje_fetch(obj);
1594    if ((!ed) || (!part)) return;
1595    rp = _edje_real_part_recursive_get(ed, part);
1596    if (!rp) return;
1597    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1598      {
1599         _edje_entry_cursor_pos_set(rp, cur, pos);
1600      }
1601 }
1602
1603 EAPI int
1604 edje_object_part_text_cursor_pos_get(const Evas_Object *obj, const char *part, Edje_Cursor cur)
1605 {
1606    Edje *ed;
1607    Edje_Real_Part *rp;
1608
1609    ed = _edje_fetch(obj);
1610    if ((!ed) || (!part)) return 0;
1611    rp = _edje_real_part_recursive_get(ed, part);
1612    if (!rp) return 0;
1613    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1614      {
1615         return _edje_entry_cursor_pos_get(rp, cur);
1616      }
1617    return 0;
1618 }
1619
1620 EAPI void
1621 edje_object_text_insert_filter_callback_add(Evas_Object *obj, const char *part, Edje_Text_Filter_Cb func, void *data)
1622 {
1623    Edje *ed;
1624    Edje_Text_Insert_Filter_Callback *cb;
1625
1626    ed = _edje_fetch(obj);
1627    if ((!ed) || (!part)) return;
1628    cb = calloc(1, sizeof(Edje_Text_Insert_Filter_Callback));
1629    cb->part = eina_stringshare_add(part);
1630    cb->func = func;
1631    cb->data = (void *)data;
1632    ed->text_insert_filter_callbacks =
1633      eina_list_append(ed->text_insert_filter_callbacks, cb);
1634 }
1635
1636 EAPI void *
1637 edje_object_text_insert_filter_callback_del(Evas_Object *obj, const char *part, Edje_Text_Filter_Cb func)
1638 {
1639    Edje *ed;
1640    Edje_Text_Insert_Filter_Callback *cb;
1641    Eina_List *l;
1642
1643    ed = _edje_fetch(obj);
1644    if ((!ed) || (!part)) return NULL;
1645    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
1646      {
1647         if ((!strcmp(cb->part, part)) && (cb->func == func))
1648           {
1649              void *data = cb->data;
1650              ed->text_insert_filter_callbacks =
1651                 eina_list_remove_list(ed->text_insert_filter_callbacks, l);
1652              eina_stringshare_del(cb->part);
1653              free(cb);
1654              return data;
1655           }
1656      }
1657    return NULL;
1658 }
1659
1660 EAPI void *
1661 edje_object_text_insert_filter_callback_del_full(Evas_Object *obj, const char *part, Edje_Text_Filter_Cb func, void *data)
1662 {
1663    Edje *ed;
1664    Edje_Text_Insert_Filter_Callback *cb;
1665    Eina_List *l;
1666
1667    ed = _edje_fetch(obj);
1668    if ((!ed) || (!part)) return NULL;
1669    EINA_LIST_FOREACH(ed->text_insert_filter_callbacks, l, cb)
1670      {
1671         if ((!strcmp(cb->part, part)) && (cb->func == func) &&
1672             (cb->data == data))
1673           {
1674              void *data = cb->data;
1675              ed->text_insert_filter_callbacks =
1676                 eina_list_remove_list(ed->text_insert_filter_callbacks, l);
1677              eina_stringshare_del(cb->part);
1678              free(cb);
1679              return data;
1680           }
1681      }
1682    return NULL;
1683 }
1684
1685 EAPI Eina_Bool
1686 edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_swallow)
1687 {
1688    Edje *ed;
1689    Edje_Real_Part *rp;
1690
1691    ed = _edje_fetch(obj);
1692    if ((!ed) || (!part)) return EINA_FALSE;
1693
1694    /* Need to recalc before providing the object. */
1695    // XXX: I guess this is not required, removing for testing purposes
1696    // XXX: uncomment if you see glitches in e17 or others.
1697    // XXX: by Gustavo, January 21th 2009.
1698    // XXX: I got a backtrace with over 30000 calls without this,
1699    // XXX: only with 32px shelves. The problem is probably somewhere else,
1700    // XXX: but until it's found, leave this here.
1701    // XXX: by Sachiel, January 21th 2009, 19:30 UTC
1702    _edje_recalc_do(ed);
1703
1704    rp = _edje_real_part_recursive_get(ed, (char *)part);
1705    if (!rp) return EINA_FALSE;
1706    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
1707      {
1708         ERR("cannot unswallow part %s: not swallow type!", rp->part->name);
1709         return EINA_FALSE;
1710      }
1711    _edje_real_part_swallow(rp, obj_swallow, EINA_TRUE);
1712    return EINA_TRUE;
1713 }
1714
1715 static void
1716 _recalc_extern_parent(Evas_Object *obj)
1717 {
1718    Evas_Object *parent;
1719    Edje *ed;
1720
1721    parent = evas_object_smart_parent_get(obj);
1722    ed = _edje_fetch(parent);
1723
1724    ed->dirty = 1;
1725    _edje_recalc(ed);
1726 }
1727
1728 EAPI void
1729 edje_extern_object_min_size_set(Evas_Object *obj, Evas_Coord minw, Evas_Coord minh)
1730 {
1731    Edje_Real_Part *rp;
1732
1733    evas_object_size_hint_min_set(obj, minw, minh);
1734    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
1735    if (rp)
1736      {
1737         rp->swallow_params.min.w = minw;
1738         rp->swallow_params.min.h = minh;
1739
1740         _recalc_extern_parent(obj);
1741      }
1742 }
1743
1744 EAPI void
1745 edje_extern_object_max_size_set(Evas_Object *obj, Evas_Coord maxw, Evas_Coord maxh)
1746 {
1747    Edje_Real_Part *rp;
1748
1749    evas_object_size_hint_max_set(obj, maxw, maxh);
1750    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
1751    if (rp)
1752      {
1753         rp->swallow_params.max.w = maxw;
1754         rp->swallow_params.max.h = maxh;
1755
1756         _recalc_extern_parent(obj);
1757      }
1758 }
1759
1760 EAPI void
1761 edje_extern_object_aspect_set(Evas_Object *obj, Edje_Aspect_Control aspect, Evas_Coord aw, Evas_Coord ah)
1762 {
1763    Edje_Real_Part *rp;
1764    Evas_Aspect_Control asp;
1765
1766    asp = EVAS_ASPECT_CONTROL_NONE;
1767    switch (aspect)
1768      {
1769       case EDJE_ASPECT_CONTROL_NONE: asp = EVAS_ASPECT_CONTROL_NONE; break;
1770       case EDJE_ASPECT_CONTROL_NEITHER: asp = EVAS_ASPECT_CONTROL_NEITHER; break;
1771       case EDJE_ASPECT_CONTROL_HORIZONTAL: asp = EVAS_ASPECT_CONTROL_HORIZONTAL; break;
1772       case EDJE_ASPECT_CONTROL_VERTICAL: asp = EVAS_ASPECT_CONTROL_VERTICAL; break;
1773       case EDJE_ASPECT_CONTROL_BOTH: asp = EVAS_ASPECT_CONTROL_BOTH; break;
1774       default: break;
1775      }
1776    if (aw < 1) aw = 1;
1777    if (ah < 1) ah = 1;
1778    evas_object_size_hint_aspect_set(obj, asp, aw, ah);
1779    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
1780    if (rp)
1781      {
1782         rp->swallow_params.aspect.mode = aspect;
1783         rp->swallow_params.aspect.w = aw;
1784         rp->swallow_params.aspect.h = ah;
1785         _recalc_extern_parent(obj);
1786      }
1787 }
1788
1789 struct edje_box_layout_builtin {
1790    const char *name;
1791    Evas_Object_Box_Layout cb;
1792 };
1793
1794 static Evas_Object_Box_Layout
1795 _edje_box_layout_builtin_find(const char *name)
1796 {
1797    const struct edje_box_layout_builtin _edje_box_layout_builtin[] = {
1798      {"horizontal", evas_object_box_layout_horizontal},
1799      {"horizontal_flow", evas_object_box_layout_flow_horizontal},
1800      {"horizontal_homogeneous", evas_object_box_layout_homogeneous_horizontal},
1801      {"horizontal_max", evas_object_box_layout_homogeneous_max_size_horizontal},
1802      {"stack", evas_object_box_layout_stack},
1803      {"vertical", evas_object_box_layout_vertical},
1804      {"vertical_flow", evas_object_box_layout_flow_vertical},
1805      {"vertical_homogeneous", evas_object_box_layout_homogeneous_vertical},
1806      {"vertical_max", evas_object_box_layout_homogeneous_max_size_vertical},
1807      {NULL, NULL}
1808    };
1809    const struct edje_box_layout_builtin *base;
1810
1811    switch (name[0])
1812      {
1813       case 'h':
1814          base = _edje_box_layout_builtin + 0;
1815          break;
1816       case 's':
1817          base = _edje_box_layout_builtin + 4;
1818          break;
1819       case 'v':
1820          base = _edje_box_layout_builtin + 5;
1821          break;
1822       default:
1823          return NULL;
1824      }
1825
1826    for (; (base->name) && (base->name[0] == name[0]); base++)
1827      if (strcmp(base->name, name) == 0)
1828        return base->cb;
1829
1830    return NULL;
1831 }
1832
1833 static Eina_Rbtree_Direction
1834 _edje_box_layout_external_node_cmp(const Eina_Rbtree *left, const Eina_Rbtree *right, __UNUSED__ void *data)
1835 {
1836    Edje_Box_Layout *l = (Edje_Box_Layout *)left;
1837    Edje_Box_Layout *r = (Edje_Box_Layout *)right;
1838
1839    if (strcmp(l->name, r->name) < 0)
1840      return EINA_RBTREE_RIGHT;
1841    else
1842      return EINA_RBTREE_LEFT;
1843 }
1844
1845 static int
1846 _edje_box_layout_external_find_cmp(const Eina_Rbtree *node, const void *key, __UNUSED__ int length, __UNUSED__ void *data)
1847 {
1848    Edje_Box_Layout *l = (Edje_Box_Layout *)node;
1849    return strcmp(key, l->name);
1850 }
1851
1852 static Edje_Box_Layout *
1853 _edje_box_layout_external_find(const char *name)
1854 {
1855    return (Edje_Box_Layout *)eina_rbtree_inline_lookup
1856      (_edje_box_layout_registry, name, 0, _edje_box_layout_external_find_cmp,
1857       NULL);
1858 }
1859
1860 Eina_Bool
1861 _edje_box_layout_find(const char *name, Evas_Object_Box_Layout *cb, void **data, void (**free_data)(void *data))
1862 {
1863    const Edje_Box_Layout *l;
1864
1865    if (!name) return EINA_FALSE;
1866
1867    *cb = _edje_box_layout_builtin_find(name);
1868    if (*cb)
1869      {
1870         *free_data = NULL;
1871         *data = NULL;
1872         return EINA_TRUE;
1873      }
1874
1875    l = _edje_box_layout_external_find(name);
1876    if (!l) return EINA_FALSE;
1877
1878    *cb = l->func;
1879    *free_data = l->layout_data_free;
1880    if (l->layout_data_get)
1881      *data = l->layout_data_get(l->data);
1882    else
1883      *data = NULL;
1884
1885    return EINA_TRUE;
1886 }
1887
1888 static void
1889 _edje_box_layout_external_free(Eina_Rbtree *node, __UNUSED__ void *data)
1890 {
1891    Edje_Box_Layout *l = (Edje_Box_Layout *)node;
1892
1893    if (l->data && l->free_data)
1894      l->free_data(l->data);
1895    free(l);
1896 }
1897
1898 static Edje_Box_Layout *
1899 _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)
1900 {
1901    Edje_Box_Layout *l;
1902    size_t name_len;
1903
1904    name_len = strlen(name) + 1;
1905    l = malloc(sizeof(Edje_Box_Layout) + name_len);
1906    if (!l)
1907      {
1908         perror("malloc");
1909         return NULL;
1910      }
1911
1912    l->func = func;
1913    l->layout_data_get = layout_data_get;
1914    l->layout_data_free = layout_data_free;
1915    l->free_data = free_data;
1916    l->data = data;
1917
1918    memcpy(l->name, name, name_len);
1919
1920    return l;
1921 }
1922
1923 EAPI void
1924 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)
1925 {
1926    Edje_Box_Layout *l;
1927
1928    if (!name) return;
1929
1930    if (_edje_box_layout_builtin_find(name))
1931      {
1932         ERR("Cannot register layout '%s': would override builtin!",
1933             name);
1934
1935         if (data && free_data) free_data(data);
1936         return;
1937      }
1938
1939    l = _edje_box_layout_external_find(name);
1940    if (!l)
1941      {
1942         if (!func)
1943           {
1944              if (data && free_data) free_data(data);
1945              return;
1946           }
1947
1948         l = _edje_box_layout_external_new
1949           (name, func, layout_data_get, layout_data_free, free_data, data);
1950         if (!l)
1951           return;
1952
1953         _edje_box_layout_registry = eina_rbtree_inline_insert
1954           (_edje_box_layout_registry, (Eina_Rbtree *)l,
1955            _edje_box_layout_external_node_cmp, NULL);
1956      }
1957    else
1958      {
1959         if (func)
1960           {
1961              if (l->data && l->free_data) l->free_data(l->data);
1962
1963              l->func = func;
1964              l->layout_data_get = layout_data_get;
1965              l->layout_data_free = layout_data_free;
1966              l->free_data = free_data;
1967              l->data = data;
1968           }
1969         else
1970           {
1971              if (data && free_data) free_data(data);
1972
1973              _edje_box_layout_registry = eina_rbtree_inline_remove
1974                (_edje_box_layout_registry, (Eina_Rbtree *)l,
1975                 _edje_box_layout_external_node_cmp, NULL);
1976              _edje_box_layout_external_free((Eina_Rbtree *)l, NULL);
1977           }
1978      }
1979 }
1980
1981 EAPI void
1982 edje_object_part_unswallow(Evas_Object *obj __UNUSED__, Evas_Object *obj_swallow)
1983 {
1984    Edje_Real_Part *rp;
1985
1986    if (!obj_swallow) return;
1987
1988    rp = (Edje_Real_Part *)evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
1989    if (!rp)
1990      return;
1991    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
1992      {
1993         ERR("cannot unswallow part %s: not swallow type!", rp->part->name);
1994         return;
1995      }
1996    if (rp->swallowed_object == obj_swallow)
1997      {
1998         evas_object_smart_member_del(rp->swallowed_object);
1999         evas_object_event_callback_del_full(rp->swallowed_object,
2000                                             EVAS_CALLBACK_FREE,
2001                                             _edje_object_part_swallow_free_cb,
2002                                             rp->edje->obj);
2003         evas_object_event_callback_del_full(rp->swallowed_object,
2004                                             EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2005                                             _edje_object_part_swallow_changed_hints_cb,
2006                                             rp);
2007         evas_object_clip_unset(rp->swallowed_object);
2008         evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
2009
2010         if (rp->part->mouse_events)
2011           _edje_callbacks_del(rp->swallowed_object, rp->edje);
2012         _edje_callbacks_focus_del(rp->swallowed_object, rp->edje);
2013
2014         rp->swallowed_object = NULL;
2015         rp->swallow_params.min.w = 0;
2016         rp->swallow_params.min.h = 0;
2017         rp->swallow_params.max.w = 0;
2018         rp->swallow_params.max.h = 0;
2019         rp->edje->dirty = 1;
2020 #ifdef EDJE_CALC_CACHE
2021         rp->invalidate = 1;
2022 #endif
2023         _edje_recalc_do(rp->edje);
2024         return;
2025      }
2026 }
2027
2028 EAPI Evas_Object *
2029 edje_object_part_swallow_get(const Evas_Object *obj, const char *part)
2030 {
2031    Edje *ed;
2032    Edje_Real_Part *rp;
2033
2034    ed = _edje_fetch(obj);
2035    if ((!ed) || (!part)) return NULL;
2036
2037    /* Need to recalc before providing the object. */
2038    _edje_recalc_do(ed);
2039
2040    rp = _edje_real_part_recursive_get(ed, (char *)part);
2041    if (!rp) return NULL;
2042    return rp->swallowed_object;
2043 }
2044
2045 EAPI void
2046 edje_object_size_min_get(const Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
2047 {
2048    Edje *ed;
2049
2050    ed = _edje_fetch(obj);
2051    if ((!ed) || (!ed->collection))
2052      {
2053         if (minw) *minw = 0;
2054         if (minh) *minh = 0;
2055         return;
2056      }
2057    if (minw) *minw = ed->collection->prop.min.w;
2058    if (minh) *minh = ed->collection->prop.min.h;
2059 }
2060
2061 EAPI void
2062 edje_object_size_max_get(const Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *maxh)
2063 {
2064    Edje *ed;
2065
2066    ed = _edje_fetch(obj);
2067    if ((!ed) || (!ed->collection))
2068      {
2069         if (maxw) *maxw = 0;
2070         if (maxh) *maxh = 0;
2071         return;
2072      }
2073
2074    /* Need to recalc before providing the object. */
2075    _edje_recalc_do(ed);
2076
2077    if (ed->collection->prop.max.w == 0)
2078      {
2079         /* XXX TODO: convert maxw to 0, fix things that break. */
2080         if (maxw) *maxw = EDJE_INF_MAX_W;
2081      }
2082    else
2083      {
2084         if (maxw) *maxw = ed->collection->prop.max.w;
2085      }
2086    if (ed->collection->prop.max.h == 0)
2087      {
2088         /* XXX TODO: convert maxh to 0, fix things that break. */
2089         if (maxh) *maxh = EDJE_INF_MAX_H;
2090      }
2091    else
2092      {
2093         if (maxh) *maxh = ed->collection->prop.max.h;
2094      }
2095 }
2096
2097 EAPI void
2098 edje_object_calc_force(Evas_Object *obj)
2099 {
2100    Edje *ed;
2101    int pf, pf2;
2102
2103    ed = _edje_fetch(obj);
2104    if (!ed) return;
2105    ed->dirty = 1;
2106 #ifdef EDJE_CALC_CACHE
2107    ed->all_part_change = 1;
2108 #endif
2109
2110    pf2 = _edje_freeze_val;
2111    pf = ed->freeze;
2112
2113    _edje_freeze_val = 0;
2114    ed->freeze = 0;
2115
2116    _edje_recalc_do(ed);
2117
2118    ed->freeze = pf;
2119    _edje_freeze_val = pf2;
2120 }
2121
2122 EAPI void
2123 edje_object_size_min_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
2124 {
2125    edje_object_size_min_restricted_calc(obj, minw, minh, 0, 0);
2126 }
2127
2128 /** Calculate the geometry used by all parts
2129  * @param obj A valid Evas_Object handle
2130  * @param x The x coordinate pointer
2131  * @param y The y coordinate pointer
2132  * @param w The width pointer
2133  * @param h The height pointer
2134  *
2135  * Calculates the geometry used by all object parts. Including out of bounds parts.
2136  */
2137 EAPI Eina_Bool
2138 edje_object_parts_extends_calc(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
2139 {
2140    Edje *ed;
2141    Evas_Coord x1 = INT_MAX, y1 = INT_MAX;
2142    Evas_Coord x2 = 0, y2 = 0;
2143    unsigned int i;
2144
2145    ed = _edje_fetch(obj);
2146    if (!ed)
2147      {
2148         if (x) *x = 0;
2149         if (y) *y = 0;
2150         if (w) *w = 0;
2151         if (h) *h = 0;
2152         return EINA_FALSE;
2153      }
2154
2155    ed->calc_only = 1;
2156
2157    /* Need to recalc before providing the object. */
2158    ed->dirty = 1;
2159    _edje_recalc_do(ed);
2160
2161    for (i = 0; i < ed->table_parts_size; i++)
2162      {
2163         Edje_Real_Part *rp;
2164         Evas_Coord rpx1, rpy1;
2165         Evas_Coord rpx2, rpy2;
2166
2167         rp = ed->table_parts[i];
2168
2169         rpx1 = rp->x;
2170         rpy1 = rp->y;
2171         rpx2 = rpx1 + rp->w;
2172         rpy2 = rpy1 + rp->h;
2173
2174         if (x1 > rpx1) x1 = rpx1;
2175         if (y1 > rpy1) y1 = rpy1;
2176         if (x2 < rpx2) x2 = rpx2;
2177         if (y2 < rpy2) y2 = rpy2;
2178      }
2179
2180    ed->calc_only = 0;
2181
2182    *x = x1;
2183    *y = y1;
2184    *w = x2 - x1;
2185    *h = y2 - y1;
2186
2187    return EINA_TRUE;
2188 }
2189
2190 /** Calculate minimum size
2191  * @param obj A valid Evas_Object handle
2192  * @param minw Minimum width pointer
2193  * @param minh Minimum height pointer
2194  * @param restrictedw Do not allow object min width calc to be less than this
2195  * @param restrictedh Do not allow object min height calc to be less than this
2196  *
2197  * Calculates the object's minimum size. Be advised that invisible parts *ARE*
2198  * taken into account in this calculation, if you don't want that to happen,
2199  * resize them to 0.
2200  */
2201 EAPI void
2202 edje_object_size_min_restricted_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord restrictedw, Evas_Coord restrictedh)
2203 {
2204    Edje *ed;
2205    Evas_Coord pw, ph;
2206    int maxw, maxh;
2207    int okw, okh;
2208    int reset_maxwh;
2209    Edje_Real_Part *pep = NULL;
2210    Eina_Bool has_non_fixed_tb = EINA_FALSE;
2211
2212    ed = _edje_fetch(obj);
2213    if ((!ed) || (!ed->collection))
2214      {
2215         if (minw) *minw = restrictedw;
2216         if (minh) *minh = restrictedh;
2217         return;
2218      }
2219    reset_maxwh = 1;
2220    ed->calc_only = 1;
2221    pw = ed->w;
2222    ph = ed->h;
2223
2224    again:
2225    ed->w = restrictedw;
2226    ed->h = restrictedh;
2227
2228    maxw = 0;
2229    maxh = 0;
2230
2231    do
2232      {
2233         unsigned int i;
2234
2235         okw = okh = 0;
2236         ed->dirty = 1;
2237 #ifdef EDJE_CALC_CACHE
2238         ed->all_part_change = 1;
2239 #endif
2240         _edje_recalc_do(ed);
2241         if (reset_maxwh)
2242           {
2243              maxw = 0;
2244              maxh = 0;
2245           }
2246         pep = NULL;
2247         for (i = 0; i < ed->table_parts_size; i++)
2248           {
2249              Edje_Real_Part *ep;
2250              int w, h;
2251              int didw;
2252
2253              ep = ed->table_parts[i];
2254              w = ep->w - ep->req.w;
2255              h = ep->h - ep->req.h;
2256              didw = 0;
2257              if (ep->chosen_description)
2258                {
2259                   if (!ep->chosen_description->fixed.w)
2260                     {
2261                        if ((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK))
2262                          {
2263                             Evas_Coord tb_mw;
2264                             evas_object_textblock_size_formatted_get(ep->object,
2265                                &tb_mw, NULL);
2266                             tb_mw -= ep->req.w;
2267                             if (tb_mw > w)
2268                               {
2269                                  w = tb_mw;
2270                               }
2271                             has_non_fixed_tb = EINA_TRUE;
2272                          }
2273                        if (w > maxw)
2274                          {
2275                             maxw = w;
2276                             okw = 1;
2277                             pep = ep;
2278                             didw = 1;
2279                          }
2280                     }
2281                   if (!ep->chosen_description->fixed.h)
2282                     {
2283                        if (!((ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) &&
2284                              (!((Edje_Part_Description_Text *)ep->chosen_description)->text.min_x) &&
2285                              (didw)))
2286                          {
2287                             if (h > maxh)
2288                               {
2289                                  maxh = h;
2290                                  okh = 1;
2291                                  pep = ep;
2292                               }
2293                          }
2294
2295                        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2296                          {
2297                             has_non_fixed_tb = EINA_TRUE;
2298                          }
2299                     }
2300                }
2301           }
2302         if (okw)
2303           {
2304              ed->w += maxw;
2305              if (ed->w < restrictedw) ed->w = restrictedw;
2306           }
2307         if (okh)
2308           {
2309              ed->h += maxh;
2310              if (ed->h < restrictedh) ed->h = restrictedh;
2311           }
2312         if ((ed->w > 4000) || (ed->h > 4000))
2313           {
2314              /* Only print it if we have a non-fixed textblock.
2315               * We should possibly avoid all of this if in this case, but in
2316               * the meanwhile, just doing this. */
2317              if (!has_non_fixed_tb)
2318                {
2319                   if (pep)
2320                      ERR("file %s, group %s has a non-fixed part '%s'. Adding 'fixed: 1 1;' to source EDC may help. Continuing discarding faulty part.",
2321                          ed->path, ed->group, pep->part->name);
2322                   else
2323                      ERR("file %s, group %s overflowed 4000x4000 with minimum size of %dx%d. Continuing discarding faulty parts.",
2324                          ed->path, ed->group, ed->w, ed->h);
2325                }
2326
2327              if (reset_maxwh)
2328                {
2329                   reset_maxwh = 0;
2330                   goto again;
2331                }
2332           }
2333      }
2334    while (okw || okh);
2335    ed->min.w = ed->w;
2336    ed->min.h = ed->h;
2337
2338    if (minw) *minw = ed->min.w;
2339    if (minh) *minh = ed->min.h;
2340
2341    ed->w = pw;
2342    ed->h = ph;
2343    ed->dirty = 1;
2344 #ifdef EDJE_CALC_CACHE
2345    ed->all_part_change = 1;
2346 #endif
2347    _edje_recalc(ed);
2348    ed->calc_only = 0;
2349 }
2350
2351 /* FIXME: Correctly return other states */
2352 EAPI const char *
2353 edje_object_part_state_get(const Evas_Object *obj, const char *part, double *val_ret)
2354 {
2355    Edje *ed;
2356    Edje_Real_Part *rp;
2357
2358    ed = _edje_fetch(obj);
2359    if ((!ed) || (!part))
2360      {
2361         if (val_ret) *val_ret = 0;
2362         return "";
2363      }
2364
2365    /* Need to recalc before providing the object. */
2366    _edje_recalc_do(ed);
2367
2368    rp = _edje_real_part_recursive_get(ed, (char *)part);
2369    if (!rp)
2370      {
2371         if (val_ret) *val_ret = 0;
2372         INF("part not found");
2373         return "";
2374      }
2375    if (rp->chosen_description)
2376      {
2377         if (val_ret) *val_ret = rp->chosen_description->state.value;
2378         if (rp->chosen_description->state.name)
2379           return rp->chosen_description->state.name;
2380         return "default";
2381      }
2382    else
2383      {
2384         if (rp->param1.description)
2385           {
2386              if (val_ret) *val_ret = rp->param1.description->state.value;
2387              if (rp->param1.description->state.name)
2388                return rp->param1.description->state.name;
2389              return "default";
2390           }
2391      }
2392    if (val_ret) *val_ret = 0;
2393    return "";
2394 }
2395
2396 EAPI Edje_Drag_Dir
2397 edje_object_part_drag_dir_get(const Evas_Object *obj, const char *part)
2398 {
2399    Edje *ed;
2400    Edje_Real_Part *rp;
2401
2402    ed = _edje_fetch(obj);
2403    if ((!ed) || (!part)) return EDJE_DRAG_DIR_NONE;
2404
2405    /* Need to recalc before providing the object. */
2406    _edje_recalc_do(ed);
2407
2408    rp = _edje_real_part_recursive_get(ed, (char *)part);
2409    if (!rp) return EDJE_DRAG_DIR_NONE;
2410    if ((rp->part->dragable.x) && (rp->part->dragable.y)) return EDJE_DRAG_DIR_XY;
2411    else if (rp->part->dragable.x) return EDJE_DRAG_DIR_X;
2412    else if (rp->part->dragable.y) return EDJE_DRAG_DIR_Y;
2413    return EDJE_DRAG_DIR_NONE;
2414 }
2415
2416 EAPI Eina_Bool
2417 edje_object_part_drag_value_set(Evas_Object *obj, const char *part, double dx, double dy)
2418 {
2419    Edje *ed;
2420    Edje_Real_Part *rp;
2421
2422    ed = _edje_fetch(obj);
2423    if ((!ed) || (!part)) return EINA_FALSE;
2424    rp = _edje_real_part_recursive_get(ed, (char *)part);
2425    if (!rp) return EINA_FALSE;
2426    if (!rp->drag) return EINA_FALSE;
2427    if (rp->drag->down.count > 0) return EINA_FALSE;
2428    if (rp->part->dragable.confine_id != -1)
2429      {
2430         dx = CLAMP(dx, 0.0, 1.0);
2431         dy = CLAMP(dy, 0.0, 1.0);
2432      }
2433    if (rp->part->dragable.x < 0) dx = 1.0 - dx;
2434    if (rp->part->dragable.y < 0) dy = 1.0 - dy;
2435    if ((rp->drag->val.x == FROM_DOUBLE(dx)) && (rp->drag->val.y == FROM_DOUBLE(dy))) return EINA_TRUE;
2436    rp->drag->val.x = FROM_DOUBLE(dx);
2437    rp->drag->val.y = FROM_DOUBLE(dy);
2438 #ifdef EDJE_CALC_CACHE
2439    rp->invalidate = 1;
2440 #endif
2441    _edje_dragable_pos_set(rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
2442    _edje_emit(rp->edje, "drag,set", rp->part->name);
2443    return EINA_TRUE;
2444 }
2445
2446 /* FIXME: Should this be x and y instead of dx/dy? */
2447 EAPI Eina_Bool
2448 edje_object_part_drag_value_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
2449 {
2450    Edje *ed;
2451    Edje_Real_Part *rp;
2452    double ddx, ddy;
2453
2454    ed = _edje_fetch(obj);
2455    if ((!ed) || (!part))
2456      {
2457         if (dx) *dx = 0;
2458         if (dy) *dy = 0;
2459         return EINA_FALSE;
2460      }
2461
2462    /* Need to recalc before providing the object. */
2463    _edje_recalc_do(ed);
2464
2465    rp = _edje_real_part_recursive_get(ed, (char *)part);
2466    if (!rp || !rp->drag)
2467      {
2468         if (dx) *dx = 0;
2469         if (dy) *dy = 0;
2470         return EINA_FALSE;
2471      }
2472    ddx = TO_DOUBLE(rp->drag->val.x);
2473    ddy = TO_DOUBLE(rp->drag->val.y);
2474    if (rp->part->dragable.x < 0) ddx = 1.0 - ddx;
2475    if (rp->part->dragable.y < 0) ddy = 1.0 - ddy;
2476    if (dx) *dx = ddx;
2477    if (dy) *dy = ddy;
2478    return EINA_TRUE;
2479 }
2480
2481 EAPI Eina_Bool
2482 edje_object_part_drag_size_set(Evas_Object *obj, const char *part, double dw, double dh)
2483 {
2484    Edje *ed;
2485    Edje_Real_Part *rp;
2486
2487    ed = _edje_fetch(obj);
2488    if ((!ed) || (!part)) return EINA_FALSE;
2489    rp = _edje_real_part_recursive_get(ed, (char *)part);
2490    if (!rp) return EINA_FALSE;
2491    if (!rp->drag) return EINA_FALSE;
2492    if (dw < 0.0) dw = 0.0;
2493    else if (dw > 1.0) dw = 1.0;
2494    if (dh < 0.0) dh = 0.0;
2495    else if (dh > 1.0) dh = 1.0;
2496    if ((rp->drag->size.x == FROM_DOUBLE(dw)) && (rp->drag->size.y == FROM_DOUBLE(dh))) return EINA_TRUE;
2497    rp->drag->size.x = FROM_DOUBLE(dw);
2498    rp->drag->size.y = FROM_DOUBLE(dh);
2499    rp->edje->dirty = 1;
2500 #ifdef EDJE_CALC_CACHE
2501    rp->invalidate = 1;
2502 #endif
2503    _edje_recalc(rp->edje);
2504    return EINA_TRUE;
2505 }
2506
2507 EAPI Eina_Bool
2508 edje_object_part_drag_size_get(const Evas_Object *obj, const char *part, double *dw, double *dh)
2509 {
2510    Edje *ed;
2511    Edje_Real_Part *rp;
2512
2513    ed = _edje_fetch(obj);
2514    if ((!ed) || (!part))
2515      {
2516         if (dw) *dw = 0;
2517         if (dh) *dh = 0;
2518         return EINA_FALSE;
2519      }
2520
2521    /* Need to recalc before providing the object. */
2522    _edje_recalc_do(ed);
2523
2524    rp = _edje_real_part_recursive_get(ed, (char *)part);
2525    if (!rp || !rp->drag)
2526      {
2527         if (dw) *dw = 0;
2528         if (dh) *dh = 0;
2529         return EINA_FALSE;
2530      }
2531    if (dw) *dw = TO_DOUBLE(rp->drag->size.x);
2532    if (dh) *dh = TO_DOUBLE(rp->drag->size.y);
2533    return EINA_TRUE;
2534 }
2535
2536 EAPI Eina_Bool
2537 edje_object_part_drag_step_set(Evas_Object *obj, const char *part, double dx, double dy)
2538 {
2539    Edje *ed;
2540    Edje_Real_Part *rp;
2541
2542    ed = _edje_fetch(obj);
2543    if ((!ed) || (!part)) return EINA_FALSE;
2544    rp = _edje_real_part_recursive_get(ed, (char *)part);
2545    if (!rp) return EINA_FALSE;
2546    if (!rp->drag) return EINA_FALSE;
2547    if (dx < 0.0) dx = 0.0;
2548    else if (dx > 1.0) dx = 1.0;
2549    if (dy < 0.0) dy = 0.0;
2550    else if (dy > 1.0) dy = 1.0;
2551    rp->drag->step.x = FROM_DOUBLE(dx);
2552    rp->drag->step.y = FROM_DOUBLE(dy);
2553 #ifdef EDJE_CALC_CACHE
2554    rp->invalidate = 1;
2555 #endif
2556    return EINA_TRUE;
2557 }
2558
2559 EAPI Eina_Bool
2560 edje_object_part_drag_step_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
2561 {
2562    Edje *ed;
2563    Edje_Real_Part *rp;
2564
2565    ed = _edje_fetch(obj);
2566    if ((!ed) || (!part))
2567      {
2568         if (dx) *dx = 0;
2569         if (dy) *dy = 0;
2570         return EINA_FALSE;
2571      }
2572
2573    /* Need to recalc before providing the object. */
2574    _edje_recalc_do(ed);
2575
2576    rp = _edje_real_part_recursive_get(ed, (char *)part);
2577    if (!rp || !rp->drag)
2578      {
2579         if (dx) *dx = 0;
2580         if (dy) *dy = 0;
2581         return EINA_FALSE;
2582      }
2583    if (dx) *dx = TO_DOUBLE(rp->drag->step.x);
2584    if (dy) *dy = TO_DOUBLE(rp->drag->step.y);
2585    return EINA_TRUE;
2586 }
2587
2588 EAPI Eina_Bool
2589 edje_object_part_drag_page_set(Evas_Object *obj, const char *part, double dx, double dy)
2590 {
2591    Edje *ed;
2592    Edje_Real_Part *rp;
2593
2594    ed = _edje_fetch(obj);
2595    if ((!ed) || (!part)) return EINA_FALSE;
2596    rp = _edje_real_part_recursive_get(ed, (char *)part);
2597    if (!rp) return EINA_FALSE;
2598    if (!rp->drag) return EINA_FALSE;
2599    if (dx < 0.0) dx = 0.0;
2600    else if (dx > 1.0) dx = 1.0;
2601    if (dy < 0.0) dy = 0.0;
2602    else if (dy > 1.0) dy = 1.0;
2603    rp->drag->page.x = FROM_DOUBLE(dx);
2604    rp->drag->page.y = FROM_DOUBLE(dy);
2605 #ifdef EDJE_CALC_CACHE
2606    rp->invalidate = 1;
2607 #endif
2608    return EINA_TRUE;
2609 }
2610
2611 EAPI Eina_Bool
2612 edje_object_part_drag_page_get(const Evas_Object *obj, const char *part, double *dx, double *dy)
2613 {
2614    Edje *ed;
2615    Edje_Real_Part *rp;
2616
2617    ed = _edje_fetch(obj);
2618    if ((!ed) || (!part))
2619      {
2620         if (dx) *dx = 0;
2621         if (dy) *dy = 0;
2622         return EINA_FALSE;
2623      }
2624
2625    /* Need to recalc before providing the object. */
2626    _edje_recalc_do(ed);
2627
2628    rp = _edje_real_part_recursive_get(ed, (char *)part);
2629    if (!rp || !rp->drag)
2630      {
2631         if (dx) *dx = 0;
2632         if (dy) *dy = 0;
2633         return EINA_FALSE;
2634      }
2635    if (dx) *dx = TO_DOUBLE(rp->drag->page.x);
2636    if (dy) *dy = TO_DOUBLE(rp->drag->page.y);
2637    return EINA_TRUE;
2638 }
2639
2640 EAPI Eina_Bool
2641 edje_object_part_drag_step(Evas_Object *obj, const char *part, double dx, double dy)
2642 {
2643    Edje *ed;
2644    Edje_Real_Part *rp;
2645    FLOAT_T px, py;
2646
2647    ed = _edje_fetch(obj);
2648    if ((!ed) || (!part)) return EINA_FALSE;
2649    rp = _edje_real_part_recursive_get(ed, (char *)part);
2650    if (!rp) return EINA_FALSE;
2651    if (!rp->drag) return EINA_FALSE;
2652    if (rp->drag->down.count > 0) return EINA_FALSE;
2653    px = rp->drag->val.x;
2654    py = rp->drag->val.y;
2655    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx),
2656                                  MUL(rp->drag->step.x, rp->part->dragable.x)));
2657    rp->drag->val.y = ADD(py, MUL(FROM_DOUBLE(dy),
2658                                  MUL(rp->drag->step.y, rp->part->dragable.y)));
2659    rp->drag->val.x = CLAMP (rp->drag->val.x, ZERO, FROM_DOUBLE(1.0));
2660    rp->drag->val.y = CLAMP (rp->drag->val.y, ZERO, FROM_DOUBLE(1.0));
2661    if ((px == rp->drag->val.x) && (py == rp->drag->val.y)) return EINA_TRUE;
2662 #ifdef EDJE_CALC_CACHE
2663    rp->invalidate = 1;
2664 #endif
2665    _edje_dragable_pos_set(rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
2666    _edje_emit(rp->edje, "drag,step", rp->part->name);
2667    return EINA_TRUE;
2668 }
2669
2670 EAPI Eina_Bool
2671 edje_object_part_drag_page(Evas_Object *obj, const char *part, double dx, double dy)
2672 {
2673    Edje *ed;
2674    Edje_Real_Part *rp;
2675    FLOAT_T px, py;
2676
2677    ed = _edje_fetch(obj);
2678    if ((!ed) || (!part)) return EINA_FALSE;
2679    rp = _edje_real_part_recursive_get(ed, (char *)part);
2680    if (!rp) return EINA_FALSE;
2681    if (!rp->drag) return EINA_FALSE;
2682    if (rp->drag->down.count > 0) return EINA_FALSE;
2683    px = rp->drag->val.x;
2684    py = rp->drag->val.y;
2685    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx), MUL(rp->drag->page.x, rp->part->dragable.x)));
2686    rp->drag->val.y = ADD(py, MUL(FROM_DOUBLE(dy), MUL(rp->drag->page.y, rp->part->dragable.y)));
2687    rp->drag->val.x = CLAMP (rp->drag->val.x, ZERO, FROM_DOUBLE(1.0));
2688    rp->drag->val.y = CLAMP (rp->drag->val.y, ZERO, FROM_DOUBLE(1.0));
2689    if ((px == rp->drag->val.x) && (py == rp->drag->val.y)) return EINA_TRUE;
2690 #ifdef EDJE_CALC_CACHE
2691    rp->invalidate = 1;
2692 #endif
2693    _edje_dragable_pos_set(rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
2694    _edje_emit(rp->edje, "drag,page", rp->part->name);
2695    return EINA_TRUE;
2696 }
2697
2698 void
2699 _edje_box_init(void)
2700 {
2701
2702 }
2703
2704 void
2705 _edje_box_shutdown(void)
2706 {
2707    if (!_edje_box_layout_registry)
2708      return;
2709
2710    eina_rbtree_delete
2711      (_edje_box_layout_registry, _edje_box_layout_external_free, NULL);
2712    _edje_box_layout_registry = NULL;
2713 }
2714
2715 EAPI Eina_Bool
2716 edje_object_part_box_append(Evas_Object *obj, const char *part, Evas_Object *child)
2717 {
2718    Edje *ed;
2719    Edje_Real_Part *rp;
2720
2721    ed = _edje_fetch(obj);
2722    if ((!ed) || (!part) || (!child)) return EINA_FALSE;
2723
2724    rp = _edje_real_part_recursive_get(ed, part);
2725    if (!rp) return EINA_FALSE;
2726    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
2727
2728    return _edje_real_part_box_append(rp, child);
2729 }
2730
2731 EAPI Eina_Bool
2732 edje_object_part_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child)
2733 {
2734    Edje *ed;
2735    Edje_Real_Part *rp;
2736
2737    ed = _edje_fetch(obj);
2738    if ((!ed) || (!part)) return EINA_FALSE;
2739
2740    rp = _edje_real_part_recursive_get(ed, part);
2741    if (!rp) return EINA_FALSE;
2742    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
2743
2744    return _edje_real_part_box_prepend(rp, child);
2745 }
2746
2747 EAPI Eina_Bool
2748 edje_object_part_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference)
2749 {
2750    Edje *ed;
2751    Edje_Real_Part *rp;
2752
2753    ed = _edje_fetch(obj);
2754    if ((!ed) || (!part)) return EINA_FALSE;
2755
2756    rp = _edje_real_part_recursive_get(ed, part);
2757    if (!rp) return EINA_FALSE;
2758    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
2759
2760    return _edje_real_part_box_insert_before(rp, child, reference);
2761 }
2762
2763 EAPI Eina_Bool
2764 edje_object_part_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos)
2765 {
2766    Edje *ed;
2767    Edje_Real_Part *rp;
2768
2769    ed = _edje_fetch(obj);
2770    if ((!ed) || (!part)) return EINA_FALSE;
2771
2772    rp = _edje_real_part_recursive_get(ed, part);
2773    if (!rp) return EINA_FALSE;
2774    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
2775
2776    return _edje_real_part_box_insert_at(rp, child, pos);
2777 }
2778
2779 EAPI Evas_Object *
2780 edje_object_part_box_remove(Evas_Object *obj, const char *part, Evas_Object *child)
2781 {
2782    Edje *ed;
2783    Edje_Real_Part *rp;
2784
2785    ed = _edje_fetch(obj);
2786    if ((!ed) || (!part)) return NULL;
2787
2788    rp = _edje_real_part_recursive_get(ed, part);
2789    if (!rp) return NULL;
2790    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
2791
2792    return _edje_real_part_box_remove(rp, child);
2793 }
2794
2795 EAPI Evas_Object *
2796 edje_object_part_box_remove_at(Evas_Object *obj, const char *part, unsigned int pos)
2797 {
2798    Edje *ed;
2799    Edje_Real_Part *rp;
2800
2801    ed = _edje_fetch(obj);
2802    if ((!ed) || (!part)) return NULL;
2803
2804    rp = _edje_real_part_recursive_get(ed, part);
2805    if (!rp) return NULL;
2806    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
2807
2808    return _edje_real_part_box_remove_at(rp, pos);
2809 }
2810
2811 EAPI Eina_Bool
2812 edje_object_part_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear)
2813 {
2814    Edje *ed;
2815    Edje_Real_Part *rp;
2816
2817    ed = _edje_fetch(obj);
2818    if ((!ed) || (!part)) return EINA_FALSE;
2819
2820    rp = _edje_real_part_recursive_get(ed, part);
2821    if (!rp) return EINA_FALSE;
2822    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
2823
2824    return _edje_real_part_box_remove_all(rp, clear);
2825
2826 }
2827
2828 static void
2829 _edje_box_child_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
2830 {
2831    Edje_Real_Part *rp = data;
2832
2833    rp->edje->dirty = 1;
2834 #ifdef EDJE_CALC_CACHE
2835    rp->invalidate = 1;
2836 #endif
2837    _edje_recalc(rp->edje);
2838 }
2839
2840 static void
2841 _edje_box_child_add(Edje_Real_Part *rp, Evas_Object *child)
2842 {
2843    evas_object_event_callback_add
2844      (child, EVAS_CALLBACK_DEL, _edje_box_child_del_cb, rp);
2845
2846    rp->edje->dirty = 1;
2847 #ifdef EDJE_CALC_CACHE
2848    rp->invalidate = 1;
2849 #endif
2850    _edje_recalc(rp->edje);
2851 }
2852
2853 static void
2854 _edje_box_child_remove(Edje_Real_Part *rp, Evas_Object *child)
2855 {
2856    evas_object_event_callback_del_full
2857      (child, EVAS_CALLBACK_DEL, _edje_box_child_del_cb, rp);
2858
2859    rp->edje->dirty = 1;
2860 #ifdef EDJE_CALC_CACHE
2861    rp->invalidate = 1;
2862 #endif
2863    _edje_recalc(rp->edje);
2864 }
2865
2866 Eina_Bool
2867 _edje_real_part_box_append(Edje_Real_Part *rp, Evas_Object *child_obj)
2868 {
2869    Evas_Object_Box_Option *opt;
2870
2871    opt = evas_object_box_append(rp->object, child_obj);
2872    if (!opt) return EINA_FALSE;
2873
2874    if (!_edje_box_layout_add_child(rp, child_obj))
2875      {
2876         evas_object_box_remove(rp->object, child_obj);
2877         return EINA_FALSE;
2878      }
2879
2880    _edje_box_child_add(rp, child_obj);
2881
2882    return EINA_TRUE;
2883 }
2884
2885 Eina_Bool
2886 _edje_real_part_box_prepend(Edje_Real_Part *rp, Evas_Object *child_obj)
2887 {
2888    Evas_Object_Box_Option *opt;
2889
2890    opt = evas_object_box_prepend(rp->object, child_obj);
2891    if (!opt) return EINA_FALSE;
2892
2893    if (!_edje_box_layout_add_child(rp, child_obj))
2894      {
2895         evas_object_box_remove(rp->object, child_obj);
2896         return EINA_FALSE;
2897      }
2898
2899    _edje_box_child_add(rp, child_obj);
2900
2901    return EINA_TRUE;
2902 }
2903
2904 Eina_Bool
2905 _edje_real_part_box_insert_before(Edje_Real_Part *rp, Evas_Object *child_obj, const Evas_Object *ref)
2906 {
2907    Evas_Object_Box_Option *opt;
2908
2909    opt = evas_object_box_insert_before(rp->object, child_obj, ref);
2910    if (!opt) return EINA_FALSE;
2911
2912    if (!_edje_box_layout_add_child(rp, child_obj))
2913      {
2914         evas_object_box_remove(rp->object, child_obj);
2915         return EINA_FALSE;
2916      }
2917
2918    _edje_box_child_add(rp, child_obj);
2919
2920    return EINA_TRUE;
2921 }
2922
2923 Eina_Bool
2924 _edje_real_part_box_insert_at(Edje_Real_Part *rp, Evas_Object *child_obj, unsigned int pos)
2925 {
2926    Evas_Object_Box_Option *opt;
2927
2928    opt = evas_object_box_insert_at(rp->object, child_obj, pos);
2929    if (!opt) return EINA_FALSE;
2930
2931    if (!_edje_box_layout_add_child(rp, child_obj))
2932      {
2933         evas_object_box_remove(rp->object, child_obj);
2934         return EINA_FALSE;
2935      }
2936
2937    _edje_box_child_add(rp, child_obj);
2938
2939    return EINA_TRUE;
2940 }
2941
2942 Evas_Object *
2943 _edje_real_part_box_remove(Edje_Real_Part *rp, Evas_Object *child_obj)
2944 {
2945    if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
2946    if (!evas_object_box_remove(rp->object, child_obj)) return NULL;
2947    _edje_box_layout_remove_child(rp, child_obj);
2948    _edje_box_child_remove(rp, child_obj);
2949    return child_obj;
2950 }
2951
2952 Evas_Object *
2953 _edje_real_part_box_remove_at(Edje_Real_Part *rp, unsigned int pos)
2954 {
2955    Evas_Object_Box_Option *opt;
2956    Evas_Object_Box_Data *priv;
2957    Evas_Object *child_obj;
2958
2959    priv = evas_object_smart_data_get(rp->object);
2960    opt = eina_list_nth(priv->children, pos);
2961    if (!opt) return NULL;
2962    child_obj = opt->obj;
2963    if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
2964    if (!evas_object_box_remove_at(rp->object, pos)) return NULL;
2965    _edje_box_layout_remove_child(rp, child_obj);
2966    _edje_box_child_remove(rp, child_obj);
2967    return child_obj;
2968 }
2969
2970 Eina_Bool
2971 _edje_real_part_box_remove_all(Edje_Real_Part *rp, Eina_Bool clear)
2972 {
2973    Eina_List *children;
2974    int i = 0;
2975
2976    children = evas_object_box_children_get(rp->object);
2977    while (children)
2978      {
2979         Evas_Object *child_obj = children->data;
2980         if (evas_object_data_get(child_obj, "\377 edje.box_item"))
2981           i++;
2982         else
2983           {
2984              _edje_box_layout_remove_child(rp, child_obj);
2985              _edje_box_child_remove(rp, child_obj);
2986              if (!evas_object_box_remove_at(rp->object, i))
2987                return EINA_FALSE;
2988              if (clear)
2989                evas_object_del(child_obj);
2990           }
2991         children = eina_list_remove_list(children, children);
2992      }
2993    return EINA_TRUE;
2994 }
2995
2996 static void
2997 _edje_table_child_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
2998 {
2999    Edje_Real_Part *rp = data;
3000
3001    rp->edje->dirty = 1;
3002 #ifdef EDJE_CALC_CACHE
3003    rp->invalidate = 1;
3004 #endif
3005    _edje_recalc(rp->edje);
3006 }
3007
3008 static void
3009 _edje_table_child_add(Edje_Real_Part *rp, Evas_Object *child)
3010 {
3011    evas_object_event_callback_add
3012      (child, EVAS_CALLBACK_DEL, _edje_table_child_del_cb, rp);
3013
3014    rp->edje->dirty = 1;
3015 #ifdef EDJE_CALC_CACHE
3016    rp->invalidate = 1;
3017 #endif
3018    _edje_recalc(rp->edje);
3019 }
3020
3021 static void
3022 _edje_table_child_remove(Edje_Real_Part *rp, Evas_Object *child)
3023 {
3024    evas_object_event_callback_del_full
3025      (child, EVAS_CALLBACK_DEL, _edje_table_child_del_cb, rp);
3026
3027    rp->edje->dirty = 1;
3028 #ifdef EDJE_CALC_CACHE
3029    rp->invalidate = 1;
3030 #endif
3031    _edje_recalc(rp->edje);
3032 }
3033
3034 EAPI Evas_Object *
3035 edje_object_part_table_child_get(Evas_Object *obj, const char *part, unsigned int col, unsigned int row)
3036 {
3037    Edje *ed;
3038    Edje_Real_Part *rp;
3039
3040    ed = _edje_fetch(obj);
3041    if ((!ed) || (!part)) return NULL;
3042
3043    rp = _edje_real_part_recursive_get(ed, part);
3044    if (!rp) return NULL;
3045    if (rp->part->type != EDJE_PART_TYPE_TABLE) return NULL;
3046
3047    return evas_object_table_child_get(rp->object, col, row);
3048 }
3049
3050 EAPI Eina_Bool
3051 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)
3052 {
3053    Edje *ed;
3054    Edje_Real_Part *rp;
3055
3056    ed = _edje_fetch(obj);
3057    if ((!ed) || (!part)) return EINA_FALSE;
3058
3059    rp = _edje_real_part_recursive_get(ed, part);
3060    if (!rp) return EINA_FALSE;
3061    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
3062
3063    return _edje_real_part_table_pack(rp, child_obj, col, row, colspan, rowspan);
3064 }
3065
3066 EAPI Eina_Bool
3067 edje_object_part_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child_obj)
3068 {
3069    Edje *ed;
3070    Edje_Real_Part *rp;
3071
3072    ed = _edje_fetch(obj);
3073    if ((!ed) || (!part)) return EINA_FALSE;
3074
3075    rp = _edje_real_part_recursive_get(ed, part);
3076    if (!rp) return EINA_FALSE;
3077    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
3078
3079    return _edje_real_part_table_unpack(rp, child_obj);
3080 }
3081
3082 EAPI Eina_Bool
3083 edje_object_part_table_col_row_size_get(const Evas_Object *obj, const char *part, int *cols, int *rows)
3084 {
3085    Edje *ed;
3086    Edje_Real_Part *rp;
3087
3088    ed = _edje_fetch(obj);
3089    if ((!ed) || (!part)) return EINA_FALSE;
3090
3091    rp = _edje_real_part_recursive_get(ed, part);
3092    if (!rp) return EINA_FALSE;
3093    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
3094
3095    evas_object_table_col_row_size_get(rp->object, cols, rows);
3096    return EINA_TRUE;
3097 }
3098
3099 EAPI Eina_Bool
3100 edje_object_part_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear)
3101 {
3102    Edje *ed;
3103    Edje_Real_Part *rp;
3104
3105    ed = _edje_fetch(obj);
3106    if ((!ed) || (!part)) return EINA_FALSE;
3107
3108    rp = _edje_real_part_recursive_get(ed, part);
3109    if (!rp) return EINA_FALSE;
3110    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
3111
3112    _edje_real_part_table_clear(rp, clear);
3113    return EINA_TRUE;
3114 }
3115
3116 static void
3117 _edje_perspective_obj_del(void *data, __UNUSED__ Evas *e, __UNUSED__ Evas_Object *obj, __UNUSED__ void *event_info)
3118 {
3119    Edje_Perspective *ps = data;
3120    Evas_Object *o;
3121
3122    EINA_LIST_FREE(ps->users, o)
3123      {
3124         Edje *ed;
3125
3126         ed = evas_object_smart_data_get(o);
3127         if (!ed) continue;
3128         ed->persp = NULL;
3129         ed->dirty = 1;
3130         _edje_recalc_do(ed);
3131      }
3132    free(ps);
3133 }
3134
3135 EAPI Edje_Perspective *
3136 edje_perspective_new(Evas *e)
3137 {
3138    Edje_Perspective *ps;
3139    Evas_Coord vx, vy, vw, vh;
3140
3141    if (!e) return NULL;
3142    ps = calloc(1, sizeof(Edje_Perspective));
3143    ps->obj = evas_object_rectangle_add(e);
3144    evas_object_data_set(ps->obj, "_edje_perspective", ps);
3145    evas_object_event_callback_add(ps->obj, EVAS_CALLBACK_DEL, _edje_perspective_obj_del, ps);
3146    evas_output_viewport_get(e, &vx, &vy, &vw, &vh);
3147    ps->e = e;
3148    ps->px = vx + (vw / 2);
3149    ps->py = vy + (vh / 2);
3150    ps->z0 = 0;
3151    ps->foc = 1000;
3152    return ps;
3153 }
3154
3155 EAPI void
3156 edje_perspective_free(Edje_Perspective *ps)
3157 {
3158    if (!ps) return;
3159    evas_object_del(ps->obj);
3160 }
3161
3162 EAPI void
3163 edje_perspective_set(Edje_Perspective *ps, Evas_Coord px, Evas_Coord py, Evas_Coord z0, Evas_Coord foc)
3164 {
3165    Eina_List *l;
3166    Evas_Object *o;
3167
3168    if (!ps) return;
3169    if ((ps->px == px) && (ps->py == py) && (ps->z0 == z0) && (ps->foc == foc)) return;
3170    ps->px = px;
3171    ps->py = py;
3172    ps->z0 = z0;
3173    ps->foc = foc;
3174    EINA_LIST_FOREACH(ps->users, l, o)
3175      {
3176         Edje *ed;
3177
3178         ed = evas_object_smart_data_get(o);
3179         if (!ed) continue;
3180         if (!ed->persp)
3181           {
3182              ed->dirty = 1;
3183              _edje_recalc_do(ed);
3184           }
3185      }
3186    if (ps->global)
3187      {
3188         EINA_LIST_FOREACH(_edje_edjes, l, o)
3189           {
3190              Edje *ed;
3191
3192              ed = evas_object_smart_data_get(o);
3193              if (!ed) continue;
3194              if (!ed->persp)
3195                {
3196                   ed->dirty = 1;
3197                   _edje_recalc_do(ed);
3198                }
3199           }
3200      }
3201 }
3202
3203 EAPI void
3204 edje_perspective_global_set(Edje_Perspective *ps, Eina_Bool global)
3205 {
3206    Evas_Object *o;
3207    Eina_List *l;
3208
3209    if (!ps) return;
3210    if (ps->global == global) return;
3211    if (global)
3212      {
3213         o = evas_object_name_find(evas_object_evas_get(ps->obj),
3214                                   "_edje_perspective");
3215         if (o) evas_object_name_set(o, NULL);
3216         evas_object_name_set(ps->obj, "_edje_perspective");
3217      }
3218    else
3219      evas_object_name_set(ps->obj, NULL);
3220    ps->global = global;
3221    EINA_LIST_FOREACH(_edje_edjes, l, o)
3222      {
3223         Edje *ed;
3224
3225         ed = evas_object_smart_data_get(o);
3226         if (!ed) continue;
3227         if (!ed->persp)
3228           {
3229              ed->dirty = 1;
3230              _edje_recalc_do(ed);
3231           }
3232      }
3233 }
3234
3235 EAPI Eina_Bool
3236 edje_perspective_global_get(const Edje_Perspective *ps)
3237 {
3238    if (!ps) return EINA_FALSE;
3239    return ps->global;
3240 }
3241
3242 EAPI const Edje_Perspective *
3243 edje_evas_global_perspective_get(const Evas *e)
3244 {
3245    Evas_Object *obj;
3246
3247    if (!e) return NULL;
3248    obj = evas_object_name_find(e, "_edje_perspective");
3249    if (!obj) return NULL;
3250    return evas_object_data_get(obj, "_edje_perspective");
3251 }
3252
3253 EAPI void
3254 edje_object_perspective_set(Evas_Object *obj, Edje_Perspective *ps)
3255 {
3256    Edje *ed;
3257
3258    ed = evas_object_smart_data_get(obj);
3259    if (!ed) return;
3260    if (ed->persp == ps) return;
3261    if (ed->persp != ps)
3262      {
3263         if (ed->persp)
3264           ed->persp->users = eina_list_remove(ed->persp->users, obj);
3265      }
3266    ed->persp = ps;
3267    if (ps) ps->users = eina_list_append(ps->users, obj);
3268    ed->dirty = 1;
3269    _edje_recalc_do(ed);
3270 }
3271
3272 EAPI const Edje_Perspective *
3273 edje_object_perspective_get(const Evas_Object *obj)
3274 {
3275    Edje *ed;
3276
3277    ed = evas_object_smart_data_get(obj);
3278    if (!ed) return NULL;
3279    return ed->persp;
3280 }
3281
3282 #define EDJE_PRELOAD_EMISSION "preload,done"
3283 #define EDJE_PRELOAD_SOURCE NULL
3284
3285 EAPI Eina_Bool
3286 edje_object_preload(Evas_Object *obj, Eina_Bool cancel)
3287 {
3288    Edje *ed;
3289    int count;
3290    unsigned int i;
3291
3292    ed = _edje_fetch(obj);
3293    if (!ed) return EINA_FALSE;
3294
3295    _edje_recalc_do(ed);
3296
3297    for (i = 0, count = 0; i < ed->table_parts_size; i++)
3298      {
3299         Edje_Real_Part *rp;
3300         Edje_Part *ep;
3301
3302         rp = ed->table_parts[i];
3303         ep = rp->part;
3304
3305         if (ep->type == EDJE_PART_TYPE_IMAGE ||
3306             (ep->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object))
3307           count++;
3308      }
3309
3310    ed->preload_count = count;
3311
3312    if (count > 0)
3313      {
3314         for (i = 0; i < ed->table_parts_size; i++)
3315           {
3316              Edje_Real_Part *rp;
3317              Edje_Part *ep;
3318
3319              rp = ed->table_parts[i];
3320              ep = rp->part;
3321
3322              if (ep->type == EDJE_PART_TYPE_IMAGE)
3323                {
3324                   const char *file = NULL;
3325                   const char *key = NULL;
3326
3327                   evas_object_event_callback_del_full(rp->object, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
3328
3329                   evas_object_image_file_get(rp->object, &file, &key);
3330                   if (!file && !key)
3331                     {
3332                        ed->preload_count--;
3333                     }
3334                   else
3335                     {
3336                        evas_object_event_callback_add(rp->object, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
3337                        evas_object_image_preload(rp->object, cancel);
3338                     }
3339                   count--;
3340                }
3341              else if (ep->type == EDJE_PART_TYPE_GROUP)
3342                {
3343                   if (rp->swallowed_object) {
3344                      edje_object_signal_callback_del(rp->swallowed_object, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE, _edje_object_signal_preload_cb);
3345                      edje_object_signal_callback_add(rp->swallowed_object, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE, _edje_object_signal_preload_cb, ed);
3346                      edje_object_preload(rp->swallowed_object, cancel);
3347
3348                      count--;
3349                   }
3350                }
3351           }
3352      }
3353    else
3354      {
3355         _edje_emit(ed, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE);
3356      }
3357
3358    return EINA_TRUE;
3359 }
3360
3361 Eina_Bool
3362 _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)
3363 {
3364    Eina_Bool ret =
3365      evas_object_table_pack(rp->object, child_obj, col, row, colspan, rowspan);
3366
3367    _edje_table_child_add(rp, child_obj);
3368
3369    return ret;
3370 }
3371
3372 Eina_Bool
3373 _edje_real_part_table_unpack(Edje_Real_Part *rp, Evas_Object *child_obj)
3374 {
3375    Eina_Bool ret = evas_object_table_unpack(rp->object, child_obj);
3376
3377    if (ret)
3378      _edje_table_child_remove(rp, child_obj);
3379
3380    return ret;
3381 }
3382
3383 void
3384 _edje_real_part_table_clear(Edje_Real_Part *rp, Eina_Bool clear)
3385 {
3386    Eina_List *children;
3387
3388    children = evas_object_table_children_get(rp->object);
3389    while (children)
3390      {
3391         Evas_Object *child_obj = children->data;
3392
3393         _edje_table_child_remove(rp, child_obj);
3394         if (!evas_object_data_get(child_obj, "\377 edje.table_item"))
3395           {
3396              evas_object_table_unpack(rp->object, child_obj);
3397              if (clear)
3398                evas_object_del(child_obj);
3399           }
3400         children = eina_list_remove_list(children, children);
3401      }
3402 }
3403
3404 Edje_Real_Part *
3405 _edje_real_part_recursive_get(const Edje *ed, const char *part)
3406 {
3407    Edje_Real_Part *rp;
3408    char **path;
3409
3410    path = eina_str_split(part, EDJE_PART_PATH_SEPARATOR_STRING, 0);
3411    if (!path) return NULL;
3412
3413    rp = _edje_real_part_recursive_get_helper(ed, path);
3414
3415    free(*path);
3416    free(path);
3417    return rp;
3418 }
3419
3420 Evas_Object *
3421 _edje_children_get(Edje_Real_Part *rp, const char *partid)
3422 {
3423    Evas_Object *child;
3424    Eina_List *l;
3425    long int v;
3426    char *p;
3427
3428    if (!partid) return NULL;
3429
3430    switch (rp->part->type)
3431      {
3432       case EDJE_PART_TYPE_EXTERNAL:
3433          return _edje_external_content_get(rp->swallowed_object, partid);
3434       case EDJE_PART_TYPE_BOX:
3435          l = evas_object_box_children_get(rp->object);
3436          break;
3437       case EDJE_PART_TYPE_TABLE:
3438          l = evas_object_table_children_get(rp->object);
3439          break;
3440       default:
3441          return NULL;
3442      }
3443
3444    v = strtol(partid, &p, 10);
3445    if ((*p == '\0') && (v >= 0))
3446      {
3447         child = eina_list_nth(l, v);
3448      }
3449    else
3450      {
3451         Evas_Object *cur;
3452         child = NULL;
3453         EINA_LIST_FREE(l, cur)
3454           {
3455              const char *name = evas_object_name_get(cur);
3456              if ((name) && (!strcmp(name, partid)))
3457                {
3458                   child = cur;
3459                   break;
3460                }
3461           }
3462      }
3463    eina_list_free(l);
3464
3465    return child;
3466 }
3467
3468 /* rebuild alternative path */
3469 char *
3470 _edje_merge_path(const char *alias, char * const *path)
3471 {
3472    char *tmp;
3473    unsigned int length = 1;
3474    unsigned int alias_length;
3475    unsigned int i;
3476
3477    if (!alias) return NULL;
3478
3479    alias_length = strlen(alias);
3480
3481    for (i = 0; path[i]; i++)
3482      length += strlen(path[i]) + 1;
3483
3484    tmp = malloc(sizeof (char) * (length + alias_length + 2));
3485    memcpy(tmp, alias, alias_length);
3486    tmp[alias_length] = '\0';
3487
3488    for (i = 0; path[i]; i++)
3489      {
3490         strcat(tmp, EDJE_PART_PATH_SEPARATOR_STRING);
3491         strcat(tmp, path[i]);
3492      }
3493
3494    return tmp;
3495 }
3496
3497
3498 Edje_Real_Part *
3499 _edje_real_part_recursive_get_helper(const Edje *ed, char **path)
3500 {
3501    Edje_Real_Part *rp;
3502    Evas_Object *child;
3503    char *idx = NULL;
3504
3505    if (!path[0])
3506      return NULL;
3507
3508    if (ed->collection && ed->collection->alias)
3509      {
3510         char *alias;
3511
3512         alias = _edje_merge_path(eina_hash_find(ed->collection->alias, path[0]), path + 1);
3513         if (alias) {
3514            rp = _edje_real_part_recursive_get(ed, alias);
3515            free(alias);
3516            return rp;
3517         }
3518      }
3519
3520    //printf("  lookup: %s on %s\n", path[0], ed->parent ? ed->parent : "-");
3521    idx = strchr(path[0], EDJE_PART_PATH_SEPARATOR_INDEXL);
3522    if (idx)
3523      {
3524         char *end;
3525
3526         end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
3527         if (end)
3528           {
3529              *end = '\0';
3530              *idx = '\0';
3531              idx++;
3532           }
3533      }
3534
3535    rp = _edje_real_part_get(ed, path[0]);
3536    if (!path[1] && !idx) return rp;
3537    if (!rp) return NULL;
3538
3539    switch (rp->part->type)
3540      {
3541       case EDJE_PART_TYPE_GROUP:
3542          if (!rp->swallowed_object) return NULL;
3543          ed = _edje_fetch(rp->swallowed_object);
3544          if (!ed) return NULL;
3545          path++;
3546          return _edje_real_part_recursive_get_helper(ed, path);
3547       case EDJE_PART_TYPE_BOX:
3548       case EDJE_PART_TYPE_TABLE:
3549       case EDJE_PART_TYPE_EXTERNAL:
3550          if (!idx) return rp;
3551          path++;
3552
3553          child = _edje_children_get(rp, idx);
3554
3555          ed = _edje_fetch(child);
3556
3557          if (!ed) return NULL;
3558          return _edje_real_part_recursive_get_helper(ed, path);
3559       default:
3560          return NULL;
3561      }
3562 }
3563
3564 /* Private Routines */
3565 Edje_Real_Part *
3566 _edje_real_part_get(const Edje *ed, const char *part)
3567 {
3568    unsigned int i;
3569
3570    if (!part) return NULL;
3571
3572    for (i = 0; i < ed->table_parts_size; i++)
3573      {
3574         Edje_Real_Part *rp;
3575
3576         rp = ed->table_parts[i];
3577         if ((rp->part->name) && (!strcmp(rp->part->name, part))) return rp;
3578      }
3579    return NULL;
3580 }
3581
3582 Edje_Color_Class *
3583 _edje_color_class_find(Edje *ed, const char *color_class)
3584 {
3585    Eina_List *l;
3586    Edje_Color_Class *cc = NULL;
3587
3588    if ((!ed) || (!color_class)) return NULL;
3589
3590    /* first look through the object scope */
3591    EINA_LIST_FOREACH(ed->color_classes, l, cc)
3592      if ((cc->name) && (!strcmp(color_class, cc->name))) return cc;
3593
3594    /* next look through the global scope */
3595    cc = eina_hash_find(_edje_color_class_hash, color_class);
3596    if (cc) return cc;
3597
3598    /* finally, look through the file scope */
3599    EINA_LIST_FOREACH(ed->file->color_classes, l, cc)
3600      if ((cc->name) && (!strcmp(color_class, cc->name))) return cc;
3601
3602    return NULL;
3603 }
3604
3605 void
3606 _edje_color_class_member_add(Edje *ed, const char *color_class)
3607 {
3608    Eina_List *members;
3609
3610    if ((!ed) || (!color_class)) return;
3611    if (!_edje_color_class_member_hash) _edje_color_class_member_hash = eina_hash_string_superfast_new(NULL);
3612    members = eina_hash_find(_edje_color_class_member_hash, color_class);
3613    if (eina_list_count(members) > 50000)
3614       ERR(EINA_COLOR_RED"E"EINA_COLOR_LIGHTRED"R"EINA_COLOR_ORANGE"R"
3615           EINA_COLOR_YELLOW"R"EINA_COLOR_GREEN"R"EINA_COLOR_CYAN"R"
3616           EINA_COLOR_LIGHTCYAN"R"EINA_COLOR_LIGHTBLUE"R"EINA_COLOR_BLUE"R"
3617           EINA_COLOR_HIGH EINA_COLOR_BLUE"R"EINA_COLOR_RED"R"EINA_COLOR_LIGHTRED"O"
3618           EINA_COLOR_ORANGE"R"EINA_COLOR_YELLOW". "EINA_COLOR_GREEN"C"
3619           EINA_COLOR_CYAN"E"EINA_COLOR_LIGHTCYAN"D"EINA_COLOR_LIGHTBLUE"R"EINA_COLOR_BLUE"I"
3620           EINA_COLOR_RESET"C"EINA_COLOR_RED" B"EINA_COLOR_LIGHTRED"R"EINA_COLOR_ORANGE"O"EINA_COLOR_YELLOW"K"
3621           EINA_COLOR_GREEN"E "EINA_COLOR_CYAN"M"EINA_COLOR_LIGHTCYAN"E"EINA_COLOR_LIGHTBLUE"! "
3622           EINA_COLOR_BLUE"I "EINA_COLOR_HIGH EINA_COLOR_BLUE"N"EINA_COLOR_RED"O"EINA_COLOR_LIGHTRED"W "
3623           EINA_COLOR_ORANGE"L"EINA_COLOR_YELLOW"E"EINA_COLOR_GREEN"A"EINA_COLOR_CYAN"K "EINA_COLOR_LIGHTCYAN"C"
3624           EINA_COLOR_LIGHTBLUE"O"EINA_COLOR_BLUE"L"EINA_COLOR_RESET"O"EINA_COLOR_RED"R"EINA_COLOR_LIGHTRED"C"
3625           EINA_COLOR_ORANGE"L"EINA_COLOR_YELLOW"A"EINA_COLOR_GREEN"S"EINA_COLOR_CYAN"S"EINA_COLOR_LIGHTCYAN"E"
3626           EINA_COLOR_LIGHTBLUE"S");
3627
3628    members = eina_list_prepend(members, ed);
3629    eina_hash_set(_edje_color_class_member_hash, color_class, members);
3630 }
3631
3632 void
3633 _edje_color_class_member_del(Edje *ed, const char *color_class)
3634 {
3635    Eina_List *members;
3636
3637    if ((!ed) || (!color_class)) return;
3638    if (!_edje_color_class_member_hash) return;
3639
3640    members = eina_hash_find(_edje_color_class_member_hash, color_class);
3641    if (!members) return;
3642
3643    members = eina_list_remove(members, ed);
3644    eina_hash_set(_edje_color_class_member_hash, color_class, members);
3645 }
3646
3647 /**
3648  * Used to free the member lists that are stored in the text_class and
3649  * color_class hashtables.
3650  */
3651 static Eina_Bool
3652 member_list_free(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
3653 {
3654    eina_list_free(data);
3655    return EINA_TRUE;
3656 }
3657
3658 void
3659 _edje_color_class_members_free(void)
3660 {
3661    if (!_edje_color_class_member_hash) return;
3662    eina_hash_foreach(_edje_color_class_member_hash, member_list_free, NULL);
3663    eina_hash_free(_edje_color_class_member_hash);
3664    _edje_color_class_member_hash = NULL;
3665 }
3666
3667 static Eina_Bool
3668 color_class_hash_list_free(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
3669 {
3670    Edje_Color_Class *cc;
3671
3672    cc = data;
3673    if (cc->name) eina_stringshare_del(cc->name);
3674    free(cc);
3675    return EINA_TRUE;
3676 }
3677
3678 void
3679 _edje_color_class_hash_free(void)
3680 {
3681    if (!_edje_color_class_hash) return;
3682    eina_hash_foreach(_edje_color_class_hash, color_class_hash_list_free, NULL);
3683    eina_hash_free(_edje_color_class_hash);
3684    _edje_color_class_hash = NULL;
3685 }
3686
3687 void
3688 _edje_color_class_on_del(Edje *ed, Edje_Part *ep)
3689 {
3690    unsigned int i;
3691
3692    if ((ep->default_desc) && (ep->default_desc->color_class))
3693      _edje_color_class_member_del(ed, ep->default_desc->color_class);
3694
3695    for (i = 0; i < ep->other.desc_count; ++i)
3696      if (ep->other.desc[i]->color_class)
3697        _edje_color_class_member_del(ed, ep->other.desc[i]->color_class);
3698 }
3699
3700 Edje_Text_Class *
3701 _edje_text_class_find(Edje *ed, const char *text_class)
3702 {
3703    Eina_List *l;
3704    Edje_Text_Class *tc;
3705
3706    if ((!ed) || (!text_class)) return NULL;
3707    EINA_LIST_FOREACH(ed->text_classes, l, tc)
3708      if ((tc->name) && (!strcmp(text_class, tc->name))) return tc;
3709    return eina_hash_find(_edje_text_class_hash, text_class);
3710 }
3711
3712 void
3713 _edje_text_class_member_direct_del(const char *text_class,
3714                                    Eina_List *lookup)
3715 {
3716    Eina_List *members;
3717
3718    members = eina_hash_find(_edje_text_class_member_hash, text_class);
3719    members = eina_list_remove_list(members, lookup);
3720    eina_hash_set(_edje_text_class_member_hash, text_class, members);
3721 }
3722
3723 void
3724 _edje_text_class_member_add(Edje *ed, const char *text_class)
3725 {
3726    Eina_List *members;
3727
3728    if ((!ed) || (!text_class)) return;
3729
3730    /* Get members list */
3731    members = eina_hash_find(_edje_text_class_member_hash, text_class);
3732
3733    /* Update the member list */
3734    members = eina_list_prepend(members, ed);
3735    if (eina_list_count(members) > 50000)
3736       printf("ERRRRRRRRRROR. CEDRIC BROKE ME! I NOW LEAK TEXTCLASSES\n");
3737
3738    /* Don't loose track of members list */
3739    if (!ed->members)
3740      ed->members = eina_hash_string_small_new(NULL);
3741    eina_hash_set(ed->members, text_class, members);
3742
3743    /* Reset the member list to the right pointer */
3744    if (!_edje_text_class_member_hash)
3745      _edje_text_class_member_hash = eina_hash_string_superfast_new(NULL);
3746    eina_hash_set(_edje_text_class_member_hash, text_class, members);
3747 }
3748
3749 void
3750 _edje_text_class_member_del(Edje *ed, const char *text_class)
3751 {
3752    Eina_List *members;
3753    Eina_List *lookup;
3754
3755    if ((!ed) || (!text_class)) return;
3756    members = eina_hash_find(_edje_text_class_member_hash, text_class);
3757    if (!members) return;
3758
3759    lookup = eina_hash_find(ed->members, text_class);
3760
3761    if (!lookup) return ;
3762
3763    eina_hash_del(ed->members, text_class, lookup);
3764    members = eina_list_remove_list(members, lookup);
3765
3766    eina_hash_set(_edje_text_class_member_hash, text_class, members);
3767 }
3768
3769 void
3770 _edje_text_class_members_free(void)
3771 {
3772    if (!_edje_text_class_member_hash) return;
3773    eina_hash_foreach(_edje_text_class_member_hash, member_list_free, NULL);
3774    eina_hash_free(_edje_text_class_member_hash);
3775    _edje_text_class_member_hash = NULL;
3776 }
3777
3778 static Eina_Bool
3779 text_class_hash_list_free(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
3780 {
3781    Edje_Text_Class *tc;
3782
3783    tc = data;
3784    if (tc->name) eina_stringshare_del(tc->name);
3785    if (tc->font) eina_stringshare_del(tc->font);
3786    free(tc);
3787    return EINA_TRUE;
3788 }
3789
3790 void
3791 _edje_text_class_hash_free(void)
3792 {
3793    if (!_edje_text_class_hash) return;
3794    eina_hash_foreach(_edje_text_class_hash, text_class_hash_list_free, NULL);
3795    eina_hash_free(_edje_text_class_hash);
3796    _edje_text_class_hash = NULL;
3797 }
3798
3799 Edje *
3800 _edje_fetch(const Evas_Object *obj)
3801 {
3802    Edje *ed;
3803
3804    if (!evas_object_smart_type_check(obj, "edje"))
3805      return NULL;
3806    ed = evas_object_smart_data_get(obj);
3807    if ((ed) && (ed->delete_me)) return NULL;
3808    return ed;
3809 }
3810
3811 int
3812 _edje_freeze(Edje *ed)
3813 {
3814    ed->freeze++;
3815 //   printf("FREEZE %i\n", ed->freeze);
3816    return ed->freeze;
3817 }
3818
3819 int
3820 _edje_thaw(Edje *ed)
3821 {
3822    ed->freeze--;
3823    if (ed->freeze < 0)
3824      {
3825 //      printf("-------------########### OVER THAW\n");
3826         ed->freeze = 0;
3827      }
3828    if ((ed->freeze == 0) && (ed->recalc))
3829      {
3830 //      printf("thaw recalc\n");
3831         _edje_recalc(ed);
3832      }
3833    return ed->freeze;
3834 }
3835
3836 int
3837 _edje_block(Edje *ed)
3838 {
3839    _edje_ref(ed);
3840    ed->block++;
3841    return ed->block;
3842 }
3843
3844 int
3845 _edje_unblock(Edje *ed)
3846 {
3847    int ret = 0;
3848
3849    if (!ed) return ret;
3850
3851    ed->block--;
3852    if (ed->block == 0) ed->block_break = 0;
3853    ret = ed->block;
3854    _edje_unref(ed);
3855    return ret;
3856 }
3857
3858 int
3859 _edje_block_break(Edje *ed)
3860 {
3861    if (ed->block_break) return 1;
3862    return 0;
3863 }
3864
3865 void
3866 _edje_block_violate(Edje *ed)
3867 {
3868    if (ed->block > 0) ed->block_break = 1;
3869 }
3870
3871 void
3872 _edje_object_part_swallow_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
3873 {
3874    Evas_Object *edje_obj;
3875
3876    edje_obj = data;
3877    edje_object_part_unswallow(edje_obj, obj);
3878    return;
3879 }
3880
3881 static void
3882 _edje_real_part_swallow_hints_update(Edje_Real_Part *rp)
3883 {
3884    const char *type;
3885
3886    type = evas_object_type_get(rp->swallowed_object);
3887
3888    rp->swallow_params.min.w = 0;
3889    rp->swallow_params.min.h = 0;
3890    rp->swallow_params.max.w = -1;
3891    rp->swallow_params.max.h = -1;
3892    if ((type) && (!strcmp(type, "edje")))
3893      {
3894         Evas_Coord w, h;
3895
3896         edje_object_size_min_get(rp->swallowed_object, &w, &h);
3897         rp->swallow_params.min.w = w;
3898         rp->swallow_params.min.h = h;
3899         edje_object_size_max_get(rp->swallowed_object, &w, &h);
3900         rp->swallow_params.max.w = w;
3901         rp->swallow_params.max.h = h;
3902      }
3903    else if ((type) && ((!strcmp(type, "text")) || (!strcmp(type, "polygon")) ||
3904                        (!strcmp(type, "line"))))
3905      {
3906         Evas_Coord w, h;
3907
3908         evas_object_geometry_get(rp->swallowed_object, NULL, NULL, &w, &h);
3909         rp->swallow_params.min.w = w;
3910         rp->swallow_params.min.h = h;
3911         rp->swallow_params.max.w = w;
3912         rp->swallow_params.max.h = h;
3913      }
3914      {
3915         Evas_Coord w1, h1, w2, h2, aw, ah;
3916         Evas_Aspect_Control am;
3917
3918         evas_object_size_hint_min_get(rp->swallowed_object, &w1, &h1);
3919         evas_object_size_hint_max_get(rp->swallowed_object, &w2, &h2);
3920         evas_object_size_hint_aspect_get(rp->swallowed_object, &am, &aw, &ah);
3921         rp->swallow_params.min.w = w1;
3922         rp->swallow_params.min.h = h1;
3923         if (w2 > 0) rp->swallow_params.max.w = w2;
3924         if (h2 > 0) rp->swallow_params.max.h = h2;
3925         switch (am)
3926           {
3927            case EVAS_ASPECT_CONTROL_NONE:
3928              rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_NONE;
3929              break;
3930            case EVAS_ASPECT_CONTROL_NEITHER:
3931              rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_NEITHER;
3932              break;
3933            case EVAS_ASPECT_CONTROL_HORIZONTAL:
3934              rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_HORIZONTAL;
3935              break;
3936            case EVAS_ASPECT_CONTROL_VERTICAL:
3937              rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_VERTICAL;
3938              break;
3939            case EVAS_ASPECT_CONTROL_BOTH:
3940              rp->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_BOTH;
3941              break;
3942            default:
3943              break;
3944           }
3945         rp->swallow_params.aspect.w = aw;
3946         rp->swallow_params.aspect.h = ah;
3947         evas_object_data_set(rp->swallowed_object, "\377 edje.swallowing_part", rp);
3948      }
3949
3950 #ifdef EDJE_CALC_CACHE
3951      rp->invalidate = 1;
3952 #endif
3953 }
3954
3955 void
3956 _edje_object_part_swallow_changed_hints_cb(void *data, __UNUSED__ Evas *e, __UNUSED__ Evas_Object *obj, __UNUSED__ void *event_info)
3957 {
3958    Edje_Real_Part *rp;
3959
3960    rp = data;
3961    _edje_real_part_swallow_hints_update(rp);
3962    rp->edje->dirty = 1;
3963    _edje_recalc(rp->edje);
3964    return;
3965 }
3966
3967 void
3968 _edje_real_part_swallow(Edje_Real_Part *rp,
3969                         Evas_Object *obj_swallow,
3970                         Eina_Bool hints_update)
3971 {
3972    if (rp->swallowed_object)
3973      {
3974         if (rp->swallowed_object != obj_swallow)
3975           {
3976              _edje_real_part_swallow_clear(rp);
3977              rp->swallowed_object = NULL;
3978           }
3979         else
3980           {
3981              if (hints_update)
3982                _edje_real_part_swallow_hints_update(rp);
3983              rp->edje->dirty = 1;
3984              _edje_recalc(rp->edje);
3985              return;
3986           }
3987      }
3988 #ifdef EDJE_CALC_CACHE
3989    rp->invalidate = 1;
3990 #endif
3991    if (!obj_swallow) return;
3992    rp->swallowed_object = obj_swallow;
3993    evas_object_smart_member_add(rp->swallowed_object, rp->edje->obj);
3994    if (rp->clip_to)
3995      evas_object_clip_set(rp->swallowed_object, rp->clip_to->object);
3996    else evas_object_clip_set(rp->swallowed_object, rp->edje->base.clipper);
3997    evas_object_stack_above(rp->swallowed_object, rp->object);
3998    evas_object_event_callback_add(rp->swallowed_object,
3999                                   EVAS_CALLBACK_FREE,
4000                                   _edje_object_part_swallow_free_cb,
4001                                   rp->edje->obj);
4002    evas_object_event_callback_add(rp->swallowed_object,
4003                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
4004                                   _edje_object_part_swallow_changed_hints_cb,
4005                                   rp);
4006
4007    if (hints_update)
4008      _edje_real_part_swallow_hints_update(rp);
4009
4010    if (rp->part->mouse_events)
4011      {
4012         _edje_callbacks_add(obj_swallow, rp->edje, rp);
4013         if (rp->part->repeat_events)
4014            evas_object_repeat_events_set(obj_swallow, 1);
4015         if (rp->part->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
4016           evas_object_pointer_mode_set(obj_swallow, rp->part->pointer_mode);
4017         evas_object_pass_events_set(obj_swallow, 0);
4018      }
4019    else
4020      evas_object_pass_events_set(obj_swallow, 1);
4021    _edje_callbacks_focus_add(rp->swallowed_object, rp->edje, rp);
4022
4023    if (rp->part->precise_is_inside)
4024      evas_object_precise_is_inside_set(obj_swallow, 1);
4025
4026    rp->edje->dirty = 1;
4027    _edje_recalc(rp->edje);
4028 }
4029
4030 void
4031 _edje_real_part_swallow_clear(Edje_Real_Part *rp)
4032 {
4033    evas_object_smart_member_del(rp->swallowed_object);
4034    evas_object_event_callback_del_full(rp->swallowed_object,
4035                                        EVAS_CALLBACK_FREE,
4036                                        _edje_object_part_swallow_free_cb,
4037                                        rp->edje->obj);
4038    evas_object_event_callback_del_full(rp->swallowed_object,
4039                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
4040                                        _edje_object_part_swallow_changed_hints_cb,
4041                                        rp);
4042    evas_object_clip_unset(rp->swallowed_object);
4043    evas_object_data_del(rp->swallowed_object, "\377 edje.swallowing_part");
4044    if (rp->part->mouse_events)
4045      _edje_callbacks_del(rp->swallowed_object, rp->edje);
4046    _edje_callbacks_focus_del(rp->swallowed_object, rp->edje);
4047 }
4048
4049 static void
4050 _edje_object_preload(Edje *ed)
4051 {
4052    ed->preload_count--;
4053    if (!ed->preload_count)
4054      _edje_emit(ed, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE);
4055 }
4056
4057 static void
4058 _edje_object_image_preload_cb(void *data, __UNUSED__ Evas *e, Evas_Object *obj, __UNUSED__ void *event_info)
4059 {
4060    Edje *ed = data;
4061
4062    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
4063    _edje_object_preload(ed);
4064 }
4065
4066 static void
4067 _edje_object_signal_preload_cb(void *data, Evas_Object *obj, __UNUSED__ const char *emission, __UNUSED__ const char *source)
4068 {
4069    Edje *ed = data;
4070
4071    edje_object_signal_callback_del(obj, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE, _edje_object_signal_preload_cb);
4072    _edje_object_preload(ed);
4073 }
4074
4075 /**
4076  * @internal
4077  * 
4078  * for edje_cc
4079  */
4080 EAPI void
4081 _edje_program_remove(Edje_Part_Collection *edc, Edje_Program *p)
4082 {
4083    Edje_Program ***array;
4084    unsigned int *count;
4085    unsigned int i;
4086
4087    if (!p->signal && !p->source)
4088      {
4089         array = &edc->programs.nocmp;
4090         count = &edc->programs.nocmp_count;
4091      }
4092    else if (p->signal && !strpbrk(p->signal, "*?[\\")
4093             && p->source && !strpbrk(p->source, "*?[\\"))
4094      {
4095         array = &edc->programs.strcmp;
4096         count = &edc->programs.strcmp_count;
4097      }
4098    else if (p->signal && edje_program_is_strncmp(p->signal)
4099             && p->source && edje_program_is_strncmp(p->source))
4100      {
4101         array = &edc->programs.strncmp;
4102         count = &edc->programs.strncmp_count;
4103      }
4104    else if (p->signal && edje_program_is_strrncmp(p->signal)
4105             && p->source && edje_program_is_strrncmp(p->source))
4106      {
4107         array = &edc->programs.strrncmp;
4108         count = &edc->programs.strrncmp_count;
4109      }
4110    else
4111      {
4112         array = &edc->programs.fnmatch;
4113         count = &edc->programs.fnmatch_count;
4114      }
4115
4116    for (i = 0; i < *count; ++i)
4117      if ((*array)[i] == p)
4118        {
4119           memmove(*array + i, *array + i + 1, sizeof (Edje_Program *) * (*count - i -1));
4120           (*count)--;
4121           break;
4122        }
4123 }
4124
4125 /**
4126  * @internal
4127  * 
4128  * for edje_cc
4129  */
4130 EAPI void
4131 _edje_program_insert(Edje_Part_Collection *edc, Edje_Program *p)
4132 {
4133    Edje_Program ***array;
4134    unsigned int *count;
4135
4136    if (!p->signal && !p->source)
4137      {
4138         array = &edc->programs.nocmp;
4139         count = &edc->programs.nocmp_count;
4140      }
4141    else if (p->signal && !strpbrk(p->signal, "*?[\\")
4142             && p->source && !strpbrk(p->source, "*?[\\"))
4143      {
4144         array = &edc->programs.strcmp;
4145         count = &edc->programs.strcmp_count;
4146      }
4147    else if (p->signal && edje_program_is_strncmp(p->signal)
4148             && p->source && edje_program_is_strncmp(p->source))
4149      {
4150         array = &edc->programs.strncmp;
4151         count = &edc->programs.strncmp_count;
4152      }
4153    else if (p->signal && edje_program_is_strrncmp(p->signal)
4154             && p->source && edje_program_is_strrncmp(p->source))
4155      {
4156         array = &edc->programs.strrncmp;
4157         count = &edc->programs.strrncmp_count;
4158      }
4159    else
4160      {
4161         array = &edc->programs.fnmatch;
4162         count = &edc->programs.fnmatch_count;
4163      }
4164
4165    *array = realloc(*array, sizeof (Edje_Program *) * (*count + 1));
4166    (*array)[(*count)++] = p;
4167 }
4168
4169 const char *
4170 edje_string_get(const Edje_String *es)
4171 {
4172    /* FIXME: Handle localization here */
4173    if (!es) return NULL;
4174    return es->str;
4175 }
4176
4177 const char *
4178 edje_string_id_get(const Edje_String *es)
4179 {
4180    /* FIXME: Handle localization here */
4181    if (!es) return NULL;
4182    return es->str;
4183 }
4184
4185
4186 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/