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