Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / lib / edje_load.c
1 #include "edje_private.h"
2
3 typedef struct _Edje_Table_Items Edje_Table_Items;
4 struct _Edje_Table_Items
5 {
6    Evas_Object *child;
7    const char *part;
8    unsigned short col;
9    unsigned short row;
10    unsigned short colspan;
11    unsigned short rowspan;
12 };
13
14 typedef struct _Edje_Drag_Items Edje_Drag_Items;
15 struct _Edje_Drag_Items
16 {
17    const char *part;
18    FLOAT_T x, y, w, h;
19    struct {
20       FLOAT_T x, y;
21    } step;
22    struct {
23       FLOAT_T x, y;
24    } page;
25 };
26
27 #ifdef EDJE_PROGRAM_CACHE
28 static Eina_Bool  _edje_collection_free_prog_cache_matches_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
29 #endif
30 static void _edje_object_pack_item_hints_set(Evas_Object *obj, Edje_Pack_Element *it);
31 static void _cb_signal_repeat(void *data, Evas_Object *obj, const char *signal, const char *source);
32
33 static Eina_List *_edje_object_collect(Edje *ed);
34
35 static int _sort_defined_boxes(const void *a, const void *b);
36
37 /************************** API Routines **************************/
38
39 EAPI Eina_Bool
40 edje_object_file_set(Evas_Object *obj, const char *file, const char *group)
41 {
42    Eina_Bool ret;
43    Edje *ed;
44
45    ed = _edje_fetch(obj);
46    if (!ed)
47      return EINA_FALSE;
48    ret = ed->api->file_set(obj, file, group);
49    _edje_object_orientation_inform(obj);
50    return ret;
51 }
52
53 EAPI void
54 edje_object_file_get(const Evas_Object *obj, const char **file, const char **group)
55 {
56    Edje *ed;
57
58    ed = _edje_fetch(obj);
59    if (!ed)
60      {
61         if (file) *file = NULL;
62         if (group) *group = NULL;
63         return;
64      }
65    if (file) *file = ed->path;
66    if (group) *group = ed->group;
67 }
68
69 EAPI Edje_Load_Error
70 edje_object_load_error_get(const Evas_Object *obj)
71 {
72    Edje *ed;
73
74    ed = _edje_fetch(obj);
75    if (!ed) return EDJE_LOAD_ERROR_NONE;
76    return ed->load_error;
77 }
78
79 EAPI const char *
80 edje_load_error_str(Edje_Load_Error error)
81 {
82    switch (error)
83      {
84       case EDJE_LOAD_ERROR_NONE:
85          return "No Error";
86       case EDJE_LOAD_ERROR_GENERIC:
87          return "Generic Error";
88       case EDJE_LOAD_ERROR_DOES_NOT_EXIST:
89          return "File Does Not Exist";
90       case EDJE_LOAD_ERROR_PERMISSION_DENIED:
91          return "Permission Denied";
92       case EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED:
93          return "Resource Allocation Failed";
94       case EDJE_LOAD_ERROR_CORRUPT_FILE:
95          return "Corrupt File";
96       case EDJE_LOAD_ERROR_UNKNOWN_FORMAT:
97          return "Unknown Format";
98       case EDJE_LOAD_ERROR_INCOMPATIBLE_FILE:
99          return "Incompatible File";
100       case EDJE_LOAD_ERROR_UNKNOWN_COLLECTION:
101          return "Unknown Collection";
102       case EDJE_LOAD_ERROR_RECURSIVE_REFERENCE:
103          return "Recursive Reference";
104       default:
105          return "Unknown Error";
106      }
107 }
108
109
110 EAPI Eina_List *
111 edje_file_collection_list(const char *file)
112 {
113    Eina_List *lst = NULL;
114    Edje_File *edf;
115    int error_ret = 0;
116
117    if ((!file) || (!*file)) return NULL;
118    edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL);
119    if (edf)
120      {
121         Eina_Iterator *i;
122         const char *key;
123
124         i = eina_hash_iterator_key_new(edf->collection);
125
126         EINA_ITERATOR_FOREACH(i, key)
127           lst = eina_list_append(lst, eina_stringshare_add(key));
128
129         eina_iterator_free(i);
130
131         _edje_cache_file_unref(edf);
132      }
133    return lst;
134 }
135
136 EAPI void
137 edje_file_collection_list_free(Eina_List *lst)
138 {
139    while (lst)
140      {
141         if (eina_list_data_get(lst)) eina_stringshare_del(eina_list_data_get(lst));
142         lst = eina_list_remove(lst, eina_list_data_get(lst));
143      }
144 }
145
146 EAPI Eina_Bool
147 edje_file_group_exists(const char *file, const char *glob)
148 {
149    Edje_File *edf;
150    int error_ret = 0;
151    Eina_Bool succeed = EINA_FALSE;
152    Eina_Bool is_glob = EINA_FALSE;
153    const char *p;
154
155    if ((!file) || (!*file) || (!glob))
156       return EINA_FALSE;
157
158    edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL);
159    if (!edf)
160       return EINA_FALSE;
161
162    for (p = glob; *p; p++)
163      {
164        if ((*p == '*') || (*p == '?') || (*p == '['))
165          {
166            is_glob = EINA_TRUE;
167            break;
168          }
169      }
170
171    if (is_glob)
172      {
173        if (!edf->collection_patterns)
174          {
175            Edje_Part_Collection_Directory_Entry *ce;
176            Eina_Iterator *i;
177            Eina_List *l = NULL;
178
179            i = eina_hash_iterator_data_new(edf->collection);
180
181            EINA_ITERATOR_FOREACH(i, ce)
182              l = eina_list_append(l, ce);
183
184            eina_iterator_free(i);
185
186            edf->collection_patterns = edje_match_collection_dir_init(l);
187            eina_list_free(l);
188          }
189
190        succeed = edje_match_collection_dir_exec(edf->collection_patterns, glob);
191        if (edf->collection_patterns)
192          {
193            edje_match_patterns_free(edf->collection_patterns);
194            edf->collection_patterns = NULL;
195          }
196      }
197    else
198      {
199         if (eina_hash_find(edf->collection, glob)) succeed = EINA_TRUE;
200      }
201    _edje_cache_file_unref(edf);
202
203    INF("edje_file_group_exists: '%s', '%s': %i\n", file, glob, succeed);
204
205    return succeed;
206 }
207
208
209 EAPI char *
210 edje_file_data_get(const char *file, const char *key)
211 {
212    Edje_File *edf;
213    char *str = NULL;
214    int error_ret = 0;
215
216    if (key)
217      {
218         edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL);
219         if (edf)
220           {
221              str = (char*) edje_string_get(eina_hash_find(edf->data, key));
222
223              if (str) str = strdup(str);
224
225              _edje_cache_file_unref(edf);
226           }
227      }
228    return str;
229 }
230
231 void
232 _edje_programs_patterns_clean(Edje *ed)
233 {
234    _edje_signals_sources_patterns_clean(&ed->patterns.programs);
235
236    eina_rbtree_delete(ed->patterns.programs.exact_match,
237                       EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
238                       NULL);
239    ed->patterns.programs.exact_match = NULL;
240
241    free(ed->patterns.programs.u.programs.globing);
242    ed->patterns.programs.u.programs.globing = NULL;
243 }
244
245 void
246 _edje_programs_patterns_init(Edje *ed)
247 {
248    Edje_Signals_Sources_Patterns *ssp = &ed->patterns.programs;
249    Edje_Program **all;
250    unsigned int i, j;
251
252    if (ssp->signals_patterns)
253      return;
254
255    if (getenv("EDJE_DUMP_PROGRAMS"))
256      {
257        INF("Group '%s' programs:", ed->group);
258 #define EDJE_DUMP_PROGRAM(Section)                                      \
259        for (i = 0; i < ed->collection->programs.Section##_count; i++)   \
260          INF(#Section" for ('%s', '%s')", ed->collection->programs.Section[i]->signal, ed->collection->programs.Section[i]->source);
261
262        EDJE_DUMP_PROGRAM(strcmp);
263        EDJE_DUMP_PROGRAM(strncmp);
264        EDJE_DUMP_PROGRAM(strrncmp);
265        EDJE_DUMP_PROGRAM(fnmatch);
266        EDJE_DUMP_PROGRAM(nocmp);
267      }
268
269    edje_match_program_hash_build(ed->collection->programs.strcmp,
270                                  ed->collection->programs.strcmp_count,
271                                  &ssp->exact_match);
272
273    j = ed->collection->programs.strncmp_count
274      + ed->collection->programs.strrncmp_count
275      + ed->collection->programs.fnmatch_count
276      + ed->collection->programs.nocmp_count;
277    if (j == 0) return ;
278
279    all = malloc(sizeof (Edje_Program *) * j);
280    if (!all) return ;
281    j = 0;
282
283    /* FIXME: Build specialized data type for each case */
284 #define EDJE_LOAD_PROGRAMS_ADD(Array, Ed, It, Git, All)                 \
285    for (It = 0; It < Ed->collection->programs.Array##_count; ++It, ++Git) \
286      All[Git] = Ed->collection->programs.Array[It];
287
288    EDJE_LOAD_PROGRAMS_ADD(fnmatch, ed, i, j, all);
289    EDJE_LOAD_PROGRAMS_ADD(strncmp, ed, i, j, all);
290    EDJE_LOAD_PROGRAMS_ADD(strrncmp, ed, i, j, all);
291    /* FIXME: Do a special pass for that one */
292    EDJE_LOAD_PROGRAMS_ADD(nocmp, ed, i, j, all);
293
294    ssp->u.programs.globing = all;
295    ssp->u.programs.count = j;
296    ssp->signals_patterns = edje_match_programs_signal_init(all, j);
297    ssp->sources_patterns = edje_match_programs_source_init(all, j);
298 }
299
300 int
301 _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *group, const char *parent, Eina_List *group_path)
302 {
303    Edje *ed;
304    Evas *tev;
305    Edje_Real_Part *rp;
306    Eina_List *textblocks = NULL;
307    Eina_List *sources = NULL;
308    Eina_List *externals = NULL;
309    Eina_List *collect = NULL;
310    unsigned int n;
311    Eina_List *parts = NULL;
312    int group_path_started = 0;
313
314    ed = _edje_fetch(obj);
315    if (!ed) return 0;
316    if (!file) file = "";
317    if (!group) group = "";
318    if (((ed->path) && (!strcmp(file, ed->path))) &&
319        (ed->group) && (!strcmp(group, ed->group)) &&
320        ed->file)
321      {
322         struct stat st;
323
324         if (stat(file, &st) != 0)
325           return 1;
326         if (st.st_mtime == ed->file->mtime)
327           return 1;
328      }
329
330    tev = evas_object_evas_get(obj);
331    evas_event_freeze(tev);
332
333    collect = _edje_object_collect(ed);
334
335    if (_edje_script_only(ed)) _edje_script_only_shutdown(ed);
336    if (_edje_lua_script_only(ed)) _edje_lua_script_only_shutdown(ed);
337
338    _edje_file_del(ed);
339
340    eina_stringshare_replace(&ed->path, file);
341    eina_stringshare_replace(&ed->group, group);
342
343    ed->parent = eina_stringshare_add(parent);
344
345    ed->load_error = EDJE_LOAD_ERROR_NONE;
346    _edje_file_add(ed);
347    ed->block_break = 0;
348
349    if (ed->file && ed->file->external_dir)
350      {
351         unsigned int i;
352
353         for (i = 0; i < ed->file->external_dir->entries_count; ++i)
354           edje_module_load(ed->file->external_dir->entries[i].entry);
355      }
356
357    _edje_textblock_styles_add(ed);
358    _edje_textblock_style_all_update(ed);
359
360    ed->has_entries = EINA_FALSE;
361
362    if (ed->collection)
363      {
364         if (ed->collection->prop.orientation != EDJE_ORIENTATION_AUTO)
365           ed->is_rtl = (ed->collection->prop.orientation ==
366                         EDJE_ORIENTATION_RTL);
367
368         ed->groups = eina_list_append(ed->groups, ed);
369
370         if (ed->collection->script_only)
371           {
372              ed->load_error = EDJE_LOAD_ERROR_NONE;
373              _edje_script_only_init(ed);
374           }
375         else if (ed->collection->lua_script_only)
376           {
377              ed->load_error = EDJE_LOAD_ERROR_NONE;
378              _edje_lua_script_only_init(ed);
379           }
380         else
381           {
382              unsigned int i;
383
384              /* colorclass stuff */
385              for (i = 0; i < ed->collection->parts_count; ++i)
386                {
387                   Edje_Part *ep;
388                   unsigned int k;
389
390                   ep = ed->collection->parts[i];
391
392                   /* Register any color classes in this parts descriptions. */
393                   if ((ep->default_desc) && (ep->default_desc->color_class))
394                     _edje_color_class_member_add(ed, ep->default_desc->color_class);
395
396                   for (k = 0; k < ep->other.desc_count; k++)
397                     {
398                        Edje_Part_Description_Common *desc;
399
400                        desc = ep->other.desc[k];
401
402                        if (desc->color_class)
403                          _edje_color_class_member_add(ed, desc->color_class);
404                     }
405                }
406              /* build real parts */
407              for (n = 0; n < ed->collection->parts_count; n++)
408                {
409                   Edje_Part *ep;
410
411                   ep = ed->collection->parts[n];
412                   rp = eina_mempool_malloc(_edje_real_part_mp, sizeof(Edje_Real_Part));
413                   if (!rp)
414                     {
415                        /* FIXME: destroy all allocated ressource, need to have a common exit point */
416                        ed->load_error = EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
417                        evas_event_thaw(tev);
418                        evas_event_thaw_eval(tev);
419                        return 0;
420                     }
421
422                   memset(rp, 0, sizeof (Edje_Real_Part));
423
424                   if ((ep->dragable.x != 0) || (ep->dragable.y != 0))
425                     {
426                        rp->drag = calloc(1, sizeof (Edje_Real_Part_Drag));
427                        if (!rp->drag)
428                          {
429                             ed->load_error = EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
430                             eina_mempool_free(_edje_real_part_mp, rp);
431                             evas_event_thaw(tev);
432                             evas_event_thaw_eval(tev);
433                             return 0;
434                          }
435
436                        rp->drag->step.x = FROM_INT(ep->dragable.step_x);
437                        rp->drag->step.y = FROM_INT(ep->dragable.step_y);
438                     }
439
440                   rp->edje = ed;
441                   _edje_ref(rp->edje);
442                   rp->part = ep;
443                   parts = eina_list_append(parts, rp);
444                   rp->param1.description = 
445                     _edje_part_description_find(ed, rp, "default", 0.0);
446                   rp->chosen_description = rp->param1.description;
447                   if (!rp->param1.description)
448                     ERR("no default part description for '%s'!",
449                         rp->part->name);
450
451                   switch (ep->type)
452                     {
453                      case EDJE_PART_TYPE_RECTANGLE:
454                         rp->object = evas_object_rectangle_add(ed->base.evas);
455                         break;
456                      case EDJE_PART_TYPE_PROXY:
457                      case EDJE_PART_TYPE_IMAGE:
458                         rp->object = evas_object_image_add(ed->base.evas);
459                         break;
460                      case EDJE_PART_TYPE_TEXT:
461                         _edje_text_part_on_add(ed, rp);
462                         rp->object = evas_object_text_add(ed->base.evas);
463                         evas_object_text_font_source_set(rp->object, ed->path);
464                         break;
465                      case EDJE_PART_TYPE_GROUP:
466                         sources = eina_list_append(sources, rp);
467                      case EDJE_PART_TYPE_SWALLOW:
468                      case EDJE_PART_TYPE_EXTERNAL:
469                         if (ep->type == EDJE_PART_TYPE_EXTERNAL)
470                           externals = eina_list_append(externals, rp);
471                         rp->object = evas_object_rectangle_add(ed->base.evas);
472                         evas_object_color_set(rp->object, 0, 0, 0, 0);
473                         evas_object_pass_events_set(rp->object, 1);
474                         evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
475                         _edje_callbacks_focus_add(rp->object, ed, rp);
476                         break;
477                      case EDJE_PART_TYPE_TEXTBLOCK:
478                         textblocks = eina_list_append(textblocks, rp);
479                         rp->object = evas_object_textblock_add(ed->base.evas);
480                         break;
481                      case EDJE_PART_TYPE_BOX:
482                         sources = eina_list_append(sources, rp);
483                         rp->object = evas_object_box_add(ed->base.evas);
484                         rp->anim = _edje_box_layout_anim_new(rp->object);
485                         break;
486                      case EDJE_PART_TYPE_TABLE:
487                         sources = eina_list_append(sources, rp);
488                         rp->object = evas_object_table_add(ed->base.evas);
489                         break;
490                      case EDJE_PART_TYPE_GRADIENT:
491                         ERR("SPANK ! SPANK ! SPANK ! YOU ARE USING GRADIENT IN PART %s FROM GROUP %s INSIDE FILE %s !! THEY ARE NOW REMOVED !",
492                             ep->name, group, file);
493                         break;
494                      case EDJE_PART_TYPE_SPACER:
495                         rp->object = NULL;
496                         break;
497                      default:
498                         ERR("wrong part type %i!", ep->type);
499                         break;
500                     }
501
502                   if (rp->object)
503                     {
504                        evas_object_smart_member_add(rp->object, ed->obj);
505 //                     evas_object_layer_set(rp->object, evas_object_layer_get(ed->obj));
506                        if (ep->type != EDJE_PART_TYPE_SWALLOW && ep->type != EDJE_PART_TYPE_GROUP && ep->type != EDJE_PART_TYPE_EXTERNAL)
507                          {
508                             if (ep->mouse_events)
509                               {
510                                  _edje_callbacks_add(rp->object, ed, rp);
511                                  if (ep->repeat_events)
512                                    evas_object_repeat_events_set(rp->object, 1);
513                                  
514                                  if (ep->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
515                                    evas_object_pointer_mode_set(rp->object, ep->pointer_mode);
516                               }
517                             else
518                               {
519                                  evas_object_pass_events_set(rp->object, 1);
520                                  evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
521                               }
522                             if (ep->precise_is_inside)
523                               evas_object_precise_is_inside_set(rp->object, 1);
524                          }
525                        if (rp->part->clip_to_id < 0)
526                          evas_object_clip_set(rp->object, ed->base.clipper);
527                     }
528                }
529              if (n > 0)
530                {
531                   Eina_List *l;
532
533                   ed->table_parts = malloc(sizeof(Edje_Real_Part *) * n);
534                   ed->table_parts_size = n;
535                   /* FIXME: check malloc return */
536                   n = 0;
537                   EINA_LIST_FOREACH(parts, l, rp)
538                     {
539                        ed->table_parts[n] = rp;
540                        n++;
541                     }
542                   eina_list_free(parts);
543                   for (i = 0; i < ed->table_parts_size; i++)
544                     {
545                        rp = ed->table_parts[i];
546                        if (rp->param1.description) /* FIXME: prevent rel to gone radient part to go wrong. You may
547                                                       be able to remove this when all theme are correctly rewritten. */
548                          {
549                             if (rp->param1.description->rel1.id_x >= 0)
550                               rp->param1.rel1_to_x = ed->table_parts[rp->param1.description->rel1.id_x % ed->table_parts_size];
551                             if (rp->param1.description->rel1.id_y >= 0)
552                               rp->param1.rel1_to_y = ed->table_parts[rp->param1.description->rel1.id_y % ed->table_parts_size];
553                             if (rp->param1.description->rel2.id_x >= 0)
554                               rp->param1.rel2_to_x = ed->table_parts[rp->param1.description->rel2.id_x % ed->table_parts_size];
555                             if (rp->param1.description->rel2.id_y >= 0)
556                               rp->param1.rel2_to_y = ed->table_parts[rp->param1.description->rel2.id_y % ed->table_parts_size];
557                          }
558                        if (rp->part->clip_to_id >= 0)
559                          {
560                             rp->clip_to = ed->table_parts[rp->part->clip_to_id % ed->table_parts_size];
561                             if (rp->clip_to &&
562                                 rp->clip_to->object &&
563                                 rp->object)
564                               {
565                                  evas_object_pass_events_set(rp->clip_to->object, 1);
566                                  evas_object_pointer_mode_set(rp->clip_to->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
567                                  evas_object_clip_set(rp->object, rp->clip_to->object);
568                               }
569                          }
570                        if (rp->drag)
571                          {
572                             if (rp->part->dragable.confine_id >= 0)
573                               rp->drag->confine_to = ed->table_parts[rp->part->dragable.confine_id % ed->table_parts_size];
574                          }
575
576                        /* replay events for dragable */
577                        if (rp->part->dragable.event_id >= 0)
578                          {
579                             rp->events_to =
580                               ed->table_parts[rp->part->dragable.event_id % ed->table_parts_size];
581                             /* events_to may be used only with dragable */
582                             if (!rp->events_to->part->dragable.x &&
583                                 !rp->events_to->part->dragable.y)
584                               rp->events_to = NULL;
585                          }
586
587                        rp->swallow_params.min.w = 0;
588                        rp->swallow_params.min.h = 0;
589                        rp->swallow_params.max.w = -1;
590                        rp->swallow_params.max.h = -1;
591
592                        if (rp->part->type == EDJE_PART_TYPE_TEXT
593                            || rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
594                          {
595                             Edje_Part_Description_Text *text;
596
597                             text = (Edje_Part_Description_Text *) rp->param1.description;
598
599                             if (ed->file->feature_ver < 1)
600                               {
601                                  text->text.id_source = -1;
602                                  text->text.id_text_source = -1;
603                               }
604
605                             if (text->text.id_source >= 0)
606                               rp->text.source = ed->table_parts[text->text.id_source % ed->table_parts_size];
607                             if (text->text.id_text_source >= 0)
608                               rp->text.text_source = ed->table_parts[text->text.id_text_source % ed->table_parts_size];
609                             if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
610                               {
611                                  _edje_entry_real_part_init(rp);
612                                  if (!ed->has_entries)
613                                    ed->has_entries = EINA_TRUE;
614                               }
615                          }
616                     }
617                }
618              
619              _edje_programs_patterns_init(ed);
620
621              n = ed->collection->programs.fnmatch_count +
622                ed->collection->programs.strcmp_count +
623                ed->collection->programs.strncmp_count +
624                ed->collection->programs.strrncmp_count +
625                ed->collection->programs.nocmp_count;
626              if (n > 0)
627                {
628                   Edje_Program *pr;
629
630                   ed->table_programs = malloc(sizeof(Edje_Program *) * n);
631                   if (ed->table_programs)
632                     {
633                        ed->table_programs_size = n;
634
635 #define EDJE_LOAD_BUILD_TABLE(Array, Ed, It, Tmp)       \
636                        for (It = 0; It < Ed->collection->programs.Array##_count; ++It) \
637                          {                                              \
638                             Tmp = Ed->collection->programs.Array[It];   \
639                             Ed->table_programs[Tmp->id] = Tmp;          \
640                          }
641
642                        EDJE_LOAD_BUILD_TABLE(fnmatch, ed, i, pr);
643                        EDJE_LOAD_BUILD_TABLE(strcmp, ed, i, pr);
644                        EDJE_LOAD_BUILD_TABLE(strncmp, ed, i, pr);
645                        EDJE_LOAD_BUILD_TABLE(strrncmp, ed, i, pr);
646                        EDJE_LOAD_BUILD_TABLE(nocmp, ed, i, pr);
647                     }
648                }
649              _edje_ref(ed);
650              _edje_block(ed);
651              _edje_freeze(ed);
652 //           if (ed->collection->script) _edje_embryo_script_init(ed);
653              _edje_var_init(ed);
654              for (i = 0; i < ed->table_parts_size; i++)
655                {
656                   rp = ed->table_parts[i];
657                   evas_object_show(rp->object);
658                   if (_edje_block_break(ed)) break;
659                   if (rp->drag)
660                     {
661                        if (rp->part->dragable.x < 0) rp->drag->val.x = FROM_DOUBLE(1.0);
662                        if (rp->part->dragable.y < 0) rp->drag->val.x = FROM_DOUBLE(1.0);
663                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
664                     }
665                }
666              ed->recalc_call = 1;
667              ed->dirty = 1;
668 #ifdef EDJE_CALC_CACHE
669              ed->all_part_change = 1;
670 #endif
671              if ((evas_object_clipees_get(ed->base.clipper)) &&
672                  (evas_object_visible_get(obj)))
673                evas_object_show(ed->base.clipper);
674
675              /* instantiate 'internal swallows' */
676              EINA_LIST_FREE(externals, rp)
677                {
678                   Edje_Part_Description_External *external;
679                   Evas_Object *child_obj;
680
681                   external = (Edje_Part_Description_External *) rp->part->default_desc;
682                   child_obj = _edje_external_type_add(rp->part->source,
683                                                       evas_object_evas_get(ed->obj), ed->obj,
684                                                       external->external_params, rp->part->name);
685                   if (child_obj)
686                     {
687                        _edje_real_part_swallow(rp, child_obj, EINA_TRUE);
688                        rp->param1.external_params = _edje_external_params_parse(child_obj,
689                                                                                 external->external_params);
690                        _edje_external_recalc_apply(ed, rp, NULL, rp->chosen_description);
691                     }
692                }
693
694              EINA_LIST_FREE(sources, rp)
695                {
696                   /* XXX: curr_item and pack_it don't require to be NULL since
697                    * XXX: they are just used when source != NULL and type == BOX,
698                    * XXX: and they're always set in this case, but GCC fails to
699                    * XXX: notice that, so let's shut it up
700                    */
701                   Edje_Pack_Element **curr_item = NULL;
702                   unsigned int item_count = 0;
703                   Edje_Pack_Element *pack_it = NULL;
704                   const char *source = NULL;
705
706                   switch (rp->part->type)
707                     {
708                      case EDJE_PART_TYPE_GROUP:
709                         source = rp->part->source;
710                         break;
711                      case EDJE_PART_TYPE_BOX:
712                      case EDJE_PART_TYPE_TABLE:
713                         if (rp->part->items)
714                           {
715                              curr_item = rp->part->items;
716                              item_count = rp->part->items_count;
717                              if (item_count > 0)
718                                {
719                                   pack_it = *curr_item;
720                                   source = pack_it->source;
721                                   item_count--;
722                                   curr_item++;
723                                }
724                           }
725                         break;
726                      default:
727                         /* This list should only be filled by group, box or table, nothing else. */
728                         abort();
729                         continue;
730                     }
731
732                   while (source)
733                     {
734                        Eina_List *l;
735                        Evas_Object *child_obj;
736                        const char *group_path_entry = eina_stringshare_add(source);
737                        const char *data;
738
739                        if (!group_path)
740                          {
741                             group_path = eina_list_append(NULL, eina_stringshare_add(group));
742                             group_path_started = 1;
743                          }
744                        /* make sure that this group isn't already in the tree of parents */
745                        EINA_LIST_FOREACH(group_path, l, data)
746                          {
747                             if (data == group_path_entry)
748                               {
749                                  ERR("recursive loop group '%s' already included inside part '%s' of group '%s' from file '%s'",
750                                      group_path_entry, rp->part->name, group, file);
751                                  textblocks = eina_list_free(textblocks);
752                                  externals = eina_list_free(externals);
753                                  sources = eina_list_free(sources);
754                                  _edje_thaw(ed);
755                                  _edje_unblock(ed);
756                                  _edje_unref(ed);
757                                  _edje_file_del(ed);
758                                  eina_stringshare_del(group_path_entry);
759                                  if (group_path_started)
760                                    {
761                                       eina_stringshare_del(eina_list_data_get(group_path));
762                                       eina_list_free(group_path);
763                                    }
764                                  ed->load_error = EDJE_LOAD_ERROR_RECURSIVE_REFERENCE;
765                                  evas_event_thaw(tev);
766                                  evas_event_thaw_eval(tev);
767                                  return 0;
768                               }
769                          }
770
771                        child_obj = edje_object_add(ed->base.evas);
772                        group_path = eina_list_append(group_path, group_path_entry);
773                        if (rp->part->type == EDJE_PART_TYPE_GROUP)
774                          {
775                             _edje_real_part_swallow(rp, child_obj, EINA_FALSE);
776                          }
777
778                        if (!_edje_object_file_set_internal(child_obj, file, source, rp->part->name, group_path))
779                          {
780                             ERR("impossible to set part '%s' of group '%s' from file '%s' to '%s'",
781                                 rp->part->name, group_path_entry, file, source);
782                             textblocks = eina_list_free(textblocks);
783                             externals = eina_list_free(externals);
784                             sources = eina_list_free(sources);
785                             _edje_thaw(ed);
786                             _edje_unblock(ed);
787                             _edje_unref(ed);
788                             _edje_file_del(ed);
789
790                             if (group_path_started)
791                               {
792                                  while (group_path)
793                                    {
794                                       eina_stringshare_del(eina_list_data_get(group_path));
795                                       group_path = eina_list_remove_list(group_path, group_path);
796                                    }
797                               }
798                             ed->load_error = edje_object_load_error_get(child_obj);
799                             evas_object_del(child_obj);
800                             evas_event_thaw(tev);
801                             evas_event_thaw_eval(tev);
802                             return 0;
803                          }
804
805                        group_path = eina_list_remove(group_path, group_path_entry);
806                        eina_stringshare_del(group_path_entry);
807
808                        edje_object_propagate_callback_add(child_obj,
809                                                           _cb_signal_repeat,
810                                                           obj);
811                        if (rp->part->type == EDJE_PART_TYPE_GROUP)
812                          {
813                             ed->groups = eina_list_append(ed->groups, _edje_fetch(child_obj));
814                             _edje_real_part_swallow(rp, child_obj, EINA_TRUE);
815                             _edje_subobj_register(ed, child_obj);
816                             source = NULL;
817                          }
818                        else
819                          {
820                             pack_it->parent = rp;
821
822                             _edje_object_pack_item_hints_set(child_obj, pack_it);
823                             if (pack_it->name)
824                                  evas_object_name_set(child_obj, pack_it->name);
825
826                             if (rp->part->type == EDJE_PART_TYPE_BOX)
827                               {
828                                  _edje_real_part_box_append(rp, child_obj);
829                                  evas_object_data_set(child_obj, "\377 edje.box_item", pack_it);
830                               }
831                             else if (rp->part->type == EDJE_PART_TYPE_TABLE)
832                               {
833                                  _edje_real_part_table_pack(rp, child_obj, pack_it->col, pack_it->row, pack_it->colspan, pack_it->rowspan);
834                                  evas_object_data_set(child_obj, "\377 edje.table_item", pack_it);
835                               }
836                             _edje_subobj_register(ed, child_obj);
837                             evas_object_show(child_obj);
838                             rp->items = eina_list_append(rp->items, child_obj);
839
840                             if (item_count > 0)
841                               {
842                                  pack_it = *curr_item;
843                                  source = pack_it->source;
844                                  curr_item++;
845                                  item_count--;
846                               }
847                             else
848                               {
849                                  source = NULL;
850                                  curr_item = NULL;
851                                  pack_it = NULL;
852                               }
853                          }
854                     }
855                }
856
857              if (group_path_started)
858                {
859                   const char *str;
860
861                   EINA_LIST_FREE(group_path, str)
862                     eina_stringshare_del(str);
863                }
864
865              /* reswallow any swallows that existed before setting the file */
866              if (collect)
867                {
868                   Edje_User_Defined *eud;
869                   Eina_List *boxes = NULL;
870
871                   EINA_LIST_FREE(collect, eud)
872                     {
873                        Evas_Object *child = NULL;
874
875                        switch (eud->type)
876                          {
877                           case EDJE_USER_SWALLOW:
878                              edje_object_part_swallow(obj, eud->part, eud->u.swallow.child);
879                              child = eud->u.swallow.child;
880                              break;
881                           case EDJE_USER_BOX_PACK:
882                              boxes = eina_list_append(boxes, eud);
883                              eud = NULL;
884                              break;
885                           case EDJE_USER_TABLE_PACK:
886                              edje_object_part_table_pack(obj, eud->part, eud->u.table.child,
887                                                          eud->u.table.col, eud->u.table.row,
888                                                          eud->u.table.colspan, eud->u.table.rowspan);
889                              child = eud->u.table.child;
890                              break;
891                           case EDJE_USER_DRAG_STEP:
892                              edje_object_part_drag_step_set(obj, eud->part,
893                                                             eud->u.drag_position.x,
894                                                             eud->u.drag_position.y);
895                              break;
896                           case EDJE_USER_DRAG_PAGE:
897                              edje_object_part_drag_page_set(obj, eud->part,
898                                                             eud->u.drag_position.x,
899                                                             eud->u.drag_position.y);
900                              break;
901                           case EDJE_USER_DRAG_VALUE:
902                              edje_object_part_drag_value_set(obj, eud->part,
903                                                              eud->u.drag_position.x,
904                                                              eud->u.drag_position.y);
905                              break;
906                           case EDJE_USER_DRAG_SIZE:
907                              edje_object_part_drag_size_set(obj, eud->part,
908                                                             eud->u.drag_size.w,
909                                                             eud->u.drag_size.h);
910                              break;
911                           case EDJE_USER_STRING:
912                              edje_object_part_text_set(obj, eud->part, eud->u.string.text);
913                              eina_stringshare_del(eud->u.string.text);
914                              break;
915                          }
916                        if (eud) _edje_user_definition_remove(eud, child);
917                     }
918
919                   boxes = eina_list_sort(boxes, -1, _sort_defined_boxes);
920                   EINA_LIST_FREE(boxes, eud)
921                     {
922                        edje_object_part_box_append(obj, eud->part, eud->u.box.child);
923                        _edje_user_definition_remove(eud, eud->u.box.child);
924                     }
925                }
926
927              if (edje_object_mirrored_get(obj))
928                edje_object_signal_emit(obj, "edje,state,rtl", "edje");
929              else
930                edje_object_signal_emit(obj, "edje,state,ltr", "edje");
931
932              _edje_recalc(ed);
933              _edje_thaw(ed);
934              _edje_unblock(ed);
935              _edje_unref(ed);
936              ed->load_error = EDJE_LOAD_ERROR_NONE;
937              _edje_emit(ed, "load", NULL);
938
939              /* instantiate 'internal textblock style' */
940              EINA_LIST_FREE(textblocks, rp)
941                if (rp->part->default_desc)
942                  {
943                     Edje_Part_Description_Text *text;
944                     Edje_Style *stl  = NULL;
945                     const char *style;
946
947                     text = (Edje_Part_Description_Text *) rp->part->default_desc;
948                     style = edje_string_get(&text->text.style);
949                     if (style)
950                       {
951                          Eina_List *l;
952
953                          EINA_LIST_FOREACH(ed->file->styles, l, stl)
954                            {
955                               if ((stl->name) && (!strcmp(stl->name, style))) break;
956                               stl = NULL;
957                            }
958                       }
959                     if (stl)
960                       {
961                          if (evas_object_textblock_style_get(rp->object) != stl->style)
962                            evas_object_textblock_style_set(rp->object, stl->style);
963                       }
964                  }
965           }
966         _edje_entry_init(ed);
967         evas_event_thaw(tev);
968         evas_event_thaw_eval(tev);
969         return 1;
970      }
971    else
972      {
973         evas_event_thaw(tev);
974         evas_event_thaw_eval(tev);
975         return 0;
976      }
977    ed->load_error = EDJE_LOAD_ERROR_NONE;
978    _edje_entry_init(ed);
979    evas_event_thaw(tev);
980    evas_event_thaw_eval(tev);
981    return 1;
982 }
983
984 void
985 _edje_file_add(Edje *ed)
986 {
987    if (!_edje_edd_edje_file) return;
988    ed->file = _edje_cache_file_coll_open(ed->path, ed->group,
989                                          &(ed->load_error),
990                                          &(ed->collection),
991                                          ed);
992
993    if (!ed->collection)
994      {
995         if (ed->file)
996           {
997              _edje_cache_file_unref(ed->file);
998              ed->file = NULL;
999           }
1000      }
1001 }
1002
1003 static int
1004 _sort_defined_boxes(const void *a, const void *b)
1005 {
1006    const Edje_User_Defined *euda = a;
1007    const Edje_User_Defined *eudb = b;
1008
1009    if (euda->part - eudb->part != 0)
1010      return euda->part - eudb->part;
1011    return euda->u.box.index - eudb->u.box.index;
1012 }
1013
1014 static Eina_List *
1015 _edje_object_collect(Edje *ed)
1016 {
1017    Edje_User_Defined *eud;
1018    Eina_List *collect;
1019    Eina_List *l;
1020
1021    collect = ed->user_defined;
1022    ed->user_defined = NULL;
1023
1024    EINA_LIST_FOREACH(collect, l, eud)
1025      {
1026         switch (eud->type)
1027           {
1028            case EDJE_USER_STRING:
1029               eud->u.string.text = eina_stringshare_ref(eud->u.string.text);
1030               break;
1031            case EDJE_USER_BOX_PACK:
1032               if (eud->u.box.index == -1)
1033                 {
1034                    Edje_User_Defined *search;
1035                    Edje_Real_Part *rp;
1036                    Eina_List *children;
1037                    Eina_List *ls;
1038                    Evas_Object *child;
1039                    int idx = 0;
1040
1041                    rp = _edje_real_part_recursive_get(ed, eud->part);
1042                    if (rp->part->type != EDJE_PART_TYPE_BOX) continue ;
1043
1044                    children = evas_object_box_children_get(rp->object);
1045                    EINA_LIST_FREE(children, child)
1046                      if (!evas_object_data_get(child, "\377 edje.box_item"))
1047                        {
1048                           EINA_LIST_FOREACH(l, ls, search)
1049                             {
1050                                if (search->type == EDJE_USER_BOX_PACK &&
1051                                    search->u.box.child == child &&
1052                                    search->part == eud->part /* beauty of stringshare ! */)
1053                                  {
1054                                     search->u.box.index = idx++;
1055                                     break;
1056                                  }
1057                             }
1058                           _edje_real_part_box_remove(rp, child);
1059                        }
1060                 }
1061               break;
1062            case EDJE_USER_TABLE_PACK:
1063              {
1064                 Edje_Real_Part *rp;
1065
1066                 rp = _edje_real_part_recursive_get(ed, eud->part);
1067                 if (rp->part->type != EDJE_PART_TYPE_TABLE) continue ;
1068
1069                 _edje_real_part_table_unpack(rp, eud->u.table.child);
1070                 break;
1071              }
1072            case EDJE_USER_SWALLOW:
1073               edje_object_part_unswallow(NULL, eud->u.swallow.child);
1074               break;
1075            case EDJE_USER_DRAG_STEP:
1076            case EDJE_USER_DRAG_PAGE:
1077            case EDJE_USER_DRAG_VALUE:
1078            case EDJE_USER_DRAG_SIZE:
1079               break;
1080           }
1081      }
1082
1083    return collect;
1084 }
1085
1086 void
1087 _edje_file_del(Edje *ed)
1088 {
1089    Edje_User_Defined *eud;
1090    Evas *tev = NULL;
1091    
1092    if (ed->obj) tev = evas_object_evas_get(ed->obj);
1093
1094    ed->groups = eina_list_free(ed->groups);
1095
1096    if (tev) evas_event_freeze(tev);
1097    if (ed->freeze_calc)
1098      {
1099         _edje_freeze_calc_list = eina_list_remove(_edje_freeze_calc_list, ed);
1100         ed->freeze_calc = 0;
1101         _edje_freeze_calc_count--;
1102      }
1103    _edje_entry_shutdown(ed);
1104    _edje_message_del(ed);
1105    _edje_block_violate(ed);
1106    _edje_var_shutdown(ed);
1107    _edje_programs_patterns_clean(ed);
1108 //   if (ed->collection)
1109 //     {
1110 //        if (ed->collection->script) _edje_embryo_script_shutdown(ed);
1111 //     }
1112
1113    if (!((ed->file) && (ed->collection)))
1114      {
1115         if (tev)
1116           {
1117              evas_event_thaw(tev);
1118              evas_event_thaw_eval(tev);
1119           }
1120         return;
1121      }
1122
1123    while (ed->user_defined)
1124      {
1125         eud = eina_list_data_get(ed->user_defined);
1126         _edje_user_definition_free(eud);
1127      }
1128
1129    if (ed->table_parts)
1130      {
1131         unsigned int i;
1132         for (i = 0; i < ed->table_parts_size; i++)
1133           {
1134              Edje_Real_Part *rp;
1135
1136              rp = ed->table_parts[i];
1137              if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1138                _edje_entry_real_part_shutdown(rp);
1139              if (rp->object)
1140                {
1141                   _edje_callbacks_del(rp->object, ed);
1142                   _edje_callbacks_focus_del(rp->object, ed);
1143                   evas_object_del(rp->object);
1144                }
1145              if (rp->swallowed_object)
1146                {
1147                   /* Objects swallowed by the app do not get deleted,
1148                    but those internally swallowed (GROUP type) do. */
1149                   switch (rp->part->type)
1150                     {
1151                      case EDJE_PART_TYPE_EXTERNAL:
1152                         _edje_external_parsed_params_free(rp->swallowed_object, rp->param1.external_params);
1153                         if (rp->param2)
1154                           _edje_external_parsed_params_free(rp->swallowed_object, rp->param2->external_params);
1155                      case EDJE_PART_TYPE_GROUP:
1156                         evas_object_del(rp->swallowed_object);
1157                      default:
1158                         break;
1159                     }
1160                   _edje_real_part_swallow_clear(rp);
1161                   rp->swallowed_object = NULL;
1162                }
1163              if (rp->items)
1164                {
1165                   /* evas_box/table handles deletion of objects */
1166                   rp->items = eina_list_free(rp->items);
1167                }
1168              if (rp->anim)
1169                {
1170                   _edje_box_layout_free_data(rp->anim);
1171                   rp->anim = NULL;
1172                }
1173              if (rp->text.text) eina_stringshare_del(rp->text.text);
1174              if (rp->text.font) eina_stringshare_del(rp->text.font);
1175              if (rp->text.cache.in_str) eina_stringshare_del(rp->text.cache.in_str);
1176              if (rp->text.cache.out_str) eina_stringshare_del(rp->text.cache.out_str);
1177
1178              if (rp->custom)
1179                {
1180                   // xxx: lua2
1181                   _edje_collection_free_part_description_clean(rp->part->type,
1182                                                                rp->custom->description,
1183                                                                ed->file->free_strings);
1184                   free(rp->custom->description);
1185                   rp->custom->description = NULL;
1186                }
1187
1188              /* Cleanup optional part. */
1189              free(rp->drag);
1190              free(rp->param1.set);
1191
1192              if (rp->param2)
1193                free(rp->param2->set);
1194              eina_mempool_free(_edje_real_part_state_mp, rp->param2);
1195
1196              if (rp->custom)
1197                free(rp->custom->set);
1198              eina_mempool_free(_edje_real_part_state_mp, rp->custom);
1199
1200              _edje_unref(rp->edje);
1201              eina_mempool_free(_edje_real_part_mp, rp);
1202           }
1203      }
1204    if ((ed->file) && (ed->collection))
1205      {
1206         Edje_Part *ep;
1207         unsigned int i;
1208
1209         _edje_textblock_styles_del(ed);
1210         for (i = 0; i < ed->collection->parts_count; ++i)
1211           {
1212              ep = ed->collection->parts[i];
1213
1214              _edje_text_part_on_del(ed, ep);
1215              _edje_color_class_on_del(ed, ep);
1216           }
1217
1218         _edje_cache_coll_unref(ed->file, ed->collection);
1219         ed->collection = NULL;
1220      }
1221    if (ed->file)
1222      {
1223 #ifdef HAVE_EIO
1224         ed->file->edjes = eina_list_remove(ed->file->edjes, ed);
1225 #endif
1226         _edje_cache_file_unref(ed->file);
1227         ed->file = NULL;
1228      }
1229    if (ed->actions)
1230      {
1231         Edje_Running_Program *runp;
1232
1233         EINA_LIST_FREE(ed->actions, runp)
1234           {
1235              _edje_anim_count--;
1236              free(runp);
1237           }
1238      }
1239    _edje_animators = eina_list_remove(_edje_animators, ed);
1240    if (ed->pending_actions)
1241      {
1242         Edje_Pending_Program *pp;
1243
1244         EINA_LIST_FREE(ed->pending_actions, pp)
1245           {
1246              ecore_timer_del(pp->timer);
1247              free(pp);
1248           }
1249      }
1250
1251    if (ed->L) _edje_lua2_script_shutdown(ed);
1252    while (ed->subobjs) _edje_subobj_unregister(ed, ed->subobjs->data);
1253    if (ed->table_parts) free(ed->table_parts);
1254    ed->table_parts = NULL;
1255    ed->table_parts_size = 0;
1256    if (ed->table_programs) free(ed->table_programs);
1257    ed->table_programs = NULL;
1258    ed->table_programs_size = 0;
1259    ed->focused_part = NULL;
1260    if (tev)
1261      {
1262         evas_event_thaw(tev);
1263         evas_event_thaw_eval(tev);
1264      }
1265 }
1266
1267 void
1268 _edje_file_free(Edje_File *edf)
1269 {
1270    Edje_Color_Class *ecc;
1271 #ifdef HAVE_EIO
1272    Ecore_Event_Handler *event;
1273 #endif
1274
1275 #define HASH_FREE(Hash)                         \
1276    if (Hash) eina_hash_free(Hash);              \
1277    Hash = NULL;
1278
1279    /* Clean cache before cleaning memory pool */
1280    if (edf->collection_cache) _edje_cache_coll_flush(edf);
1281
1282    HASH_FREE(edf->fonts);
1283    HASH_FREE(edf->collection);
1284    HASH_FREE(edf->data);
1285
1286    if (edf->image_dir)
1287      {
1288         unsigned int i;
1289
1290         if (edf->free_strings)
1291           {
1292              for (i = 0; i < edf->image_dir->entries_count; ++i)
1293                eina_stringshare_del(edf->image_dir->entries[i].entry);
1294           }
1295
1296         /* Sets have been added after edje received eet dictionnary support */
1297         for (i = 0; i < edf->image_dir->sets_count; ++i)
1298           {
1299              Edje_Image_Directory_Set_Entry *se;
1300
1301              EINA_LIST_FREE(edf->image_dir->sets[i].entries, se)
1302                free(se);
1303
1304           }
1305
1306         free(edf->image_dir->entries);
1307         free(edf->image_dir->sets);
1308         free(edf->image_dir);
1309      }
1310    if (edf->sound_dir)
1311      {
1312         unsigned int i;
1313
1314         if (edf->free_strings)
1315           {
1316              for (i = 0; i < edf->sound_dir->samples_count; ++i)
1317                {
1318                   eina_stringshare_del(edf->sound_dir->samples[i].name);
1319                   eina_stringshare_del(edf->sound_dir->samples[i].snd_src);
1320                }
1321
1322              for (i = 0; i < edf->sound_dir->tones_count; ++i)
1323                eina_stringshare_del(edf->sound_dir->tones[i].name);
1324           }
1325         free(edf->sound_dir->samples);
1326         free(edf->sound_dir->tones);
1327         free(edf->sound_dir);
1328      }
1329
1330    if (edf->external_dir)
1331      {
1332         if (edf->external_dir->entries) free(edf->external_dir->entries);
1333         free(edf->external_dir);
1334      }
1335
1336    eina_hash_free(edf->color_hash);
1337    EINA_LIST_FREE(edf->color_classes, ecc)
1338      {
1339         if (edf->free_strings && ecc->name) eina_stringshare_del(ecc->name);
1340         free(ecc);
1341      }
1342
1343    if (edf->collection_patterns) edje_match_patterns_free(edf->collection_patterns);
1344 #ifdef HAVE_EIO
1345    if (edf->timeout) ecore_timer_del(edf->timeout);
1346    EINA_LIST_FREE(edf->handlers, event)
1347      ecore_event_handler_del(event);
1348    eio_monitor_del(edf->monitor);
1349 #endif
1350    if (edf->path) eina_stringshare_del(edf->path);
1351    if (edf->free_strings && edf->compiler) eina_stringshare_del(edf->compiler);
1352    _edje_textblock_style_cleanup(edf);
1353    if (edf->ef) eet_close(edf->ef);
1354    free(edf);
1355 }
1356
1357 static void
1358 _edje_program_free(Edje_Program *pr, Eina_Bool free_strings)
1359 {
1360    Edje_Program_Target *prt;
1361    Edje_Program_After *pa;
1362
1363    if (free_strings)
1364      {
1365         if (pr->name) eina_stringshare_del(pr->name);
1366         if (pr->signal) eina_stringshare_del(pr->signal);
1367         if (pr->source) eina_stringshare_del(pr->source);
1368         if (pr->filter.part) eina_stringshare_del(pr->filter.part);
1369         if (pr->filter.state) eina_stringshare_del(pr->filter.state);
1370         if (pr->state) eina_stringshare_del(pr->state);
1371         if (pr->state2) eina_stringshare_del(pr->state2);
1372    if (pr->sample_name) eina_stringshare_del(pr->sample_name);
1373    if (pr->tone_name) eina_stringshare_del(pr->tone_name);
1374      }
1375    EINA_LIST_FREE(pr->targets, prt)
1376      free(prt);
1377    EINA_LIST_FREE(pr->after, pa)
1378      free(pa);
1379    free(pr);
1380 }
1381
1382 void
1383 _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collection_Directory_Entry *ce)
1384 {
1385    unsigned int i;
1386
1387    _edje_embryo_script_shutdown(ec);
1388
1389 #define EDJE_LOAD_PROGRAM_FREE(Array, Ec, It, FreeStrings)      \
1390    for (It = 0; It < Ec->programs.Array##_count; ++It)          \
1391      _edje_program_free(Ec->programs.Array[It], FreeStrings);   \
1392    free(Ec->programs.Array);
1393
1394    EDJE_LOAD_PROGRAM_FREE(fnmatch, ec, i, edf->free_strings);
1395    EDJE_LOAD_PROGRAM_FREE(strcmp, ec, i, edf->free_strings);
1396    EDJE_LOAD_PROGRAM_FREE(strncmp, ec, i, edf->free_strings);
1397    EDJE_LOAD_PROGRAM_FREE(strrncmp, ec, i, edf->free_strings);
1398    EDJE_LOAD_PROGRAM_FREE(nocmp, ec, i, edf->free_strings);
1399
1400    for (i = 0; i < ec->parts_count; ++i)
1401      {
1402         Edje_Part *ep;
1403         unsigned int j;
1404
1405         ep = ec->parts[i];
1406
1407         if (edf->free_strings && ep->name) eina_stringshare_del(ep->name);
1408         if (ep->default_desc)
1409           {
1410              _edje_collection_free_part_description_clean(ep->type, ep->default_desc, edf->free_strings);
1411              ep->default_desc = NULL;
1412           }
1413         for (j = 0; j < ep->other.desc_count; ++j)
1414           _edje_collection_free_part_description_clean(ep->type, ep->other.desc[j], edf->free_strings);
1415
1416         free(ep->other.desc);
1417         /* Alloc for RTL objects in edje_calc.c:_edje_part_description_find() */
1418         if(ep->other.desc_rtl)
1419           free(ep->other.desc_rtl);
1420
1421         free(ep->items);
1422 // technically need this - but we ASSUME we use "one_big" so everything gets
1423 // freed in one go lower down when we del the mempool... but what if pool goes
1424 // "over"?
1425         eina_mempool_free(ce->mp.part, ep);
1426      }
1427    free(ec->parts);
1428    ec->parts = NULL;
1429
1430    if (ec->data)
1431      {
1432         Eina_Iterator *it;
1433         Edje_String *es;
1434
1435         it = eina_hash_iterator_data_new(ec->data);
1436         EINA_ITERATOR_FOREACH(it, es)
1437           free(es);
1438         eina_iterator_free(it);
1439
1440         eina_hash_free(ec->data);
1441      }
1442 #ifdef EDJE_PROGRAM_CACHE
1443    if (ec->prog_cache.no_matches) eina_hash_free(ec->prog_cache.no_matches);
1444    if (ec->prog_cache.matches)
1445      {
1446         eina_hash_foreach(ec->prog_cache.matches,
1447                           _edje_collection_free_prog_cache_matches_free_cb,
1448                           NULL);
1449         eina_hash_free(ec->prog_cache.matches);
1450      }
1451 #endif
1452    if (ec->script) embryo_program_free(ec->script);
1453    _edje_lua2_script_unload(ec);
1454
1455    eina_hash_free(ec->alias);
1456    eina_hash_free(ec->aliased);
1457
1458    /* Destroy all part and description. */
1459    eina_mempool_del(ce->mp.RECTANGLE);
1460    eina_mempool_del(ce->mp.TEXT);
1461    eina_mempool_del(ce->mp.IMAGE);
1462    eina_mempool_del(ce->mp.PROXY);
1463    eina_mempool_del(ce->mp.SWALLOW);
1464    eina_mempool_del(ce->mp.TEXTBLOCK);
1465    eina_mempool_del(ce->mp.GROUP);
1466    eina_mempool_del(ce->mp.BOX);
1467    eina_mempool_del(ce->mp.TABLE);
1468    eina_mempool_del(ce->mp.EXTERNAL);
1469    eina_mempool_del(ce->mp.SPACER);
1470    eina_mempool_del(ce->mp.part);
1471    memset(&ce->mp, 0, sizeof (ce->mp));
1472
1473    eina_mempool_del(ce->mp_rtl.RECTANGLE);
1474    eina_mempool_del(ce->mp_rtl.TEXT);
1475    eina_mempool_del(ce->mp_rtl.IMAGE);
1476    eina_mempool_del(ce->mp_rtl.PROXY);
1477    eina_mempool_del(ce->mp_rtl.SWALLOW);
1478    eina_mempool_del(ce->mp_rtl.TEXTBLOCK);
1479    eina_mempool_del(ce->mp_rtl.GROUP);
1480    eina_mempool_del(ce->mp_rtl.BOX);
1481    eina_mempool_del(ce->mp_rtl.TABLE);
1482    eina_mempool_del(ce->mp_rtl.EXTERNAL);
1483    eina_mempool_del(ce->mp_rtl.SPACER);
1484    memset(&ce->mp_rtl, 0, sizeof (ce->mp_rtl));
1485    free(ec);
1486    ce->ref = NULL;
1487 }
1488
1489 void
1490 _edje_collection_free_part_description_clean(int type, Edje_Part_Description_Common *desc, Eina_Bool free_strings)
1491 {
1492    if (free_strings && desc->color_class) eina_stringshare_del(desc->color_class);
1493
1494    switch (type)
1495      {
1496       case EDJE_PART_TYPE_IMAGE:
1497         {
1498            Edje_Part_Description_Image *img;
1499            unsigned int i;
1500
1501            img = (Edje_Part_Description_Image *) desc;
1502
1503            for (i = 0; i < img->image.tweens_count; ++i)
1504              free(img->image.tweens[i]);
1505            free(img->image.tweens);
1506            break;
1507         }
1508       case EDJE_PART_TYPE_EXTERNAL:
1509         {
1510            Edje_Part_Description_External *external;
1511
1512            external = (Edje_Part_Description_External *) desc;
1513
1514            if (external->external_params)
1515              _edje_external_params_free(external->external_params, free_strings);
1516            break;
1517         }
1518       case EDJE_PART_TYPE_TEXT:
1519       case EDJE_PART_TYPE_TEXTBLOCK:
1520          if (free_strings)
1521            {
1522               Edje_Part_Description_Text *text;
1523
1524               text = (Edje_Part_Description_Text *) desc;
1525
1526               if (text->text.text.str)      eina_stringshare_del(text->text.text.str);
1527               if (text->text.text_class)    eina_stringshare_del(text->text.text_class);
1528               if (text->text.style.str)     eina_stringshare_del(text->text.style.str);
1529               if (text->text.font.str)      eina_stringshare_del(text->text.font.str);
1530            }
1531          break;
1532      }
1533 }
1534
1535 void
1536 _edje_collection_free_part_description_free(int type,
1537                                             Edje_Part_Description_Common *desc,
1538                                             Edje_Part_Collection_Directory_Entry *ce,
1539                                             Eina_Bool free_strings)
1540 {
1541 #define FREE_POOL(Type, Ce, Desc)                                       \
1542    case EDJE_PART_TYPE_##Type: eina_mempool_free(Ce->mp.Type, Desc);    \
1543                                ce->count.Type--;                        \
1544                                break;
1545
1546    _edje_collection_free_part_description_clean(type, desc, free_strings);
1547
1548    switch (type)
1549      {
1550         FREE_POOL(RECTANGLE, ce, desc);
1551         FREE_POOL(TEXT, ce, desc);
1552         FREE_POOL(IMAGE, ce, desc);
1553         FREE_POOL(PROXY, ce, desc);
1554         FREE_POOL(SWALLOW, ce, desc);
1555         FREE_POOL(TEXTBLOCK, ce, desc);
1556         FREE_POOL(GROUP, ce, desc);
1557         FREE_POOL(BOX, ce, desc);
1558         FREE_POOL(TABLE, ce, desc);
1559         FREE_POOL(EXTERNAL, ce, desc);
1560      }
1561 }
1562
1563 #ifdef EDJE_PROGRAM_CACHE
1564 static Eina_Bool
1565 _edje_collection_free_prog_cache_matches_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
1566 {
1567    eina_list_free((Eina_List *)data);
1568    return EINA_TRUE;
1569    key = NULL;
1570    hash = NULL;
1571    fdata = NULL;
1572 }
1573 #endif
1574
1575 static void
1576 _edje_object_pack_item_hints_set(Evas_Object *obj, Edje_Pack_Element *it)
1577 {
1578    Evas_Coord w = 0, h = 0, minw, minh;
1579
1580    minw = it->min.w;
1581    minh = it->min.h;
1582
1583    if ((minw <= 0) && (minh <= 0))
1584      {
1585         edje_object_size_min_get(obj, &w, &h);
1586         if ((w <= 0) && (h <= 0))
1587           edje_object_size_min_calc(obj, &w, &h);
1588      }
1589    else
1590      {
1591         w = minw;
1592         h = minh;
1593      }
1594    if (((minw <= 0) && (minh <= 0)) && ((w > 0) || (h > 0)))
1595      evas_object_size_hint_min_set(obj, w, h);
1596    else
1597      evas_object_size_hint_min_set(obj, minw, minh);
1598
1599    evas_object_size_hint_request_set(obj, it->prefer.w, it->prefer.h);
1600    evas_object_size_hint_max_set(obj, it->max.w, it->max.h);
1601    evas_object_size_hint_padding_set(obj, it->padding.l, it->padding.r, it->padding.t, it->padding.b);
1602    evas_object_size_hint_align_set(obj, TO_DOUBLE(it->align.x), TO_DOUBLE(it->align.y));
1603    evas_object_size_hint_weight_set(obj, TO_DOUBLE(it->weight.x), TO_DOUBLE(it->weight.y));
1604    evas_object_size_hint_aspect_set(obj, it->aspect.mode, it->aspect.w, it->aspect.h);
1605
1606    evas_object_resize(obj, w, h);
1607 }
1608
1609 static const char *
1610 _edje_find_alias(Eina_Hash *aliased, char *src, int *length)
1611 {
1612    const char *alias;
1613    char *search;
1614
1615    *length = strlen(src);
1616    if (*length == 0) return NULL;
1617
1618    alias = eina_hash_find(aliased, src);
1619    if (alias) return alias;
1620
1621    search = strrchr(src, EDJE_PART_PATH_SEPARATOR);
1622    if (search == NULL) return NULL;
1623
1624    *search = '\0';
1625    alias = _edje_find_alias(aliased, src, length);
1626    *search = EDJE_PART_PATH_SEPARATOR;
1627
1628    return alias;
1629 }
1630
1631 static void
1632 _cb_signal_repeat(void *data, Evas_Object *obj, const char *sig, const char *source)
1633 {
1634    Edje_Pack_Element *pack_it;
1635    Evas_Object  *parent;
1636    Edje         *ed;
1637    Edje         *ed_parent;
1638    char          new_src[4096]; /* XXX is this max reasonable? */
1639    size_t        length_parent = 0;
1640    size_t        length_index = 0;
1641    size_t        length_source;
1642    int           i = 0;
1643    const char   *alias = NULL;
1644    Edje_Message_Signal emsg;
1645
1646    parent = data;
1647    ed = _edje_fetch(obj);
1648    if (!ed) return;
1649
1650    pack_it = evas_object_data_get(obj, "\377 edje.box_item");
1651    if (!pack_it) pack_it = evas_object_data_get(obj, "\377 edje.table_item");
1652    if (pack_it)
1653      {
1654         if (!pack_it->name)
1655           {
1656              Eina_List *child = NULL;
1657              Evas_Object *o;
1658
1659              if (pack_it->parent->part->type == EDJE_PART_TYPE_BOX)
1660                {
1661                   child = evas_object_box_children_get(pack_it->parent->object);
1662                }
1663              else if (pack_it->parent->part->type == EDJE_PART_TYPE_TABLE)
1664                {
1665                   child = evas_object_table_children_get(pack_it->parent->object);
1666                }
1667
1668              EINA_LIST_FREE(child, o)
1669                {
1670                   if (o == obj) break;
1671                   i++;
1672                }
1673
1674              eina_list_free(child);
1675
1676              length_index = 12;
1677           }
1678         else
1679           {
1680              length_index = strlen(pack_it->name) + 2;
1681           }
1682      }
1683
1684    /* Replace snprint("%s%c%s") == memcpy + *new_src + memcat */
1685    if (ed->parent)
1686      length_parent = strlen(ed->parent);
1687    length_source = strlen(source);
1688    if (length_source + length_parent + 2 + length_index > sizeof(new_src))
1689      return;
1690
1691    if (ed->parent)
1692      memcpy(new_src, ed->parent, length_parent);
1693    if (ed->parent && length_index)
1694      {
1695         new_src[length_parent++] = EDJE_PART_PATH_SEPARATOR_INDEXL;
1696         if (length_index == 12)
1697           length_parent += eina_convert_itoa(i, new_src + length_parent);
1698         else
1699           {
1700              memcpy(new_src + length_parent, pack_it->name, length_index);
1701              length_parent += length_index - 2;
1702           }
1703         new_src[length_parent++] = EDJE_PART_PATH_SEPARATOR_INDEXR;
1704      }
1705
1706    new_src[length_parent] = EDJE_PART_PATH_SEPARATOR;
1707    memcpy(new_src + length_parent + 1, source, length_source + 1);
1708
1709    /* Handle alias renaming */
1710    ed_parent = _edje_fetch(parent);
1711    if (ed_parent && ed_parent->collection && ed_parent->collection->aliased)
1712      {
1713         int length;
1714
1715         alias = _edje_find_alias(ed_parent->collection->aliased, new_src, &length);
1716
1717         if (alias)
1718           {
1719              int origin;
1720
1721              /* Add back the end of the source */
1722              origin = strlen(new_src);
1723              length ++; /* Remove the trailing ':' from the count */
1724              if (origin > length)
1725                {
1726                   char *tmp;
1727                   size_t alias_length;
1728
1729                   alias_length = strlen(alias);
1730                   tmp = alloca(alias_length + origin - length + 2);
1731                   memcpy(tmp, alias, alias_length);
1732                   tmp[alias_length] = EDJE_PART_PATH_SEPARATOR;
1733                   memcpy(tmp + alias_length + 1, new_src + length, origin - length + 1);
1734
1735                   alias = tmp;
1736                }
1737           }
1738      }
1739    
1740    emsg.sig = sig;
1741    emsg.src = alias ? alias : new_src;
1742    emsg.data = NULL;
1743    if (ed_parent)
1744      _edje_message_send(ed_parent, EDJE_QUEUE_SCRIPT, 
1745                         EDJE_MESSAGE_SIGNAL, 0, &emsg);
1746 }