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