1b5a1374aa2527be4564af2c307acc5607ab23f5
[framework/uifw/edje.git] / src / bin / edje_cc_out.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <stddef.h>
8 #else
9 # ifdef HAVE_STDLIB_H
10 #  include <stdlib.h>
11 # endif
12 #endif
13 #ifdef HAVE_ALLOCA_H
14 # include <alloca.h>
15 #elif !defined alloca
16 # ifdef __GNUC__
17 #  define alloca __builtin_alloca
18 # elif defined _AIX
19 #  define alloca __alloca
20 # elif defined _MSC_VER
21 #  include <malloc.h>
22 #  define alloca _alloca
23 # elif !defined HAVE_ALLOCA
24 #  ifdef  __cplusplus
25 extern "C"
26 #  endif
27 void *alloca (size_t);
28 # endif
29 #endif
30
31 #include <string.h>
32 #include <limits.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35
36 #include <Ecore_Evas.h>
37
38 #include "edje_cc.h"
39 #include "edje_convert.h"
40 #include "edje_multisense_convert.h"
41
42 #include <lua.h>
43 #include <lauxlib.h>
44
45 typedef struct _External_Lookup External_Lookup;
46 typedef struct _Part_Lookup Part_Lookup;
47 typedef struct _Program_Lookup Program_Lookup;
48 typedef struct _Group_Lookup Group_Lookup;
49 typedef struct _Image_Lookup Image_Lookup;
50 typedef struct _Slave_Lookup Slave_Lookup;
51 typedef struct _Code_Lookup Code_Lookup;
52
53
54 struct _External_Lookup
55 {
56    char *name;
57 };
58
59 struct _Part_Lookup
60 {
61    Edje_Part_Collection *pc;
62    char *name;
63    int *dest;
64 };
65
66 struct _Program_Lookup
67 {
68    Edje_Part_Collection *pc;
69
70    union
71    {
72       char *name;
73       Edje_Program *ep;
74    } u;
75
76    int *dest;
77
78    Eina_Bool anonymous : 1;
79 };
80
81 struct _Group_Lookup
82 {
83    char *name;
84    Edje_Part *part;
85 };
86
87 struct _String_Lookup
88 {
89    char *name;
90    int *dest;
91 };
92
93 struct _Image_Lookup
94 {
95    char *name;
96    int *dest;
97    Eina_Bool *set;
98 };
99
100 struct _Slave_Lookup
101 {
102    int *master;
103    int *slave;
104 };
105
106 struct _Code_Lookup
107 {
108    char *ptr;
109    int   len;
110    int   val;
111    Eina_Bool set;
112 };
113
114 typedef struct _Script_Lua_Writer Script_Lua_Writer;
115
116 struct _Script_Lua_Writer
117 {
118    char *buf;
119    int size;
120 };
121
122 typedef struct _Script_Write Script_Write;;
123 typedef struct _Head_Write Head_Write;
124 typedef struct _Fonts_Write Fonts_Write;
125 typedef struct _Image_Write Image_Write;
126 typedef struct _Sound_Write Sound_Write;
127 typedef struct _Group_Write Group_Write;
128
129 struct _Script_Write
130 {
131    Eet_File *ef;
132    Code *cd;
133    int i;
134    Ecore_Exe *exe;
135    int tmpn_fd, tmpo_fd;
136    char tmpn[PATH_MAX];
137    char tmpo[PATH_MAX];
138    char *errstr;
139 };
140
141 struct _Head_Write
142 {
143    Eet_File *ef;
144    char *errstr;
145 };
146
147 struct _Fonts_Write
148 {
149    Eet_File *ef;
150    Font *fn;
151    char *errstr;
152 };
153
154 struct _Image_Write
155 {
156    Eet_File *ef;
157    Edje_Image_Directory_Entry *img;
158    Evas_Object *im;
159    int w, h;
160    int alpha;
161    unsigned int *data;
162    char *path;
163    char *errstr;
164 };
165
166 struct _Sound_Write
167 {
168    Eet_File *ef;
169    Edje_Sound_Sample *sample;
170    int i;
171 };
172
173 struct _Group_Write
174 {
175    Eet_File *ef;
176    Edje_Part_Collection *pc;
177    char *errstr;
178 };
179
180 static int pending_threads = 0;
181
182 static void data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char* ptr, int len));
183
184 Edje_File *edje_file = NULL;
185 Eina_List *edje_collections = NULL;
186 Eina_Hash *edje_collections_lookup = NULL;
187 Eina_List *externals = NULL;
188 Eina_List *fonts = NULL;
189 Eina_List *codes = NULL;
190 Eina_List *code_lookups = NULL;
191 Eina_List *aliases = NULL;
192
193 static Eet_Data_Descriptor *edd_edje_file = NULL;
194 static Eet_Data_Descriptor *edd_edje_part_collection = NULL;
195
196 static Eina_List *program_lookups = NULL;
197 static Eina_List *group_lookups = NULL;
198 static Eina_List *image_lookups = NULL;
199 static Eina_List *part_slave_lookups = NULL;
200 static Eina_List *image_slave_lookups= NULL;
201
202 static Eina_Hash *part_dest_lookup = NULL;
203 static Eina_Hash *part_pc_dest_lookup = NULL;
204
205 void
206 error_and_abort(Eet_File *ef __UNUSED__, const char *fmt, ...)
207 {
208    va_list ap;
209
210    va_start(ap, fmt);
211    eina_log_vprint(_edje_cc_log_dom, EINA_LOG_LEVEL_CRITICAL,
212                    "unknown", "unknown", 0, fmt, ap);
213    va_end(ap);
214    unlink(file_out);
215    if (watchfile) unlink(watchfile);
216    exit(-1);
217 }
218
219 static unsigned int
220 _double_pointer_key_length(const void *key __UNUSED__)
221 {
222    return sizeof (void*) * 2;
223 }
224
225 static int
226 _double_pointer_key_cmp(const void *key1, int key1_length,
227                         const void *key2, int key2_length __UNUSED__)
228 {
229    return memcmp(key1, key2, key1_length);
230 }
231
232 static int
233 _double_pointer_key_hash(const void *key, int key_length __UNUSED__)
234 {
235 #ifdef __LP64__
236    return eina_hash_int64(key, sizeof (void*)) ^
237      eina_hash_int64((void*)(((unsigned char*) key) + sizeof (void*)), sizeof (void*));
238 #else
239    /* double 32 bits pointer is ... 64bits awesome ! */
240    return eina_hash_int64(key, key_length);
241 #endif
242 }
243
244 static void
245 data_part_lookup_free(Part_Lookup *pl)
246 {
247    free(pl->name);
248    free(pl);
249 }
250
251 void
252 data_setup(void)
253 {
254    edd_edje_file = _edje_edd_edje_file;
255    edd_edje_part_collection = _edje_edd_edje_part_collection;
256
257    part_dest_lookup = eina_hash_pointer_new(EINA_FREE_CB(eina_list_free));
258    part_pc_dest_lookup = eina_hash_new(EINA_KEY_LENGTH(_double_pointer_key_length),
259                                        EINA_KEY_CMP(_double_pointer_key_cmp),
260                                        EINA_KEY_HASH(_double_pointer_key_hash),
261                                        EINA_FREE_CB(data_part_lookup_free),
262                                        8);
263 }
264
265 static void
266 check_image_part_desc(Edje_Part_Collection *pc, Edje_Part *ep,
267                       Edje_Part_Description_Image *epd, Eet_File *ef)
268 {
269    unsigned int i;
270
271    if (epd->image.id == -1 && epd->common.visible)
272      WRN("Collection %s(%i): image attributes missing for "
273          "part \"%s\", description \"%s\" %f",
274          pc->part, pc->id, ep->name, epd->common.state.name, epd->common.state.value);
275
276    for (i = 0; i < epd->image.tweens_count; ++i)
277      {
278         if (epd->image.tweens[i]->id == -1)
279           error_and_abort(ef, "Collection %i: tween image id missing for "
280                           "part \"%s\", description \"%s\" %f",
281                           pc->id, ep->name, epd->common.state.name, epd->common.state.value);
282     }
283 }
284
285 static void
286 check_packed_items(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
287 {
288    unsigned int i;
289
290    for (i = 0; i < ep->items_count; ++i)
291      {
292         if (ep->items[i]->type == EDJE_PART_TYPE_GROUP && !ep->items[i]->source)
293           error_and_abort(ef, "Collection %i: missing source on packed item "
294                           "of type GROUP in part \"%s\"",
295                           pc->id, ep->name);
296         if (ep->type == EDJE_PART_TYPE_TABLE && (ep->items[i]->col < 0 || ep->items[i]->row < 0))
297           error_and_abort(ef, "Collection %i: missing col/row on packed item "
298                           "for part \"%s\" of type TABLE",
299                           pc->id, ep->name);
300      }
301 }
302
303 static void
304 check_nameless_state(Edje_Part_Collection *pc, Edje_Part *ep, Edje_Part_Description_Common *ed, Eet_File *ef)
305 {
306    if (!ed->state.name)
307       error_and_abort(ef, "Collection %i: description with state missing on part \"%s\"",
308                       pc->id, ep->name);
309 }
310
311 static void
312 check_part(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
313 {
314    unsigned int i;
315    /* FIXME: check image set and sort them. */
316    if (!ep->default_desc)
317      error_and_abort(ef, "Collection %i: default description missing "
318                      "for part \"%s\"", pc->id, ep->name);
319
320    for (i = 0; i < ep->other.desc_count; ++i)
321      check_nameless_state(pc, ep, ep->other.desc[i], ef);
322
323    if (ep->type == EDJE_PART_TYPE_IMAGE)
324      {
325         check_image_part_desc(pc, ep, (Edje_Part_Description_Image*) ep->default_desc, ef);
326
327         for (i = 0; i < ep->other.desc_count; ++i)
328           check_image_part_desc (pc, ep, (Edje_Part_Description_Image*) ep->other.desc[i], ef);
329      }
330    else if ((ep->type == EDJE_PART_TYPE_BOX) ||
331             (ep->type == EDJE_PART_TYPE_TABLE))
332      check_packed_items(pc, ep, ef);
333
334    /* FIXME: When mask are supported remove this check */
335    if (ep->clip_to_id != -1 &&
336        pc->parts[ep->clip_to_id]->type != EDJE_PART_TYPE_RECTANGLE)
337      error_and_abort(ef, "Collection %i: clip_to point to a non RECT part '%s' !",
338                      pc->id, pc->parts[ep->clip_to_id]->name);
339 }
340
341 static void
342 check_program(Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef)
343 {
344    switch (ep->action)
345      {
346       case EDJE_ACTION_TYPE_STATE_SET:
347       case EDJE_ACTION_TYPE_ACTION_STOP:
348       case EDJE_ACTION_TYPE_DRAG_VAL_SET:
349       case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
350       case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
351          if (!ep->targets)
352            error_and_abort(ef, "Collection %i: target missing in program "
353                            "\"%s\"", pc->id, ep->name);
354          break;
355       default:
356          break;
357      }
358 }
359
360 static void
361 data_thread_head(void *data, Ecore_Thread *thread __UNUSED__)
362 {
363    Head_Write *hw = data;
364    int bytes = 0;
365    char buf[PATH_MAX];
366
367    if (edje_file)
368      {
369         if (edje_file->collection)
370           {
371              Edje_Part_Collection_Directory_Entry *ce;
372
373              EINA_LIST_FREE(aliases, ce)
374                {
375                   Edje_Part_Collection_Directory_Entry *sce;
376
377                   if (!ce->entry)
378                     {
379                        snprintf(buf, sizeof(buf),
380                                 "Collection %i: name missing.", ce->id);
381                        hw->errstr = strdup(buf);
382                        return;
383                     }
384
385                   sce = eina_hash_find(edje_collections_lookup, &ce->id);
386                   if (sce)
387                     {
388                        memcpy(&ce->count, &sce->count, sizeof (ce->count));
389                     }
390                   else
391                     {
392                        snprintf(buf, sizeof(buf),
393                                 "Collection %s (%i) can't find an correct alias.",
394                                 ce->entry, ce->id);
395                        hw->errstr = strdup(buf);
396                        return;
397                     }
398
399                   eina_hash_direct_add(edje_file->collection, ce->entry, ce);
400                }
401           }
402         bytes = eet_data_write(hw->ef, edd_edje_file, "edje/file", edje_file,
403                                compress_mode);
404         if (bytes <= 0)
405           {
406              snprintf(buf, sizeof(buf),
407                       "Unable to write \"edje_file\" entry to \"%s\"",
408                       file_out);
409              hw->errstr = strdup(buf);
410              return;
411           }
412      }
413
414    INF("Wrote %9i bytes (%4iKb) for \"edje_file\" header",
415        bytes, (bytes + 512) / 1024);
416 }
417
418 static void
419 data_thread_head_end(void *data, Ecore_Thread *thread __UNUSED__)
420 {
421    Head_Write *hw = data;
422
423    pending_threads--;
424    if (pending_threads <= 0) ecore_main_loop_quit();
425    if (hw->errstr)
426      {
427         error_and_abort(hw->ef, hw->errstr);
428         free(hw->errstr);
429      }
430    free(hw);
431 }
432
433 static void
434 data_write_header(Eet_File *ef)
435 {
436    Head_Write  *hw;
437
438    hw = calloc(1, sizeof(Head_Write));
439    hw->ef = ef;
440    pending_threads++;
441    if (threads)
442      ecore_thread_run(data_thread_head, data_thread_head_end, NULL, hw);
443    else
444      {
445         data_thread_head(hw, NULL);
446         data_thread_head_end(hw, NULL);
447      }
448 }
449
450 static void
451 data_thread_fonts(void *data, Ecore_Thread *thread __UNUSED__)
452 {
453    Fonts_Write *fc = data;
454    Eina_List *ll;
455    Eina_File *f = NULL;
456    void *m = NULL;
457    int bytes = 0;
458    char buf[PATH_MAX];
459    char buf2[PATH_MAX];
460
461    f = eina_file_open(fc->fn->file, 0);
462    if (f)
463      {
464        using_file(fc->fn->file, 'F');
465         m = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
466      }
467    else
468      {
469         char *dat;
470
471         EINA_LIST_FOREACH(fnt_dirs, ll, dat)
472           {
473              snprintf(buf, sizeof(buf), "%s/%s", dat, fc->fn->file);
474              f = eina_file_open(buf, 0);
475              if (f)
476                {
477                  using_file(buf, 'F');
478                   m = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
479                   if (m) break;
480                   eina_file_close(f);
481                   f = NULL;
482                }
483           }
484      }
485    if (!m)
486      {
487         if (f) eina_file_close(f);
488         snprintf(buf, sizeof(buf),
489                  "Unable to load font part \"%s\" entry to %s",
490                  fc->fn->file, file_out);
491         fc->errstr = strdup(buf);
492         return;
493      }
494
495    snprintf(buf, sizeof(buf), "edje/fonts/%s", fc->fn->name);
496    bytes = eet_write(fc->ef, buf, m, eina_file_size_get(f), compress_mode);
497
498    if ((bytes <= 0) || eina_file_map_faulted(f, m))
499      {
500         eina_file_map_free(f, m);
501         eina_file_close(f);
502         snprintf(buf2, sizeof(buf2),
503                  "Unable to write font part \"%s\" as \"%s\" "
504                  "part entry to %s", fc->fn->file, buf, file_out);
505         fc->errstr = strdup(buf2);
506         return;
507      }
508
509    INF("Wrote %9i bytes (%4iKb) for \"%s\" font entry \"%s\" compress: [real: %2.1f%%]",
510        bytes, (bytes + 512) / 1024, buf, fc->fn->file,
511        100 - (100 * (double)bytes) / ((double)(eina_file_size_get(f)))
512        );
513    eina_file_map_free(f, m);
514    eina_file_close(f);
515 }
516
517 static void
518 data_thread_fonts_end(void *data, Ecore_Thread *thread __UNUSED__)
519 {
520    Fonts_Write *fc = data;
521    pending_threads--;
522    if (pending_threads <= 0) ecore_main_loop_quit();
523    if (fc->errstr)
524      {
525         error_and_abort(fc->ef, fc->errstr);
526         free(fc->errstr);
527      }
528    free(fc);
529 }
530
531 static void
532 data_write_fonts(Eet_File *ef, int *font_num)
533 {
534    Eina_Iterator *it;
535    Font *fn;
536
537    if (!edje_file->fonts) return;
538
539    it = eina_hash_iterator_data_new(edje_file->fonts);
540    EINA_ITERATOR_FOREACH(it, fn)
541      {
542         Fonts_Write *fc;
543
544         fc = calloc(1, sizeof(Fonts_Write));
545         if (!fc) continue;
546         fc->ef = ef;
547         fc->fn = fn;
548         pending_threads++;
549         if (threads)
550           ecore_thread_run(data_thread_fonts, data_thread_fonts_end, NULL, fc);
551         else
552           {
553              data_thread_fonts(fc, NULL);
554              data_thread_fonts_end(fc, NULL);
555           }
556         *font_num += 1;
557      }
558    eina_iterator_free(it);
559 }
560
561 static void
562 error_and_abort_image_load_error(Eet_File *ef, const char *file, int error)
563 {
564    const char *errmsg = evas_load_error_str(error);
565    char hint[1024] = "";
566
567    if (error == EVAS_LOAD_ERROR_DOES_NOT_EXIST)
568      {
569         snprintf
570           (hint, sizeof(hint),
571            " Check if path to file \"%s\" is correct "
572            "(both directory and file name).",
573            file);
574      }
575    else if (error == EVAS_LOAD_ERROR_CORRUPT_FILE)
576      {
577         snprintf
578           (hint, sizeof(hint),
579            " Check if file \"%s\" is consistent.",
580            file);
581      }
582    else if (error == EVAS_LOAD_ERROR_UNKNOWN_FORMAT)
583      {
584         const char *ext = strrchr(file, '.');
585         const char **itr, *known_loaders[] = {
586           /* list from evas_image_load.c */
587           "png",
588           "jpg",
589           "jpeg",
590           "jfif",
591           "eet",
592           "edj",
593           "eap",
594           "edb",
595           "xpm",
596           "tiff",
597           "tif",
598           "svg",
599           "svgz",
600           "gif",
601           "pbm",
602           "pgm",
603           "ppm",
604           "pnm",
605           "bmp",
606           "ico",
607           "tga",
608           NULL
609         };
610
611         if (!ext)
612           {
613              snprintf
614                (hint, sizeof(hint),
615                 " File \"%s\" does not have an extension, "
616                 "maybe it should?",
617                 file);
618              goto show_err;
619           }
620
621         ext++;
622         for (itr = known_loaders; *itr; itr++)
623           {
624              if (strcasecmp(ext, *itr) == 0)
625                {
626                   snprintf
627                     (hint, sizeof(hint),
628                      " Check if Evas was compiled with %s module enabled and "
629                      "all required dependencies exist.",
630                      ext);
631                   goto show_err;
632                }
633           }
634
635         snprintf(hint, sizeof(hint),
636                  " Check if Evas supports loading files of type \"%s\" (%s) "
637                  "and this module was compiled and all its dependencies exist.",
638                  ext, file);
639      }
640  show_err:
641    error_and_abort
642      (ef, "Unable to load image \"%s\" used by file \"%s\": %s.%s",
643       file, file_out, errmsg, hint);
644 }
645
646 static void
647 data_thread_image(void *data, Ecore_Thread *thread __UNUSED__)
648 {
649    Image_Write *iw = data;
650    char buf[PATH_MAX], buf2[PATH_MAX];
651    unsigned int *start, *end;
652    Eina_Bool opaque = EINA_TRUE;
653    int bytes = 0;
654
655    if ((iw->data) && (iw->w > 0) && (iw->h > 0))
656      {
657         int mode, qual;
658
659         snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id);
660         qual = 80;
661         if ((iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
662             (iw->img->source_param == 0))
663           mode = 0; /* RAW */
664         else if ((iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
665                  (iw->img->source_param == 1))
666           mode = 1; /* COMPRESS */
667         else
668           mode = 2; /* LOSSY */
669         if ((mode == 0) && (no_raw))
670           {
671              mode = 1; /* promote compression */
672              iw->img->source_param = 95;
673           }
674         if ((mode == 2) && (no_lossy)) mode = 1; /* demote compression */
675         if ((mode == 1) && (no_comp))
676           {
677              if (no_lossy) mode = 0; /* demote compression */
678              else if (no_raw)
679                {
680                   iw->img->source_param = 90;
681                   mode = 2; /* no choice. lossy */
682                }
683           }
684         if (mode == 2)
685           {
686              qual = iw->img->source_param;
687              if (qual < min_quality) qual = min_quality;
688              if (qual > max_quality) qual = max_quality;
689           }
690         if (iw->alpha)
691           {
692              start = (unsigned int *) iw->data;
693              end = start + (iw->w * iw->h);
694              while (start < end)
695                {
696                   if ((*start & 0xff000000) != 0xff000000)
697                     {
698                        opaque = EINA_FALSE;
699                        break;
700                     }
701                   start++;
702                }
703              if (opaque) iw->alpha = 0;
704           }
705         if (mode == 0)
706           bytes = eet_data_image_write(iw->ef, buf,
707                                        iw->data, iw->w, iw->h,
708                                        iw->alpha,
709                                        0, 0, 0);
710         else if (mode == 1)
711           bytes = eet_data_image_write(iw->ef, buf,
712                                        iw->data, iw->w, iw->h,
713                                        iw->alpha,
714                                        compress_mode,
715                                        0, 0);
716         else if (mode == 2)
717           bytes = eet_data_image_write(iw->ef, buf,
718                                        iw->data, iw->w, iw->h,
719                                        iw->alpha,
720                                        0, qual, 1);
721         if (bytes <= 0)
722           {
723              snprintf(buf2, sizeof(buf2),
724                       "Unable to write image part "
725                       "\"%s\" as \"%s\" part entry to "
726                       "%s", iw->img->entry, buf, file_out);
727              iw->errstr = strdup(buf2);
728              return;
729           }
730      }
731    else
732      {
733         snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id);
734         snprintf(buf2, sizeof(buf2),
735                  "Unable to load image part "
736                  "\"%s\" as \"%s\" part entry to "
737                  "%s", iw->img->entry, buf, file_out);
738         iw->errstr = strdup(buf2);
739         return;
740      }
741
742    if (eina_log_domain_level_check(_edje_cc_log_dom, EINA_LOG_LEVEL_INFO))
743      {
744         struct stat st;
745
746         if (!iw->path || (stat(iw->path, &st))) st.st_size = 0;
747         INF("Wrote %9i bytes (%4iKb) for \"%s\" image entry \"%s\" compress: [raw: %2.1f%%] [real: %2.1f%%]",
748                bytes, (bytes + 512) / 1024, buf, iw->img->entry,
749                100 - (100 * (double)bytes) / ((double)(iw->w * iw->h * 4)),
750                100 - (100 * (double)bytes) / ((double)(st.st_size))
751               );
752      }
753 }
754
755 static void
756 data_thread_image_end(void *data, Ecore_Thread *thread __UNUSED__)
757 {
758    Image_Write *iw = data;
759
760    pending_threads--;
761    if (pending_threads <= 0) ecore_main_loop_quit();
762    if (iw->errstr)
763      {
764         error_and_abort(iw->ef, iw->errstr);
765         free(iw->errstr);
766      }
767    if (iw->path) free(iw->path);
768    evas_object_del(iw->im);
769    free(iw);
770 }
771
772 static void
773 data_image_preload_done(void *data, Evas *e __UNUSED__, Evas_Object *o, void *event_info __UNUSED__)
774 {
775    Image_Write *iw = data;
776
777    evas_object_image_size_get(o, &iw->w, &iw->h);
778    iw->alpha = evas_object_image_alpha_get(o);
779    iw->data = evas_object_image_data_get(o, 0);
780    if (threads)
781      ecore_thread_run(data_thread_image, data_thread_image_end, NULL, iw);
782    else
783      {
784         data_thread_image(iw, NULL);
785         data_thread_image_end(iw, NULL);
786      }
787 }
788
789 static void
790 data_write_images(Eet_File *ef, int *image_num)
791 {
792    int i;
793    Ecore_Evas *ee;
794    Evas *evas;
795
796    if (!((edje_file) && (edje_file->image_dir))) return;
797
798    ecore_evas_init();
799    ee = ecore_evas_buffer_new(1, 1);
800    if (!ee)
801      error_and_abort(ef, "Cannot create buffer engine canvas for image load.");
802    evas = ecore_evas_get(ee);
803
804    for (i = 0; i < (int)edje_file->image_dir->entries_count; i++)
805      {
806         Edje_Image_Directory_Entry *img;
807
808         img = &edje_file->image_dir->entries[i];
809         if ((img->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) ||
810             (img->entry == NULL))
811           {
812           }
813         else
814           {
815              Evas_Object *im;
816              Eina_List *ll;
817              char *s;
818              int load_err = EVAS_LOAD_ERROR_NONE;
819              Image_Write *iw;
820
821              iw = calloc(1, sizeof(Image_Write));
822              iw->ef = ef;
823              iw->img = img;
824              iw->im = im = evas_object_image_add(evas);
825              if (threads)
826                evas_object_event_callback_add(im,
827                                               EVAS_CALLBACK_IMAGE_PRELOADED,
828                                               data_image_preload_done,
829                                               iw);
830              EINA_LIST_FOREACH(img_dirs, ll, s)
831                {
832                   char buf[PATH_MAX];
833
834                   snprintf(buf, sizeof(buf), "%s/%s", s, img->entry);
835                   evas_object_image_file_set(im, buf, NULL);
836                   load_err = evas_object_image_load_error_get(im);
837                   if (load_err == EVAS_LOAD_ERROR_NONE)
838                     {
839                        *image_num += 1;
840                        iw->path = strdup(buf);
841                        pending_threads++;
842                        if (threads)
843                          evas_object_image_preload(im, 0);
844                        using_file(buf, 'I');
845                        if (!threads)
846                          data_image_preload_done(iw, evas, im, NULL);
847                        break;
848                     }
849                }
850              if (load_err != EVAS_LOAD_ERROR_NONE)
851                {
852                   evas_object_image_file_set(im, img->entry, NULL);
853                   load_err = evas_object_image_load_error_get(im);
854                   if (load_err == EVAS_LOAD_ERROR_NONE)
855                     {
856                        *image_num += 1;
857                        iw->path = strdup(img->entry);
858                        pending_threads++;
859                        if (threads)
860                          evas_object_image_preload(im, 0);
861                        using_file(img->entry, 'I');
862                        if (!threads)
863                          data_image_preload_done(iw, evas, im, NULL);
864                     }
865                   else
866                     error_and_abort_image_load_error
867                     (ef, img->entry, load_err);
868                }
869           }
870      }
871 }
872
873 static void
874 data_thread_sounds(void *data, Ecore_Thread *thread __UNUSED__)
875 {
876    Sound_Write *sw = data;
877    Eina_List *ll;
878 #ifdef HAVE_LIBSNDFILE
879    Edje_Sound_Encode *enc_info;
880 #endif
881    char *dir_path = NULL;
882    char snd_path[PATH_MAX];
883    char sndid_str[15];
884    Eina_File *f = NULL;
885    void *m = NULL;
886    int bytes = 0;
887
888    // Search the Sound file in all the -sd ( sound directory )
889    EINA_LIST_FOREACH(snd_dirs, ll, dir_path)
890      {
891         snprintf((char *)snd_path, sizeof(snd_path), "%s/%s", dir_path,
892                  sw->sample->snd_src);
893         f = eina_file_open(snd_path, 0);
894         if (f) break;
895      }
896    if (!f)
897      {
898         snprintf((char *)snd_path, sizeof(snd_path), "%s",
899                  sw->sample->snd_src);
900         f = eina_file_open(snd_path, 0);
901      }
902 #ifdef HAVE_LIBSNDFILE
903    if (f) eina_file_close(f);
904    enc_info = _edje_multisense_encode(snd_path, sw->sample,
905                                       sw->sample->quality);
906    f = eina_file_open(enc_info->file, 0);
907    if (f) using_file(enc_info->file, 'S');
908 #else
909    if (f) using_file(snd_path, 'S');
910 #endif
911    if (!f)
912      {
913         ERR("Unable to load sound data of: %s", sw->sample->name);
914         exit(-1);
915      }
916
917    snprintf(sndid_str, sizeof(sndid_str), "edje/sounds/%i", sw->sample->id);
918    m = eina_file_map_all(f, EINA_FILE_WILLNEED);
919    if (m)
920      {
921         bytes = eet_write(sw->ef, sndid_str, m, eina_file_size_get(f),
922                           EET_COMPRESSION_NONE);
923         if (eina_file_map_faulted(f, m))
924           {
925              ERR("File access error when reading '%s'",
926                  eina_file_filename_get(f));
927              exit(-1);
928           }
929         eina_file_map_free(f, m);
930      }
931    eina_file_close(f);
932
933 #ifdef HAVE_LIBSNDFILE
934    //If encoded temporary file, delete it.
935    if (enc_info->encoded) unlink(enc_info->file);
936 #endif
937 #ifdef HAVE_LIBSNDFILE
938    INF("Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry \"%s\"",
939        bytes, (bytes + 512) / 1024,
940        sndid_str, enc_info->comp_type, sw->sample->name);
941 #else
942    INF("Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry \"%s\"",
943        bytes, (bytes + 512) / 1024,
944        sndid_str, "RAW PCM", sw->sample->name);
945 #endif
946
947 #ifdef HAVE_LIBSNDFILE
948    if ((enc_info->file) && (!enc_info->encoded))
949      eina_stringshare_del(enc_info->file);
950    if (enc_info) free(enc_info);
951    enc_info = NULL;
952 #endif
953 }
954
955 static void
956 data_thread_sounds_end(void *data, Ecore_Thread *thread __UNUSED__)
957 {
958    Sound_Write *sw = data;
959    pending_threads--;
960    if (pending_threads <= 0) ecore_main_loop_quit();
961    free(sw);
962 }
963
964 static void
965 data_write_sounds(Eet_File *ef, int *sound_num)
966 {
967    if ((edje_file) && (edje_file->sound_dir))
968      {
969         int i;
970
971         for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
972           {
973              Sound_Write *sw;
974
975              sw = calloc(1, sizeof(Sound_Write));
976              if (!sw) continue;
977              sw->ef = ef;
978              sw->sample = &edje_file->sound_dir->samples[i];
979              sw->i = i;
980              *sound_num += 1;
981              pending_threads++;
982              if (threads)
983                ecore_thread_run(data_thread_sounds, data_thread_sounds_end, NULL, sw);
984              else
985                {
986                   data_thread_sounds(sw, NULL);
987                   data_thread_sounds_end(sw, NULL);
988                }
989           }
990      }
991 }
992
993 static void
994 check_groups(Eet_File *ef)
995 {
996    Edje_Part_Collection *pc;
997    Eina_List *l;
998
999    /* sanity checks for parts and programs */
1000    EINA_LIST_FOREACH(edje_collections, l, pc)
1001      {
1002         unsigned int i;
1003
1004         for (i = 0; i < pc->parts_count; ++i)
1005           check_part(pc, pc->parts[i], ef);
1006
1007 #define CHECK_PROGRAM(Type, Pc, It)                             \
1008         for (It = 0; It < Pc->programs.Type ## _count; ++It)    \
1009           check_program(Pc, Pc->programs.Type[i], ef);          \
1010
1011         CHECK_PROGRAM(fnmatch, pc, i);
1012         CHECK_PROGRAM(strcmp, pc, i);
1013         CHECK_PROGRAM(strncmp, pc, i);
1014         CHECK_PROGRAM(strrncmp, pc, i);
1015         CHECK_PROGRAM(nocmp, pc, i);
1016      }
1017 }
1018
1019 static void
1020 data_thread_group(void *data, Ecore_Thread *thread __UNUSED__)
1021 {
1022    Group_Write *gw = data;
1023    int bytes;
1024    char buf[PATH_MAX];
1025    char buf2[PATH_MAX];
1026
1027    snprintf(buf, sizeof(buf), "edje/collections/%i", gw->pc->id);
1028    bytes = eet_data_write(gw->ef, edd_edje_part_collection, buf, gw->pc,
1029                           compress_mode);
1030    return;
1031    if (bytes <= 0)
1032      {
1033         snprintf(buf2, sizeof(buf2),
1034                  "Unable to write \"%s\" part entry to %s",
1035                  buf, file_out);
1036         gw->errstr = strdup(buf2);
1037         return;
1038      }
1039
1040    INF("Wrote %9i bytes (%4iKb) for \"%s\" aka \"%s\" collection entry",
1041        bytes, (bytes + 512) / 1024, buf, gw->pc->part);
1042 }
1043
1044 static void
1045 data_thread_group_end(void *data, Ecore_Thread *thread __UNUSED__)
1046 {
1047    Group_Write *gw = data;
1048    pending_threads--;
1049    if (pending_threads <= 0) ecore_main_loop_quit();
1050    if (gw->errstr)
1051      {
1052         error_and_abort(gw->ef, gw->errstr);
1053         free(gw->errstr);
1054      }
1055    free(gw);
1056 }
1057
1058 static void
1059 data_write_groups(Eet_File *ef, int *collection_num)
1060 {
1061    Eina_List *l;
1062    Edje_Part_Collection *pc;
1063
1064    EINA_LIST_FOREACH(edje_collections, l, pc)
1065      {
1066         Group_Write *gw;
1067
1068         gw = calloc(1, sizeof(Group_Write));
1069         if (!gw)
1070           {
1071              error_and_abort(ef, "Cannot allocate memory for group writer");
1072              return;
1073           }
1074         gw->ef = ef;
1075         gw->pc = pc;
1076         pending_threads++;
1077         if (threads)
1078           ecore_thread_run(data_thread_group, data_thread_group_end, NULL, gw);
1079         else
1080           {
1081              data_thread_group(gw, NULL);
1082              data_thread_group_end(gw, NULL);
1083           }
1084         *collection_num += 1;
1085      }
1086 }
1087
1088 static void
1089 create_script_file(Eet_File *ef, const char *filename, const Code *cd, int fd)
1090 {
1091    FILE *f = fdopen(fd, "wb");
1092    if (!f)
1093      error_and_abort(ef, "Unable to open temp file \"%s\" for script "
1094                      "compilation.", filename);
1095
1096    Eina_List *ll;
1097    Code_Program *cp;
1098
1099    fprintf(f, "#include <edje>\n");
1100    int ln = 2;
1101
1102    if (cd->shared)
1103      {
1104         while (ln < (cd->l1 - 1))
1105           {
1106              fprintf(f, " \n");
1107              ln++;
1108           }
1109         {
1110            char *sp;
1111            int hash = 0;
1112            int newlined = 0;
1113
1114            for (sp = cd->shared; *sp; sp++)
1115              {
1116                 if ((sp[0] == '#') && (newlined))
1117                   {
1118                      hash = 1;
1119                   }
1120                 newlined = 0;
1121                 if (sp[0] == '\n') newlined = 1;
1122                 if (!hash) fputc(sp[0], f);
1123                 else if (sp[0] == '\n') hash = 0;
1124              }
1125            fputc('\n', f);
1126         }
1127         ln += cd->l2 - cd->l1 + 1;
1128      }
1129    EINA_LIST_FOREACH(cd->programs, ll, cp)
1130      {
1131         if (cp->script)
1132           {
1133              while (ln < (cp->l1 - 1))
1134                {
1135                   fprintf(f, " \n");
1136                   ln++;
1137                }
1138              /* FIXME: this prototype needs to be */
1139              /* formalised and set in stone */
1140              fprintf(f, "public _p%i(sig[], src[]) {", cp->id);
1141              {
1142                 char *sp;
1143                 int hash = 0;
1144                 int newlined = 0;
1145
1146                 for (sp = cp->script; *sp; sp++)
1147                   {
1148                      if ((sp[0] == '#') && (newlined))
1149                        {
1150                           hash = 1;
1151                        }
1152                      newlined = 0;
1153                      if (sp[0] == '\n') newlined = 1;
1154                      if (!hash) fputc(sp[0], f);
1155                      else if (sp[0] == '\n') hash = 0;
1156                   }
1157              }
1158              fprintf(f, "}\n");
1159              ln += cp->l2 - cp->l1 + 1;
1160           }
1161      }
1162
1163    fclose(f);
1164 }
1165
1166 static void
1167 data_thread_script(void *data, Ecore_Thread *thread __UNUSED__)
1168 {
1169    Script_Write *sc = data;
1170    FILE *f;
1171    int size;
1172    char buf[PATH_MAX];
1173
1174    f = fdopen(sc->tmpo_fd, "rb");
1175    if (!f)
1176      {
1177         snprintf(buf, sizeof(buf),
1178                  "Unable to open script object \"%s\" for reading.",
1179                  sc->tmpo);
1180         sc->errstr = strdup(buf);
1181         return;
1182      }
1183
1184    fseek(f, 0, SEEK_END);
1185    size = ftell(f);
1186    rewind(f);
1187
1188    if (size > 0)
1189      {
1190         void *dat = malloc(size);
1191
1192         if (dat)
1193           {
1194              if (fread(dat, size, 1, f) != 1)
1195                {
1196                   snprintf(buf, sizeof(buf),
1197                            "Unable to read all of script object \"%s\"",
1198                            sc->tmpo);
1199                   sc->errstr = strdup(buf);
1200                   return;
1201                }
1202              snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i",
1203                       sc->i);
1204              eet_write(sc->ef, buf, dat, size, compress_mode);
1205              free(dat);
1206           }
1207         else
1208           {
1209              snprintf(buf, sizeof(buf),
1210                       "Alloc failed for %lu bytes", (unsigned long)size);
1211              sc->errstr = strdup(buf);
1212              return;
1213           }
1214      }
1215    fclose(f);
1216
1217    if (!no_save)
1218      {
1219         Eina_List *ll;
1220         Code_Program *cp;
1221
1222         if (sc->cd->original)
1223           {
1224              snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i", sc->i);
1225              eet_write(sc->ef, buf, sc->cd->original,
1226                        strlen(sc->cd->original) + 1, compress_mode);
1227           }
1228         EINA_LIST_FOREACH(sc->cd->programs, ll, cp)
1229           {
1230              if (!cp->original) continue;
1231              snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i/%i",
1232                       sc->i, cp->id);
1233              eet_write(sc->ef, buf, cp->original,
1234                        strlen(cp->original) + 1, compress_mode);
1235           }
1236      }
1237
1238    unlink(sc->tmpn);
1239    unlink(sc->tmpo);
1240    close(sc->tmpn_fd);
1241    close(sc->tmpo_fd);
1242 }
1243
1244 static void
1245 data_thread_script_end(void *data, Ecore_Thread *thread __UNUSED__)
1246 {
1247    Script_Write *sc = data;
1248    pending_threads--;
1249    if (pending_threads <= 0) ecore_main_loop_quit();
1250    if (sc->errstr)
1251      {
1252         error_and_abort(sc->ef, sc->errstr);
1253         free(sc->errstr);
1254      }
1255    free(sc);
1256 }
1257
1258 static Eina_Bool
1259 data_scripts_exe_del_cb(void *data __UNUSED__, int evtype __UNUSED__, void *evinfo)
1260 {
1261    Script_Write *sc = data;
1262    Ecore_Exe_Event_Del *ev = evinfo;
1263
1264    if (!ev->exe) return ECORE_CALLBACK_RENEW;
1265    if (ecore_exe_data_get(ev->exe) != sc) return ECORE_CALLBACK_RENEW;
1266    if (ev->exit_code != 0)
1267      {
1268         error_and_abort(sc->ef, "Compiling script code not clean.");
1269         return ECORE_CALLBACK_CANCEL;
1270      }
1271    if (threads)
1272      {
1273         pending_threads++;
1274         ecore_thread_run(data_thread_script, data_thread_script_end, NULL, sc);
1275      }
1276    else
1277      {
1278         pending_threads++;
1279         data_thread_script(sc, NULL);
1280         data_thread_script_end(sc, NULL);
1281      }
1282    pending_threads--;
1283    if (pending_threads <= 0) ecore_main_loop_quit();
1284    return ECORE_CALLBACK_CANCEL;
1285 }
1286
1287 static void
1288 data_write_scripts(Eet_File *ef)
1289 {
1290    Eina_List *l;
1291    int i;
1292
1293    if (!tmp_dir)
1294 #ifdef HAVE_EVIL
1295      tmp_dir = (char *)evil_tmpdir_get();
1296 #else
1297      tmp_dir = "/tmp";
1298 #endif
1299
1300    for (i = 0, l = codes; l; l = eina_list_next(l), i++)
1301      {
1302         Code *cd = eina_list_data_get(l);
1303         Script_Write *sc;
1304         char buf[PATH_MAX];
1305
1306         if (cd->is_lua)
1307           continue;
1308         if ((!cd->shared) && (!cd->programs))
1309           continue;
1310         sc = calloc(1, sizeof(Script_Write));
1311         sc->ef = ef;
1312         sc->cd = cd;
1313         sc->i = i;
1314         snprintf(sc->tmpn, PATH_MAX, "%s/edje_cc.sma-tmp-XXXXXX", tmp_dir);
1315         sc->tmpn_fd = mkstemp(sc->tmpn);
1316         if (sc->tmpn_fd < 0)
1317           error_and_abort(ef, "Unable to open temp file \"%s\" for script "
1318                           "compilation.", sc->tmpn);
1319         snprintf(sc->tmpo, PATH_MAX, "%s/edje_cc.amx-tmp-XXXXXX", tmp_dir);
1320         sc->tmpo_fd = mkstemp(sc->tmpo);
1321         if (sc->tmpo_fd < 0)
1322           {
1323              unlink(sc->tmpn);
1324              error_and_abort(ef, "Unable to open temp file \"%s\" for script "
1325                              "compilation.", sc->tmpn);
1326           }
1327         create_script_file(ef, sc->tmpn, cd, sc->tmpn_fd);
1328         snprintf(buf, sizeof(buf),
1329                  "%s/embryo_cc -i %s/include -o %s %s",
1330                  eina_prefix_bin_get(pfx),
1331                  eina_prefix_data_get(pfx),
1332                  sc->tmpo, sc->tmpn);
1333         pending_threads++;
1334         sc->exe = ecore_exe_run(buf, sc);
1335         ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
1336                                 data_scripts_exe_del_cb, sc);
1337      }
1338 }
1339
1340 #ifdef LUA_BINARY
1341 static int
1342 _edje_lua_script_writer(lua_State *L __UNUSED__, const void *chunk_buf, size_t chunk_size, void *_data)
1343 {
1344    Script_Lua_Writer *data;
1345    void *old;
1346
1347    data = (Script_Lua_Writer *)_data;
1348    old = data->buf;
1349    data->buf = malloc(data->size + chunk_size);
1350    memcpy(data->buf, old, data->size);
1351    memcpy(&((data->buf)[data->size]), chunk_buf, chunk_size);
1352    if (old) free(old);
1353    data->size += chunk_size;
1354
1355    return 0;
1356 }
1357 #endif
1358
1359 void
1360 _edje_lua_error_and_abort(lua_State *L, int err_code, Script_Write *sc)
1361 {
1362    char buf[PATH_MAX];
1363    char *err_type;
1364
1365    switch (err_code)
1366      {
1367       case LUA_ERRRUN:
1368         err_type = "runtime";
1369         break;
1370       case LUA_ERRSYNTAX:
1371         err_type = "syntax";
1372         break;
1373       case LUA_ERRMEM:
1374         err_type = "memory allocation";
1375         break;
1376       case LUA_ERRERR:
1377         err_type = "error handler";
1378         break;
1379       default:
1380         err_type = "unknown";
1381         break;
1382      }
1383    snprintf(buf, sizeof(buf),
1384             "Lua %s error: %s", err_type, lua_tostring(L, -1));
1385    sc->errstr = strdup(buf);
1386 }
1387
1388 static void
1389 data_thread_lua_script(void *data, Ecore_Thread *thread __UNUSED__)
1390 {
1391    Script_Write *sc = data;
1392    char buf[PATH_MAX];
1393    lua_State *L;
1394    int ln = 1;
1395    luaL_Buffer b;
1396    Script_Lua_Writer dat;
1397    Eina_List *ll;
1398    Code_Program *cp;
1399 #ifdef LUA_BINARY
1400    int err_code;
1401 #endif
1402
1403    L = luaL_newstate();
1404    if (!L)
1405      {
1406         snprintf(buf, sizeof(buf),
1407                  "Lua error: Lua state could not be initialized");
1408         sc->errstr = strdup(buf);
1409         return;
1410      }
1411
1412    luaL_buffinit(L, &b);
1413
1414    dat.buf = NULL;
1415    dat.size = 0;
1416    if (sc->cd->shared)
1417      {
1418         while (ln < (sc->cd->l1 - 1))
1419           {
1420              luaL_addchar(&b, '\n');
1421              ln++;
1422           }
1423         luaL_addstring(&b, sc->cd->shared);
1424         ln += sc->cd->l2 - sc->cd->l1;
1425      }
1426
1427    EINA_LIST_FOREACH(sc->cd->programs, ll, cp)
1428      {
1429         if (cp->script)
1430           {
1431              while (ln < (cp->l1 - 1))
1432                {
1433                   luaL_addchar(&b, '\n');
1434                   ln++;
1435                }
1436              luaL_addstring(&b, "_G[");
1437              lua_pushnumber(L, cp->id);
1438              luaL_addvalue(&b);
1439              luaL_addstring(&b, "] = function (ed, signal, source)");
1440              luaL_addstring(&b, cp->script);
1441              luaL_addstring(&b, "end\n");
1442              ln += cp->l2 - cp->l1 + 1;
1443           }
1444      }
1445    luaL_pushresult(&b);
1446 #ifdef LUA_BINARY
1447    if (err_code = luaL_loadstring(L, lua_tostring (L, -1)))
1448      {
1449         _edje_lua_error_and_abort(L, err_code, sc);
1450         return;
1451      }
1452    lua_dump(L, _edje_lua_script_writer, &dat);
1453 #else // LUA_PLAIN_TEXT
1454    dat.buf = (char *)lua_tostring(L, -1);
1455    dat.size = strlen(dat.buf);
1456 #endif
1457    //printf("lua chunk size: %d\n", dat.size);
1458
1459    /*
1460     * TODO load and test Lua chunk
1461     */
1462
1463    /*
1464     if (luaL_loadbuffer(L, globbuf, globbufsize, "edje_lua_script"))
1465     printf("lua load error: %s\n", lua_tostring (L, -1));
1466     if (lua_pcall(L, 0, 0, 0))
1467     printf("lua call error: %s\n", lua_tostring (L, -1));
1468     */
1469
1470    snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", sc->i);
1471    if (eet_write(sc->ef, buf, dat.buf, dat.size, compress_mode) <= 0)
1472      {
1473         snprintf(buf, sizeof(buf),
1474                  "Unable to write script %i", sc->i);
1475         sc->errstr = strdup(buf);
1476         return;
1477      }
1478 #ifdef LUA_BINARY
1479    free(dat.buf);
1480 #endif
1481    lua_close(L);
1482 }
1483
1484 static void
1485 data_thread_lua_script_end(void *data, Ecore_Thread *thread __UNUSED__)
1486 {
1487    Script_Write *sc = data;
1488    pending_threads--;
1489    if (pending_threads <= 0) ecore_main_loop_quit();
1490    if (sc->errstr)
1491      {
1492         error_and_abort(sc->ef, sc->errstr);
1493         free(sc->errstr);
1494      }
1495    free(sc);
1496 }
1497
1498 static void
1499 data_write_lua_scripts(Eet_File *ef)
1500 {
1501    Eina_List *l;
1502    int i;
1503
1504    for (i = 0, l = codes; l; l = eina_list_next(l), i++)
1505      {
1506         Code *cd;
1507         Script_Write *sc;
1508
1509         cd = (Code *)eina_list_data_get(l);
1510         if (!cd->is_lua)
1511           continue;
1512         if ((!cd->shared) && (!cd->programs))
1513           continue;
1514
1515         sc = calloc(1, sizeof(Script_Write));
1516         sc->ef = ef;
1517         sc->cd = cd;
1518         sc->i = i;
1519         pending_threads++;
1520         if (threads)
1521           ecore_thread_run(data_thread_lua_script, data_thread_lua_script_end, NULL, sc);
1522         else
1523           {
1524              data_thread_lua_script(sc, NULL);
1525              data_thread_lua_script_end(sc, NULL);
1526           }
1527      }
1528 }
1529
1530 static void
1531 data_thread_source(void *data, Ecore_Thread *thread __UNUSED__)
1532 {
1533    Eet_File *ef = data;
1534    source_append(ef);
1535 }
1536
1537 static void
1538 data_thread_source_end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__)
1539 {
1540    pending_threads--;
1541    if (pending_threads <= 0) ecore_main_loop_quit();
1542 }
1543
1544 static void
1545 data_thread_fontmap(void *data, Ecore_Thread *thread __UNUSED__)
1546 {
1547    Eet_File *ef = data;
1548    source_fontmap_save(ef, fonts);
1549 }
1550
1551 static void
1552 data_thread_fontmap_end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__)
1553 {
1554    pending_threads--;
1555    if (pending_threads <= 0) ecore_main_loop_quit();
1556 }
1557
1558 void
1559 data_write(void)
1560 {
1561    Eet_File *ef;
1562    int image_num = 0;
1563    int sound_num = 0;
1564    int font_num = 0;
1565    int collection_num = 0;
1566    double t;
1567
1568    if (!edje_file)
1569      {
1570         ERR("No data to put in \"%s\"", file_out);
1571         exit(-1);
1572      }
1573
1574    ef = eet_open(file_out, EET_FILE_MODE_WRITE);
1575    if (!ef)
1576      {
1577         ERR("Unable to open \"%s\" for writing output", file_out);
1578         exit(-1);
1579      }
1580
1581    check_groups(ef);
1582
1583    ecore_thread_max_set(ecore_thread_max_get() * 2);
1584
1585    pending_threads++;
1586    t = ecore_time_get();
1587    data_write_header(ef);
1588
1589    INF("header: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1590    data_write_groups(ef, &collection_num);
1591    INF("groups: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1592    data_write_scripts(ef);
1593    INF("scripts: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1594    data_write_lua_scripts(ef);
1595    INF("lua scripts: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1596
1597    pending_threads++;
1598    if (threads)
1599      ecore_thread_run(data_thread_source, data_thread_source_end, NULL, ef);
1600    else
1601      {
1602         data_thread_source(ef, NULL);
1603         data_thread_source_end(ef, NULL);
1604      }
1605    INF("source: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1606    pending_threads++;
1607    if (threads)
1608      ecore_thread_run(data_thread_fontmap, data_thread_fontmap_end, NULL, ef);
1609    else
1610      {
1611         data_thread_fontmap(ef, NULL);
1612         data_thread_fontmap_end(ef, NULL);
1613      }
1614    INF("fontmap: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1615    data_write_images(ef, &image_num);
1616    INF("images: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1617    data_write_fonts(ef, &font_num);
1618    INF("fonts: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1619    data_write_sounds(ef, &sound_num);
1620    INF("sounds: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1621    pending_threads--;
1622    if (pending_threads > 0) ecore_main_loop_begin();
1623    INF("THREADS: %3.5f", ecore_time_get() - t); t = ecore_time_get();
1624
1625    eet_close(ef);
1626
1627    if (eina_log_domain_level_check(_edje_cc_log_dom, EINA_LOG_LEVEL_INFO))
1628      {
1629         printf("Summary:\n"
1630                "  Wrote %i collections\n"
1631                "  Wrote %i images\n"
1632                "  Wrote %i sounds\n"
1633                "  Wrote %i fonts\n"
1634                ,
1635                collection_num,
1636                image_num,
1637                sound_num,
1638                font_num);
1639      }
1640 }
1641
1642 void
1643 reorder_parts(void)
1644 {
1645    Edje_Part_Collection *pc;
1646    Edje_Part **parts;
1647    Edje_Part_Parser *ep, *ep2;
1648    Eina_List *l;
1649
1650    /* sanity checks for parts and programs */
1651    EINA_LIST_FOREACH(edje_collections, l, pc)
1652      {
1653         unsigned int i, j, k;
1654         Eina_Bool found = EINA_FALSE;
1655
1656         for (i = 0; i < pc->parts_count; i++)
1657           {
1658              ep = (Edje_Part_Parser *)pc->parts[i];
1659              if (ep->reorder.insert_before && ep->reorder.insert_after)
1660                ERR("Unable to use together insert_before and insert_after in part \"%s\".", pc->parts[i]->name);
1661
1662              if (ep->reorder.done)
1663                {
1664                   continue;
1665                }
1666              if (ep->reorder.insert_before || ep->reorder.insert_after)
1667                {
1668                   found = EINA_FALSE;
1669                   for (j = 0; j < pc->parts_count; j++)
1670                     {
1671                        if (ep->reorder.insert_before &&
1672                            !strcmp(ep->reorder.insert_before, pc->parts[j]->name))
1673                          {
1674                             ep2 = (Edje_Part_Parser *)pc->parts[j];
1675                             if (ep2->reorder.after)
1676                               ERR("The part \"%s\" is ambiguous ordered part.",
1677                                   pc->parts[i]->name);
1678                             if (ep2->reorder.linked_prev)
1679                               ERR("Unable to insert two or more parts in same part \"%s\".",
1680                                   pc->parts[j]->name);
1681                             k = j - 1;
1682                             found = EINA_TRUE;
1683                             ep2->reorder.linked_prev += ep->reorder.linked_prev + 1;
1684                             ep->reorder.before = (Edje_Part_Parser *)pc->parts[j];
1685                             while (ep2->reorder.before)
1686                               {
1687                                  ep2->reorder.before->reorder.linked_prev = ep2->reorder.linked_prev + 1;
1688                                  ep2 = ep2->reorder.before;
1689                               }
1690                             break;
1691                          }
1692                        else if (ep->reorder.insert_after &&
1693                            !strcmp(ep->reorder.insert_after, pc->parts[j]->name))
1694                          {
1695                             ep2 = (Edje_Part_Parser *)pc->parts[j];
1696                             if (ep2->reorder.before)
1697                               ERR("The part \"%s\" is ambiguous ordered part.", pc->parts[i]->name);
1698                             if (ep2->reorder.linked_next)
1699                               ERR("Unable to insert two or more parts in same part \"%s\".", pc->parts[j]->name);
1700                             k = j;
1701                             found = EINA_TRUE;
1702                             ep2->reorder.linked_next += ep->reorder.linked_next + 1;
1703                             ep->reorder.after = (Edje_Part_Parser *)pc->parts[j];
1704                             while (ep2->reorder.after)
1705                               {
1706                                  ep2->reorder.after->reorder.linked_next = ep2->reorder.linked_next + 1;
1707                                  ep2 = ep2->reorder.after;
1708                               }
1709                             break;
1710                          }
1711                     }
1712                   if (found)
1713                     {
1714                        unsigned int amount, linked;
1715
1716                        if (((i > k) && ((i - ep->reorder.linked_prev) <= k))
1717                            || ((i < k) && ((i + ep->reorder.linked_next) >= k)))
1718                          ERR("The part order is wrong. It has circular dependency.");
1719
1720                        amount = ep->reorder.linked_prev + ep->reorder.linked_next + 1;
1721                        linked = i - ep->reorder.linked_prev;
1722                        parts = malloc(amount * sizeof(Edje_Part));
1723                        for (j = 0 ; j < amount ; j++)
1724                          {
1725                             parts[j] = pc->parts[linked];
1726                             linked++;
1727                          }
1728                        if (i > k)
1729                          {
1730                             for (j = i - ep->reorder.linked_prev - 1 ; j >= k ; j--)
1731                               {
1732                                  pc->parts[j + amount] = pc->parts[j];
1733                                  pc->parts[j + amount]->id = j + amount;
1734                               }
1735                             for (j = 0 ; j < amount ; j++)
1736                               {
1737                                  pc->parts[j + k] = parts[j];
1738                                  pc->parts[j + k]->id = j + k;
1739                               }
1740                          }
1741                        else if (i < k)
1742                          {
1743                             for (j = i + ep->reorder.linked_next + 1 ; j <= k ; j++)
1744                               {
1745                                  pc->parts[j - amount] = pc->parts[j];
1746                                  pc->parts[j - amount]->id = j - amount;
1747                               }
1748                             for (j = 0 ; j < amount ; j++)
1749                               {
1750                                  pc->parts[j + k - amount + 1] = parts[j];
1751                                  pc->parts[j + k - amount + 1]->id = j + k - amount + 1;
1752                               }
1753                             i -= amount;
1754                          }
1755                        ep->reorder.done = EINA_TRUE;
1756                        free(parts);
1757                     }
1758                }
1759           }
1760      }
1761 }
1762
1763 void
1764 data_queue_group_lookup(const char *name, Edje_Part *part)
1765 {
1766    Group_Lookup *gl;
1767
1768    if (!name || !name[0]) return;
1769
1770    gl = mem_alloc(SZ(Group_Lookup));
1771    group_lookups = eina_list_append(group_lookups, gl);
1772    gl->name = mem_strdup(name);
1773    gl->part = part;
1774 }
1775
1776 void
1777 data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
1778 {
1779    void *key[2];
1780    Part_Lookup *pl = NULL;
1781    Eina_List *list;
1782
1783    key[0] = pc;
1784    key[1] = dest;
1785
1786    pl = eina_hash_find(part_pc_dest_lookup, &key);
1787    if (pl)
1788      {
1789         free(pl->name);
1790         if (name[0])
1791           {
1792              pl->name = mem_strdup(name);
1793           }
1794         else
1795           {
1796              list = eina_hash_find(part_dest_lookup, &pl->dest);
1797              list = eina_list_remove(list, pl);
1798              eina_hash_set(part_dest_lookup, &pl->dest, list);
1799              free(pl);
1800           }
1801         return ;
1802      }
1803
1804    if (!name[0]) return;
1805
1806    pl = mem_alloc(SZ(Part_Lookup));
1807    pl->pc = pc;
1808    pl->name = mem_strdup(name);
1809    pl->dest = dest;
1810
1811    eina_hash_add(part_pc_dest_lookup, &key, pl);
1812
1813    list = eina_hash_find(part_dest_lookup, &pl->dest);
1814    list = eina_list_prepend(list, pl);
1815    eina_hash_set(part_dest_lookup, &pl->dest, list);
1816 }
1817
1818 void
1819 data_queue_copied_part_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1820 {
1821    Eina_List *list;
1822    Eina_List *l;
1823    Part_Lookup *pl;
1824
1825    list = eina_hash_find(part_dest_lookup, &src);
1826    EINA_LIST_FOREACH(list, l, pl)
1827      data_queue_part_lookup(pc, pl->name, dest);
1828 }
1829
1830 void
1831 data_queue_anonymous_lookup(Edje_Part_Collection *pc, Edje_Program *ep, int *dest)
1832 {
1833    Eina_List *l, *l2;
1834    Program_Lookup *pl;
1835
1836    if (!ep) return ; /* FIXME: should we stop compiling ? */
1837
1838    EINA_LIST_FOREACH(program_lookups, l, pl)
1839      {
1840         if (pl->u.ep == ep)
1841           {
1842              Code *cd;
1843              Code_Program *cp;
1844
1845              cd = eina_list_data_get(eina_list_last(codes));
1846
1847              EINA_LIST_FOREACH(cd->programs, l2, cp)
1848                {
1849                   if (&(cp->id) == pl->dest)
1850                     {
1851                        cd->programs = eina_list_remove(cd->programs, cp);
1852                        free(cp);
1853                        cp = NULL;
1854                     }
1855                }
1856              program_lookups = eina_list_remove(program_lookups, pl);
1857              free(pl);
1858           }
1859      }
1860
1861    if (dest)
1862      {
1863         pl = mem_alloc(SZ(Program_Lookup));
1864         program_lookups = eina_list_append(program_lookups, pl);
1865         pl->pc = pc;
1866         pl->u.ep = ep;
1867         pl->dest = dest;
1868         pl->anonymous = EINA_TRUE;
1869      }
1870 }
1871
1872 void
1873 data_queue_copied_anonymous_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1874 {
1875    Eina_List *l;
1876    Program_Lookup *pl;
1877    unsigned int i;
1878
1879    EINA_LIST_FOREACH(program_lookups, l, pl)
1880      {
1881         if (pl->dest == src && pl->u.ep->name)
1882           {
1883              for (i = 0 ; i < pc->programs.fnmatch_count ; i++)
1884                {
1885                   if (pc->programs.fnmatch[i]->name &&
1886                       !strcmp(pl->u.ep->name, pc->programs.fnmatch[i]->name))
1887                     data_queue_anonymous_lookup(pc, pc->programs.fnmatch[i], dest);
1888                }
1889              for (i = 0 ; i < pc->programs.strcmp_count ; i++)
1890                {
1891                   if (pc->programs.strcmp[i]->name &&
1892                       !strcmp(pl->u.ep->name, pc->programs.strcmp[i]->name))
1893                     data_queue_anonymous_lookup(pc, pc->programs.strcmp[i], dest);
1894                }
1895              for (i = 0 ; i < pc->programs.strncmp_count ; i++)
1896                {
1897                   if (pc->programs.strncmp[i]->name &&
1898                       !strcmp(pl->u.ep->name, pc->programs.strncmp[i]->name))
1899                     data_queue_anonymous_lookup(pc, pc->programs.strncmp[i], dest);
1900                }
1901              for (i = 0 ; i < pc->programs.strrncmp_count ; i++)
1902                {
1903                   if (pc->programs.strrncmp[i]->name &&
1904                       !strcmp(pl->u.ep->name, pc->programs.strrncmp[i]->name))
1905                     data_queue_anonymous_lookup(pc, pc->programs.strrncmp[i], dest);
1906                }
1907              for (i = 0 ; i < pc->programs.nocmp_count ; i++)
1908                {
1909                   if (pc->programs.nocmp[i]->name &&
1910                       !strcmp(pl->u.ep->name, pc->programs.nocmp[i]->name))
1911                     data_queue_anonymous_lookup(pc, pc->programs.nocmp[i], dest);
1912                }
1913           }
1914      }
1915 }
1916
1917 void
1918 data_queue_program_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
1919 {
1920    Program_Lookup *pl;
1921
1922    if (!name) return ; /* FIXME: should we stop compiling ? */
1923
1924    pl = mem_alloc(SZ(Program_Lookup));
1925    program_lookups = eina_list_append(program_lookups, pl);
1926    pl->pc = pc;
1927    pl->u.name = mem_strdup(name);
1928    pl->dest = dest;
1929    pl->anonymous = EINA_FALSE;
1930 }
1931
1932 void
1933 data_queue_copied_program_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1934 {
1935    Eina_List *l;
1936    Program_Lookup *pl;
1937
1938    EINA_LIST_FOREACH(program_lookups, l, pl)
1939      {
1940         if (pl->dest == src)
1941           data_queue_program_lookup(pc, pl->u.name, dest);
1942      }
1943 }
1944
1945 void
1946 data_queue_image_lookup(char *name, int *dest, Eina_Bool *set)
1947 {
1948    Image_Lookup *il;
1949
1950    il = mem_alloc(SZ(Image_Lookup));
1951    image_lookups = eina_list_append(image_lookups, il);
1952    il->name = mem_strdup(name);
1953    il->dest = dest;
1954    il->set = set;
1955 }
1956
1957 void
1958 data_queue_image_remove(int *dest, Eina_Bool *set)
1959 {
1960    Eina_List *l;
1961    Image_Lookup *il;
1962
1963    EINA_LIST_FOREACH(image_lookups, l, il)
1964      {
1965         if (il->dest == dest && il->set == set)
1966           {
1967              image_lookups = eina_list_remove_list(image_lookups, l);
1968              free(il->name);
1969              free(il);
1970              return ;
1971           }
1972      }
1973  }
1974
1975 void
1976 data_queue_copied_image_lookup(int *src, int *dest, Eina_Bool *set)
1977 {
1978    Eina_List *l;
1979    Image_Lookup *il;
1980
1981    EINA_LIST_FOREACH(image_lookups, l, il)
1982      {
1983         if (il->dest == src)
1984           data_queue_image_lookup(il->name, dest, set);
1985      }
1986 }
1987 void
1988 data_queue_part_slave_lookup(int *master, int *slave)
1989 {
1990    Slave_Lookup *sl;
1991
1992    sl = mem_alloc(SZ(Slave_Lookup));
1993    part_slave_lookups = eina_list_append(part_slave_lookups, sl);
1994    sl->master = master;
1995    sl->slave = slave;
1996 }
1997
1998 void
1999 data_queue_image_slave_lookup(int *master, int *slave)
2000 {
2001    Slave_Lookup *sl;
2002
2003    sl = mem_alloc(SZ(Slave_Lookup));
2004    image_slave_lookups = eina_list_append(image_slave_lookups, sl);
2005    sl->master = master;
2006    sl->slave = slave;
2007 }
2008
2009 void
2010 handle_slave_lookup(Eina_List *list, int *master, int value)
2011 {
2012    Eina_List *l;
2013    Slave_Lookup *sl;
2014
2015    EINA_LIST_FOREACH(list, l, sl)
2016      if (sl->master == master)
2017        *sl->slave = value;
2018 }
2019
2020 void
2021 data_process_lookups(void)
2022 {
2023    Edje_Part_Collection *pc;
2024    Eina_Iterator *it;
2025    Part_Lookup *part;
2026    Program_Lookup *program;
2027    Group_Lookup *group;
2028    Image_Lookup *image;
2029    Eina_List *l2;
2030    Eina_List *l;
2031    Eina_Hash *images_in_use;
2032    void *data;
2033    Eina_Bool is_lua = EINA_FALSE;
2034
2035    /* remove all unreferenced Edje_Part_Collection */
2036    EINA_LIST_FOREACH_SAFE(edje_collections, l, l2, pc)
2037      {
2038         Edje_Part_Collection_Directory_Entry *alias;
2039         Edje_Part_Collection_Directory_Entry *find;
2040         Eina_List *l3;
2041         unsigned int id = 0;
2042         unsigned int i;
2043
2044         if (!pc->part)
2045           {
2046              ERR("A collection without a name was detected, that's not allowed.");
2047              exit(-1);
2048           }
2049         find = eina_hash_find(edje_file->collection, pc->part);
2050         if (find && find->id == pc->id)
2051           continue ;
2052
2053         EINA_LIST_FOREACH(aliases, l3, alias)
2054           if (alias->id == pc->id)
2055             continue ;
2056
2057         /* This Edje_Part_Collection is not used at all */
2058         edje_collections = eina_list_remove_list(edje_collections, l);
2059         l3 = eina_list_nth_list(codes, pc->id);
2060         codes = eina_list_remove_list(codes, l3);
2061
2062         /* Unref all image used by that group */
2063         for (i = 0; i < pc->parts_count; ++i)
2064           part_description_image_cleanup(pc->parts[i]);
2065
2066         /* Correct all id */
2067         EINA_LIST_FOREACH(edje_collections, l3, pc)
2068           {
2069              Eina_List *l4;
2070
2071              /* Some group could be removed from the collection, but still be referenced by alias */
2072              find = eina_hash_find(edje_file->collection, pc->part);
2073              if (pc->id != find->id) find = NULL;
2074
2075              /* Update all matching alias */
2076              EINA_LIST_FOREACH(aliases, l4, alias)
2077                if (pc->id == alias->id)
2078                  alias->id = id;
2079
2080              pc->id = id++;
2081              if (find) find->id = pc->id;
2082           }
2083      }
2084
2085    EINA_LIST_FOREACH(edje_collections, l, pc)
2086      {
2087         unsigned int count = 0;
2088         unsigned int i;
2089
2090         if (pc->lua_script_only)
2091           is_lua = EINA_TRUE;
2092 #define PROGRAM_ID_SET(Type, Pc, It, Count)                             \
2093         for (It = 0; It < Pc->programs.Type ## _count; ++It)            \
2094           {                                                             \
2095              Pc->programs.Type[It]->id = Count++;                       \
2096           }
2097
2098         PROGRAM_ID_SET(fnmatch, pc, i, count);
2099         PROGRAM_ID_SET(strcmp, pc, i, count);
2100         PROGRAM_ID_SET(strncmp, pc, i, count);
2101         PROGRAM_ID_SET(strrncmp, pc, i, count);
2102         PROGRAM_ID_SET(nocmp, pc, i, count);
2103
2104 #undef PROGRAM_ID_SET
2105      }
2106
2107    it = eina_hash_iterator_data_new(part_pc_dest_lookup);
2108    EINA_ITERATOR_FOREACH(it, part)
2109      {
2110         Edje_Part *ep;
2111         unsigned int i;
2112
2113         if (!strcmp(part->name, "-"))
2114           {
2115              *(part->dest) = -1;
2116           }
2117         else
2118           {
2119              char *alias;
2120              alias = eina_hash_find(part->pc->alias, part->name);
2121              if (!alias)
2122                alias = part->name;
2123              for (i = 0; i < part->pc->parts_count; ++i)
2124                {
2125                   ep = part->pc->parts[i];
2126
2127                   if ((ep->name) && (!strcmp(ep->name, alias)))
2128                     {
2129                        handle_slave_lookup(part_slave_lookups, part->dest, ep->id);
2130                        *(part->dest) = ep->id;
2131                        break;
2132                     }
2133                }
2134
2135              if (i == part->pc->parts_count)
2136                {
2137                   ERR("Unable to find part name \"%s\" needed in group '%s'.",
2138                       alias, part->pc->part);
2139                   exit(-1);
2140                }
2141           }
2142      }
2143    eina_iterator_free(it);
2144    eina_hash_free(part_dest_lookup);
2145    eina_hash_free(part_pc_dest_lookup);
2146
2147    EINA_LIST_FREE(program_lookups, program)
2148      {
2149         unsigned int i;
2150         Eina_Bool find = EINA_FALSE;
2151
2152 #define PROGRAM_MATCH(Type, Pl, It)                                     \
2153         for (It = 0; It < Pl->pc->programs.Type ## _count; ++It)        \
2154           {                                                             \
2155              Edje_Program *ep;                                          \
2156              \
2157              ep = Pl->pc->programs.Type[It];                            \
2158              \
2159              if ((Pl->anonymous && ep == Pl->u.ep) ||                   \
2160                  ((!Pl->anonymous) && (ep->name) && (!strcmp(ep->name, Pl->u.name)))) \
2161                {                                                        \
2162                   *(Pl->dest) = ep->id;                                 \
2163                   find = EINA_TRUE;                                     \
2164                   break;                                                \
2165                }                                                        \
2166           }
2167
2168         PROGRAM_MATCH(fnmatch, program, i);
2169         PROGRAM_MATCH(strcmp, program, i);
2170         PROGRAM_MATCH(strncmp, program, i);
2171         PROGRAM_MATCH(strrncmp, program, i);
2172         PROGRAM_MATCH(nocmp, program, i);
2173
2174 #undef PROGRAM_MATCH
2175
2176         if (!find)
2177           {
2178              if (!program->anonymous)
2179                ERR("Unable to find program name \"%s\".",
2180                    program->u.name);
2181              else
2182                ERR("Unable to find anonymous program.");
2183              exit(-1);
2184           }
2185
2186         if (!program->anonymous)
2187           free(program->u.name);
2188         free(program);
2189      }
2190
2191    EINA_LIST_FREE(group_lookups, group)
2192      {
2193         Edje_Part_Collection_Directory_Entry *de;
2194
2195         if (group->part)
2196           {
2197              if (group->part->type != EDJE_PART_TYPE_GROUP
2198                  && group->part->type != EDJE_PART_TYPE_TEXTBLOCK
2199                  && group->part->type != EDJE_PART_TYPE_BOX
2200                  && group->part->type != EDJE_PART_TYPE_TABLE)
2201                goto free_group;
2202           }
2203
2204         de = eina_hash_find(edje_file->collection, group->name);
2205
2206         if (!de)
2207           {
2208              Eina_Bool found = EINA_FALSE;
2209
2210              EINA_LIST_FOREACH(aliases, l, de)
2211                if (strcmp(de->entry, group->name) == 0)
2212                  {
2213                     found = EINA_TRUE;
2214                     break;
2215                  }
2216              if (!found) de = NULL;
2217           }
2218
2219         if (!de)
2220           {
2221              ERR("Unable to find group name \"%s\".", group->name);
2222              exit(-1);
2223           }
2224
2225 free_group:
2226         free(group->name);
2227         free(group);
2228      }
2229
2230    images_in_use = eina_hash_string_superfast_new(NULL);
2231
2232    EINA_LIST_FREE(image_lookups, image)
2233      {
2234         Eina_Bool find = EINA_FALSE;
2235
2236         if (edje_file->image_dir)
2237           {
2238              Edje_Image_Directory_Entry *de;
2239              unsigned int i;
2240
2241              for (i = 0; i < edje_file->image_dir->entries_count; ++i)
2242                {
2243                   de = edje_file->image_dir->entries + i;
2244
2245                   if ((de->entry) && (!strcmp(de->entry, image->name)))
2246                     {
2247                        handle_slave_lookup(image_slave_lookups, image->dest, de->id);
2248                        if (de->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
2249                          *(image->dest) = -de->id - 1;
2250                        else
2251                          *(image->dest) = de->id;
2252                        *(image->set) = EINA_FALSE;
2253                        find = EINA_TRUE;
2254
2255                        if (!eina_hash_find(images_in_use, image->name))
2256                          eina_hash_direct_add(images_in_use, de->entry, de);
2257                        break;
2258                     }
2259                }
2260
2261              if (!find)
2262                {
2263                   Edje_Image_Directory_Set *set;
2264
2265                   for (i = 0; i < edje_file->image_dir->sets_count; ++i)
2266                     {
2267                        set = edje_file->image_dir->sets + i;
2268
2269                        if ((set->name) && (!strcmp(set->name, image->name)))
2270                          {
2271                             Edje_Image_Directory_Set_Entry *child;
2272                             Eina_List *lc;
2273
2274                             handle_slave_lookup(image_slave_lookups, image->dest, set->id);
2275                             *(image->dest) = set->id;
2276                             *(image->set) = EINA_TRUE;
2277                             find = EINA_TRUE;
2278
2279                             EINA_LIST_FOREACH(set->entries, lc, child)
2280                                if (!eina_hash_find(images_in_use, child->name))
2281                                  eina_hash_direct_add(images_in_use, child->name, child);
2282
2283                             if (!eina_hash_find(images_in_use, image->name))
2284                               eina_hash_direct_add(images_in_use, set->name, set);
2285                             break;
2286                          }
2287                     }
2288                }
2289           }
2290
2291         if (!find)
2292           {
2293              ERR("Unable to find image name \"%s\".", image->name);
2294              exit(-1);
2295           }
2296
2297         free(image->name);
2298         free(image);
2299      }
2300
2301    if (edje_file->image_dir && !is_lua)
2302      {
2303         Edje_Image_Directory_Entry *de;
2304         Edje_Image_Directory_Set *set;
2305         unsigned int i;
2306
2307         for (i = 0; i < edje_file->image_dir->entries_count; ++i)
2308           {
2309              de = edje_file->image_dir->entries + i;
2310
2311              if (de->entry && eina_hash_find(images_in_use, de->entry))
2312                continue ;
2313
2314              INF("Image '%s' in resource 'edje/image/%i' will not be included as it is unused.",
2315                  de->entry, de->id);
2316
2317              de->entry = NULL;
2318           }
2319
2320         for (i = 0; i < edje_file->image_dir->sets_count; ++i)
2321           {
2322              set = edje_file->image_dir->sets + i;
2323
2324              if (set->name && eina_hash_find(images_in_use, set->name))
2325                continue ;
2326
2327              INF("Set '%s' will not be included as it is unused.", set->name);
2328
2329              set->name = NULL;
2330              set->entries = NULL;
2331           }
2332      }
2333
2334    eina_hash_free(images_in_use);
2335
2336    EINA_LIST_FREE(part_slave_lookups, data)
2337      free(data);
2338
2339    EINA_LIST_FREE(image_slave_lookups, data)
2340      free(data);
2341 }
2342
2343 static void
2344 data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char* ptr, int len))
2345 {
2346    char *p;
2347    char *key;
2348    int keyl;
2349    int quote, escape;
2350
2351    key = alloca(strlen(prefix) + 2 + 1);
2352    if (!key) return;
2353    strcpy(key, prefix);
2354    strcat(key, ":\"");
2355    keyl = strlen(key);
2356    quote = 0;
2357    escape = 0;
2358    for (p = s; (p) && (*p); p++)
2359      {
2360         if (!quote)
2361           {
2362              if (*p == '\"')
2363                {
2364                   quote = 1;
2365                   p++;
2366                }
2367           }
2368         if (!quote)
2369           {
2370              if (!strncmp(p, key, keyl))
2371                {
2372                   char *ptr;
2373                   int len;
2374                   int inesc = 0;
2375                   char *name;
2376
2377                   ptr = p;
2378                   p += keyl;
2379                   while ((*p))
2380                     {
2381                        if (!inesc)
2382                          {
2383                             if (*p == '\\') inesc = 1;
2384                             else if (*p == '\"')
2385                               {
2386                                  /* string concatenation, see below */
2387                                  if (*(p + 1) != '\"')
2388                                    break;
2389                                  else
2390                                    p++;
2391                               }
2392                          }
2393                        else
2394                             inesc = 0;
2395                        p++;
2396                     }
2397                   len = p - ptr + 1;
2398                   name = alloca(len);
2399                   if (name)
2400                     {
2401                        char *pp;
2402                        int i;
2403
2404                        name[0] = 0;
2405                        pp = ptr + keyl;
2406                        inesc = 0;
2407                        i = 0;
2408                        while (*pp)
2409                          {
2410                             if (!inesc)
2411                               {
2412                                  if (*pp == '\\') inesc = 1;
2413                                  else if (*pp == '\"')
2414                                    {
2415                                       /* concat strings like "foo""bar" to "foobar" */
2416                                       if (*(pp + 1) == '\"')
2417                                         pp++;
2418                                       else
2419                                         {
2420                                            name[i] = 0;
2421                                            break;
2422                                         }
2423                                    }
2424                                  else
2425                                    {
2426                                       name[i] = *pp;
2427                                       name[i + 1] = 0;
2428                                       i++;
2429                                    }
2430                               }
2431                             else
2432                               inesc = 0;
2433                             pp++;
2434                         }
2435                       func(pc, name, ptr, len);
2436                    }
2437               }
2438           }
2439         else
2440           {
2441              if (!escape)
2442                {
2443                   if (*p == '\"') quote = 0;
2444                   else if (*p == '\\') escape = 1;
2445                }
2446              else if (escape)
2447                {
2448                   escape = 0;
2449                }
2450           }
2451      }
2452 }
2453
2454 static void
2455 _data_queue_part_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
2456 {
2457    Code_Lookup *cl;
2458
2459    cl = mem_alloc(SZ(Code_Lookup));
2460    cl->ptr = ptr;
2461    cl->len = len;
2462
2463    data_queue_part_lookup(pc, name, &(cl->val));
2464
2465    code_lookups = eina_list_append(code_lookups, cl);
2466 }
2467 static void
2468 _data_queue_program_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
2469 {
2470    Code_Lookup *cl;
2471
2472    cl = mem_alloc(SZ(Code_Lookup));
2473    cl->ptr = ptr;
2474    cl->len = len;
2475
2476    data_queue_program_lookup(pc, name, &(cl->val));
2477
2478    code_lookups = eina_list_append(code_lookups, cl);
2479 }
2480 static void
2481 _data_queue_group_lookup(Edje_Part_Collection *pc __UNUSED__, char *name, char *ptr __UNUSED__, int len __UNUSED__)
2482 {
2483    data_queue_group_lookup(name, NULL);
2484 }
2485 static void
2486 _data_queue_image_pc_lookup(Edje_Part_Collection *pc __UNUSED__, char *name, char *ptr, int len)
2487 {
2488    Code_Lookup *cl;
2489
2490    cl = mem_alloc(SZ(Code_Lookup));
2491    cl->ptr = ptr;
2492    cl->len = len;
2493
2494    data_queue_image_lookup(name, &(cl->val),  &(cl->set));
2495
2496    code_lookups = eina_list_append(code_lookups, cl);
2497 }
2498
2499 void
2500 data_process_scripts(void)
2501 {
2502    Eina_List *l, *l2;
2503
2504    for (l = codes, l2 = edje_collections; (l) && (l2); l = eina_list_next(l), l2 = eina_list_next(l2))
2505      {
2506         Edje_Part_Collection *pc;
2507         Code *cd;
2508
2509         cd = eina_list_data_get(l);
2510         pc = eina_list_data_get(l2);
2511
2512         if ((cd->shared) && (!cd->is_lua))
2513           {
2514              data_process_string(pc, "PART",    cd->shared, _data_queue_part_lookup);
2515              data_process_string(pc, "PROGRAM", cd->shared, _data_queue_program_lookup);
2516              data_process_string(pc, "IMAGE",   cd->shared, _data_queue_image_pc_lookup);
2517              data_process_string(pc, "GROUP",   cd->shared, _data_queue_group_lookup);
2518           }
2519
2520         if (cd->programs)
2521           {
2522              Code_Program *cp;
2523              Eina_List *ll;
2524
2525              EINA_LIST_FOREACH(cd->programs, ll, cp)
2526                {
2527                   if (cp->script)
2528                     {
2529                        data_process_string(pc, "PART",    cp->script, _data_queue_part_lookup);
2530                        data_process_string(pc, "PROGRAM", cp->script, _data_queue_program_lookup);
2531                        data_process_string(pc, "IMAGE",   cp->script, _data_queue_image_pc_lookup);
2532                        data_process_string(pc, "GROUP",   cp->script, _data_queue_group_lookup);
2533                     }
2534                }
2535           }
2536      }
2537 }
2538
2539 void
2540 data_process_script_lookups(void)
2541 {
2542    Eina_List *l;
2543    Code_Lookup *cl;
2544
2545    EINA_LIST_FOREACH(code_lookups, l, cl)
2546      {
2547         char buf[12];
2548         int n;
2549
2550         /* FIXME !! Handle set in program */
2551         n = eina_convert_itoa(cl->val, buf);
2552         if (n > cl->len)
2553           {
2554              ERR("The unexpected happened. A numeric replacement string was larger than the original!");
2555              exit(-1);
2556           }
2557         memset(cl->ptr, ' ', cl->len);
2558         strncpy(cl->ptr, buf, n);
2559      }
2560 }
2561
2562 void
2563 using_file(const char *filename, const char type)
2564 {
2565    FILE *f;
2566
2567    if (!watchfile) return;
2568    f = fopen(watchfile, "ab");
2569    if (!f) return ;
2570    if (anotate)
2571      {
2572        fprintf(f, "%c: %s\n", type, filename);
2573      }
2574    else
2575      {
2576        fputs(filename, f);
2577        fputc('\n', f);
2578      }
2579    fclose(f);
2580 }