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