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