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