Imported Upstream version 1.7.2
[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 (pl->u.ep->name && pc->programs.fnmatch[i]->name &&
1904                       !strcmp(pl->u.ep->name, pc->programs.fnmatch[i]->name))
1905                     data_queue_anonymous_lookup(pc, pc->programs.fnmatch[i], dest);
1906                }
1907              for (i = 0 ; i < pc->programs.strcmp_count ; i++)
1908                {
1909                   if (pl->u.ep->name && pc->programs.strcmp[i]->name &&
1910                       !strcmp(pl->u.ep->name, pc->programs.strcmp[i]->name))
1911                     data_queue_anonymous_lookup(pc, pc->programs.strcmp[i], dest);
1912                }
1913              for (i = 0 ; i < pc->programs.strncmp_count ; i++)
1914                {
1915                   if (pl->u.ep->name && pc->programs.strncmp[i]->name &&
1916                       !strcmp(pl->u.ep->name, pc->programs.strncmp[i]->name))
1917                     data_queue_anonymous_lookup(pc, pc->programs.strncmp[i], dest);
1918                }
1919              for (i = 0 ; i < pc->programs.strrncmp_count ; i++)
1920                {
1921                   if (pl->u.ep->name && pc->programs.strrncmp[i]->name &&
1922                       !strcmp(pl->u.ep->name, pc->programs.strrncmp[i]->name))
1923                     data_queue_anonymous_lookup(pc, pc->programs.strrncmp[i], dest);
1924                }
1925              for (i = 0 ; i < pc->programs.nocmp_count ; i++)
1926                {
1927                   if (pl->u.ep->name && pc->programs.nocmp[i]->name &&
1928                       !strcmp(pl->u.ep->name, pc->programs.nocmp[i]->name))
1929                     data_queue_anonymous_lookup(pc, pc->programs.nocmp[i], dest);
1930                }
1931           }
1932      }
1933 }
1934
1935 void
1936 data_queue_program_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
1937 {
1938    Program_Lookup *pl;
1939
1940    if (!name) return ; /* FIXME: should we stop compiling ? */
1941
1942    pl = mem_alloc(SZ(Program_Lookup));
1943    program_lookups = eina_list_append(program_lookups, pl);
1944    pl->pc = pc;
1945    pl->u.name = mem_strdup(name);
1946    pl->dest = dest;
1947    pl->anonymous = EINA_FALSE;
1948 }
1949
1950 void
1951 data_queue_copied_program_lookup(Edje_Part_Collection *pc, int *src, int *dest)
1952 {
1953    Eina_List *l;
1954    Program_Lookup *pl;
1955
1956    EINA_LIST_FOREACH(program_lookups, l, pl)
1957      {
1958         if (pl->dest == src)
1959           data_queue_program_lookup(pc, pl->u.name, dest);
1960      }
1961 }
1962
1963 void
1964 data_queue_image_lookup(char *name, int *dest, Eina_Bool *set)
1965 {
1966    Image_Lookup *il;
1967
1968    il = mem_alloc(SZ(Image_Lookup));
1969    image_lookups = eina_list_append(image_lookups, il);
1970    il->name = mem_strdup(name);
1971    il->dest = dest;
1972    il->set = set;
1973 }
1974
1975 void
1976 data_queue_image_remove(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 == dest && il->set == set)
1984           {
1985              image_lookups = eina_list_remove_list(image_lookups, l);
1986              free(il->name);
1987              free(il);
1988              return ;
1989           }
1990      }
1991  }
1992
1993 void
1994 data_queue_copied_image_lookup(int *src, int *dest, Eina_Bool *set)
1995 {
1996    Eina_List *l;
1997    Image_Lookup *il;
1998
1999    EINA_LIST_FOREACH(image_lookups, l, il)
2000      {
2001         if (il->dest == src)
2002           data_queue_image_lookup(il->name, dest, set);
2003      }
2004 }
2005 void
2006 data_queue_part_slave_lookup(int *master, int *slave)
2007 {
2008    Slave_Lookup *sl;
2009
2010    sl = mem_alloc(SZ(Slave_Lookup));
2011    part_slave_lookups = eina_list_append(part_slave_lookups, sl);
2012    sl->master = master;
2013    sl->slave = slave;
2014 }
2015
2016 void
2017 data_queue_image_slave_lookup(int *master, int *slave)
2018 {
2019    Slave_Lookup *sl;
2020
2021    sl = mem_alloc(SZ(Slave_Lookup));
2022    image_slave_lookups = eina_list_append(image_slave_lookups, sl);
2023    sl->master = master;
2024    sl->slave = slave;
2025 }
2026
2027 void
2028 handle_slave_lookup(Eina_List *list, int *master, int value)
2029 {
2030    Eina_List *l;
2031    Slave_Lookup *sl;
2032
2033    EINA_LIST_FOREACH(list, l, sl)
2034      if (sl->master == master)
2035        *sl->slave = value;
2036 }
2037
2038 void
2039 data_process_lookups(void)
2040 {
2041    Edje_Part_Collection *pc;
2042    Part_Lookup *part;
2043    Program_Lookup *program;
2044    Group_Lookup *group;
2045    Image_Lookup *image;
2046    Eina_List *l2;
2047    Eina_List *l;
2048    Eina_Hash *images_in_use;
2049    void *data;
2050    Eina_Bool is_lua = EINA_FALSE;
2051
2052    /* remove all unreferenced Edje_Part_Collection */
2053    EINA_LIST_FOREACH_SAFE(edje_collections, l, l2, pc)
2054      {
2055         Edje_Part_Collection_Directory_Entry *alias;
2056         Edje_Part_Collection_Directory_Entry *find;
2057         Eina_List *l3;
2058         unsigned int id = 0;
2059         unsigned int i;
2060
2061         if (!pc->part)
2062           {
2063              ERR("A collection without a name was detected, that's not allowed.");
2064              exit(-1);
2065           }
2066         find = eina_hash_find(edje_file->collection, pc->part);
2067         if (find && find->id == pc->id)
2068           continue ;
2069
2070         EINA_LIST_FOREACH(aliases, l3, alias)
2071           if (alias->id == pc->id)
2072             continue ;
2073
2074         /* This Edje_Part_Collection is not used at all */
2075         edje_collections = eina_list_remove_list(edje_collections, l);
2076         l3 = eina_list_nth_list(codes, pc->id);
2077         codes = eina_list_remove_list(codes, l3);
2078
2079         /* Unref all image used by that group */
2080         for (i = 0; i < pc->parts_count; ++i)
2081           part_description_image_cleanup(pc->parts[i]);
2082
2083         /* Correct all id */
2084         EINA_LIST_FOREACH(edje_collections, l3, pc)
2085           {
2086              Eina_List *l4;
2087
2088              /* Some group could be removed from the collection, but still be referenced by alias */
2089              find = eina_hash_find(edje_file->collection, pc->part);
2090              if (pc->id != find->id) find = NULL;
2091
2092              /* Update all matching alias */
2093              EINA_LIST_FOREACH(aliases, l4, alias)
2094                if (pc->id == alias->id)
2095                  alias->id = id;
2096
2097              pc->id = id++;
2098              if (find) find->id = pc->id;
2099           }
2100      }
2101
2102    EINA_LIST_FOREACH(edje_collections, l, pc)
2103      {
2104         unsigned int count = 0;
2105         unsigned int i;
2106
2107         if (pc->lua_script_only)
2108           is_lua = EINA_TRUE;
2109 #define PROGRAM_ID_SET(Type, Pc, It, Count)                             \
2110         for (It = 0; It < Pc->programs.Type ## _count; ++It)            \
2111           {                                                             \
2112              Pc->programs.Type[It]->id = Count++;                       \
2113           }
2114
2115         PROGRAM_ID_SET(fnmatch, pc, i, count);
2116         PROGRAM_ID_SET(strcmp, pc, i, count);
2117         PROGRAM_ID_SET(strncmp, pc, i, count);
2118         PROGRAM_ID_SET(strrncmp, pc, i, count);
2119         PROGRAM_ID_SET(nocmp, pc, i, count);
2120
2121 #undef PROGRAM_ID_SET
2122      }
2123
2124    EINA_LIST_FREE(part_lookups, part)
2125      {
2126         Edje_Part *ep;
2127         unsigned int i;
2128
2129         if (!strcmp(part->name, "-"))
2130           {
2131              *(part->dest) = -1;
2132           }
2133         else
2134           {
2135              char *alias;
2136              alias = eina_hash_find(part->pc->alias, part->name);
2137              if (!alias)
2138                alias = part->name;
2139              for (i = 0; i < part->pc->parts_count; ++i)
2140                {
2141                   ep = part->pc->parts[i];
2142
2143                   if ((ep->name) && (!strcmp(ep->name, alias)))
2144                     {
2145                        handle_slave_lookup(part_slave_lookups, part->dest, ep->id);
2146                        *(part->dest) = ep->id;
2147                        break;
2148                     }
2149                }
2150
2151              if (i == part->pc->parts_count)
2152                {
2153                   ERR("Unable to find part name \"%s\" needed in group '%s'.",
2154                       alias, part->pc->part);
2155                   exit(-1);
2156                }
2157           }
2158
2159         free(part->name);
2160         free(part);
2161      }
2162
2163    EINA_LIST_FREE(program_lookups, program)
2164      {
2165         unsigned int i;
2166         Eina_Bool find = EINA_FALSE;
2167
2168 #define PROGRAM_MATCH(Type, Pl, It)                                     \
2169         for (It = 0; It < Pl->pc->programs.Type ## _count; ++It)        \
2170           {                                                             \
2171              Edje_Program *ep;                                          \
2172              \
2173              ep = Pl->pc->programs.Type[It];                            \
2174              \
2175              if ((Pl->anonymous && ep == Pl->u.ep) ||                   \
2176                  ((!Pl->anonymous) && (ep->name) && (!strcmp(ep->name, Pl->u.name)))) \
2177                {                                                        \
2178                   *(Pl->dest) = ep->id;                                 \
2179                   find = EINA_TRUE;                                     \
2180                   break;                                                \
2181                }                                                        \
2182           }
2183
2184         PROGRAM_MATCH(fnmatch, program, i);
2185         PROGRAM_MATCH(strcmp, program, i);
2186         PROGRAM_MATCH(strncmp, program, i);
2187         PROGRAM_MATCH(strrncmp, program, i);
2188         PROGRAM_MATCH(nocmp, program, i);
2189
2190 #undef PROGRAM_MATCH
2191
2192         if (!find)
2193           {
2194              if (!program->anonymous)
2195                ERR("Unable to find program name \"%s\".",
2196                    program->u.name);
2197              else
2198                ERR("Unable to find anonymous program.");
2199              exit(-1);
2200           }
2201
2202         if (!program->anonymous)
2203           free(program->u.name);
2204         free(program);
2205      }
2206
2207    EINA_LIST_FREE(group_lookups, group)
2208      {
2209         Edje_Part_Collection_Directory_Entry *de;
2210
2211         if (group->part)
2212           {
2213              if (group->part->type != EDJE_PART_TYPE_GROUP
2214                  && group->part->type != EDJE_PART_TYPE_TEXTBLOCK
2215                  && group->part->type != EDJE_PART_TYPE_BOX
2216                  && group->part->type != EDJE_PART_TYPE_TABLE)
2217                goto free_group;
2218           }
2219
2220         de = eina_hash_find(edje_file->collection, group->name);
2221
2222         if (!de)
2223           {
2224              Eina_Bool found = EINA_FALSE;
2225
2226              EINA_LIST_FOREACH(aliases, l, de)
2227                if (strcmp(de->entry, group->name) == 0)
2228                  {
2229                     found = EINA_TRUE;
2230                     break;
2231                  }
2232              if (!found) de = NULL;
2233           }
2234
2235         if (!de)
2236           {
2237              ERR("Unable to find group name \"%s\".", group->name);
2238              exit(-1);
2239           }
2240
2241 free_group:
2242         free(group->name);
2243         free(group);
2244      }
2245
2246    images_in_use = eina_hash_string_superfast_new(NULL);
2247
2248    EINA_LIST_FREE(image_lookups, image)
2249      {
2250         Eina_Bool find = EINA_FALSE;
2251
2252         if (edje_file->image_dir)
2253           {
2254              Edje_Image_Directory_Entry *de;
2255              unsigned int i;
2256
2257              for (i = 0; i < edje_file->image_dir->entries_count; ++i)
2258                {
2259                   de = edje_file->image_dir->entries + i;
2260
2261                   if ((de->entry) && (!strcmp(de->entry, image->name)))
2262                     {
2263                        handle_slave_lookup(image_slave_lookups, image->dest, de->id);
2264                        if (de->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
2265                          *(image->dest) = -de->id - 1;
2266                        else
2267                          *(image->dest) = de->id;
2268                        *(image->set) = EINA_FALSE;
2269                        find = EINA_TRUE;
2270
2271                        if (!eina_hash_find(images_in_use, image->name))
2272                          eina_hash_direct_add(images_in_use, de->entry, de);
2273                        break;
2274                     }
2275                }
2276
2277              if (!find)
2278                {
2279                   Edje_Image_Directory_Set *set;
2280
2281                   for (i = 0; i < edje_file->image_dir->sets_count; ++i)
2282                     {
2283                        set = edje_file->image_dir->sets + i;
2284
2285                        if ((set->name) && (!strcmp(set->name, image->name)))
2286                          {
2287                             Edje_Image_Directory_Set_Entry *child;
2288                             Eina_List *lc;
2289
2290                             handle_slave_lookup(image_slave_lookups, image->dest, set->id);
2291                             *(image->dest) = set->id;
2292                             *(image->set) = EINA_TRUE;
2293                             find = EINA_TRUE;
2294
2295                             EINA_LIST_FOREACH(set->entries, lc, child)
2296                                if (!eina_hash_find(images_in_use, child->name))
2297                                  eina_hash_direct_add(images_in_use, child->name, child);
2298
2299                             if (!eina_hash_find(images_in_use, image->name))
2300                               eina_hash_direct_add(images_in_use, set->name, set);
2301                             break;
2302                          }
2303                     }
2304                }
2305           }
2306
2307         if (!find)
2308           {
2309              ERR("Unable to find image name \"%s\".", image->name);
2310              exit(-1);
2311           }
2312
2313         free(image->name);
2314         free(image);
2315      }
2316
2317    if (edje_file->image_dir && !is_lua)
2318      {
2319         Edje_Image_Directory_Entry *de;
2320         Edje_Image_Directory_Set *set;
2321         unsigned int i;
2322
2323         for (i = 0; i < edje_file->image_dir->entries_count; ++i)
2324           {
2325              de = edje_file->image_dir->entries + i;
2326
2327              if (de->entry && eina_hash_find(images_in_use, de->entry))
2328                continue ;
2329
2330              INF("Image '%s' in resource 'edje/image/%i' will not be included as it is unused.",
2331                  de->entry, de->id);
2332
2333              de->entry = NULL;
2334           }
2335
2336         for (i = 0; i < edje_file->image_dir->sets_count; ++i)
2337           {
2338              set = edje_file->image_dir->sets + i;
2339
2340              if (set->name && eina_hash_find(images_in_use, set->name))
2341                continue ;
2342
2343              INF("Set '%s' will not be included as it is unused.", set->name);
2344
2345              set->name = NULL;
2346              set->entries = NULL;
2347           }
2348      }
2349
2350    eina_hash_free(images_in_use);
2351
2352    EINA_LIST_FREE(part_slave_lookups, data)
2353      free(data);
2354
2355    EINA_LIST_FREE(image_slave_lookups, data)
2356      free(data);
2357 }
2358
2359 static void
2360 data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char* ptr, int len))
2361 {
2362    char *p;
2363    char *key;
2364    int keyl;
2365    int quote, escape;
2366
2367    key = alloca(strlen(prefix) + 2 + 1);
2368    if (!key) return;
2369    strcpy(key, prefix);
2370    strcat(key, ":\"");
2371    keyl = strlen(key);
2372    quote = 0;
2373    escape = 0;
2374    for (p = s; (p) && (*p); p++)
2375      {
2376         if (!quote)
2377           {
2378              if (*p == '\"')
2379                {
2380                   quote = 1;
2381                   p++;
2382                }
2383           }
2384         if (!quote)
2385           {
2386              if (!strncmp(p, key, keyl))
2387                {
2388                   char *ptr;
2389                   int len;
2390                   int inesc = 0;
2391                   char *name;
2392
2393                   ptr = p;
2394                   p += keyl;
2395                   while ((*p))
2396                     {
2397                        if (!inesc)
2398                          {
2399                             if (*p == '\\') inesc = 1;
2400                             else if (*p == '\"')
2401                               {
2402                                  /* string concatenation, see below */
2403                                  if (*(p + 1) != '\"')
2404                                    break;
2405                                  else
2406                                    p++;
2407                               }
2408                          }
2409                        else
2410                             inesc = 0;
2411                        p++;
2412                     }
2413                   len = p - ptr + 1;
2414                   name = alloca(len);
2415                   if (name)
2416                     {
2417                        char *pp;
2418                        int i;
2419
2420                        name[0] = 0;
2421                        pp = ptr + keyl;
2422                        inesc = 0;
2423                        i = 0;
2424                        while (*pp)
2425                          {
2426                             if (!inesc)
2427                               {
2428                                  if (*pp == '\\') inesc = 1;
2429                                  else if (*pp == '\"')
2430                                    {
2431                                       /* concat strings like "foo""bar" to "foobar" */
2432                                       if (*(pp + 1) == '\"')
2433                                         pp++;
2434                                       else
2435                                         {
2436                                            name[i] = 0;
2437                                            break;
2438                                         }
2439                                    }
2440                                  else
2441                                    {
2442                                       name[i] = *pp;
2443                                       name[i + 1] = 0;
2444                                       i++;
2445                                    }
2446                               }
2447                             else
2448                               inesc = 0;
2449                             pp++;
2450                         }
2451                       func(pc, name, ptr, len);
2452                    }
2453               }
2454           }
2455         else
2456           {
2457              if (!escape)
2458                {
2459                   if (*p == '\"') quote = 0;
2460                   else if (*p == '\\') escape = 1;
2461                }
2462              else if (escape)
2463                {
2464                   escape = 0;
2465                }
2466           }
2467      }
2468 }
2469
2470 static void
2471 _data_queue_part_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
2472 {
2473    Code_Lookup *cl;
2474
2475    cl = mem_alloc(SZ(Code_Lookup));
2476    cl->ptr = ptr;
2477    cl->len = len;
2478
2479    data_queue_part_lookup(pc, name, &(cl->val));
2480
2481    code_lookups = eina_list_append(code_lookups, cl);
2482 }
2483 static void
2484 _data_queue_program_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
2485 {
2486    Code_Lookup *cl;
2487
2488    cl = mem_alloc(SZ(Code_Lookup));
2489    cl->ptr = ptr;
2490    cl->len = len;
2491
2492    data_queue_program_lookup(pc, name, &(cl->val));
2493
2494    code_lookups = eina_list_append(code_lookups, cl);
2495 }
2496 static void
2497 _data_queue_group_lookup(Edje_Part_Collection *pc __UNUSED__, char *name, char *ptr __UNUSED__, int len __UNUSED__)
2498 {
2499    data_queue_group_lookup(name, NULL);
2500 }
2501 static void
2502 _data_queue_image_pc_lookup(Edje_Part_Collection *pc __UNUSED__, char *name, char *ptr, int len)
2503 {
2504    Code_Lookup *cl;
2505
2506    cl = mem_alloc(SZ(Code_Lookup));
2507    cl->ptr = ptr;
2508    cl->len = len;
2509
2510    data_queue_image_lookup(name, &(cl->val),  &(cl->set));
2511
2512    code_lookups = eina_list_append(code_lookups, cl);
2513 }
2514
2515 void
2516 data_process_scripts(void)
2517 {
2518    Eina_List *l, *l2;
2519
2520    for (l = codes, l2 = edje_collections; (l) && (l2); l = eina_list_next(l), l2 = eina_list_next(l2))
2521      {
2522         Edje_Part_Collection *pc;
2523         Code *cd;
2524
2525         cd = eina_list_data_get(l);
2526         pc = eina_list_data_get(l2);
2527
2528         if ((cd->shared) && (!cd->is_lua))
2529           {
2530              data_process_string(pc, "PART",    cd->shared, _data_queue_part_lookup);
2531              data_process_string(pc, "PROGRAM", cd->shared, _data_queue_program_lookup);
2532              data_process_string(pc, "IMAGE",   cd->shared, _data_queue_image_pc_lookup);
2533              data_process_string(pc, "GROUP",   cd->shared, _data_queue_group_lookup);
2534           }
2535
2536         if (cd->programs)
2537           {
2538              Code_Program *cp;
2539              Eina_List *ll;
2540
2541              EINA_LIST_FOREACH(cd->programs, ll, cp)
2542                {
2543                   if (cp->script)
2544                     {
2545                        data_process_string(pc, "PART",    cp->script, _data_queue_part_lookup);
2546                        data_process_string(pc, "PROGRAM", cp->script, _data_queue_program_lookup);
2547                        data_process_string(pc, "IMAGE",   cp->script, _data_queue_image_pc_lookup);
2548                        data_process_string(pc, "GROUP",   cp->script, _data_queue_group_lookup);
2549                     }
2550                }
2551           }
2552      }
2553 }
2554
2555 void
2556 data_process_script_lookups(void)
2557 {
2558    Eina_List *l;
2559    Code_Lookup *cl;
2560
2561    EINA_LIST_FOREACH(code_lookups, l, cl)
2562      {
2563         char buf[12];
2564         int n;
2565
2566         /* FIXME !! Handle set in program */
2567         n = eina_convert_itoa(cl->val, buf);
2568         if (n > cl->len)
2569           {
2570              ERR("The unexpected happened. A numeric replacement string was larger than the original!");
2571              exit(-1);
2572           }
2573         memset(cl->ptr, ' ', cl->len);
2574         strncpy(cl->ptr, buf, n);
2575      }
2576 }
2577
2578 void
2579 using_file(const char *filename)
2580 {
2581    FILE *f;
2582
2583    if (!watchfile) return;
2584    f = fopen(watchfile, "ab");
2585    if (!f) return ;
2586    fputs(filename, f);
2587    fputc('\n', f);
2588    fclose(f);
2589 }