efl

Форк
0
/
edje_load.c 
2730 строк · 92.1 Кб
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
   {
21
      FLOAT_T x, y;
22
   } step;
23
   struct
24
   {
25
      FLOAT_T x, y;
26
   } page;
27
};
28

29
void _edje_file_add(Edje *ed, const Eina_File *f);
30

31
/* START - Nested part support */
32
#define _edje_smart_nested_type "Evas_Smart_Nested"
33
typedef struct _Edje_Nested_Support Edje_Nested_Support;
34
struct _Edje_Nested_Support /* We builed nested-parts list using this struct */
35
{
36
   Evas_Object  *o; /* Smart object containing nested children */
37
   unsigned char nested_children_count; /* Number of nested children */
38
};
39

40
Evas_Smart *
41
_edje_smart_nested_smart_class_new(void)
42
{
43
   static Evas_Smart_Class _sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("EdjeNested");
44
   static const Evas_Smart_Class *class = NULL;
45
   static Evas_Smart *smart;
46

47
   if (smart)
48
     return smart;
49

50
   class = &_sc;
51
   smart = evas_smart_class_new(class);
52
   return smart;
53
}
54

55
Evas_Object *
56
edje_smart_nested_add(Evas *evas)
57
{
58
   return evas_object_smart_add(evas, _edje_smart_nested_smart_class_new());
59
}
60

61
/* END   - Nested part support */
62

63
#ifdef EDJE_PROGRAM_CACHE
64
static Eina_Bool  _edje_collection_free_prog_cache_matches_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata);
65
#endif
66
static void       _edje_object_pack_item_hints_set(Evas_Object *obj, Edje_Pack_Element *it);
67
static void       _cb_signal_repeat(void *data, Evas_Object *obj, const char *signal, const char *source);
68

69
static Eina_Hash *_edje_object_collect(Edje *ed);
70

71
static int        _sort_defined_boxes(const void *a, const void *b);
72

73
/************************** API Routines **************************/
74

75
EOLIAN const char *
76
_efl_canvas_layout_efl_file_file_get(Eo *obj EINA_UNUSED, Edje *ed)
77
{
78
   return ed->path;
79
}
80

81
EOLIAN const char *
82
_efl_canvas_layout_efl_file_group_get(Eo *obj EINA_UNUSED, Edje *ed)
83
{
84
   return ed->group;
85
}
86

87
EOLIAN Eina_Error
88
_efl_canvas_layout_layout_load_error_get(const Eo *obj EINA_UNUSED, Edje *ed)
89
{
90
   switch (ed->load_error)
91
     {
92
      case EDJE_LOAD_ERROR_NONE: return EFL_GFX_IMAGE_LOAD_ERROR_NONE;
93
      case EDJE_LOAD_ERROR_GENERIC: return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
94
      case EDJE_LOAD_ERROR_DOES_NOT_EXIST: return EFL_GFX_IMAGE_LOAD_ERROR_DOES_NOT_EXIST;
95
      case EDJE_LOAD_ERROR_PERMISSION_DENIED: return EFL_GFX_IMAGE_LOAD_ERROR_PERMISSION_DENIED;
96
      case EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED: return EFL_GFX_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
97
      case EDJE_LOAD_ERROR_CORRUPT_FILE: return EFL_GFX_IMAGE_LOAD_ERROR_CORRUPT_FILE;
98
      case EDJE_LOAD_ERROR_UNKNOWN_FORMAT: return EFL_GFX_IMAGE_LOAD_ERROR_UNKNOWN_FORMAT;
99
      case EDJE_LOAD_ERROR_INCOMPATIBLE_FILE: return EFL_GFX_IMAGE_LOAD_ERROR_INCOMPATIBLE_FILE;
100
      case EDJE_LOAD_ERROR_UNKNOWN_COLLECTION: return EFL_GFX_IMAGE_LOAD_ERROR_UNKNOWN_COLLECTION;
101
      case EDJE_LOAD_ERROR_RECURSIVE_REFERENCE: return EFL_GFX_IMAGE_LOAD_ERROR_RECURSIVE_REFERENCE;
102
      default: break;
103
     }
104
   return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
105
}
106

107
EAPI const char *
108
edje_load_error_str(Edje_Load_Error error)
109
{
110
   switch (error)
111
     {
112
      case EDJE_LOAD_ERROR_NONE:
113
        return "No Error";
114

115
      case EDJE_LOAD_ERROR_GENERIC:
116
        return "Generic Error";
117

118
      case EDJE_LOAD_ERROR_DOES_NOT_EXIST:
119
        return "File Does Not Exist";
120

121
      case EDJE_LOAD_ERROR_PERMISSION_DENIED:
122
        return "Permission Denied";
123

124
      case EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED:
125
        return "Resource Allocation Failed";
126

127
      case EDJE_LOAD_ERROR_CORRUPT_FILE:
128
        return "Corrupt File";
129

130
      case EDJE_LOAD_ERROR_UNKNOWN_FORMAT:
131
        return "Unknown Format";
132

133
      case EDJE_LOAD_ERROR_INCOMPATIBLE_FILE:
134
        return "Incompatible File";
135

136
      case EDJE_LOAD_ERROR_UNKNOWN_COLLECTION:
137
        return "Unknown Collection";
138

139
      case EDJE_LOAD_ERROR_RECURSIVE_REFERENCE:
140
        return "Recursive Reference";
141

142
      default:
143
        return "Unknown Error";
144
     }
145
}
146

147
EAPI Eina_List *
148
edje_mmap_collection_list(Eina_File *f)
149
{
150
   Eina_List *lst = NULL;
151
   Edje_File *edf;
152
   int error_ret = 0;
153

154
   if (!f) return NULL;
155
   edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
156
   if (edf)
157
     {
158
        Eina_Iterator *i;
159
        const char *key;
160

161
        i = eina_hash_iterator_key_new(edf->collection);
162

163
        EINA_ITERATOR_FOREACH(i, key)
164
          lst = eina_list_append(lst, eina_stringshare_add(key));
165

166
        eina_iterator_free(i);
167

168
        _edje_cache_file_unref(edf);
169
     }
170

171
   return lst;
172
}
173

174
EAPI Eina_List *
175
edje_file_collection_list(const char *file)
176
{
177
   Eina_File *f;
178
   Eina_List *lst = NULL;
179
   char *tmp;
180

181
   if ((!file) || (!*file)) return NULL;
182
   tmp = eina_vpath_resolve(file);
183
   f = eina_file_open(tmp, EINA_FALSE);
184
   if (!f) goto err;
185

186
   lst = edje_mmap_collection_list(f);
187

188
   eina_file_close(f); // close matching open OK
189
err:
190
   free(tmp);
191
   return lst;
192
}
193

194
EAPI void
195
edje_file_collection_list_free(Eina_List *lst)
196
{
197
   while (lst)
198
     {
199
        if (eina_list_data_get(lst)) eina_stringshare_del(eina_list_data_get(lst));
200
        lst = eina_list_remove(lst, eina_list_data_get(lst));
201
     }
202
}
203

204
EAPI void
205
edje_mmap_collection_list_free(Eina_List *lst)
206
{
207
   edje_file_collection_list_free(lst);
208
}
209

210
EAPI Eina_List *
211
edje_mmap_color_class_used_list(Eina_File *f)
212
{
213
   Eina_List *lst = NULL, *l;
214
   Edje_File *edf;
215
   int error_ret = 0;
216
   const char *s;
217

218
   if (!f) return NULL;
219
   edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
220
   if (edf)
221
     {
222
        Edje_Color_Class_Info *cc_info;
223

224
        cc_info = eet_data_read(edf->ef, _edje_edd_edje_color_class_info,
225
                                "edje/color_class_info");
226
        if (cc_info)
227
          {
228
             EINA_LIST_FOREACH(cc_info->colors, l, s)
229
               lst = eina_list_append(lst, eina_stringshare_add(s));
230
             eina_list_free(cc_info->colors);
231
             free(cc_info);
232
          }
233
        _edje_cache_file_unref(edf);
234
     }
235

236
   return lst;
237
}
238

239
EAPI Eina_List *
240
edje_file_color_class_used_list(const char *file)
241
{
242
   Eina_File *f;
243
   Eina_List *lst = NULL;
244
   char *tmp;
245

246
   if ((!file) || (!*file)) return NULL;
247
   tmp = eina_vpath_resolve(file);
248
   f = eina_file_open(tmp, EINA_FALSE);
249
   if (!f) goto err;
250

251
   lst = edje_mmap_collection_list(f);
252

253
   eina_file_close(f); // close matching open OK
254
err:
255
   free(tmp);
256
   return lst;
257
}
258

259
EAPI void
260
edje_file_color_class_used_free(Eina_List *lst)
261
{
262
   eina_list_free(lst);
263
}
264

265

266
EAPI Eina_Bool
267
edje_mmap_group_exists(Eina_File *f, const char *glob)
268
{
269
   Edje_File *edf;
270
   int error_ret = 0;
271
   Eina_Bool succeed = EINA_FALSE;
272
   Eina_Bool is_glob = EINA_FALSE;
273
   const char *p;
274

275
   if ((!f) || (!glob))
276
     return EINA_FALSE;
277

278
   edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
279
   if (!edf) return EINA_FALSE;
280

281
   for (p = glob; *p; p++)
282
     {
283
        if ((*p == '*') || (*p == '?') || (*p == '['))
284
          {
285
             is_glob = EINA_TRUE;
286
             break;
287
          }
288
     }
289

290
   if (is_glob)
291
     {
292
        if (!edf->collection_patterns)
293
          {
294
             Edje_Part_Collection_Directory_Entry *ce;
295
             Eina_Iterator *i;
296
             Eina_List *l = NULL;
297

298
             i = eina_hash_iterator_data_new(edf->collection);
299

300
             EINA_ITERATOR_FOREACH(i, ce)
301
               l = eina_list_append(l, ce);
302

303
             eina_iterator_free(i);
304

305
             edf->collection_patterns = edje_match_collection_dir_init(l);
306
             eina_list_free(l);
307
          }
308

309
        succeed = edje_match_collection_dir_exec(edf->collection_patterns, glob);
310
        if (edf->collection_patterns)
311
          {
312
             edje_match_patterns_free(edf->collection_patterns);
313
             edf->collection_patterns = NULL;
314
          }
315
     }
316
   else
317
     {
318
        if (eina_hash_find(edf->collection, glob)) succeed = EINA_TRUE;
319
     }
320
   _edje_cache_file_unref(edf);
321

322
   DBG("edje_file_group_exists: '%s', '%s': %i.", eina_file_filename_get(f), glob, succeed);
323

324
   return succeed;
325
}
326

327
EAPI Eina_Bool
328
edje_mmap_3d_has(Eina_File *f EINA_UNUSED, const char *group EINA_UNUSED)
329
{
330
   return EINA_FALSE;
331
}
332

333
typedef struct _Edje_File_Iterator Edje_File_Iterator;
334
struct _Edje_File_Iterator
335
{
336
   Eina_Iterator  iterator;
337

338
   Eina_Iterator *it;
339
};
340

341
static Eina_Bool
342
_edje_file_iterator_next(Eina_Iterator *it, void **data)
343
{
344
   Edje_File_Iterator *et = (void *)it;
345
   Edje_File *edf = NULL;
346

347
   if (!eina_iterator_next(et->it, (void **)&edf))
348
     return EINA_FALSE;
349

350
   *data = edf->f;
351
   return EINA_TRUE;
352
}
353

354
static void *
355
_edje_file_iterator_container(Eina_Iterator *it EINA_UNUSED)
356
{
357
   return NULL;
358
}
359

360
static void
361
_edje_file_iterator_free(Eina_Iterator *it)
362
{
363
   Edje_File_Iterator *et = (void *)it;
364

365
   EINA_MAGIC_SET(&et->iterator, 0);
366
   eina_iterator_free(et->it);
367
   free(et);
368
}
369

370
EAPI Eina_Iterator *
371
edje_file_iterator_new(void)
372
{
373
   Edje_File_Iterator *it;
374

375
   it = calloc(1, sizeof (Edje_File_Iterator));
376
   if (!it) return NULL;
377

378
   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
379
   it->it = eina_hash_iterator_data_new(_edje_file_hash);
380

381
   it->iterator.version = EINA_ITERATOR_VERSION;
382
   it->iterator.next = _edje_file_iterator_next;
383
   it->iterator.get_container = _edje_file_iterator_container;
384
   it->iterator.free = _edje_file_iterator_free;
385

386
   return &it->iterator;
387
}
388

389
EAPI Eina_Bool
390
edje_file_group_exists(const char *file, const char *glob)
391
{
392
   Eina_File *f;
393
   Eina_Bool result = EINA_FALSE;
394
   char *tmp;
395

396
   if ((!file) || (!*file) || (!glob))
397
     return EINA_FALSE;
398

399
   tmp = eina_vpath_resolve(file);
400
   f = eina_file_open(tmp, EINA_FALSE);
401
   if (!f) goto err;
402

403
   result = edje_mmap_group_exists(f, glob);
404

405
   eina_file_close(f); // close matching open OK
406
err:
407
   free(tmp);
408

409
   return result;
410
}
411

412
EAPI char *
413
edje_mmap_data_get(const Eina_File *f, const char *key)
414
{
415
   Edje_File *edf;
416
   char *str = NULL;
417
   int error_ret = 0;
418

419
   if (!key) return NULL;
420

421
   edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
422
   if (edf)
423
     {
424
        str = (char *)edje_string_get(eina_hash_find(edf->data, key));
425

426
        if (str) str = strdup(str);
427

428
        _edje_cache_file_unref(edf);
429
     }
430
   return str;
431
}
432

433
EAPI char *
434
edje_file_data_get(const char *file, const char *key)
435
{
436
   Eina_File *f;
437
   char *str = NULL, *tmp;
438

439
   if (!key) return NULL;
440

441
   tmp = eina_vpath_resolve(file);
442
   f = eina_file_open(tmp, EINA_FALSE);
443
   if (!f)
444
     {
445
        ERR("File [%s] can not be opened.", file);
446
        goto err;
447
     }
448
   str = edje_mmap_data_get(f, key);
449
   eina_file_close(f); // close matching open OK
450
err:
451
   free(tmp);
452

453
   return str;
454
}
455

456
void
457
_edje_programs_patterns_clean(Edje_Part_Collection *edc)
458
{
459
   _edje_signals_sources_patterns_clean(&edc->patterns.programs);
460

461
   eina_rbtree_delete(edc->patterns.programs.exact_match,
462
                      EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
463
                      NULL);
464
   edc->patterns.programs.exact_match = NULL;
465

466
   free(edc->patterns.programs.u.programs.globing);
467
   edc->patterns.programs.u.programs.globing = NULL;
468
}
469

470
void
471
_evas_object_viewport_del(void *data, Evas *_evas EINA_UNUSED, Evas_Object *eo EINA_UNUSED, void   *event_info EINA_UNUSED)
472
{
473
   Eo* viewport = (Eo*) data;
474
   evas_object_del(viewport);
475
}
476

477
#ifdef HAVE_EPHYSICS
478
static void
479
_edje_physics_world_update_cb(void *data, EPhysics_World *world EINA_UNUSED, void *event_info EINA_UNUSED)
480
{
481
   Edje *edje = data;
482
   if (EPH_LOAD()) _edje_recalc_do(edje);
483
}
484
#endif
485

486
Eina_Bool
487
_edje_part_allowed_seat_find(Edje_Real_Part *rp, const char *seat_name)
488
{
489
   const char *name;
490
   unsigned int i;
491

492
   for (i = 0; i < rp->part->allowed_seats_count; i++)
493
     {
494
        name = rp->part->allowed_seats[i]->name;
495
        if (!strcmp(seat_name, name))
496
          return EINA_TRUE;
497
     }
498

499
   return EINA_FALSE;
500
}
501

502
/* It goes throught the list of registered seats and
503
 * set event filters for each of these seats. */
504
static void
505
_edje_part_seat_filter_apply(Edje *ed, Edje_Real_Part *rp)
506
{
507
   Edje_Seat *seat;
508
   Eina_List *l;
509
   Eina_Bool found;
510

511
   EINA_LIST_FOREACH(ed->seats, l, seat)
512
     {
513
        found = _edje_part_allowed_seat_find(rp, seat->name);
514
        efl_input_seat_event_filter_set(rp->object, seat->device, found);
515
     }
516
}
517

518
/* It goes throught the list of all edje parts and
519
 * set event filters for each of these parts. Should be called when
520
 * a new seat is added.
521
 */
522
static void
523
_edje_seat_event_filter_apply(Edje *ed, Edje_Seat *seat)
524
{
525
   Edje_Real_Part *rp;
526
   unsigned short i;
527
   Eina_Bool found;
528

529
   for (i = 0; i < ed->table_parts_size; i++)
530
     {
531
        rp = ed->table_parts[i];
532
        if (!rp->part->allowed_seats)
533
          continue;
534

535
        found = _edje_part_allowed_seat_find(rp, seat->name);
536
        efl_input_seat_event_filter_set(rp->object, seat->device, found);
537
     }
538
}
539

540
static void
541
_edje_device_add(Edje *ed, Efl_Input_Device *dev)
542
{
543
   Edje_Seat *s, *seat = NULL;
544
   Eina_Stringshare *name;
545
   char sig[256];
546
   Eina_List *l;
547

548
   if (ed->collection && ed->collection->use_custom_seat_names)
549
     name = eina_stringshare_add(efl_name_get(dev));
550
   else
551
     {
552
        ed->seats_count++;
553
        name = eina_stringshare_printf("seat%i", ed->seats_count);
554
     }
555
   EINA_SAFETY_ON_NULL_RETURN(name);
556

557
   EINA_LIST_FOREACH(ed->seats, l, s)
558
     {
559
        if (s->name != name)
560
          continue;
561
        seat = s;
562
        break;
563
     }
564

565
   if (!seat)
566
     {
567
        seat = calloc(1, sizeof(Edje_Seat));
568
        EINA_SAFETY_ON_NULL_GOTO(seat, seat_err);
569
        ed->seats = eina_list_append(ed->seats, seat);
570
        seat->name = eina_stringshare_ref(name);
571
     }
572

573
   seat->device = dev;
574
   snprintf(sig, sizeof(sig), "seat,added,%s,%s", seat->name,
575
            efl_name_get(dev));
576
   _edje_emit(ed, sig, "");
577
   _edje_seat_event_filter_apply(ed, seat);
578

579
seat_err:
580
   eina_stringshare_del(name);
581
}
582

583
static void
584
_edje_device_added_cb(void *data, const Efl_Event *event)
585
{
586
   Efl_Input_Device *dev = event->info;
587
   Edje *ed = data;
588

589
   if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_TYPE_SEAT)
590
     return;
591

592
   _edje_device_add(ed, dev);
593
}
594

595
static void
596
_edje_device_removed_cb(void *data, const Efl_Event *event)
597
{
598
   Efl_Input_Device *dev = event->info;
599
   Edje_Seat *s, *seat = NULL;
600
   Edje *ed = data;
601
   char sig[256];
602
   Eina_List *l;
603

604
   if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_TYPE_SEAT)
605
     return;
606

607
   EINA_LIST_FOREACH(ed->seats, l, s)
608
     {
609
        if (s->device != dev)
610
          continue;
611
        seat = s;
612
        break;
613
     }
614

615
   /* It shouldn't happen. New seats are always registered. */
616
   EINA_SAFETY_ON_NULL_RETURN(seat);
617

618
   seat->device = NULL;
619
   snprintf(sig, sizeof(sig), "seat,removed,%s", seat->name);
620
   _edje_emit(ed, sig, "");
621
}
622

623
static void
624
_edje_device_changed_cb(void *data, const Efl_Event *event)
625
{
626
   Efl_Input_Device *dev = event->info;
627
   Edje_Seat *s, *seat = NULL;
628
   Eina_Stringshare *name;
629
   Edje *ed = data;
630
   char sig[256];
631
   Eina_List *l;
632

633
   if (efl_input_device_type_get(dev) != EFL_INPUT_DEVICE_TYPE_SEAT)
634
     return;
635

636
   EINA_LIST_FOREACH(ed->seats, l, s)
637
     {
638
        if (s->device != dev)
639
          continue;
640
        seat = s;
641
        break;
642
     }
643

644
   /* not registered seat */
645
   if (!seat)
646
     return;
647

648
   name = efl_name_get(dev);
649
   if (!name)
650
     return;
651

652
   /* no name changes */
653
   if (eina_streq(seat->name, name))
654
     return;
655

656
   /* check if device name was changed to match name used on EDC */
657
   EINA_LIST_FOREACH(ed->seats, l, s)
658
     {
659
        if (eina_streq(s->name, name))
660
          {
661
             if (s->device == dev)
662
               continue;
663
             if (s->device)
664
               {
665
                  WRN("Two seats were detected with the same name: %s.\n"
666
                      "Fix it or focus will misbehave", name);
667
                  break;
668
               }
669

670
             /* merge seats */
671
             s->device = dev;
672
             if (seat->focused_part)
673
               s->focused_part = seat->focused_part;
674

675
             ed->seats = eina_list_remove(ed->seats, seat);
676
             eina_stringshare_del(seat->name);
677
             free(seat);
678

679
             _edje_seat_event_filter_apply(ed, s);
680

681
             return;
682
          }
683
     }
684

685
   snprintf(sig, sizeof(sig), "seat,renamed,%s,%s", seat->name, name);
686
   eina_stringshare_replace(&seat->name, name);
687
   _edje_emit(ed, sig, "");
688
   _edje_seat_event_filter_apply(ed, seat);
689
}
690

691
static void _edje_device_canvas_del(void *data, const Efl_Event *event);
692

693
EFL_CALLBACKS_ARRAY_DEFINE(edje_device_callbacks,
694
                           { EFL_CANVAS_SCENE_EVENT_DEVICE_ADDED, _edje_device_added_cb },
695
                           { EFL_CANVAS_SCENE_EVENT_DEVICE_REMOVED, _edje_device_removed_cb },
696
                           { EFL_EVENT_DEL, _edje_device_canvas_del });
697

698
EFL_CALLBACKS_ARRAY_DEFINE(edje_device_custom_callbacks,
699
                           { EFL_CANVAS_SCENE_EVENT_DEVICE_CHANGED, _edje_device_changed_cb },
700
                           { EFL_CANVAS_SCENE_EVENT_DEVICE_ADDED, _edje_device_added_cb },
701
                           { EFL_CANVAS_SCENE_EVENT_DEVICE_REMOVED, _edje_device_removed_cb },
702
                           { EFL_EVENT_DEL, _edje_device_canvas_del });
703

704
static void
705
_edje_device_canvas_del(void *data, const Efl_Event *event)
706
{
707
   Edje *ed = data;
708

709
   if (ed->collection && ed->collection->use_custom_seat_names)
710
     efl_event_callback_array_del(event->object, edje_device_custom_callbacks(), ed);
711
   else
712
     efl_event_callback_array_del(event->object, edje_device_callbacks(), ed);
713
}
714

715
void
716
_edje_devices_add(Edje *ed, Evas *tev)
717
{
718
   const Eina_List *devices, *l;
719
   Efl_Input_Device *dev;
720

721
   ed->need_seat = EINA_TRUE;
722

723
   devices = evas_device_list(tev, NULL);
724
   EINA_LIST_FOREACH(devices, l, dev)
725
     {
726
        if (efl_input_device_type_get(dev) == EFL_INPUT_DEVICE_TYPE_SEAT)
727
          _edje_device_add(ed, dev);
728
     }
729

730
   if (ed->collection && ed->collection->use_custom_seat_names)
731
     efl_event_callback_array_add(tev, edje_device_custom_callbacks(), ed);
732
   else
733
     efl_event_callback_array_add(tev, edje_device_callbacks(), ed);
734
}
735

736
static inline void
737
_edje_process_colorclass(Edje *ed)
738
{
739
   unsigned int i;
740

741
   for (i = 0; i < ed->collection->parts_count; ++i)
742
     {
743
        Edje_Part *ep;
744
        unsigned int k;
745

746
        ep = ed->collection->parts[i];
747

748
        /* Register any color classes in this parts descriptions. */
749
        if ((ep->default_desc) && (ep->default_desc->color_class))
750
          efl_observable_observer_add(_edje_color_class_member, ep->default_desc->color_class, ed->obj);
751

752
        for (k = 0; k < ep->other.desc_count; k++)
753
          {
754
             Edje_Part_Description_Common *desc;
755

756
             desc = ep->other.desc[k];
757

758
             if (desc->color_class)
759
               efl_observable_observer_add(_edje_color_class_member, desc->color_class, ed->obj);
760
          }
761
     }
762
}
763

764
static inline void
765
_edje_process_sizeclass(Edje *ed)
766
{
767
   unsigned int i;
768

769
   for (i = 0; i < ed->collection->parts_count; ++i)
770
     {
771
        Edje_Part *ep;
772
        unsigned int k;
773

774
        ep = ed->collection->parts[i];
775

776
        /* Register any size classes in this parts descriptions. */
777
        if ((ep->default_desc) && (ep->default_desc->size_class))
778
          efl_observable_observer_add(_edje_size_class_member, ep->default_desc->size_class, ed->obj);
779

780
        for (k = 0; k < ep->other.desc_count; k++)
781
          {
782
             Edje_Part_Description_Common *desc;
783

784
             desc = ep->other.desc[k];
785

786
             if (desc->size_class)
787
               efl_observable_observer_add(_edje_size_class_member, desc->size_class, ed->obj);
788
          }
789
     }
790
}
791

792
#ifdef HAVE_EPHYSICS
793
static inline void
794
_edje_process_physics(Edje *ed)
795
{
796
   if (EPH_LOAD())
797
     {
798
        EPH_CALL(ephysics_init)();
799
        ed->world = EPH_CALL(ephysics_world_new)();
800
        EPH_CALL(ephysics_world_event_callback_add)
801
         (ed->world, EPHYSICS_CALLBACK_WORLD_UPDATE,
802
          _edje_physics_world_update_cb, ed);
803
        EPH_CALL(ephysics_world_rate_set)
804
         (ed->world, ed->collection->physics.world.rate);
805
        EPH_CALL(ephysics_world_gravity_set)
806
         (ed->world, ed->collection->physics.world.gravity.x,
807
          ed->collection->physics.world.gravity.y,
808
          ed->collection->physics.world.gravity.z);
809
     }
810
}
811
#endif
812

813
Eina_Error
814
_edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const char *group, const char *parent, Eina_List *group_path, Eina_Array *nested)
815
{
816
   Edje *ed;
817
   Evas *tev;
818
   Edje_Real_Part *rp;
819
   Eina_List *textblocks = NULL;
820
   Eina_List *sources = NULL;
821
   Eina_List *externals = NULL;
822
   Eina_Hash *collect = NULL;
823
   unsigned int n;
824
   Eina_Array parts;
825
   int group_path_started = 0;
826
   Evas_Object *nested_smart = NULL;
827
   char lang[PATH_MAX];
828
   Eina_Bool had_file;
829
   Eina_Hash *part_match = NULL;
830

831
   /* Get data pointer of top-of-stack */
832
   int idx = eina_array_count(nested) - 1;
833
   Edje_Nested_Support *st_nested = (idx >= 0) ? eina_array_data_get(nested, idx) : NULL;
834

835
   ed = _edje_fetch(obj);
836
   if (!ed) return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
837
   if (!group) group = "";
838
   if ((ed->file) && (ed->file->f == file) &&
839
       (ed->group) && (!strcmp(group, ed->group)))
840
     {
841
        return 0;
842
     }
843
   had_file = !!ed->file;
844

845
   tev = evas_object_evas_get(obj);
846
   evas_event_freeze(tev);
847

848
   collect = _edje_object_collect(ed);
849
   if (collect)
850
     part_match = eina_hash_string_superfast_new(NULL);
851

852
   if (_edje_lua_script_only(ed)) _edje_lua_script_only_shutdown(ed);
853

854
#ifdef HAVE_EPHYSICS
855
   /* clear physics world  / shutdown ephysics */
856
   if ((ed->collection) && (ed->collection->physics_enabled) && (ed->world))
857
     {
858
        if (EPH_LOAD())
859
          {
860
             EPH_CALL(ephysics_world_del)(ed->world);
861
             EPH_CALL(ephysics_shutdown)();
862
          }
863
     }
864
#endif
865

866
   _edje_file_del(ed);
867

868
   eina_stringshare_replace(&ed->path, file ? eina_file_filename_get(file) : NULL);
869
   eina_stringshare_replace(&ed->group, group);
870

871
   ed->parent = eina_stringshare_add(parent);
872

873
   ed->load_error = EDJE_LOAD_ERROR_NONE;
874
   _edje_file_add(ed, file);
875
   ed->block_break = EINA_FALSE;
876

877

878
   ed->has_entries = EINA_FALSE;
879

880
   if (ed->collection)
881
     {
882
        if (ed->collection->parts_count > 0xffff)
883
          {
884
             ed->load_error = EDJE_LOAD_ERROR_CORRUPT_FILE;
885
             _edje_file_del(ed);
886
             return EFL_GFX_IMAGE_LOAD_ERROR_CORRUPT_FILE;
887
          }
888
        eina_array_step_set(&parts, sizeof (Eina_Array), 8);
889

890
        if (ed->collection->prop.orientation != EDJE_ORIENTATION_AUTO)
891
          ed->is_rtl = (ed->collection->prop.orientation ==
892
                        EDJE_ORIENTATION_RTL);
893

894
        ed->groups = eina_list_append(ed->groups, ed);
895

896
        if (ed->collection->lua_script_only)
897
          {
898
             ed->load_error = EDJE_LOAD_ERROR_NONE;
899
             _edje_lua_script_only_init(ed);
900
          }
901
        else
902
          {
903
             unsigned int i;
904

905
             if (ed->collection->physics_enabled)
906
               {
907
#ifdef HAVE_EPHYSICS
908
                  _edje_process_physics(ed);
909
#else
910
                     ERR("Edje compiled without support to physics.");
911
#endif
912
               }
913

914
             /* handle multiseat stuff */
915
             if (ed->collection->need_seat || ed->need_seat)
916
               _edje_devices_add(ed, tev);
917

918
             /* colorclass stuff */
919
             _edje_process_colorclass(ed);
920

921
             /* sizeclass stuff */
922
             _edje_process_sizeclass(ed);
923

924
             /* build real parts */
925
             for (n = 0; n < ed->collection->parts_count; n++)
926
               {
927
                  Edje_Part *ep;
928
                  Eina_Bool memerr = EINA_FALSE;
929

930
                  ep = ed->collection->parts[n];
931
                  if (part_match)
932
                    eina_hash_add(part_match, ep->name, (void*)1);
933

934
                  if (ep->nested_children_count) /* Add object to nested parts list */
935
                    {
936
                       st_nested = malloc(sizeof(*st_nested));
937
                       nested_smart = st_nested->o = edje_smart_nested_add(tev);
938

939
                       /* We add 1 to children_count because the parent
940
                          object is added to smart obj children as well */
941
                       st_nested->nested_children_count =
942
                         ep->nested_children_count + 1;
943

944
                       evas_object_show(st_nested->o);
945

946
                       eina_array_push(nested, st_nested);
947
                    }
948

949
                  rp = eina_mempool_malloc(_edje_real_part_mp, sizeof(Edje_Real_Part));
950
                  if (!rp)
951
                    {
952
                       /* FIXME: destroy all allocated ressource, need to have a common exit point */
953
                       ed->load_error = EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
954
                       goto on_error;
955
                    }
956

957
                  memset(rp, 0, sizeof (Edje_Real_Part));
958

959
                  if ((ep->dragable.x != 0) || (ep->dragable.y != 0))
960
                    {
961
                       rp->drag = calloc(1, sizeof (Edje_Real_Part_Drag));
962
                       if (!rp->drag)
963
                         {
964
                            ed->load_error = EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
965
                            goto on_error;
966
                         }
967

968
                       rp->drag->step.x = FROM_INT(ep->dragable.step_x);
969
                       rp->drag->step.y = FROM_INT(ep->dragable.step_y);
970
                    }
971
                  // allow part type specific data - this keeps real_part smaller
972
                  switch (ep->type)
973
                    {
974
                     case EDJE_PART_TYPE_TEXT:
975
                     case EDJE_PART_TYPE_TEXTBLOCK:
976
                       rp->type = EDJE_RP_TYPE_TEXT;
977
                       rp->typedata.text = calloc(1, sizeof(Edje_Real_Part_Text));
978
                       if (!rp->typedata.text) memerr = EINA_TRUE;
979
                       break;
980

981
                     case EDJE_PART_TYPE_GROUP:
982
                     case EDJE_PART_TYPE_SWALLOW:
983
                     case EDJE_PART_TYPE_EXTERNAL:
984
                       rp->type = EDJE_RP_TYPE_SWALLOW;
985
                       rp->typedata.swallow = calloc(1, sizeof(Edje_Real_Part_Swallow));
986
                       if (!rp->typedata.swallow) memerr = EINA_TRUE;
987
                       break;
988

989
                     case EDJE_PART_TYPE_BOX:
990
                     case EDJE_PART_TYPE_TABLE:
991
                       rp->type = EDJE_RP_TYPE_CONTAINER;
992
                       rp->typedata.container = calloc(1, sizeof(Edje_Real_Part_Container));
993
                       if (!rp->typedata.container) memerr = EINA_TRUE;
994
                       break;
995

996
                     case EDJE_PART_TYPE_VECTOR:
997
                       rp->type = EDJE_RP_TYPE_VECTOR;
998
                       rp->typedata.vector = calloc(1, sizeof(Edje_Real_Part_Vector));
999
                       if (!rp->typedata.vector)
1000
                         memerr = EINA_TRUE;
1001
                       else
1002
                         rp->typedata.vector->current_id = -1;
1003
                       break;
1004

1005
                     default:
1006
                       break;
1007
                    }
1008

1009
                  if (memerr)
1010
                    {
1011
                       if (rp->drag) free(rp->drag);
1012
                       ed->load_error = EDJE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1013
                       eina_mempool_free(_edje_real_part_mp, rp);
1014
                       evas_event_thaw(tev);
1015
                       evas_event_thaw_eval(tev);
1016
                       return EFL_GFX_IMAGE_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
1017
                    }
1018

1019
                  _edje_ref(ed);
1020
                  rp->part = ep;
1021
                  eina_array_push(&parts, rp);
1022
                  rp->param1.description =
1023
                    _edje_part_description_find(ed, rp, "default", 0.0, EINA_TRUE);
1024
                  rp->chosen_description = rp->param1.description;
1025
                  if (!rp->param1.description)
1026
                    ERR("no default part description for '%s'!",
1027
                        rp->part->name);
1028

1029
                  switch (ep->type)
1030
                    {
1031
                     case EDJE_PART_TYPE_RECTANGLE:
1032
                       rp->object = evas_object_rectangle_add(ed->base.evas);
1033
                       break;
1034

1035
                     case EDJE_PART_TYPE_VECTOR:
1036
                       rp->object = evas_object_vg_add(ed->base.evas);
1037
                       break;
1038

1039
                     case EDJE_PART_TYPE_PROXY:
1040
                     case EDJE_PART_TYPE_IMAGE:
1041
                       rp->object = evas_object_image_add(ed->base.evas);
1042
                       break;
1043

1044
                     case EDJE_PART_TYPE_SNAPSHOT:
1045
                       rp->object = evas_object_image_filled_add(ed->base.evas);
1046
                       evas_object_image_snapshot_set(rp->object, EINA_TRUE);
1047
                       break;
1048

1049
                     case EDJE_PART_TYPE_TEXT:
1050
                       _edje_text_part_on_add(ed, rp);
1051
                       rp->object = evas_object_text_add(ed->base.evas);
1052
                       evas_object_text_font_source_set(rp->object, ed->path);
1053
                       break;
1054

1055
                     case EDJE_PART_TYPE_GROUP:
1056
                       sources = eina_list_append(sources, rp);
1057

1058
                       EINA_FALLTHROUGH;
1059
                     // fallthrough intentional
1060
                     case EDJE_PART_TYPE_SWALLOW:
1061
                       EINA_FALLTHROUGH;
1062
                     case EDJE_PART_TYPE_EXTERNAL:
1063
                       if (ep->type == EDJE_PART_TYPE_EXTERNAL)
1064
                         externals = eina_list_append(externals, rp);
1065
                       rp->object = evas_object_rectangle_add(ed->base.evas);
1066
                       evas_object_color_set(rp->object, 0, 0, 0, 0);
1067
                       evas_object_pass_events_set(rp->object, 1);
1068
                       evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
1069
                       _edje_callbacks_focus_add(rp->object, ed, rp);
1070
                       break;
1071

1072
                     case EDJE_PART_TYPE_TEXTBLOCK:
1073
                       _edje_textblock_styles_add(ed, rp);
1074
                       textblocks = eina_list_append(textblocks, rp);
1075
                       rp->object = evas_object_textblock_add(ed->base.evas);
1076
                       break;
1077

1078
                     case EDJE_PART_TYPE_BOX:
1079
                       sources = eina_list_append(sources, rp);
1080
                       rp->object = evas_object_box_add(ed->base.evas);
1081
                       rp->typedata.container->anim = _edje_box_layout_anim_new(rp->object);
1082
                       break;
1083

1084
                     case EDJE_PART_TYPE_TABLE:
1085
                       sources = eina_list_append(sources, rp);
1086
                       rp->object = evas_object_table_add(ed->base.evas);
1087
                       break;
1088

1089
                     case EDJE_PART_TYPE_GRADIENT:
1090
                       ERR("YOU ARE USING GRADIENT IN PART %s FROM GROUP %s INSIDE FILE %s !! THEY ARE NOW REMOVED !",
1091
                           ep->name, group, eina_file_filename_get(file));
1092
                       break;
1093

1094
                     case EDJE_PART_TYPE_SPACER:
1095
                       rp->object = NULL;
1096
                       break;
1097

1098
                     default:
1099
                       ERR("wrong part type %i!", ep->type);
1100
                       break;
1101
                    }
1102

1103
                  if (rp->object)
1104
                    {
1105
                       if (nested_smart) /* Update this pointer to father object only
1106
                                            this will make smart object size == father sz */
1107
                         {
1108
                            rp->nested_smart = nested_smart;
1109
                            nested_smart = NULL;
1110
                         }
1111

1112
                       if (ep->allowed_seats)
1113
                         _edje_part_seat_filter_apply(ed, rp);
1114

1115
                       if (ep->no_render)
1116
                         efl_canvas_object_no_render_set(rp->object, 1);
1117

1118
                       if (st_nested && st_nested->nested_children_count) /* Add this to list of children */
1119
                         {
1120
                            evas_object_smart_member_add(rp->object,
1121
                                                         st_nested->o);
1122

1123
                            st_nested->nested_children_count--;
1124

1125
                            /* No more nested children for this obj */
1126
                            while (st_nested && (st_nested->nested_children_count == 0))
1127
                              {
1128
                                 /* Loop to add smart counter as child */
1129
                                 Evas_Object *p_obj = st_nested->o;
1130

1131
                                 st_nested = eina_array_pop(nested);
1132
                                 free(st_nested);
1133

1134
                                 /* Check for parent in stack */
1135
                                 idx = eina_array_count(nested) - 1;
1136
                                 st_nested = (idx >= 0) ? eina_array_data_get(nested, idx) : NULL;
1137

1138
                                 if (st_nested)
1139
                                   {
1140
                                      st_nested->nested_children_count--;
1141
                                      evas_object_smart_member_add(p_obj, st_nested->o);
1142
                                   }
1143
                                 else
1144
                                   {
1145
                                      evas_object_smart_member_add(p_obj, ed->obj);
1146
                                   }
1147
                              }
1148
                         }
1149
                       else
1150
                         evas_object_smart_member_add(rp->object, ed->obj);
1151

1152
                       //		       evas_object_layer_set(rp->object, evas_object_layer_get(ed->obj));
1153
                       rp->mouse_events = ep->mouse_events;
1154
                       rp->repeat_events = ep->repeat_events;
1155

1156
                       if (ep->type != EDJE_PART_TYPE_SWALLOW && ep->type != EDJE_PART_TYPE_GROUP && ep->type != EDJE_PART_TYPE_EXTERNAL)
1157
                         {
1158
                            if (rp->mouse_events)
1159
                              {
1160
                                 _edje_callbacks_add(rp->object, ed, rp);
1161
                                 if (rp->repeat_events)
1162
                                   evas_object_repeat_events_set(rp->object, rp->repeat_events);
1163

1164
                                 if (ep->pointer_mode != EVAS_OBJECT_POINTER_MODE_AUTOGRAB)
1165
                                   evas_object_pointer_mode_set(rp->object, ep->pointer_mode);
1166
                              }
1167
                            else
1168
                              {
1169
                                 evas_object_pass_events_set(rp->object, 1);
1170
                                 evas_object_pointer_mode_set(rp->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
1171
                              }
1172
                            efl_canvas_object_anti_alias_set(rp->object, ep->anti_alias);
1173
                            efl_canvas_object_precise_is_inside_set(rp->object, ep->precise_is_inside);
1174
                         }
1175
                       if (rp->part->clip_to_id < 0)
1176
                         evas_object_clip_set(rp->object, ed->base.clipper);
1177
                    }
1178
               }
1179
             if (n > 0)
1180
               {
1181
                  ed->table_parts = malloc(sizeof(Edje_Real_Part *) * n);
1182
                  ed->table_parts_size = n;
1183
                  /* FIXME: check malloc return */
1184
                  n = eina_array_count(&parts) - 1;
1185
                  while ((rp = eina_array_pop(&parts)))
1186
                    {
1187
                       ed->table_parts[n] = rp;
1188
                       n--;
1189
                    }
1190
                  for (i = 0; i < ed->table_parts_size; i++)
1191
                    {
1192
                       Edje_Real_Part *clip_to = NULL;
1193

1194
                       rp = ed->table_parts[i];
1195
                       if (rp->param1.description)   /* FIXME: prevent rel to gone radient part to go wrong. You may
1196
                                                        be able to remove this when all theme are correctly rewritten. */
1197
                         {
1198
                            if (rp->param1.description->rel1.id_x >= 0)
1199
                              rp->param1.description->rel1.id_x %= ed->table_parts_size;
1200
                            if (rp->param1.description->rel1.id_y >= 0)
1201
                              rp->param1.description->rel1.id_y %= ed->table_parts_size;
1202
                            if (rp->param1.description->rel2.id_x >= 0)
1203
                              rp->param1.description->rel2.id_x %= ed->table_parts_size;
1204
                            if (rp->param1.description->rel2.id_y >= 0)
1205
                              rp->param1.description->rel2.id_y %= ed->table_parts_size;
1206
                         }
1207

1208
                       if (rp->param1.description && (rp->param1.description->clip_to_id >= 0))
1209
                         {
1210
                            clip_to = ed->table_parts[rp->param1.description->clip_to_id % ed->table_parts_size];
1211
                            ed->has_state_clip = EINA_TRUE;
1212
                         }
1213
                       else if (rp->part->clip_to_id >= 0)
1214
                         clip_to = ed->table_parts[rp->part->clip_to_id % ed->table_parts_size];
1215
                       if (clip_to && clip_to->object && rp->object)
1216
                         {
1217
                            evas_object_pass_events_set(clip_to->object, 1);
1218
                            evas_object_pointer_mode_set(clip_to->object, EVAS_OBJECT_POINTER_MODE_NOGRAB);
1219
                            evas_object_clip_set(rp->object, clip_to->object);
1220
                         }
1221

1222
                       if (rp->drag)
1223
                         {
1224
                            if (rp->part->dragable.confine_id >= 0)
1225
                              rp->drag->confine_to = ed->table_parts[rp->part->dragable.confine_id % ed->table_parts_size];
1226
                            if (rp->part->dragable.threshold_id >= 0)
1227
                              rp->drag->threshold = ed->table_parts[rp->part->dragable.threshold_id % ed->table_parts_size];
1228
                         }
1229

1230
                       if ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1231
                           (rp->typedata.swallow))
1232
                         {
1233
                            rp->typedata.swallow->swallow_params.min.w = 0;
1234
                            rp->typedata.swallow->swallow_params.min.h = 0;
1235
                            rp->typedata.swallow->swallow_params.max.w = -1;
1236
                            rp->typedata.swallow->swallow_params.max.h = -1;
1237
                         }
1238

1239
                       if (rp->part->type == EDJE_PART_TYPE_TEXT
1240
                           || rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1241
                         {
1242
                            Edje_Part_Description_Text *text;
1243

1244
                            text = (Edje_Part_Description_Text *)rp->param1.description;
1245
                            if (text)
1246
                              {
1247
                                 if (ed->file->feature_ver < 1)
1248
                                   {
1249
                                      text->text.id_source = -1;
1250
                                      text->text.id_text_source = -1;
1251
                                   }
1252

1253
                                 if ((rp->type == EDJE_RP_TYPE_TEXT) &&
1254
                                     (rp->typedata.text))
1255
                                   {
1256
                                      if (text->text.id_source >= 0)
1257
                                        {
1258
                                           rp->typedata.text->source =
1259
                                             ed->table_parts[text->text.id_source % ed->table_parts_size];
1260
                                        }
1261

1262
                                      if (text->text.id_text_source >= 0)
1263
                                        {
1264
                                           rp->typedata.text->text_source =
1265
                                             ed->table_parts[text->text.id_text_source % ed->table_parts_size];
1266
                                        }
1267
                                   }
1268
                              }
1269

1270
                            if ((rp->part->type == EDJE_PART_TYPE_TEXTBLOCK) &&
1271
                                  rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1272
                              {
1273
                                 _edje_entry_real_part_init(ed, rp);
1274
                                 if (!ed->has_entries)
1275
                                   ed->has_entries = EINA_TRUE;
1276
                              }
1277
                         }
1278
                    }
1279
               }
1280

1281
             _edje_ref(ed);
1282
             _edje_block(ed);
1283
             _edje_util_freeze(ed);
1284
             _edje_var_init(ed);
1285
             for (i = 0; i < ed->table_parts_size; i++)
1286
               {
1287
                  rp = ed->table_parts[i];
1288
                  /* SPACER parts do not have objects */
1289
                  if (rp->object) evas_object_show(rp->object);
1290
                  if (_edje_block_break(ed)) break;
1291
                  if (rp->drag)
1292
                    {
1293
                       if (rp->part->dragable.x < 0) rp->drag->val.x = FROM_DOUBLE(1.0);
1294
                       if (rp->part->dragable.y < 0) rp->drag->val.x = FROM_DOUBLE(1.0);
1295
                       _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
1296
                    }
1297
               }
1298
             ed->recalc_call = EINA_TRUE;
1299
             ed->dirty = EINA_TRUE;
1300
#ifdef EDJE_CALC_CACHE
1301
             ed->all_part_change = EINA_TRUE;
1302
#endif
1303
             if ((evas_object_clipees_has(ed->base.clipper)) &&
1304
                 (evas_object_visible_get(obj)))
1305
               evas_object_show(ed->base.clipper);
1306

1307
             /* instantiate 'internal swallows' */
1308
             EINA_LIST_FREE(externals, rp)
1309
               {
1310
                  Edje_Part_Description_External *external;
1311
                  Evas_Object *child_obj;
1312

1313
                  external = (Edje_Part_Description_External *)rp->part->default_desc;
1314
                  child_obj = _edje_external_type_add(rp->part->source,
1315
                                                      evas_object_evas_get(ed->obj), ed->obj,
1316
                                                      external->external_params, rp->part->name);
1317
                  if (child_obj)
1318
                    {
1319
                       _edje_real_part_swallow(ed, rp, child_obj, EINA_TRUE);
1320
                       rp->param1.external_params = _edje_external_params_parse(child_obj,
1321
                                                                                external->external_params);
1322
                       _edje_external_recalc_apply(ed, rp, NULL, rp->chosen_description);
1323
                    }
1324
               }
1325

1326
             EINA_LIST_FREE(sources, rp)
1327
               {
1328
                  /* XXX: curr_item and pack_it don't require to be NULL since
1329
                   * XXX: they are just used when source != NULL and type == BOX,
1330
                   * XXX: and they're always set in this case, but GCC fails to
1331
                   * XXX: notice that, so let's shut it up
1332
                   */
1333
                  Edje_Pack_Element **curr_item = NULL;
1334
                  unsigned int item_count = 0;
1335
                  Edje_Pack_Element *pack_it = NULL;
1336
                  const char *source = NULL;
1337

1338
                  switch (rp->part->type)
1339
                    {
1340
                     case EDJE_PART_TYPE_GROUP:
1341
                       source = rp->part->source;
1342
                       break;
1343

1344
                     case EDJE_PART_TYPE_BOX:
1345
                     case EDJE_PART_TYPE_TABLE:
1346
                       if (rp->part->items)
1347
                         {
1348
                            curr_item = rp->part->items;
1349
                            item_count = rp->part->items_count;
1350
                            if (item_count > 0)
1351
                              {
1352
                                 pack_it = *curr_item;
1353
                                 source = pack_it->source;
1354
                                 item_count--;
1355
                                 curr_item++;
1356
                              }
1357
                         }
1358
                       break;
1359

1360
                     default:
1361
                       /* This list should only be filled by group, box or table, nothing else. */
1362
                       abort();
1363
                    }
1364

1365
                  while (source)
1366
                    {
1367
                       Eina_List *l;
1368
                       Evas_Object *child_obj;
1369
                       Edje_Pack_Element pack_it_copy;
1370
                       const char *group_path_entry = eina_stringshare_add(source);
1371
                       const char *data;
1372

1373
                       if (!group_path)
1374
                         {
1375
                            group_path = eina_list_append(NULL, eina_stringshare_add(group));
1376
                            group_path_started = 1;
1377
                         }
1378
                       /* make sure that this group isn't already in the tree of parents */
1379
                       EINA_LIST_FOREACH(group_path, l, data)
1380
                         {
1381
                            if (data == group_path_entry)
1382
                              {
1383
                                 ERR("recursive loop group '%s' already included inside part '%s' of group '%s' from file '%s'",
1384
                                     group_path_entry, rp->part->name, group, eina_file_filename_get(file));
1385
                                 ed->load_error = EDJE_LOAD_ERROR_RECURSIVE_REFERENCE;
1386
                                 eina_stringshare_del(group_path_entry);
1387
                                 goto on_error;
1388
                              }
1389
                         }
1390

1391
                       if (pack_it)
1392
                         {
1393
                            pack_it_copy = *pack_it;
1394
                         }
1395
                       else
1396
                         {
1397
                            memset(&pack_it_copy, 0, sizeof (pack_it_copy));
1398
                         }
1399

1400
                       do
1401
                         {
1402
                            Eina_Error load_error;
1403
                            child_obj = edje_object_add(ed->base.evas);
1404
                            edje_object_mirrored_set(child_obj, edje_object_mirrored_get(ed->obj));
1405

1406
                            group_path = eina_list_append(group_path, group_path_entry);
1407
                            if (rp->part->type == EDJE_PART_TYPE_GROUP)
1408
                              {
1409
                                 _edje_real_part_swallow(ed, rp, child_obj, EINA_FALSE);
1410
                              }
1411

1412
                            load_error = _edje_object_file_set_internal(child_obj, file, source, rp->part->name, group_path, nested);
1413
                            if (load_error)
1414
                              {
1415
                                 ERR("impossible to set part '%s' of group '%s' from file '%s' to '%s'",
1416
                                     rp->part->name, group_path_entry, eina_file_filename_get(file), source);
1417
                                 ed->load_error = edje_object_load_error_get(child_obj);
1418
                                 evas_object_del(child_obj);
1419
                                 eina_stringshare_del(group_path_entry);
1420
                                 goto on_error;
1421
                              }
1422

1423
                            group_path = eina_list_remove(group_path, group_path_entry);
1424

1425
                            edje_object_propagate_callback_add(child_obj,
1426
                                                               _cb_signal_repeat,
1427
                                                               obj);
1428
                            if (rp->part->type == EDJE_PART_TYPE_GROUP)
1429
                              {
1430
                                 Edje *edg = _edje_fetch(child_obj);
1431
                                 ed->groups = eina_list_append(ed->groups, edg);
1432
                                 evas_object_data_set(child_obj, "\377 edje.part_obj", rp);
1433
                                 _edje_real_part_swallow(ed, rp, child_obj, EINA_FALSE);
1434
                                 _edje_subobj_register(ed, child_obj);
1435
                                 source = NULL;
1436
                              }
1437
                            else
1438
                              {
1439
                                 if ((rp->type == EDJE_RP_TYPE_CONTAINER) &&
1440
                                     (rp->typedata.container))
1441
                                   {
1442
                                      Eina_Strbuf *buf = NULL;
1443
                                      const char *name = pack_it_copy.name;
1444

1445
                                      pack_it->parent = rp;
1446

1447
                                      _edje_object_pack_item_hints_set(child_obj, &pack_it_copy);
1448

1449
                                      if (pack_it->spread.h > 1 && pack_it->spread.w >= 1)
1450
                                        {
1451
                                           buf = eina_strbuf_new();
1452
                                           if (name)
1453
                                             eina_strbuf_append_printf(buf, "%s{%i,%i}", name, pack_it_copy.col, pack_it_copy.row);
1454
                                           else
1455
                                             eina_strbuf_append_printf(buf, "%i,%i", pack_it_copy.col, pack_it_copy.row);
1456
                                           name = eina_strbuf_string_get(buf);
1457
                                        }
1458
                                      if (name) evas_object_name_set(child_obj, name);
1459
                                      if (buf) eina_strbuf_free(buf);
1460

1461
                                      if (rp->part->type == EDJE_PART_TYPE_BOX)
1462
                                        {
1463
                                           _edje_real_part_box_append(ed, rp, child_obj);
1464
                                           evas_object_data_set(child_obj, "\377 edje.box_item", pack_it);
1465
                                        }
1466
                                      else if (rp->part->type == EDJE_PART_TYPE_TABLE)
1467
                                        {
1468
                                           _edje_real_part_table_pack(ed, rp, child_obj,
1469
                                                                      pack_it_copy.col, pack_it_copy.row,
1470
                                                                      pack_it_copy.colspan, pack_it_copy.rowspan);
1471
                                           evas_object_data_set(child_obj, "\377 edje.table_item", pack_it);
1472
                                        }
1473
                                      _edje_subobj_register(ed, child_obj);
1474
                                      evas_object_show(child_obj);
1475
                                      rp->typedata.container->items = eina_list_append(rp->typedata.container->items, child_obj);
1476
                                   }
1477
                              }
1478

1479
                            pack_it_copy.spread.w--;
1480
                            pack_it_copy.col++;
1481
                            if (pack_it_copy.spread.w < 1 && pack_it)
1482
                              {
1483
                                 pack_it_copy.col = pack_it->col;
1484
                                 pack_it_copy.row++;
1485
                                 pack_it_copy.spread.h--;
1486
                                 pack_it_copy.spread.w = pack_it->spread.w;
1487
                              }
1488
                         }
1489
                       while (pack_it_copy.spread.h > 0);
1490

1491
                       eina_stringshare_del(group_path_entry);
1492

1493
                       if ((rp->type == EDJE_RP_TYPE_CONTAINER) &&
1494
                           (rp->typedata.container))
1495
                         {
1496
                            if (item_count > 0)
1497
                              {
1498
                                 pack_it = *curr_item;
1499
                                 source = pack_it->source;
1500
                                 curr_item++;
1501
                                 item_count--;
1502
                              }
1503
                            else
1504
                              {
1505
                                 source = NULL;
1506
                                 curr_item = NULL;
1507
                                 pack_it = NULL;
1508
                              }
1509
                         }
1510
                    }
1511
               }
1512

1513
             if (group_path_started)
1514
               {
1515
                  const char *str;
1516

1517
                  EINA_LIST_FREE(group_path, str)
1518
                    eina_stringshare_del(str);
1519
               }
1520

1521
             /* reswallow any swallows that existed before setting the file */
1522
             if (collect)
1523
               {
1524
                  Edje_User_Defined *eud;
1525
                  Eina_List *boxes = NULL;
1526
                  Eina_Iterator *it;
1527
                  Eina_List *l, *ll;
1528

1529
                  it = eina_hash_iterator_data_new(collect);
1530
                  EINA_ITERATOR_FOREACH(it, l)
1531
                    {
1532
                       EINA_LIST_FOREACH(l, ll, eud)
1533
                         {
1534
                            Evas_Object *child = NULL;
1535

1536
                            if (!eina_hash_find(part_match, eud->part))
1537
                              {
1538
                                 /* part no longer exists */
1539
                                 switch (eud->type)
1540
                                   {
1541
                                    case EDJE_USER_SWALLOW:
1542
                                      child = eud->u.swallow.child;
1543
                                      break;
1544
                                    case EDJE_USER_BOX_PACK:
1545
                                      child = eud->u.box.child;
1546
                                      break;
1547
                                    case EDJE_USER_TABLE_PACK:
1548
                                      child = eud->u.table.child;
1549
                                      break;
1550
                                    case EDJE_USER_STRING:
1551
                                      eina_stringshare_del(eud->u.string.text);
1552
                                      /* string has extra ref in this case */
1553
                                      if (!had_file)
1554
                                        eina_stringshare_del(eud->u.string.text);
1555
                                      break;
1556
                                    case EDJE_USER_DRAG_STEP:
1557
                                    case EDJE_USER_DRAG_PAGE:
1558
                                    case EDJE_USER_DRAG_VALUE:
1559
                                    case EDJE_USER_DRAG_SIZE:
1560
                                      break;
1561
                                    case EDJE_USER_TEXT_STYLE:
1562
                                      {
1563
                                         Edje_Part_Text_Prop *prop;
1564
                                         EINA_LIST_FREE(eud->u.text_style.props, prop)
1565
                                           free(prop);
1566
                                      }
1567
                                    break;
1568
                                    case EDJE_USER_TEXT_EXPAND:
1569
                                    default:
1570
                                      break;
1571
                                   }
1572
                                 if (child)
1573
                                   {
1574
                                      WRN("Container part '%s' no longer exists, hiding previously-contained child object", eud->part);
1575
                                      evas_object_hide(child);
1576
                                   }
1577
                              }
1578
                            else
1579
                              {
1580
                                 switch (eud->type)
1581
                                   {
1582
                                    case EDJE_USER_SWALLOW:
1583
                                      edje_object_part_swallow(obj, eud->part, eud->u.swallow.child);
1584
                                      child = eud->u.swallow.child;
1585
                                      break;
1586

1587
                                    case EDJE_USER_BOX_PACK:
1588
                                      boxes = eina_list_append(boxes, eud);
1589
                                      eud = NULL;
1590
                                      break;
1591

1592
                                    case EDJE_USER_TABLE_PACK:
1593
                                      edje_object_part_table_pack(obj, eud->part, eud->u.table.child,
1594
                                                                  eud->u.table.col, eud->u.table.row,
1595
                                                                  eud->u.table.colspan, eud->u.table.rowspan);
1596
                                      child = eud->u.table.child;
1597
                                      break;
1598

1599
                                    case EDJE_USER_DRAG_STEP:
1600
                                      edje_object_part_drag_step_set(obj, eud->part,
1601
                                                                     eud->u.drag_position.x,
1602
                                                                     eud->u.drag_position.y);
1603
                                      break;
1604

1605
                                    case EDJE_USER_DRAG_PAGE:
1606
                                      edje_object_part_drag_page_set(obj, eud->part,
1607
                                                                     eud->u.drag_position.x,
1608
                                                                     eud->u.drag_position.y);
1609
                                      break;
1610

1611
                                    case EDJE_USER_DRAG_VALUE:
1612
                                      edje_object_part_drag_value_set(obj, eud->part,
1613
                                                                      eud->u.drag_position.x,
1614
                                                                      eud->u.drag_position.y);
1615
                                      break;
1616

1617
                                    case EDJE_USER_DRAG_SIZE:
1618
                                      edje_object_part_drag_size_set(obj, eud->part,
1619
                                                                     eud->u.drag_size.w,
1620
                                                                     eud->u.drag_size.h);
1621
                                      break;
1622

1623
                                    case EDJE_USER_STRING:
1624
                                      switch (eud->u.string.type)
1625
                                        {
1626
                                         case EDJE_TEXT_TYPE_NORMAL:
1627
                                           efl_text_set(efl_part(obj, eud->part), eud->u.string.text);
1628
                                           break;
1629
                                         case EDJE_TEXT_TYPE_MARKUP:
1630
                                           efl_text_markup_set(efl_part(obj, eud->part), eud->u.string.text);
1631
                                           break;
1632
                                         case EDJE_TEXT_TYPE_ESCAPED:
1633
                                           edje_object_part_text_escaped_set(obj, eud->part, eud->u.string.text);
1634
                                           break;
1635
                                         case EDJE_TEXT_TYPE_UNESCAPED:
1636
                                           edje_object_part_text_unescaped_set(obj, eud->part, eud->u.string.text);
1637
                                           break;
1638
                                        }
1639
                                      eina_stringshare_del(eud->u.string.text);
1640
                                      /* string has extra ref in this case */
1641
                                      if (!had_file)
1642
                                        eina_stringshare_del(eud->u.string.text);
1643
                                      break;
1644

1645
                                    case EDJE_USER_TEXT_STYLE:
1646
                                        {
1647
                                           Edje_Part_Text_Prop *prop;
1648
                                           EINA_LIST_FREE(eud->u.text_style.props, prop)
1649
                                             {
1650
                                                _canvas_layout_user_text_apply(eud, obj,
1651
                                                      prop);
1652
                                                free(prop);
1653
                                             }
1654
                                        }
1655
                                      break;
1656
                                    case EDJE_USER_TEXT_EXPAND:
1657
                                        {
1658
                                           efl_canvas_layout_part_text_expand_set(
1659
                                                 efl_part(obj, eud->part),
1660
                                                 eud->u.text_expand.expand);
1661
                                        }
1662
                                      break;
1663
                                   }
1664
                              }
1665
                         }
1666
                    }
1667
                  eina_iterator_free(it);
1668

1669
                  boxes = eina_list_sort(boxes, -1, _sort_defined_boxes);
1670
                  EINA_LIST_FREE(boxes, eud)
1671
                    edje_object_part_box_append(obj, eud->part, eud->u.box.child);
1672
                  eina_hash_free(part_match);
1673
                  eina_hash_free(collect);
1674
               }
1675
             if (_edje_language)
1676
               snprintf(lang, sizeof(lang), "edje,language,%s", _edje_language);
1677
             else
1678
             snprintf(lang, sizeof(lang), "edje,language,%s", "none");
1679
             edje_object_signal_emit(obj, lang, "edje");
1680

1681
             if (edje_object_mirrored_get(obj))
1682
               edje_object_signal_emit(obj, "edje,state,rtl", "edje");
1683
             else
1684
               edje_object_signal_emit(obj, "edje,state,ltr", "edje");
1685

1686
             _edje_recalc(ed);
1687
             _edje_util_thaw(ed);
1688
             _edje_unblock(ed);
1689
             _edje_unref(ed);
1690
             ed->load_error = EDJE_LOAD_ERROR_NONE;
1691
             _edje_emit(ed, "load", NULL);
1692

1693
             /* instantiate 'internal textblock style' */
1694
             EINA_LIST_FREE(textblocks, rp)
1695
               if (rp->part->default_desc)
1696
                 {
1697
                    Edje_Part_Description_Text *text;
1698
                    Evas_Textblock_Style *style = NULL;
1699

1700
                    text = (Edje_Part_Description_Text *)rp->part->default_desc;
1701
                    style = _edje_textblock_style_get(ed, edje_string_get(&text->text.style));
1702

1703
                    if (evas_object_textblock_style_get(rp->object) != style)
1704
                      evas_object_textblock_style_set(rp->object, style);
1705
                 }
1706
          }
1707
        _edje_entry_init(ed);
1708
        eina_array_flush(&parts);
1709
        evas_event_thaw(tev);
1710
        evas_event_thaw_eval(tev);
1711
        return 0;
1712
     }
1713
   evas_event_thaw(tev);
1714
   evas_event_thaw_eval(tev);
1715
   return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
1716

1717
on_error:
1718
   eina_list_free(textblocks);
1719
   eina_list_free(externals);
1720
   eina_list_free(sources);
1721
   eina_array_flush(&parts);
1722
   _edje_util_thaw(ed);
1723
   _edje_unblock(ed);
1724
   _edje_unref(ed);
1725
   _edje_file_del(ed);
1726
   if (group_path_started)
1727
     {
1728
        const char *path;
1729

1730
        EINA_LIST_FREE(group_path, path)
1731
          eina_stringshare_del(path);
1732
     }
1733
   evas_event_thaw(tev);
1734
   evas_event_thaw_eval(tev);
1735
   return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
1736
}
1737

1738
void
1739
_edje_file_add(Edje *ed, const Eina_File *f)
1740
{
1741
   if (!_edje_edd_edje_file) return;
1742
   if (!f)
1743
     {
1744
        ed->load_error = EDJE_LOAD_ERROR_DOES_NOT_EXIST;
1745
     }
1746
   else
1747
     {
1748
        int err = 0;
1749

1750
        ed->file = _edje_cache_file_coll_open(f, ed->group, &(err),
1751
                                              &(ed->collection), ed);
1752
        ed->load_error = (unsigned short)err;
1753
     }
1754

1755
   if (!ed->collection)
1756
     {
1757
        if (ed->file)
1758
          {
1759
             _edje_cache_file_unref(ed->file);
1760
             ed->file = NULL;
1761
          }
1762
     }
1763
}
1764

1765
static int
1766
_sort_defined_boxes(const void *a, const void *b)
1767
{
1768
   const Edje_User_Defined *euda = a;
1769
   const Edje_User_Defined *eudb = b;
1770

1771
   if (euda->part - eudb->part != 0)
1772
     return euda->part - eudb->part;
1773
   return euda->u.box.index - eudb->u.box.index;
1774
}
1775

1776
static Eina_Hash *
1777
_edje_object_collect(Edje *ed)
1778
{
1779
   Edje_User_Defined *eud;
1780
   Eina_Hash *collect;
1781
   Eina_List *l, *ll;
1782
   Eina_Iterator *it;
1783

1784
   collect = ed->user_defined;
1785
   ed->user_defined = NULL;
1786

1787
   it = eina_hash_iterator_data_new(collect);
1788
   EINA_ITERATOR_FOREACH(it, l)
1789
     {
1790
        EINA_LIST_FOREACH(l, ll, eud)
1791
          {
1792
             switch (eud->type)
1793
               {
1794
                case EDJE_USER_STRING:
1795
                  eud->u.string.text = eina_stringshare_ref(eud->u.string.text);
1796
                  break;
1797

1798
                case EDJE_USER_BOX_PACK:
1799
                  if (eud->u.box.index == -1)
1800
                    {
1801
                       Edje_User_Defined *search;
1802
                       Edje_Real_Part *rp;
1803
                       Eina_List *children;
1804
                       Eina_List *ls;
1805
                       Evas_Object *child;
1806
                       int idx = 0;
1807

1808
                       rp = _edje_real_part_recursive_get(&ed, eud->part);
1809
                       if (rp)
1810
                         {
1811
                            if (rp->part->type != EDJE_PART_TYPE_BOX) continue;
1812

1813
                            children = evas_object_box_children_get(rp->object);
1814
                            EINA_LIST_FREE(children, child)
1815
                              if (!evas_object_data_get(child, "\377 edje.box_item"))
1816
                                {
1817
                                   EINA_LIST_FOREACH(l, ls, search)
1818
                                     {
1819
                                        if (search->type == EDJE_USER_BOX_PACK &&
1820
                                            search->u.box.child == child &&
1821
                                            search->part == eud->part /* beauty of stringshare ! */)
1822
                                          {
1823
                                             search->u.box.index = idx++;
1824
                                             break;
1825
                                          }
1826
                                     }
1827
                                   _edje_real_part_box_remove(eud->ed, rp, child);
1828
                                }
1829
                         }
1830
                    }
1831
                  break;
1832

1833
                case EDJE_USER_TABLE_PACK:
1834
                {
1835
                   Edje_Real_Part *rp;
1836

1837
                   rp = _edje_real_part_recursive_get(&ed, eud->part);
1838
                   if (rp)
1839
                     {
1840
                        if (rp->part->type != EDJE_PART_TYPE_TABLE) continue;
1841
                        _edje_real_part_table_unpack(eud->ed, rp, eud->u.table.child);
1842
                     }
1843
                   break;
1844
                }
1845

1846
                case EDJE_USER_SWALLOW:
1847
                  edje_object_part_unswallow(NULL, eud->u.swallow.child);
1848
                  break;
1849

1850
                case EDJE_USER_TEXT_STYLE:
1851
                  _canvas_layout_user_text_collect(ed, eud);
1852
                  break;
1853

1854
                case EDJE_USER_DRAG_STEP:
1855
                case EDJE_USER_DRAG_PAGE:
1856
                case EDJE_USER_DRAG_VALUE:
1857
                case EDJE_USER_DRAG_SIZE:
1858
                case EDJE_USER_TEXT_EXPAND:
1859
                  break;
1860
               }
1861
          }
1862
     }
1863
   eina_iterator_free(it);
1864

1865
   return collect;
1866
}
1867

1868
void
1869
_edje_file_callbacks_del(Edje *ed, Evas *e)
1870
{
1871
   Evas *tev = e;
1872

1873
   if (!tev) tev = evas_object_evas_get(ed->obj);
1874
   if (ed->collection && ed->collection->use_custom_seat_names)
1875
     efl_event_callback_array_del(tev, edje_device_custom_callbacks(), ed);
1876
   else
1877
     efl_event_callback_array_del(tev, edje_device_callbacks(), ed);
1878
}
1879

1880
void
1881
_edje_file_del(Edje *ed)
1882
{
1883
   Evas *tev = NULL;
1884

1885
   if (ed->obj && (!efl_invalidated_get(ed->obj)))
1886
     tev = evas_object_evas_get(ed->obj);
1887

1888
   ed->groups = eina_list_free(ed->groups);
1889

1890
   if (tev)
1891
     {
1892
        _edje_file_callbacks_del(ed, tev);
1893
        evas_event_freeze(tev);
1894
     }
1895

1896
   if (ed->freeze_calc)
1897
     {
1898
        _edje_util_freeze_calc_list = eina_list_remove(_edje_util_freeze_calc_list, ed);
1899
        ed->freeze_calc = EINA_FALSE;
1900
        _edje_util_freeze_calc_count--;
1901
     }
1902
   _edje_entry_shutdown(ed);
1903
   _edje_message_del(ed);
1904
   _edje_block_violate(ed);
1905
   _edje_var_shutdown(ed);
1906
   if (!((ed->file) && (ed->collection)))
1907
     {
1908
        if (tev)
1909
          {
1910
             evas_event_thaw(tev);
1911
             evas_event_thaw_eval(tev);
1912
          }
1913
        return;
1914
     }
1915

1916
   eina_hash_free(ed->user_defined);
1917
   ed->user_defined = NULL;
1918

1919
   if (ed->table_parts)
1920
     {
1921
        unsigned int i;
1922
        for (i = 0; i < ed->table_parts_size; i++)
1923
          {
1924
             Edje_Real_Part *rp;
1925
#ifdef HAVE_EPHYSICS
1926
             Evas_Object *face_obj;
1927
#endif
1928

1929
             rp = ed->table_parts[i];
1930
             if (!rp) continue;
1931

1932
#ifdef HAVE_EPHYSICS
1933
             EINA_LIST_FREE(rp->body_faces, face_obj)
1934
               evas_object_del(face_obj);
1935
#endif
1936

1937
             if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1938
               _edje_entry_real_part_shutdown(ed, rp);
1939

1940
             if (rp->custom)
1941
               {
1942
                  // xxx: lua2
1943
                  _edje_collection_free_part_description_clean(rp->part->type,
1944
                                                               rp->custom->description,
1945
                                                               ed->file->free_strings);
1946
                  free(rp->custom->description);
1947
                  rp->custom->description = NULL;
1948
               }
1949

1950
             if ((rp->type == EDJE_RP_TYPE_CONTAINER) &&
1951
                 (rp->typedata.container))
1952
               {
1953
                  if (rp->typedata.container->items)
1954
                    {
1955
                       /* evas_box/table handles deletion of objects */
1956
                       rp->typedata.container->items = eina_list_free(rp->typedata.container->items);
1957
                    }
1958
                  if (rp->typedata.container->anim)
1959
                    {
1960
                       _edje_box_layout_free_data(rp->typedata.container->anim);
1961
                       rp->typedata.container->anim = NULL;
1962
                    }
1963
                  free(rp->typedata.container);
1964
                  rp->typedata.container = NULL;
1965
               }
1966
             else if ((rp->type == EDJE_RP_TYPE_TEXT) &&
1967
                      (rp->typedata.text))
1968
               {
1969
                  eina_stringshare_del(rp->typedata.text->text);
1970
                  eina_stringshare_del(rp->typedata.text->font);
1971
                  eina_stringshare_del(rp->typedata.text->cache.in_str);
1972
                  eina_stringshare_del(rp->typedata.text->cache.out_str);
1973
                  free(rp->typedata.text);
1974
                  rp->typedata.text = NULL;
1975
               }
1976
             else if ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1977
                      (rp->typedata.swallow))
1978
               {
1979
                  if (rp->typedata.swallow->swallowed_object)
1980
                    {
1981
                       /* Objects swallowed by the app do not get deleted,
1982
                          but those internally swallowed (GROUP type) do. */
1983
                       switch (rp->part->type)
1984
                         {
1985
                          case EDJE_PART_TYPE_EXTERNAL:
1986
                            _edje_external_parsed_params_free(rp->typedata.swallow->swallowed_object, rp->param1.external_params);
1987
                            if (rp->param2)
1988
                              _edje_external_parsed_params_free(rp->typedata.swallow->swallowed_object, rp->param2->external_params);
1989
                            EINA_FALLTHROUGH;
1990

1991
                          // fallthrough intentional
1992
                          case EDJE_PART_TYPE_GROUP:
1993
                            evas_object_del(rp->typedata.swallow->swallowed_object);
1994
                            rp->typedata.swallow->swallowed_object = NULL;
1995
                          default:
1996
                            break;
1997
                         }
1998
                       _edje_real_part_swallow_clear(ed, rp);
1999
                    }
2000
                  free(rp->typedata.swallow);
2001
                  rp->typedata.swallow = NULL;
2002
               }
2003
             else if ((rp->type == EDJE_RP_TYPE_VECTOR) &&
2004
                      (rp->typedata.vector))
2005
               {
2006
                  if (rp->typedata.vector->anim)
2007
                    {
2008
                       efl_canvas_object_animation_stop(rp->object);
2009
                       efl_del(rp->typedata.vector->anim);
2010
                    }
2011
                  if (rp->typedata.vector->lottie_virtual_file)
2012
                    eina_file_close(rp->typedata.vector->lottie_virtual_file);
2013
                  if (rp->typedata.vector->lottie_data)
2014
                    free(rp->typedata.vector->lottie_data);
2015

2016
                  free(rp->typedata.vector);
2017
                  rp->typedata.vector = NULL;
2018
               }
2019

2020
             if (rp->object)
2021
               {
2022
                  _edje_callbacks_focus_del(rp->object, ed);
2023
                  _edje_callbacks_del(rp->object, ed);
2024
                  evas_object_del(rp->object);
2025
                  rp->object = NULL;
2026
               }
2027

2028
             /* Cleanup optional part. */
2029
             free(rp->drag);
2030
             rp->drag = NULL;
2031
             free(rp->param1.set);
2032
             rp->param1.set = NULL;
2033

2034
             if (rp->param2)
2035
               {
2036
                  free(rp->param2->set);
2037
                  rp->param2->set = NULL;
2038
#ifdef EDJE_CALC_CACHE
2039
                  _edje_calc_params_clear(&(rp->param2->p));
2040
#endif
2041
               }
2042
             eina_mempool_free(_edje_real_part_state_mp, rp->param2);
2043

2044
             if (rp->custom)
2045
               {
2046
                  free(rp->custom->set);
2047
                  rp->custom->set = NULL;
2048
#ifdef EDJE_CALC_CACHE
2049
                  _edje_calc_params_clear(&(rp->custom->p));
2050
#endif
2051
               }
2052
             eina_mempool_free(_edje_real_part_state_mp, rp->custom);
2053

2054
             if (rp->current)
2055
               {
2056
#ifdef EDJE_CALC_CACHE
2057
                  _edje_calc_params_clear(rp->current);
2058
#endif
2059
                  free(rp->current);
2060
                  rp->current = NULL;
2061
               }
2062
             _edje_unref(ed);
2063
#ifdef EDJE_CALC_CACHE
2064
             _edje_calc_params_clear(&(rp->param1.p));
2065
#endif
2066
             eina_mempool_free(_edje_real_part_mp, rp);
2067
             ed->table_parts[i] = NULL;
2068
          }
2069
     }
2070
   if ((ed->file) && (ed->collection))
2071
     {
2072
        Edje_Part *ep;
2073
        unsigned int i;
2074

2075
        for (i = 0; i < ed->collection->parts_count; ++i)
2076
          {
2077
             ep = ed->collection->parts[i];
2078

2079
             _edje_textblock_styles_del(ed, ep);
2080
             _edje_text_part_on_del(ed, ep);
2081
             _edje_color_class_on_del(ed, ep);
2082
          }
2083
        _edje_object_textblock_styles_cache_cleanup(ed);
2084

2085
        _edje_cache_coll_unref(ed->file, ed->collection);
2086
        ed->collection = NULL;
2087
     }
2088
   if (ed->file)
2089
     {
2090
        _edje_cache_file_unref(ed->file);
2091
        ed->file = NULL;
2092
     }
2093

2094
   // Cleanup all animator
2095
   if (ed->actions)
2096
     {
2097
        Edje_Running_Program *runp;
2098

2099
        EINA_LIST_FREE(ed->actions, runp)
2100
          free(runp);
2101
     }
2102
   efl_event_callback_del(ed->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _edje_timer_cb, ed);
2103
   ecore_animator_del(ed->animator);
2104
   ed->animator = NULL;
2105

2106
   if (ed->pending_actions)
2107
     {
2108
        Edje_Pending_Program *pp;
2109

2110
        EINA_LIST_FREE(ed->pending_actions, pp)
2111
          {
2112
             ecore_timer_del(pp->timer);
2113
             pp->timer = NULL;
2114
             free(pp);
2115
          }
2116
     }
2117

2118
   if (ed->seats)
2119
     {
2120
        Edje_Seat *seat;
2121

2122
        EINA_LIST_FREE(ed->seats, seat)
2123
          {
2124
             eina_stringshare_del(seat->name);
2125
             free(seat);
2126
          }
2127
        ed->seats_count = 0;
2128
     }
2129

2130
   if (ed->L) _edje_lua2_script_shutdown(ed);
2131
   while (ed->subobjs)
2132
     _edje_subobj_unregister(ed, ed->subobjs->data);
2133
   if (ed->table_parts) free(ed->table_parts);
2134
   ed->table_parts = NULL;
2135
   ed->table_parts_size = 0;
2136
   if (tev)
2137
     {
2138
        evas_event_thaw(tev);
2139
        evas_event_thaw_eval(tev);
2140
     }
2141
}
2142

2143
void
2144
_edje_file_free(Edje_File *edf)
2145
{
2146
   Edje_Color_Tree_Node *ectn;
2147
   Edje_Color_Class *ecc;
2148
   Edje_Text_Class *etc;
2149
   Edje_Size_Class *esc;
2150

2151
#define HASH_FREE(Hash)            \
2152
  if (Hash) eina_hash_free(Hash);  \
2153
  Hash = NULL;
2154

2155
   /* Clean cache before cleaning memory pool */
2156
   if (edf->collection_cache) _edje_cache_coll_flush(edf);
2157

2158
   HASH_FREE(edf->fonts);
2159
   HASH_FREE(edf->collection);
2160
   HASH_FREE(edf->data);
2161
   HASH_FREE(edf->image_id_hash);
2162

2163
   if (edf->requires_count)
2164
     {
2165
        unsigned int i;
2166

2167
        for (i = 0; i < edf->requires_count; i++)
2168
          eina_stringshare_del(edf->requires[i]);
2169
        free(edf->requires);
2170
     }
2171

2172
   if (edf->image_dir)
2173
     {
2174
        unsigned int i;
2175

2176
        if (edf->free_strings)
2177
          {
2178
             for (i = 0; i < edf->image_dir->entries_count; ++i)
2179
               eina_stringshare_del(edf->image_dir->entries[i].entry);
2180

2181
             for (i = 0; i < edf->image_dir->vectors_count; ++i)
2182
               eina_stringshare_del(edf->image_dir->vectors[i].entry);
2183
          }
2184

2185
        /* Sets have been added after edje received eet dictionary support */
2186
        for (i = 0; i < edf->image_dir->sets_count; ++i)
2187
          {
2188
             Edje_Image_Directory_Set_Entry *se;
2189

2190
             EINA_LIST_FREE(edf->image_dir->sets[i].entries, se)
2191
               free(se);
2192
          }
2193

2194
        free(edf->image_dir->entries);
2195
        free(edf->image_dir->sets);
2196
        free(edf->image_dir->vectors);
2197
        free(edf->image_dir);
2198
     }
2199
   if (edf->sound_dir)
2200
     {
2201
        unsigned int i;
2202

2203
        if (edf->free_strings)
2204
          {
2205
             for (i = 0; i < edf->sound_dir->samples_count; ++i)
2206
               {
2207
                  eina_stringshare_del(edf->sound_dir->samples[i].name);
2208
                  eina_stringshare_del(edf->sound_dir->samples[i].snd_src);
2209
               }
2210

2211
             for (i = 0; i < edf->sound_dir->tones_count; ++i)
2212
               eina_stringshare_del(edf->sound_dir->tones[i].name);
2213
          }
2214
        free(edf->sound_dir->samples);
2215
        free(edf->sound_dir->tones);
2216
        free(edf->sound_dir);
2217
     }
2218

2219
   if (edf->vibration_dir)
2220
     {
2221
        unsigned int i;
2222

2223
        if (edf->free_strings)
2224
          {
2225
             for (i = 0; i < edf->vibration_dir->samples_count; ++i)
2226
               {
2227
                  eina_stringshare_del(edf->vibration_dir->samples[i].name);
2228
                  eina_stringshare_del(edf->vibration_dir->samples[i].src);
2229
               }
2230
          }
2231
        free(edf->vibration_dir->samples);
2232
        free(edf->vibration_dir);
2233
     }
2234

2235
   if (edf->filter_dir)
2236
     {
2237
        int i;
2238

2239
        if (edf->free_strings)
2240
          {
2241
             for (i = 0; i < edf->filter_dir->filters_count; ++i)
2242
               {
2243
                  eina_stringshare_del(edf->filter_dir->filters[i].name);
2244
                  eina_stringshare_del(edf->filter_dir->filters[i].script);
2245
               }
2246
          }
2247
        free(edf->filter_dir->filters);
2248
        free(edf->filter_dir);
2249
     }
2250

2251
   if (edf->mo_dir)
2252
     {
2253
        unsigned int i;
2254
        if (edf->free_strings)
2255
          {
2256
             for (i = 0; i < edf->mo_dir->mo_entries_count; ++i)
2257
               {
2258
                  eina_stringshare_del(edf->mo_dir->mo_entries[i].locale);
2259
                  eina_stringshare_del(edf->mo_dir->mo_entries[i].mo_src);
2260
               }
2261
          }
2262
        free(edf->mo_dir->mo_entries);
2263
        free(edf->mo_dir);
2264
     }
2265

2266
   if (edf->external_dir)
2267
     {
2268
        if (edf->external_dir->entries) free(edf->external_dir->entries);
2269
        free(edf->external_dir);
2270
     }
2271

2272
   eina_hash_free(edf->color_tree_hash);
2273
   EINA_LIST_FREE(edf->color_tree, ectn)
2274
     {
2275
        if (edf->free_strings && ectn->name) eina_stringshare_del(ectn->name);
2276
        eina_list_free(ectn->color_classes);
2277
        free(ectn);
2278
     }
2279

2280
   eina_hash_free(edf->color_hash);
2281
   EINA_LIST_FREE(edf->color_classes, ecc)
2282
     {
2283
        if (edf->free_strings && ecc->name) eina_stringshare_del(ecc->name);
2284
        if (edf->free_strings) eina_stringshare_del(ecc->desc);
2285
        free(ecc);
2286
     }
2287

2288
   eina_hash_free(edf->text_hash);
2289
   EINA_LIST_FREE(edf->text_classes, etc)
2290
     {
2291
        if (edf->free_strings)
2292
          {
2293
             if (etc->name) eina_stringshare_del(etc->name);
2294
             if (etc->font) eina_stringshare_del(etc->font);
2295
          }
2296
        free(etc);
2297
     }
2298

2299
   eina_hash_free(edf->size_hash);
2300
   EINA_LIST_FREE(edf->size_classes, esc)
2301
     {
2302
        if (edf->free_strings && esc->name) eina_stringshare_del(esc->name);
2303
        free(esc);
2304
     }
2305

2306
   if (edf->collection_patterns) edje_match_patterns_free(edf->collection_patterns);
2307
   if (edf->path) eina_stringshare_del(edf->path);
2308
   if (edf->free_strings && edf->compiler) eina_stringshare_del(edf->compiler);
2309
   if (edf->free_strings) eina_stringshare_del(edf->id);
2310
   eina_hash_free(edf->style_hash);
2311
   _edje_file_textblock_style_cleanup(edf);
2312
   if (edf->ef) eet_close(edf->ef);
2313
   if (edf->f) eina_file_close(edf->f);  // close matching open (in _edje_file_open) OK
2314
   free(edf);
2315
}
2316

2317
static void
2318
_edje_program_free(Edje_Program *pr, Eina_Bool free_strings)
2319
{
2320
   Edje_Program_Target *prt;
2321
   Edje_Program_After *pa;
2322

2323
   if (free_strings)
2324
     {
2325
        if (pr->name) eina_stringshare_del(pr->name);
2326
        if (pr->signal) eina_stringshare_del(pr->signal);
2327
        if (pr->source) eina_stringshare_del(pr->source);
2328
        if (pr->filter.part) eina_stringshare_del(pr->filter.part);
2329
        if (pr->filter.state) eina_stringshare_del(pr->filter.state);
2330
        if (pr->state) eina_stringshare_del(pr->state);
2331
        if (pr->state2) eina_stringshare_del(pr->state2);
2332
        if (pr->sample_name) eina_stringshare_del(pr->sample_name);
2333
        if (pr->tone_name) eina_stringshare_del(pr->tone_name);
2334
        if (pr->seat) eina_stringshare_del(pr->seat);
2335
     }
2336
   EINA_LIST_FREE(pr->targets, prt)
2337
     free(prt);
2338
   EINA_LIST_FREE(pr->after, pa)
2339
     free(pa);
2340
   free(pr);
2341
}
2342

2343
void
2344
_edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec, Edje_Part_Collection_Directory_Entry *ce)
2345
{
2346
   unsigned int i;
2347

2348
   _edje_embryo_script_shutdown(ec);
2349

2350
#define EDJE_LOAD_PROGRAM_FREE(Array, Ec, It, FreeStrings)    \
2351
  for (It = 0; It < Ec->programs.Array##_count; ++It)         \
2352
    _edje_program_free(Ec->programs.Array[It], FreeStrings);  \
2353
  free(Ec->programs.Array);
2354

2355
   EDJE_LOAD_PROGRAM_FREE(fnmatch, ec, i, edf->free_strings);
2356
   EDJE_LOAD_PROGRAM_FREE(strcmp, ec, i, edf->free_strings);
2357
   EDJE_LOAD_PROGRAM_FREE(strncmp, ec, i, edf->free_strings);
2358
   EDJE_LOAD_PROGRAM_FREE(strrncmp, ec, i, edf->free_strings);
2359
   EDJE_LOAD_PROGRAM_FREE(nocmp, ec, i, edf->free_strings);
2360

2361
   for (i = 0; i < ec->parts_count; ++i)
2362
     {
2363
        Edje_Part *ep;
2364
        unsigned int j;
2365

2366
        ep = ec->parts[i];
2367

2368
        if (edf->free_strings && ep->name) eina_stringshare_del(ep->name);
2369
        if (ep->default_desc)
2370
          {
2371
             _edje_collection_free_part_description_clean(ep->type, ep->default_desc, edf->free_strings);
2372
             ep->default_desc = NULL;
2373
          }
2374
        for (j = 0; j < ep->other.desc_count; ++j)
2375
          _edje_collection_free_part_description_clean(ep->type, ep->other.desc[j], edf->free_strings);
2376

2377
        free(ep->other.desc);
2378
        /* Alloc for RTL objects in edje_calc.c:_edje_part_description_find() */
2379
        if (ep->other.desc_rtl)
2380
          free(ep->other.desc_rtl);
2381

2382
        for (j = 0; j < ep->items_count; ++j)
2383
          free(ep->items[j]);
2384
        free(ep->items);
2385

2386
        for (j = 0; j < ep->allowed_seats_count; ++j)
2387
          {
2388
             if (edf->free_strings)
2389
               eina_stringshare_del(ep->allowed_seats[j]->name);
2390
             free(ep->allowed_seats[j]);
2391
          }
2392
        free(ep->allowed_seats);
2393
        // technically need this - but we ASSUME we use "one_big" so everything gets
2394
        // freed in one go lower down when we del the mempool... but what if pool goes
2395
        // "over"?
2396
        eina_mempool_free(ce->mp->mp.part, ep);
2397
     }
2398
   free(ec->parts);
2399
   ec->parts = NULL;
2400

2401
   if (ec->data)
2402
     {
2403
        Eina_Iterator *it;
2404
        Edje_String *es;
2405

2406
        it = eina_hash_iterator_data_new(ec->data);
2407
        EINA_ITERATOR_FOREACH(it, es)
2408
          free(es);
2409
        eina_iterator_free(it);
2410

2411
        eina_hash_free(ec->data);
2412
     }
2413
#ifdef EDJE_PROGRAM_CACHE
2414
   if (ec->prog_cache.no_matches) eina_hash_free(ec->prog_cache.no_matches);
2415
   if (ec->prog_cache.matches)
2416
     {
2417
        eina_hash_foreach(ec->prog_cache.matches,
2418
                          _edje_collection_free_prog_cache_matches_free_cb,
2419
                          NULL);
2420
        eina_hash_free(ec->prog_cache.matches);
2421
     }
2422
#endif
2423
   _edje_programs_patterns_clean(ec);
2424
   if (ec->patterns.table_programs) free(ec->patterns.table_programs);
2425
   ec->patterns.table_programs = NULL;
2426
   ec->patterns.table_programs_size = 0;
2427

2428
   if (ec->script) embryo_program_free(ec->script);
2429
   _edje_lua2_script_unload(ec);
2430

2431
   if (ec->limits.parts) free(ec->limits.parts);
2432

2433
   eina_hash_free(ec->alias);
2434
   eina_hash_free(ec->aliased);
2435

2436
   /* Destroy all part and description. */
2437
   edje_cache_emp_free(ce);
2438
   free(ec);
2439
}
2440

2441
void
2442
_edje_collection_free_part_description_clean(int type, Edje_Part_Description_Common *desc, Eina_Bool free_strings)
2443
{
2444
   unsigned int i;
2445

2446
   if (free_strings && desc->color_class) eina_stringshare_del(desc->color_class);
2447
   //clean the map colors
2448
   if (desc->map.colors)
2449
     {
2450
        for (i = 0; i < desc->map.colors_count; i++)
2451
          free(desc->map.colors[i]);
2452
        free(desc->map.colors);
2453
     }
2454

2455
   switch (type)
2456
     {
2457
      case EDJE_PART_TYPE_IMAGE:
2458
      {
2459
         Edje_Part_Description_Image *img;
2460

2461
         img = (Edje_Part_Description_Image *)desc;
2462

2463
         for (i = 0; i < img->image.tweens_count; ++i)
2464
           free(img->image.tweens[i]);
2465
         free(img->image.tweens);
2466
         break;
2467
      }
2468

2469
      case EDJE_PART_TYPE_EXTERNAL:
2470
      {
2471
         Edje_Part_Description_External *external;
2472

2473
         external = (Edje_Part_Description_External *)desc;
2474

2475
         if (external->external_params)
2476
           _edje_external_params_free(external->external_params, free_strings);
2477
         break;
2478
      }
2479

2480
      case EDJE_PART_TYPE_TEXT:
2481
      case EDJE_PART_TYPE_TEXTBLOCK:
2482
        if (free_strings)
2483
          {
2484
             Edje_Part_Description_Text *text;
2485

2486
             text = (Edje_Part_Description_Text *)desc;
2487

2488
             eina_stringshare_del(text->text.text.str);
2489
             eina_stringshare_del(text->text.domain);
2490
             eina_stringshare_del(text->text.text_class);
2491
             eina_stringshare_del(text->text.style.str);
2492
             eina_stringshare_del(text->text.font.str);
2493
          }
2494
        break;
2495
     }
2496
}
2497

2498
void
2499
_edje_collection_free_part_description_free(int type,
2500
                                            Edje_Part_Description_Common *desc,
2501
                                            Edje_Part_Collection_Directory_Entry *ce,
2502
                                            Eina_Bool free_strings)
2503
{
2504
#define FREE_POOL(Type, Ce, Desc)                                     \
2505
case EDJE_PART_TYPE_##Type: eina_mempool_free(ce->mp->mp.Type, Desc); \
2506
  ce->count.Type--;                                                   \
2507
  break;
2508

2509
   _edje_collection_free_part_description_clean(type, desc, free_strings);
2510

2511
   switch (type)
2512
     {
2513
        FREE_POOL(RECTANGLE, ce, desc);
2514
        FREE_POOL(TEXT, ce, desc);
2515
        FREE_POOL(IMAGE, ce, desc);
2516
        FREE_POOL(PROXY, ce, desc);
2517
        FREE_POOL(SWALLOW, ce, desc);
2518
        FREE_POOL(TEXTBLOCK, ce, desc);
2519
        FREE_POOL(GROUP, ce, desc);
2520
        FREE_POOL(BOX, ce, desc);
2521
        FREE_POOL(TABLE, ce, desc);
2522
        FREE_POOL(EXTERNAL, ce, desc);
2523
        FREE_POOL(SNAPSHOT, ce, desc);
2524
        FREE_POOL(SPACER, ce, desc);
2525
     }
2526
}
2527

2528
#ifdef EDJE_PROGRAM_CACHE
2529
static Eina_Bool
2530
_edje_collection_free_prog_cache_matches_free_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
2531
{
2532
   eina_list_free((Eina_List *)data);
2533
   return EINA_TRUE;
2534
   key = NULL;
2535
   hash = NULL;
2536
   fdata = NULL;
2537
}
2538

2539
#endif
2540

2541
static void
2542
_edje_object_pack_item_hints_set(Evas_Object *obj, Edje_Pack_Element *it)
2543
{
2544
   Evas_Coord w = 0, h = 0, minw, minh;
2545
   Evas_Aspect_Control mode = EVAS_ASPECT_CONTROL_NONE;
2546

2547
   minw = it->min.w;
2548
   minh = it->min.h;
2549

2550
   if ((minw <= 0) && (minh <= 0))
2551
     {
2552
        edje_object_size_min_get(obj, &w, &h);
2553
        if ((w <= 0) && (h <= 0))
2554
          edje_object_size_min_calc(obj, &w, &h);
2555
     }
2556
   else
2557
     {
2558
        w = minw;
2559
        h = minh;
2560
     }
2561
   if (((minw <= 0) && (minh <= 0)) && ((w > 0) || (h > 0)))
2562
     evas_object_size_hint_min_set(obj, w, h);
2563
   else
2564
     evas_object_size_hint_min_set(obj, minw, minh);
2565

2566
   evas_object_size_hint_request_set(obj, it->prefer.w, it->prefer.h);
2567
   evas_object_size_hint_max_set(obj, it->max.w, it->max.h);
2568
   evas_object_size_hint_padding_set(obj, it->padding.l, it->padding.r, it->padding.t, it->padding.b);
2569
   evas_object_size_hint_align_set(obj, TO_DOUBLE(it->align.x), TO_DOUBLE(it->align.y));
2570
   evas_object_size_hint_weight_set(obj, TO_DOUBLE(it->weight.x), TO_DOUBLE(it->weight.y));
2571

2572
   switch (it->aspect.mode)
2573
     {
2574
      case EDJE_ASPECT_CONTROL_NONE: mode = EVAS_ASPECT_CONTROL_NONE; break;
2575

2576
      case EDJE_ASPECT_CONTROL_NEITHER: mode = EVAS_ASPECT_CONTROL_NEITHER; break;
2577

2578
      case EDJE_ASPECT_CONTROL_HORIZONTAL: mode = EVAS_ASPECT_CONTROL_HORIZONTAL; break;
2579

2580
      case EDJE_ASPECT_CONTROL_VERTICAL: mode = EVAS_ASPECT_CONTROL_VERTICAL; break;
2581

2582
      case EDJE_ASPECT_CONTROL_BOTH: mode = EVAS_ASPECT_CONTROL_BOTH; break;
2583
     }
2584
   evas_object_size_hint_aspect_set(obj, mode, it->aspect.w, it->aspect.h);
2585

2586
   evas_object_resize(obj, w, h);
2587
}
2588

2589
const char *
2590
_edje_find_alias(Eina_Hash *aliased, char *src, int *length)
2591
{
2592
   const char *alias;
2593
   char *search;
2594

2595
   *length = strlen(src);
2596
   if (*length == 0) return NULL;
2597

2598
   alias = eina_hash_find(aliased, src);
2599
   if (alias) return alias;
2600

2601
   search = strrchr(src, EDJE_PART_PATH_SEPARATOR);
2602
   if (search == NULL) return NULL;
2603

2604
   *search = '\0';
2605
   alias = _edje_find_alias(aliased, src, length);
2606
   *search = EDJE_PART_PATH_SEPARATOR;
2607

2608
   return alias;
2609
}
2610

2611
static void
2612
_cb_signal_repeat(void *data, Evas_Object *obj, const char *sig, const char *source)
2613
{
2614
   Edje_Pack_Element *pack_it;
2615
   Evas_Object *parent;
2616
   Edje *ed;
2617
   Edje *ed_parent;
2618
   char new_src[4096];          /* XXX is this max reasonable? */
2619
   size_t length_parent = 0;
2620
   size_t length_index = 0;
2621
   size_t length_source;
2622
   int i = 0;
2623
   const char *alias = NULL;
2624
   const char *name = NULL;
2625
   Edje_Message_Signal emsg;
2626

2627
   parent = data;
2628
   ed = _edje_fetch(obj);
2629
   if (!ed) return;
2630

2631
   pack_it = evas_object_data_get(obj, "\377 edje.box_item");
2632
   if (!pack_it) pack_it = evas_object_data_get(obj, "\377 edje.table_item");
2633
   name = evas_object_name_get(obj);
2634

2635
   if (pack_it)
2636
     {
2637
        if (!name) name = pack_it->name;
2638
        if (!name)
2639
          {
2640
             Eina_Iterator *it = NULL;
2641
             Evas_Object *o;
2642

2643
             if (pack_it->parent->part->type == EDJE_PART_TYPE_BOX)
2644
               {
2645
                  it = evas_object_box_iterator_new(pack_it->parent->object);
2646
               }
2647
             else if (pack_it->parent->part->type == EDJE_PART_TYPE_TABLE)
2648
               {
2649
                  it = evas_object_table_iterator_new(pack_it->parent->object);
2650
               }
2651

2652
             EINA_ITERATOR_FOREACH(it, o)
2653
               {
2654
                  if (o == obj) break;
2655
                  i++;
2656
               }
2657
             eina_iterator_free(it);
2658

2659
             length_index = 12;
2660
          }
2661
        else
2662
          {
2663
             length_index = strlen(name) + 2;
2664
          }
2665
     }
2666

2667
   /* Replace snprint("%s%c%s") == memcpy + *new_src + memcat */
2668
   if (ed->parent)
2669
     length_parent = strlen(ed->parent);
2670
   length_source = strlen(source);
2671
   if (length_source + length_parent + 2 + length_index > sizeof(new_src))
2672
     return;
2673

2674
   if (ed->parent)
2675
     memcpy(new_src, ed->parent, length_parent);
2676
   if (ed->parent && length_index)
2677
     {
2678
        new_src[length_parent++] = EDJE_PART_PATH_SEPARATOR_INDEXL;
2679
        if ((pack_it->parent->part->type == EDJE_PART_TYPE_BOX) ||
2680
            (!name && (pack_it->parent->part->type == EDJE_PART_TYPE_TABLE)))
2681
          length_parent += eina_convert_itoa(i, new_src + length_parent);
2682
        else if (name)
2683
          {
2684
             memcpy(new_src + length_parent, name, length_index - 2);
2685
             length_parent += length_index - 2;
2686
          }
2687
        new_src[length_parent++] = EDJE_PART_PATH_SEPARATOR_INDEXR;
2688
     }
2689

2690
   new_src[length_parent] = EDJE_PART_PATH_SEPARATOR;
2691
   memcpy(new_src + length_parent + 1, source, length_source + 1);
2692

2693
   /* Handle alias renaming */
2694
   ed_parent = _edje_fetch(parent);
2695
   if (ed_parent && ed_parent->collection && ed_parent->collection->aliased)
2696
     {
2697
        int length;
2698

2699
        alias = _edje_find_alias(ed_parent->collection->aliased, new_src, &length);
2700

2701
        if (alias)
2702
          {
2703
             int origin;
2704

2705
             /* Add back the end of the source */
2706
             origin = strlen(new_src);
2707
             length++;  /* Remove the trailing ':' from the count */
2708
             if (origin > length)
2709
               {
2710
                  char *tmp;
2711
                  size_t alias_length;
2712

2713
                  alias_length = strlen(alias);
2714
                  tmp = alloca(alias_length + origin - length + 2);
2715
                  memcpy(tmp, alias, alias_length);
2716
                  tmp[alias_length] = EDJE_PART_PATH_SEPARATOR;
2717
                  memcpy(tmp + alias_length + 1, new_src + length, origin - length + 1);
2718

2719
                  alias = tmp;
2720
               }
2721
          }
2722
     }
2723

2724
   emsg.sig = sig;
2725
   emsg.src = alias ? alias : new_src;
2726
   emsg.data = NULL;
2727
   if (ed_parent)
2728
     _edje_util_message_send(ed_parent, EDJE_QUEUE_SCRIPT,
2729
                             EDJE_MESSAGE_SIGNAL, 0, &emsg);
2730
}
2731

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.