Imported Upstream version 1.7.3
[platform/upstream/edje.git] / src / bin / edje_inspector.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <locale.h>
6 #include <fnmatch.h>
7 #include <unistd.h>
8 #include <errno.h>
9
10 #include "Edje.h"
11 #define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT 1
12 #include "Edje_Edit.h"
13
14 #include <Ecore.h>
15 #include <Ecore_Evas.h>
16 #include <Ecore_Getopt.h>
17
18 static int _log_dom;
19 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
20 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
21 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
22 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
23 #define CRIT(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
24
25 #define INDENT "   "
26 #define INDENT2 INDENT INDENT
27 #define INDENT3 INDENT2 INDENT
28 #define INDENT4 INDENT3 INDENT
29 #define INDENT5 INDENT4 INDENT
30 #define INDENT6 INDENT5 INDENT
31 #define INDENT7 INDENT6 INDENT
32
33 #define FLOAT_PRECISION 0.0001
34 #define FDIFF(a, b) (fabs((a) - (b)) > FLOAT_PRECISION)
35
36 /* context */
37 static Eina_List *groups;
38 static Ecore_Evas *ee;
39
40 /* options */
41 static const char *file;
42 static char *group = NULL;
43 static char *part = NULL;
44 static char *program = NULL;
45 static int detail = 1;
46 static Eina_Bool api_only = EINA_FALSE;
47 static Eina_Bool api_fix = EINA_FALSE;
48 static Eina_Bool machine = EINA_FALSE;
49
50 static const char *mode_choices[] = {
51   "groups",
52   "parts",
53   "programs",
54   "groups-names",
55   "part-names",
56   "global-data",
57   "images",
58   "fonts",
59   "externals",
60   NULL,
61 };
62
63 static const char *detail_choices[] = {
64   "none",
65   "terse",
66   "all",
67   NULL
68 };
69
70 const Ecore_Getopt optdesc = {
71   "edje_inspector",
72   "%prog [options] <file.edj>",
73   PACKAGE_VERSION,
74   "(C) 2010 - The Enlightenment Project",
75   "BSD",
76   "Edje file inspector, let one see groups, parts, programs and other details "
77   "of a compiled (binary) edje file.\n",
78   0,
79   {
80     ECORE_GETOPT_CHOICE('m', "mode", "Choose which mode to operate on file.",
81                         mode_choices),
82     ECORE_GETOPT_CHOICE('d', "detail", "Choose detail level (default=terse)",
83                         detail_choices),
84     ECORE_GETOPT_STORE_STR('g', "group", "Limit output to group (or glob)."),
85     ECORE_GETOPT_STORE_STR('p', "part", "Limit output to part (or glob)."),
86     ECORE_GETOPT_STORE_STR('r', "program",
87                            "Limit output to program (or glob)."),
88     ECORE_GETOPT_STORE_TRUE('a', "api-only", "Limit to just api parts or "
89                             "programs."),
90     ECORE_GETOPT_STORE_TRUE('A', "api-fix", "Fix API names to be C compliant."),
91     ECORE_GETOPT_STORE_TRUE('M', "machine", "Produce machine readable output."),
92     ECORE_GETOPT_LICENSE('L', "license"),
93     ECORE_GETOPT_COPYRIGHT('C', "copyright"),
94     ECORE_GETOPT_VERSION('V', "version"),
95     ECORE_GETOPT_HELP('h', "help"),
96     ECORE_GETOPT_SENTINEL
97   }
98 };
99
100 static inline Eina_Bool
101 matches(const char *name, const char *pattern)
102 {
103    if (!pattern) return EINA_TRUE;
104    return fnmatch(pattern, name, 0) == 0;
105 }
106
107 static void
108 group_begin(const char *name)
109 {
110    if (machine) printf("GROUP-BEGIN\nNAME: %s\n", name);
111    else printf("group { name: '%s';\n", name);
112 }
113
114 static void
115 group_end(void)
116 {
117    if (machine) puts("GROUP-END");
118    else puts("}");
119 }
120
121 static void
122 group_details(Evas_Object *ed)
123 {
124    int w, h;
125
126    if (detail < 1) return;
127
128    if (machine) puts("GROUP-DETAILS-BEGIN");
129
130    w = edje_edit_group_min_w_get(ed);
131    h = edje_edit_group_min_h_get(ed);
132    if (machine) printf("MIN-W: %d\nMIN-H: %d\n", w, h);
133    else if ((w > 0) || (h > 0)) printf(INDENT "min: %d %d;\n", w, h);
134
135    w = edje_edit_group_max_w_get(ed);
136    h = edje_edit_group_max_h_get(ed);
137    if (machine) printf("MAX-W: %d\nMAX-H: %d\n", w, h);
138    else if ((w > 0) || (h > 0)) printf(INDENT "max: %d %d;\n", w, h);
139
140    if (detail > 1)
141      {
142         Eina_List *dl;
143         dl = edje_edit_group_data_list_get(ed);
144         if (dl)
145           {
146              Eina_List *l;
147              const char *k;
148              if (machine) puts(INDENT "GROUP-DETAILS-DATA-BEGIN");
149              else puts(INDENT "data {");
150
151              EINA_LIST_FOREACH(dl, l, k)
152                {
153                   const char *v = edje_edit_group_data_value_get(ed, k);
154                   if (machine) printf("ITEM: \"%s\" \"%s\"\n", k, v);
155                   else printf(INDENT2 "item: \"%s\" \"%s\";\n", k, v);
156                }
157
158              edje_edit_string_list_free(dl);
159
160              if (machine) puts(INDENT "GROUP-DETAILS-DATA-END");
161              else puts(INDENT "}");
162           }
163      }
164
165    if (machine) puts("GROUP-DETAILS-END");
166 }
167
168 static void
169 parts_begin(void)
170 {
171    if (machine) puts("PARTS-BEGIN");
172    else puts(INDENT "parts {");
173 }
174
175 static void
176 parts_end(void)
177 {
178    if (machine) puts("PARTS-END");
179    else puts(INDENT "}");
180 }
181
182 static const char *
183 part_type_name_get(Edje_Part_Type t)
184 {
185    switch (t)
186      {
187       case EDJE_PART_TYPE_RECTANGLE:
188          return "RECT";
189       case EDJE_PART_TYPE_TEXT:
190          return "TEXT";
191       case EDJE_PART_TYPE_IMAGE:
192          return "IMAGE";
193       case EDJE_PART_TYPE_PROXY:
194          return "PROXY";
195       case EDJE_PART_TYPE_SWALLOW:
196          return "SWALLOW";
197       case EDJE_PART_TYPE_TEXTBLOCK:
198          return "TEXTBLOCK";
199       case EDJE_PART_TYPE_GRADIENT:
200          return "GRADIENT";
201       case EDJE_PART_TYPE_GROUP:
202          return "GROUP";
203       case EDJE_PART_TYPE_BOX:
204          return "BOX";
205       case EDJE_PART_TYPE_TABLE:
206          return "TABLE";
207       case EDJE_PART_TYPE_EXTERNAL:
208          return "EXTERNAL";
209       case EDJE_PART_TYPE_SPACER:
210          return "SPACER";
211
212       case EDJE_PART_TYPE_NONE:
213       case EDJE_PART_TYPE_LAST:
214          ERR("Invalid part type %d", t);
215          return "???";
216       default:
217          ERR("Unknown part type %d", t);
218          return "???";
219      }
220 }
221
222 static void
223 state_begin(const char *state, double value)
224 {
225    if (machine)
226      printf("PART-STATE-BEGIN\nNAME: %s\nVALUE: %2.1f\n", state, value);
227    else
228      {
229         printf(INDENT3 "description { state: \"%s\" %2.1f;", state, value);
230         if (detail > 0) putchar('\n');
231      }
232 }
233
234 static const char *
235 aspect_pref_name_get(int id)
236 {
237    switch (id)
238      {
239       case 0: return "NONE";
240       case 1: return "VERTICAL";
241       case 2: return "HORIZONTAL";
242       case 3: return "BOTH";
243       default:
244          ERR("Unknown aspect preference %d", id);
245          return "???";
246      }
247 }
248
249 static const char *
250 border_fill_name_get(int id)
251 {
252    switch (id)
253      {
254       case 0: return "NONE";
255       case 1: return "DEFAULT";
256       case 2: return "SOLID";
257       default:
258          ERR("Unknown border fill %d", id);
259          return "???";
260      }
261 }
262
263 static void
264 state_details(Evas_Object *ed, const char *ppart, const char *state, double value)
265 {
266    Edje_Part_Type t = edje_edit_part_type_get(ed, ppart);
267    double dx, dy;
268    const char *str, *str2;
269    int x, y, r, g, b, a;
270
271    if (detail < 1) return;
272
273    b = edje_edit_state_visible_get(ed, ppart, state, value);
274    if (machine) printf("VISIBLE: %d\n", b);
275    else if (!b) puts(INDENT4 "visible: 0;");
276
277    edje_edit_state_color_get(ed, ppart, state, value, &r, &g, &b, &a);
278    if (machine)
279      printf("COLOR-R: %d\nCOLOR-G: %d\nCOLOR-B: %d\nCOLOR-A: %d\n", r, g, b, a);
280    else if ((r != 255) || (g != 255) || (b != 255) || (a != 255))
281      printf(INDENT4 "color: %d %d %d %d;\n", r, g, b, a);
282
283    if (detail > 1)
284      {
285         edje_edit_state_color2_get(ed, ppart, state, value, &r, &g, &b, &a);
286         if (machine)
287           printf("COLOR2-R: %d\nCOLOR2-G: %d\nCOLOR2-B: %d\nCOLOR2-A: %d\n",
288                  r, g, b, a);
289         else if ((r != 255) || (g != 255) || (b != 255) || (a != 255))
290           printf(INDENT4 "color2: %d %d %d %d;\n", r, g, b, a);
291
292         edje_edit_state_color3_get(ed, ppart, state, value, &r, &g, &b, &a);
293         if (machine)
294           printf("COLOR3-R: %d\nCOLOR3-G: %d\nCOLOR3-B: %d\nCOLOR3-A: %d\n",
295                  r, g, b, a);
296         else if ((r != 255) || (g != 255) || (b != 255) || (a != 255))
297           printf(INDENT4 "color3: %d %d %d %d;\n", r, g, b, a);
298      }
299
300    dx = edje_edit_state_align_x_get(ed, ppart, state, value);
301    dy = edje_edit_state_align_y_get(ed, ppart, state, value);
302    if (machine) printf("ALIGN-X: %g\nALIGN-Y: %g\n", dx, dy);
303    else if (FDIFF(dx, 0.5) || FDIFF(dy, 0.5))
304      printf(INDENT4 "align: %g %g;\n", dx, dy);
305
306    x = edje_edit_state_min_w_get(ed, ppart, state, value);
307    y = edje_edit_state_min_h_get(ed, ppart, state, value);
308    if (machine) printf("MIN-W: %d\nMIN-H: %d\n", x, y);
309    else if ((x) || (y)) printf(INDENT4 "min: %d %d;\n", x, y);
310
311    x = edje_edit_state_max_w_get(ed, ppart, state, value);
312    y = edje_edit_state_max_h_get(ed, ppart, state, value);
313    if (machine) printf("MAX-W: %d\nMAX-H: %d\n", x, y);
314    else if ((x != -1) || (y != -1)) printf(INDENT4 "max: %d %d;\n", x, y);
315
316    //TODO Support fixed
317    //TODO Support step
318
319    if (detail > 1)
320      {
321         dx = edje_edit_state_aspect_min_get(ed, ppart, state, value);
322         dy = edje_edit_state_aspect_max_get(ed, ppart, state, value);
323         if (machine) printf("ASPECT-MIN: %g\nASPECT-MAX: %g\n", dx, dy);
324         else if (FDIFF(dx, 0.0) || FDIFF(dy, 0.0))
325           printf(INDENT4 "aspect: %g %g;\n", dx, dy);
326
327         x = edje_edit_state_aspect_pref_get(ed, ppart, state, value);
328         str = aspect_pref_name_get(x);
329         if (machine) printf("ASPECT-PREFERENCE: %s\n", str);
330         else if (x) printf(INDENT4 "aspect_preference: %s;\n", str);
331         /* do not free this str! */
332
333         str = edje_edit_state_color_class_get(ed, ppart, state, value);
334         if (machine) printf("COLOR_CLASS: %s\n", str ? str : "");
335         else if (str) printf(INDENT4 "color_class: \"%s\";\n", str);
336         edje_edit_string_free(str);
337      }
338
339    dx = edje_edit_state_rel1_relative_x_get(ed, ppart, state, value);
340    dy = edje_edit_state_rel1_relative_y_get(ed, ppart, state, value);
341    x = edje_edit_state_rel1_offset_x_get(ed, ppart, state, value);
342    y = edje_edit_state_rel1_offset_y_get(ed, ppart, state, value);
343    str = edje_edit_state_rel1_to_x_get(ed, ppart, state, value);
344    str2 = edje_edit_state_rel1_to_y_get(ed, ppart, state, value);
345    if (FDIFF(dx, 0.0) || FDIFF(dy, 0.0) || (x) || (y) || (str) || (str2))
346      {
347         if (machine) puts("REL1-BEGIN");
348         else puts(INDENT4 "rel1 {");
349
350         if (machine) printf("RELATIVE-X: %g\nRELATIVE-Y: %g\n", dx, dy);
351         else if (FDIFF(dx, 0.0) || FDIFF(dy, 0.0))
352           printf(INDENT5 "relative: %g %g;\n", dx, dy);
353
354         if (machine) printf("OFFSET-X: %d\nOFFSET-Y: %d\n", x, y);
355         else if ((x) || (y)) printf(INDENT5 "offset: %d %d;\n", x, y);
356
357         if (machine)
358           printf("TO-X: %s\nTO-Y: %s\n", str ? str : "", str2 ? str2 : "");
359         else if (((str) && (str2)) && (!strcmp(str, str2)))
360           printf(INDENT5 "to: \"%s\";\n", str);
361         else
362           {
363              if (str) printf(INDENT5 "to_x: \"%s\";\n", str);
364              if (str2) printf(INDENT5 "to_y: \"%s\";\n", str2);
365           }
366
367         if (machine) puts("REL1-END");
368         else puts(INDENT4 "}");
369      }
370    edje_edit_string_free(str);
371    edje_edit_string_free(str2);
372
373    dx = edje_edit_state_rel2_relative_x_get(ed, ppart, state, value);
374    dy = edje_edit_state_rel2_relative_y_get(ed, ppart, state, value);
375    x = edje_edit_state_rel2_offset_x_get(ed, ppart, state, value);
376    y = edje_edit_state_rel2_offset_y_get(ed, ppart, state, value);
377    str = edje_edit_state_rel2_to_x_get(ed, ppart, state, value);
378    str2 = edje_edit_state_rel2_to_y_get(ed, ppart, state, value);
379    if (FDIFF(dx, 1.0) || FDIFF(dy, 1.0) || (x != -1) || (y != -1) ||
380        (str) || (str2))
381      {
382         if (machine) puts("REL2-BEGIN");
383         else puts(INDENT4 "rel2 {");
384
385         if (machine) printf("RELATIVE-X: %g\nRELATIVE-Y: %g\n", dx, dy);
386         else if (FDIFF(dx, 1.0) || FDIFF(dy, 1.0))
387           printf(INDENT5 "relative: %g %g;\n", dx, dy);
388
389         if (machine) printf("OFFSET-X: %d\nOFFSET-Y: %d\n", x, y);
390         else if ((x != -1) || (y != -1))
391           printf(INDENT5 "offset: %d %d;\n", x, y);
392
393         if (machine)
394           printf("TO-X: %s\nTO-Y: %s\n", str ? str : "", str2 ? str2 : "");
395         else if (((str) && (str2)) && (!strcmp(str, str2)))
396           printf(INDENT5 "to: \"%s\";\n", str);
397         else
398           {
399              if (str) printf(INDENT5 "to_x: \"%s\";\n", str);
400              if (str2) printf(INDENT5 "to_y: \"%s\";\n", str2);
401           }
402
403         if (machine) puts("REL2-END");
404         else puts(INDENT4 "}");
405      }
406    edje_edit_string_free(str);
407    edje_edit_string_free(str2);
408
409    if (t == EDJE_PART_TYPE_IMAGE)
410      {
411         str = edje_edit_state_image_get(ed, ppart, state, value);
412
413         if (machine) printf("IMAGE-BEGIN\nNORMAL: %s\n", str ? str : "");
414         else if (detail > 1)
415           {
416              puts(INDENT4 "image {");
417              if (str) printf(INDENT5 "normal: \"%s\";\n", str);
418           }
419         else if (str) printf(INDENT4 "image.normal: \"%s\";\n", str);
420
421         edje_edit_string_free(str);
422
423         if (detail > 1)
424           {
425              Eina_List *tweens, *l;
426              int bl, br, bt, bb, x2, y2;
427              double dx2, dy2;
428              Eina_Bool has_orgin, has_size;
429
430              tweens = edje_edit_state_tweens_list_get(ed, ppart, state, value);
431              EINA_LIST_FOREACH(tweens, l, str)
432                {
433                   if (machine) printf("TWEEN: %s\n", str);
434                   else printf(INDENT5 "tween: \"%s\";\n", str);
435                }
436              edje_edit_string_list_free(tweens);
437
438              edje_edit_state_image_border_get
439                (ed, ppart, state, value, &bl, &br, &bt, &bb);
440              if (machine)
441                printf("BORDER-LEFT: %d\nBORDER-RIGHT: %d\n"
442                       "BORDER-TOP: %d\nBORDER-BOTTOM: %d\n", bl, br, bt, bb);
443              else if ((bl) || (br) || (bt) || (bb))
444                printf(INDENT5 "border: %d %d %d %d;\n", bl, br, bt, bb);
445
446              x = edje_edit_state_image_border_fill_get(ed, ppart, state, value);
447              str = border_fill_name_get(x);
448              if (machine) printf("BORDER-FILL: %s\n", str);
449              else if (x != 1) printf(INDENT5 "middle: %s;\n", str);
450              /* do not free str! */
451
452              // TODO support image.fill.smooth
453
454              dx = edje_edit_state_fill_origin_relative_x_get
455                (ed, ppart, state, value);
456              dy = edje_edit_state_fill_origin_relative_y_get
457                (ed, ppart, state, value);
458              x = edje_edit_state_fill_origin_offset_x_get
459                (ed, ppart, state, value);
460              y = edje_edit_state_fill_origin_offset_y_get
461                (ed, ppart, state, value);
462
463              dx2 = edje_edit_state_fill_size_relative_x_get
464                (ed, ppart, state, value);
465              dy2 = edje_edit_state_fill_size_relative_y_get
466                (ed, ppart, state, value);
467              x2 = edje_edit_state_fill_size_offset_x_get
468                (ed, ppart, state, value);
469              y2 = edje_edit_state_fill_size_offset_y_get
470                (ed, ppart, state, value);
471
472              has_orgin = (FDIFF(dx, 0.0) || FDIFF(dy, 0.0) || (x) || (y));
473              has_size = (FDIFF(dx2, 1.0) || FDIFF(dy2, 1.0) || (x2) || (y2));
474
475              if ((has_orgin) || (has_size))
476                {
477                   if (machine) puts("IMAGE-FILL-BEGIN");
478                   else puts(INDENT5 "fill {");
479
480                   if (has_orgin)
481                     {
482                        if (machine)
483                          printf("ORIGIN-RELATIVE-X: %g\n"
484                                 "ORIGIN-RELATIVE-Y: %g\n"
485                                 "ORIGIN-OFFSET-X: %d\n"
486                                 "ORIGIN-OFFSET-Y: %d\n",
487                                 dx, dy, x, y);
488                        else
489                          printf(INDENT6 "origin {\n"
490                                 INDENT7 "relative: %g %g;\n"
491                                 INDENT7 "offset: %d %d;\n"
492                                 INDENT6 "}\n",
493                                 dx, dy, x, y);
494                     }
495
496                   if (has_size)
497                     {
498                        if (machine)
499                          printf("SIZE-RELATIVE-X: %g\n"
500                                 "SIZE-RELATIVE-Y: %g\n"
501                                 "SIZE-OFFSET-X: %d\n"
502                                 "SIZE-OFFSET-Y: %d\n",
503                                 dx2, dy2, x2, y2);
504                        else
505                          printf(INDENT6 "size {\n"
506                                 INDENT7 "relative: %g %g;\n"
507                                 INDENT7 "offset: %d %d;\n"
508                                 INDENT6 "}\n",
509                                 dx2, dy2, x2, y2);
510                     }
511
512                   if (machine) puts("IMAGE-FILL-END");
513                   else puts(INDENT5 "}");
514                }
515           }
516
517         if (machine) puts("IMAGE-END");
518         else if (detail > 1) puts(INDENT4 "}");
519      }
520    else if (t == EDJE_PART_TYPE_PROXY)
521      { 
522        int x2, y2;
523        double dx2, dy2;
524        Eina_Bool has_orgin, has_size;
525
526        if (machine) puts("PROXY-BEGIN");
527        else puts(INDENT4 "proxy {");
528        // TODO Support source
529        // TODO support proxy.fill.smooth
530
531        dx = edje_edit_state_fill_origin_relative_x_get
532          (ed, ppart, state, value);
533        dy = edje_edit_state_fill_origin_relative_y_get
534          (ed, ppart, state, value);
535        x = edje_edit_state_fill_origin_offset_x_get
536          (ed, ppart, state, value);
537        y = edje_edit_state_fill_origin_offset_y_get
538          (ed, ppart, state, value);
539
540        dx2 = edje_edit_state_fill_size_relative_x_get
541          (ed, ppart, state, value);
542        dy2 = edje_edit_state_fill_size_relative_y_get
543          (ed, ppart, state, value);
544        x2 = edje_edit_state_fill_size_offset_x_get
545          (ed, ppart, state, value);
546        y2 = edje_edit_state_fill_size_offset_y_get
547          (ed, ppart, state, value);
548
549        has_orgin = (FDIFF(dx, 0.0) || FDIFF(dy, 0.0) || (x) || (y));
550        has_size = (FDIFF(dx2, 1.0) || FDIFF(dy2, 1.0) || (x2) || (y2));
551
552        if ((has_orgin) || (has_size))
553          {
554            if (machine) puts("PROXY-FILL-BEGIN");
555            else puts(INDENT5 "fill {");
556
557            if (has_orgin)
558              {
559                if (machine)
560                  printf("ORIGIN-RELATIVE-X: %g\n"
561                         "ORIGIN-RELATIVE-Y: %g\n"
562                         "ORIGIN-OFFSET-X: %d\n"
563                         "ORIGIN-OFFSET-Y: %d\n",
564                         dx, dy, x, y);
565                else
566                  printf(INDENT6 "origin {\n"
567                         INDENT7 "relative: %g %g;\n"
568                         INDENT7 "offset: %d %d;\n"
569                         INDENT6 "}\n",
570                         dx, dy, x, y);
571              }
572
573            if (has_size)
574              {
575                if (machine)
576                  printf("SIZE-RELATIVE-X: %g\n"
577                         "SIZE-RELATIVE-Y: %g\n"
578                         "SIZE-OFFSET-X: %d\n"
579                         "SIZE-OFFSET-Y: %d\n",
580                         dx2, dy2, x2, y2);
581                else
582                  printf(INDENT6 "size {\n"
583                         INDENT7 "relative: %g %g;\n"
584                         INDENT7 "offset: %d %d;\n"
585                         INDENT6 "}\n",
586                         dx2, dy2, x2, y2);
587              }
588
589            if (machine) puts("PROXY-FILL-END");
590            else puts(INDENT5 "}");
591          }
592
593         if (machine) puts("PROXY-END");
594         else puts(INDENT4 "}");       
595      }
596    else if ((t == EDJE_PART_TYPE_TEXTBLOCK) || (t == EDJE_PART_TYPE_TEXT))
597      {
598         if (machine) puts("TEXT-BEGIN");
599         else puts(INDENT4 "text {");
600
601         str = edje_edit_state_text_get(ed, ppart, state, value);
602         if (machine) printf("TEXT: %s\n", str ? str : "");
603         else if (str) printf(INDENT5 "text: \"%s\";\n", str);
604         edje_edit_string_free(str);
605
606         str = edje_edit_state_font_get(ed, ppart, state, value);
607         if (machine) printf("FONT: %s\n", str ? str : "");
608         else if (str) printf(INDENT5 "font: \"%s\";\n", str);
609         edje_edit_string_free(str);
610
611         x = edje_edit_state_text_size_get(ed, ppart, state, value);
612         if (machine) printf("SIZE: %d\n", x);
613         else if (x > 0) printf(INDENT5 "size: %d;\n", x);
614
615         // TODO text_class
616
617         dx = edje_edit_state_text_align_x_get(ed, ppart, state, value);
618         dy = edje_edit_state_text_align_y_get(ed, ppart, state, value);
619         if (machine) printf("TEXT-ALIGN-X: %g\nTEXT-ALIGN-Y: %g\n", dx, dy);
620         else if (FDIFF(dx, 0.5) || FDIFF(dy, 0.5))
621           printf(INDENT5 "align: %g %g;\n", dx, dy);
622
623         x = edje_edit_state_text_fit_x_get(ed, ppart, state, value);
624         y = edje_edit_state_text_fit_y_get(ed, ppart, state, value);
625         if (machine) printf("TEXT-FIT-X: %d\nTEXT-FIT-Y: %d\n", x, y);
626         else if ((x) || (y)) printf(INDENT5 "fit: %d %d;\n", x, y);
627
628         dx = edje_edit_state_text_elipsis_get(ed, ppart, state, value);
629         if (machine) printf("TEXT-ELIPSIS: %g\n", dx);
630         else if (FDIFF(dx, 0.5)) printf(INDENT5 "elipsis: %g;\n", dx);
631
632         if (machine) puts("TEXT-END");
633         else puts(INDENT4 "}");
634      }
635    else if (t == EDJE_PART_TYPE_EXTERNAL)
636      {
637         const Eina_List *params, *l;
638         const Edje_External_Param *p;
639
640         params = edje_edit_state_external_params_list_get
641           (ed, ppart, state, value);
642
643         if (params)
644           {
645              if (machine) puts("PARAMS-BEGIN");
646              else puts(INDENT4 "params {");
647
648              EINA_LIST_FOREACH(params, l, p)
649                switch (p->type)
650                  {
651                   case EDJE_EXTERNAL_PARAM_TYPE_INT:
652                      printf(INDENT5 "int: \"%s\" \"%d\";\n", p->name, p->i);
653                      break;
654                   case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
655                      printf(INDENT5 "double: \"%s\" \"%g\";\n", p->name, p->d);
656                      break;
657                   case EDJE_EXTERNAL_PARAM_TYPE_STRING:
658                      if (p->s)
659                        printf(INDENT5 "string: \"%s\" \"%s\";\n",
660                               p->name, p->s);
661                      break;
662                   case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
663                      printf(INDENT5 "bool: \"%s\" \"%d\";\n", p->name, p->i);
664                      break;
665                   case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
666                      if (p->s)
667                        printf(INDENT5 "choice: \"%s\" \"%s\";\n",
668                               p->name, p->s);
669                      break;
670                   default:
671                      break;
672                  }
673
674              if (machine) puts("PARAMS-END");
675              else puts(INDENT4 "}");
676           }
677      }
678 }
679
680 static void
681 state_end(void)
682 {
683    if (machine) puts("PART-STATE-END");
684    else if (detail > 0) puts(INDENT3 "}");
685    else puts(" }");
686 }
687
688 static void
689 part_begin(Evas_Object *ed, const char *name)
690 {
691    const char *type = part_type_name_get(edje_edit_part_type_get(ed, name));
692    if (machine) printf("PART-BEGIN\nNAME: %s\nTYPE: %s\n", name, type);
693    else
694      {
695         printf(INDENT2 "part { name: '%s'; type: %s;", name, type);
696         if (detail > 0) putchar('\n');
697      }
698 }
699
700 static const char *
701 text_effect_name_get(Edje_Text_Effect effect)
702 {
703    switch (effect)
704      {
705       case EDJE_TEXT_EFFECT_NONE:
706          return "NONE";
707       case EDJE_TEXT_EFFECT_PLAIN:
708          return "PLAIN";
709       case EDJE_TEXT_EFFECT_OUTLINE:
710          return "OUTLINE";
711       case EDJE_TEXT_EFFECT_SOFT_OUTLINE:
712          return "SOFT_OUTLINE";
713       case EDJE_TEXT_EFFECT_SHADOW:
714          return "SHADOW";
715       case EDJE_TEXT_EFFECT_SOFT_SHADOW:
716          return "SOFT_SHADOW";
717       case EDJE_TEXT_EFFECT_OUTLINE_SHADOW:
718          return "OUTLINE_SHADOW";
719       case EDJE_TEXT_EFFECT_OUTLINE_SOFT_SHADOW:
720          return "OUTLINE_SOFT_SHADOW";
721       case EDJE_TEXT_EFFECT_FAR_SHADOW:
722          return "FAR_SHADOW";
723       case EDJE_TEXT_EFFECT_FAR_SOFT_SHADOW:
724          return "FAR_SOFT_SHADOW";
725       case EDJE_TEXT_EFFECT_GLOW:
726          return "GLOW";
727
728       case EDJE_TEXT_EFFECT_LAST:
729          ERR("Invalid part type %d", effect);
730          return "???";
731       default:
732          ERR("Unknown effect type %d", effect);
733          return "???";
734      }
735 }
736
737 static inline Eina_Bool
738 _c_id_allowed(char c)
739 {
740    if ((c >= '0') && (c <= '9')) return EINA_TRUE;
741    if ((c >= 'a') && (c <= 'z')) return EINA_TRUE;
742    if ((c >= 'A') && (c <= 'Z')) return EINA_TRUE;
743    return EINA_FALSE;
744 }
745
746 static char *
747 _api_name_fix(const char *orig)
748 {
749    char *d, *d_end, buf[256];
750    const char *s;
751
752    if (!orig) return NULL;
753    if (!api_fix) return strdup(orig);
754
755    s = orig;
756    d = buf;
757    d_end = d + sizeof(buf) - 1;
758    for (; (*s != '\0') && (d < d_end); s++, d++)
759      if (_c_id_allowed(*s)) *d = *s;
760      else *d = '_';
761    *d = '\0';
762
763    return strdup(buf);
764 }
765
766 static char *
767 _part_api_name_get(Evas_Object *ed, const char *ppart)
768 {
769    const char *orig = edje_edit_part_api_name_get(ed, ppart);
770    char *fix = _api_name_fix(orig);
771    edje_edit_string_free(orig);
772    return fix;
773 }
774
775 static void
776 part_details(Evas_Object *ed, const char *ppart)
777 {
778    Eina_List *states, *l;
779    Eina_Bool b;
780    const char *str, *str2;
781    char *api;
782
783    if (detail < 1) return;
784
785    if (machine) puts("PART-DETAILS-BEGIN");
786
787    str = api =_part_api_name_get(ed, ppart);
788    str2 = edje_edit_part_api_description_get(ed, ppart);
789    if (machine)
790      {
791         printf("API-NAME: %s\n", str ? str : "");
792         printf("API-DESCRIPTION: %s\n", str2 ? str2 : "");
793      }
794    else if ((str) || (str2))
795      printf(INDENT3 "api: \"%s\" \"%s\";\n", str ? str : "", str2 ? str2 : "");
796    free(api);
797    edje_edit_string_free(str2);
798
799    b = edje_edit_part_mouse_events_get(ed, ppart);
800    if (machine) printf("MOUSE_EVENTS: %d\n", b);
801    else if (!b) puts(INDENT3 "mouse_events: 0;");
802
803    if (detail > 1)
804      {
805         b = edje_edit_part_repeat_events_get(ed, ppart);
806         if (machine) printf("REPEAT_EVENTS: %d\n", b);
807         else if (b) puts(INDENT3 "repeat_events: 1;");
808
809         b = edje_edit_part_scale_get(ed, ppart);
810         if (machine) printf("SCALE: %d\n", b);
811         else if (b) puts(INDENT3 "scale: 1;");
812      }
813
814    str = edje_edit_part_clip_to_get(ed, ppart);
815    if (machine) printf("CLIP_TO: %s\n", str ? str : "");
816    else if (str) printf(INDENT3 "clip_to: \"%s\";\n", str);
817    edje_edit_string_free(str);
818
819    str = edje_edit_part_source_get(ed, ppart);
820    if (machine) printf("SOURCE: %s\n", str ? str : "");
821    else if (str) printf(INDENT3 "source: \"%s\";\n", str);
822    edje_edit_string_free(str);
823
824    if (detail > 1)
825      {
826         if (edje_edit_part_type_get(ed, ppart) == EDJE_PART_TYPE_TEXT)
827           {
828              str = text_effect_name_get(edje_edit_part_effect_get(ed, ppart));
829              if (machine) printf("EFFECT: %s\n", str ? str : "");
830              else if (str) printf(INDENT3 "effect: %s;\n", str);
831              /* do not free this str! */
832           }
833
834         if (edje_edit_part_drag_x_get(ed, ppart) ||
835             edje_edit_part_drag_y_get(ed, ppart))
836           {
837              int dir, step, count;
838
839              if (machine) puts("DRAGABLE-BEGIN");
840              else puts(INDENT3 "dragable {");
841
842              dir = edje_edit_part_drag_x_get(ed, ppart);
843              step = edje_edit_part_drag_step_x_get(ed, ppart);
844              count = edje_edit_part_drag_count_x_get(ed, ppart);
845              if (machine) printf("DRAG-X: %d %d %d\n", dir, step, count);
846              else printf(INDENT4 "x: %d %d %d;\n", dir, step, count);
847
848              dir = edje_edit_part_drag_y_get(ed, ppart);
849              step = edje_edit_part_drag_step_y_get(ed, ppart);
850              count = edje_edit_part_drag_count_y_get(ed, ppart);
851              if (machine) printf("DRAG-Y: %d %d %d\n", dir, step, count);
852              else printf(INDENT4 "y: %d %d %d;\n", dir, step, count);
853
854              str = edje_edit_part_drag_confine_get(ed, ppart);
855              if (machine) printf("DRAG-CONFINE: %s\n", str ? str : "");
856              else if (str) printf(INDENT4 "confine: \"%s\";\n", str);
857              edje_edit_string_free(str);
858
859              str = edje_edit_part_drag_event_get(ed, ppart);
860              if (machine) printf("DRAG-EVENTS: %s\n", str ? str : "");
861              else if (str) printf(INDENT4 "events: \"%s\";\n", str);
862              edje_edit_string_free(str);
863
864              if (machine) puts("DRAGABLE-END");
865              else puts(INDENT3 "}");
866           }
867      }
868
869    states = edje_edit_part_states_list_get(ed, ppart);
870    EINA_LIST_FOREACH(states, l, str)
871      {
872         char state[512], *delim;
873         double value;
874         eina_strlcpy(state, str, sizeof(state)); /* bad states_list! :-( */
875         delim = strchr(state, ' ');
876         *delim = '\0';
877         delim++;
878         value = strtod(delim, NULL);
879         state_begin(state, value);
880         state_details(ed, ppart, state, value);
881         state_end();
882      }
883    edje_edit_string_list_free(states);
884
885    if (machine) puts("PART-DETAILS-END");
886 }
887
888 static void
889 part_end(void)
890 {
891    if (machine) puts("PART-END");
892    else if (detail > 0) puts(INDENT2 "}");
893    else puts(" }");
894 }
895
896 static int
897 _groups_names_list(void)
898 {
899    Eina_List *l;
900    const char *name;
901    Eina_Bool found = EINA_FALSE;
902
903    EINA_LIST_FOREACH(groups, l, name)
904      {
905         if (!matches(name, group))
906           {
907              DBG("filter out group '%s': does not match '%s'", name, group);
908              continue;
909           }
910         found = EINA_TRUE;
911         puts(name);
912      }
913
914    if (!found) WRN("no groups match '%s'", group);
915    return !found;
916 }
917
918 static int
919 _parts_names_list(void)
920 {
921    Eina_List *gl, *pl, *parts;
922    const char *gname, *pname;
923    Eina_Bool found_group = EINA_FALSE, found_part = EINA_FALSE;
924
925    EINA_LIST_FOREACH(groups, gl, gname)
926      {
927         Evas_Object *ed;
928
929         if (!matches(gname, group))
930           {
931              DBG("filter out group '%s': does not match '%s'", gname, group);
932              continue;
933           }
934
935         ed = edje_edit_object_add(ecore_evas_get(ee));
936         if (!edje_object_file_set(ed, file, gname))
937           {
938              Edje_Load_Error err = edje_object_load_error_get(ed);
939              const char *errmsg = edje_load_error_str(err);
940              ERR("could not load group '%s' from file '%s': %s",
941                  gname, file, errmsg);
942              evas_object_del(ed);
943              continue;
944           }
945
946         found_group = EINA_TRUE;
947         group_begin(gname);
948
949         parts = edje_edit_parts_list_get(ed);
950         EINA_LIST_FOREACH(parts, pl, pname)
951           {
952              if (!matches(pname, part))
953                {
954                   DBG("filter out part '%s': does not match '%s'", pname, part);
955                   continue;
956                }
957              if (api_only)
958                {
959                   if (!edje_edit_part_api_name_get(ed, pname))
960                     {
961                        DBG("filter out part '%s': not API.", pname);
962                        continue;
963                     }
964                }
965              if (machine) printf("PART: %s\n", pname);
966              else printf(INDENT "part: %s\n", pname);
967           }
968         edje_edit_string_list_free(parts);
969
970         group_end();
971         evas_object_del(ed);
972      }
973
974    if (!found_group) WRN("no groups match '%s'", group);
975    if (!found_part) WRN("no parts match '%s'", part);
976    return (!found_group) || (!found_part);
977 }
978
979 static Eina_Bool
980 _group_parts_list(Evas_Object *ed)
981 {
982    Eina_Bool found = EINA_FALSE;
983    Eina_List *parts, *l;
984    const char *name;
985
986    parts_begin();
987
988    parts = edje_edit_parts_list_get(ed);
989    EINA_LIST_FOREACH(parts, l, name)
990      {
991         if (!matches(name, part))
992           {
993              DBG("filter out part '%s': does not match '%s'", name, part);
994              continue;
995           }
996         if (api_only)
997           {
998              if (!edje_edit_part_api_name_get(ed, name))
999                {
1000                   DBG("filter out part '%s': not API.", name);
1001                   continue;
1002                }
1003           }
1004
1005         found = EINA_TRUE;
1006         part_begin(ed, name);
1007         part_details(ed, name);
1008         part_end();
1009      }
1010
1011    parts_end();
1012    return found;
1013 }
1014
1015 static void
1016 programs_begin(void)
1017 {
1018    if (machine) puts("PROGRAMS-BEGIN");
1019    else puts(INDENT "programs {");
1020 }
1021
1022 static void
1023 programs_end(void)
1024 {
1025    if (machine) puts("PROGRAMS-END");
1026    else puts(INDENT "}");
1027 }
1028
1029 static void
1030 program_begin(const char *name)
1031 {
1032    if (machine) printf("PROGRAM-BEGIN\nNAME: %s\n", name ? name : "");
1033    else
1034      {
1035         printf(INDENT2 "program { name: '%s';\n", name ? name : "");
1036      }
1037 }
1038
1039 static void
1040 program_end(void)
1041 {
1042    if (machine) puts("PROGRAM-END");
1043    else puts(INDENT2 "}");
1044 }
1045
1046
1047 static char *
1048 _program_api_name_get(Evas_Object *ed, const char *pprogram)
1049 {
1050    const char *orig = edje_edit_program_api_name_get(ed, pprogram);
1051    char *fix = _api_name_fix(orig);
1052    edje_edit_string_free(orig);
1053    return fix;
1054 }
1055
1056 static const char *
1057 _transition_name_get(Edje_Tween_Mode mode)
1058 {
1059    switch (mode)
1060      {
1061       case EDJE_TWEEN_MODE_LINEAR: return "LINEAR";
1062       case EDJE_TWEEN_MODE_ACCELERATE: return "ACCELERATE";
1063       case EDJE_TWEEN_MODE_DECELERATE: return "DECELERATE";
1064       case EDJE_TWEEN_MODE_SINUSOIDAL: return "SINUSOIDAL";
1065       default:
1066          ERR("Unknown transition mode %d", mode);
1067          return "???";
1068      }
1069 }
1070
1071 static void
1072 program_details(Evas_Object *ed, const char *pprogram)
1073 {
1074    const char *str, *str2;
1075    char *api;
1076
1077    if (detail < 1) return;
1078
1079    if (machine) puts("PROGRAM-DETAILS-BEGIN");
1080
1081    str = api =_program_api_name_get(ed, pprogram);
1082    str2 = edje_edit_program_api_description_get(ed, pprogram);
1083    if (machine)
1084      {
1085         printf("API-NAME: %s\n", str ? str : "");
1086         printf("API-DESCRIPTION: %s\n", str2 ? str2 : "");
1087      }
1088    else if ((str) || (str2))
1089      printf(INDENT3 "api: \"%s\" \"%s\";\n", str ? str : "", str2 ? str2 : "");
1090    free(api);
1091    edje_edit_string_free(str2);
1092
1093    str = edje_edit_program_signal_get(ed, pprogram);
1094    if (machine) printf("SIGNAL: %s\n", str ? str : "");
1095    else if (str) printf(INDENT3 "signal: \"%s\";\n", str);
1096    edje_edit_string_free(str);
1097
1098    str = edje_edit_program_source_get(ed, pprogram);
1099    if (machine) printf("SOURCE: %s\n", str ? str : "");
1100    else if (str) printf(INDENT3 "source: \"%s\";\n", str);
1101    edje_edit_string_free(str);
1102
1103    if (detail >= 1)
1104      {
1105         Eina_List *lst, *l;
1106         Edje_Action_Type type = edje_edit_program_action_get(ed, pprogram);
1107         switch (type)
1108           {
1109            case EDJE_ACTION_TYPE_ACTION_STOP:
1110               if (machine) puts("ACTION: ACTION_STOP");
1111               else puts(INDENT3 "action: ACTION_STOP;");
1112               break;
1113            case EDJE_ACTION_TYPE_STATE_SET:
1114               str = edje_edit_program_state_get(ed, pprogram);
1115               if (machine)
1116                 printf("ACTION: STATE_SET\nACTION-STATE: %s %g\n",
1117                        str, edje_edit_program_value_get(ed, pprogram));
1118               else
1119                 printf(INDENT3 "action: STATE_SET \"%s\" %2.1f;\n",
1120                        str, edje_edit_program_value_get(ed, pprogram));
1121               edje_edit_string_free(str);
1122               break;
1123            case EDJE_ACTION_TYPE_SIGNAL_EMIT:
1124               str = edje_edit_program_state_get(ed, pprogram);
1125               str2 = edje_edit_program_state2_get(ed, pprogram);
1126               if (machine)
1127                 printf("ACTION: SIGNAL_EMIT\nACTION-SIGNAL: %s\n"
1128                        "ACTION-SOURCE: %s\n",
1129                        str ? str : "", str2 ? str2 : "");
1130               else if ((str) || (str2))
1131                 printf(INDENT3 "action: SIGNAL_EMIT \"%s\" \"%s\";\n",
1132                        str ? str : "", str2 ? str2 : "");
1133               edje_edit_string_free(str);
1134               edje_edit_string_free(str2);
1135               break;
1136               //TODO Support Drag
1137               //~ case EDJE_ACTION_TYPE_DRAG_VAL_SET:
1138               //~ eina_strbuf_append(buf, I4"action: DRAG_VAL_SET TODO;\n");
1139               //~ break;
1140               //~ case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
1141               //~ eina_strbuf_append(buf, I4"action: DRAG_VAL_STEP TODO;\n");
1142               //~ break;
1143               //~ case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
1144               //~ eina_strbuf_append(buf, I4"action: DRAG_VAL_PAGE TODO;\n");
1145               //~ break;
1146            default:
1147               ERR("Unhandled pprogram action type %d", type);
1148               break;
1149           }
1150
1151         if (detail > 1)
1152           {
1153              double from, range;
1154
1155              from = edje_edit_program_transition_time_get(ed, pprogram);
1156              if (from > 0.0)
1157                {
1158                   str = _transition_name_get
1159                     (edje_edit_program_transition_get(ed, pprogram));
1160                   if (machine)
1161                     printf("TRANSITION-NAME: %s\nTRANSITION-DURATION: %g\n",
1162                            str, from);
1163                   else printf(INDENT3 "transition: %s %g;\n", str, from);
1164                   /* do not free str! */
1165                }
1166
1167              from = edje_edit_program_in_from_get(ed, pprogram);
1168              range = edje_edit_program_in_range_get(ed, pprogram);
1169              if (FDIFF(from, 0.0) || FDIFF(range, 0.0))
1170                {
1171                   if (machine)
1172                     printf("IN-FROM: %g\nIN-RANGE: %g\n", from, range);
1173                   else printf(INDENT3 "in: %g %g;\n", from, range);
1174                }
1175           }
1176
1177         lst = edje_edit_program_targets_get(ed, pprogram);
1178         EINA_LIST_FOREACH(lst, l, str)
1179           if (machine) printf("TARGET: %s\n", str);
1180           else printf(INDENT3 "target: \"%s\";\n", str);
1181         edje_edit_string_list_free(lst);
1182
1183         lst = edje_edit_program_afters_get(ed, pprogram);
1184         EINA_LIST_FOREACH(lst, l, str)
1185           if (machine) printf("AFTER: %s\n", str);
1186           else printf(INDENT3 "after: \"%s\";\n", str);
1187         edje_edit_string_list_free(lst);
1188
1189         // TODO Support script {}
1190      }
1191
1192    if (machine) puts("PROGRAM-DETAILS-END");
1193 }
1194
1195 static Eina_Bool
1196 _group_programs_list(Evas_Object *ed)
1197 {
1198    Eina_Bool found = EINA_FALSE;
1199    Eina_List *programs, *l;
1200    const char *name;
1201
1202    programs_begin();
1203
1204    /* TODO: change programs to operate on their ID instead of names!
1205     * needs huge change in Edje_Edit.h
1206     */
1207    WRN("listing only programs with names!");
1208    programs = edje_edit_programs_list_get(ed);
1209    EINA_LIST_FOREACH(programs, l, name)
1210      {
1211         if (!matches(name, program))
1212           {
1213              DBG("filter out program '%s': does not match '%s'", name, program);
1214              continue;
1215           }
1216         if (api_only)
1217           {
1218              if (!edje_edit_program_api_name_get(ed, name))
1219                {
1220                   DBG("filter out program '%s': not API.", name);
1221                   continue;
1222                }
1223           }
1224
1225         found = EINA_TRUE;
1226         program_begin(name);
1227         program_details(ed, name);
1228         program_end();
1229      }
1230
1231    programs_end();
1232    return found;
1233 }
1234
1235 static int
1236 _list(const char *mode)
1237 {
1238    Eina_List *l;
1239    const char *name;
1240    int ret = 0;
1241    Eina_Bool found_group = EINA_FALSE;
1242    Eina_Bool req_part, found_part, req_prog, found_prog;
1243
1244    if ((!strcmp(mode, "parts")) || (!strcmp(mode, "groups")))
1245      {
1246         req_part = EINA_TRUE;
1247         found_part = EINA_FALSE;
1248      }
1249    else
1250      {
1251         req_part = EINA_FALSE;
1252         found_part = EINA_TRUE;
1253      }
1254
1255    if ((!strcmp(mode, "programs")) || (!strcmp(mode, "groups")))
1256      {
1257         req_prog = EINA_TRUE;
1258         found_prog = EINA_FALSE;
1259      }
1260    else
1261      {
1262         req_prog = EINA_FALSE;
1263         found_prog = EINA_TRUE;
1264      }
1265
1266    EINA_LIST_FOREACH(groups, l, name)
1267      {
1268         Evas_Object *ed;
1269
1270         if (!matches(name, group))
1271           {
1272              DBG("filter out group '%s': does not match '%s'", name, group);
1273              continue;
1274           }
1275
1276         ed = edje_edit_object_add(ecore_evas_get(ee));
1277         if (!edje_object_file_set(ed, file, name))
1278           {
1279              Edje_Load_Error err = edje_object_load_error_get(ed);
1280              const char *errmsg = edje_load_error_str(err);
1281              ERR("could not load group '%s' from file '%s': %s",
1282                  name, file, errmsg);
1283              evas_object_del(ed);
1284              continue;
1285           }
1286
1287         found_group = EINA_TRUE;
1288         group_begin(name);
1289         group_details(ed);
1290
1291         if (req_part) found_part |= _group_parts_list(ed);
1292         if (req_prog) found_prog |= _group_programs_list(ed);
1293
1294         group_end();
1295         evas_object_del(ed);
1296      }
1297
1298    /* no hard requirement for parts or programs for group listing */
1299    if (!strcmp(mode, "groups")) req_part = req_prog = EINA_FALSE;
1300
1301    if (!found_group)
1302      {
1303         WRN("no groups match '%s'", group);
1304         ret = 1;
1305      }
1306    if ((req_part) && (!found_part))
1307      {
1308         WRN("no parts match '%s'", part);
1309         ret = 1;
1310      }
1311    if ((req_prog) && (!found_prog))
1312      {
1313         WRN("no programs match '%s'", program);
1314         ret = 1;
1315      }
1316    return ret;
1317 }
1318
1319 static Evas_Object *
1320 _edje_object_any_get(void)
1321 {
1322    Evas_Object *ed = edje_edit_object_add(ecore_evas_get(ee));
1323    Eina_List *l;
1324    const char *name;
1325    if (!ed) return NULL;
1326    EINA_LIST_FOREACH(groups, l, name)
1327      if (edje_object_file_set(ed, file, name)) return ed;
1328    evas_object_del(ed);
1329    return NULL;
1330 }
1331
1332 static Eina_Bool
1333 _gdata_list(void)
1334 {
1335    Evas_Object *ed = _edje_object_any_get();
1336    Eina_List *l, *data;
1337    const char *key;
1338
1339    if (!ed) return EINA_FALSE;
1340
1341    data = edje_edit_data_list_get(ed);
1342
1343    if (machine) puts("DATA-BEGIN");
1344    else puts("data {");
1345
1346    EINA_LIST_FOREACH(data, l, key)
1347      {
1348         const char *value = edje_edit_data_value_get(ed, key);
1349         if (machine) printf("ITEM: \"%s\" \"%s\"\n", key, value);
1350         else printf(INDENT "item: \"%s\" \"%s\";\n", key, value);
1351      }
1352
1353    if (machine) puts("DATA-END");
1354    else puts("}");
1355
1356    edje_edit_string_list_free(data);
1357    evas_object_del(ed);
1358    return EINA_TRUE;
1359 }
1360
1361 static const char *
1362 _comp_str_get(Evas_Object *ed, const char *img)
1363 {
1364    static char buf[128];
1365    Edje_Edit_Image_Comp type = edje_edit_image_compression_type_get(ed, img);
1366    int rate;
1367
1368    switch (type)
1369      {
1370       case EDJE_EDIT_IMAGE_COMP_RAW:
1371          return "RAW";
1372       case EDJE_EDIT_IMAGE_COMP_USER:
1373          return "USER";
1374       case EDJE_EDIT_IMAGE_COMP_COMP:
1375          return "COMP";
1376       case EDJE_EDIT_IMAGE_COMP_LOSSY:
1377          rate = edje_edit_image_compression_rate_get(ed, img);
1378          snprintf(buf, sizeof(buf), "LOSSY %d", rate);
1379          return buf;
1380       default:
1381          ERR("Unknown compression type %d", type);
1382          return "???";
1383      }
1384 }
1385
1386 static Eina_Bool
1387 _images_list(void)
1388 {
1389    Evas_Object *ed = _edje_object_any_get();
1390    Eina_List *l, *images;
1391    const char *img;
1392
1393    if (!ed) return EINA_FALSE;
1394
1395    images = edje_edit_images_list_get(ed);
1396
1397    if (machine) puts("IMAGES-BEGIN");
1398    else puts("images {");
1399
1400    EINA_LIST_FOREACH(images, l, img)
1401      {
1402         int id = edje_edit_image_id_get(ed, img);
1403         const char *comp = _comp_str_get(ed, img);
1404
1405         if (detail < 1)
1406           {
1407              if (machine) printf("IMAGE: %s\n", img);
1408              else printf(INDENT "image: \"%s\" %s;\n", img, comp);
1409           }
1410         else if (detail == 1)
1411           {
1412              if (machine) printf("IMAGE: \"%s\" \"%s\"\n", img, comp);
1413              else printf(INDENT "image: \"%s\" %s;\n", img, comp);
1414           }
1415         else
1416           {
1417              if (machine)
1418                printf("IMAGE: \"edje/images/%d\" \"%s\" \"%s\"\n",
1419                       id, img, comp);
1420              else
1421                printf(INDENT "image: \"%s\" %s; /* id: \"edje/images/%d\" */\n",
1422                       img, comp, id);
1423           }
1424      }
1425
1426    if (machine) puts("IMAGES-END");
1427    else puts("}");
1428
1429    edje_edit_string_list_free(images);
1430    evas_object_del(ed);
1431    return EINA_TRUE;
1432 }
1433
1434 static Eina_Bool
1435 _fonts_list(void)
1436 {
1437    Evas_Object *ed = _edje_object_any_get();
1438    Eina_List *l, *fonts;
1439    const char *alias;
1440
1441    if (!ed) return EINA_FALSE;
1442
1443    fonts = edje_edit_fonts_list_get(ed);
1444
1445    if (machine) puts("FONTS-BEGIN");
1446    else puts("fonts {");
1447
1448    EINA_LIST_FOREACH(fonts, l, alias)
1449      {
1450         const char *path = edje_edit_font_path_get(ed, alias);
1451
1452         if (detail < 1)
1453           {
1454              if (machine) printf("FONT: %s\n", alias);
1455              else printf(INDENT "font: \"%s\" \"%s\";\n", path, alias);
1456           }
1457         else if (detail == 1)
1458           {
1459              if (machine) printf("FONT: \"%s\" \"%s\"\n", path, alias);
1460              else printf(INDENT "font: \"%s\" \"%s\";\n", path, alias);
1461           }
1462         else
1463           {
1464              if (machine)
1465                printf("FONT: \"edje/fonts/%s\" \"%s\" \"%s\"\n",
1466                       alias, path, alias);
1467              else
1468                printf(INDENT
1469                       "font: \"%s\" \"%s\"; /* id: \"edje/fonts/%s\" */\n",
1470                       path, alias, alias);
1471           }
1472
1473         edje_edit_string_free(path);
1474      }
1475
1476    if (machine) puts("FONTS-END");
1477    else puts("}");
1478
1479    edje_edit_string_list_free(fonts);
1480    evas_object_del(ed);
1481    return EINA_TRUE;
1482 }
1483
1484 static Eina_Bool
1485 _externals_list(void)
1486 {
1487    Evas_Object *ed = _edje_object_any_get();
1488    Eina_List *l, *externals;
1489    const char *key;
1490
1491    if (!ed) return EINA_FALSE;
1492
1493    externals = edje_edit_externals_list_get(ed);
1494
1495    if (machine) puts("EXTERNALS-BEGIN");
1496    else puts("externals {");
1497
1498    EINA_LIST_FOREACH(externals, l, key)
1499      {
1500         if (machine) printf("EXTERNAL: %s\n", key);
1501         else printf(INDENT "external: \"%s\";\n", key);
1502      }
1503
1504    if (machine) puts("EXTERNALS-END");
1505    else puts("}");
1506
1507    edje_edit_string_list_free(externals);
1508    evas_object_del(ed);
1509    return EINA_TRUE;
1510 }
1511
1512
1513 int
1514 main(int argc, char **argv)
1515 {
1516    Eina_Bool quit_option = EINA_FALSE;
1517    char *mode = NULL;
1518    char *detail_name = NULL;
1519    int arg_index;
1520    int ret = 0;
1521    Ecore_Getopt_Value values[] = {
1522      ECORE_GETOPT_VALUE_STR(mode),
1523      ECORE_GETOPT_VALUE_STR(detail_name),
1524      ECORE_GETOPT_VALUE_STR(group),
1525      ECORE_GETOPT_VALUE_STR(part),
1526      ECORE_GETOPT_VALUE_STR(program),
1527      ECORE_GETOPT_VALUE_BOOL(api_only),
1528      ECORE_GETOPT_VALUE_BOOL(api_fix),
1529      ECORE_GETOPT_VALUE_BOOL(machine),
1530      ECORE_GETOPT_VALUE_BOOL(quit_option),
1531      ECORE_GETOPT_VALUE_BOOL(quit_option),
1532      ECORE_GETOPT_VALUE_BOOL(quit_option),
1533      ECORE_GETOPT_VALUE_BOOL(quit_option),
1534      ECORE_GETOPT_VALUE_NONE
1535    };
1536
1537    setlocale(LC_NUMERIC, "C");
1538
1539    ecore_init();
1540    ecore_evas_init();
1541    eina_init();
1542    edje_init();
1543
1544    _log_dom = eina_log_domain_register("edje_inspector", EINA_COLOR_YELLOW);
1545    if (_log_dom < 0)
1546      {
1547         EINA_LOG_CRIT("could not register log domain 'edje_inspector'");
1548         ret = 1;
1549         goto error_log;
1550      }
1551
1552    arg_index = ecore_getopt_parse(&optdesc, values, argc, argv);
1553    if (arg_index < 0)
1554      {
1555         ERR("could not parse arguments.");
1556         ret = 1;
1557         goto error_getopt;
1558      }
1559    else if (quit_option) goto error_getopt;
1560    else if (arg_index != argc - 1)
1561      {
1562         ERR("incorrect number of parameters. Requires one single file.");
1563         ret = 1;
1564         goto error_getopt;
1565      }
1566
1567    if (!mode) mode = (char *)mode_choices[0];
1568
1569    if (detail_name)
1570      {
1571         if (!strcmp(detail_name, "none")) detail = 0;
1572         else if (!strcmp(detail_name, "terse")) detail = 1;
1573         else if (!strcmp(detail_name, "all")) detail = 2;
1574         else ERR("Unknown detail level: '%s'", detail_name);
1575      }
1576
1577    file = argv[arg_index];
1578
1579    // check if the file is accessible
1580    if (access(file, R_OK) == -1)
1581      {
1582         int e = errno;
1583         ERR("File '%s' not accessible, error %d (%s).\n",
1584             file, e, strerror(e));
1585         ret = 1;
1586         goto error_getopt;
1587      }
1588
1589    DBG("mode=%s, detail=%d(%s), group=%s, part=%s, program=%s, api-only=%hhu"
1590        ", api-fix=%hhu, machine=%hhu, file=%s",
1591        mode, detail, detail_name,
1592        group ? group : "",
1593        part ? part : "",
1594        program ? program : "",
1595        api_only, api_fix, machine, file);
1596
1597
1598    groups = edje_file_collection_list(file);
1599    if (!groups)
1600      {
1601         ERR("no groups in edje file '%s'", file);
1602         ret = 1;
1603         goto error_getopt;
1604      }
1605
1606    if (!strcmp(mode, "groups-names")) ret = _groups_names_list();
1607    else
1608      {
1609         ee = ecore_evas_buffer_new(1, 1);
1610         if (!ee)
1611           {
1612              ERR("could not create ecore_evas_buffer");
1613              ret = 1;
1614           }
1615         else
1616           {
1617              if (!strcmp(mode, "parts-names")) ret = _parts_names_list();
1618              else if (!strcmp(mode, "global-data")) ret = _gdata_list();
1619              else if (!strcmp(mode, "images")) ret = _images_list();
1620              else if (!strcmp(mode, "fonts")) ret = _fonts_list();
1621              else if (!strcmp(mode, "externals")) ret = _externals_list();
1622              else ret = _list(mode);
1623              ecore_evas_free(ee);
1624           }
1625      }
1626
1627    edje_file_collection_list_free(groups);
1628  error_getopt:
1629    eina_log_domain_unregister(_log_dom);
1630  error_log:
1631    edje_shutdown();
1632    ecore_evas_shutdown();
1633    ecore_shutdown();
1634    eina_shutdown();
1635
1636    return ret;
1637 }