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