1 #include "edje_private.h"
2 
3 #include "../evas/canvas/evas_box_eo.h"
4 #include "../evas/canvas/evas_line_eo.h"
5 #include "../evas/canvas/evas_text_eo.h"
6 
7 //In implementations that gets properties for user-created edje,
8 //edje calculation should be performed regardless of the size of edje.
9 #define EDJE_RECALC_DO(ed) \
10    do { \
11      Eina_Bool calc_flag = EINA_FALSE; \
12      if (!ed->has_size) \
13        { \
14           ed->has_size = EINA_TRUE; \
15           calc_flag = EINA_TRUE; \
16        } \
17      _edje_recalc_do(ed); \
18      if (calc_flag) ed->has_size = EINA_FALSE; \
19    } while (0)
20 
21 typedef struct _Edje_Box_Layout Edje_Box_Layout;
22 struct _Edje_Box_Layout
23 {
24    EINA_RBTREE;
25    Evas_Object_Box_Layout func;
26    void                  *(*layout_data_get)(void *);
27    void                   (*layout_data_free)(void *);
28    void                  *data;
29    void                   (*free_data)(void *);
30    char                   name[];
31 };
32 
33 static Eina_Hash *_edje_color_class_hash = NULL;
34 static Eina_Hash *_edje_text_class_hash = NULL;
35 static Eina_Hash *_edje_size_class_hash = NULL;
36 
37 Efl_Observable *_edje_color_class_member = NULL;
38 Efl_Observable *_edje_text_class_member = NULL;
39 Efl_Observable *_edje_size_class_member = NULL;
40 
41 static Eina_Rbtree *_edje_box_layout_registry = NULL;
42 
43 char *_edje_fontset_append = NULL;
44 char *_edje_fontset_append_escaped = NULL;
45 FLOAT_T _edje_scale = ZERO;
46 Eina_Bool _edje_password_show_last = EINA_FALSE;
47 double _edje_password_show_last_timeout = 0;
48 int _edje_util_freeze_val = 0;
49 int _edje_util_freeze_calc_count = 0;
50 Eina_List *_edje_util_freeze_calc_list = NULL;
51 
52 const char *_edje_language = NULL;
53 const char *_edje_cache_path = NULL;
54 
55 typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data;
56 struct _Edje_List_Foreach_Data
57 {
58    Eina_List *list;
59 };
60 
61 typedef struct _Edje_Refcount Edje_Refcount;
62 struct _Edje_Refcount
63 {
64    EINA_REFCOUNT;
65 
66    Edje *ed;
67 };
68 
69 static Eina_Bool _edje_color_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
70 static Eina_Bool _edje_text_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
71 static Eina_Bool _edje_size_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
72 static void      _edje_object_image_preload_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
73 static void      _edje_object_signal_preload_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
74 static void      _edje_user_def_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *child EINA_UNUSED, void *einfo EINA_UNUSED);
75 static void      _edje_child_remove(Edje *ed, Edje_Real_Part *rp, Evas_Object *child);
76 
77 Edje_Real_Part  *_edje_real_part_recursive_get_helper(Edje **ed, char **path);
78 
79 static void
_edje_user_definition_free_internal(Edje_User_Defined * eud)80 _edje_user_definition_free_internal(Edje_User_Defined *eud)
81 {
82    Evas_Object *child = NULL;
83    switch (eud->type)
84      {
85       case EDJE_USER_SWALLOW:
86         child = eud->u.swallow.child;
87         break;
88 
89       case EDJE_USER_BOX_PACK:
90         child = eud->u.box.child;
91         break;
92 
93       case EDJE_USER_TABLE_PACK:
94         child = eud->u.table.child;
95         break;
96 
97       default: break;
98      }
99    if (child) evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
100    eina_stringshare_del(eud->part);
101    free(eud);
102 }
103 
104 static void
_edje_user_definition_list_free_internal(Eina_List * l)105 _edje_user_definition_list_free_internal(Eina_List *l)
106 {
107    Edje_User_Defined *eud;
108    EINA_LIST_FREE(l, eud)
109      _edje_user_definition_free_internal(eud);
110 }
111 
112 static Edje_User_Defined *
_edje_user_definition_new(Edje_User_Defined_Type type,const char * part,Edje * ed)113 _edje_user_definition_new(Edje_User_Defined_Type type, const char *part, Edje *ed)
114 {
115    Edje_User_Defined *eud;
116 
117    if (!ed->user_defined)
118      ed->user_defined = eina_hash_string_superfast_new((Eina_Free_Cb)_edje_user_definition_list_free_internal);
119    EINA_SAFETY_ON_NULL_RETURN_VAL(ed->user_defined, NULL);
120 
121    eud = malloc(sizeof (Edje_User_Defined));
122    if (!eud) return NULL;
123 
124    eud->type = type;
125    eud->part = eina_stringshare_add(part);
126    eud->ed = ed;
127    eina_hash_list_direct_append(ed->user_defined, eud->part, eud);
128 
129    return eud;
130 }
131 
132 void
_edje_user_definition_free(Edje_User_Defined * eud)133 _edje_user_definition_free(Edje_User_Defined *eud)
134 {
135    Edje_Real_Part *rp;
136 
137    switch (eud->type)
138      {
139       case EDJE_USER_SWALLOW:
140         rp = _edje_real_part_recursive_get(&eud->ed, eud->part);
141         if (rp)
142           {
143              _edje_real_part_swallow_clear(eud->ed, rp);
144              if ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
145                  (rp->typedata.swallow))
146                {
147                   rp->typedata.swallow->swallowed_object = NULL;
148                   rp->typedata.swallow->swallow_params.min.w = 0;
149                   rp->typedata.swallow->swallow_params.min.h = 0;
150                   rp->typedata.swallow->swallow_params.max.w = 0;
151                   rp->typedata.swallow->swallow_params.max.h = 0;
152                }
153              eud->ed->dirty = EINA_TRUE;
154              eud->ed->recalc_call = EINA_TRUE;
155 #ifdef EDJE_CALC_CACHE
156              rp->invalidate = EINA_TRUE;
157 #endif
158              /* this seems to be as unnecessary as the one in part_unswallow()
159               * cedric, 1 February 2016
160               */
161              // _edje_recalc_do(eud->ed);
162           }
163         break;
164 
165       case EDJE_USER_BOX_PACK:
166         rp = _edje_real_part_recursive_get(&eud->ed, eud->part);
167         if (rp) _edje_child_remove(eud->ed, rp, eud->u.box.child);
168         break;
169 
170       case EDJE_USER_TABLE_PACK:
171         rp = _edje_real_part_recursive_get(&eud->ed, eud->part);
172         if (rp) _edje_child_remove(eud->ed, rp, eud->u.table.child);
173         break;
174 
175       case EDJE_USER_TEXT_STYLE:
176       {
177          Edje_Part_Text_Prop *prop;
178          EINA_LIST_FREE(eud->u.text_style.props, prop)
179            {
180               free(prop);
181            }
182          break;
183       }
184 
185       case EDJE_USER_STRING:
186       case EDJE_USER_DRAG_STEP:
187       case EDJE_USER_DRAG_PAGE:
188       case EDJE_USER_DRAG_VALUE:
189       case EDJE_USER_DRAG_SIZE:
190       case EDJE_USER_TEXT_EXPAND:
191         break;
192      }
193 
194    /* edje may be destructing */
195    if (eud->ed->user_defined) eina_hash_list_remove(eud->ed->user_defined, eud->part, eud);
196    _edje_user_definition_free_internal(eud);
197 }
198 
199 static void
_edje_user_def_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * child EINA_UNUSED,void * einfo EINA_UNUSED)200 _edje_user_def_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *child EINA_UNUSED, void *einfo EINA_UNUSED)
201 {
202    Edje_User_Defined *eud = data;
203 
204    _edje_user_definition_free(eud);
205 }
206 
207 /************************** API Routines **************************/
208 
209 #define FASTFREEZE 1
210 
211 EAPI void
edje_freeze(void)212 edje_freeze(void)
213 {
214 #ifdef FASTFREEZE
215    _edje_util_freeze_val++;
216 #else
217 // FIXME: could just have a global freeze instead of per object
218 // above i tried.. but this broke some things. notable e17's menus. why?
219    Edje *ed;
220 
221    EINA_INLIST_FOREACH(_edje_edjes, ed) edje_object_freeze(ed->obj);
222 #endif
223 }
224 
225 #ifdef FASTFREEZE
226 static void
_edje_util_thaw_edje(Edje * ed)227 _edje_util_thaw_edje(Edje *ed)
228 {
229    unsigned short i;
230 
231    for (i = 0; i < ed->table_parts_size; i++)
232      {
233         Edje_Real_Part *rp;
234 
235         rp = ed->table_parts[i];
236         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
237             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
238              (rp->typedata.swallow)) &&
239             (rp->typedata.swallow->swallowed_object))
240           {
241              Edje *ed2;
242 
243              ed2 = _edje_fetch(rp->typedata.swallow->swallowed_object);
244              if (ed2) _edje_util_thaw_edje(ed2);
245           }
246      }
247    if ((ed->recalc) && (ed->freeze == 0)) _edje_recalc_do(ed);
248 }
249 
250 #endif
251 
252 void
_edje_language_signal_emit(Edje * ed,Evas_Object * obj,char * signal)253 _edje_language_signal_emit(Edje *ed, Evas_Object *obj, char *signal)
254 {
255    unsigned short i;
256 
257    for (i = 0; i < ed->table_parts_size; i++)
258      {
259         Edje_Real_Part *rp = ed->table_parts[i];
260 
261         if (rp->part->type == EDJE_PART_TYPE_TEXT ||
262             rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
263           {
264              Edje_Part_Description_Text *text;
265 
266              text = (Edje_Part_Description_Text *)rp->param1.description;
267              if (text->text.text.translated)
268                text->text.text.translated = NULL;
269 
270              if (rp->param2)
271                {
272                   text = (Edje_Part_Description_Text *)rp->param2->description;
273                   if (text->text.text.translated)
274                     text->text.text.translated = NULL;
275                }
276 
277              if (rp->custom)
278                {
279                   text = (Edje_Part_Description_Text *)rp->custom->description;
280                   if (text->text.text.translated)
281                     text->text.text.translated = NULL;
282                }
283           }
284      }
285    edje_object_signal_emit(obj, signal, "edje");
286    edje_object_calc_force(obj);
287 }
288 
289 EOLIAN void
_efl_canvas_layout_efl_ui_i18n_language_set(Eo * obj,Edje * ed,const char * locale)290 _efl_canvas_layout_efl_ui_i18n_language_set(Eo *obj, Edje *ed, const char *locale)
291 {
292    const char *lookup;
293    char *signal;
294    size_t length;
295 
296    if (!locale) return;
297    lookup = strstr(locale, ".");
298    length = lookup ? (size_t)(lookup - locale) : strlen(locale);
299 
300    eina_stringshare_replace_length(&ed->language, locale, length);
301 
302    signal = alloca(length + 15);
303    if (ed->language)
304      snprintf(signal, length + 15, "edje,language,%s", ed->language);
305    else
306      snprintf(signal, length + 15, "edje,language,%s", "none");
307 
308    _edje_language_signal_emit(ed, obj, signal);
309 }
310 
311 EOLIAN const char *
_efl_canvas_layout_efl_ui_i18n_language_get(const Eo * obj EINA_UNUSED,Edje * ed)312 _efl_canvas_layout_efl_ui_i18n_language_get(const Eo *obj EINA_UNUSED, Edje *ed)
313 {
314    if (!ed->language)
315      return _edje_language;
316 
317    return ed->language;
318 }
319 
320 EAPI void
edje_language_set(const char * locale)321 edje_language_set(const char *locale)
322 {
323    Edje *ed;
324    const char *lookup;
325    char *signal;
326    char *loc;
327    int length;
328 
329    if (!locale) return;
330    lookup = strstr(locale, ".");
331    length = lookup ? lookup - locale : (int)strlen(locale);
332    loc = alloca(length + 1);
333    memcpy(loc, locale, length);
334    loc[length] = '\0';
335 
336    eina_stringshare_replace(&_edje_language, loc);
337 
338    signal = alloca(length + 15);
339    snprintf(signal, length + 15, "edje,language,%s", loc);
340 
341    EINA_INLIST_FOREACH(_edje_edjes, ed)
342      {
343         if (ed->language) continue;
344         _edje_language_signal_emit(ed, ed->obj, signal);
345      }
346 }
347 
348 EAPI void
edje_thaw(void)349 edje_thaw(void)
350 {
351 #ifdef FASTFREEZE
352    if (!_edje_util_freeze_val) return;
353    _edje_util_freeze_val--;
354    if ((_edje_util_freeze_val == 0) && (_edje_util_freeze_calc_count > 0))
355      {
356         Edje *ed;
357 
358         _edje_util_freeze_calc_count = 0;
359         EINA_LIST_FREE(_edje_util_freeze_calc_list, ed)
360           {
361              _edje_util_thaw_edje(ed);
362              ed->freeze_calc = EINA_FALSE;
363           }
364      }
365 #else
366    Edje *ed;
367 
368    EINA_INLIST_FOREACH(_edje_edjes, ed) edje_object_thaw(ed->obj);
369 #endif
370 }
371 
372 EAPI void
edje_fontset_append_set(const char * fonts)373 edje_fontset_append_set(const char *fonts)
374 {
375    if (_edje_fontset_append)
376      {
377         free(_edje_fontset_append);
378         free(_edje_fontset_append_escaped);
379      }
380    _edje_fontset_append = fonts ? strdup(fonts) : NULL;
381    _edje_fontset_append_escaped = fonts ? eina_str_escape(fonts) : NULL;
382 }
383 
384 EAPI const char *
edje_fontset_append_get(void)385 edje_fontset_append_get(void)
386 {
387    return _edje_fontset_append;
388 }
389 
390 EAPI void
edje_scale_set(double scale)391 edje_scale_set(double scale)
392 {
393    Edje *ed;
394 
395    if (EQ(_edje_scale, FROM_DOUBLE(scale))) return;
396    _edje_scale = FROM_DOUBLE(scale);
397    EINA_INLIST_FOREACH(_edje_edjes, ed) edje_object_calc_force(ed->obj);
398 }
399 
400 EAPI double
edje_scale_get(void)401 edje_scale_get(void)
402 {
403    return TO_DOUBLE(_edje_scale);
404 }
405 
406 EAPI void
edje_password_show_last_set(Eina_Bool password_show_last)407 edje_password_show_last_set(Eina_Bool password_show_last)
408 {
409    if (_edje_password_show_last == password_show_last) return;
410    _edje_password_show_last = password_show_last;
411 }
412 
413 EAPI void
edje_password_show_last_timeout_set(double password_show_last_timeout)414 edje_password_show_last_timeout_set(double password_show_last_timeout)
415 {
416    if (EINA_DBL_EQ(_edje_password_show_last_timeout, password_show_last_timeout)) return;
417    _edje_password_show_last_timeout = password_show_last_timeout;
418 }
419 
420 EOLIAN void
_efl_canvas_layout_efl_gfx_entity_scale_set(Eo * obj EINA_UNUSED,Edje * ed,double scale)421 _efl_canvas_layout_efl_gfx_entity_scale_set(Eo *obj EINA_UNUSED, Edje *ed, double scale)
422 {
423    Edje *ged;
424    Evas_Object *o;
425    Eina_List *l;
426    unsigned short i;
427 
428    if (EQ(ed->scale, FROM_DOUBLE(scale))) return;
429    ed->scale = FROM_DOUBLE(scale);
430    EINA_LIST_FOREACH(ed->groups, l, ged)
431      edje_object_scale_set(ged->obj, scale);
432    for (i = 0; i < ed->table_parts_size; i++)
433      {
434         Edje_Real_Part *ep;
435         ep = ed->table_parts[i];
436         if ((ep->part->type == EDJE_PART_TYPE_BOX) ||
437             (ep->part->type == EDJE_PART_TYPE_TABLE))
438           {
439              EINA_LIST_FOREACH(ep->typedata.container->items, l, o)
440                edje_object_scale_set(o, scale);
441           }
442      }
443    _edje_recalc(ed);
444 }
445 
446 EOLIAN double
_efl_canvas_layout_efl_gfx_entity_scale_get(const Eo * obj EINA_UNUSED,Edje * ed)447 _efl_canvas_layout_efl_gfx_entity_scale_get(const Eo *obj EINA_UNUSED, Edje *ed)
448 {
449    return TO_DOUBLE(ed->scale);
450 }
451 
452 EAPI double
edje_object_base_scale_get(const Evas_Object * obj)453 edje_object_base_scale_get(const Evas_Object *obj)
454 {
455    Edje *ed;
456 
457    ed = _edje_fetch(obj);
458    if (!ed || !ed->file) return 1.0;
459    return TO_DOUBLE(ed->file->base_scale);
460 }
461 
462 EOLIAN Eina_Bool
_efl_canvas_layout_efl_ui_i18n_mirrored_get(const Eo * obj EINA_UNUSED,Edje * ed)463 _efl_canvas_layout_efl_ui_i18n_mirrored_get(const Eo *obj EINA_UNUSED, Edje *ed)
464 {
465    return ed->is_rtl;
466 }
467 
468 void
_edje_object_orientation_inform(Evas_Object * obj)469 _edje_object_orientation_inform(Evas_Object *obj)
470 {
471    if (!obj) return;
472    if (edje_object_mirrored_get(obj))
473      edje_object_signal_emit(obj, "edje,state,rtl", "edje");
474    else
475      edje_object_signal_emit(obj, "edje,state,ltr", "edje");
476 }
477 
478 EOLIAN void
_efl_canvas_layout_efl_ui_i18n_mirrored_set(Eo * obj,Edje * ed,Eina_Bool rtl)479 _efl_canvas_layout_efl_ui_i18n_mirrored_set(Eo *obj, Edje *ed, Eina_Bool rtl)
480 {
481    unsigned short i;
482 
483    if (ed->is_rtl == rtl) return;
484 
485    ed->is_rtl = rtl;
486 
487    for (i = 0; i < ed->table_parts_size; i++)
488      {
489         Edje_Real_Part *ep;
490         const char *s;
491         double v;
492 
493         ep = ed->table_parts[i];
494         s = ep->param1.description->state.name,
495         v = ep->param1.description->state.value;
496         _edje_part_description_apply(ed, ep, s, v, NULL, 0.0);
497         ep->chosen_description = ep->param1.description;
498      }
499    if (!ed->freeze) _edje_recalc_do(ed);
500 
501    _edje_object_orientation_inform(obj);
502 
503    return;
504 }
505 
506 EOLIAN const char *
_efl_canvas_layout_efl_layout_group_group_data_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * key)507 _efl_canvas_layout_efl_layout_group_group_data_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *key)
508 {
509    if (!key) return NULL;
510    if (!ed->collection) return NULL;
511    if (!ed->collection->data) return NULL;
512 
513    return edje_string_get(eina_hash_find(ed->collection->data, key));
514 }
515 
516 EOLIAN int
_efl_canvas_layout_efl_layout_calc_calc_freeze(Eo * obj EINA_UNUSED,Edje * ed)517 _efl_canvas_layout_efl_layout_calc_calc_freeze(Eo *obj EINA_UNUSED, Edje *ed)
518 {
519    unsigned short i;
520 
521    for (i = 0; i < ed->table_parts_size; i++)
522      {
523         Edje_Real_Part *rp;
524         rp = ed->table_parts[i];
525         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
526             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
527              (rp->typedata.swallow)) &&
528             (rp->typedata.swallow->swallowed_object))
529           edje_object_freeze(rp->typedata.swallow->swallowed_object);
530      }
531    return _edje_util_freeze(ed);
532 }
533 
534 EOLIAN int
_efl_canvas_layout_efl_layout_calc_calc_thaw(Eo * obj EINA_UNUSED,Edje * ed)535 _efl_canvas_layout_efl_layout_calc_calc_thaw(Eo *obj EINA_UNUSED, Edje *ed)
536 {
537    unsigned short i;
538 
539    for (i = 0; i < ed->table_parts_size; i++)
540      {
541         Edje_Real_Part *rp;
542 
543         rp = ed->table_parts[i];
544         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
545             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
546              (rp->typedata.swallow)) &&
547             (rp->typedata.swallow->swallowed_object))
548           edje_object_thaw(rp->typedata.swallow->swallowed_object);
549      }
550    return _edje_util_thaw(ed);
551 }
552 
553 static Eina_Bool
_edje_color_class_set_internal(Eina_Hash * hash,const char * color_class,Efl_Gfx_Color_Class_Layer layer,int r,int g,int b,int a,Eina_Bool * need_update)554 _edje_color_class_set_internal(Eina_Hash *hash, const char *color_class, Efl_Gfx_Color_Class_Layer layer, int r, int g, int b, int a, Eina_Bool *need_update)
555 {
556    Edje_Color_Class *cc;
557 
558    if (!color_class)
559      return EINA_FALSE;
560 
561    if (r < 0) r = 0;
562    else if (r > 255)
563      r = 255;
564    if (g < 0) g = 0;
565    else if (g > 255)
566      g = 255;
567    if (b < 0) b = 0;
568    else if (b > 255)
569      b = 255;
570    if (a < 0) a = 0;
571    else if (a > 255)
572      a = 255;
573 
574    cc = eina_hash_find(hash, color_class);
575    if (cc)
576      {
577         switch (layer)
578           {
579            case EFL_GFX_COLOR_CLASS_LAYER_NORMAL:
580              if ((cc->r == r) && (cc->g == g) &&
581                  (cc->b == b) && (cc->a == a))
582                {
583                   *need_update = EINA_FALSE;
584                   return EINA_TRUE;
585                }
586              break;
587 
588            case EFL_GFX_COLOR_CLASS_LAYER_OUTLINE:
589              if ((cc->r2 == r) && (cc->g2 == g) &&
590                  (cc->b2 == b) && (cc->a2 == a))
591                {
592                   *need_update = EINA_FALSE;
593                   return EINA_TRUE;
594                }
595              break;
596 
597            case EFL_GFX_COLOR_CLASS_LAYER_SHADOW:
598              if ((cc->r3 == r) && (cc->g3 == g) &&
599                  (cc->b3 == b) && (cc->a3 == a))
600                {
601                   *need_update = EINA_FALSE;
602                   return EINA_TRUE;
603                }
604              break;
605 
606            default:
607              return EINA_FALSE;
608           }
609      }
610    else
611      {
612         cc = calloc(1, sizeof(Edje_Color_Class));
613         if (!cc) return EINA_FALSE;
614 
615         cc->name = eina_stringshare_add(color_class);
616         if (!cc->name)
617           {
618              free(cc);
619              return EINA_FALSE;
620           }
621 
622         eina_hash_direct_add(hash, cc->name, cc);
623      }
624 
625    switch (layer)
626      {
627       case EFL_GFX_COLOR_CLASS_LAYER_NORMAL:
628         cc->r = r;
629         cc->g = g;
630         cc->b = b;
631         cc->a = a;
632         break;
633 
634       case EFL_GFX_COLOR_CLASS_LAYER_OUTLINE:
635         cc->r2 = r;
636         cc->g2 = g;
637         cc->b2 = b;
638         cc->a2 = a;
639         break;
640 
641       case EFL_GFX_COLOR_CLASS_LAYER_SHADOW:
642         cc->r3 = r;
643         cc->g3 = g;
644         cc->b3 = b;
645         cc->a3 = a;
646         break;
647     }
648 
649    *need_update = EINA_TRUE;
650 
651    return EINA_TRUE;
652 }
653 
654 static Eina_Bool
_edje_color_class_get_internal(Edje_Color_Class * cc,Efl_Gfx_Color_Class_Layer layer,int * r,int * g,int * b,int * a)655 _edje_color_class_get_internal(Edje_Color_Class *cc, Efl_Gfx_Color_Class_Layer layer, int *r, int *g, int *b, int *a)
656 {
657    if (cc)
658      {
659         switch (layer)
660           {
661            case EFL_GFX_COLOR_CLASS_LAYER_NORMAL:
662              if (r) *r = cc->r;
663              if (g) *g = cc->g;
664              if (b) *b = cc->b;
665              if (a) *a = cc->a;
666              break;
667 
668            case EFL_GFX_COLOR_CLASS_LAYER_OUTLINE:
669              if (r) *r = cc->r2;
670              if (g) *g = cc->g2;
671              if (b) *b = cc->b2;
672              if (a) *a = cc->a2;
673              break;
674 
675            case EFL_GFX_COLOR_CLASS_LAYER_SHADOW:
676              if (r) *r = cc->r3;
677              if (g) *g = cc->g3;
678              if (b) *b = cc->b3;
679              if (a) *a = cc->a3;
680              break;
681           }
682         return EINA_TRUE;
683      }
684    else
685      {
686         if (r) *r = 0;
687         if (g) *g = 0;
688         if (b) *b = 0;
689         if (a) *a = 0;
690 
691         return EINA_FALSE;
692      }
693 }
694 
695 EAPI Eina_Bool
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)696 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)
697 {
698    Eina_Bool result = EINA_TRUE;
699    Eina_Bool normal = EINA_FALSE , outline = EINA_FALSE , shadow = EINA_FALSE;
700 
701    if (!_edje_color_class_hash)
702      _edje_color_class_hash = eina_hash_string_superfast_new(NULL);
703 
704    result &= _edje_color_class_set_internal(_edje_color_class_hash, color_class, EFL_GFX_COLOR_CLASS_LAYER_NORMAL, r, g, b, a, &normal);
705    result &= _edje_color_class_set_internal(_edje_color_class_hash, color_class, EFL_GFX_COLOR_CLASS_LAYER_OUTLINE, r2, g2, b2, a2, &outline);
706    result &= _edje_color_class_set_internal(_edje_color_class_hash, color_class, EFL_GFX_COLOR_CLASS_LAYER_SHADOW, r3, g3, b3, a3, &shadow);
707 
708    // either of them changes then request an update.
709    if (result && (normal || outline || shadow))
710      efl_observable_observers_update(_edje_color_class_member, color_class, "color_class,set");
711 
712    return result;
713 }
714 
715 EOLIAN Eina_Bool
_edje_global_efl_gfx_color_class_color_class_set(Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * color_class,Efl_Gfx_Color_Class_Layer layer,int r,int g,int b,int a)716 _edje_global_efl_gfx_color_class_color_class_set(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED,
717                                                  const char *color_class, Efl_Gfx_Color_Class_Layer layer, int r, int g, int b, int a)
718 {
719    Eina_Bool int_ret;
720    Eina_Bool need_update = EINA_FALSE;
721 
722    if (!_edje_color_class_hash)
723      _edje_color_class_hash = eina_hash_string_superfast_new(NULL);
724 
725    int_ret = _edje_color_class_set_internal(_edje_color_class_hash, color_class, layer, r, g, b, a, &need_update);
726 
727    if ((int_ret) && (need_update))
728      efl_observable_observers_update(_edje_color_class_member, color_class, "color_class,set");
729 
730    return int_ret;
731 }
732 
733 EAPI Eina_Bool
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)734 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)
735 {
736    Eina_Bool int_ret = EINA_TRUE;
737 
738    int_ret &= efl_gfx_color_class_get(_edje_global(), color_class, EFL_GFX_COLOR_CLASS_LAYER_NORMAL, r, g, b, a);
739    int_ret &= efl_gfx_color_class_get(_edje_global(), color_class, EFL_GFX_COLOR_CLASS_LAYER_OUTLINE, r2, g2, b2, a2);
740    int_ret &= efl_gfx_color_class_get(_edje_global(), color_class, EFL_GFX_COLOR_CLASS_LAYER_SHADOW, r3, g3, b3, a3);
741 
742    return int_ret;
743 }
744 
745 EOLIAN Eina_Bool
_edje_global_efl_gfx_color_class_color_class_get(const Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * color_class,Efl_Gfx_Color_Class_Layer layer,int * r,int * g,int * b,int * a)746 _edje_global_efl_gfx_color_class_color_class_get(const Eo *obj EINA_UNUSED, void *pd EINA_UNUSED,
747                                                  const char *color_class, Efl_Gfx_Color_Class_Layer layer, int *r, int *g, int *b, int *a)
748 {
749    Edje_Color_Class *cc;
750 
751    if (!color_class)
752      cc = NULL;
753    else
754      cc = eina_hash_find(_edje_color_class_hash, color_class);
755 
756    return _edje_color_class_get_internal(cc, layer, r, g, b, a);
757 }
758 
759 EAPI void
edje_color_class_del(const char * color_class)760 edje_color_class_del(const char *color_class)
761 {
762    efl_gfx_color_class_del(_edje_global(), color_class);
763 }
764 
765 EOLIAN void
_edje_global_efl_gfx_color_class_color_class_del(Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * color_class)766 _edje_global_efl_gfx_color_class_color_class_del(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const char *color_class)
767 {
768    Edje_Color_Class *cc;
769 
770    if (!color_class) return;
771 
772    cc = eina_hash_find(_edje_color_class_hash, color_class);
773    if (!cc) return;
774 
775    eina_hash_del(_edje_color_class_hash, color_class, cc);
776    eina_stringshare_del(cc->name);
777    free(cc);
778 
779    efl_observable_observers_update(_edje_color_class_member, color_class, "color_class,del");
780 }
781 
782 Eina_List *
edje_color_class_list(void)783 edje_color_class_list(void)
784 {
785    Edje_List_Foreach_Data fdata;
786 
787    if (!_edje_color_class_hash) return NULL;
788    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
789    eina_hash_foreach(_edje_color_class_hash,
790                      _edje_color_class_list_foreach, &fdata);
791 
792    return fdata.list;
793 }
794 
795 typedef struct _Edje_Active_Color_Class_Iterator Edje_Active_Color_Class_Iterator;
796 struct _Edje_Active_Color_Class_Iterator
797 {
798    Eina_Iterator    iterator;
799 
800    Edje_Color_Class cc;
801 
802    Eina_Iterator   *classes;
803 };
804 
805 static Eina_Bool
_edje_color_class_active_iterator_next(Eina_Iterator * it,void ** data)806 _edje_color_class_active_iterator_next(Eina_Iterator *it, void **data)
807 {
808    Edje_Active_Color_Class_Iterator *et = (void *)it;
809    Efl_Observable_Tuple *tuple = NULL;
810    Efl_Observer *o;
811    Edje *ed;
812    Edje_Color_Class *cc = NULL;
813 
814    if (!eina_iterator_next(et->classes, (void **)&tuple)) return EINA_FALSE;
815    if (!tuple) return EINA_FALSE;
816 
817    if (!eina_iterator_next(tuple->data, (void **)&o)) return EINA_FALSE;
818 
819    ed = efl_data_scope_get(o, EFL_CANVAS_LAYOUT_CLASS);
820    if (!ed) return EINA_FALSE;
821 
822    /*
823       We actually need to ask on an object to get the correct value.
824       It is being assumed that the color key are the same for all object here.
825       This can some times not be the case, but for now we should be fine.
826     */
827    cc = _edje_color_class_find(ed, tuple->key);
828    if (!cc) return EINA_FALSE;
829    et->cc = *cc;
830 
831    /*
832       Any of the Edje object referenced should have a file with a valid
833       description for this color class. Let's bet on that for now.
834     */
835    if (ed->file)
836      cc = eina_hash_find(ed->file->color_hash, tuple->key);
837    if (!cc) return EINA_FALSE;
838    et->cc.desc = cc->desc;
839 
840    *data = &et->cc;
841 
842    return EINA_TRUE;
843 }
844 
845 static void *
_edje_color_class_active_iterator_container(Eina_Iterator * it EINA_UNUSED)846 _edje_color_class_active_iterator_container(Eina_Iterator *it EINA_UNUSED)
847 {
848    return NULL;
849 }
850 
851 static void
_edje_color_class_active_iterator_free(Eina_Iterator * it)852 _edje_color_class_active_iterator_free(Eina_Iterator *it)
853 {
854    Edje_Active_Color_Class_Iterator *et = (void *)it;
855 
856    eina_iterator_free(et->classes);
857    EINA_MAGIC_SET(&et->iterator, 0);
858    free(et);
859 }
860 
861 EAPI Eina_Iterator *
edje_color_class_active_iterator_new(void)862 edje_color_class_active_iterator_new(void)
863 {
864    Edje_Active_Color_Class_Iterator *it;
865 
866    if (!_edje_color_class_member) return NULL;
867    it = calloc(1, sizeof (Edje_Active_Color_Class_Iterator));
868    if (!it) return NULL;
869 
870    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
871    it->classes = efl_observable_iterator_tuple_new(_edje_color_class_member);
872 
873    it->iterator.version = EINA_ITERATOR_VERSION;
874    it->iterator.next = _edje_color_class_active_iterator_next;
875    it->iterator.get_container = _edje_color_class_active_iterator_container;
876    it->iterator.free = _edje_color_class_active_iterator_free;
877 
878    return &it->iterator;
879 }
880 
881 static Eina_Bool
_edje_color_class_list_foreach(const Eina_Hash * hash EINA_UNUSED,const void * key,void * data EINA_UNUSED,void * fdata)882 _edje_color_class_list_foreach(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata)
883 {
884    Edje_List_Foreach_Data *fd;
885 
886    fd = fdata;
887    fd->list = eina_list_append(fd->list, strdup(key));
888    return EINA_TRUE;
889 }
890 
891 EAPI Eina_Bool
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)892 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)
893 {
894    Eina_Bool int_ret = EINA_TRUE;
895 
896    int_ret &= efl_gfx_color_class_set(obj, color_class, EFL_GFX_COLOR_CLASS_LAYER_NORMAL, r, g, b, a);
897    int_ret &= efl_gfx_color_class_set(obj, color_class, EFL_GFX_COLOR_CLASS_LAYER_OUTLINE, r2, g2, b2, a2);
898    int_ret &= efl_gfx_color_class_set(obj, color_class, EFL_GFX_COLOR_CLASS_LAYER_SHADOW, r3, g3, b3, a3);
899 
900    return int_ret;
901 }
902 
903 EOLIAN Eina_Bool
_efl_canvas_layout_efl_gfx_color_class_color_class_set(Eo * obj EINA_UNUSED,Edje * ed,const char * color_class,Efl_Gfx_Color_Class_Layer layer,int r,int g,int b,int a)904 _efl_canvas_layout_efl_gfx_color_class_color_class_set(Eo *obj EINA_UNUSED, Edje *ed, const char *color_class, Efl_Gfx_Color_Class_Layer layer, int r, int g, int b, int a)
905 {
906    Eina_Bool int_ret;
907    Eina_Bool need_update;
908 
909    int_ret = _edje_color_class_set_internal(ed->color_classes, color_class, layer, r, g, b, a, &need_update);
910 
911    if ((int_ret) && (need_update))
912      {
913         Edje_Real_Part *rp;
914         unsigned short i;
915 
916         ed->dirty = EINA_TRUE;
917         ed->recalc_call = EINA_TRUE;
918 #ifdef EDJE_CALC_CACHE
919         ed->all_part_change = EINA_TRUE;
920 #endif
921         for (i = 0; i < ed->table_parts_size; i++)
922           {
923              rp = ed->table_parts[i];
924              if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
925                  ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
926                   (rp->typedata.swallow)) &&
927                  (rp->typedata.swallow->swallowed_object))
928                efl_gfx_color_class_set(rp->typedata.swallow->swallowed_object,
929                                        color_class, layer, r, g, b, a);
930           }
931 
932         _edje_recalc(ed);
933         _edje_emit(ed, "color_class,set", color_class);
934      }
935 
936    return int_ret;
937 }
938 
939 EAPI Eina_Bool
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)940 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)
941 {
942    Eina_Bool int_ret = EINA_TRUE;
943 
944    int_ret &= efl_gfx_color_class_get(obj, color_class, EFL_GFX_COLOR_CLASS_LAYER_NORMAL, r, g, b, a);
945    int_ret &= efl_gfx_color_class_get(obj, color_class, EFL_GFX_COLOR_CLASS_LAYER_OUTLINE, r2, g2, b2, a2);
946    int_ret &= efl_gfx_color_class_get(obj, color_class, EFL_GFX_COLOR_CLASS_LAYER_SHADOW, r3, g3, b3, a3);
947 
948    return int_ret;
949 }
950 
951 EOLIAN Eina_Bool
_efl_canvas_layout_efl_gfx_color_class_color_class_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * color_class,Efl_Gfx_Color_Class_Layer layer,int * r,int * g,int * b,int * a)952 _efl_canvas_layout_efl_gfx_color_class_color_class_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *color_class, Efl_Gfx_Color_Class_Layer layer, int *r, int *g, int *b, int *a)
953 {
954    Edje_Color_Class *cc;
955 
956    if (!color_class)
957      cc = NULL;
958    else
959      cc = _edje_color_class_find(ed, color_class);
960 
961    return _edje_color_class_get_internal(cc, layer, r, g, b, a);
962 }
963 
964 EAPI const char *
edje_object_color_class_description_get(const Evas_Object * obj,const char * color_class)965 edje_object_color_class_description_get(const Evas_Object *obj, const char *color_class)
966 {
967    return efl_gfx_color_class_description_get(obj, color_class);
968 }
969 
970 EOLIAN const char *
_efl_canvas_layout_efl_gfx_color_class_color_class_description_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * color_class)971 _efl_canvas_layout_efl_gfx_color_class_color_class_description_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *color_class)
972 {
973    Edje_Color_Class *cc = _edje_color_class_find(ed, color_class);
974    return cc ? cc->desc : NULL;
975 }
976 
977 EAPI void
edje_object_color_class_del(Evas_Object * obj,const char * color_class)978 edje_object_color_class_del(Evas_Object *obj, const char *color_class)
979 {
980    efl_gfx_color_class_del(obj, color_class);
981 }
982 
983 EOLIAN void
_efl_canvas_layout_efl_gfx_color_class_color_class_del(Eo * obj EINA_UNUSED,Edje * ed,const char * color_class)984 _efl_canvas_layout_efl_gfx_color_class_color_class_del(Eo *obj EINA_UNUSED, Edje *ed, const char *color_class)
985 {
986    Edje_Color_Class *cc = NULL;
987    unsigned short i;
988 
989    if (!color_class) return;
990 
991    eina_hash_del(ed->color_classes, color_class, cc);
992 
993    for (i = 0; i < ed->table_parts_size; i++)
994      {
995         Edje_Real_Part *rp;
996 
997         rp = ed->table_parts[i];
998         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
999             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1000              (rp->typedata.swallow)) &&
1001             (rp->typedata.swallow->swallowed_object))
1002           efl_gfx_color_class_del(rp->typedata.swallow->swallowed_object, color_class);
1003      }
1004 
1005    ed->dirty = EINA_TRUE;
1006    ed->recalc_call = EINA_TRUE;
1007 #ifdef EDJE_CALC_CACHE
1008    ed->all_part_change = EINA_TRUE;
1009 #endif
1010    _edje_recalc(ed);
1011    _edje_emit(ed, "color_class,del", color_class);
1012 }
1013 
1014 EAPI Eina_Bool
edje_object_color_class_clear(const Evas_Object * obj)1015 edje_object_color_class_clear(const Evas_Object *obj)
1016 {
1017    efl_gfx_color_class_clear((Eo *)obj);
1018 
1019    return EINA_TRUE;
1020 }
1021 
1022 EOLIAN void
_efl_canvas_layout_efl_gfx_color_class_color_class_clear(Eo * obj EINA_UNUSED,Edje * ed)1023 _efl_canvas_layout_efl_gfx_color_class_color_class_clear(Eo *obj EINA_UNUSED, Edje *ed)
1024 {
1025    Edje_List_Foreach_Data fdata;
1026    Edje_Color_Class *cc = NULL;
1027    Eina_List *l;
1028    char *color_class;
1029    unsigned short i;
1030 
1031    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
1032    eina_hash_foreach(ed->color_classes, _edje_color_class_list_foreach, &fdata);
1033 
1034    EINA_LIST_FOREACH(fdata.list, l, color_class)
1035      eina_hash_del(ed->color_classes, color_class, cc);
1036 
1037    for (i = 0; i < ed->table_parts_size; i++)
1038      {
1039         Edje_Real_Part *rp;
1040 
1041         rp = ed->table_parts[i];
1042         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
1043             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1044              (rp->typedata.swallow)) &&
1045             (rp->typedata.swallow->swallowed_object))
1046           efl_gfx_color_class_clear(rp->typedata.swallow->swallowed_object);
1047      }
1048 
1049    ed->dirty = EINA_TRUE;
1050    ed->recalc_call = EINA_TRUE;
1051 #ifdef EDJE_CALC_CACHE
1052    ed->all_part_change = EINA_TRUE;
1053 #endif
1054    _edje_recalc(ed);
1055 
1056    EINA_LIST_FREE(fdata.list, color_class)
1057      {
1058         _edje_emit(ed, "color_class,del", color_class);
1059         free(color_class);
1060      }
1061 }
1062 
1063 typedef struct _Edje_File_Color_Class_Iterator Edje_File_Color_Class_Iterator;
1064 struct _Edje_File_Color_Class_Iterator
1065 {
1066    Edje_Active_Color_Class_Iterator it;
1067 
1068    Edje_File                       *edf;
1069 };
1070 
1071 static Eina_Bool
_edje_mmap_color_class_iterator_next(Eina_Iterator * it,void ** data)1072 _edje_mmap_color_class_iterator_next(Eina_Iterator *it, void **data)
1073 {
1074    Edje_File_Color_Class_Iterator *et = (void *)it;
1075    Eina_Hash_Tuple *tuple = NULL;
1076    Edje_Color_Class *cc = NULL;
1077 
1078    if (!eina_iterator_next(et->it.classes, (void **)&tuple)) return EINA_FALSE;
1079    if (!tuple) return EINA_FALSE;
1080 
1081    cc = tuple->data;
1082 
1083    et->it.cc = *cc;
1084 
1085    *data = &et->it.cc;
1086    return EINA_TRUE;
1087 }
1088 
1089 static void *
_edje_mmap_color_class_iterator_container(Eina_Iterator * it)1090 _edje_mmap_color_class_iterator_container(Eina_Iterator *it)
1091 {
1092    Edje_File_Color_Class_Iterator *et = (void *)it;
1093 
1094    return et->edf->f;
1095 }
1096 
1097 static void
_edje_mmap_color_class_iterator_free(Eina_Iterator * it)1098 _edje_mmap_color_class_iterator_free(Eina_Iterator *it)
1099 {
1100    Edje_File_Color_Class_Iterator *et = (void *)it;
1101 
1102    eina_iterator_free(et->it.classes);
1103    _edje_cache_file_unref(et->edf);
1104    EINA_MAGIC_SET(&et->it.iterator, 0);
1105    free(et);
1106 }
1107 
1108 EAPI Eina_Iterator *
edje_mmap_color_class_iterator_new(Eina_File * f)1109 edje_mmap_color_class_iterator_new(Eina_File *f)
1110 {
1111    Edje_File_Color_Class_Iterator *it;
1112    Edje_File *edf;
1113    int error_ret;
1114 
1115    edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
1116    if (!edf) return NULL;
1117 
1118    it = calloc(1, sizeof (Edje_File_Color_Class_Iterator));
1119    if (!it) goto on_error;
1120 
1121    EINA_MAGIC_SET(&it->it.iterator, EINA_MAGIC_ITERATOR);
1122    it->edf = edf;
1123    it->it.classes = eina_hash_iterator_tuple_new(edf->color_hash);
1124 
1125    it->it.iterator.version = EINA_ITERATOR_VERSION;
1126    it->it.iterator.next = _edje_mmap_color_class_iterator_next;
1127    it->it.iterator.get_container = _edje_mmap_color_class_iterator_container;
1128    it->it.iterator.free = _edje_mmap_color_class_iterator_free;
1129 
1130    return &it->it.iterator;
1131 
1132 on_error:
1133    _edje_cache_file_unref(edf);
1134    return NULL;
1135 }
1136 
1137 EAPI Eina_Bool
edje_text_class_set(const char * text_class,const char * font,Evas_Font_Size size)1138 edje_text_class_set(const char *text_class, const char *font, Evas_Font_Size size)
1139 {
1140    return efl_gfx_text_class_set(_edje_global(), text_class, font, (Efl_Font_Size)size);
1141 }
1142 
1143 EOLIAN Eina_Bool
_edje_global_efl_gfx_text_class_text_class_set(Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * text_class,const char * font,Efl_Font_Size size)1144 _edje_global_efl_gfx_text_class_text_class_set(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED,
1145                                                const char *text_class, const char *font, Efl_Font_Size size)
1146 {
1147    Edje_Text_Class *tc;
1148 
1149    if (!text_class) return EINA_FALSE;
1150    if (!font) font = "";
1151 
1152    tc = eina_hash_find(_edje_text_class_hash, text_class);
1153    /* Create new text class */
1154    if (!tc)
1155      {
1156         tc = calloc(1, sizeof(Edje_Text_Class));
1157         if (!tc) return EINA_FALSE;
1158         tc->name = eina_stringshare_add(text_class);
1159         if (!tc->name)
1160           {
1161              free(tc);
1162              return EINA_FALSE;
1163           }
1164         if (!_edje_text_class_hash) _edje_text_class_hash = eina_hash_string_superfast_new(NULL);
1165         eina_hash_add(_edje_text_class_hash, text_class, tc);
1166 
1167         tc->font = eina_stringshare_add(font);
1168         tc->size = size;
1169      }
1170    else
1171      {
1172         /* Match and the same, return */
1173         if (((tc->font && font) && !strcmp(tc->font, font)) &&
1174             (tc->size == size))
1175           return EINA_TRUE;
1176 
1177         /* Update the class found */
1178         eina_stringshare_replace(&tc->font, font);
1179         tc->size = size;
1180      }
1181 
1182    /* Tell all members of the text class to recalc */
1183    efl_observable_observers_update(_edje_text_class_member, text_class, NULL);
1184 
1185    return EINA_TRUE;
1186 }
1187 
1188 EAPI Eina_Bool
edje_text_class_get(const char * text_class,const char ** font,Evas_Font_Size * size)1189 edje_text_class_get(const char *text_class, const char **font, Evas_Font_Size *size)
1190 {
1191    return efl_gfx_text_class_get(_edje_global(), text_class, font, (Efl_Font_Size *)size);
1192 }
1193 
1194 EOLIAN Eina_Bool
_edje_global_efl_gfx_text_class_text_class_get(const Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * text_class,const char ** font,Efl_Font_Size * size)1195 _edje_global_efl_gfx_text_class_text_class_get(const Eo *obj EINA_UNUSED, void *pd EINA_UNUSED,
1196                                                const char *text_class, const char **font, Efl_Font_Size *size)
1197 {
1198    Edje_Text_Class *tc;
1199 
1200    if (!text_class) return EINA_FALSE;
1201 
1202    tc = eina_hash_find(_edje_text_class_hash, text_class);
1203 
1204    if (tc)
1205      {
1206         if (font) *font = tc->font;
1207         if (size) *size = tc->size;
1208      }
1209    else
1210      {
1211         if (font) *font = NULL;
1212         if (size) *size = 0;
1213 
1214         return EINA_FALSE;
1215      }
1216    return EINA_TRUE;
1217 }
1218 
1219 EAPI void
edje_text_class_del(const char * text_class)1220 edje_text_class_del(const char *text_class)
1221 {
1222    efl_gfx_text_class_del(_edje_global(), text_class);
1223 }
1224 
1225 EOLIAN void
_edje_global_efl_gfx_text_class_text_class_del(Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * text_class)1226 _edje_global_efl_gfx_text_class_text_class_del(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const char *text_class)
1227 {
1228    Edje_Text_Class *tc;
1229 
1230    if (!text_class) return;
1231 
1232    tc = eina_hash_find(_edje_text_class_hash, text_class);
1233    if (!tc) return;
1234 
1235    eina_hash_del(_edje_text_class_hash, text_class, tc);
1236    eina_stringshare_del(tc->name);
1237    eina_stringshare_del(tc->font);
1238    free(tc);
1239 
1240    efl_observable_observers_update(_edje_text_class_member, text_class, NULL);
1241 }
1242 
1243 Eina_List *
edje_text_class_list(void)1244 edje_text_class_list(void)
1245 {
1246    Edje_List_Foreach_Data fdata;
1247 
1248    if (!_edje_text_class_hash) return NULL;
1249    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
1250    eina_hash_foreach(_edje_text_class_hash,
1251                      _edje_text_class_list_foreach, &fdata);
1252    return fdata.list;
1253 }
1254 
1255 typedef struct _Edje_Active_Text_Class_Iterator Edje_Active_Text_Class_Iterator;
1256 struct _Edje_Active_Text_Class_Iterator
1257 {
1258    Eina_Iterator    iterator;
1259    Edje_Text_Class  tc;
1260    Eina_Iterator   *classes;
1261 };
1262 
1263 static Eina_Bool
_edje_text_class_active_iterator_next(Eina_Iterator * it,void ** data)1264 _edje_text_class_active_iterator_next(Eina_Iterator *it, void **data)
1265 {
1266    Edje_Active_Text_Class_Iterator *et = (void *)it;
1267    Efl_Observable_Tuple *tuple = NULL;
1268    Efl_Observer *o;
1269    Edje *ed;
1270    Edje_Text_Class *tc;
1271 
1272    if (!eina_iterator_next(et->classes, (void **)&tuple)) return EINA_FALSE;
1273    if (!tuple) return EINA_FALSE;
1274 
1275    if (!eina_iterator_next(tuple->data, (void **)&o)) return EINA_FALSE;
1276 
1277    ed = efl_data_scope_get(o, EFL_CANVAS_LAYOUT_CLASS);
1278    if (!ed) return EINA_FALSE;
1279 
1280    /*
1281       We actually need to ask on an object to get the correct value.
1282       It is being assumed that the size key are the same for all object here.
1283       This can some times not be the case, but for now we should be fine.
1284     */
1285    tc = _edje_text_class_find(ed, tuple->key);
1286    if (!tc) return EINA_FALSE;
1287    et->tc = *tc;
1288 
1289    *data = &et->tc;
1290 
1291    return EINA_TRUE;
1292 }
1293 
1294 static void *
_edje_text_class_active_iterator_container(Eina_Iterator * it EINA_UNUSED)1295 _edje_text_class_active_iterator_container(Eina_Iterator *it EINA_UNUSED)
1296 {
1297    return NULL;
1298 }
1299 
1300 static void
_edje_text_class_active_iterator_free(Eina_Iterator * it)1301 _edje_text_class_active_iterator_free(Eina_Iterator *it)
1302 {
1303    Edje_Active_Text_Class_Iterator *et = (void *)it;
1304 
1305    eina_iterator_free(et->classes);
1306    EINA_MAGIC_SET(&et->iterator, 0);
1307    free(et);
1308 }
1309 
1310 EAPI Eina_Iterator *
edje_text_class_active_iterator_new(void)1311 edje_text_class_active_iterator_new(void)
1312 {
1313    Edje_Active_Text_Class_Iterator *it;
1314 
1315    if (!_edje_text_class_member) return NULL;
1316    it = calloc(1, sizeof (Edje_Active_Text_Class_Iterator));
1317    if (!it) return NULL;
1318 
1319    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1320    it->classes = efl_observable_iterator_tuple_new(_edje_text_class_member);
1321 
1322    it->iterator.version = EINA_ITERATOR_VERSION;
1323    it->iterator.next = _edje_text_class_active_iterator_next;
1324    it->iterator.get_container = _edje_text_class_active_iterator_container;
1325    it->iterator.free = _edje_text_class_active_iterator_free;
1326 
1327    return &it->iterator;
1328 }
1329 
1330 static Eina_Bool
_edje_text_class_list_foreach(const Eina_Hash * hash EINA_UNUSED,const void * key,void * data EINA_UNUSED,void * fdata)1331 _edje_text_class_list_foreach(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata)
1332 {
1333    Edje_List_Foreach_Data *fd;
1334 
1335    fd = fdata;
1336    fd->list = eina_list_append(fd->list, eina_stringshare_add(key));
1337    return EINA_TRUE;
1338 }
1339 
1340 static Edje_File *
_edje_file_find(const char * file)1341 _edje_file_find(const char *file)
1342 {
1343    char *tmp = NULL;
1344    Eina_File *f = NULL;
1345    Edje_File *edf = NULL;
1346 
1347    if (!file) return NULL;
1348 
1349    tmp = eina_vpath_resolve(file);
1350    if (!tmp) return NULL;
1351 
1352    f = eina_file_open(tmp, EINA_FALSE);
1353 
1354    if (tmp) free(tmp);
1355    if (!f) return NULL;
1356 
1357    edf = _edje_file_cache_find(f);
1358 
1359    eina_file_close(f);
1360    return edf;
1361 }
1362 
1363 EAPI Eina_Bool
edje_file_text_class_get(const char * file,const char * text_class,const char ** font,Evas_Font_Size * size)1364 edje_file_text_class_get(const char *file, const char * text_class, const char **font, Evas_Font_Size *size)
1365 {
1366    Edje_Text_Class *tc = NULL;
1367    Edje_File *edf = NULL;
1368    Eina_Bool ret = EINA_FALSE;
1369 
1370    if (font) *font = NULL;
1371    if (size) *size = 0;
1372 
1373    if ((!file) || (!text_class)) return ret;
1374    if ((!font) && (!size)) return ret; // No need to go deep
1375 
1376    edf = _edje_file_find(file);
1377    if (!edf) return ret;
1378 
1379    tc = eina_hash_find(edf->text_hash, text_class);
1380    if (!tc) goto end;
1381 
1382    if (font) *font = tc->font;
1383    if (size) *size = tc->size;
1384    ret = EINA_TRUE;
1385 
1386 end:
1387    _edje_cache_file_unref(edf);
1388    return ret;
1389 }
1390 
1391 EAPI Eina_Bool
edje_file_text_class_del(const char * file,const char * text_class)1392 edje_file_text_class_del(const char *file, const char *text_class)
1393 {
1394    Edje_Text_Class *tc = NULL;
1395    Edje_File *edf = NULL;
1396    Eina_Bool ret = EINA_FALSE;
1397    if ((!file) || (!text_class)) return ret;
1398 
1399    edf = _edje_file_find(file);
1400    if (!edf) return ret;
1401 
1402    tc = eina_hash_find(edf->text_hash, text_class);
1403    if (!tc) goto end;
1404 
1405    eina_hash_del(edf->text_hash, text_class, tc);
1406    eina_stringshare_del(tc->name);
1407    eina_stringshare_del(tc->font);
1408    free(tc);
1409 
1410    /* Tell all members of the text class to recalc */
1411    efl_observable_observers_update(_edje_text_class_member, text_class, edf);
1412 
1413    ret = EINA_TRUE;
1414 end:
1415    _edje_cache_file_unref(edf);
1416    return ret;
1417 }
1418 
1419 EAPI Eina_Bool
edje_file_text_class_set(const char * file,const char * text_class,const char * font,Evas_Font_Size size)1420 edje_file_text_class_set(const char *file, const char *text_class, const char *font, Evas_Font_Size size)
1421 {
1422    Edje_File *edf = NULL;
1423    Edje_Text_Class *tc = NULL;
1424    Eina_Bool ret = EINA_FALSE;
1425 
1426    if ((!file) || (!text_class)) return ret;
1427 
1428    edf = _edje_file_find(file);
1429    if (!edf) return ret;
1430 
1431    // update text_class properties, or create new text_class if not found
1432    if (edf->text_hash) tc = eina_hash_find(edf->text_hash, text_class);
1433    if (!tc)
1434      {
1435         /* Create new text class */
1436         tc = calloc(1, sizeof(Edje_Text_Class));
1437         if (!tc) goto error_end;
1438         tc->name = eina_stringshare_add(text_class);
1439         if (!tc->name)
1440           {
1441              free(tc);
1442              goto error_end;
1443           }
1444         if (!edf->text_hash) edf->text_hash = eina_hash_string_small_new(NULL);
1445         eina_hash_direct_add(edf->text_hash, text_class, tc);
1446 
1447         tc->font = eina_stringshare_add(font);
1448         tc->size = size;
1449      }
1450    else
1451      {
1452         /* Match and the same, return */
1453         if (((tc->font && font) && !strcmp(tc->font, font)) &&
1454             (tc->size == size))
1455              goto success_end;
1456 
1457         /* Update the class found */
1458         eina_stringshare_replace(&tc->font, font);
1459         tc->size = size;
1460      }
1461 
1462 
1463    /* Tell all members of the text class to recalc */
1464    efl_observable_observers_update(_edje_text_class_member, text_class, edf);
1465 
1466 success_end:
1467    ret = EINA_TRUE;
1468 
1469 error_end:
1470    _edje_cache_file_unref(edf);
1471    return ret;
1472 }
1473 
1474 EAPI Eina_Bool
edje_object_text_class_set(Evas_Object * obj,const char * text_class,const char * font,Evas_Font_Size size)1475 edje_object_text_class_set(Evas_Object *obj, const char *text_class, const char *font, Evas_Font_Size size)
1476 {
1477    return efl_gfx_text_class_set(obj, text_class, font, (Efl_Font_Size)size);
1478 }
1479 
1480 EOLIAN Eina_Bool
_efl_canvas_layout_efl_gfx_text_class_text_class_set(Eo * obj EINA_UNUSED,Edje * ed,const char * text_class,const char * font,Efl_Font_Size size)1481 _efl_canvas_layout_efl_gfx_text_class_text_class_set(Eo *obj EINA_UNUSED, Edje *ed, const char *text_class, const char *font, Efl_Font_Size size)
1482 {
1483    Edje_Text_Class *tc = NULL;
1484    unsigned short i;
1485 
1486    if ((!ed) || (!text_class)) return EINA_FALSE;
1487 
1488    tc = eina_hash_find(ed->text_classes, text_class);
1489 
1490    /* for each text_class in the edje */
1491    if (tc)
1492      {
1493         if ((tc->name) && (!strcmp(tc->name, text_class)))
1494           {
1495              /* Match and the same, return */
1496              if ((tc->size == size) &&
1497                  ((tc->font == font) ||
1498                   (tc->font && font && !strcmp(tc->font, font))))
1499                {
1500                   return EINA_TRUE;
1501                }
1502 
1503              /* Update new text class properties */
1504              eina_stringshare_replace(&tc->font, font);
1505              tc->size = size;
1506           }
1507      }
1508 
1509    if (!tc)
1510      {
1511         /* No matches, create a new text class */
1512         tc = calloc(1, sizeof(Edje_Text_Class));
1513         if (!tc) return EINA_FALSE;
1514         tc->name = eina_stringshare_add(text_class);
1515         if (!tc->name)
1516           {
1517              free(tc);
1518              return EINA_FALSE;
1519           }
1520         tc->font = eina_stringshare_add(font);
1521         tc->size = size;
1522         /* Add to edje's text class list */
1523         eina_hash_direct_add(ed->text_classes, tc->name, tc);
1524      }
1525 
1526    for (i = 0; i < ed->table_parts_size; i++)
1527      {
1528         Edje_Real_Part *rp;
1529 
1530         rp = ed->table_parts[i];
1531         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
1532             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1533              (rp->typedata.swallow)) &&
1534             (rp->typedata.swallow->swallowed_object))
1535           efl_gfx_text_class_set(rp->typedata.swallow->swallowed_object,
1536                                  text_class, font, size);
1537      }
1538 
1539    efl_observer_update(obj, _edje_text_class_member, text_class, ed);
1540 
1541    return EINA_TRUE;
1542 }
1543 
1544 EAPI Eina_Bool
edje_object_text_class_get(const Evas_Object * obj,const char * text_class,const char ** font,Evas_Font_Size * size)1545 edje_object_text_class_get(const Evas_Object *obj, const char *text_class, const char **font, Evas_Font_Size *size)
1546 {
1547    return efl_gfx_text_class_get(obj, text_class, font, (Efl_Font_Size *)size);
1548 }
1549 
1550 EOLIAN Eina_Bool
_efl_canvas_layout_efl_gfx_text_class_text_class_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * text_class,const char ** font,Efl_Font_Size * size)1551 _efl_canvas_layout_efl_gfx_text_class_text_class_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *text_class, const char **font, Efl_Font_Size *size)
1552 {
1553    Edje_Text_Class *tc = _edje_text_class_find(ed, text_class);
1554 
1555    if (tc)
1556      {
1557         if (font) *font = tc->font;
1558         if (size) *size = tc->size;
1559      }
1560    else
1561      {
1562         if (font) *font = NULL;
1563         if (size) *size = 0;
1564 
1565         return EINA_FALSE;
1566      }
1567    return EINA_TRUE;
1568 }
1569 
1570 EAPI void
edje_object_text_class_del(Evas_Object * obj,const char * text_class)1571 edje_object_text_class_del(Evas_Object *obj, const char *text_class)
1572 {
1573    efl_gfx_text_class_del(obj, text_class);
1574 }
1575 
1576 EOLIAN void
_efl_canvas_layout_efl_gfx_text_class_text_class_del(Eo * obj EINA_UNUSED,Edje * ed,const char * text_class)1577 _efl_canvas_layout_efl_gfx_text_class_text_class_del(Eo *obj EINA_UNUSED, Edje *ed, const char *text_class)
1578 {
1579    Edje_Text_Class *tc = NULL;
1580    unsigned short i;
1581 
1582    if (!text_class) return;
1583 
1584    eina_hash_del(ed->text_classes, text_class, tc);
1585 
1586    for (i = 0; i < ed->table_parts_size; i++)
1587      {
1588         Edje_Real_Part *rp;
1589 
1590         rp = ed->table_parts[i];
1591         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
1592             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1593              (rp->typedata.swallow)) &&
1594             (rp->typedata.swallow->swallowed_object))
1595           efl_gfx_text_class_del(rp->typedata.swallow->swallowed_object, text_class);
1596      }
1597 
1598    efl_observer_update(obj, _edje_text_class_member, text_class, ed);
1599 }
1600 
1601 typedef struct _Edje_File_Text_Class_Iterator Edje_File_Text_Class_Iterator;
1602 struct _Edje_File_Text_Class_Iterator
1603 {
1604    Edje_Active_Text_Class_Iterator it;
1605 
1606    Edje_File                       *edf;
1607 };
1608 
1609 static Eina_Bool
_edje_mmap_text_class_iterator_next(Eina_Iterator * it,void ** data)1610 _edje_mmap_text_class_iterator_next(Eina_Iterator *it, void **data)
1611 {
1612    Edje_File_Text_Class_Iterator *et = (void *)it;
1613    Eina_Hash_Tuple *tuple = NULL;
1614    Edje_Text_Class *tc = NULL;
1615 
1616    if (!eina_iterator_next(et->it.classes, (void **)&tuple)) return EINA_FALSE;
1617    if (!tuple) return EINA_FALSE;
1618 
1619    tc = tuple->data;
1620 
1621    et->it.tc = *tc;
1622 
1623    *data = &et->it.tc;
1624    return EINA_TRUE;
1625 }
1626 
1627 static void *
_edje_mmap_text_class_iterator_container(Eina_Iterator * it)1628 _edje_mmap_text_class_iterator_container(Eina_Iterator *it)
1629 {
1630    Edje_File_Text_Class_Iterator *et = (void *)it;
1631 
1632    return et->edf->f;
1633 }
1634 
1635 static void
_edje_mmap_text_class_iterator_free(Eina_Iterator * it)1636 _edje_mmap_text_class_iterator_free(Eina_Iterator *it)
1637 {
1638    Edje_File_Text_Class_Iterator *et = (void *)it;
1639 
1640    eina_iterator_free(et->it.classes);
1641    _edje_cache_file_unref(et->edf);
1642    EINA_MAGIC_SET(&et->it.iterator, 0);
1643    free(et);
1644 }
1645 
1646 EAPI Eina_Iterator *
edje_mmap_text_class_iterator_new(Eina_File * f)1647 edje_mmap_text_class_iterator_new(Eina_File *f)
1648 {
1649    Edje_File_Text_Class_Iterator *it;
1650    Edje_File *edf;
1651    int error_ret;
1652 
1653    edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
1654    if (!edf) return NULL;
1655 
1656    it = calloc(1, sizeof (Edje_File_Text_Class_Iterator));
1657    if (!it) goto on_error;
1658 
1659    EINA_MAGIC_SET(&it->it.iterator, EINA_MAGIC_ITERATOR);
1660    it->edf = edf;
1661    it->it.classes = eina_hash_iterator_tuple_new(edf->text_hash);
1662 
1663    it->it.iterator.version = EINA_ITERATOR_VERSION;
1664    it->it.iterator.next = _edje_mmap_text_class_iterator_next;
1665    it->it.iterator.get_container = _edje_mmap_text_class_iterator_container;
1666    it->it.iterator.free = _edje_mmap_text_class_iterator_free;
1667 
1668    return &it->it.iterator;
1669 
1670 on_error:
1671    _edje_cache_file_unref(edf);
1672    return NULL;
1673 }
1674 
1675 EAPI Eina_Bool
edje_size_class_set(const char * size_class,Evas_Coord minw,Evas_Coord minh,Evas_Coord maxw,Evas_Coord maxh)1676 edje_size_class_set(const char *size_class, Evas_Coord minw, Evas_Coord minh, Evas_Coord maxw, Evas_Coord maxh)
1677 {
1678    return efl_gfx_size_class_set(_edje_global(), size_class, minw, minh, maxw, maxh);
1679 }
1680 
1681 EOLIAN Eina_Bool
_edje_global_efl_gfx_size_class_size_class_set(Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * size_class,Evas_Coord minw,Evas_Coord minh,Evas_Coord maxw,Evas_Coord maxh)1682 _edje_global_efl_gfx_size_class_size_class_set(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const char *size_class,
1683                                                Evas_Coord minw, Evas_Coord minh, Evas_Coord maxw, Evas_Coord maxh)
1684 {
1685    Edje_Size_Class *sc;
1686 
1687    if (!size_class) return EINA_FALSE;
1688 
1689    sc = eina_hash_find(_edje_size_class_hash, size_class);
1690    /* Create new size class */
1691    if (!sc)
1692      {
1693         sc = calloc(1, sizeof(Edje_Size_Class));
1694         if (!sc) return EINA_FALSE;
1695         sc->name = eina_stringshare_add(size_class);
1696         if (!sc->name)
1697           {
1698              free(sc);
1699              return EINA_FALSE;
1700           }
1701         if (!_edje_size_class_hash) _edje_size_class_hash = eina_hash_string_superfast_new(NULL);
1702         eina_hash_add(_edje_size_class_hash, size_class, sc);
1703 
1704         sc->minw = minw;
1705         sc->minh = minh;
1706         sc->maxw = maxw;
1707         sc->maxh = maxh;
1708      }
1709    else
1710      {
1711         /* Match and the same, return */
1712         if ((sc->minw == minw) && (sc->minh == minh) &&
1713             (sc->maxw == maxw) && (sc->maxh == maxh))
1714           return EINA_TRUE;
1715 
1716         /* Update the class found */
1717         sc->minw = minw;
1718         sc->minh = minh;
1719         sc->maxw = maxw;
1720         sc->maxh = maxh;
1721      }
1722 
1723    /* Tell all members of the size class to recalc */
1724    efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
1725 
1726    return EINA_TRUE;
1727 }
1728 
1729 EAPI Eina_Bool
edje_size_class_get(const char * size_class,Evas_Coord * minw,Evas_Coord * minh,Evas_Coord * maxw,Evas_Coord * maxh)1730 edje_size_class_get(const char *size_class, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord *maxw, Evas_Coord *maxh)
1731 {
1732    return efl_gfx_size_class_get(_edje_global(), size_class, minw, minh, maxw, maxh);
1733 }
1734 
1735 EOLIAN Eina_Bool
_edje_global_efl_gfx_size_class_size_class_get(const Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * size_class,Evas_Coord * minw,Evas_Coord * minh,Evas_Coord * maxw,Evas_Coord * maxh)1736 _edje_global_efl_gfx_size_class_size_class_get(const Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const char *size_class,
1737                                                Evas_Coord *minw, Evas_Coord *minh, Evas_Coord *maxw, Evas_Coord *maxh)
1738 {
1739    Edje_Size_Class *sc;
1740 
1741    if (!size_class) return EINA_FALSE;
1742 
1743    sc = eina_hash_find(_edje_size_class_hash, size_class);
1744 
1745    if (sc)
1746      {
1747         if (minw) *minw = sc->minw;
1748         if (minh) *minh = sc->minh;
1749         if (maxw) *maxw = sc->maxw;
1750         if (maxh) *maxh = sc->maxh;
1751      }
1752    else
1753      {
1754         if (minw) *minw = 0;
1755         if (minh) *minh = 0;
1756         if (maxw) *maxw = 0;
1757         if (maxh) *maxh = 0;
1758 
1759         return EINA_FALSE;
1760      }
1761    return EINA_TRUE;
1762 }
1763 
1764 EAPI void
edje_size_class_del(const char * size_class)1765 edje_size_class_del(const char *size_class)
1766 {
1767    efl_gfx_size_class_del(_edje_global(), size_class);
1768 }
1769 
1770 EOLIAN void
_edje_global_efl_gfx_size_class_size_class_del(Eo * obj EINA_UNUSED,void * pd EINA_UNUSED,const char * size_class)1771 _edje_global_efl_gfx_size_class_size_class_del(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const char *size_class)
1772 {
1773    Edje_Size_Class *sc;
1774 
1775    if (!size_class) return;
1776 
1777    sc = eina_hash_find(_edje_size_class_hash, size_class);
1778    if (!sc) return;
1779 
1780    eina_hash_del(_edje_size_class_hash, size_class, sc);
1781    eina_stringshare_del(sc->name);
1782    free(sc);
1783 
1784    efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
1785 }
1786 
1787 Eina_List *
edje_size_class_list(void)1788 edje_size_class_list(void)
1789 {
1790    Edje_List_Foreach_Data fdata;
1791 
1792    if (!_edje_size_class_hash) return NULL;
1793    memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
1794    eina_hash_foreach(_edje_size_class_hash,
1795                      _edje_size_class_list_foreach, &fdata);
1796    return fdata.list;
1797 }
1798 
1799 typedef struct _Edje_Active_Size_Class_Iterator Edje_Active_Size_Class_Iterator;
1800 struct _Edje_Active_Size_Class_Iterator
1801 {
1802    Eina_Iterator    iterator;
1803    Edje_Size_Class  sc;
1804    Eina_Iterator   *classes;
1805 };
1806 
1807 static Eina_Bool
_edje_size_class_active_iterator_next(Eina_Iterator * it,void ** data)1808 _edje_size_class_active_iterator_next(Eina_Iterator *it, void **data)
1809 {
1810    Edje_Active_Size_Class_Iterator *et = (void *)it;
1811    Efl_Observable_Tuple *tuple = NULL;
1812    Efl_Observer *o;
1813    Edje *ed;
1814    Edje_Size_Class *sc;
1815 
1816    if (!eina_iterator_next(et->classes, (void **)&tuple)) return EINA_FALSE;
1817    if (!tuple) return EINA_FALSE;
1818 
1819    if (!eina_iterator_next(tuple->data, (void **)&o)) return EINA_FALSE;
1820 
1821    ed = efl_data_scope_get(o, EFL_CANVAS_LAYOUT_CLASS);
1822    if (!ed) return EINA_FALSE;
1823 
1824    /*
1825       We actually need to ask on an object to get the correct value.
1826       It is being assumed that the size key are the same for all object here.
1827       This can some times not be the case, but for now we should be fine.
1828     */
1829    sc = _edje_size_class_find(ed, tuple->key);
1830    if (!sc) return EINA_FALSE;
1831    et->sc = *sc;
1832 
1833    *data = &et->sc;
1834 
1835    return EINA_TRUE;
1836 }
1837 
1838 static void *
_edje_size_class_active_iterator_container(Eina_Iterator * it EINA_UNUSED)1839 _edje_size_class_active_iterator_container(Eina_Iterator *it EINA_UNUSED)
1840 {
1841    return NULL;
1842 }
1843 
1844 static void
_edje_size_class_active_iterator_free(Eina_Iterator * it)1845 _edje_size_class_active_iterator_free(Eina_Iterator *it)
1846 {
1847    Edje_Active_Size_Class_Iterator *et = (void *)it;
1848 
1849    eina_iterator_free(et->classes);
1850    EINA_MAGIC_SET(&et->iterator, 0);
1851    free(et);
1852 }
1853 
1854 EAPI Eina_Iterator *
edje_size_class_active_iterator_new(void)1855 edje_size_class_active_iterator_new(void)
1856 {
1857    Edje_Active_Size_Class_Iterator *it;
1858 
1859    if (!_edje_size_class_member) return NULL;
1860    it = calloc(1, sizeof (Edje_Active_Size_Class_Iterator));
1861    if (!it) return NULL;
1862 
1863    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1864    it->classes = efl_observable_iterator_tuple_new(_edje_size_class_member);
1865 
1866    it->iterator.version = EINA_ITERATOR_VERSION;
1867    it->iterator.next = _edje_size_class_active_iterator_next;
1868    it->iterator.get_container = _edje_size_class_active_iterator_container;
1869    it->iterator.free = _edje_size_class_active_iterator_free;
1870 
1871    return &it->iterator;
1872 }
1873 
1874 static Eina_Bool
_edje_size_class_list_foreach(const Eina_Hash * hash EINA_UNUSED,const void * key,void * data EINA_UNUSED,void * fdata)1875 _edje_size_class_list_foreach(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata)
1876 {
1877    Edje_List_Foreach_Data *fd;
1878 
1879    fd = fdata;
1880    fd->list = eina_list_append(fd->list, eina_stringshare_add(key));
1881    return EINA_TRUE;
1882 }
1883 
1884 EAPI Eina_Bool
edje_object_size_class_set(Evas_Object * obj,const char * size_class,Evas_Coord minw,Evas_Coord minh,Evas_Coord maxw,Evas_Coord maxh)1885 edje_object_size_class_set(Evas_Object *obj, const char *size_class, Evas_Coord minw, Evas_Coord minh, Evas_Coord maxw, Evas_Coord maxh)
1886 {
1887    return efl_gfx_size_class_set(obj, size_class, minw, minh, maxw, maxh);
1888 }
1889 
1890 EOLIAN Eina_Bool
_efl_canvas_layout_efl_gfx_size_class_size_class_set(Eo * obj EINA_UNUSED,Edje * ed,const char * size_class,Evas_Coord minw,Evas_Coord minh,Evas_Coord maxw,Evas_Coord maxh)1891 _efl_canvas_layout_efl_gfx_size_class_size_class_set(Eo *obj EINA_UNUSED, Edje *ed, const char *size_class, Evas_Coord minw, Evas_Coord minh, Evas_Coord maxw, Evas_Coord maxh)
1892 {
1893    Edje_Size_Class *sc = NULL;
1894    unsigned short i;
1895 
1896    if ((!ed) || (!size_class)) return EINA_FALSE;
1897 
1898    /* for each size_class in the edje */
1899    sc = eina_hash_find(ed->size_classes, size_class);
1900 
1901    if (sc)
1902      {
1903         if ((sc->minw == minw) && (sc->minh == minh) &&
1904             (sc->maxw == maxw) && (sc->maxh == maxh))
1905           {
1906              return EINA_TRUE;
1907           }
1908 
1909           /* Update new size class properties */
1910           sc->minw = minw;
1911           sc->minh = minh;
1912           sc->maxw = maxw;
1913           sc->maxh = maxh;
1914      }
1915    else
1916      {
1917         /* No matches, create a new size class */
1918         sc = calloc(1, sizeof(Edje_Size_Class));
1919         if (!sc) return EINA_FALSE;
1920         sc->name = eina_stringshare_add(size_class);
1921         if (!sc->name)
1922           {
1923              free(sc);
1924              return EINA_FALSE;
1925           }
1926         sc->minw = minw;
1927         sc->minh = minh;
1928         sc->maxw = maxw;
1929         sc->maxh = maxh;
1930         /* Add to edje's size class list */
1931         eina_hash_direct_add(ed->size_classes, sc->name, sc);
1932      }
1933 
1934    for (i = 0; i < ed->table_parts_size; i++)
1935      {
1936         Edje_Real_Part *rp;
1937 
1938         rp = ed->table_parts[i];
1939         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
1940             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1941              (rp->typedata.swallow)) &&
1942             (rp->typedata.swallow->swallowed_object))
1943           efl_gfx_size_class_set(rp->typedata.swallow->swallowed_object,
1944                                  size_class, minw, minh, maxw, maxh);
1945      }
1946 
1947    efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
1948 
1949    return EINA_TRUE;
1950 }
1951 
1952 EAPI Eina_Bool
edje_object_size_class_get(const Evas_Object * obj,const char * size_class,Evas_Coord * minw,Evas_Coord * minh,Evas_Coord * maxw,Evas_Coord * maxh)1953 edje_object_size_class_get(const Evas_Object *obj, const char *size_class, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord *maxw, Evas_Coord *maxh)
1954 {
1955    return efl_gfx_size_class_get(obj, size_class, minw, minh, maxw, maxh);
1956 }
1957 
1958 EOLIAN Eina_Bool
_efl_canvas_layout_efl_gfx_size_class_size_class_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * size_class,Evas_Coord * minw,Evas_Coord * minh,Evas_Coord * maxw,Evas_Coord * maxh)1959 _efl_canvas_layout_efl_gfx_size_class_size_class_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *size_class, Evas_Coord *minw, Evas_Coord *minh, Evas_Coord *maxw, Evas_Coord *maxh)
1960 {
1961    Edje_Size_Class *sc = _edje_size_class_find(ed, size_class);
1962 
1963    if (sc)
1964      {
1965         if (minw) *minw = sc->minw;
1966         if (minh) *minh = sc->minh;
1967         if (maxw) *maxw = sc->maxw;
1968         if (maxh) *maxh = sc->maxh;
1969      }
1970    else
1971      {
1972         if (minw) *minw = 0;
1973         if (minh) *minh = 0;
1974         if (maxw) *maxw = 0;
1975         if (maxh) *maxh = 0;
1976 
1977         return EINA_FALSE;
1978      }
1979    return EINA_TRUE;
1980 }
1981 
1982 EAPI void
edje_object_size_class_del(Evas_Object * obj,const char * size_class)1983 edje_object_size_class_del(Evas_Object *obj, const char *size_class)
1984 {
1985    efl_gfx_size_class_del(obj, size_class);
1986 }
1987 
1988 EOLIAN void
_efl_canvas_layout_efl_gfx_size_class_size_class_del(Eo * obj EINA_UNUSED,Edje * ed,const char * size_class)1989 _efl_canvas_layout_efl_gfx_size_class_size_class_del(Eo *obj EINA_UNUSED, Edje *ed, const char *size_class)
1990 {
1991    Edje_Size_Class *sc = NULL;
1992    unsigned short i;
1993 
1994    if (!size_class) return;
1995 
1996    eina_hash_del(ed->size_classes, size_class, sc);
1997 
1998    for (i = 0; i < ed->table_parts_size; i++)
1999      {
2000         Edje_Real_Part *rp;
2001 
2002         rp = ed->table_parts[i];
2003         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
2004             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
2005              (rp->typedata.swallow)) &&
2006             (rp->typedata.swallow->swallowed_object))
2007           efl_gfx_size_class_del(rp->typedata.swallow->swallowed_object, size_class);
2008      }
2009 
2010    efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
2011 }
2012 
2013 typedef struct _Edje_File_Size_Class_Iterator Edje_File_Size_Class_Iterator;
2014 struct _Edje_File_Size_Class_Iterator
2015 {
2016    Edje_Active_Size_Class_Iterator it;
2017    Edje_File                      *edf;
2018 };
2019 
2020 static Eina_Bool
_edje_mmap_size_class_iterator_next(Eina_Iterator * it,void ** data)2021 _edje_mmap_size_class_iterator_next(Eina_Iterator *it, void **data)
2022 {
2023    Edje_File_Size_Class_Iterator *et = (void *)it;
2024    Eina_Hash_Tuple *tuple = NULL;
2025    Edje_Size_Class *sc = NULL;
2026 
2027    if (!eina_iterator_next(et->it.classes, (void **)&tuple)) return EINA_FALSE;
2028    if (!tuple) return EINA_FALSE;
2029 
2030    sc = tuple->data;
2031 
2032    et->it.sc = *sc;
2033 
2034    *data = &et->it.sc;
2035    return EINA_TRUE;
2036 }
2037 
2038 static void *
_edje_mmap_size_class_iterator_container(Eina_Iterator * it)2039 _edje_mmap_size_class_iterator_container(Eina_Iterator *it)
2040 {
2041    Edje_File_Size_Class_Iterator *et = (void *)it;
2042 
2043    return et->edf->f;
2044 }
2045 
2046 static void
_edje_mmap_size_class_iterator_free(Eina_Iterator * it)2047 _edje_mmap_size_class_iterator_free(Eina_Iterator *it)
2048 {
2049    Edje_File_Size_Class_Iterator *et = (void *)it;
2050 
2051    eina_iterator_free(et->it.classes);
2052    _edje_cache_file_unref(et->edf);
2053    EINA_MAGIC_SET(&et->it.iterator, 0);
2054    free(et);
2055 }
2056 
2057 EAPI Eina_Iterator *
edje_mmap_size_class_iterator_new(Eina_File * f)2058 edje_mmap_size_class_iterator_new(Eina_File *f)
2059 {
2060    Edje_File_Size_Class_Iterator *it;
2061    Edje_File *edf;
2062    int error_ret;
2063 
2064    edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
2065    if (!edf) return NULL;
2066 
2067    it = calloc(1, sizeof (Edje_File_Size_Class_Iterator));
2068    if (!it) goto on_error;
2069 
2070    EINA_MAGIC_SET(&it->it.iterator, EINA_MAGIC_ITERATOR);
2071    it->edf = edf;
2072    it->it.classes = eina_hash_iterator_tuple_new(edf->size_hash);
2073 
2074    it->it.iterator.version = EINA_ITERATOR_VERSION;
2075    it->it.iterator.next = _edje_mmap_size_class_iterator_next;
2076    it->it.iterator.get_container = _edje_mmap_size_class_iterator_container;
2077    it->it.iterator.free = _edje_mmap_size_class_iterator_free;
2078 
2079    return &it->it.iterator;
2080 
2081 on_error:
2082    _edje_cache_file_unref(edf);
2083    return NULL;
2084 }
2085 
2086 /* Legacy API: exposes internal object. Easy to abuse. */
2087 EAPI const Evas_Object *
edje_object_part_object_get(const Eo * obj,const char * part)2088 edje_object_part_object_get(const Eo *obj, const char *part)
2089 {
2090    Edje_Real_Part *rp;
2091    Edje *ed;
2092 
2093    ed = _edje_fetch(obj);
2094    if ((!ed) || (!part)) return NULL;
2095 
2096    /* Need to recalc before providing the object. */
2097    if (!ed->freeze) EDJE_RECALC_DO(ed);
2098 
2099    rp = _edje_real_part_recursive_get(&ed, part);
2100    if (!rp) return NULL;
2101 
2102    return rp->object;
2103 }
2104 
2105 EAPI void
edje_object_item_provider_set(Edje_Object * obj,Edje_Item_Provider_Cb func,void * data)2106 edje_object_item_provider_set(Edje_Object *obj, Edje_Item_Provider_Cb func, void *data)
2107 {
2108    Edje *ed = _edje_fetch(obj);
2109    if (!ed) return;
2110    ed->item_provider.func = func;
2111    ed->item_provider.data = data;
2112 }
2113 
2114 EAPI void
edje_object_text_change_cb_set(Eo * obj,Edje_Text_Change_Cb func,void * data)2115 edje_object_text_change_cb_set(Eo *obj, Edje_Text_Change_Cb func, void *data)
2116 {
2117    unsigned short i;
2118    Edje *ed;
2119 
2120    ed = _edje_fetch(obj);
2121    if (!ed) return;
2122    ed->text_change.func = func;
2123    ed->text_change.data = data;
2124 
2125    for (i = 0; i < ed->table_parts_size; i++)
2126      {
2127         Edje_Real_Part *rp;
2128 
2129         rp = ed->table_parts[i];
2130         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
2131             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
2132              (rp->typedata.swallow)) &&
2133             (rp->typedata.swallow->swallowed_object))
2134           edje_object_text_change_cb_set(rp->typedata.swallow->swallowed_object, func, data);
2135      }
2136 }
2137 
2138 Eina_Bool
_edje_object_part_text_raw_generic_set(Edje * ed,Evas_Object * obj,Edje_Real_Part * rp,const char * part,const char * text,Eina_Bool set_markup,Eina_Bool legacy)2139 _edje_object_part_text_raw_generic_set(Edje *ed, Evas_Object *obj, Edje_Real_Part *rp, const char *part, const char *text, Eina_Bool set_markup, Eina_Bool legacy)
2140 {
2141    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2142        (!rp->typedata.text)) return EINA_TRUE;
2143    if ((!rp->typedata.text->text) && (!text))
2144      return EINA_TRUE;  /* nothing to do, no error */
2145    if ((rp->typedata.text->text) && (text) &&
2146        (!strcmp(rp->typedata.text->text, text)))
2147      return EINA_TRUE;  /* nothing to do, no error */
2148    if (rp->typedata.text->text)
2149      {
2150         eina_stringshare_del(rp->typedata.text->text);
2151         rp->typedata.text->text = NULL;
2152      }
2153    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2154      _edje_entry_text_markup_set(rp, text);
2155    else
2156    if (text)
2157      {
2158         if (legacy || (rp->part->type == EDJE_PART_TYPE_TEXT) || set_markup)
2159           {
2160              rp->typedata.text->text = eina_stringshare_add(text);
2161           }
2162         else // !legacy && (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2163              // && !set_markup
2164           {
2165              char *mkup;
2166              mkup = efl_text_markup_util_text_to_markup(
2167                 text);
2168              rp->typedata.text->text = eina_stringshare_add(mkup);
2169              free(mkup);
2170           }
2171      }
2172    ed->dirty = EINA_TRUE;
2173    ed->recalc_call = EINA_TRUE;
2174    ed->recalc_hints = EINA_TRUE;
2175 #ifdef EDJE_CALC_CACHE
2176    rp->invalidate = EINA_TRUE;
2177 #endif
2178    _edje_recalc(ed);
2179    if (ed->text_change.func)
2180      ed->text_change.func(ed->text_change.data, obj, part);
2181    edje_object_signal_emit(ed->obj, "edje,text,changed", "edje");
2182 
2183    return EINA_TRUE;
2184 }
2185 
2186 Eina_Bool
_edje_object_part_text_raw_set(Edje * ed,Evas_Object * obj,Edje_Real_Part * rp,const char * part,const char * text)2187 _edje_object_part_text_raw_set(Edje *ed, Evas_Object *obj, Edje_Real_Part *rp, const char *part, const char *text)
2188 {
2189    return _edje_object_part_text_raw_generic_set(ed, obj, rp, part, text,
2190                                                  EINA_FALSE, EINA_TRUE);
2191 }
2192 
2193 Edje_User_Defined *
_edje_user_text_style_definition_fetch(Edje * ed,const char * part)2194 _edje_user_text_style_definition_fetch(Edje *ed, const char *part)
2195 {
2196    Edje_User_Defined *eud;
2197    Eina_List *l, *ll;
2198 
2199    l = eina_hash_find(ed->user_defined, part);
2200    EINA_LIST_FOREACH(l, ll, eud)
2201      if (eud->type == EDJE_USER_TEXT_STYLE) break;
2202 
2203    if (!eud)
2204      {
2205         eud = _edje_user_definition_new(EDJE_USER_TEXT_STYLE, part, ed);
2206         if (!eud) return NULL;
2207         eud->u.text_style.types = EDJE_PART_TEXT_PROP_NONE;
2208         eud->u.text_style.props = NULL;
2209      }
2210 
2211    return eud;
2212 }
2213 
2214 Edje_User_Defined *
_edje_user_text_expand_definition_fetch(Edje * ed,const char * part)2215 _edje_user_text_expand_definition_fetch(Edje *ed, const char *part)
2216 {
2217    Edje_User_Defined *eud;
2218    Eina_List *l, *ll;
2219 
2220    l = eina_hash_find(ed->user_defined, part);
2221    EINA_LIST_FOREACH(l, ll, eud)
2222      if (eud->type == EDJE_USER_TEXT_EXPAND) break;
2223 
2224    if (!eud)
2225      {
2226         eud = _edje_user_definition_new(EDJE_USER_TEXT_EXPAND, part, ed);
2227         if (!eud) return NULL;
2228         eud->u.text_expand.expand = EFL_CANVAS_LAYOUT_PART_TEXT_EXPAND_NONE;
2229      }
2230 
2231    return eud;
2232 }
2233 
2234 void
_edje_user_define_string(Edje * ed,const char * part,const char * raw_text,Edje_Text_Type type)2235 _edje_user_define_string(Edje *ed, const char *part, const char *raw_text, Edje_Text_Type type)
2236 {
2237    /* NOTE: This one is tricky, text is referenced in rp->typedata.text->text for the life of the
2238       rp. So on edje_object_file_set, we should first ref it, before destroying the old
2239       layout. */
2240    Edje_User_Defined *eud;
2241    Eina_List *l, *ll;
2242 
2243    l = eina_hash_find(ed->user_defined, part);
2244    EINA_LIST_FOREACH(l, ll, eud)
2245      if (eud->type == EDJE_USER_STRING)
2246        {
2247           if (!raw_text)
2248             {
2249                _edje_user_definition_free(eud);
2250                return;
2251             }
2252           eud->u.string.text = raw_text;
2253           eud->u.string.type = type;
2254           return;
2255        }
2256 
2257    eud = _edje_user_definition_new(EDJE_USER_STRING, part, ed);
2258    if (!eud) return;
2259    eud->u.string.text = raw_text;
2260    eud->u.string.type = type;
2261 }
2262 
2263 Eina_Bool
_edje_efl_text_text_set(Eo * obj,Edje * ed,const char * part,const char * text,Eina_Bool legacy,Eina_Bool set_markup)2264 _edje_efl_text_text_set(Eo *obj, Edje *ed, const char *part, const char *text,
2265                    Eina_Bool legacy, Eina_Bool set_markup)
2266 {
2267    Edje_Real_Part *rp;
2268    Eina_Bool int_ret;
2269 
2270    if ((!ed) || (!part)) return EINA_FALSE;
2271    if ((!ed->file) && (!legacy))
2272      {
2273         _edje_user_define_string(ed, part, eina_stringshare_add(text),
2274           set_markup ? EDJE_TEXT_TYPE_MARKUP : EDJE_TEXT_TYPE_NORMAL);
2275         return EINA_TRUE;
2276      }
2277    rp = _edje_real_part_recursive_get(&ed, part);
2278    if (!rp) return EINA_FALSE;
2279    if ((rp->part->type != EDJE_PART_TYPE_TEXT) &&
2280        (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return EINA_FALSE;
2281    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2282        (!rp->typedata.text))
2283      {
2284         return EINA_TRUE;
2285      }
2286    int_ret = _edje_object_part_text_raw_generic_set(ed, obj, rp, part, text,
2287                                                     set_markup, legacy);
2288    _edje_user_define_string(ed, part, rp->typedata.text->text,
2289      set_markup ? EDJE_TEXT_TYPE_MARKUP : EDJE_TEXT_TYPE_NORMAL);
2290    return int_ret;
2291 }
2292 
2293 const char *
_edje_efl_text_text_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * part,Eina_Bool legacy,Eina_Bool get_markup)2294 _edje_efl_text_text_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *part,
2295                    Eina_Bool legacy, Eina_Bool get_markup)
2296 {
2297    Edje_Real_Part *rp;
2298 
2299    if ((!ed) || (!part)) return NULL;
2300 
2301    rp = _edje_real_part_recursive_get(&ed, part);
2302    if (!rp) return NULL;
2303    if ((rp->type != EDJE_RP_TYPE_TEXT) ||
2304        (!rp->typedata.text)) return NULL;
2305    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2306      {
2307         return _edje_entry_text_get(rp);
2308      }
2309    else
2310      {
2311         if (rp->part->type == EDJE_PART_TYPE_TEXT)
2312           {
2313              Edje_Part_Description_Text *desc;
2314              if (rp->typedata.text->text)
2315                return rp->typedata.text->text;
2316              else
2317                {
2318                   desc = (Edje_Part_Description_Text *) rp->chosen_description;
2319                   if (desc->text.text.translated)
2320                     return desc->text.text.translated;
2321                   else
2322                     return desc->text.text.str;
2323                }
2324           }
2325         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2326           {
2327              const char *entry;
2328              if (legacy)
2329                {
2330                   if (rp->typedata.text->text)
2331                     {
2332                        entry = rp->typedata.text->text;
2333                     }
2334                   else
2335                     {
2336 #ifdef EDJE_CALC_CACHE
2337                        if (rp->invalidate || ed->all_part_change)
2338 #else
2339                        if (ed->dirty)
2340 #endif
2341                          EDJE_RECALC_DO(ed);
2342                        entry = evas_object_textblock_text_markup_get(rp->object);
2343                     }
2344                }
2345              else
2346                {
2347                   if (get_markup)
2348                     {
2349 #ifdef EDJE_CALC_CACHE
2350                        if (rp->invalidate || ed->all_part_change)
2351 #else
2352                        if (ed->dirty)
2353 #endif
2354                          EDJE_RECALC_DO(ed);
2355                        entry = efl_text_markup_get(rp->object);
2356                     }
2357                   else
2358                     {
2359                        entry = rp->typedata.text->text;
2360                     }
2361                }
2362 
2363              return entry;
2364           }
2365      }
2366 
2367    return NULL;
2368 }
2369 
2370 EAPI const char *
edje_object_part_text_selection_get(const Eo * obj,const char * part)2371 edje_object_part_text_selection_get(const Eo *obj, const char *part)
2372 {
2373    Edje_Real_Part *rp;
2374    Edje *ed;
2375 
2376    ed = _edje_fetch(obj);
2377 
2378    if ((!ed) || (!part)) return NULL;
2379    rp = _edje_real_part_recursive_get(&ed, part);
2380    if (!rp) return NULL;
2381    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2382      return _edje_entry_selection_get(rp);
2383 
2384    return NULL;
2385 }
2386 
2387 EAPI void
edje_object_part_text_select_none(const Eo * obj,const char * part)2388 edje_object_part_text_select_none(const Eo *obj, const char *part)
2389 {
2390    Edje_Real_Part *rp;
2391    Edje *ed;
2392 
2393    ed = _edje_fetch(obj);
2394 
2395    if ((!ed) || (!part)) return;
2396    rp = _edje_real_part_recursive_get(&ed, part);
2397    if (!rp) return;
2398    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2399      _edje_entry_select_none(rp);
2400 }
2401 
2402 EAPI void
edje_object_part_text_select_all(const Eo * obj,const char * part)2403 edje_object_part_text_select_all(const Eo *obj, const char *part)
2404 {
2405    Edje_Real_Part *rp;
2406    Edje *ed;
2407 
2408    ed = _edje_fetch(obj);
2409 
2410    if ((!ed) || (!part)) return;
2411    rp = _edje_real_part_recursive_get(&ed, part);
2412    if (!rp) return;
2413    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2414      _edje_entry_select_all(rp);
2415 }
2416 
2417 EOLIAN void
_efl_canvas_layout_part_text_cursor_geometry_get(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)2418 _efl_canvas_layout_part_text_cursor_geometry_get(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
2419 {
2420    Edje_Real_Part *rp;
2421 
2422    if (x) *x = 0;
2423    if (y) *y = 0;
2424    if (w) *w = 0;
2425    if (h) *h = 0;
2426    if ((!ed) || (!part)) return;
2427    rp = _edje_real_part_recursive_get(&ed, part);
2428    if (!rp) return;
2429    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2430      {
2431         _edje_entry_cursor_geometry_get(rp, x, y, w, h, NULL);
2432         if (x) *x -= ed->x;
2433         if (y) *y -= ed->y;
2434      }
2435 }
2436 
2437 EAPI void
edje_object_part_text_select_allow_set(const Eo * obj,const char * part,Eina_Bool allow)2438 edje_object_part_text_select_allow_set(const Eo *obj, const char *part, Eina_Bool allow)
2439 {
2440    Edje_Real_Part *rp;
2441    Edje *ed;
2442 
2443    ed = _edje_fetch(obj);
2444 
2445    if ((!ed) || (!part)) return;
2446    rp = _edje_real_part_recursive_get(&ed, part);
2447    if (!rp) return;
2448    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2449      _edje_entry_select_allow_set(rp, allow);
2450 }
2451 
2452 EAPI void
edje_object_part_text_select_abort(const Eo * obj,const char * part)2453 edje_object_part_text_select_abort(const Eo *obj, const char *part)
2454 {
2455    Edje_Real_Part *rp;
2456    Edje *ed;
2457 
2458    ed = _edje_fetch(obj);
2459 
2460    if ((!ed) || (!part)) return;
2461    rp = _edje_real_part_recursive_get(&ed, part);
2462    if (!rp) return;
2463    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2464      _edje_entry_select_abort(rp);
2465 }
2466 
2467 EAPI void
edje_object_part_text_select_begin(const Eo * obj,const char * part)2468 edje_object_part_text_select_begin(const Eo *obj, const char *part)
2469 {
2470    Edje_Real_Part *rp;
2471    Edje *ed;
2472 
2473    ed = _edje_fetch(obj);
2474 
2475    if ((!ed) || (!part)) return;
2476    rp = _edje_real_part_recursive_get(&ed, part);
2477    if (!rp) return;
2478    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2479      _edje_entry_select_begin(rp);
2480 }
2481 
2482 EAPI void
edje_object_part_text_select_extend(const Eo * obj,const char * part)2483 edje_object_part_text_select_extend(const Eo *obj, const char *part)
2484 {
2485    Edje_Real_Part *rp;
2486    Edje *ed;
2487 
2488    ed = _edje_fetch(obj);
2489 
2490    if ((!ed) || (!part)) return;
2491    rp = _edje_real_part_recursive_get(&ed, part);
2492    if (!rp) return;
2493    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2494      _edje_entry_select_extend(rp);
2495 }
2496 
2497 EOLIAN Eina_Bool
_efl_canvas_layout_part_text_cursor_next(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2498 _efl_canvas_layout_part_text_cursor_next(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2499 {
2500    Edje_Real_Part *rp;
2501 
2502    if ((!ed) || (!part)) return EINA_FALSE;
2503    rp = _edje_real_part_recursive_get(&ed, part);
2504    if (!rp) return EINA_FALSE;
2505    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2506      {
2507         return _edje_entry_cursor_next(rp, cur);
2508      }
2509 
2510    return EINA_FALSE;
2511 }
2512 
2513 EOLIAN Eina_Bool
_efl_canvas_layout_part_text_cursor_prev(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2514 _efl_canvas_layout_part_text_cursor_prev(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2515 {
2516    Edje_Real_Part *rp;
2517 
2518    if ((!ed) || (!part)) return EINA_FALSE;
2519    rp = _edje_real_part_recursive_get(&ed, part);
2520    if (!rp) return EINA_FALSE;
2521    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2522      {
2523         return _edje_entry_cursor_prev(rp, cur);
2524      }
2525 
2526    return EINA_FALSE;
2527 }
2528 
2529 EOLIAN Eina_Bool
_efl_canvas_layout_part_text_cursor_up(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2530 _efl_canvas_layout_part_text_cursor_up(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2531 {
2532    Edje_Real_Part *rp;
2533 
2534    if ((!ed) || (!part)) return EINA_FALSE;
2535    rp = _edje_real_part_recursive_get(&ed, part);
2536    if (!rp) return EINA_FALSE;
2537    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2538      {
2539         return _edje_entry_cursor_up(rp, cur);
2540      }
2541 
2542    return EINA_FALSE;
2543 }
2544 
2545 EOLIAN Eina_Bool
_efl_canvas_layout_part_text_cursor_down(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2546 _efl_canvas_layout_part_text_cursor_down(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2547 {
2548    Edje_Real_Part *rp;
2549 
2550    if ((!ed) || (!part)) return EINA_FALSE;
2551    rp = _edje_real_part_recursive_get(&ed, part);
2552    if (!rp) return EINA_FALSE;
2553    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2554      {
2555         return _edje_entry_cursor_down(rp, cur);
2556      }
2557 
2558    return EINA_FALSE;
2559 }
2560 
2561 EOLIAN void
_efl_canvas_layout_part_text_cursor_begin_set(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2562 _efl_canvas_layout_part_text_cursor_begin_set(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2563 {
2564    Edje_Real_Part *rp;
2565 
2566    if ((!ed) || (!part)) return;
2567    rp = _edje_real_part_recursive_get(&ed, part);
2568    if (!rp) return;
2569    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2570      {
2571         _edje_entry_cursor_begin(rp, cur);
2572      }
2573 }
2574 
2575 EOLIAN void
_efl_canvas_layout_part_text_cursor_end_set(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2576 _efl_canvas_layout_part_text_cursor_end_set(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2577 {
2578    Edje_Real_Part *rp;
2579 
2580    if ((!ed) || (!part)) return;
2581    rp = _edje_real_part_recursive_get(&ed, part);
2582    if (!rp) return;
2583    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2584      {
2585         _edje_entry_cursor_end(rp, cur);
2586      }
2587 }
2588 
2589 EOLIAN void
_efl_canvas_layout_part_text_cursor_copy(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor src,Edje_Cursor dst)2590 _efl_canvas_layout_part_text_cursor_copy(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor src, Edje_Cursor dst)
2591 {
2592    Edje_Real_Part *rp;
2593 
2594    if ((!ed) || (!part)) return;
2595    rp = _edje_real_part_recursive_get(&ed, part);
2596    if (!rp) return;
2597    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2598      {
2599         _edje_entry_cursor_copy(rp, src, dst);
2600      }
2601 }
2602 
2603 EOLIAN void
_efl_canvas_layout_part_text_cursor_line_begin_set(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2604 _efl_canvas_layout_part_text_cursor_line_begin_set(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2605 {
2606    Edje_Real_Part *rp;
2607 
2608    if ((!ed) || (!part)) return;
2609    rp = _edje_real_part_recursive_get(&ed, part);
2610    if (!rp) return;
2611    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2612      {
2613         _edje_entry_cursor_line_begin(rp, cur);
2614      }
2615 }
2616 
2617 EOLIAN void
_efl_canvas_layout_part_text_cursor_line_end_set(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2618 _efl_canvas_layout_part_text_cursor_line_end_set(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2619 {
2620    Edje_Real_Part *rp;
2621 
2622    if ((!ed) || (!part)) return;
2623    rp = _edje_real_part_recursive_get(&ed, part);
2624    if (!rp) return;
2625    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2626      {
2627         _edje_entry_cursor_line_end(rp, cur);
2628      }
2629 }
2630 
2631 EOLIAN Eina_Bool
_efl_canvas_layout_part_text_cursor_coord_set(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur,Evas_Coord x,Evas_Coord y)2632 _efl_canvas_layout_part_text_cursor_coord_set(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur, Evas_Coord x, Evas_Coord y)
2633 {
2634    Edje_Real_Part *rp;
2635 
2636    if ((!ed) || (!part)) return EINA_FALSE;
2637    rp = _edje_real_part_recursive_get(&ed, part);
2638    if (!rp) return EINA_FALSE;
2639    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2640      {
2641         return _edje_entry_cursor_coord_set(rp, cur, x, y);
2642      }
2643 
2644    return EINA_FALSE;
2645 }
2646 
2647 EOLIAN void
_efl_canvas_layout_part_text_cursor_pos_set(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur,int pos)2648 _efl_canvas_layout_part_text_cursor_pos_set(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur, int pos)
2649 {
2650    Edje_Real_Part *rp;
2651 
2652    if ((!ed) || (!part)) return;
2653    rp = _edje_real_part_recursive_get(&ed, part);
2654    if (!rp) return;
2655    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2656      {
2657         _edje_entry_cursor_pos_set(rp, cur, pos);
2658      }
2659 }
2660 
2661 EOLIAN int
_efl_canvas_layout_part_text_cursor_pos_get(Eo * obj EINA_UNUSED,Edje * ed,const char * part,Edje_Cursor cur)2662 _efl_canvas_layout_part_text_cursor_pos_get(Eo *obj EINA_UNUSED, Edje *ed, const char *part, Edje_Cursor cur)
2663 {
2664    int ret;
2665    Edje_Real_Part *rp;
2666    ret = 0;
2667 
2668    if ((!ed) || (!part)) return ret;
2669    rp = _edje_real_part_recursive_get(&ed, part);
2670    if (!rp) return ret;
2671    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2672      {
2673         ret = _edje_entry_cursor_pos_get(rp, cur);
2674      }
2675 
2676    return ret;
2677 }
2678 
2679 EAPI void *
edje_object_part_text_imf_context_get(const Eo * obj,const char * part)2680 edje_object_part_text_imf_context_get(const Eo *obj, const char *part)
2681 {
2682    Edje_Real_Part *rp;
2683    Edje *ed;
2684 
2685    ed = _edje_fetch(obj);
2686 
2687    if ((!ed) || (!part)) return NULL;
2688 
2689    rp = _edje_real_part_recursive_get(&ed, (char *)part);
2690    if (!rp) return NULL;
2691 
2692    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2693      return _edje_entry_imf_context_get(rp);
2694 
2695    return NULL;
2696 }
2697 
2698 EAPI void
edje_object_part_text_imf_context_reset(const Eo * obj,const char * part)2699 edje_object_part_text_imf_context_reset(const Eo *obj, const char *part)
2700 {
2701    Edje_Real_Part *rp;
2702    Edje *ed;
2703 
2704    ed = _edje_fetch(obj);
2705 
2706    if ((!ed) || (!part)) return;
2707    rp = _edje_real_part_recursive_get(&ed, part);
2708    if (!rp) return;
2709    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2710      {
2711         _edje_entry_imf_context_reset(rp);
2712      }
2713 }
2714 
2715 EAPI void
edje_object_part_text_input_panel_layout_set(Eo * obj,const char * part,Edje_Input_Panel_Layout layout)2716 edje_object_part_text_input_panel_layout_set(Eo *obj, const char *part, Edje_Input_Panel_Layout layout)
2717 {
2718    Edje_Real_Part *rp;
2719    Edje *ed;
2720 
2721    ed = _edje_fetch(obj);
2722 
2723    if ((!ed) || (!part)) return;
2724    rp = _edje_real_part_recursive_get(&ed, part);
2725    if (!rp) return;
2726    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2727      {
2728         _edje_entry_input_panel_layout_set(rp, layout);
2729      }
2730 }
2731 
2732 EAPI Edje_Input_Panel_Layout
edje_object_part_text_input_panel_layout_get(const Eo * obj,const char * part)2733 edje_object_part_text_input_panel_layout_get(const Eo *obj, const char *part)
2734 {
2735    Edje_Input_Panel_Layout ret;
2736    Edje_Real_Part *rp;
2737    ret = EDJE_INPUT_PANEL_LAYOUT_INVALID;
2738    Edje *ed;
2739 
2740    ed = _edje_fetch(obj);
2741 
2742    if ((!ed) || (!part)) return ret;
2743    rp = _edje_real_part_recursive_get(&ed, part);
2744    if (!rp) return ret;
2745    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2746      {
2747         ret = _edje_entry_input_panel_layout_get(rp);
2748      }
2749 
2750    return ret;
2751 }
2752 
2753 EAPI void
edje_object_part_text_input_panel_layout_variation_set(Eo * obj,const char * part,int variation)2754 edje_object_part_text_input_panel_layout_variation_set(Eo *obj, const char *part, int variation)
2755 {
2756    Edje_Real_Part *rp;
2757    Edje *ed;
2758 
2759    ed = _edje_fetch(obj);
2760 
2761    if ((!ed) || (!part)) return;
2762    rp = _edje_real_part_recursive_get(&ed, part);
2763    if (!rp) return;
2764    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2765      {
2766         _edje_entry_input_panel_layout_variation_set(rp, variation);
2767      }
2768 }
2769 
2770 EAPI int
edje_object_part_text_input_panel_layout_variation_get(const Eo * obj,const char * part)2771 edje_object_part_text_input_panel_layout_variation_get(const Eo *obj, const char *part)
2772 {
2773    int r;
2774 
2775    Edje_Real_Part *rp;
2776    Edje *ed;
2777 
2778    ed = _edje_fetch(obj);
2779 
2780    r = 0;
2781    if ((!ed) || (!part)) return r;
2782    rp = _edje_real_part_recursive_get(&ed, part);
2783    if (!rp) return r;
2784    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2785      {
2786         r = _edje_entry_input_panel_layout_variation_get(rp);
2787      }
2788    return r;
2789 }
2790 
2791 EAPI void
edje_object_part_text_autocapital_type_set(Eo * obj,const char * part,Edje_Text_Autocapital_Type autocapital_type)2792 edje_object_part_text_autocapital_type_set(Eo *obj, const char *part, Edje_Text_Autocapital_Type autocapital_type)
2793 {
2794    Edje_Real_Part *rp;
2795    Edje *ed;
2796 
2797    ed = _edje_fetch(obj);
2798    if ((!ed) || (!part)) return;
2799    rp = _edje_real_part_recursive_get(&ed, part);
2800    if (!rp) return;
2801    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2802      {
2803         _edje_entry_autocapital_type_set(rp, autocapital_type);
2804      }
2805 }
2806 
2807 EAPI Edje_Text_Autocapital_Type
edje_object_part_text_autocapital_type_get(const Eo * obj,const char * part)2808 edje_object_part_text_autocapital_type_get(const Eo *obj, const char *part)
2809 {
2810    Edje_Text_Autocapital_Type ret;
2811    Edje_Real_Part *rp;
2812    ret = EDJE_TEXT_AUTOCAPITAL_TYPE_NONE;
2813    Edje *ed;
2814 
2815    ed = _edje_fetch(obj);
2816 
2817    if ((!ed) || (!part)) return ret;
2818    rp = _edje_real_part_recursive_get(&ed, part);
2819    if (!rp) return ret;
2820    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2821      {
2822         ret = _edje_entry_autocapital_type_get(rp);
2823      }
2824 
2825    return ret;
2826 }
2827 
2828 EAPI void
edje_object_part_text_prediction_allow_set(Eo * obj,const char * part,Eina_Bool prediction)2829 edje_object_part_text_prediction_allow_set(Eo *obj, const char *part, Eina_Bool prediction)
2830 {
2831    Edje_Real_Part *rp;
2832    Edje *ed;
2833 
2834    ed = _edje_fetch(obj);
2835 
2836    if ((!ed) || (!part)) return;
2837    rp = _edje_real_part_recursive_get(&ed, part);
2838    if (!rp) return;
2839    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2840      {
2841         _edje_entry_prediction_allow_set(rp, prediction);
2842      }
2843 }
2844 
2845 EAPI Eina_Bool
edje_object_part_text_prediction_allow_get(const Eo * obj,const char * part)2846 edje_object_part_text_prediction_allow_get(const Eo *obj, const char *part)
2847 {
2848    Eina_Bool ret;
2849    Edje_Real_Part *rp;
2850    ret = EINA_FALSE;
2851    Edje *ed;
2852 
2853    ed = _edje_fetch(obj);
2854 
2855    if ((!ed) || (!part)) return ret;
2856    rp = _edje_real_part_recursive_get(&ed, part);
2857    if (!rp) return ret;
2858    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2859      {
2860         ret = _edje_entry_prediction_allow_get(rp);
2861      }
2862 
2863    return ret;
2864 }
2865 
2866 EAPI void
edje_object_part_text_input_hint_set(Eo * obj,const char * part,Edje_Input_Hints input_hints)2867 edje_object_part_text_input_hint_set(Eo *obj, const char *part, Edje_Input_Hints input_hints)
2868 {
2869    Edje_Real_Part *rp;
2870    Edje *ed;
2871 
2872    ed = _edje_fetch(obj);
2873 
2874    if ((!ed) || (!part)) return;
2875    rp = _edje_real_part_recursive_get(&ed, part);
2876    if (!rp) return;
2877    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2878      {
2879         _edje_entry_input_hint_set(rp, input_hints);
2880      }
2881 }
2882 
2883 EAPI Edje_Input_Hints
edje_object_part_text_input_hint_get(const Eo * obj,const char * part)2884 edje_object_part_text_input_hint_get(const Eo *obj, const char *part)
2885 {
2886    Edje_Real_Part *rp;
2887    Edje *ed;
2888 
2889    ed = _edje_fetch(obj);
2890 
2891    if ((!ed) || (!part)) return EINA_FALSE;
2892    rp = _edje_real_part_recursive_get(&ed, part);
2893    if (!rp) return EINA_FALSE;
2894    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2895      {
2896         return _edje_entry_input_hint_get(rp);
2897      }
2898    return EINA_FALSE;
2899 }
2900 
2901 EAPI void
edje_object_part_text_input_panel_enabled_set(Eo * obj,const char * part,Eina_Bool enabled)2902 edje_object_part_text_input_panel_enabled_set(Eo *obj, const char *part, Eina_Bool enabled)
2903 {
2904    Edje_Real_Part *rp;
2905    Edje *ed;
2906 
2907    ed = _edje_fetch(obj);
2908 
2909    if ((!ed) || (!part)) return;
2910    rp = _edje_real_part_recursive_get(&ed, part);
2911    if (!rp) return;
2912    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2913      {
2914         _edje_entry_input_panel_enabled_set(rp, enabled);
2915      }
2916 }
2917 
2918 EAPI Eina_Bool
edje_object_part_text_input_panel_enabled_get(const Eo * obj,const char * part)2919 edje_object_part_text_input_panel_enabled_get(const Eo *obj, const char *part)
2920 {
2921    Eina_Bool ret;
2922    Edje_Real_Part *rp;
2923    ret = EINA_FALSE;
2924    Edje *ed;
2925 
2926    ed = _edje_fetch(obj);
2927 
2928    if ((!ed) || (!part)) return ret;
2929    rp = _edje_real_part_recursive_get(&ed, part);
2930    if (!rp) return ret;
2931    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2932      {
2933         ret = _edje_entry_input_panel_enabled_get(rp);
2934      }
2935 
2936    return ret;
2937 }
2938 
2939 EAPI void
edje_object_part_text_input_panel_show(const Eo * obj,const char * part)2940 edje_object_part_text_input_panel_show(const Eo *obj, const char *part)
2941 {
2942    Edje_Real_Part *rp;
2943    Edje *ed;
2944 
2945    ed = _edje_fetch(obj);
2946 
2947    if ((!ed) || (!part)) return;
2948    rp = _edje_real_part_recursive_get(&ed, part);
2949    if (!rp) return;
2950    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2951      _edje_entry_input_panel_show(rp);
2952 }
2953 
2954 EAPI void
edje_object_part_text_input_panel_hide(const Eo * obj,const char * part)2955 edje_object_part_text_input_panel_hide(const Eo *obj, const char *part)
2956 {
2957    Edje_Real_Part *rp;
2958    Edje *ed;
2959 
2960    ed = _edje_fetch(obj);
2961 
2962    if ((!ed) || (!part)) return;
2963    rp = _edje_real_part_recursive_get(&ed, part);
2964    if (!rp) return;
2965    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2966      _edje_entry_input_panel_hide(rp);
2967 }
2968 
2969 EAPI void
edje_object_part_text_input_panel_language_set(Eo * obj,const char * part,Edje_Input_Panel_Lang lang)2970 edje_object_part_text_input_panel_language_set(Eo *obj, const char *part, Edje_Input_Panel_Lang lang)
2971 {
2972    Edje_Real_Part *rp;
2973    Edje *ed;
2974 
2975    ed = _edje_fetch(obj);
2976 
2977    if ((!ed) || (!part)) return;
2978    rp = _edje_real_part_recursive_get(&ed, part);
2979    if (!rp) return;
2980    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
2981      {
2982         _edje_entry_input_panel_language_set(rp, lang);
2983      }
2984 }
2985 
2986 EAPI Edje_Input_Panel_Lang
edje_object_part_text_input_panel_language_get(const Eo * obj,const char * part)2987 edje_object_part_text_input_panel_language_get(const Eo *obj, const char *part)
2988 {
2989    Edje_Input_Panel_Lang ret;
2990    Edje_Real_Part *rp;
2991    ret = EDJE_INPUT_PANEL_LANG_AUTOMATIC;
2992    Edje *ed;
2993 
2994    ed = _edje_fetch(obj);
2995 
2996    if ((!ed) || (!part)) return ret;
2997    rp = _edje_real_part_recursive_get(&ed, part);
2998    if (!rp) return ret;
2999    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3000      {
3001         ret = _edje_entry_input_panel_language_get(rp);
3002      }
3003 
3004    return ret;
3005 }
3006 
3007 EAPI void
edje_object_part_text_input_panel_imdata_set(Eo * obj,const char * part,const void * data,int len)3008 edje_object_part_text_input_panel_imdata_set(Eo *obj, const char *part, const void *data, int len)
3009 {
3010    Edje_Real_Part *rp;
3011    Edje *ed;
3012 
3013    ed = _edje_fetch(obj);
3014 
3015    if ((!ed) || (!part)) return;
3016    rp = _edje_real_part_recursive_get(&ed, part);
3017    if (!rp) return;
3018    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3019      {
3020         _edje_entry_input_panel_imdata_set(rp, data, len);
3021      }
3022 }
3023 
3024 EAPI void
edje_object_part_text_input_panel_imdata_get(const Eo * obj,const char * part,void * data,int * len)3025 edje_object_part_text_input_panel_imdata_get(const Eo *obj, const char *part, void *data, int *len)
3026 {
3027    Edje_Real_Part *rp;
3028    Edje *ed;
3029 
3030    ed = _edje_fetch(obj);
3031 
3032    if ((!ed) || (!part)) return;
3033    rp = _edje_real_part_recursive_get(&ed, part);
3034    if (!rp) return;
3035    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3036      {
3037         _edje_entry_input_panel_imdata_get(rp, data, len);
3038      }
3039 }
3040 
3041 EAPI void
edje_object_part_text_input_panel_return_key_type_set(Eo * obj,const char * part,Edje_Input_Panel_Return_Key_Type return_key_type)3042 edje_object_part_text_input_panel_return_key_type_set(Eo *obj, const char *part, Edje_Input_Panel_Return_Key_Type return_key_type)
3043 {
3044    Edje_Real_Part *rp;
3045    Edje *ed;
3046 
3047    ed = _edje_fetch(obj);
3048 
3049    if ((!ed) || (!part)) return;
3050    rp = _edje_real_part_recursive_get(&ed, part);
3051    if (!rp) return;
3052    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3053      {
3054         _edje_entry_input_panel_return_key_type_set(rp, return_key_type);
3055      }
3056 }
3057 
3058 EAPI Edje_Input_Panel_Return_Key_Type
edje_object_part_text_input_panel_return_key_type_get(const Eo * obj,const char * part)3059 edje_object_part_text_input_panel_return_key_type_get(const Eo *obj, const char *part)
3060 {
3061    Edje_Input_Panel_Return_Key_Type ret;
3062    Edje_Real_Part *rp;
3063    ret = EDJE_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3064    Edje *ed;
3065 
3066    ed = _edje_fetch(obj);
3067 
3068    if ((!ed) || (!part)) return ret;
3069    rp = _edje_real_part_recursive_get(&ed, part);
3070    if (!rp) return ret;
3071    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3072      {
3073         ret = _edje_entry_input_panel_return_key_type_get(rp);
3074      }
3075 
3076    return ret;
3077 }
3078 
3079 EAPI void
edje_object_part_text_input_panel_return_key_disabled_set(Eo * obj,const char * part,Eina_Bool disabled)3080 edje_object_part_text_input_panel_return_key_disabled_set(Eo *obj, const char *part, Eina_Bool disabled)
3081 {
3082    Edje_Real_Part *rp;
3083    Edje *ed;
3084 
3085    ed = _edje_fetch(obj);
3086 
3087    if ((!ed) || (!part)) return;
3088    rp = _edje_real_part_recursive_get(&ed, part);
3089    if (!rp) return;
3090    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3091      {
3092         _edje_entry_input_panel_return_key_disabled_set(rp, disabled);
3093      }
3094 }
3095 
3096 EAPI Eina_Bool
edje_object_part_text_input_panel_return_key_disabled_get(const Eo * obj,const char * part)3097 edje_object_part_text_input_panel_return_key_disabled_get(const Eo *obj, const char *part)
3098 {
3099    Eina_Bool ret;
3100    Edje_Real_Part *rp;
3101    Edje *ed;
3102 
3103    ret = EINA_FALSE;
3104    ed = _edje_fetch(obj);
3105 
3106    if ((!ed) || (!part)) return ret;
3107    rp = _edje_real_part_recursive_get(&ed, part);
3108    if (!rp) return ret;
3109    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3110      {
3111         ret = _edje_entry_input_panel_return_key_disabled_get(rp);
3112      }
3113 
3114    return ret;
3115 }
3116 
3117 EAPI void
edje_object_part_text_input_panel_show_on_demand_set(Eo * obj,const char * part,Eina_Bool ondemand)3118 edje_object_part_text_input_panel_show_on_demand_set(Eo *obj, const char *part, Eina_Bool ondemand)
3119 {
3120    Edje_Real_Part *rp;
3121    Edje *ed;
3122 
3123    ed = _edje_fetch(obj);
3124 
3125    if ((!ed) || (!part)) return;
3126    rp = _edje_real_part_recursive_get(&ed, part);
3127    if (!rp) return;
3128    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3129      {
3130         _edje_entry_input_panel_show_on_demand_set(rp, ondemand);
3131      }
3132 }
3133 
3134 EAPI Eina_Bool
edje_object_part_text_input_panel_show_on_demand_get(const Eo * obj,const char * part)3135 edje_object_part_text_input_panel_show_on_demand_get(const Eo *obj, const char *part)
3136 {
3137    Eina_Bool ret;
3138    Edje_Real_Part *rp;
3139    Edje *ed;
3140 
3141    ret = EINA_FALSE;
3142    ed = _edje_fetch(obj);
3143 
3144    if ((!ed) || (!part)) return ret;
3145    rp = _edje_real_part_recursive_get(&ed, part);
3146    if (!rp) return ret;
3147    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3148      {
3149         ret = _edje_entry_input_panel_show_on_demand_get(rp);
3150      }
3151 
3152    return ret;
3153 }
3154 
3155 EAPI void
edje_object_part_text_prediction_hint_set(Eo * obj,const char * part,const char * prediction_hint)3156 edje_object_part_text_prediction_hint_set(Eo *obj, const char *part, const char *prediction_hint)
3157 {
3158    Edje_Real_Part *rp;
3159    Edje *ed;
3160 
3161    ed = _edje_fetch(obj);
3162 
3163    if ((!ed) || (!part)) return;
3164    rp = _edje_real_part_recursive_get(&ed, part);
3165    if (!rp) return;
3166    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3167      {
3168         _edje_entry_prediction_hint_set(rp, prediction_hint);
3169      }
3170 }
3171 
3172 Eina_Bool
_edje_efl_content_content_set(Edje * ed,const char * part,Efl_Gfx_Entity * obj_swallow)3173 _edje_efl_content_content_set(Edje *ed, const char *part, Efl_Gfx_Entity *obj_swallow)
3174 {
3175    Edje_Real_Part *rp, *rpcur;
3176    Edje_User_Defined *eud = NULL;
3177 
3178    if ((!ed) || (!part)) return EINA_FALSE;
3179 
3180    /* Need to recalc before providing the object. */
3181    // XXX: I guess this is not required, removing for testing purposes
3182    // XXX: uncomment if you see glitches in e17 or others.
3183    // XXX: by Gustavo, January 21th 2009.
3184    // XXX: I got a backtrace with over 30000 calls without this,
3185    // XXX: only with 32px shelves. The problem is probably somewhere else,
3186    // XXX: but until it's found, leave this here.
3187    // XXX: by Sachiel, January 21th 2009, 19:30 UTC
3188    // GFY: I decided to try removing this while optimizing some edc and saw
3189    // SRS: no downside after moderate testing, so I decided to commit it.
3190    // LOL: - zmike, 1 April 2015
3191    //_edje_recalc_do(ed);
3192 
3193    rp = _edje_real_part_recursive_get(&ed, part);
3194    rpcur = evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
3195    if (rpcur)
3196      {
3197         Edje *sed;
3198 
3199         /* the object is already swallowed in the requested part */
3200         if (rpcur == rp) return EINA_TRUE;
3201         sed = evas_object_data_get(obj_swallow, ".edje");
3202         if (sed)
3203           {
3204              /* The object is already swallowed somewhere, unswallow it first */
3205              edje_object_part_unswallow(sed->obj, obj_swallow);
3206           }
3207      }
3208 
3209    if (!ed->file)
3210      {
3211         eud = _edje_user_definition_new(EDJE_USER_SWALLOW, part, ed);
3212         if (eud)
3213           {
3214              evas_object_event_callback_add(obj_swallow, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
3215              eud->u.swallow.child = obj_swallow;
3216           }
3217         return EINA_TRUE;
3218      }
3219    if (!rp)
3220      {
3221         DBG("cannot swallow part %s: part not exist!", part);
3222         return EINA_FALSE;
3223      }
3224    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
3225      {
3226         ERR("cannot swallow part %s: not swallow type!", rp->part->name);
3227         return EINA_FALSE;
3228      }
3229    if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
3230        (!rp->typedata.swallow)) return EINA_FALSE;
3231    _edje_real_part_swallow(ed, rp, obj_swallow, EINA_TRUE);
3232 
3233    if (rp->typedata.swallow->swallowed_object)
3234      {
3235         eud = _edje_user_definition_new(EDJE_USER_SWALLOW, part, ed);
3236         if (eud)
3237           {
3238              evas_object_event_callback_add(obj_swallow, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
3239              eud->u.swallow.child = obj_swallow;
3240           }
3241      }
3242    if (ed->has_content_change_event_cb)
3243      efl_event_callback_call(ed->obj, EFL_CONTENT_EVENT_CONTENT_CHANGED, obj_swallow);
3244    return EINA_TRUE;
3245 }
3246 
3247 EAPI void
edje_extern_object_min_size_set(Evas_Object * obj,Evas_Coord minw,Evas_Coord minh)3248 edje_extern_object_min_size_set(Evas_Object *obj, Evas_Coord minw, Evas_Coord minh)
3249 {
3250    if (!obj) return;
3251 
3252    evas_object_size_hint_min_set(obj, minw, minh);
3253 }
3254 
3255 EAPI void
edje_extern_object_max_size_set(Evas_Object * obj,Evas_Coord maxw,Evas_Coord maxh)3256 edje_extern_object_max_size_set(Evas_Object *obj, Evas_Coord maxw, Evas_Coord maxh)
3257 {
3258    if (!obj) return;
3259 
3260    evas_object_size_hint_max_set(obj, maxw, maxh);
3261 }
3262 
3263 EAPI void
edje_extern_object_aspect_set(Evas_Object * obj,Edje_Aspect_Control aspect,Evas_Coord aw,Evas_Coord ah)3264 edje_extern_object_aspect_set(Evas_Object *obj, Edje_Aspect_Control aspect, Evas_Coord aw, Evas_Coord ah)
3265 {
3266    if (!obj) return;
3267    Evas_Aspect_Control asp;
3268 
3269    asp = EVAS_ASPECT_CONTROL_NONE;
3270    switch (aspect)
3271      {
3272       case EDJE_ASPECT_CONTROL_NONE: asp = EVAS_ASPECT_CONTROL_NONE; break;
3273 
3274       case EDJE_ASPECT_CONTROL_NEITHER: asp = EVAS_ASPECT_CONTROL_NEITHER; break;
3275 
3276       case EDJE_ASPECT_CONTROL_HORIZONTAL: asp = EVAS_ASPECT_CONTROL_HORIZONTAL; break;
3277 
3278       case EDJE_ASPECT_CONTROL_VERTICAL: asp = EVAS_ASPECT_CONTROL_VERTICAL; break;
3279 
3280       case EDJE_ASPECT_CONTROL_BOTH: asp = EVAS_ASPECT_CONTROL_BOTH; break;
3281 
3282       default: break;
3283      }
3284    if (aw < 1) aw = 1;
3285    if (ah < 1) ah = 1;
3286    evas_object_size_hint_aspect_set(obj, asp, aw, ah);
3287 }
3288 
3289 struct edje_box_layout_builtin
3290 {
3291    const char            *name;
3292    Evas_Object_Box_Layout cb;
3293 };
3294 
3295 static Evas_Object_Box_Layout
_edje_box_layout_builtin_find(const char * name)3296 _edje_box_layout_builtin_find(const char *name)
3297 {
3298    const struct edje_box_layout_builtin _edje_box_layout_builtin[] = {
3299       {"horizontal", evas_object_box_layout_horizontal},
3300       {"horizontal_flow", evas_object_box_layout_flow_horizontal},
3301       {"horizontal_homogeneous", evas_object_box_layout_homogeneous_horizontal},
3302       {"horizontal_max", evas_object_box_layout_homogeneous_max_size_horizontal},
3303       {"stack", evas_object_box_layout_stack},
3304       {"vertical", evas_object_box_layout_vertical},
3305       {"vertical_flow", evas_object_box_layout_flow_vertical},
3306       {"vertical_homogeneous", evas_object_box_layout_homogeneous_vertical},
3307       {"vertical_max", evas_object_box_layout_homogeneous_max_size_vertical},
3308       {NULL, NULL}
3309    };
3310    const struct edje_box_layout_builtin *base;
3311 
3312    switch (name[0])
3313      {
3314       case 'h':
3315         base = _edje_box_layout_builtin + 0;
3316         break;
3317 
3318       case 's':
3319         base = _edje_box_layout_builtin + 4;
3320         break;
3321 
3322       case 'v':
3323         base = _edje_box_layout_builtin + 5;
3324         break;
3325 
3326       default:
3327         return NULL;
3328      }
3329 
3330    for (; (base->name) && (base->name[0] == name[0]); base++)
3331      if (strcmp(base->name, name) == 0)
3332        return base->cb;
3333 
3334    return NULL;
3335 }
3336 
3337 static Eina_Rbtree_Direction
_edje_box_layout_part_external_node_cmp(const Eina_Rbtree * left,const Eina_Rbtree * right,void * data EINA_UNUSED)3338 _edje_box_layout_part_external_node_cmp(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data EINA_UNUSED)
3339 {
3340    Edje_Box_Layout *l = (Edje_Box_Layout *)left;
3341    Edje_Box_Layout *r = (Edje_Box_Layout *)right;
3342 
3343    if (strcmp(l->name, r->name) < 0)
3344      return EINA_RBTREE_RIGHT;
3345    else
3346      return EINA_RBTREE_LEFT;
3347 }
3348 
3349 static int
_edje_box_layout_part_external_find_cmp(const Eina_Rbtree * node,const void * key,int length EINA_UNUSED,void * data EINA_UNUSED)3350 _edje_box_layout_part_external_find_cmp(const Eina_Rbtree *node, const void *key, int length EINA_UNUSED, void *data EINA_UNUSED)
3351 {
3352    Edje_Box_Layout *l = (Edje_Box_Layout *)node;
3353    return strcmp(key, l->name);
3354 }
3355 
3356 static Edje_Box_Layout *
_edje_box_layout_part_external_find(const char * name)3357 _edje_box_layout_part_external_find(const char *name)
3358 {
3359    return (Edje_Box_Layout *)eina_rbtree_inline_lookup
3360             (_edje_box_layout_registry, name, 0, _edje_box_layout_part_external_find_cmp,
3361             NULL);
3362 }
3363 
3364 EAPI Eina_Bool
edje_object_part_text_prediction_hint_hash_set(Eo * obj,const char * part,const char * key,const char * value)3365 edje_object_part_text_prediction_hint_hash_set(Eo *obj, const char *part, const char *key, const char *value)
3366 {
3367    Edje_Real_Part *rp;
3368    Edje *ed;
3369 
3370    ed = _edje_fetch(obj);
3371 
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->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3376      {
3377         return _edje_entry_prediction_hint_hash_set(rp, key, value);
3378      }
3379    else
3380      return EINA_FALSE;
3381 }
3382 
3383 EAPI Eina_Bool
edje_object_part_text_prediction_hint_hash_del(Eo * obj,const char * part,const char * key)3384 edje_object_part_text_prediction_hint_hash_del(Eo *obj, const char *part, const char *key)
3385 {
3386    Edje_Real_Part *rp;
3387    Edje *ed;
3388 
3389    ed = _edje_fetch(obj);
3390 
3391    if ((!ed) || (!part)) return EINA_FALSE;
3392    rp = _edje_real_part_recursive_get(&ed, part);
3393    if (!rp) return EINA_FALSE;
3394    if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3395      {
3396         return _edje_entry_prediction_hint_hash_del(rp, key);
3397      }
3398    else
3399      return EINA_FALSE;
3400 }
3401 
3402 Eina_Bool
_edje_box_layout_find(const char * name,Evas_Object_Box_Layout * cb,void ** data,void (** free_data)(void * data))3403 _edje_box_layout_find(const char *name, Evas_Object_Box_Layout *cb, void **data, void(**free_data) (void *data))
3404 {
3405    const Edje_Box_Layout *l;
3406 
3407    if (!name) return EINA_FALSE;
3408 
3409    *cb = _edje_box_layout_builtin_find(name);
3410    if (*cb)
3411      {
3412         *free_data = NULL;
3413         *data = NULL;
3414         return EINA_TRUE;
3415      }
3416 
3417    l = _edje_box_layout_part_external_find(name);
3418    if (!l) return EINA_FALSE;
3419 
3420    *cb = l->func;
3421    *free_data = l->layout_data_free;
3422    if (l->layout_data_get)
3423      *data = l->layout_data_get(l->data);
3424    else
3425      *data = NULL;
3426 
3427    return EINA_TRUE;
3428 }
3429 
3430 static void
_edje_box_layout_part_external_free(Eina_Rbtree * node,void * data EINA_UNUSED)3431 _edje_box_layout_part_external_free(Eina_Rbtree *node, void *data EINA_UNUSED)
3432 {
3433    Edje_Box_Layout *l = (Edje_Box_Layout *)node;
3434 
3435    if (l->data && l->free_data)
3436      l->free_data(l->data);
3437    free(l);
3438 }
3439 
3440 static Edje_Box_Layout *
_edje_box_layout_part_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)3441 _edje_box_layout_part_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)
3442 {
3443    Edje_Box_Layout *l;
3444    size_t name_len;
3445 
3446    name_len = strlen(name) + 1;
3447    l = malloc(sizeof(Edje_Box_Layout) + name_len);
3448    if (!l) return NULL;
3449 
3450    l->func = func;
3451    l->layout_data_get = layout_data_get;
3452    l->layout_data_free = layout_data_free;
3453    l->free_data = free_data;
3454    l->data = data;
3455 
3456    memcpy(l->name, name, name_len);
3457 
3458    return l;
3459 }
3460 
3461 EAPI void
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)3462 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)
3463 {
3464    Edje_Box_Layout *l;
3465 
3466    if (!name) return;
3467 
3468    if (_edje_box_layout_builtin_find(name))
3469      {
3470         ERR("Cannot register layout '%s': would override builtin!",
3471             name);
3472 
3473         if (data && free_data) free_data(data);
3474         return;
3475      }
3476 
3477    l = _edje_box_layout_part_external_find(name);
3478    if (!l)
3479      {
3480         if (!func)
3481           {
3482              if (data && free_data) free_data(data);
3483              return;
3484           }
3485 
3486         l = _edje_box_layout_part_external_new
3487             (name, func, layout_data_get, layout_data_free, free_data, data);
3488         if (!l)
3489           return;
3490 
3491         _edje_box_layout_registry = eina_rbtree_inline_insert
3492             (_edje_box_layout_registry, (Eina_Rbtree *)l,
3493             _edje_box_layout_part_external_node_cmp, NULL);
3494      }
3495    else
3496      {
3497         if (func)
3498           {
3499              if (l->data && l->free_data) l->free_data(l->data);
3500 
3501              l->func = func;
3502              l->layout_data_get = layout_data_get;
3503              l->layout_data_free = layout_data_free;
3504              l->free_data = free_data;
3505              l->data = data;
3506           }
3507         else
3508           {
3509              if (data && free_data) free_data(data);
3510 
3511              _edje_box_layout_registry = eina_rbtree_inline_remove
3512                  (_edje_box_layout_registry, (Eina_Rbtree *)l,
3513                  _edje_box_layout_part_external_node_cmp, NULL);
3514              _edje_box_layout_part_external_free((Eina_Rbtree *)l, NULL);
3515           }
3516      }
3517 }
3518 
3519 static Edje_Real_Part *
_swallow_real_part_get(Evas_Object * obj_swallow)3520 _swallow_real_part_get(Evas_Object *obj_swallow)
3521 {
3522    Edje_Real_Part *rp;
3523 
3524    if (!obj_swallow)
3525      return NULL;
3526 
3527    rp = (Edje_Real_Part *)evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
3528    if (!rp)
3529      return NULL;
3530    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
3531      {
3532         ERR("part %s is not a swallow type!", rp->part->name);
3533         return NULL;
3534      }
3535 
3536    if ((rp->type != EDJE_RP_TYPE_SWALLOW) || (!rp->typedata.swallow))
3537      return NULL;
3538 
3539    if (rp->typedata.swallow->swallowed_object == obj_swallow)
3540      return rp;
3541 
3542    return NULL;
3543 }
3544 
3545 EOLIAN Eina_Bool
_efl_canvas_layout_content_remove(Eo * obj EINA_UNUSED,Edje * ed,Evas_Object * obj_swallow)3546 _efl_canvas_layout_content_remove(Eo *obj EINA_UNUSED, Edje *ed, Evas_Object *obj_swallow)
3547 {
3548    Edje_Real_Part *rp;
3549    Edje_User_Defined *eud;
3550    Eina_Iterator *it;
3551    Eina_List *l, *ll;
3552 
3553    rp = _swallow_real_part_get(obj_swallow);
3554    if (!rp) return EINA_FALSE;
3555 
3556    it = eina_hash_iterator_data_new(ed->user_defined);
3557    EINA_ITERATOR_FOREACH(it, l)
3558      {
3559         EINA_LIST_FOREACH(l, ll, eud)
3560           if ((eud->type == EDJE_USER_SWALLOW) && (eud->u.swallow.child == obj_swallow))
3561             {
3562                _edje_user_definition_free(eud);
3563                eina_iterator_free(it);
3564                return EINA_TRUE;
3565             }
3566      }
3567    eina_iterator_free(it);
3568    _edje_real_part_swallow_clear(ed, rp);
3569    rp->typedata.swallow->swallowed_object = NULL;
3570    rp->typedata.swallow->swallow_params.min.w = 0;
3571    rp->typedata.swallow->swallow_params.min.h = 0;
3572    rp->typedata.swallow->swallow_params.max.w = 0;
3573    rp->typedata.swallow->swallow_params.max.h = 0;
3574    ed->dirty = EINA_TRUE;
3575    ed->recalc_call = EINA_TRUE;
3576 #ifdef EDJE_CALC_CACHE
3577    rp->invalidate = EINA_TRUE;
3578 #endif
3579    /* this seems to be as unnecessary as the calc in part_swallow()
3580     * -zmike, 6 April 2015
3581     */
3582    //_edje_recalc_do(ed);
3583 
3584    return EINA_TRUE;
3585 }
3586 
3587 typedef struct _Content_Part_Iterator Content_Part_Iterator;
3588 struct _Content_Part_Iterator
3589 {
3590    Eina_Iterator  iterator;
3591    Eo            *object;
3592    Edje          *ed;
3593    unsigned       index;
3594 };
3595 
3596 static Eina_Bool
_content_part_iterator_next(Content_Part_Iterator * it,void ** data)3597 _content_part_iterator_next(Content_Part_Iterator *it, void **data)
3598 {
3599    for (; it->index < it->ed->table_parts_size; it->index++)
3600      {
3601         Edje_Real_Part *rp = it->ed->table_parts[it->index];
3602         if (rp->part && rp->part->type == EDJE_PART_TYPE_SWALLOW)
3603           {
3604              if (data) *data = (void*) rp->typedata.swallow->swallowed_object;
3605              it->index++;
3606              return EINA_TRUE;
3607           }
3608      }
3609 
3610    return EINA_FALSE;
3611 }
3612 
3613 static Eo *
_content_part_iterator_get_container(Content_Part_Iterator * it)3614 _content_part_iterator_get_container(Content_Part_Iterator *it)
3615 {
3616    return it->object;
3617 }
3618 
3619 static void
_content_part_iterator_free(Content_Part_Iterator * it)3620 _content_part_iterator_free(Content_Part_Iterator *it)
3621 {
3622    free(it);
3623 }
3624 
3625 EOLIAN Eina_Iterator*
_efl_canvas_layout_efl_container_content_iterate(Eo * obj,Edje * ed)3626 _efl_canvas_layout_efl_container_content_iterate(Eo *obj, Edje *ed)
3627 {
3628    Content_Part_Iterator *it;
3629 
3630    it = calloc(1, sizeof(*it));
3631    if (!it) return NULL;
3632 
3633    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
3634 
3635    it->iterator.version = EINA_ITERATOR_VERSION;
3636    it->iterator.next = FUNC_ITERATOR_NEXT(_content_part_iterator_next);
3637    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_content_part_iterator_get_container);
3638    it->iterator.free = FUNC_ITERATOR_FREE(_content_part_iterator_free);
3639    it->object = obj;
3640    it->ed = ed;
3641    it->index = 0;
3642 
3643    return &it->iterator;
3644 }
3645 
3646 EOLIAN int
_efl_canvas_layout_efl_container_content_count(Eo * obj EINA_UNUSED,Edje * pd)3647 _efl_canvas_layout_efl_container_content_count(Eo *obj EINA_UNUSED, Edje *pd)
3648 {
3649    Edje_Real_Part *rp;
3650    int result = 0;
3651 
3652    for (int i = 0; i < pd->table_parts_size; ++i)
3653      {
3654         rp = pd->table_parts[i];
3655         if (rp->part && rp->part->type == EDJE_PART_TYPE_SWALLOW)
3656           result ++;
3657      }
3658 
3659    return result;
3660 }
3661 
3662 
3663 Efl_Gfx_Entity *
_edje_efl_content_content_get(Edje * ed,const char * part)3664 _edje_efl_content_content_get(Edje *ed, const char *part)
3665 {
3666    Edje_Real_Part *rp;
3667 
3668    if ((!ed) || (!part)) return NULL;
3669 
3670    rp = _edje_real_part_recursive_get(&ed, part);
3671    if (!rp) return NULL;
3672 
3673    if (rp->type != EDJE_RP_TYPE_SWALLOW)
3674      {
3675         ERR("Edje group '%s' part '%s' is not a swallow. Did "
3676             "you mean to call efl_part() instead?", ed->group, part);
3677         return NULL;
3678      }
3679 
3680    if (!rp->typedata.swallow) return NULL;
3681    return rp->typedata.swallow->swallowed_object;
3682 }
3683 
3684 EOLIAN Eo *
_efl_canvas_layout_efl_part_part_get(Eo * obj,Edje * ed,const char * part)3685 _efl_canvas_layout_efl_part_part_get(Eo *obj, Edje *ed, const char *part)
3686 {
3687    Edje_Real_Part *rp;
3688 
3689    if ((!ed) || (!part)) return NULL;
3690 
3691    rp = _edje_real_part_recursive_get(&ed, part);
3692    if (!rp)
3693      {
3694         // Note: This could be disabled if debug is not required.
3695         static const Edje_Real_Part _invalid_part = {};
3696         rp = (Edje_Real_Part *) &_invalid_part;
3697         return _edje_invalid_internal_proxy_get(obj, ed, rp, part);
3698      }
3699 
3700    if (rp->part->type == EDJE_PART_TYPE_BOX)
3701      return _edje_box_internal_proxy_get(obj, ed, rp, rp->part->name);
3702    else if (rp->part->type == EDJE_PART_TYPE_TABLE)
3703      return _edje_table_internal_proxy_get(obj, ed, rp, rp->part->name);
3704    else if (rp->part->type == EDJE_PART_TYPE_SWALLOW)
3705      return _edje_swallow_internal_proxy_get(obj, ed, rp, rp->part->name);
3706    else if (rp->part->type == EDJE_PART_TYPE_EXTERNAL)
3707      return _edje_external_internal_proxy_get(obj, ed, rp, rp->part->name);
3708    else if (rp->part->type == EDJE_PART_TYPE_TEXT)
3709      return _edje_text_internal_proxy_get(obj, ed, rp, rp->part->name);
3710    else if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
3711      return _edje_text_internal_proxy_get(obj, ed, rp, rp->part->name);
3712    else
3713      return _edje_other_internal_proxy_get(obj, ed, rp, rp->part->name);
3714 }
3715 
3716 EOLIAN Eina_Size2D
_efl_canvas_layout_efl_layout_group_group_size_min_get(const Eo * obj EINA_UNUSED,Edje * ed)3717 _efl_canvas_layout_efl_layout_group_group_size_min_get(const Eo *obj EINA_UNUSED, Edje *ed)
3718 {
3719    if ((!ed) || (!ed->collection))
3720      return EINA_SIZE2D(0, 0);
3721 
3722    return ed->collection->prop.min;
3723 }
3724 
3725 EOLIAN Eina_Size2D
_efl_canvas_layout_efl_layout_group_group_size_max_get(const Eo * obj EINA_UNUSED,Edje * ed)3726 _efl_canvas_layout_efl_layout_group_group_size_max_get(const Eo *obj EINA_UNUSED, Edje *ed)
3727 {
3728    Eina_Size2D sz;
3729 
3730    if ((!ed) || (!ed->collection))
3731      return EINA_SIZE2D(0, 0);
3732 
3733    /* Need to recalc before providing the object. */
3734    if (!ed->freeze) EDJE_RECALC_DO(ed);
3735 
3736    sz = ed->collection->prop.max;
3737 
3738    /* XXX TODO: use 0 as max, fix things that break. */
3739    if (sz.w == 0) sz.w = EDJE_INF_MAX_W;
3740    if (sz.h == 0) sz.h = EDJE_INF_MAX_H;
3741    return sz;
3742 }
3743 
3744 EOLIAN Eina_Bool
_efl_canvas_layout_efl_layout_group_part_exist_get(const Eo * obj EINA_UNUSED,Edje * ed,const char * part)3745 _efl_canvas_layout_efl_layout_group_part_exist_get(const Eo *obj EINA_UNUSED, Edje *ed, const char *part)
3746 {
3747    Edje_Real_Part *rp;
3748 
3749    if (!part) return EINA_FALSE;
3750    if (ed->delete_me) return EINA_FALSE;
3751    rp = _edje_real_part_recursive_get(&ed, part);
3752    if (!rp) return EINA_FALSE;
3753 
3754    return EINA_TRUE;
3755 }
3756 
3757 EOLIAN void
_efl_canvas_layout_efl_layout_calc_calc_force(Eo * obj EINA_UNUSED,Edje * ed)3758 _efl_canvas_layout_efl_layout_calc_calc_force(Eo *obj EINA_UNUSED, Edje *ed)
3759 {
3760    int pf, pf2;
3761 
3762    if (!ed) return;
3763    ed->dirty = EINA_TRUE;
3764 #ifdef EDJE_CALC_CACHE
3765    ed->all_part_change = EINA_TRUE;
3766 #endif
3767 
3768    pf2 = _edje_util_freeze_val;
3769    pf = ed->freeze;
3770 
3771    _edje_util_freeze_val = 0;
3772    ed->freeze = 0;
3773 
3774    _edje_recalc_do(ed);
3775 
3776    ed->freeze = pf;
3777    _edje_util_freeze_val = pf2;
3778 }
3779 
3780 EOLIAN Eina_Rect
_efl_canvas_layout_efl_layout_calc_calc_parts_extends(Eo * obj EINA_UNUSED,Edje * ed)3781 _efl_canvas_layout_efl_layout_calc_calc_parts_extends(Eo *obj EINA_UNUSED, Edje *ed)
3782 {
3783    Evas_Coord xx1 = INT_MAX, yy1 = INT_MAX;
3784    Evas_Coord xx2 = 0, yy2 = 0, w = 0, h = 0;
3785    unsigned short i;
3786 
3787    ed->calc_only = EINA_TRUE;
3788 
3789    /* Need to recalc before providing the object. */
3790    ed->dirty = EINA_TRUE;
3791    _edje_recalc_do(ed);
3792 
3793    for (i = 0; i < ed->table_parts_size; i++)
3794      {
3795         Edje_Real_Part *rp;
3796         Evas_Coord rpx1, rpy1;
3797         Evas_Coord rpx2, rpy2;
3798 
3799         rp = ed->table_parts[i];
3800 
3801         rpx1 = rp->x;
3802         rpy1 = rp->y;
3803         rpx2 = rpx1 + rp->w;
3804         rpy2 = rpy1 + rp->h;
3805 
3806         if (xx1 > rpx1) xx1 = rpx1;
3807         if (yy1 > rpy1) yy1 = rpy1;
3808         if (xx2 < rpx2) xx2 = rpx2;
3809         if (yy2 < rpy2) yy2 = rpy2;
3810      }
3811 
3812    ed->calc_only = EINA_FALSE;
3813 
3814    if ((xx2 - xx1) > 0) w = xx2 - xx1;
3815    if ((yy2 - yy1) > 0) h = yy2 - yy1;
3816 
3817    return (Eina_Rect) { (Eina_Rectangle) { xx1, yy1, w, h } };
3818 }
3819 
3820 EOLIAN Eina_Size2D
_efl_canvas_layout_efl_layout_calc_calc_size_min(Eo * obj EINA_UNUSED,Edje * ed,Eina_Size2D restricted)3821 _efl_canvas_layout_efl_layout_calc_calc_size_min(Eo *obj EINA_UNUSED, Edje *ed, Eina_Size2D restricted)
3822 {
3823    const int CALC_COUNT_LIMIT = 255;
3824 
3825    Evas_Coord orig_w, orig_h; //original edje size
3826    int max_over_w, max_over_h;  //maximum over-calculated size.
3827    int calc_count = 0;
3828    Eina_Bool repeat_w, repeat_h;
3829    Eina_Bool reset_max = EINA_TRUE;
3830    Edje_Real_Part *pep = NULL;
3831    /* Only for legacy calculation logic */
3832    Evas_Coord ins_l, ins_r;
3833    Eina_Bool has_fixed_tb;
3834    Eina_Bool legacy_calc;
3835    Eina_Size2D ret;
3836 
3837    if ((!ed) || (!ed->collection))
3838      return restricted;
3839 
3840    /*
3841     * It decides a calculation logic according to efl_version of Edje file.
3842     * There was wrong/special consideration for Textblock parts.
3843     * Becasue of that, Textblock parts can have minimum size according to its text contents
3844     * even if there is [text.min: 0 0]. It made people confused.
3845     *
3846     * To keep backward compatibility, legacy_calc will be used for old version of EDJ files.
3847     * With enabling legacy_calc, You can't see proper min/max result accroding to documents.
3848     */
3849    if (!ed->file || ((ed->file->efl_version.major >= 1) && (ed->file->efl_version.minor >= 19)))
3850      legacy_calc = EINA_FALSE;
3851    else
3852      legacy_calc = EINA_TRUE;
3853 
3854    //Simulate object minimum size.
3855    ed->calc_only = EINA_TRUE;
3856 
3857    orig_w = ed->w;
3858    orig_h = ed->h;
3859 
3860 again:
3861    //restrict minimum size to
3862    ed->w = restricted.w;
3863    ed->h = restricted.h;
3864 
3865    max_over_w = 0;
3866    max_over_h = 0;
3867 
3868    do
3869      {
3870         unsigned short i;
3871 
3872         calc_count++;
3873 
3874         repeat_w = EINA_FALSE;
3875         repeat_h = EINA_FALSE;
3876         ed->dirty = EINA_TRUE;
3877 #ifdef EDJE_CALC_CACHE
3878         ed->all_part_change = EINA_TRUE;
3879 #endif
3880         _edje_recalc_do(ed);
3881 
3882         if (reset_max)
3883           {
3884              max_over_w = 0;
3885              max_over_h = 0;
3886           }
3887 
3888         pep = NULL;
3889         /* Only for legacy calculation logic */
3890         has_fixed_tb = EINA_TRUE;
3891 
3892         //for parts
3893         for (i = 0; i < ed->table_parts_size; i++)
3894           {
3895              Edje_Real_Part *ep = ed->table_parts[i];
3896 
3897              if (!ep->chosen_description) continue;
3898 
3899              //diff, how much it's over-sized.
3900              int over_w = (ep->w - ep->req.w);
3901              int over_h = (ep->h - ep->req.h);
3902 
3903              /* Only for legacy calculation logic */
3904              Eina_Bool skip_h = EINA_FALSE;
3905 
3906              //width
3907              if (!ep->chosen_description->fixed.w)
3908                {
3909                   if ((legacy_calc) && (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK))
3910                     {
3911                        //We care textblock width size specially.
3912                        Evas_Coord tb_mw;
3913                        evas_object_textblock_size_formatted_get(ep->object,
3914                                                                 &tb_mw, NULL);
3915                        evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r, NULL, NULL);
3916                        tb_mw = ins_l + tb_mw + ins_r;
3917                        tb_mw -= ep->req.w;
3918                        if (tb_mw > over_w) over_w = tb_mw;
3919                        has_fixed_tb = EINA_FALSE;
3920                     }
3921 
3922                   if (over_w > max_over_w)
3923                     {
3924                        max_over_w = over_w;
3925                        repeat_w = EINA_TRUE;
3926                        pep = ep;
3927 
3928                        /* Only for legacy calculation logic */
3929                        skip_h = EINA_TRUE;
3930                     }
3931                }
3932              //height
3933              if (!ep->chosen_description->fixed.h)
3934                {
3935                   if (legacy_calc)
3936                     {
3937                        if ((ep->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
3938                            ((Edje_Part_Description_Text *)ep->chosen_description)->text.min_x ||
3939                            !skip_h)
3940                          {
3941                             if (over_h > max_over_h)
3942                               {
3943                                  max_over_h = over_h;
3944                                  repeat_h = EINA_TRUE;
3945                                  pep = ep;
3946                               }
3947                          }
3948 
3949                        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
3950                          has_fixed_tb = EINA_FALSE;
3951                     }
3952                   else if (over_h > max_over_h)
3953                     {
3954                        max_over_h = over_h;
3955                        repeat_h = EINA_TRUE;
3956                        pep = ep;
3957                     }
3958                }
3959           }
3960         if (repeat_w)
3961           {
3962              ed->w += max_over_w;
3963 
3964              //exceptional handling.
3965              if (ed->w < restricted.w) ed->w = restricted.w;
3966           }
3967         if (repeat_h)
3968           {
3969              ed->h += max_over_h;
3970 
3971              //exceptional handling.
3972              if (ed->h < restricted.h) ed->h = restricted.h;
3973           }
3974 
3975         if (reset_max && (calc_count > CALC_COUNT_LIMIT))
3976           {
3977              if (legacy_calc)
3978                {
3979                   /* Only print it if we have a non-fixed textblock.
3980                    * We should possibly avoid all of this if in this case, but in
3981                    * the meanwhile, just doing this. */
3982                   if (!has_fixed_tb)
3983                     {
3984                        if (pep)
3985                          ERR("file %s, group %s has a non-fixed part '%s'. Adding 'fixed: 1 1;' to source EDC may help. Continuing discarding faulty part.",
3986                              ed->path, ed->group, pep->part->name);
3987                        else
3988                          ERR("file %s, group %s runs infinite minimum calculation loops.Continuing discarding faulty parts.",
3989                              ed->path, ed->group);
3990                     }
3991                }
3992              else
3993                {
3994                   /* We should possibly avoid all of this if in this case, but in
3995                    * the meanwhile, just doing this. */
3996                   if (pep)
3997                     ERR("file %s, group %s has a non-fixed part '%s'. Adding 'fixed: 1 1;' to source EDC may help. Continuing discarding faulty part.",
3998                         ed->path, ed->group, pep->part->name);
3999                   else
4000                     ERR("file %s, group %s runs infinite minimum calculation loops.Continuing discarding faulty parts.",
4001                         ed->path, ed->group);
4002                }
4003 
4004              reset_max = EINA_FALSE;
4005              goto again;
4006           }
4007      }
4008    while (repeat_w || repeat_h);
4009 
4010    ed->min.w = ed->w;
4011    ed->min.h = ed->h;
4012    ret = EINA_SIZE2D(ed->min.w, ed->min.h);
4013 
4014    ed->w = orig_w;
4015    ed->h = orig_h;
4016 
4017    ed->dirty = EINA_TRUE;
4018 #ifdef EDJE_CALC_CACHE
4019    ed->all_part_change = EINA_TRUE;
4020 #endif
4021    _edje_recalc(ed);
4022    ed->calc_only = EINA_FALSE;
4023 
4024    return ret;
4025 }
4026 
4027 /* FIXME: Correctly return other states */
4028 const char *
_edje_object_part_state_get(Edje * ed,const char * part,double * val_ret)4029 _edje_object_part_state_get(Edje *ed, const char *part, double *val_ret)
4030 {
4031    const char *ret;
4032 
4033    Edje_Real_Part *rp;
4034    ret = "";
4035 
4036    if ((!ed) || (!part))
4037      {
4038         if (val_ret) *val_ret = 0;
4039         return ret;
4040      }
4041 
4042    /* Need to recalc before providing the object. */
4043    _edje_recalc_do(ed);
4044 
4045    rp = _edje_real_part_recursive_get(&ed, part);
4046    if (!rp)
4047      {
4048         if (val_ret) *val_ret = 0;
4049         INF("part not found");
4050         return ret;
4051      }
4052    if (rp->chosen_description)
4053      {
4054         if (val_ret) *val_ret = rp->chosen_description->state.value;
4055         if (rp->chosen_description->state.name)
4056           ret = rp->chosen_description->state.name;
4057         else
4058           ret = "default";
4059         return ret;
4060      }
4061    else
4062      {
4063         if (rp->param1.description)
4064           {
4065              if (val_ret) *val_ret = rp->param1.description->state.value;
4066              if (rp->param1.description->state.name)
4067                ret = rp->param1.description->state.name;
4068              else
4069                ret = "default";
4070              return ret;
4071           }
4072      }
4073    if (val_ret) *val_ret = 0;
4074 
4075    return ret;
4076 }
4077 
4078 Edje_Drag_Dir
_edje_object_part_drag_dir_get(Edje * ed,const char * part)4079 _edje_object_part_drag_dir_get(Edje *ed, const char *part)
4080 {
4081    Edje_Drag_Dir ret;
4082    Edje_Real_Part *rp;
4083    ret = EDJE_DRAG_DIR_NONE;
4084 
4085    if ((!ed) || (!part)) return ret;
4086 
4087    /* Need to recalc before providing the object. */
4088    _edje_recalc_do(ed);
4089 
4090    rp = _edje_real_part_recursive_get(&ed, part);
4091    if (!rp) return ret;
4092    if ((rp->part->dragable.x) && (rp->part->dragable.y)) ret = EDJE_DRAG_DIR_XY;
4093    else if (rp->part->dragable.x)
4094      ret = EDJE_DRAG_DIR_X;
4095    else if (rp->part->dragable.y)
4096      ret = EDJE_DRAG_DIR_Y;
4097 
4098    return ret;
4099 }
4100 
4101 Eina_Bool
_edje_object_part_drag_value_set(Edje * ed,const char * part,double dx,double dy)4102 _edje_object_part_drag_value_set(Edje *ed, const char *part, double dx, double dy)
4103 {
4104    Edje_Real_Part *rp = NULL;
4105    Edje_User_Defined *eud;
4106    Eina_List *l, *ll;
4107 
4108    if ((!ed) || (!part)) return EINA_FALSE;
4109    if (ed->file)
4110      {
4111         rp = _edje_real_part_recursive_get(&ed, part);
4112         if (!rp) return EINA_FALSE;
4113         if (!rp->drag) return EINA_FALSE;
4114      }
4115 
4116    l = eina_hash_find(ed->user_defined, part);
4117    EINA_LIST_FOREACH(l, ll, eud)
4118      if (eud->type == EDJE_USER_DRAG_VALUE)
4119        {
4120           eud->u.drag_position.x = dx;
4121           eud->u.drag_position.y = dy;
4122           break;
4123        }
4124    if (!eud)
4125      {
4126         eud = _edje_user_definition_new(EDJE_USER_DRAG_VALUE, part, ed);
4127         if (eud)
4128           {
4129              eud->u.drag_position.x = dx;
4130              eud->u.drag_position.y = dy;
4131           }
4132      }
4133    if (!ed->file) return EINA_TRUE;
4134 
4135    if (rp->part->dragable.confine_id != -1)
4136      {
4137         dx = CLAMP(dx, 0.0, 1.0);
4138         dy = CLAMP(dy, 0.0, 1.0);
4139      }
4140    if (rp->part->dragable.x < 0) dx = 1.0 - dx;
4141    if (rp->part->dragable.y < 0) dy = 1.0 - dy;
4142    if (EQ(rp->drag->val.x, FROM_DOUBLE(dx)) && EQ(rp->drag->val.y, FROM_DOUBLE(dy)))
4143      {
4144         return EINA_TRUE;
4145      }
4146    rp->drag->val.x = FROM_DOUBLE(dx);
4147    rp->drag->val.y = FROM_DOUBLE(dy);
4148 #ifdef EDJE_CALC_CACHE
4149    rp->invalidate = EINA_TRUE;
4150 #endif
4151    _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
4152    _edje_emit(ed, "drag,set", rp->part->name);
4153 
4154    return EINA_TRUE;
4155 }
4156 
4157 /* FIXME: Should this be x and y instead of dx/dy? */
4158 Eina_Bool
_edje_object_part_drag_value_get(Edje * ed,const char * part,double * dx,double * dy)4159 _edje_object_part_drag_value_get(Edje *ed, const char *part, double *dx, double *dy)
4160 {
4161    Edje_Real_Part *rp;
4162    double ddx, ddy;
4163 
4164    if ((!ed) || (!part))
4165      {
4166         if (dx) *dx = 0;
4167         if (dy) *dy = 0;
4168         return EINA_FALSE;
4169      }
4170 
4171    /* Need to recalc before providing the object. */
4172    _edje_recalc_do(ed);
4173 
4174    rp = _edje_real_part_recursive_get(&ed, part);
4175    if (!rp || !rp->drag)
4176      {
4177         if (dx) *dx = 0;
4178         if (dy) *dy = 0;
4179         return EINA_FALSE;
4180      }
4181    ddx = TO_DOUBLE(rp->drag->val.x);
4182    ddy = TO_DOUBLE(rp->drag->val.y);
4183    if (rp->part->dragable.x < 0) ddx = 1.0 - ddx;
4184    if (rp->part->dragable.y < 0) ddy = 1.0 - ddy;
4185    if (dx) *dx = ddx;
4186    if (dy) *dy = ddy;
4187 
4188    return EINA_TRUE;
4189 }
4190 
4191 Eina_Bool
_edje_object_part_drag_size_set(Edje * ed,const char * part,double dw,double dh)4192 _edje_object_part_drag_size_set(Edje *ed, const char *part, double dw, double dh)
4193 {
4194    Edje_Real_Part *rp = NULL;
4195    Edje_User_Defined *eud;
4196    Eina_List *l, *ll;
4197 
4198    if ((!ed) || (!part)) return EINA_FALSE;
4199    rp = _edje_real_part_recursive_get(&ed, part);
4200    if (ed->file)
4201      {
4202         if (!rp) return EINA_FALSE;
4203         if (!rp->drag) return EINA_FALSE;
4204      }
4205 
4206    l = eina_hash_find(ed->user_defined, part);
4207    EINA_LIST_FOREACH(l, ll, eud)
4208      if (eud->type == EDJE_USER_DRAG_SIZE)
4209        {
4210           eud->u.drag_size.w = dw;
4211           eud->u.drag_size.h = dh;
4212           break;
4213        }
4214    if (!eud)
4215      {
4216         eud = _edje_user_definition_new(EDJE_USER_DRAG_SIZE, part, ed);
4217         if (eud)
4218           {
4219              eud->u.drag_size.w = dw;
4220              eud->u.drag_size.h = dh;
4221           }
4222      }
4223    if (!ed->file) return EINA_TRUE;
4224 
4225    if (dw < 0.0) dw = 0.0;
4226    else if (dw > 1.0)
4227      dw = 1.0;
4228    if (dh < 0.0) dh = 0.0;
4229    else if (dh > 1.0)
4230      dh = 1.0;
4231    if (EQ(rp->drag->size.x, FROM_DOUBLE(dw)) && EQ(rp->drag->size.y, FROM_DOUBLE(dh)))
4232      {
4233         return EINA_TRUE;
4234      }
4235    rp->drag->size.x = FROM_DOUBLE(dw);
4236    rp->drag->size.y = FROM_DOUBLE(dh);
4237    ed->dirty = EINA_TRUE;
4238    ed->recalc_call = EINA_TRUE;
4239 #ifdef EDJE_CALC_CACHE
4240    rp->invalidate = EINA_TRUE;
4241 #endif
4242    _edje_recalc(ed);
4243 
4244    return EINA_TRUE;
4245 }
4246 
4247 Eina_Bool
_edje_object_part_drag_size_get(Edje * ed,const char * part,double * dw,double * dh)4248 _edje_object_part_drag_size_get(Edje *ed, const char *part, double *dw, double *dh)
4249 {
4250    Edje_Real_Part *rp;
4251 
4252    if ((!ed) || (!part))
4253      {
4254         if (dw) *dw = 0;
4255         if (dh) *dh = 0;
4256         return EINA_FALSE;
4257      }
4258 
4259    /* Need to recalc before providing the object. */
4260    _edje_recalc_do(ed);
4261 
4262    rp = _edje_real_part_recursive_get(&ed, part);
4263    if (!rp || !rp->drag)
4264      {
4265         if (dw) *dw = 0;
4266         if (dh) *dh = 0;
4267         return EINA_FALSE;
4268      }
4269    if (dw) *dw = TO_DOUBLE(rp->drag->size.x);
4270    if (dh) *dh = TO_DOUBLE(rp->drag->size.y);
4271 
4272    return EINA_TRUE;
4273 }
4274 
4275 Eina_Bool
_edje_object_part_drag_step_set(Edje * ed,const char * part,double dx,double dy)4276 _edje_object_part_drag_step_set(Edje *ed, const char *part, double dx, double dy)
4277 {
4278    Edje_Real_Part *rp = NULL;
4279    Edje_User_Defined *eud;
4280    Eina_List *l, *ll;
4281 
4282    if ((!ed) || (!part)) return EINA_FALSE;
4283    rp = _edje_real_part_recursive_get(&ed, part);
4284    if (ed->file)
4285      {
4286         if (!rp) return EINA_FALSE;
4287         if (!rp->drag) return EINA_FALSE;
4288      }
4289 
4290    l = eina_hash_find(ed->user_defined, part);
4291    EINA_LIST_FOREACH(l, ll, eud)
4292      if (eud->type == EDJE_USER_DRAG_STEP)
4293        {
4294           eud->u.drag_position.x = dx;
4295           eud->u.drag_position.y = dy;
4296           break;
4297        }
4298    if (!eud)
4299      {
4300         eud = _edje_user_definition_new(EDJE_USER_DRAG_STEP, part, ed);
4301         if (eud)
4302           {
4303              eud->u.drag_position.x = dx;
4304              eud->u.drag_position.y = dy;
4305           }
4306      }
4307    if (!ed->file) return EINA_TRUE;
4308 
4309    if (dx < 0.0) dx = 0.0;
4310    else if (dx > 1.0)
4311      dx = 1.0;
4312    if (dy < 0.0) dy = 0.0;
4313    else if (dy > 1.0)
4314      dy = 1.0;
4315    rp->drag->step.x = FROM_DOUBLE(dx);
4316    rp->drag->step.y = FROM_DOUBLE(dy);
4317 #ifdef EDJE_CALC_CACHE
4318    rp->invalidate = EINA_TRUE;
4319 #endif
4320 
4321    return EINA_TRUE;
4322 }
4323 
4324 Eina_Bool
_edje_object_part_drag_step_get(Edje * ed,const char * part,double * dx,double * dy)4325 _edje_object_part_drag_step_get(Edje *ed, const char *part, double *dx, double *dy)
4326 {
4327    Edje_Real_Part *rp;
4328 
4329    if ((!ed) || (!part))
4330      {
4331         if (dx) *dx = 0;
4332         if (dy) *dy = 0;
4333         return EINA_FALSE;
4334      }
4335 
4336    /* Need to recalc before providing the object. */
4337    _edje_recalc_do(ed);
4338 
4339    rp = _edje_real_part_recursive_get(&ed, part);
4340    if (!rp || !rp->drag)
4341      {
4342         if (dx) *dx = 0;
4343         if (dy) *dy = 0;
4344         return EINA_FALSE;
4345      }
4346    if (dx) *dx = TO_DOUBLE(rp->drag->step.x);
4347    if (dy) *dy = TO_DOUBLE(rp->drag->step.y);
4348 
4349    return EINA_TRUE;
4350 }
4351 
4352 Eina_Bool
_edje_object_part_drag_page_set(Edje * ed,const char * part,double dx,double dy)4353 _edje_object_part_drag_page_set(Edje *ed, const char *part, double dx, double dy)
4354 {
4355    Edje_Real_Part *rp = NULL;
4356    Edje_User_Defined *eud;
4357    Eina_List *l, *ll;
4358 
4359    if ((!ed) || (!part)) return EINA_FALSE;
4360    if (ed->file)
4361      {
4362         rp = _edje_real_part_recursive_get(&ed, part);
4363         if (!rp) return EINA_FALSE;
4364         if (!rp->drag) return EINA_FALSE;
4365      }
4366 
4367    l = eina_hash_find(ed->user_defined, part);
4368    EINA_LIST_FOREACH(l, ll, eud)
4369      if (eud->type == EDJE_USER_DRAG_PAGE)
4370        {
4371           eud->u.drag_position.x = dx;
4372           eud->u.drag_position.y = dy;
4373           break;
4374        }
4375    if (!eud)
4376      {
4377         eud = _edje_user_definition_new(EDJE_USER_DRAG_PAGE, part, ed);
4378         if (eud)
4379           {
4380              eud->u.drag_position.x = dx;
4381              eud->u.drag_position.y = dy;
4382           }
4383      }
4384    if (!ed->file) return EINA_TRUE;
4385 
4386    if (dx < 0.0) dx = 0.0;
4387    else if (dx > 1.0)
4388      dx = 1.0;
4389    if (dy < 0.0) dy = 0.0;
4390    else if (dy > 1.0)
4391      dy = 1.0;
4392    rp->drag->page.x = FROM_DOUBLE(dx);
4393    rp->drag->page.y = FROM_DOUBLE(dy);
4394 #ifdef EDJE_CALC_CACHE
4395    rp->invalidate = EINA_TRUE;
4396 #endif
4397 
4398    return EINA_TRUE;
4399 }
4400 
4401 Eina_Bool
_edje_object_part_drag_page_get(Edje * ed,const char * part,double * dx,double * dy)4402 _edje_object_part_drag_page_get(Edje *ed, const char *part, double *dx, double *dy)
4403 {
4404    Edje_Real_Part *rp;
4405 
4406    if ((!ed) || (!part))
4407      {
4408         if (dx) *dx = 0;
4409         if (dy) *dy = 0;
4410         return EINA_FALSE;
4411      }
4412 
4413    /* Need to recalc before providing the object. */
4414    _edje_recalc_do(ed);
4415 
4416    rp = _edje_real_part_recursive_get(&ed, part);
4417    if (!rp || !rp->drag)
4418      {
4419         if (dx) *dx = 0;
4420         if (dy) *dy = 0;
4421         return EINA_FALSE;
4422      }
4423    if (dx) *dx = TO_DOUBLE(rp->drag->page.x);
4424    if (dy) *dy = TO_DOUBLE(rp->drag->page.y);
4425 
4426    return EINA_TRUE;
4427 }
4428 
4429 Eina_Bool
_edje_object_part_drag_step(Edje * ed,const char * part,double dx,double dy)4430 _edje_object_part_drag_step(Edje *ed, const char *part, double dx, double dy)
4431 {
4432    Edje_Real_Part *rp = NULL;
4433    FLOAT_T px, py;
4434    Edje_User_Defined *eud;
4435    Eina_List *l, *ll;
4436 
4437    if ((!ed) || (!part)) return EINA_FALSE;
4438    if (ed->file)
4439      {
4440         rp = _edje_real_part_recursive_get(&ed, part);
4441         if (!rp) return EINA_FALSE;
4442         if (!rp->drag) return EINA_FALSE;
4443      }
4444 
4445    l = eina_hash_find(ed->user_defined, part);
4446    EINA_LIST_FOREACH(l, ll, eud)
4447      if (eud->type == EDJE_USER_DRAG_STEP)
4448        {
4449           eud->u.drag_position.x = dx;
4450           eud->u.drag_position.y = dy;
4451           break;
4452        }
4453    if (!eud)
4454      {
4455         eud = _edje_user_definition_new(EDJE_USER_DRAG_STEP, part, ed);
4456         if (eud)
4457           {
4458              eud->u.drag_position.x = dx;
4459              eud->u.drag_position.y = dy;
4460           }
4461      }
4462    if (!ed->file) return EINA_TRUE;
4463 
4464    px = rp->drag->val.x;
4465    py = rp->drag->val.y;
4466    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx),
4467                                  MUL(rp->drag->step.x, rp->part->dragable.x)));
4468    rp->drag->val.y = ADD(py, MUL(FROM_DOUBLE(dy),
4469                                  MUL(rp->drag->step.y, rp->part->dragable.y)));
4470    rp->drag->val.x = CLAMP(rp->drag->val.x, ZERO, FROM_DOUBLE(1.0));
4471    rp->drag->val.y = CLAMP(rp->drag->val.y, ZERO, FROM_DOUBLE(1.0));
4472    if (EQ(px, rp->drag->val.x) && EQ(py, rp->drag->val.y))
4473      {
4474         return EINA_TRUE;
4475      }
4476 #ifdef EDJE_CALC_CACHE
4477    rp->invalidate = EINA_TRUE;
4478 #endif
4479    _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
4480    _edje_emit(ed, "drag,step", rp->part->name);
4481 
4482    return EINA_TRUE;
4483 }
4484 
4485 Eina_Bool
_edje_object_part_drag_page(Edje * ed,const char * part,double dx,double dy)4486 _edje_object_part_drag_page(Edje *ed, const char *part, double dx, double dy)
4487 {
4488    Edje_Real_Part *rp = NULL;
4489    FLOAT_T px, py;
4490    Edje_User_Defined *eud;
4491    Eina_List *l, *ll;
4492 
4493    if ((!ed) || (!part)) return EINA_FALSE;
4494    if (ed->file)
4495      {
4496         rp = _edje_real_part_recursive_get(&ed, part);
4497         if (!rp) return EINA_FALSE;
4498         if (!rp->drag) return EINA_FALSE;
4499      }
4500 
4501    l = eina_hash_find(ed->user_defined, part);
4502    EINA_LIST_FOREACH(l, ll, eud)
4503      if (eud->type == EDJE_USER_DRAG_PAGE)
4504        {
4505           eud->u.drag_position.x = dx;
4506           eud->u.drag_position.y = dy;
4507           break;
4508        }
4509    if (!eud)
4510      {
4511         eud = _edje_user_definition_new(EDJE_USER_DRAG_PAGE, part, ed);
4512         if (eud)
4513           {
4514              eud->u.drag_position.x = dx;
4515              eud->u.drag_position.y = dy;
4516           }
4517      }
4518    if (!ed->file) return EINA_TRUE;
4519 
4520    px = rp->drag->val.x;
4521    py = rp->drag->val.y;
4522    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx), MUL(rp->drag->page.x, rp->part->dragable.x)));
4523    rp->drag->val.y = ADD(py, MUL(FROM_DOUBLE(dy), MUL(rp->drag->page.y, rp->part->dragable.y)));
4524    rp->drag->val.x = CLAMP(rp->drag->val.x, ZERO, FROM_DOUBLE(1.0));
4525    rp->drag->val.y = CLAMP(rp->drag->val.y, ZERO, FROM_DOUBLE(1.0));
4526    if (EQ(px, rp->drag->val.x) && EQ(py, rp->drag->val.y))
4527      {
4528         return EINA_TRUE;
4529      }
4530 #ifdef EDJE_CALC_CACHE
4531    rp->invalidate = EINA_TRUE;
4532 #endif
4533    _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
4534    _edje_emit(ed, "drag,page", rp->part->name);
4535 
4536    return EINA_TRUE;
4537 }
4538 
4539 void
_edje_box_init(void)4540 _edje_box_init(void)
4541 {
4542 }
4543 
4544 void
_edje_box_shutdown(void)4545 _edje_box_shutdown(void)
4546 {
4547    if (!_edje_box_layout_registry)
4548      return;
4549 
4550    eina_rbtree_delete
4551      (_edje_box_layout_registry, _edje_box_layout_part_external_free, NULL);
4552    _edje_box_layout_registry = NULL;
4553 }
4554 
4555 Eina_Bool
_edje_part_box_append(Edje * ed,const char * part,Evas_Object * child)4556 _edje_part_box_append(Edje *ed, const char *part, Evas_Object *child)
4557 {
4558    Eina_Bool ret;
4559    Edje_Real_Part *rp = NULL;
4560    ret = EINA_FALSE;
4561 
4562    if ((!ed) || (!part) || (!child)) return ret;
4563 
4564    if (ed->file)
4565      {
4566         rp = _edje_real_part_recursive_get(&ed, part);
4567         if (!rp) return ret;
4568         if (rp->part->type != EDJE_PART_TYPE_BOX) return ret;
4569      }
4570 
4571    if ((!ed->file) || _edje_real_part_box_append(ed, rp, child))
4572      {
4573         Edje_User_Defined *eud;
4574 
4575         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
4576         if (!eud) return ret;
4577         eud->u.box.child = child;
4578         eud->u.box.index = -1;
4579 
4580         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
4581         ret = EINA_TRUE;
4582      }
4583 
4584    return ret;
4585 }
4586 
4587 Eina_Bool
_edje_part_box_prepend(Edje * ed,const char * part,Evas_Object * child)4588 _edje_part_box_prepend(Edje *ed, const char *part, Evas_Object *child)
4589 {
4590    Eina_Bool ret;
4591    Edje_Real_Part *rp = NULL;
4592    ret = EINA_FALSE;
4593 
4594    if ((!ed) || (!part)) return ret;
4595 
4596    if (ed->file)
4597      {
4598         rp = _edje_real_part_recursive_get(&ed, part);
4599         if (!rp) return ret;
4600         if (rp->part->type != EDJE_PART_TYPE_BOX) return ret;
4601      }
4602 
4603    if ((!ed->file) || _edje_real_part_box_prepend(ed, rp, child))
4604      {
4605         Edje_User_Defined *eud;
4606 
4607         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
4608         if (!eud) return ret;
4609         eud->u.box.child = child;
4610 
4611         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
4612         ret = EINA_TRUE;
4613      }
4614 
4615    return ret;
4616 }
4617 
4618 Eina_Bool
_edje_part_box_insert_before(Edje * ed,const char * part,Evas_Object * child,const Evas_Object * reference)4619 _edje_part_box_insert_before(Edje *ed, const char *part, Evas_Object *child, const Evas_Object *reference)
4620 {
4621    Eina_Bool ret;
4622    Edje_Real_Part *rp = NULL;
4623    ret = EINA_FALSE;
4624 
4625    if ((!ed) || (!part)) return ret;
4626 
4627    if (ed->file)
4628      {
4629         rp = _edje_real_part_recursive_get(&ed, part);
4630         if (!rp) return ret;
4631         if (rp->part->type != EDJE_PART_TYPE_BOX) return ret;
4632      }
4633 
4634    if ((!ed->file) || _edje_real_part_box_insert_before(ed, rp, child, reference))
4635      {
4636         Edje_User_Defined *eud;
4637 
4638         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
4639         if (!eud) return ret;
4640         eud->u.box.child = child;
4641 
4642         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
4643         ret = EINA_TRUE;
4644      }
4645 
4646    return ret;
4647 }
4648 
4649 Eina_Bool
_edje_part_box_insert_after(Edje * ed,const char * part,Evas_Object * child,const Evas_Object * reference)4650 _edje_part_box_insert_after(Edje *ed, const char *part, Evas_Object *child, const Evas_Object *reference)
4651 {
4652    Eina_Bool ret;
4653    Edje_Real_Part *rp = NULL;
4654    ret = EINA_FALSE;
4655 
4656    if ((!ed) || (!part)) return ret;
4657 
4658    if (ed->file)
4659      {
4660         rp = _edje_real_part_recursive_get(&ed, part);
4661         if (!rp) return ret;
4662         if (rp->part->type != EDJE_PART_TYPE_BOX) return ret;
4663      }
4664 
4665    if ((!ed->file) || _edje_real_part_box_insert_after(ed, rp, child, reference))
4666      {
4667         Edje_User_Defined *eud;
4668 
4669         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
4670         if (!eud) return ret;
4671         eud->u.box.child = child;
4672 
4673         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
4674         ret = EINA_TRUE;
4675      }
4676 
4677    return ret;
4678 }
4679 
4680 Eina_Bool
_edje_part_box_insert_at(Edje * ed,const char * part,Evas_Object * child,unsigned int pos)4681 _edje_part_box_insert_at(Edje *ed, const char *part, Evas_Object *child, unsigned int pos)
4682 {
4683    Eina_Bool ret;
4684    Edje_Real_Part *rp = NULL;
4685    ret = EINA_FALSE;
4686 
4687    if ((!ed) || (!part)) return ret;
4688 
4689    if (ed->file)
4690      {
4691         rp = _edje_real_part_recursive_get(&ed, part);
4692         if (!rp) return ret;
4693         if (rp->part->type != EDJE_PART_TYPE_BOX) return ret;
4694      }
4695 
4696    if ((!ed->file) || _edje_real_part_box_insert_at(ed, rp, child, pos))
4697      {
4698         Edje_User_Defined *eud;
4699 
4700         eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
4701         if (!eud) return ret;
4702         eud->u.box.child = child;
4703 
4704         evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
4705         ret = EINA_TRUE;
4706      }
4707 
4708    return ret;
4709 }
4710 
4711 static void
_edje_part_box_remove_user_definition(Edje * ed,Eina_Stringshare * part,Evas_Object * child)4712 _edje_part_box_remove_user_definition(Edje *ed, Eina_Stringshare *part, Evas_Object *child)
4713 {
4714    Edje_User_Defined *eud;
4715    Eina_List *l, *ll;
4716 
4717    l = eina_hash_find(ed->user_defined, part);
4718    EINA_LIST_FOREACH(l, ll, eud)
4719      if (eud->type == EDJE_USER_BOX_PACK && eud->u.box.child == child)
4720        {
4721           _edje_user_definition_free(eud);
4722           return;
4723        }
4724 }
4725 
4726 Evas_Object *
_edje_part_box_remove(Edje * ed,const char * part,Evas_Object * child)4727 _edje_part_box_remove(Edje *ed, const char *part, Evas_Object *child)
4728 {
4729    Edje_Real_Part *rp;
4730    Evas_Object *r;
4731 
4732    if ((!ed) || (!part)) return NULL;
4733 
4734    rp = _edje_real_part_recursive_get(&ed, part);
4735    if (!rp) return NULL;
4736    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
4737 
4738    r = _edje_real_part_box_remove(ed, rp, child);
4739 
4740    if (r) _edje_part_box_remove_user_definition(ed, part, r);
4741    return r;
4742 }
4743 
4744 Evas_Object *
_edje_part_box_remove_at(Edje * ed,const char * part,unsigned int pos)4745 _edje_part_box_remove_at(Edje *ed, const char *part, unsigned int pos)
4746 {
4747    Edje_Real_Part *rp;
4748    Evas_Object *r;
4749 
4750    if ((!ed) || (!part)) return NULL;
4751 
4752    rp = _edje_real_part_recursive_get(&ed, part);
4753    if (!rp) return NULL;
4754    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
4755 
4756    r = _edje_real_part_box_remove_at(ed, rp, pos);
4757 
4758    if (r) _edje_part_box_remove_user_definition(ed, part, r);
4759    return r;
4760 }
4761 
4762 Evas_Object *
_edje_part_box_content_at(Edje * ed,const char * part,unsigned int pos)4763 _edje_part_box_content_at(Edje *ed, const char *part, unsigned int pos)
4764 {
4765    Edje_Real_Part *rp;
4766    Evas_Object *r;
4767 
4768    if ((!ed) || (!part)) return NULL;
4769 
4770    rp = _edje_real_part_recursive_get(&ed, part);
4771    if (!rp) return NULL;
4772    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
4773 
4774    r = _edje_real_part_box_content_at(ed, rp, pos);
4775    return r;
4776 }
4777 
4778 Eina_Bool
_edje_part_box_remove_all(Edje * ed,const char * part,Eina_Bool clear)4779 _edje_part_box_remove_all(Edje *ed, const char *part, Eina_Bool clear)
4780 {
4781    Eina_Bool ret;
4782    Edje_Real_Part *rp;
4783    ret = EINA_FALSE;
4784 
4785    if ((!ed) || (!part)) return ret;
4786 
4787    rp = _edje_real_part_recursive_get(&ed, part);
4788    if (!rp) return ret;
4789    if (rp->part->type != EDJE_PART_TYPE_BOX) return ret;
4790 
4791    if (_edje_real_part_box_remove_all(ed, rp, clear))
4792      {
4793         ret = EINA_TRUE;
4794         eina_hash_del_by_key(ed->user_defined, part);
4795      }
4796 
4797    return ret;
4798 }
4799 
4800 typedef struct _Part_Iterator Part_Iterator;
4801 struct _Part_Iterator
4802 {
4803    Eina_Iterator  iterator;
4804    Eo            *object;
4805    Edje          *ed;
4806    unsigned       index;
4807 };
4808 
4809 static Eina_Bool
_part_iterator_next(Part_Iterator * it,void ** data)4810 _part_iterator_next(Part_Iterator *it, void **data)
4811 {
4812    for (; it->index < it->ed->table_parts_size; it->index++)
4813      {
4814         Edje_Real_Part *rp = it->ed->table_parts[it->index];
4815         if (rp->part->access)
4816           {
4817              if (data) *data = (void*) rp->part->name;
4818              it->index++;
4819              return EINA_TRUE;
4820           }
4821      }
4822 
4823    return EINA_FALSE;
4824 }
4825 
4826 static Eo *
_part_iterator_get_container(Part_Iterator * it)4827 _part_iterator_get_container(Part_Iterator *it)
4828 {
4829    return it->object;
4830 }
4831 
4832 static void
_part_iterator_free(Part_Iterator * it)4833 _part_iterator_free(Part_Iterator *it)
4834 {
4835    free(it);
4836 }
4837 
4838 EOLIAN Eina_Iterator *
_efl_canvas_layout_access_part_iterate(Eo * obj EINA_UNUSED,Edje * ed)4839 _efl_canvas_layout_access_part_iterate(Eo *obj EINA_UNUSED, Edje *ed)
4840 {
4841    Part_Iterator *it;
4842 
4843    it = calloc(1, sizeof(*it));
4844    if (!it) return NULL;
4845 
4846    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
4847 
4848    it->iterator.version = EINA_ITERATOR_VERSION;
4849    it->iterator.next = FUNC_ITERATOR_NEXT(_part_iterator_next);
4850    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_part_iterator_get_container);
4851    it->iterator.free = FUNC_ITERATOR_FREE(_part_iterator_free);
4852    it->object = obj;
4853    it->ed = ed;
4854    it->index = 0;
4855 
4856    return &it->iterator;
4857 }
4858 
4859 EAPI Eina_List *
edje_object_access_part_list_get(const Edje_Object * obj)4860 edje_object_access_part_list_get(const Edje_Object *obj)
4861 {
4862    Eina_List *access_parts = NULL;
4863    Eina_Iterator *it;
4864    const char *str;
4865 
4866    it = efl_canvas_layout_access_part_iterate((Eo *) obj);
4867    EINA_ITERATOR_FOREACH(it, str)
4868      access_parts = eina_list_append(access_parts, str);
4869    eina_iterator_free(it);
4870 
4871    return access_parts;
4872 }
4873 
4874 static void
_edje_child_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * child,void * einfo EINA_UNUSED)4875 _edje_child_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *child, void *einfo EINA_UNUSED)
4876 {
4877    Edje_Real_Part *rp = data;
4878    Edje_User_Defined *eud;
4879    Eina_List *l, *ll;
4880    Edje *ed = evas_object_data_get(child, ".edje");
4881 
4882    if (!ed) return;
4883    l = eina_hash_find(ed->user_defined, rp->part->name);
4884    EINA_LIST_FOREACH(l, ll, eud)
4885      if (rp->part->type == EDJE_PART_TYPE_BOX)
4886        {
4887           if (eud->type == EDJE_USER_BOX_PACK &&
4888               eud->u.box.child == child)
4889             {
4890                _edje_user_definition_free(eud);
4891                break;
4892             }
4893        }
4894      else if (rp->part->type == EDJE_PART_TYPE_TABLE)
4895        {
4896           if (eud->type == EDJE_USER_TABLE_PACK &&
4897               eud->u.table.child == child)
4898             {
4899                _edje_user_definition_free(eud);
4900                break;
4901             }
4902        }
4903 
4904    ed->dirty = EINA_TRUE;
4905    ed->recalc_call = EINA_TRUE;
4906 #ifdef EDJE_CALC_CACHE
4907    rp->invalidate = EINA_TRUE;
4908 #endif
4909    _edje_recalc(ed);
4910 }
4911 
4912 static void
_edje_child_add(Edje * ed,Edje_Real_Part * rp,Evas_Object * child)4913 _edje_child_add(Edje *ed, Edje_Real_Part *rp, Evas_Object *child)
4914 {
4915    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_child_del_cb, rp);
4916    evas_object_data_set(child, ".edje", ed);
4917    if (!ed) return;
4918    efl_parent_set(child, ed->obj);
4919    ed->dirty = EINA_TRUE;
4920    ed->recalc_call = EINA_TRUE;
4921 #ifdef EDJE_CALC_CACHE
4922    rp->invalidate = EINA_TRUE;
4923 #endif
4924    _edje_recalc(ed);
4925 }
4926 
4927 static void
_eo_unparent_helper(Eo * child,Eo * parent)4928 _eo_unparent_helper(Eo *child, Eo *parent)
4929 {
4930    if (efl_invalidated_get(child)) return ;
4931    if (efl_parent_get(child) == parent)
4932      {
4933         if (efl_invalidated_get(evas_object_evas_get(parent)))
4934           // Temporary reparenting children to the main loop.
4935           // They are about to die, but shouldn't just yet.
4936           {
4937              efl_parent_set(child, efl_main_loop_get());
4938           }
4939         else
4940           {
4941              efl_parent_set(child, evas_object_evas_get(parent));
4942           }
4943      }
4944 }
4945 
4946 static void
_edje_child_remove(Edje * ed,Edje_Real_Part * rp,Evas_Object * child)4947 _edje_child_remove(Edje *ed, Edje_Real_Part *rp, Evas_Object *child)
4948 {
4949    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL, _edje_child_del_cb, rp);
4950    evas_object_data_del(child, ".edje");
4951    if (!ed) return;
4952    _eo_unparent_helper(child, ed->obj);
4953    ed->dirty = EINA_TRUE;
4954    ed->recalc_call = EINA_TRUE;
4955 #ifdef EDJE_CALC_CACHE
4956    rp->invalidate = EINA_TRUE;
4957 #endif
4958    _edje_recalc(ed);
4959 }
4960 
4961 Eina_Bool
_edje_real_part_box_append(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj)4962 _edje_real_part_box_append(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj)
4963 {
4964    Evas_Object_Box_Option *opt;
4965 
4966    opt = evas_object_box_append(rp->object, child_obj);
4967    if (!opt) return EINA_FALSE;
4968 
4969    if (!_edje_box_layout_add_child(rp, child_obj))
4970      {
4971         evas_object_box_remove(rp->object, child_obj);
4972         return EINA_FALSE;
4973      }
4974 
4975    _edje_child_add(ed, rp, child_obj);
4976 
4977    return EINA_TRUE;
4978 }
4979 
4980 Eina_Bool
_edje_real_part_box_prepend(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj)4981 _edje_real_part_box_prepend(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj)
4982 {
4983    Evas_Object_Box_Option *opt;
4984 
4985    opt = evas_object_box_prepend(rp->object, child_obj);
4986    if (!opt) return EINA_FALSE;
4987 
4988    if (!_edje_box_layout_add_child(rp, child_obj))
4989      {
4990         evas_object_box_remove(rp->object, child_obj);
4991         return EINA_FALSE;
4992      }
4993 
4994    _edje_child_add(ed, rp, child_obj);
4995 
4996    return EINA_TRUE;
4997 }
4998 
4999 Eina_Bool
_edje_real_part_box_insert_before(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj,const Evas_Object * ref)5000 _edje_real_part_box_insert_before(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj, const Evas_Object *ref)
5001 {
5002    Evas_Object_Box_Option *opt;
5003 
5004    opt = evas_object_box_insert_before(rp->object, child_obj, ref);
5005    if (!opt) return EINA_FALSE;
5006 
5007    if (!_edje_box_layout_add_child(rp, child_obj))
5008      {
5009         evas_object_box_remove(rp->object, child_obj);
5010         return EINA_FALSE;
5011      }
5012 
5013    _edje_child_add(ed, rp, child_obj);
5014 
5015    return EINA_TRUE;
5016 }
5017 
5018 Eina_Bool
_edje_real_part_box_insert_after(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj,const Evas_Object * ref)5019 _edje_real_part_box_insert_after(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj, const Evas_Object *ref)
5020 {
5021    Evas_Object_Box_Option *opt;
5022 
5023    opt = evas_object_box_insert_after(rp->object, child_obj, ref);
5024    if (!opt) return EINA_FALSE;
5025 
5026    if (!_edje_box_layout_add_child(rp, child_obj))
5027      {
5028         evas_object_box_remove(rp->object, child_obj);
5029         return EINA_FALSE;
5030      }
5031 
5032    _edje_child_add(ed, rp, child_obj);
5033 
5034    return EINA_TRUE;
5035 }
5036 
5037 Eina_Bool
_edje_real_part_box_insert_at(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj,unsigned int pos)5038 _edje_real_part_box_insert_at(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj, unsigned int pos)
5039 {
5040    Evas_Object_Box_Option *opt;
5041 
5042    opt = evas_object_box_insert_at(rp->object, child_obj, pos);
5043    if (!opt) return EINA_FALSE;
5044 
5045    if (!_edje_box_layout_add_child(rp, child_obj))
5046      {
5047         evas_object_box_remove(rp->object, child_obj);
5048         return EINA_FALSE;
5049      }
5050 
5051    _edje_child_add(ed, rp, child_obj);
5052 
5053    return EINA_TRUE;
5054 }
5055 
5056 Evas_Object *
_edje_real_part_box_content_at(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,unsigned int pos)5057 _edje_real_part_box_content_at(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, unsigned int pos)
5058 {
5059    Evas_Object_Box_Option *opt;
5060    Evas_Object_Box_Data *priv;
5061 
5062    priv = efl_data_scope_get(rp->object, EVAS_BOX_CLASS);
5063    opt = eina_list_nth(priv->children, pos);
5064    if (!opt) return NULL;
5065    return opt->obj;
5066 }
5067 
5068 Evas_Object *
_edje_real_part_box_remove(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj)5069 _edje_real_part_box_remove(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj)
5070 {
5071    if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
5072    if (!evas_object_box_remove(rp->object, child_obj)) return NULL;
5073    _edje_box_layout_remove_child(rp, child_obj);
5074    _edje_child_remove(ed, rp, child_obj);
5075    return child_obj;
5076 }
5077 
5078 Evas_Object *
_edje_real_part_box_remove_at(Edje * ed,Edje_Real_Part * rp,unsigned int pos)5079 _edje_real_part_box_remove_at(Edje *ed, Edje_Real_Part *rp, unsigned int pos)
5080 {
5081    Evas_Object_Box_Option *opt;
5082    Evas_Object_Box_Data *priv;
5083    Evas_Object *child_obj;
5084 
5085    priv = efl_data_scope_get(rp->object, EVAS_BOX_CLASS);
5086    opt = eina_list_nth(priv->children, pos);
5087    if (!opt) return NULL;
5088    child_obj = opt->obj;
5089    if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
5090    if (!evas_object_box_remove_at(rp->object, pos)) return NULL;
5091    _edje_box_layout_remove_child(rp, child_obj);
5092    _edje_child_remove(ed, rp, child_obj);
5093    return child_obj;
5094 }
5095 
5096 Eina_Bool
_edje_real_part_box_remove_all(Edje * ed,Edje_Real_Part * rp,Eina_Bool clear)5097 _edje_real_part_box_remove_all(Edje *ed, Edje_Real_Part *rp, Eina_Bool clear)
5098 {
5099    Eina_List *children;
5100    int i = 0;
5101 
5102    children = evas_object_box_children_get(rp->object);
5103    while (children)
5104      {
5105         Evas_Object *child_obj = children->data;
5106         if (evas_object_data_get(child_obj, "\377 edje.box_item"))
5107           i++;
5108         else
5109           {
5110              _edje_box_layout_remove_child(rp, child_obj);
5111              _edje_child_remove(ed, rp, child_obj);
5112              if (!evas_object_box_remove_at(rp->object, i))
5113                {
5114                   eina_list_free(children);
5115                   return EINA_FALSE;
5116                }
5117              if (clear)
5118                evas_object_del(child_obj);
5119           }
5120         children = eina_list_remove_list(children, children);
5121      }
5122    return EINA_TRUE;
5123 }
5124 
5125 Evas_Object *
_edje_part_table_child_get(Edje * ed,const char * part,unsigned int col,unsigned int row)5126 _edje_part_table_child_get(Edje *ed, const char *part, unsigned int col, unsigned int row)
5127 {
5128    Edje_Real_Part *rp;
5129 
5130    if ((!ed) || (!part)) return NULL;
5131 
5132    rp = _edje_real_part_recursive_get(&ed, part);
5133    if (!rp) return NULL;
5134    if (rp->part->type != EDJE_PART_TYPE_TABLE) return NULL;
5135 
5136    return evas_object_table_child_get(rp->object, col, row);
5137 }
5138 
5139 Eina_Bool
_edje_part_table_pack(Edje * ed,const char * part,Evas_Object * child_obj,unsigned short col,unsigned short row,unsigned short colspan,unsigned short rowspan)5140 _edje_part_table_pack(Edje *ed, const char *part, Evas_Object *child_obj, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
5141 {
5142    Eina_Bool ret;
5143    Edje_Real_Part *rp = NULL;
5144    Edje_User_Defined *eud;
5145    ret = EINA_FALSE;
5146 
5147    if ((!ed) || (!part)) return ret;
5148 
5149    if (ed->file)
5150      {
5151         rp = _edje_real_part_recursive_get(&ed, part);
5152         if (!rp) return ret;
5153         if (rp->part->type != EDJE_PART_TYPE_TABLE) return ret;
5154      }
5155 
5156    if ((!ed->file) || _edje_real_part_table_pack(ed, rp, child_obj, col, row, colspan, rowspan))
5157      {
5158         ret = EINA_TRUE;
5159         eud = _edje_user_definition_new(EDJE_USER_TABLE_PACK, part, ed);
5160         if (!eud) return ret;
5161 
5162         eud->u.table.child = child_obj;
5163         eud->u.table.col = col;
5164         eud->u.table.row = row;
5165         eud->u.table.colspan = colspan;
5166         eud->u.table.rowspan = rowspan;
5167 
5168         evas_object_event_callback_add(child_obj, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
5169      }
5170 
5171    return ret;
5172 }
5173 
5174 Eina_Bool
_edje_part_table_unpack(Edje * ed,const char * part,Evas_Object * child_obj)5175 _edje_part_table_unpack(Edje *ed, const char *part, Evas_Object *child_obj)
5176 {
5177    Eina_Bool ret;
5178    Edje_Real_Part *rp;
5179    ret = EINA_FALSE;
5180 
5181    if ((!ed) || (!part)) return ret;
5182 
5183    rp = _edje_real_part_recursive_get(&ed, part);
5184    if (!rp) return ret;
5185    if (rp->part->type != EDJE_PART_TYPE_TABLE) return ret;
5186 
5187    if (_edje_real_part_table_unpack(ed, rp, child_obj))
5188      {
5189         ret = EINA_TRUE;
5190         Edje_User_Defined *eud;
5191         Eina_List *l, *ll;
5192 
5193         l = eina_hash_find(ed->user_defined, part);
5194         EINA_LIST_FOREACH(l, ll, eud)
5195           if (eud->type == EDJE_USER_TABLE_PACK &&
5196               eud->u.table.child == child_obj)
5197             {
5198                _edje_user_definition_free(eud);
5199                break;
5200             }
5201      }
5202 
5203    return ret;
5204 }
5205 
5206 Eina_Bool
_edje_part_table_col_row_size_get(Edje * ed,const char * part,int * cols,int * rows)5207 _edje_part_table_col_row_size_get(Edje *ed, const char *part, int *cols, int *rows)
5208 {
5209    Edje_Real_Part *rp;
5210 
5211    if ((!ed) || (!part)) return EINA_FALSE;
5212 
5213    rp = _edje_real_part_recursive_get(&ed, part);
5214    if (!rp) return EINA_FALSE;
5215    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
5216 
5217    evas_object_table_col_row_size_get(rp->object, cols, rows);
5218 
5219    return EINA_TRUE;
5220 }
5221 
5222 Eina_Bool
_edje_part_table_clear(Edje * ed,const char * part,Eina_Bool clear)5223 _edje_part_table_clear(Edje *ed, const char *part, Eina_Bool clear)
5224 {
5225    Edje_Real_Part *rp;
5226 
5227    if ((!ed) || (!part)) return EINA_FALSE;
5228 
5229    rp = _edje_real_part_recursive_get(&ed, part);
5230    if (!rp) return EINA_FALSE;
5231    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
5232 
5233    _edje_real_part_table_clear(ed, rp, clear);
5234 
5235    return EINA_TRUE;
5236 }
5237 
5238 static void
_edje_perspective_obj_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)5239 _edje_perspective_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
5240 {
5241    Edje_Perspective *ps = data;
5242    Evas_Object *o;
5243 
5244    EINA_LIST_FREE(ps->users, o)
5245      {
5246         Edje *ed;
5247 
5248         ed = efl_data_scope_get(o, EFL_CANVAS_LAYOUT_CLASS);
5249         if (!ed) continue;
5250         ed->persp = NULL;
5251         ed->dirty = EINA_TRUE;
5252         ed->recalc_call = EINA_TRUE;
5253         _edje_recalc_do(ed);
5254      }
5255    free(ps);
5256 }
5257 
5258 EAPI Edje_Perspective *
edje_perspective_new(Evas * e)5259 edje_perspective_new(Evas *e)
5260 {
5261    Edje_Perspective *ps;
5262    Evas_Coord vx, vy, vw, vh;
5263 
5264    if (!e) return NULL;
5265    ps = calloc(1, sizeof(Edje_Perspective));
5266    ps->obj = evas_object_rectangle_add(e);
5267    evas_object_data_set(ps->obj, "_edje_perspective", ps);
5268    evas_object_event_callback_add(ps->obj, EVAS_CALLBACK_DEL, _edje_perspective_obj_del, ps);
5269    evas_output_viewport_get(e, &vx, &vy, &vw, &vh);
5270    ps->e = e;
5271    ps->px = vx + (vw / 2);
5272    ps->py = vy + (vh / 2);
5273    ps->z0 = 0;
5274    ps->foc = 1000;
5275    return ps;
5276 }
5277 
5278 EAPI void
edje_perspective_free(Edje_Perspective * ps)5279 edje_perspective_free(Edje_Perspective *ps)
5280 {
5281    if (!ps) return;
5282    evas_object_del(ps->obj);
5283 }
5284 
5285 EAPI void
edje_perspective_set(Edje_Perspective * ps,Evas_Coord px,Evas_Coord py,Evas_Coord z0,Evas_Coord foc)5286 edje_perspective_set(Edje_Perspective *ps, Evas_Coord px, Evas_Coord py, Evas_Coord z0, Evas_Coord foc)
5287 {
5288    Eina_List *l;
5289    Evas_Object *o;
5290 
5291    if (!ps) return;
5292    if ((ps->px == px) && (ps->py == py) && (ps->z0 == z0) && (ps->foc == foc)) return;
5293    ps->px = px;
5294    ps->py = py;
5295    ps->z0 = z0;
5296    ps->foc = foc;
5297    EINA_LIST_FOREACH(ps->users, l, o)
5298      {
5299         Edje *ed;
5300 
5301         ed = efl_data_scope_get(o, EFL_CANVAS_LAYOUT_CLASS);
5302         if (!ed) continue;
5303         if (!ed->persp)
5304           {
5305              ed->dirty = EINA_TRUE;
5306              ed->recalc_call = EINA_TRUE;
5307              _edje_recalc_do(ed);
5308           }
5309      }
5310    if (ps->global)
5311      {
5312         Edje *ed;
5313 
5314         EINA_INLIST_FOREACH(_edje_edjes, ed)
5315           {
5316              if (!ed->persp)
5317                {
5318                   ed->dirty = EINA_TRUE;
5319                   ed->recalc_call = EINA_TRUE;
5320                   _edje_recalc_do(ed);
5321                }
5322           }
5323      }
5324 }
5325 
5326 EAPI void
edje_perspective_global_set(Edje_Perspective * ps,Eina_Bool global)5327 edje_perspective_global_set(Edje_Perspective *ps, Eina_Bool global)
5328 {
5329    Edje *ed;
5330    Evas_Object *o;
5331 
5332    if (!ps) return;
5333    if (ps->global == global) return;
5334    if (global)
5335      {
5336         o = evas_object_name_find(evas_object_evas_get(ps->obj),
5337                                   "_edje_perspective");
5338         if (o) evas_object_name_set(o, NULL);
5339         evas_object_name_set(ps->obj, "_edje_perspective");
5340      }
5341    else
5342      evas_object_name_set(ps->obj, NULL);
5343    ps->global = global;
5344    EINA_INLIST_FOREACH(_edje_edjes, ed)
5345      {
5346         if (!ed->persp)
5347           {
5348              ed->dirty = EINA_TRUE;
5349              ed->recalc_call = EINA_TRUE;
5350              _edje_recalc_do(ed);
5351           }
5352      }
5353 }
5354 
5355 EAPI Eina_Bool
edje_perspective_global_get(const Edje_Perspective * ps)5356 edje_perspective_global_get(const Edje_Perspective *ps)
5357 {
5358    if (!ps) return EINA_FALSE;
5359    return ps->global;
5360 }
5361 
5362 EAPI const Edje_Perspective *
edje_evas_global_perspective_get(const Evas * e)5363 edje_evas_global_perspective_get(const Evas *e)
5364 {
5365    Evas_Object *obj;
5366 
5367    if (!e) return NULL;
5368    obj = evas_object_name_find(e, "_edje_perspective");
5369    if (!obj) return NULL;
5370    return evas_object_data_get(obj, "_edje_perspective");
5371 }
5372 
5373 EAPI void
edje_object_perspective_set(Eo * obj,Edje_Perspective * ps)5374 edje_object_perspective_set(Eo *obj, Edje_Perspective *ps)
5375 {
5376    Edje *ed = _edje_fetch(obj);
5377    if (!ed) return;
5378    if (ed->persp == ps) return;
5379    if (ed->persp != ps)
5380      {
5381         if (ed->persp)
5382           ed->persp->users = eina_list_remove(ed->persp->users, obj);
5383      }
5384    ed->persp = ps;
5385    if (ps) ps->users = eina_list_append(ps->users, obj);
5386    ed->dirty = EINA_TRUE;
5387    ed->recalc_call = EINA_TRUE;
5388    _edje_recalc_do(ed);
5389 }
5390 
5391 EAPI const Edje_Perspective *
edje_object_perspective_get(const Eo * obj)5392 edje_object_perspective_get(const Eo *obj)
5393 {
5394    Edje *ed =_edje_fetch(obj);
5395    if (!ed) return NULL;
5396    return ed->persp;
5397 }
5398 
5399 #define EDJE_PRELOAD_EMISSION "preload,done"
5400 #define EDJE_PRELOAD_SOURCE   NULL
5401 
5402 EAPI Eina_Bool
edje_object_preload(Eo * obj,Eina_Bool cancel)5403 edje_object_preload(Eo *obj, Eina_Bool cancel)
5404 {
5405    unsigned short count;
5406    unsigned short i;
5407    Edje *ed;
5408 
5409    ed = _edje_fetch(obj);
5410    if (!ed) return EINA_FALSE;
5411 
5412    _edje_recalc_do(ed);
5413 
5414    for (i = 0, count = 0; i < ed->table_parts_size; i++)
5415      {
5416         Edje_Real_Part *rp;
5417         Edje_Part *ep;
5418 
5419         rp = ed->table_parts[i];
5420         ep = rp->part;
5421 
5422         if ((ep->type == EDJE_PART_TYPE_IMAGE) ||
5423             ((ep->type == EDJE_PART_TYPE_GROUP) &&
5424              ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
5425               (rp->typedata.swallow)) &&
5426              (rp->typedata.swallow->swallowed_object)))
5427           count++;
5428      }
5429 
5430    ed->preload_count = count;
5431 
5432    if (count > 0)
5433      {
5434         for (i = 0; i < ed->table_parts_size; i++)
5435           {
5436              Edje_Real_Part *rp;
5437              Edje_Part *ep;
5438 
5439              rp = ed->table_parts[i];
5440              ep = rp->part;
5441 
5442              if (ep->type == EDJE_PART_TYPE_IMAGE)
5443                {
5444                   const char *file = NULL;
5445                   const char *key = NULL;
5446 
5447                   evas_object_event_callback_del_full(rp->object, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
5448 
5449                   evas_object_image_file_get(rp->object, &file, &key);
5450                   if (!file && !key)
5451                     {
5452                        ed->preload_count--;
5453                     }
5454                   else
5455                     {
5456                        evas_object_event_callback_add(rp->object, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
5457                        evas_object_image_preload(rp->object, cancel);
5458                     }
5459                   count--;
5460                }
5461              else if (ep->type == EDJE_PART_TYPE_GROUP)
5462                {
5463                   if (((rp->type == EDJE_RP_TYPE_SWALLOW) &&
5464                        (rp->typedata.swallow)) &&
5465                       (rp->typedata.swallow->swallowed_object))
5466                     {
5467                        char *tmp;
5468 
5469                        if (rp->part->name)
5470                          {
5471                             tmp = alloca(strlen(rp->part->name) + 2);
5472                             sprintf(tmp, "%s:", rp->part->name);
5473 
5474                             edje_object_signal_callback_del(obj, EDJE_PRELOAD_EMISSION, tmp, _edje_object_signal_preload_cb);
5475                             edje_object_signal_callback_add(obj, EDJE_PRELOAD_EMISSION, tmp, _edje_object_signal_preload_cb, ed);
5476                             edje_object_preload(rp->typedata.swallow->swallowed_object, cancel);
5477                          }
5478                        else
5479                          {
5480                             ed->preload_count--;
5481                          }
5482                        count--;
5483                     }
5484                }
5485           }
5486      }
5487    else
5488      {
5489         _edje_emit(ed, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE);
5490      }
5491 
5492    return EINA_TRUE;
5493 }
5494 
5495 EOLIAN void
_efl_canvas_layout_efl_layout_calc_calc_auto_update_hints_set(Eo * obj EINA_UNUSED,Edje * ed,Eina_Bool update)5496 _efl_canvas_layout_efl_layout_calc_calc_auto_update_hints_set(Eo *obj EINA_UNUSED, Edje *ed, Eina_Bool update)
5497 {
5498    if (!ed) return;
5499    if (ed->update_hints == !!update) return;
5500 
5501    ed->update_hints = !!update;
5502    if (update)
5503      {
5504         ed->recalc_hints = EINA_TRUE;
5505         _edje_recalc(ed);
5506      }
5507 }
5508 
5509 EOLIAN Eina_Bool
_efl_canvas_layout_efl_layout_calc_calc_auto_update_hints_get(const Eo * obj EINA_UNUSED,Edje * ed)5510 _efl_canvas_layout_efl_layout_calc_calc_auto_update_hints_get(const Eo *obj EINA_UNUSED, Edje *ed)
5511 {
5512    return ed->update_hints;
5513 }
5514 
5515 Eina_Bool
_edje_real_part_table_pack(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj,unsigned short col,unsigned short row,unsigned short colspan,unsigned short rowspan)5516 _edje_real_part_table_pack(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
5517 {
5518    Eina_Bool ret =
5519      evas_object_table_pack(rp->object, child_obj, col, row, colspan, rowspan);
5520 
5521    _edje_child_add(ed, rp, child_obj);
5522 
5523    return ret;
5524 }
5525 
5526 Eina_Bool
_edje_real_part_table_unpack(Edje * ed,Edje_Real_Part * rp,Evas_Object * child_obj)5527 _edje_real_part_table_unpack(Edje *ed, Edje_Real_Part *rp, Evas_Object *child_obj)
5528 {
5529    Eina_Bool ret = evas_object_table_unpack(rp->object, child_obj);
5530 
5531    if (ret)
5532      _edje_child_remove(ed, rp, child_obj);
5533 
5534    return ret;
5535 }
5536 
5537 void
_edje_real_part_table_clear(Edje * ed,Edje_Real_Part * rp,Eina_Bool clear)5538 _edje_real_part_table_clear(Edje *ed, Edje_Real_Part *rp, Eina_Bool clear)
5539 {
5540    Eina_List *children;
5541 
5542    children = evas_object_table_children_get(rp->object);
5543    while (children)
5544      {
5545         Evas_Object *child_obj = children->data;
5546 
5547         _edje_child_remove(ed, rp, child_obj);
5548         if (!evas_object_data_get(child_obj, "\377 edje.table_item"))
5549           {
5550              evas_object_table_unpack(rp->object, child_obj);
5551              if (clear)
5552                evas_object_del(child_obj);
5553           }
5554         children = eina_list_remove_list(children, children);
5555      }
5556 }
5557 
5558 Edje_Part_Description_Text *
_edje_real_part_text_source_description_get(Edje_Real_Part * ep,Edje_Real_Part ** rp2)5559 _edje_real_part_text_source_description_get(Edje_Real_Part *ep, Edje_Real_Part **rp2)
5560 {
5561    Edje_Part_Description_Text *et;
5562    Edje_Real_Part *rp = ep->typedata.text->source;
5563    if (ep->typedata.text->source->type == EDJE_RP_TYPE_SWALLOW)
5564      {
5565         Edje *ed2;
5566 
5567         et = (Edje_Part_Description_Text *)ep->param1.description;
5568         ed2 = _edje_fetch(ep->typedata.text->source->typedata.swallow->swallowed_object);
5569         if (!ed2) return NULL;
5570         rp = _edje_real_part_recursive_get(&ed2, et->text.id_source_part);
5571         if (!rp) return NULL;
5572         et = (Edje_Part_Description_Text *)rp->chosen_description;
5573      }
5574    else
5575      et = (Edje_Part_Description_Text *)ep->typedata.text->source->chosen_description;
5576    if (rp2) *rp2 = rp;
5577    return et;
5578 }
5579 
5580 Edje_Part_Description_Text *
_edje_real_part_text_text_source_description_get(Edje_Real_Part * ep,Edje_Real_Part ** rp2)5581 _edje_real_part_text_text_source_description_get(Edje_Real_Part *ep, Edje_Real_Part **rp2)
5582 {
5583    Edje_Part_Description_Text *et;
5584    Edje_Real_Part *rp = ep->typedata.text->text_source;
5585    if (ep->typedata.text->text_source->type == EDJE_RP_TYPE_SWALLOW)
5586      {
5587         Edje *ed2;
5588 
5589         et = (Edje_Part_Description_Text *)ep->param1.description;
5590         ed2 = _edje_fetch(ep->typedata.text->text_source->typedata.swallow->swallowed_object);
5591         if (!ed2) return NULL;
5592         rp = _edje_real_part_recursive_get(&ed2, et->text.id_text_source_part);
5593         if (!rp) return NULL;
5594         et = (Edje_Part_Description_Text *)rp->chosen_description;
5595      }
5596    else
5597      et = (Edje_Part_Description_Text *)ep->typedata.text->text_source->chosen_description;
5598    if (rp2) *rp2 = rp;
5599    return et;
5600 }
5601 
5602 Edje_Real_Part *
_edje_real_part_recursive_get(Edje ** ed,const char * part)5603 _edje_real_part_recursive_get(Edje **ed, const char *part)
5604 {
5605    Edje_Real_Part *rp;
5606    char **path;
5607 
5608    path = eina_str_split(part, EDJE_PART_PATH_SEPARATOR_STRING, 0);
5609    if (!path) return NULL;
5610 
5611    rp = _edje_real_part_recursive_get_helper(ed, path);
5612 
5613    free(*path);
5614    free(path);
5615    return rp;
5616 }
5617 
5618 Evas_Object *
_edje_children_get(Edje_Real_Part * rp,const char * partid)5619 _edje_children_get(Edje_Real_Part *rp, const char *partid)
5620 {
5621    Evas_Object *child = NULL;
5622    Eina_Iterator *it = NULL;
5623    long int v;
5624    char *p;
5625 
5626    if (!partid) return NULL;
5627 
5628    switch (rp->part->type)
5629      {
5630       case EDJE_PART_TYPE_EXTERNAL:
5631         if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
5632             (!rp->typedata.swallow)) return NULL;
5633         return _edje_external_content_get
5634                  (rp->typedata.swallow->swallowed_object, partid);
5635 
5636       case EDJE_PART_TYPE_BOX:
5637         it = evas_object_box_iterator_new(rp->object);
5638         break;
5639 
5640       case EDJE_PART_TYPE_TABLE:
5641         it = evas_object_table_iterator_new(rp->object);
5642         break;
5643 
5644       default:
5645         return NULL;
5646      }
5647 
5648    v = strtol(partid, &p, 10);
5649    if ((*p == '\0') && (v >= 0))
5650      {
5651         int i = 0;
5652         EINA_ITERATOR_FOREACH(it, child)
5653           {
5654              if (i == v) break;
5655              i++;
5656           }
5657         if (i != v) child = NULL;
5658      }
5659    else
5660      {
5661         Evas_Object *cur;
5662 
5663         EINA_ITERATOR_FOREACH(it, cur)
5664           {
5665              const char *name = evas_object_name_get(cur);
5666              if ((name) && (!strcmp(name, partid)))
5667                {
5668                   child = cur;
5669                   break;
5670                }
5671           }
5672      }
5673    eina_iterator_free(it);
5674 
5675    return child;
5676 }
5677 
5678 /* rebuild alternative path */
5679 char *
_edje_merge_path(const char * alias,char * const * path)5680 _edje_merge_path(const char *alias, char *const *path)
5681 {
5682    char *tmp;
5683    unsigned int length = 1;
5684    unsigned int alias_length;
5685    unsigned int i;
5686 
5687    if (!alias) return NULL;
5688 
5689    alias_length = strlen(alias);
5690 
5691    for (i = 0; path[i]; i++)
5692      length += strlen(path[i]) + 1;
5693 
5694    tmp = malloc(sizeof (char) * (length + alias_length + 2));
5695    memcpy(tmp, alias, alias_length);
5696    tmp[alias_length] = '\0';
5697 
5698    for (i = 0; path[i]; i++)
5699      {
5700         strcat(tmp, EDJE_PART_PATH_SEPARATOR_STRING);
5701         strcat(tmp, path[i]);
5702      }
5703 
5704    return tmp;
5705 }
5706 
5707 Edje_Real_Part *
_edje_real_part_recursive_get_helper(Edje ** ed,char ** path)5708 _edje_real_part_recursive_get_helper(Edje **ed, char **path)
5709 {
5710    Edje_Real_Part *rp;
5711    Evas_Object *child;
5712    char *idx = NULL;
5713 
5714    if (!path[0])
5715      return NULL;
5716 
5717    if ((*ed)->collection && (*ed)->collection->alias)
5718      {
5719         char *alias;
5720 
5721         alias = _edje_merge_path(eina_hash_find((*ed)->collection->alias, path[0]), path + 1);
5722         if (alias)
5723           {
5724              rp = _edje_real_part_recursive_get(ed, alias);
5725              free(alias);
5726              return rp;
5727           }
5728      }
5729 
5730    //printf("  lookup: %s on %s\n", path[0], ed->parent ? ed->parent : "-");
5731    idx = strchr(path[0], EDJE_PART_PATH_SEPARATOR_INDEXL);
5732    if (idx)
5733      {
5734         char *end;
5735 
5736         end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
5737         if (end)
5738           {
5739              *end = '\0';
5740              *idx = '\0';
5741              idx++;
5742           }
5743      }
5744 
5745    rp = _edje_real_part_get(*ed, path[0]);
5746    if (!path[1] && !idx) return rp;
5747    if (!rp) return NULL;
5748 
5749    switch (rp->part->type)
5750      {
5751       case EDJE_PART_TYPE_GROUP:
5752         if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
5753             (!rp->typedata.swallow)) return NULL;
5754         if (!rp->typedata.swallow->swallowed_object) return NULL;
5755         *ed = _edje_fetch(rp->typedata.swallow->swallowed_object);
5756         if (!*ed) return NULL;
5757         path++;
5758         return _edje_real_part_recursive_get_helper(ed, path);
5759 
5760       case EDJE_PART_TYPE_BOX:
5761       case EDJE_PART_TYPE_TABLE:
5762       case EDJE_PART_TYPE_EXTERNAL:
5763         if (!idx) return rp;
5764         path++;
5765 
5766         child = _edje_children_get(rp, idx);
5767 
5768         *ed = _edje_fetch(child);
5769 
5770         if (!*ed) return NULL;
5771         return _edje_real_part_recursive_get_helper(ed, path);
5772 
5773       default:
5774         return NULL;
5775      }
5776 }
5777 
5778 /* Private Routines - do not call eo_do inside this one */
5779 Edje_Real_Part *
_edje_real_part_get(const Edje * ed,const char * part)5780 _edje_real_part_get(const Edje *ed, const char *part)
5781 {
5782    unsigned short i;
5783 
5784    if (!part) return NULL;
5785 
5786    for (i = 0; i < ed->table_parts_size; i++)
5787      {
5788         Edje_Real_Part *rp;
5789 
5790         rp = ed->table_parts[i];
5791         if ((rp->part->name) && (!strcmp(rp->part->name, part))) return rp;
5792      }
5793    return NULL;
5794 }
5795 
5796 void *
_edje_hash_find_helper(const Eina_Hash * hash,const char * key)5797 _edje_hash_find_helper(const Eina_Hash *hash, const char *key)
5798 {
5799    static const char *remember_key = NULL;
5800    void *data;
5801    int i, j;
5802    char **tokens;
5803    unsigned int tokens_count = 0;
5804 
5805    data = eina_hash_find(hash, key);
5806    if (data)
5807      return data;
5808 
5809    // We only receive pointer from Eet files as key, we can
5810    // assume them constant over the life time of the program.
5811    if (remember_key == key)
5812      return NULL;
5813 
5814    // It is usually faster to walk the string once to check
5815    // if there will be any tokens to process, that to allocate
5816    // an array, copy one token, and then just free it.
5817    if (strchr(key, '/') == NULL)
5818      {
5819         remember_key = key;
5820         return NULL;
5821      }
5822 
5823    tokens = eina_str_split_full(key, "/", 0, &tokens_count);
5824    if ((tokens) && (tokens_count > 1))
5825      {
5826         Eina_Strbuf *buf = NULL;
5827 
5828         buf = eina_strbuf_new();
5829 
5830         for (i = tokens_count - 2; i >= 0; i--)
5831           {
5832              for (j = 0; j < i; j++)
5833                {
5834                   eina_strbuf_append(buf, tokens[j]);
5835                   eina_strbuf_append(buf, "/");
5836                }
5837              eina_strbuf_append(buf, tokens[tokens_count - 1]);
5838 
5839              data = eina_hash_find(hash, eina_strbuf_string_get(buf));
5840              if (data) break;
5841 
5842              eina_strbuf_reset(buf);
5843           }
5844 
5845         eina_strbuf_free(buf);
5846      }
5847    else
5848      {
5849         remember_key = key;
5850      }
5851 
5852    if (tokens)
5853      {
5854         free(tokens[0]);
5855         free(tokens);
5856      }
5857    return data;
5858 }
5859 
5860 Edje_Color_Class *
_edje_color_class_find(const Edje * ed,const char * color_class)5861 _edje_color_class_find(const Edje *ed, const char *color_class)
5862 {
5863    Edje_Color_Class *cc = NULL;
5864 
5865    if ((!ed) || (!color_class)) return NULL;
5866 
5867    /* first look through the object scope */
5868    cc = eina_hash_find(ed->color_classes, color_class);
5869    if (cc) return cc;
5870 
5871    /* next look through the global scope */
5872    cc = eina_hash_find(_edje_color_class_hash, color_class);
5873    if (cc) return cc;
5874 
5875    /* finally, look through the file scope */
5876    if (ed->file)
5877      cc = eina_hash_find(ed->file->color_hash, color_class);
5878    if (cc) return cc;
5879 
5880    return NULL;
5881 }
5882 
5883 Edje_Color_Class *
_edje_color_class_recursive_find_helper(const Edje * ed,Eina_Hash * hash,const char * color_class)5884 _edje_color_class_recursive_find_helper(const Edje *ed, Eina_Hash *hash, const char *color_class)
5885 {
5886    Edje_Color_Class *cc = NULL;
5887    Edje_Color_Tree_Node *ctn = NULL;
5888    const char *parent;
5889 
5890    if (!eina_hash_population(hash)) return NULL;
5891 
5892    cc = _edje_hash_find_helper(hash, color_class);
5893    if (cc) return cc;
5894    else if (ed->file)
5895      {
5896         parent = color_class;
5897         while ((ctn = eina_hash_find(ed->file->color_tree_hash, parent)))
5898           {
5899              parent = ctn->name;
5900              cc = eina_hash_find(hash, parent);
5901              if (cc) return cc;
5902           }
5903      }
5904    return NULL;
5905 }
5906 
5907 Edje_Color_Class *
_edje_color_class_recursive_find(const Edje * ed,const char * color_class)5908 _edje_color_class_recursive_find(const Edje *ed, const char *color_class)
5909 {
5910    Edje_Color_Class *cc = NULL;
5911 
5912    if ((!ed) || (!color_class)) return NULL;
5913 
5914    /* first look through the object scope */
5915    cc = _edje_color_class_recursive_find_helper(ed, ed->color_classes, color_class);
5916    if (cc) return cc;
5917 
5918    /* next look through the global scope */
5919    cc = _edje_color_class_recursive_find_helper(ed, _edje_color_class_hash, color_class);
5920    if (cc) return cc;
5921 
5922    /* finally, look through the file scope */
5923    if (ed->file)
5924      cc = _edje_color_class_recursive_find_helper(ed, ed->file->color_hash, color_class);
5925    if (cc) return cc;
5926 
5927    return NULL;
5928 }
5929 
5930 static Eina_Bool
color_class_hash_list_free(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * fdata EINA_UNUSED)5931 color_class_hash_list_free(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
5932 {
5933    Edje_Color_Class *cc;
5934 
5935    cc = data;
5936    if (cc->name) eina_stringshare_del(cc->name);
5937    free(cc);
5938    return EINA_TRUE;
5939 }
5940 
5941 void
_edje_color_class_hash_free(void)5942 _edje_color_class_hash_free(void)
5943 {
5944    if (!_edje_color_class_hash) return;
5945    eina_hash_foreach(_edje_color_class_hash, color_class_hash_list_free, NULL);
5946    eina_hash_free(_edje_color_class_hash);
5947    _edje_color_class_hash = NULL;
5948 }
5949 
5950 void
_edje_color_class_on_del(Edje * ed,Edje_Part * ep)5951 _edje_color_class_on_del(Edje *ed, Edje_Part *ep)
5952 {
5953    unsigned int i;
5954 
5955    if ((ep->default_desc) && (ep->default_desc->color_class))
5956      efl_observable_observer_del(_edje_color_class_member, ep->default_desc->color_class, ed->obj);
5957 
5958    for (i = 0; i < ep->other.desc_count; ++i)
5959      if (ep->other.desc[i]->color_class)
5960        efl_observable_observer_del(_edje_color_class_member, ep->other.desc[i]->color_class, ed->obj);
5961 }
5962 
5963 Edje_Text_Class *
_edje_text_class_find(Edje * ed,const char * text_class)5964 _edje_text_class_find(Edje *ed, const char *text_class)
5965 {
5966    Edje_Text_Class *tc = NULL;
5967 
5968    if (!text_class) return NULL;
5969 
5970    if (!ed)
5971      {
5972         /* If ed object is NULL, then look through the global scope only */
5973         return eina_hash_find(_edje_text_class_hash, text_class);
5974      }
5975 
5976    /* first look through the object scope */
5977    tc = eina_hash_find(ed->text_classes, text_class);
5978 
5979    /* next look through the global scope */
5980    if (!tc)
5981      tc = eina_hash_find(_edje_text_class_hash, text_class);
5982 
5983    /* finally, look through the file scope */
5984    if (!tc && ed->file)
5985      tc = eina_hash_find(ed->file->text_hash, text_class);
5986 
5987    return tc;
5988 }
5989 
5990 static Eina_Bool
text_class_hash_list_free(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * fdata EINA_UNUSED)5991 text_class_hash_list_free(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
5992 {
5993    Edje_Text_Class *tc;
5994 
5995    tc = data;
5996    if (tc->name) eina_stringshare_del(tc->name);
5997    if (tc->font) eina_stringshare_del(tc->font);
5998    free(tc);
5999    return EINA_TRUE;
6000 }
6001 
6002 void
_edje_text_class_hash_free(void)6003 _edje_text_class_hash_free(void)
6004 {
6005    if (!_edje_text_class_hash) return;
6006    eina_hash_foreach(_edje_text_class_hash, text_class_hash_list_free, NULL);
6007    eina_hash_free(_edje_text_class_hash);
6008    _edje_text_class_hash = NULL;
6009 }
6010 
6011 Edje_Size_Class *
_edje_size_class_find(Edje * ed,const char * size_class)6012 _edje_size_class_find(Edje *ed, const char *size_class)
6013 {
6014    Edje_Size_Class *sc;
6015 
6016    if ((!ed) || (!size_class)) return NULL;
6017 
6018    /* first look through the object scope */
6019    sc = eina_hash_find(ed->size_classes, size_class);
6020    if (sc) return sc;
6021 
6022    /* next look through the global scope */
6023    sc = eina_hash_find(_edje_size_class_hash, size_class);
6024    if (sc) return sc;
6025 
6026    /* finally, look through the file scope */
6027    if (ed->file)
6028      sc = eina_hash_find(ed->file->size_hash, size_class);
6029    if (sc) return sc;
6030 
6031    return NULL;
6032 }
6033 
6034 static Eina_Bool
size_class_hash_list_free(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * data,void * fdata EINA_UNUSED)6035 size_class_hash_list_free(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
6036 {
6037    Edje_Size_Class *sc;
6038 
6039    sc = data;
6040    if (sc->name) eina_stringshare_del(sc->name);
6041    free(sc);
6042    return EINA_TRUE;
6043 }
6044 
6045 void
_edje_size_class_hash_free(void)6046 _edje_size_class_hash_free(void)
6047 {
6048    if (!_edje_size_class_hash) return;
6049    eina_hash_foreach(_edje_size_class_hash, size_class_hash_list_free, NULL);
6050    eina_hash_free(_edje_size_class_hash);
6051    _edje_size_class_hash = NULL;
6052 }
6053 
6054 Edje *
_edje_fetch(const Evas_Object * obj)6055 _edje_fetch(const Evas_Object *obj)
6056 {
6057    Edje *ed;
6058 
6059    if (!obj || !efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
6060      return NULL;
6061    ed = efl_data_scope_get(obj, EFL_CANVAS_LAYOUT_CLASS);
6062    if ((ed) && (ed->delete_me)) return NULL;
6063    return ed;
6064 }
6065 
6066 int
_edje_util_freeze(Edje * ed)6067 _edje_util_freeze(Edje *ed)
6068 {
6069    ed->freeze++;
6070 //   printf("FREEZE %i\n", ed->freeze);
6071    return ed->freeze;
6072 }
6073 
6074 int
_edje_util_thaw(Edje * ed)6075 _edje_util_thaw(Edje *ed)
6076 {
6077    if (ed->freeze == 0) return 0;
6078    ed->freeze--;
6079    if ((ed->freeze == 0) && (ed->recalc))
6080      {
6081         //	printf("thaw recalc\n");
6082         _edje_recalc(ed);
6083      }
6084    return ed->freeze;
6085 }
6086 
6087 int
_edje_block(Edje * ed)6088 _edje_block(Edje *ed)
6089 {
6090    _edje_ref(ed);
6091    ed->block++;
6092    return ed->block;
6093 }
6094 
6095 int
_edje_unblock(Edje * ed)6096 _edje_unblock(Edje *ed)
6097 {
6098    int ret = 0;
6099 
6100    if (!ed) return ret;
6101 
6102    ed->block--;
6103    if (ed->block == 0) ed->block_break = EINA_FALSE;
6104    ret = ed->block;
6105    _edje_unref(ed);
6106    return ret;
6107 }
6108 
6109 int
_edje_block_break(Edje * ed)6110 _edje_block_break(Edje *ed)
6111 {
6112    if (ed->block_break) return 1;
6113    return 0;
6114 }
6115 
6116 void
_edje_block_violate(Edje * ed)6117 _edje_block_violate(Edje *ed)
6118 {
6119    if (ed->block > 0) ed->block_break = EINA_TRUE;
6120 }
6121 
6122 void
_edje_object_part_swallow_free_cb(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)6123 _edje_object_part_swallow_free_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6124 {
6125    Edje_User_Defined *eud;
6126    Eina_List *l, *ll;
6127    Eina_Iterator *it;
6128    Edje *ed;
6129    Edje_Real_Part *rp;
6130 
6131    ed = evas_object_data_get(obj, ".edje");
6132    if (!ed) return;
6133    it = eina_hash_iterator_data_new(ed->user_defined);
6134    EINA_ITERATOR_FOREACH(it, l)
6135      {
6136         EINA_LIST_FOREACH(l, ll, eud)
6137           if (eud->type == EDJE_USER_SWALLOW && eud->u.swallow.child == obj)
6138             {
6139                _edje_user_definition_free(eud);
6140                goto out;
6141             }
6142      }
6143 out:
6144    rp = evas_object_data_get(obj, "\377 edje.swallowing_part");
6145    if (rp && (rp->part->type == EDJE_PART_TYPE_SWALLOW))
6146      edje_object_part_unswallow(ed->obj, obj);
6147 
6148    return;
6149 }
6150 
6151 static void
_edje_real_part_swallow_hints_update(Edje_Real_Part * rp)6152 _edje_real_part_swallow_hints_update(Edje_Real_Part *rp)
6153 {
6154    if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
6155        (!rp->typedata.swallow)) return;
6156 
6157    rp->typedata.swallow->swallow_params.min.w = 0;
6158    rp->typedata.swallow->swallow_params.min.h = 0;
6159    rp->typedata.swallow->swallow_params.max.w = -1;
6160    rp->typedata.swallow->swallow_params.max.h = -1;
6161    if (efl_isa(rp->typedata.swallow->swallowed_object, EFL_CANVAS_LAYOUT_CLASS))
6162      {
6163         Evas_Coord w = 0, h = 0;
6164 
6165 #if 0
6166         edje_object_size_min_get(rp->typedata.swallow->swallowed_object, &w, &h);
6167         rp->typedata.swallow->swallow_params.min.w = w;
6168         rp->typedata.swallow->swallow_params.min.h = h;
6169 #endif
6170         edje_object_size_max_get(rp->typedata.swallow->swallowed_object, &w, &h);
6171         rp->typedata.swallow->swallow_params.max.w = w;
6172         rp->typedata.swallow->swallow_params.max.h = h;
6173      }
6174    else if (efl_isa(rp->typedata.swallow->swallowed_object, EVAS_TEXT_CLASS) ||
6175             efl_isa(rp->typedata.swallow->swallowed_object, EFL_CANVAS_POLYGON_CLASS) ||
6176             efl_isa(rp->typedata.swallow->swallowed_object, EVAS_LINE_CLASS))
6177      {
6178         Evas_Coord w = 0, h = 0;
6179 
6180         evas_object_geometry_get(rp->typedata.swallow->swallowed_object, NULL, NULL, &w, &h);
6181 #if 0
6182         rp->typedata.swallow->swallow_params.min.w = w;
6183         rp->typedata.swallow->swallow_params.min.h = h;
6184 #endif
6185         rp->typedata.swallow->swallow_params.max.w = w;
6186         rp->typedata.swallow->swallow_params.max.h = h;
6187      }
6188    {
6189       Evas_Coord w1 = 0, h1 = 0, w2 = 0, h2 = 0, aw = 0, ah = 0;
6190       Evas_Aspect_Control am = EVAS_ASPECT_CONTROL_NONE;
6191 
6192       evas_object_size_hint_combined_min_get(rp->typedata.swallow->swallowed_object, &w1, &h1);
6193       evas_object_size_hint_combined_max_get(rp->typedata.swallow->swallowed_object, &w2, &h2);
6194       evas_object_size_hint_aspect_get(rp->typedata.swallow->swallowed_object, &am, &aw, &ah);
6195       rp->typedata.swallow->swallow_params.min.w = w1;
6196       rp->typedata.swallow->swallow_params.min.h = h1;
6197       if (w2 > 0) rp->typedata.swallow->swallow_params.max.w = w2;
6198       if (h2 > 0) rp->typedata.swallow->swallow_params.max.h = h2;
6199       switch (am)
6200         {
6201          case EVAS_ASPECT_CONTROL_NONE:
6202            rp->typedata.swallow->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_NONE;
6203            break;
6204 
6205          case EVAS_ASPECT_CONTROL_NEITHER:
6206            rp->typedata.swallow->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_NEITHER;
6207            break;
6208 
6209          case EVAS_ASPECT_CONTROL_HORIZONTAL:
6210            rp->typedata.swallow->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_HORIZONTAL;
6211            break;
6212 
6213          case EVAS_ASPECT_CONTROL_VERTICAL:
6214            rp->typedata.swallow->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_VERTICAL;
6215            break;
6216 
6217          case EVAS_ASPECT_CONTROL_BOTH:
6218            rp->typedata.swallow->swallow_params.aspect.mode = EDJE_ASPECT_CONTROL_BOTH;
6219            break;
6220 
6221          default:
6222            break;
6223         }
6224       rp->typedata.swallow->swallow_params.aspect.w = aw;
6225       rp->typedata.swallow->swallow_params.aspect.h = ah;
6226       evas_object_data_set(rp->typedata.swallow->swallowed_object, "\377 edje.swallowing_part", rp);
6227    }
6228 
6229 #ifdef EDJE_CALC_CACHE
6230    rp->invalidate = EINA_TRUE;
6231 #endif
6232 }
6233 
6234 void
_edje_object_part_swallow_changed_hints_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)6235 _edje_object_part_swallow_changed_hints_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6236 {
6237    Edje_Real_Part *rp;
6238    Edje *ed;
6239 
6240    rp = data;
6241    ed = evas_object_data_get(obj, ".edje");
6242    if (!ed) return;
6243    _edje_real_part_swallow_hints_update(rp);
6244    ed->dirty = EINA_TRUE;
6245    ed->recalc_call = EINA_TRUE;
6246    ed->recalc_hints = EINA_TRUE;
6247 
6248    _edje_recalc(ed);
6249    return;
6250 }
6251 
6252 void
_edje_object_part_swallow_image_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)6253 _edje_object_part_swallow_image_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
6254 {
6255    Edje_Real_Part *rp = data;
6256    Evas_Coord w, h;
6257    Evas_Map *map;
6258 
6259    if (!rp->chosen_description->map.on) return;
6260    if (rp->type != EDJE_RP_TYPE_SWALLOW) return;
6261    if (!rp->typedata.swallow) return;
6262    if (evas_object_image_source_get(rp->typedata.swallow->swallowed_object))
6263      return;
6264 
6265    map = (Evas_Map *)evas_object_map_get(rp->typedata.swallow->swallowed_object);
6266    if (!map) return;
6267 
6268    evas_object_image_size_get(rp->typedata.swallow->swallowed_object, &w, &h);
6269    evas_map_point_image_uv_set(map, 0, 0, 0);
6270    evas_map_point_image_uv_set(map, 1, w, 0);
6271    evas_map_point_image_uv_set(map, 2, w, h);
6272    evas_map_point_image_uv_set(map, 3, 0, h);
6273 
6274    evas_object_map_set(rp->typedata.swallow->swallowed_object, map);
6275 }
6276 
6277 void
_edje_real_part_swallow(Edje * ed,Edje_Real_Part * rp,Evas_Object * obj_swallow,Eina_Bool hints_update)6278 _edje_real_part_swallow(Edje *ed,
6279                         Edje_Real_Part *rp,
6280                         Evas_Object *obj_swallow,
6281                         Eina_Bool hints_update)
6282 {
6283    if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
6284        (!rp->typedata.swallow)) return;
6285    if (rp->typedata.swallow->swallowed_object)
6286      {
6287         if (rp->typedata.swallow->swallowed_object != obj_swallow)
6288           {
6289              edje_object_part_unswallow(ed->obj, rp->typedata.swallow->swallowed_object);
6290           }
6291         else
6292           {
6293              if (hints_update)
6294                _edje_real_part_swallow_hints_update(rp);
6295              ed->dirty = EINA_TRUE;
6296              ed->recalc_call = EINA_TRUE;
6297              ed->recalc_hints = EINA_TRUE;
6298              _edje_recalc(ed);
6299              return;
6300           }
6301      }
6302 #ifdef EDJE_CALC_CACHE
6303    rp->invalidate = EINA_TRUE;
6304 #endif
6305    if (!obj_swallow) return;
6306    rp->typedata.swallow->swallowed_object = obj_swallow;
6307    efl_parent_set(obj_swallow, ed->obj);
6308    evas_object_smart_member_add(rp->typedata.swallow->swallowed_object, ed->obj);
6309    if (rp->part->clip_to_id >= 0)
6310      {
6311         Edje_Real_Part *clip_to;
6312 
6313         clip_to = ed->table_parts[rp->part->clip_to_id % ed->table_parts_size];
6314         evas_object_clip_set(rp->typedata.swallow->swallowed_object, clip_to->object);
6315      }
6316    else evas_object_clip_set(rp->typedata.swallow->swallowed_object, ed->base.clipper);
6317    //FIXME: I'm not sure why Edje Nested is a parent of the rp->object here. Is it normal case?
6318    if (evas_object_smart_parent_get(rp->object) == ed->obj)
6319      evas_object_stack_above(rp->typedata.swallow->swallowed_object, rp->object);
6320    evas_object_event_callback_add(rp->typedata.swallow->swallowed_object,
6321                                   EVAS_CALLBACK_DEL,
6322                                   _edje_object_part_swallow_free_cb,
6323                                   rp);
6324    evas_object_event_callback_add(rp->typedata.swallow->swallowed_object,
6325                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
6326                                   _edje_object_part_swallow_changed_hints_cb,
6327                                   rp);
6328    evas_object_data_set(rp->typedata.swallow->swallowed_object, ".edje", ed);
6329 
6330    //If the map is enabled, uv should be updated when image size is changed.
6331    if (efl_isa(rp->typedata.swallow->swallowed_object, EFL_CANVAS_IMAGE_INTERNAL_CLASS))
6332      evas_object_event_callback_add(obj_swallow, EVAS_CALLBACK_IMAGE_RESIZE,
6333                                     _edje_object_part_swallow_image_resize_cb,
6334                                     rp);
6335 
6336    if (hints_update)
6337      _edje_real_part_swallow_hints_update(rp);
6338 
6339    if (rp->mouse_events)
6340      {
6341         _edje_callbacks_add(obj_swallow, ed, rp);
6342         evas_object_repeat_events_set(obj_swallow, rp->repeat_events);
6343         if (rp->part->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
6344           evas_object_pointer_mode_set(obj_swallow, rp->part->pointer_mode);
6345         evas_object_pass_events_set(obj_swallow, 0);
6346      }
6347    else
6348      evas_object_pass_events_set(obj_swallow, 1);
6349    _edje_callbacks_focus_add(rp->typedata.swallow->swallowed_object, ed, rp);
6350    efl_canvas_object_anti_alias_set(obj_swallow, rp->part->anti_alias);
6351    efl_canvas_object_precise_is_inside_set(obj_swallow, rp->part->precise_is_inside);
6352 
6353    ed->dirty = EINA_TRUE;
6354    ed->recalc_call = EINA_TRUE;
6355    ed->recalc_hints = EINA_TRUE;
6356    _edje_recalc(ed);
6357 }
6358 
6359 void
_edje_real_part_swallow_clear(Edje * ed,Edje_Real_Part * rp)6360 _edje_real_part_swallow_clear(Edje *ed, Edje_Real_Part *rp)
6361 {
6362    if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
6363        (!rp->typedata.swallow)) return;
6364    if (!rp->typedata.swallow->swallowed_object) return;
6365    if (rp->chosen_description->map.on ||
6366        (rp->invalidate && rp->prev_description && rp->prev_description->map.on))
6367      {
6368         evas_object_map_enable_set(rp->typedata.swallow->swallowed_object, EINA_FALSE);
6369      }
6370    _eo_unparent_helper(rp->typedata.swallow->swallowed_object, ed->obj);
6371    evas_object_smart_member_del(rp->typedata.swallow->swallowed_object);
6372    evas_object_event_callback_del_full(rp->typedata.swallow->swallowed_object,
6373                                        EVAS_CALLBACK_DEL,
6374                                        _edje_object_part_swallow_free_cb,
6375                                        rp);
6376    evas_object_event_callback_del_full(rp->typedata.swallow->swallowed_object,
6377                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
6378                                        _edje_object_part_swallow_changed_hints_cb,
6379                                        rp);
6380    if (efl_isa(rp->typedata.swallow->swallowed_object, EFL_CANVAS_IMAGE_INTERNAL_CLASS))
6381      evas_object_event_callback_del_full(rp->typedata.swallow->swallowed_object,
6382                                          EVAS_CALLBACK_IMAGE_RESIZE,
6383                                          _edje_object_part_swallow_image_resize_cb,
6384                                          rp);
6385    evas_object_clip_unset(rp->typedata.swallow->swallowed_object);
6386    evas_object_data_del(rp->typedata.swallow->swallowed_object, "\377 edje.swallowing_part");
6387    _edje_callbacks_del(rp->typedata.swallow->swallowed_object, ed);
6388    _edje_callbacks_focus_del(rp->typedata.swallow->swallowed_object, ed);
6389    rp->typedata.swallow->swallowed_object = NULL;
6390 }
6391 
6392 static void
_edje_object_preload_helper(Edje * ed)6393 _edje_object_preload_helper(Edje *ed)
6394 {
6395    ed->preload_count--;
6396    if (!ed->preload_count)
6397      _edje_emit(ed, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE);
6398 }
6399 
6400 static void
_edje_object_image_preload_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)6401 _edje_object_image_preload_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6402 {
6403    Edje *ed = data;
6404 
6405    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_IMAGE_PRELOADED, _edje_object_image_preload_cb, ed);
6406    _edje_object_preload_helper(ed);
6407 }
6408 
6409 static void
_edje_object_signal_preload_cb(void * data,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)6410 _edje_object_signal_preload_cb(void *data, Evas_Object *obj, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
6411 {
6412    Edje *ed = data;
6413 
6414    edje_object_signal_callback_del(obj, EDJE_PRELOAD_EMISSION, EDJE_PRELOAD_SOURCE, _edje_object_signal_preload_cb);
6415    _edje_object_preload_helper(ed);
6416 }
6417 
6418 /**
6419  * @internal
6420  *
6421  * for edje_cc
6422  */
6423 EAPI void
_edje_program_remove(Edje_Part_Collection * edc,Edje_Program * p)6424 _edje_program_remove(Edje_Part_Collection *edc, Edje_Program *p)
6425 {
6426    Edje_Program ***array;
6427    unsigned int *count;
6428    unsigned int i;
6429 
6430    if (!p->signal && !p->source)
6431      {
6432         array = &edc->programs.nocmp;
6433         count = &edc->programs.nocmp_count;
6434      }
6435    else if (p->signal && !strpbrk(p->signal, "*?[\\")
6436             && p->source && !strpbrk(p->source, "*?[\\"))
6437      {
6438         array = &edc->programs.strcmp;
6439         count = &edc->programs.strcmp_count;
6440      }
6441    else if (p->signal && edje_program_is_strncmp(p->signal)
6442             && p->source && edje_program_is_strncmp(p->source))
6443      {
6444         array = &edc->programs.strncmp;
6445         count = &edc->programs.strncmp_count;
6446      }
6447    else if (p->signal && edje_program_is_strrncmp(p->signal)
6448             && p->source && edje_program_is_strrncmp(p->source))
6449      {
6450         array = &edc->programs.strrncmp;
6451         count = &edc->programs.strrncmp_count;
6452      }
6453    else
6454      {
6455         array = &edc->programs.fnmatch;
6456         count = &edc->programs.fnmatch_count;
6457      }
6458 
6459    for (i = 0; i < *count; ++i)
6460      if ((*array)[i] == p)
6461        {
6462           memmove(*array + i, *array + i + 1, sizeof (Edje_Program *) * (*count - i - 1));
6463           (*count)--;
6464           break;
6465        }
6466 }
6467 
6468 /**
6469  * @internal
6470  *
6471  * for edje_cc
6472  */
6473 EAPI void
_edje_program_insert(Edje_Part_Collection * edc,Edje_Program * p)6474 _edje_program_insert(Edje_Part_Collection *edc, Edje_Program *p)
6475 {
6476    Edje_Program ***array, **temp;
6477    unsigned int *count;
6478 
6479    if (!p->signal && !p->source)
6480      {
6481         array = &edc->programs.nocmp;
6482         count = &edc->programs.nocmp_count;
6483      }
6484    else if (p->signal && !strpbrk(p->signal, "*?[\\")
6485             && p->source && !strpbrk(p->source, "*?[\\"))
6486      {
6487         array = &edc->programs.strcmp;
6488         count = &edc->programs.strcmp_count;
6489      }
6490    else if (p->signal && edje_program_is_strncmp(p->signal)
6491             && p->source && edje_program_is_strncmp(p->source))
6492      {
6493         array = &edc->programs.strncmp;
6494         count = &edc->programs.strncmp_count;
6495      }
6496    else if (p->signal && edje_program_is_strrncmp(p->signal)
6497             && p->source && edje_program_is_strrncmp(p->source))
6498      {
6499         array = &edc->programs.strrncmp;
6500         count = &edc->programs.strrncmp_count;
6501      }
6502    else
6503      {
6504         array = &edc->programs.fnmatch;
6505         count = &edc->programs.fnmatch_count;
6506      }
6507 
6508    temp = *array;
6509    *array = realloc(*array, sizeof (Edje_Program *) * (*count + 1));
6510    if (*array)
6511      {
6512         (*array)[(*count)++] = p;
6513      }
6514    else
6515      {
6516         *array = temp;
6517      }
6518 }
6519 
6520 const char *
edje_string_get(const Edje_String * es)6521 edje_string_get(const Edje_String *es)
6522 {
6523    /* FIXME: Handle localization here */
6524    if (!es) return NULL;
6525    return es->str;
6526 }
6527 
6528 const char *
edje_string_id_get(const Edje_String * es)6529 edje_string_id_get(const Edje_String *es)
6530 {
6531    /* FIXME: Handle localization here */
6532    if (!es) return NULL;
6533    return es->str;
6534 }
6535 
6536 static void
_cb_subobj_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)6537 _cb_subobj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6538 {
6539    Edje *ed = data;
6540    _edje_subobj_unregister(ed, obj);
6541 }
6542 
6543 void
_edje_subobj_register(Edje * ed,Evas_Object * ob)6544 _edje_subobj_register(Edje *ed, Evas_Object *ob)
6545 {
6546    ed->subobjs = eina_list_append(ed->subobjs, ob);
6547    evas_object_event_callback_add(ob, EVAS_CALLBACK_DEL,
6548                                   _cb_subobj_del, ed);
6549 }
6550 
6551 void
_edje_subobj_unregister(Edje * ed,Evas_Object * obj)6552 _edje_subobj_unregister(Edje *ed, Evas_Object *obj)
6553 {
6554    ed->subobjs = eina_list_remove(ed->subobjs, obj);
6555    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
6556                                        _cb_subobj_del, ed);
6557 }
6558 
6559 EAPI const char *
edje_object_part_object_name_get(const Evas_Object * obj)6560 edje_object_part_object_name_get(const Evas_Object *obj)
6561 {
6562    Edje_Real_Part *rp;
6563 
6564    rp = evas_object_data_get(obj, "real_part");
6565    return rp ? rp->part->name : NULL;
6566 }
6567 
6568 Eina_Bool
_edje_real_part_mouse_events_get(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)6569 _edje_real_part_mouse_events_get(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
6570 {
6571    if (!rp) return EINA_FALSE;
6572 
6573    return rp->mouse_events;
6574 }
6575 
6576 void
_edje_real_part_mouse_events_set(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,Eina_Bool mouse_events)6577 _edje_real_part_mouse_events_set(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, Eina_Bool mouse_events)
6578 {
6579    if (!rp) return;
6580 
6581    rp->mouse_events = !!mouse_events;
6582 
6583    if (rp->mouse_events)
6584      {
6585         evas_object_pass_events_set(rp->object, 0);
6586         _edje_callbacks_add(rp->object, ed, rp);
6587      }
6588    else
6589      {
6590         evas_object_pass_events_set(rp->object, 1);
6591         _edje_callbacks_del(rp->object, ed);
6592      }
6593 }
6594 
6595 Eina_Bool
_edje_real_part_repeat_events_get(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)6596 _edje_real_part_repeat_events_get(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
6597 {
6598    if (!rp) return EINA_FALSE;
6599 
6600    return rp->repeat_events;
6601 }
6602 
6603 void
_edje_real_part_repeat_events_set(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,Eina_Bool repeat_events)6604 _edje_real_part_repeat_events_set(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, Eina_Bool repeat_events)
6605 {
6606    if (!rp) return;
6607 
6608    rp->repeat_events = !!repeat_events;
6609 
6610    if (rp->repeat_events)
6611      evas_object_repeat_events_set(rp->object, 1);
6612    else
6613      evas_object_repeat_events_set(rp->object, 0);
6614 }
6615 
6616 void
_edje_real_part_pointer_mode_set(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,Evas_Object_Pointer_Mode mode)6617 _edje_real_part_pointer_mode_set(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, Evas_Object_Pointer_Mode mode)
6618 {
6619    if (!rp) return;
6620 
6621    rp->pointer_mode = mode;
6622 
6623    evas_object_pointer_mode_set(rp->object, mode);
6624 }
6625 
6626 Evas_Event_Flags
_edje_real_part_ignore_flags_get(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)6627 _edje_real_part_ignore_flags_get(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
6628 {
6629    if (!rp) return EVAS_EVENT_FLAG_NONE;
6630 
6631    return rp->ignore_flags;
6632 }
6633 
6634 void
_edje_real_part_ignore_flags_set(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,Evas_Event_Flags ignore_flags)6635 _edje_real_part_ignore_flags_set(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, Evas_Event_Flags ignore_flags)
6636 {
6637    if (!rp) return;
6638 
6639    rp->ignore_flags = ignore_flags;
6640 }
6641 
6642 Evas_Event_Flags
_edje_real_part_mask_flags_get(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)6643 _edje_real_part_mask_flags_get(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
6644 {
6645    if (!rp) return EVAS_EVENT_FLAG_NONE;
6646 
6647    return rp->mask_flags;
6648 }
6649 
6650 void
_edje_real_part_mask_flags_set(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,Evas_Event_Flags mask_flags)6651 _edje_real_part_mask_flags_set(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, Evas_Event_Flags mask_flags)
6652 {
6653    if (!rp) return;
6654 
6655    rp->mask_flags = mask_flags;
6656 }
6657 
6658 /* Legacy APIs */
6659 
6660 static inline Eina_Bool
_edje_part_fetch(const Edje_Object * obj,const char * part,Edje ** ped,Edje_Real_Part ** prp)6661 _edje_part_fetch(const Edje_Object *obj, const char *part, Edje **ped, Edje_Real_Part **prp)
6662 {
6663    if (!part) return EINA_FALSE;
6664 
6665    *ped = _edje_fetch(obj);
6666    if (!*ped) return EINA_FALSE;
6667 
6668    *prp = _edje_real_part_recursive_get(ped, part);
6669    if (!*prp) return EINA_FALSE;
6670 
6671    return EINA_TRUE;
6672 }
6673 
6674 EAPI Eina_Bool
edje_object_part_swallow(Edje_Object * obj,const char * part,Evas_Object * obj_swallow)6675 edje_object_part_swallow(Edje_Object *obj, const char *part, Evas_Object *obj_swallow)
6676 {
6677    Edje_Real_Part *rp;
6678    Edje *ed;
6679 
6680    if (!_edje_part_fetch(obj, part, &ed, &rp)) return EINA_FALSE;
6681 
6682    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
6683      {
6684         ERR("Invalid call on a non-swallow part: '%s' in group '%s'", part, ed->group);
6685         return EINA_FALSE;
6686      }
6687 
6688    return efl_content_set(efl_part(obj, part), obj_swallow);
6689 }
6690 
6691 EAPI void
edje_object_part_unswallow(Edje_Object * obj,Evas_Object * obj_swallow)6692 edje_object_part_unswallow(Edje_Object *obj, Evas_Object *obj_swallow)
6693 {
6694    efl_canvas_layout_content_remove(obj, obj_swallow);
6695 }
6696 
6697 EAPI Evas_Object *
edje_object_part_swallow_get(const Edje_Object * obj,const char * part)6698 edje_object_part_swallow_get(const Edje_Object *obj, const char *part)
6699 {
6700    Edje_Real_Part *rp;
6701    Edje *ed;
6702 
6703    if (!_edje_part_fetch(obj, part, &ed, &rp)) return NULL;
6704 
6705    if (rp->part->type != EDJE_PART_TYPE_SWALLOW)
6706      {
6707         // Legacy compatibility: return swallowed_object on non-swallow parts
6708         if ((rp->type == EDJE_RP_TYPE_SWALLOW) && rp->typedata.swallow)
6709           {
6710              INF("Part is not a swallow: '%s' in group '%s'", part, ed->group);
6711              return rp->typedata.swallow->swallowed_object;
6712           }
6713 
6714         ERR("Invalid call on a non-swallow part: '%s' in group '%s'", part, ed->group);
6715         return NULL;
6716      }
6717 
6718    return efl_content_get(efl_part(obj, part));
6719 }
6720 
6721 EAPI Eina_Bool
edje_object_part_text_set(const Edje_Object * obj,const char * part,const char * text)6722 edje_object_part_text_set(const Edje_Object *obj, const char *part, const char *text)
6723 {
6724    Edje *ed;
6725 
6726    ed = _edje_fetch(obj);
6727 
6728    return _edje_efl_text_text_set((Eo *) obj, ed, part, text, EINA_TRUE, EINA_TRUE);
6729 }
6730 
6731 EAPI const char *
edje_object_part_text_get(const Edje_Object * obj,const char * part)6732 edje_object_part_text_get(const Edje_Object *obj, const char *part)
6733 {
6734    Edje_Real_Part *rp;
6735    Edje *ed;
6736 
6737    if (!_edje_part_fetch(obj, part, &ed, &rp)) return NULL;
6738 
6739    if ((rp->part->type != EDJE_PART_TYPE_TEXT) &&
6740        (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK))
6741      {
6742         ERR("Invalid call on a non-text or non-textblock part: '%s' in group '%s'", part, ed->group);
6743         return NULL;
6744      }
6745 
6746    ed = _edje_fetch(obj);
6747    if (!ed)
6748      {
6749         ERR("Failed to get Edje data from object: '%p'", obj);
6750         return NULL;
6751      }
6752 
6753    return _edje_efl_text_text_get(obj, ed, part, EINA_TRUE, EINA_FALSE);
6754 }
6755 
6756 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
6757