merge with master
[framework/uifw/edje.git] / src / bin / edje_cc_handlers.c
1 /*
2     Concerning the EDC reference:
3
4     The formatting for blocks and properties has been implemented as a table
5     which is filled using ALIASES.
6     For maximum flexibility I implemented them in the \@code/\@encode style,
7     this means that missing one or changing the order most certainly cause
8     formatting errors.
9
10     \@block
11         block name
12     \@context
13         code sample of the block
14     \@description
15         the block's description
16     \@endblock
17
18     \@property
19         property name
20     \@parameters
21         property's parameter list
22     \@effect
23         the property description (lol)
24     \@endproperty
25 */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <string.h>
32 #include <errno.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <sys/mman.h>
36 #include <unistd.h>
37
38 #include "edje_cc.h"
39
40 /**
41  * @page edcref Edje Data Collection reference
42  * An Edje Data Collection, it's a plain text file (normally identified with the
43  * .edc extension), consisting of instructions for the Edje Compiler.
44  *
45  * The syntax for the edje data collection files follows a simple structure of
46  * "blocks { .. }" that can contain "properties: ..", more blocks, or both.
47  *
48  * @anchor sec_quickaccess Quick access to block descriptions:
49  * <ul>
50  *    <li>@ref sec_toplevel "Top-Level"</li>
51  *    <li>@ref sec_group "Group"</li>
52  *    <li>@ref sec_description "State description"</li>
53  *    <ul>
54  *      <li>@ref sec_description_image "Image"</li>
55  *      <li>@ref sec_description_text "Text"</li>
56  *      <li>@ref sec_description_box "Box"</li>
57  *      <li>@ref sec_description_table "Table"</li>
58  *      <li>@ref sec_description_map "Map (3d/transformations)"</li>
59  *    </ul>
60  *    <li>@ref sec_program "Program block"</li>
61  * </ul>
62  *
63  * @author Andres Blanc (dresb) andresblanc@gmail.com
64  *
65  * <table class="edcref" border="0">
66  */
67
68 static Edje_Part_Collection_Directory_Entry *current_de = NULL;
69 static Edje_Part *current_part = NULL;
70 static Edje_Pack_Element *current_item = NULL;
71 static Edje_Part_Description_Common *current_desc = NULL;
72 static Edje_Part_Description_Common *parent_desc = NULL;
73 static Edje_Program *current_program = NULL;
74
75 struct _Edje_Cc_Handlers_Hierarchy_Info
76 {  /* Struct that keeps globals value to impl hierarchy */
77    Edje_Part_Collection_Directory_Entry *current_de;
78    Edje_Part *current_part;
79    Edje_Pack_Element *current_item;
80    Edje_Part_Description_Common *current_desc;
81    Edje_Part_Description_Common *parent_desc;
82    Edje_Program *current_program;
83    Edje_Part *ep;
84 };
85 typedef struct _Edje_Cc_Handlers_Hierarchy_Info Edje_Cc_Handlers_Hierarchy_Info;
86
87 static Eina_Array *part_hierarchy = NULL; /* stack parts,support nested parts */
88 static void edje_cc_handlers_hierarchy_set(Edje_Part *src);
89 static Edje_Part *edje_cc_handlers_hierarchy_parent_get(void);
90 static void edje_cc_handlers_hierarchy_push(Edje_Part *ep, Edje_Part *cp);
91 static void edje_cc_handlers_hierarchy_rename(Edje_Part *old, Edje_Part *new);
92 static void edje_cc_handlers_hierarchy_pop(void);
93
94 static void st_externals_external(void);
95
96 static void st_images_image(void);
97 static void ob_images_set(void);
98 static void st_images_set_name(void);
99 static void ob_images_set_image(void);
100 static void st_images_set_image_image(void);
101 static void st_images_set_image_size(void);
102
103 static void st_fonts_font(void);
104
105 static void st_data_item(void);
106 static void st_data_file(void);
107
108 static void ob_styles_style(void);
109 static void st_styles_style_name(void);
110 static void st_styles_style_base(void);
111 static void st_styles_style_tag(void);
112
113 static void ob_color_class(void);
114 static void st_color_class_name(void);
115 static void st_color_class_color(void);
116 static void st_color_class_color2(void);
117 static void st_color_class_color3(void);
118
119 static void ob_collections(void);
120
121 static void ob_collections_group(void);
122 static void st_collections_group_name(void);
123 static void st_collections_group_inherit(void);
124 static void st_collections_group_script_only(void);
125 static void st_collections_group_alias(void);
126 static void st_collections_group_min(void);
127 static void st_collections_group_max(void);
128 static void st_collections_group_broadcast_signal(void);
129 static void st_collections_group_data_item(void);
130 static void st_collections_group_orientation(void);
131
132 static void st_collections_group_limits_vertical(void);
133 static void st_collections_group_limits_horizontal(void);
134
135 static void ob_collections_group_script(void);
136 static void ob_collections_group_lua_script(void);
137
138 static void st_collections_group_parts_alias(void);
139
140 static Edje_Part *edje_cc_handlers_part_make(void);
141 static void ob_collections_group_parts_part(void);
142 static void st_collections_group_parts_part_name(void);
143 static void st_collections_group_parts_part_type(void);
144 static void st_collections_group_parts_part_insert_before(void);
145 static void st_collections_group_parts_part_insert_after(void);
146 static void st_collections_group_parts_part_effect(void);
147 static void st_collections_group_parts_part_mouse_events(void);
148 static void st_collections_group_parts_part_repeat_events(void);
149 static void st_collections_group_parts_part_ignore_flags(void);
150 static void st_collections_group_parts_part_scale(void);
151 static void st_collections_group_parts_part_pointer_mode(void);
152 static void st_collections_group_parts_part_precise_is_inside(void);
153 static void st_collections_group_parts_part_use_alternate_font_metrics(void);
154 static void st_collections_group_parts_part_clip_to_id(void);
155 static void st_collections_group_parts_part_source(void);
156 static void st_collections_group_parts_part_source2(void);
157 static void st_collections_group_parts_part_source3(void);
158 static void st_collections_group_parts_part_source4(void);
159 static void st_collections_group_parts_part_source5(void);
160 static void st_collections_group_parts_part_source6(void);
161 static void st_collections_group_parts_part_entry_mode(void);
162 static void st_collections_group_parts_part_select_mode(void);
163 static void st_collections_group_parts_part_cursor_mode(void);
164 static void st_collections_group_parts_part_multiline(void);
165 static void st_collections_group_parts_part_access(void);
166 static void st_collections_group_parts_part_dragable_x(void);
167 static void st_collections_group_parts_part_dragable_y(void);
168 static void st_collections_group_parts_part_dragable_confine(void);
169 static void st_collections_group_parts_part_dragable_events(void);
170
171 /* box and table items share these */
172 static void ob_collections_group_parts_part_box_items_item(void);
173 static void st_collections_group_parts_part_box_items_item_type(void);
174 static void st_collections_group_parts_part_box_items_item_name(void);
175 static void st_collections_group_parts_part_box_items_item_source(void);
176 static void st_collections_group_parts_part_box_items_item_min(void);
177 static void st_collections_group_parts_part_box_items_item_prefer(void);
178 static void st_collections_group_parts_part_box_items_item_max(void);
179 static void st_collections_group_parts_part_box_items_item_padding(void);
180 static void st_collections_group_parts_part_box_items_item_align(void);
181 static void st_collections_group_parts_part_box_items_item_weight(void);
182 static void st_collections_group_parts_part_box_items_item_aspect(void);
183 static void st_collections_group_parts_part_box_items_item_aspect_mode(void);
184 static void st_collections_group_parts_part_box_items_item_options(void);
185 /* but these are only for table */
186 static void st_collections_group_parts_part_table_items_item_position(void);
187 static void st_collections_group_parts_part_table_items_item_span(void);
188
189 static void ob_collections_group_parts_part_description(void);
190 static void st_collections_group_parts_part_description_inherit(void);
191 static void st_collections_group_parts_part_description_source(void);
192 static void st_collections_group_parts_part_description_state(void);
193 static void st_collections_group_parts_part_description_visible(void);
194 static void st_collections_group_parts_part_description_limit(void);
195 static void st_collections_group_parts_part_description_align(void);
196 static void st_collections_group_parts_part_description_fixed(void);
197 static void st_collections_group_parts_part_description_min(void);
198 static void st_collections_group_parts_part_description_minmul(void);
199 static void st_collections_group_parts_part_description_max(void);
200 static void st_collections_group_parts_part_description_step(void);
201 static void st_collections_group_parts_part_description_aspect(void);
202 static void st_collections_group_parts_part_description_aspect_preference(void);
203 static void st_collections_group_parts_part_description_rel1_relative(void);
204 static void st_collections_group_parts_part_description_rel1_offset(void);
205 static void st_collections_group_parts_part_description_rel1_to_set(const char *name);
206 static void st_collections_group_parts_part_description_rel1_to(void);
207 static void st_collections_group_parts_part_description_rel1_to_x(void);
208 static void st_collections_group_parts_part_description_rel1_to_y(void);
209 static void st_collections_group_parts_part_description_rel2_relative(void);
210 static void st_collections_group_parts_part_description_rel2_offset(void);
211 static void st_collections_group_parts_part_description_rel2_to_set(const char *name);
212 static void st_collections_group_parts_part_description_rel2_to(void);
213 static void st_collections_group_parts_part_description_rel2_to_x(void);
214 static void st_collections_group_parts_part_description_rel2_to_y(void);
215 static void st_collections_group_parts_part_description_image_normal(void);
216 static void st_collections_group_parts_part_description_image_tween(void);
217 static void st_collections_group_parts_part_description_image_border(void);
218 static void st_collections_group_parts_part_description_image_middle(void);
219 static void st_collections_group_parts_part_description_image_border_scale(void);
220 static void st_collections_group_parts_part_description_image_border_scale_by(void);
221 static void st_collections_group_parts_part_description_image_scale_hint(void);
222 static void st_collections_group_parts_part_description_fill_smooth(void);
223 static void st_collections_group_parts_part_description_fill_origin_relative(void);
224 static void st_collections_group_parts_part_description_fill_origin_offset(void);
225 static void st_collections_group_parts_part_description_fill_size_relative(void);
226 static void st_collections_group_parts_part_description_fill_size_offset(void);
227 static void st_collections_group_parts_part_description_fill_spread(void);
228 static void st_collections_group_parts_part_description_fill_type(void);
229 static void st_collections_group_parts_part_description_color_class(void);
230 static void st_collections_group_parts_part_description_color(void);
231 static void st_collections_group_parts_part_description_color2(void);
232 static void st_collections_group_parts_part_description_color3(void);
233 static void st_collections_group_parts_part_description_text_text(void);
234 static void st_collections_group_parts_part_description_text_text_class(void);
235 static void st_collections_group_parts_part_description_text_font(void);
236 static void st_collections_group_parts_part_description_text_style(void);
237 static void st_collections_group_parts_part_description_text_repch(void);
238 static void st_collections_group_parts_part_description_text_size(void);
239 static void st_collections_group_parts_part_description_text_size_range(void);
240 static void st_collections_group_parts_part_description_text_fit(void);
241 static void st_collections_group_parts_part_description_text_min(void);
242 static void st_collections_group_parts_part_description_text_max(void);
243 static void st_collections_group_parts_part_description_text_align(void);
244 static void st_collections_group_parts_part_description_text_source(void);
245 static void st_collections_group_parts_part_description_text_text_source(void);
246 static void st_collections_group_parts_part_description_text_elipsis(void);
247 static void st_collections_group_parts_part_description_box_layout(void);
248 static void st_collections_group_parts_part_description_box_align(void);
249 static void st_collections_group_parts_part_description_box_padding(void);
250 static void st_collections_group_parts_part_description_box_min(void);
251 static void st_collections_group_parts_part_description_table_homogeneous(void);
252 static void st_collections_group_parts_part_description_table_align(void);
253 static void st_collections_group_parts_part_description_table_padding(void);
254 static void st_collections_group_parts_part_description_table_min(void);
255 static void st_collections_group_parts_part_description_map_perspective(void);
256 static void st_collections_group_parts_part_description_map_light(void);
257 static void st_collections_group_parts_part_description_map_rotation_center(void);
258 static void st_collections_group_parts_part_description_map_rotation_x(void);
259 static void st_collections_group_parts_part_description_map_rotation_y(void);
260 static void st_collections_group_parts_part_description_map_rotation_z(void);
261 static void st_collections_group_parts_part_description_map_on(void);
262 static void st_collections_group_parts_part_description_map_smooth(void);
263 static void st_collections_group_parts_part_description_map_alpha(void);
264 static void st_collections_group_parts_part_description_map_backface_cull(void);
265 static void st_collections_group_parts_part_description_map_perspective_on(void);
266 static void st_collections_group_parts_part_description_perspective_zplane(void);
267 static void st_collections_group_parts_part_description_perspective_focal(void);
268 static void st_collections_group_parts_part_api(void);
269
270 /* external part parameters */
271 static void st_collections_group_parts_part_description_params_int(void);
272 static void ob_collections_group_programs_program(void);
273 static void st_collections_group_parts_part_description_params_double(void);
274
275 static void st_collections_group_programs_program_name(void);
276 static void st_collections_group_parts_part_description_params_string(void);
277 static void st_collections_group_parts_part_description_params_bool(void);
278 static void st_collections_group_parts_part_description_params_choice(void);
279 static void st_collections_group_programs_program_signal(void);
280 static void st_collections_group_programs_program_source(void);
281 static void st_collections_group_programs_program_filter(void);
282 static void st_collections_group_programs_program_in(void);
283 static void st_collections_group_programs_program_action(void);
284 static void st_collections_group_programs_program_transition(void);
285 static void st_collections_group_programs_program_target(void);
286 static void st_collections_group_programs_program_after(void);
287 static void st_collections_group_programs_program_api(void);
288
289 static void ob_collections_group_programs_program_script(void);
290
291 static void st_collections_group_sound_sample_name(void);
292 static void st_collections_group_sound_sample_source(void);
293 static void st_collections_group_sound_tone(void);
294 /*****/
295
296 New_Statement_Handler statement_handlers[] =
297 {
298      {"externals.external", st_externals_external},
299      {"images.image", st_images_image},
300      {"images.set.name", st_images_set_name},
301      {"images.set.image.image", st_images_set_image_image},
302      {"images.set.image.size", st_images_set_image_size},
303      {"fonts.font", st_fonts_font},
304      {"data.item", st_data_item},
305      {"data.file", st_data_file},
306      {"styles.style.name", st_styles_style_name},
307      {"styles.style.base", st_styles_style_base},
308      {"styles.style.tag", st_styles_style_tag},
309      {"color_classes.color_class.name", st_color_class_name},
310      {"color_classes.color_class.color", st_color_class_color},
311      {"color_classes.color_class.color2", st_color_class_color2},
312      {"color_classes.color_class.color3", st_color_class_color3},
313      {"collections.externals.external", st_externals_external}, /* dup */
314      {"collections.image", st_images_image}, /* dup */
315      {"collections.set.name", st_images_set_name}, /* dup */
316      {"collections.set.image.image", st_images_set_image_image}, /* dup */
317      {"collections.set.image.size", st_images_set_image_size}, /* dup */
318      {"collections.images.image", st_images_image}, /* dup */
319      {"collections.images.set.name", st_images_set_name}, /* dup */
320      {"collections.images.set.image.image", st_images_set_image_image}, /* dup */
321      {"collections.images.set.image.size", st_images_set_image_size}, /* dup */
322      {"collections.font", st_fonts_font}, /* dup */
323      {"collections.fonts.font", st_fonts_font}, /* dup */
324      {"collections.styles.style.name", st_styles_style_name}, /* dup */
325      {"collections.styles.style.base", st_styles_style_base}, /* dup */
326      {"collections.styles.style.tag", st_styles_style_tag}, /* dup */
327      {"collections.color_classes.color_class.name", st_color_class_name}, /* dup */
328      {"collections.color_classes.color_class.color", st_color_class_color}, /* dup */
329      {"collections.color_classes.color_class.color2", st_color_class_color2}, /* dup */
330      {"collections.color_classes.color_class.color3", st_color_class_color3}, /* dup */
331      {"collections.sounds.sample.name", st_collections_group_sound_sample_name},
332      {"collections.sounds.sample.source", st_collections_group_sound_sample_source},
333      {"collections.group.sounds.sample.name", st_collections_group_sound_sample_name}, /* dup */
334      {"collections.group.sounds.sample.source", st_collections_group_sound_sample_source}, /* dup */
335      {"collections.sounds.tone", st_collections_group_sound_tone},
336      {"collections.group.sounds.tone", st_collections_group_sound_tone}, /* dup */
337      {"collections.group.name", st_collections_group_name},
338      {"collections.group.inherit", st_collections_group_inherit},
339      {"collections.group.script_only", st_collections_group_script_only},
340      {"collections.group.lua_script_only", st_collections_group_script_only},
341      {"collections.group.alias", st_collections_group_alias},
342      {"collections.group.min", st_collections_group_min},
343      {"collections.group.max", st_collections_group_max},
344      {"collections.group.broadcast_signal", st_collections_group_broadcast_signal},
345      {"collections.group.orientation", st_collections_group_orientation},
346      {"collections.group.data.item", st_collections_group_data_item},
347      {"collections.group.limits.horizontal", st_collections_group_limits_horizontal},
348      {"collections.group.limits.vertical", st_collections_group_limits_vertical},
349      {"collections.group.externals.external", st_externals_external}, /* dup */
350      {"collections.group.image", st_images_image}, /* dup */
351      {"collections.group.set.name", st_images_set_name},
352      {"collections.group.set.image.image", st_images_set_image_image},
353      {"collections.group.set.image.size", st_images_set_image_size},
354      {"collections.group.images.image", st_images_image}, /* dup */
355      {"collections.group.images.set.name", st_images_set_name},
356      {"collections.group.images.set.image.image", st_images_set_image_image},
357      {"collections.group.images.set.image.size", st_images_set_image_size},
358      {"collections.group.font", st_fonts_font}, /* dup */
359      {"collections.group.fonts.font", st_fonts_font}, /* dup */
360      {"collections.group.styles.style.name", st_styles_style_name}, /* dup */
361      {"collections.group.styles.style.base", st_styles_style_base}, /* dup */
362      {"collections.group.styles.style.tag", st_styles_style_tag}, /* dup */
363      {"collections.group.color_classes.color_class.name", st_color_class_name}, /* dup */
364      {"collections.group.color_classes.color_class.color", st_color_class_color}, /* dup */
365      {"collections.group.color_classes.color_class.color2", st_color_class_color2}, /* dup */
366      {"collections.group.color_classes.color_class.color3", st_color_class_color3}, /* dup */
367      {"collections.group.parts.alias", st_collections_group_parts_alias },
368      {"collections.group.parts.image", st_images_image}, /* dup */
369      {"collections.group.parts.set.name", st_images_set_name},
370      {"collections.group.parts.set.image.image", st_images_set_image_image},
371      {"collections.group.parts.set.image.size", st_images_set_image_size},
372      {"collections.group.parts.images.image", st_images_image}, /* dup */
373      {"collections.group.parts.images.set.name", st_images_set_name},
374      {"collections.group.parts.images.set.image.image", st_images_set_image_image},
375      {"collections.group.parts.images.set.image.size", st_images_set_image_size},
376      {"collections.group.parts.font", st_fonts_font}, /* dup */
377      {"collections.group.parts.fonts.font", st_fonts_font}, /* dup */
378      {"collections.group.parts.styles.style.name", st_styles_style_name}, /* dup */
379      {"collections.group.parts.styles.style.base", st_styles_style_base}, /* dup */
380      {"collections.group.parts.styles.style.tag", st_styles_style_tag}, /* dup */
381      {"collections.group.parts.color_classes.color_class.name", st_color_class_name}, /* dup */
382      {"collections.group.parts.color_classes.color_class.color", st_color_class_color}, /* dup */
383      {"collections.group.parts.color_classes.color_class.color2", st_color_class_color2}, /* dup */
384      {"collections.group.parts.color_classes.color_class.color3", st_color_class_color3}, /* dup */
385      {"collections.group.parts.part.name", st_collections_group_parts_part_name},
386      {"collections.group.parts.part.api", st_collections_group_parts_part_api},
387      {"collections.group.parts.part.type", st_collections_group_parts_part_type},
388      {"collections.group.parts.part.insert_before", st_collections_group_parts_part_insert_before},
389      {"collections.group.parts.part.insert_after", st_collections_group_parts_part_insert_after},
390      {"collections.group.parts.part.effect", st_collections_group_parts_part_effect},
391      {"collections.group.parts.part.mouse_events", st_collections_group_parts_part_mouse_events},
392      {"collections.group.parts.part.repeat_events", st_collections_group_parts_part_repeat_events},
393      {"collections.group.parts.part.ignore_flags", st_collections_group_parts_part_ignore_flags},
394      {"collections.group.parts.part.scale", st_collections_group_parts_part_scale},
395      {"collections.group.parts.part.pointer_mode", st_collections_group_parts_part_pointer_mode},
396      {"collections.group.parts.part.precise_is_inside", st_collections_group_parts_part_precise_is_inside},
397      {"collections.group.parts.part.use_alternate_font_metrics", st_collections_group_parts_part_use_alternate_font_metrics},
398      {"collections.group.parts.part.clip_to", st_collections_group_parts_part_clip_to_id},
399      {"collections.group.parts.part.source", st_collections_group_parts_part_source},
400      {"collections.group.parts.part.source2", st_collections_group_parts_part_source2},
401      {"collections.group.parts.part.source3", st_collections_group_parts_part_source3},
402      {"collections.group.parts.part.source4", st_collections_group_parts_part_source4},
403      {"collections.group.parts.part.source5", st_collections_group_parts_part_source5},
404      {"collections.group.parts.part.source6", st_collections_group_parts_part_source6},
405      {"collections.group.parts.part.dragable.x", st_collections_group_parts_part_dragable_x},
406      {"collections.group.parts.part.dragable.y", st_collections_group_parts_part_dragable_y},
407      {"collections.group.parts.part.dragable.confine", st_collections_group_parts_part_dragable_confine},
408      {"collections.group.parts.part.dragable.events", st_collections_group_parts_part_dragable_events},
409      {"collections.group.parts.part.entry_mode", st_collections_group_parts_part_entry_mode},
410      {"collections.group.parts.part.select_mode", st_collections_group_parts_part_select_mode},
411      {"collections.group.parts.part.cursor_mode", st_collections_group_parts_part_cursor_mode},
412      {"collections.group.parts.part.multiline", st_collections_group_parts_part_multiline},
413      {"collections.group.parts.part.access", st_collections_group_parts_part_access},
414      {"collections.group.parts.part.image", st_images_image}, /* dup */
415      {"collections.group.parts.part.set.name", st_images_set_name},
416      {"collections.group.parts.part.set.image.image", st_images_set_image_image},
417      {"collections.group.parts.part.set.image.size", st_images_set_image_size},
418      {"collections.group.parts.part.images.image", st_images_image}, /* dup */
419      {"collections.group.parts.part.images.set.name", st_images_set_name},
420      {"collections.group.parts.part.images.set.image.image", st_images_set_image_image},
421      {"collections.group.parts.part.images.set.image.size", st_images_set_image_size},
422      {"collections.group.parts.part.font", st_fonts_font}, /* dup */
423      {"collections.group.parts.part.fonts.font", st_fonts_font}, /* dup */
424      {"collections.group.parts.part.styles.style.name", st_styles_style_name}, /* dup */
425      {"collections.group.parts.part.styles.style.base", st_styles_style_base}, /* dup */
426      {"collections.group.parts.part.styles.style.tag", st_styles_style_tag}, /* dup */
427      {"collections.group.parts.part.color_classes.color_class.name", st_color_class_name}, /* dup */
428      {"collections.group.parts.part.color_classes.color_class.color", st_color_class_color}, /* dup */
429      {"collections.group.parts.part.color_classes.color_class.color2", st_color_class_color2}, /* dup */
430      {"collections.group.parts.part.color_classes.color_class.color3", st_color_class_color3}, /* dup */
431      {"collections.group.parts.part.box.items.item.type", st_collections_group_parts_part_box_items_item_type},
432      {"collections.group.parts.part.box.items.item.name", st_collections_group_parts_part_box_items_item_name},
433      {"collections.group.parts.part.box.items.item.source", st_collections_group_parts_part_box_items_item_source},
434      {"collections.group.parts.part.box.items.item.min", st_collections_group_parts_part_box_items_item_min},
435      {"collections.group.parts.part.box.items.item.prefer", st_collections_group_parts_part_box_items_item_prefer},
436      {"collections.group.parts.part.box.items.item.max", st_collections_group_parts_part_box_items_item_max},
437      {"collections.group.parts.part.box.items.item.padding", st_collections_group_parts_part_box_items_item_padding},
438      {"collections.group.parts.part.box.items.item.align", st_collections_group_parts_part_box_items_item_align},
439      {"collections.group.parts.part.box.items.item.weight", st_collections_group_parts_part_box_items_item_weight},
440      {"collections.group.parts.part.box.items.item.aspect", st_collections_group_parts_part_box_items_item_aspect},
441      {"collections.group.parts.part.box.items.item.aspect_mode", st_collections_group_parts_part_box_items_item_aspect_mode},
442      {"collections.group.parts.part.box.items.item.options", st_collections_group_parts_part_box_items_item_options},
443      {"collections.group.parts.part.table.items.item.type", st_collections_group_parts_part_box_items_item_type}, /* dup */
444      {"collections.group.parts.part.table.items.item.name", st_collections_group_parts_part_box_items_item_name}, /* dup */
445      {"collections.group.parts.part.table.items.item.source", st_collections_group_parts_part_box_items_item_source}, /* dup */
446      {"collections.group.parts.part.table.items.item.min", st_collections_group_parts_part_box_items_item_min}, /* dup */
447      {"collections.group.parts.part.table.items.item.prefer", st_collections_group_parts_part_box_items_item_prefer}, /* dup */
448      {"collections.group.parts.part.table.items.item.max", st_collections_group_parts_part_box_items_item_max}, /* dup */
449      {"collections.group.parts.part.table.items.item.padding", st_collections_group_parts_part_box_items_item_padding}, /* dup */
450      {"collections.group.parts.part.table.items.item.align", st_collections_group_parts_part_box_items_item_align}, /* dup */
451      {"collections.group.parts.part.table.items.item.weight", st_collections_group_parts_part_box_items_item_weight}, /* dup */
452      {"collections.group.parts.part.table.items.item.aspect", st_collections_group_parts_part_box_items_item_aspect}, /* dup */
453      {"collections.group.parts.part.table.items.item.aspect_mode", st_collections_group_parts_part_box_items_item_aspect_mode}, /* dup */
454      {"collections.group.parts.part.table.items.item.options", st_collections_group_parts_part_box_items_item_options}, /* dup */
455      {"collections.group.parts.part.table.items.item.position", st_collections_group_parts_part_table_items_item_position},
456      {"collections.group.parts.part.table.items.item.span", st_collections_group_parts_part_table_items_item_span},
457      {"collections.group.parts.part.description.inherit", st_collections_group_parts_part_description_inherit},
458      {"collections.group.parts.part.description.source", st_collections_group_parts_part_description_source},
459      {"collections.group.parts.part.description.state", st_collections_group_parts_part_description_state},
460      {"collections.group.parts.part.description.visible", st_collections_group_parts_part_description_visible},
461      {"collections.group.parts.part.description.limit", st_collections_group_parts_part_description_limit},
462      {"collections.group.parts.part.description.align", st_collections_group_parts_part_description_align},
463      {"collections.group.parts.part.description.fixed", st_collections_group_parts_part_description_fixed},
464      {"collections.group.parts.part.description.min", st_collections_group_parts_part_description_min},
465      {"collections.group.parts.part.description.minmul", st_collections_group_parts_part_description_minmul},
466      {"collections.group.parts.part.description.max", st_collections_group_parts_part_description_max},
467      {"collections.group.parts.part.description.step", st_collections_group_parts_part_description_step},
468      {"collections.group.parts.part.description.aspect", st_collections_group_parts_part_description_aspect},
469      {"collections.group.parts.part.description.aspect_preference", st_collections_group_parts_part_description_aspect_preference},
470      {"collections.group.parts.part.description.rel1.relative", st_collections_group_parts_part_description_rel1_relative},
471      {"collections.group.parts.part.description.rel1.offset", st_collections_group_parts_part_description_rel1_offset},
472      {"collections.group.parts.part.description.rel1.to", st_collections_group_parts_part_description_rel1_to},
473      {"collections.group.parts.part.description.rel1.to_x", st_collections_group_parts_part_description_rel1_to_x},
474      {"collections.group.parts.part.description.rel1.to_y", st_collections_group_parts_part_description_rel1_to_y},
475      {"collections.group.parts.part.description.rel2.relative", st_collections_group_parts_part_description_rel2_relative},
476      {"collections.group.parts.part.description.rel2.offset", st_collections_group_parts_part_description_rel2_offset},
477      {"collections.group.parts.part.description.rel2.to", st_collections_group_parts_part_description_rel2_to},
478      {"collections.group.parts.part.description.rel2.to_x", st_collections_group_parts_part_description_rel2_to_x},
479      {"collections.group.parts.part.description.rel2.to_y", st_collections_group_parts_part_description_rel2_to_y},
480      {"collections.group.parts.part.description.image.normal", st_collections_group_parts_part_description_image_normal},
481      {"collections.group.parts.part.description.image.tween", st_collections_group_parts_part_description_image_tween},
482      {"collections.group.parts.part.description.image.image", st_images_image}, /* dup */
483      {"collections.group.parts.part.description.image.set.name", st_images_set_name},
484      {"collections.group.parts.part.description.image.set.image.image", st_images_set_image_image},
485      {"collections.group.parts.part.description.image.set.image.size", st_images_set_image_size},
486      {"collections.group.parts.part.description.image.images.image", st_images_image}, /* dup */
487      {"collections.group.parts.part.description.image.images.set.name", st_images_set_name},
488      {"collections.group.parts.part.description.image.images.set.image.image", st_images_set_image_image},
489      {"collections.group.parts.part.description.image.images.set.image.size", st_images_set_image_size},
490      {"collections.group.parts.part.description.image.border", st_collections_group_parts_part_description_image_border},
491      {"collections.group.parts.part.description.image.middle", st_collections_group_parts_part_description_image_middle},
492      {"collections.group.parts.part.description.image.border_scale", st_collections_group_parts_part_description_image_border_scale},
493      {"collections.group.parts.part.description.image.border_scale_by", st_collections_group_parts_part_description_image_border_scale_by},
494      {"collections.group.parts.part.description.image.scale_hint", st_collections_group_parts_part_description_image_scale_hint},
495      {"collections.group.parts.part.description.fill.smooth", st_collections_group_parts_part_description_fill_smooth},
496      {"collections.group.parts.part.description.fill.origin.relative", st_collections_group_parts_part_description_fill_origin_relative},
497      {"collections.group.parts.part.description.fill.origin.offset", st_collections_group_parts_part_description_fill_origin_offset},
498      {"collections.group.parts.part.description.fill.size.relative", st_collections_group_parts_part_description_fill_size_relative},
499      {"collections.group.parts.part.description.fill.size.offset", st_collections_group_parts_part_description_fill_size_offset},
500      {"collections.group.parts.part.description.fill.spread", st_collections_group_parts_part_description_fill_spread},
501      {"collections.group.parts.part.description.fill.type", st_collections_group_parts_part_description_fill_type},
502      {"collections.group.parts.part.description.color_class", st_collections_group_parts_part_description_color_class},
503      {"collections.group.parts.part.description.color", st_collections_group_parts_part_description_color},
504      {"collections.group.parts.part.description.color2", st_collections_group_parts_part_description_color2},
505      {"collections.group.parts.part.description.color3", st_collections_group_parts_part_description_color3},
506      {"collections.group.parts.part.description.text.text", st_collections_group_parts_part_description_text_text},
507      {"collections.group.parts.part.description.text.text_class", st_collections_group_parts_part_description_text_text_class},
508      {"collections.group.parts.part.description.text.font", st_collections_group_parts_part_description_text_font},
509      {"collections.group.parts.part.description.text.style", st_collections_group_parts_part_description_text_style},
510      {"collections.group.parts.part.description.text.repch", st_collections_group_parts_part_description_text_repch},
511      {"collections.group.parts.part.description.text.size", st_collections_group_parts_part_description_text_size},
512      {"collections.group.parts.part.description.text.size_range", st_collections_group_parts_part_description_text_size_range},
513      {"collections.group.parts.part.description.text.fit", st_collections_group_parts_part_description_text_fit},
514      {"collections.group.parts.part.description.text.min", st_collections_group_parts_part_description_text_min},
515      {"collections.group.parts.part.description.text.max", st_collections_group_parts_part_description_text_max},
516      {"collections.group.parts.part.description.text.align", st_collections_group_parts_part_description_text_align},
517      {"collections.group.parts.part.description.text.source", st_collections_group_parts_part_description_text_source},
518      {"collections.group.parts.part.description.text.text_source", st_collections_group_parts_part_description_text_text_source},
519      {"collections.group.parts.part.description.text.font", st_fonts_font}, /* dup */
520      {"collections.group.parts.part.description.text.fonts.font", st_fonts_font}, /* dup */
521      {"collections.group.parts.part.description.text.elipsis", st_collections_group_parts_part_description_text_elipsis},
522      {"collections.group.parts.part.description.text.ellipsis", st_collections_group_parts_part_description_text_elipsis},
523      {"collections.group.parts.part.description.box.layout", st_collections_group_parts_part_description_box_layout},
524      {"collections.group.parts.part.description.box.align", st_collections_group_parts_part_description_box_align},
525      {"collections.group.parts.part.description.box.padding", st_collections_group_parts_part_description_box_padding},
526      {"collections.group.parts.part.description.box.min", st_collections_group_parts_part_description_box_min},
527      {"collections.group.parts.part.description.table.homogeneous", st_collections_group_parts_part_description_table_homogeneous},
528      {"collections.group.parts.part.description.table.align", st_collections_group_parts_part_description_table_align},
529      {"collections.group.parts.part.description.table.padding", st_collections_group_parts_part_description_table_padding},
530      {"collections.group.parts.part.description.table.min", st_collections_group_parts_part_description_table_min},
531      {"collections.group.parts.part.description.map.perspective", st_collections_group_parts_part_description_map_perspective},
532      {"collections.group.parts.part.description.map.light", st_collections_group_parts_part_description_map_light},
533      {"collections.group.parts.part.description.map.rotation.center", st_collections_group_parts_part_description_map_rotation_center},
534      {"collections.group.parts.part.description.map.rotation.x", st_collections_group_parts_part_description_map_rotation_x},
535      {"collections.group.parts.part.description.map.rotation.y", st_collections_group_parts_part_description_map_rotation_y},
536      {"collections.group.parts.part.description.map.rotation.z", st_collections_group_parts_part_description_map_rotation_z},
537      {"collections.group.parts.part.description.map.on", st_collections_group_parts_part_description_map_on},
538      {"collections.group.parts.part.description.map.smooth", st_collections_group_parts_part_description_map_smooth},
539      {"collections.group.parts.part.description.map.alpha", st_collections_group_parts_part_description_map_alpha},
540      {"collections.group.parts.part.description.map.backface_cull", st_collections_group_parts_part_description_map_backface_cull},
541      {"collections.group.parts.part.description.map.perspective_on", st_collections_group_parts_part_description_map_perspective_on},
542      {"collections.group.parts.part.description.perspective.zplane", st_collections_group_parts_part_description_perspective_zplane},
543      {"collections.group.parts.part.description.perspective.focal", st_collections_group_parts_part_description_perspective_focal},
544      {"collections.group.parts.part.description.params.int", st_collections_group_parts_part_description_params_int},
545      {"collections.group.parts.part.description.params.double", st_collections_group_parts_part_description_params_double},
546      {"collections.group.parts.part.description.params.string", st_collections_group_parts_part_description_params_string},
547      {"collections.group.parts.part.description.params.bool", st_collections_group_parts_part_description_params_bool},
548      {"collections.group.parts.part.description.params.choice", st_collections_group_parts_part_description_params_choice},
549      {"collections.group.parts.part.description.images.image", st_images_image}, /* dup */
550      {"collections.group.parts.part.description.images.set.name", st_images_set_name},
551      {"collections.group.parts.part.description.images.set.image.image", st_images_set_image_image},
552      {"collections.group.parts.part.description.images.set.image.size", st_images_set_image_size},
553      {"collections.group.parts.part.description.font", st_fonts_font}, /* dup */
554      {"collections.group.parts.part.description.fonts.font", st_fonts_font}, /* dup */
555      {"collections.group.parts.part.description.styles.style.name", st_styles_style_name}, /* dup */
556      {"collections.group.parts.part.description.styles.style.base", st_styles_style_base}, /* dup */
557      {"collections.group.parts.part.description.styles.style.tag", st_styles_style_tag}, /* dup */
558      {"collections.group.parts.part.description.color_classes.color_class.name", st_color_class_name}, /* dup */
559      {"collections.group.parts.part.description.color_classes.color_class.color", st_color_class_color}, /* dup */
560      {"collections.group.parts.part.description.color_classes.color_class.color2", st_color_class_color2}, /* dup */
561      {"collections.group.parts.part.description.color_classes.color_class.color3", st_color_class_color3}, /* dup */
562      {"collections.group.parts.part.description.programs.image", st_images_image}, /* dup */
563      {"collections.group.parts.part.description.programs.set.name", st_images_set_name},
564      {"collections.group.parts.part.description.programs.set.image.image", st_images_set_image_image},
565      {"collections.group.parts.part.description.programs.set.image.size", st_images_set_image_size},
566      {"collections.group.parts.part.description.programs.images.image", st_images_image}, /* dup */
567      {"collections.group.parts.part.description.programs.images.set.name", st_images_set_name},
568      {"collections.group.parts.part.description.programs.images.set.image.image", st_images_set_image_image},
569      {"collections.group.parts.part.description.programs.images.set.image.size", st_images_set_image_size},
570      {"collections.group.parts.part.description.programs.font", st_fonts_font}, /* dup */
571      {"collections.group.parts.part.description.programs.fonts.font", st_fonts_font}, /* dup */
572      {"collections.group.parts.part.description.programs.program.name", st_collections_group_programs_program_name}, /* dup */
573      {"collections.group.parts.part.description.programs.program.signal", st_collections_group_programs_program_signal}, /* dup */
574      {"collections.group.parts.part.description.programs.program.source", st_collections_group_programs_program_source}, /* dup */
575      {"collections.group.parts.part.description.programs.program.in", st_collections_group_programs_program_in}, /* dup */
576      {"collections.group.parts.part.description.programs.program.action", st_collections_group_programs_program_action}, /* dup */
577      {"collections.group.parts.part.description.programs.program.transition", st_collections_group_programs_program_transition}, /* dup */
578      {"collections.group.parts.part.description.programs.program.target", st_collections_group_programs_program_target}, /* dup */
579      {"collections.group.parts.part.description.programs.program.after", st_collections_group_programs_program_after}, /* dup */
580      {"collections.group.parts.part.description.programs.program.api", st_collections_group_programs_program_api}, /* dup */
581      {"collections.group.parts.part.description.program.name", st_collections_group_programs_program_name}, /* dup */
582      {"collections.group.parts.part.description.program.signal", st_collections_group_programs_program_signal}, /* dup */
583      {"collections.group.parts.part.description.program.source", st_collections_group_programs_program_source}, /* dup */
584      {"collections.group.parts.part.description.program.in", st_collections_group_programs_program_in}, /* dup */
585      {"collections.group.parts.part.description.program.action", st_collections_group_programs_program_action}, /* dup */
586      {"collections.group.parts.part.description.program.transition", st_collections_group_programs_program_transition}, /* dup */
587      {"collections.group.parts.part.description.program.target", st_collections_group_programs_program_target}, /* dup */
588      {"collections.group.parts.part.description.program.after", st_collections_group_programs_program_after}, /* dup */
589      {"collections.group.parts.part.description.program.api", st_collections_group_programs_program_api}, /* dup */
590      {"collections.group.parts.part.programs.image", st_images_image}, /* dup */
591      {"collections.group.parts.part.programs.set.name", st_images_set_name},
592      {"collections.group.parts.part.programs.set.image.image", st_images_set_image_image},
593      {"collections.group.parts.part.programs.set.image.size", st_images_set_image_size},
594      {"collections.group.parts.part.programs.images.image", st_images_image}, /* dup */
595      {"collections.group.parts.part.programs.images.set.name", st_images_set_name},
596      {"collections.group.parts.part.programs.images.set.image.image", st_images_set_image_image},
597      {"collections.group.parts.part.programs.images.set.image.size", st_images_set_image_size},
598      {"collections.group.parts.part.programs.font", st_fonts_font}, /* dup */
599      {"collections.group.parts.part.programs.fonts.font", st_fonts_font}, /* dup */
600      {"collections.group.parts.part.programs.program.name", st_collections_group_programs_program_name}, /* dup */
601      {"collections.group.parts.part.programs.program.signal", st_collections_group_programs_program_signal}, /* dup */
602      {"collections.group.parts.part.programs.program.source", st_collections_group_programs_program_source}, /* dup */
603      {"collections.group.parts.part.programs.program.in", st_collections_group_programs_program_in}, /* dup */
604      {"collections.group.parts.part.programs.program.action", st_collections_group_programs_program_action}, /* dup */
605      {"collections.group.parts.part.programs.program.transition", st_collections_group_programs_program_transition}, /* dup */
606      {"collections.group.parts.part.programs.program.target", st_collections_group_programs_program_target}, /* dup */
607      {"collections.group.parts.part.programs.program.after", st_collections_group_programs_program_after}, /* dup */
608      {"collections.group.parts.part.programs.program.api", st_collections_group_programs_program_api}, /* dup */
609      {"collections.group.parts.part.program.name", st_collections_group_programs_program_name}, /* dup */
610      {"collections.group.parts.part.program.signal", st_collections_group_programs_program_signal}, /* dup */
611      {"collections.group.parts.part.program.source", st_collections_group_programs_program_source}, /* dup */
612      {"collections.group.parts.part.program.in", st_collections_group_programs_program_in}, /* dup */
613      {"collections.group.parts.part.program.action", st_collections_group_programs_program_action}, /* dup */
614      {"collections.group.parts.part.program.transition", st_collections_group_programs_program_transition}, /* dup */
615      {"collections.group.parts.part.program.target", st_collections_group_programs_program_target}, /* dup */
616      {"collections.group.parts.part.program.after", st_collections_group_programs_program_after}, /* dup */
617      {"collections.group.parts.part.program.api", st_collections_group_programs_program_api}, /* dup */
618      {"collections.group.parts.programs.image", st_images_image}, /* dup */
619      {"collections.group.parts.programs.set.name", st_images_set_name},
620      {"collections.group.parts.programs.set.image.image", st_images_set_image_image},
621      {"collections.group.parts.programs.set.image.size", st_images_set_image_size},
622      {"collections.group.parts.programs.images.image", st_images_image}, /* dup */
623      {"collections.group.parts.programs.images.set.name", st_images_set_name},
624      {"collections.group.parts.programs.images.set.image.image", st_images_set_image_image},
625      {"collections.group.parts.programs.images.set.image.size", st_images_set_image_size},
626      {"collections.group.parts.programs.font", st_fonts_font}, /* dup */
627      {"collections.group.parts.programs.fonts.font", st_fonts_font}, /* dup */
628      {"collections.group.parts.programs.program.name", st_collections_group_programs_program_name}, /* dup */
629      {"collections.group.parts.programs.program.signal", st_collections_group_programs_program_signal}, /* dup */
630      {"collections.group.parts.programs.program.source", st_collections_group_programs_program_source}, /* dup */
631      {"collections.group.parts.programs.program.filter", st_collections_group_programs_program_filter}, /* dup */
632      {"collections.group.parts.programs.program.in", st_collections_group_programs_program_in}, /* dup */
633      {"collections.group.parts.programs.program.action", st_collections_group_programs_program_action}, /* dup */
634      {"collections.group.parts.programs.program.transition", st_collections_group_programs_program_transition}, /* dup */
635      {"collections.group.parts.programs.program.target", st_collections_group_programs_program_target}, /* dup */
636      {"collections.group.parts.programs.program.after", st_collections_group_programs_program_after},
637      {"collections.group.parts.programs.program.api", st_collections_group_programs_program_api},
638      {"collections.group.parts.program.name", st_collections_group_programs_program_name}, /* dup */
639      {"collections.group.parts.program.signal", st_collections_group_programs_program_signal}, /* dup */
640      {"collections.group.parts.program.source", st_collections_group_programs_program_source}, /* dup */
641      {"collections.group.parts.program.filter", st_collections_group_programs_program_filter}, /* dup */
642      {"collections.group.parts.program.in", st_collections_group_programs_program_in}, /* dup */
643      {"collections.group.parts.program.action", st_collections_group_programs_program_action}, /* dup */
644      {"collections.group.parts.program.transition", st_collections_group_programs_program_transition}, /* dup */
645      {"collections.group.parts.program.target", st_collections_group_programs_program_target}, /* dup */
646      {"collections.group.parts.program.after", st_collections_group_programs_program_after}, /* dup */
647      {"collections.group.parts.program.api", st_collections_group_programs_program_api}, /* dup */
648      {"collections.group.program.name", st_collections_group_programs_program_name}, /* dup */
649      {"collections.group.program.signal", st_collections_group_programs_program_signal}, /* dup */
650      {"collections.group.program.source", st_collections_group_programs_program_source}, /* dup */
651      {"collections.group.program.filter", st_collections_group_programs_program_filter}, /* dup */
652      {"collections.group.program.in", st_collections_group_programs_program_in}, /* dup */
653      {"collections.group.program.action", st_collections_group_programs_program_action}, /* dup */
654      {"collections.group.program.transition", st_collections_group_programs_program_transition}, /* dup */
655      {"collections.group.program.target", st_collections_group_programs_program_target}, /* dup */
656      {"collections.group.program.after", st_collections_group_programs_program_after}, /* dup */
657      {"collections.group.program.api", st_collections_group_programs_program_api}, /* dup */
658      {"collections.group.programs.program.name", st_collections_group_programs_program_name},
659      {"collections.group.programs.program.signal", st_collections_group_programs_program_signal},
660      {"collections.group.programs.program.source", st_collections_group_programs_program_source},
661      {"collections.group.programs.program.filter", st_collections_group_programs_program_filter}, /* dup */
662      {"collections.group.programs.program.in", st_collections_group_programs_program_in},
663      {"collections.group.programs.program.action", st_collections_group_programs_program_action},
664      {"collections.group.programs.program.transition", st_collections_group_programs_program_transition},
665      {"collections.group.programs.program.target", st_collections_group_programs_program_target},
666      {"collections.group.programs.program.after", st_collections_group_programs_program_after},
667      {"collections.group.programs.program.api", st_collections_group_programs_program_api},
668      {"collections.group.programs.image", st_images_image}, /* dup */
669      {"collections.group.programs.set.name", st_images_set_name},
670      {"collections.group.programs.set.image.image", st_images_set_image_image},
671      {"collections.group.programs.set.image.size", st_images_set_image_size},
672      {"collections.group.programs.images.image", st_images_image}, /* dup */
673      {"collections.group.programs.images.set.name", st_images_set_name},
674      {"collections.group.programs.images.set.image.image", st_images_set_image_image},
675      {"collections.group.programs.images.set.image.size", st_images_set_image_size},
676      {"collections.group.programs.font", st_fonts_font}, /* dup */
677      {"collections.group.programs.fonts.font", st_fonts_font} /* dup */
678 };
679
680 New_Object_Handler object_handlers[] =
681 {
682      {"externals", NULL},
683      {"images", NULL},
684      {"images.set", ob_images_set},
685      {"images.set.image", ob_images_set_image},
686      {"fonts", NULL},
687      {"data", NULL},
688      {"styles", NULL},
689      {"styles.style", ob_styles_style},
690      {"color_classes", NULL},
691      {"color_classes.color_class", ob_color_class},
692      {"spectra", NULL},
693      {"collections", ob_collections},
694      {"collections.externals", NULL}, /* dup */
695      {"collections.set", ob_images_set}, /* dup */
696      {"collections.set.image", ob_images_set_image}, /* dup */
697      {"collections.images", NULL}, /* dup */
698      {"collections.images.set", ob_images_set}, /* dup */
699      {"collections.images.set.image", ob_images_set_image}, /* dup */
700      {"collections.fonts", NULL}, /* dup */
701      {"collections.styles", NULL}, /* dup */
702      {"collections.styles.style", ob_styles_style}, /* dup */
703      {"collections.color_classes", NULL}, /* dup */
704      {"collections.color_classes.color_class", ob_color_class}, /* dup */
705      {"collections.sounds", NULL},
706      {"collections.group.sounds", NULL}, /* dup */
707      {"collections.sounds.sample", NULL},
708      {"collections.group.sounds.sample", NULL}, /* dup */
709      {"collections.group", ob_collections_group},
710      {"collections.group.data", NULL},
711      {"collections.group.limits", NULL},
712      {"collections.group.script", ob_collections_group_script},
713      {"collections.group.lua_script", ob_collections_group_lua_script},
714      {"collections.group.externals", NULL}, /* dup */
715      {"collections.group.set", ob_images_set}, /* dup */
716      {"collections.group.set.image", ob_images_set_image}, /* dup */
717      {"collections.group.images", NULL}, /* dup */
718      {"collections.group.images.set", ob_images_set}, /* dup */
719      {"collections.group.images.set.image", ob_images_set_image}, /* dup */
720      {"collections.group.fonts", NULL}, /* dup */
721      {"collections.group.styles", NULL}, /* dup */
722      {"collections.group.styles.style", ob_styles_style}, /* dup */
723      {"collections.group.color_classes", NULL}, /* dup */
724      {"collections.group.color_classes.color_class", ob_color_class}, /* dup */
725      {"collections.group.parts", NULL},
726      {"collections.group.parts.set", ob_images_set}, /* dup */
727      {"collections.group.parts.set.image", ob_images_set_image}, /* dup */
728      {"collections.group.parts.images", NULL}, /* dup */
729      {"collections.group.parts.images.set", ob_images_set}, /* dup */
730      {"collections.group.parts.images.set.image", ob_images_set_image}, /* dup */
731      {"collections.group.parts.fonts", NULL}, /* dup */
732      {"collections.group.parts.styles", NULL}, /* dup */
733      {"collections.group.parts.styles.style", ob_styles_style}, /* dup */
734      {"collections.group.parts.color_classes", NULL}, /* dup */
735      {"collections.group.parts.color_classes.color_class", ob_color_class}, /* dup */
736      {"collections.group.parts.part", ob_collections_group_parts_part},
737      {"collections.group.parts.part.dragable", NULL},
738      {"collections.group.parts.part.set", ob_images_set}, /* dup */
739      {"collections.group.parts.part.set.image", ob_images_set_image}, /* dup */
740      {"collections.group.parts.part.images", NULL}, /* dup */
741      {"collections.group.parts.part.images.set", ob_images_set}, /* dup */
742      {"collections.group.parts.part.images.set.image", ob_images_set_image}, /* dup */
743      {"collections.group.parts.part.fonts", NULL}, /* dup */
744      {"collections.group.parts.part.styles", NULL}, /* dup */
745      {"collections.group.parts.part.styles.style", ob_styles_style}, /* dup */
746      {"collections.group.parts.part.color_classes", NULL}, /* dup */
747      {"collections.group.parts.part.color_classes.color_class", ob_color_class}, /* dup */
748      {"collections.group.parts.part.box", NULL},
749      {"collections.group.parts.part.box.items", NULL},
750      {"collections.group.parts.part.box.items.item", ob_collections_group_parts_part_box_items_item},
751      {"collections.group.parts.part.table", NULL},
752      {"collections.group.parts.part.table.items", NULL},
753      {"collections.group.parts.part.table.items.item", ob_collections_group_parts_part_box_items_item}, /* dup */
754      {"collections.group.parts.part.description", ob_collections_group_parts_part_description},
755      {"collections.group.parts.part.description.rel1", NULL},
756      {"collections.group.parts.part.description.rel2", NULL},
757      {"collections.group.parts.part.description.image", NULL}, /* dup */
758      {"collections.group.parts.part.description.image.set", ob_images_set}, /* dup */
759      {"collections.group.parts.part.description.image.set.image", ob_images_set_image}, /* dup */
760      {"collections.group.parts.part.description.image.images", NULL}, /* dup */
761      {"collections.group.parts.part.description.image.images.set", ob_images_set}, /* dup */
762      {"collections.group.parts.part.description.image.images.set.image", ob_images_set_image}, /* dup */
763      {"collections.group.parts.part.description.fill", NULL},
764      {"collections.group.parts.part.description.fill.origin", NULL},
765      {"collections.group.parts.part.description.fill.size", NULL},
766      {"collections.group.parts.part.description.text", NULL},
767      {"collections.group.parts.part.description.text.fonts", NULL}, /* dup */
768      {"collections.group.parts.part.description.images", NULL}, /* dup */
769      {"collections.group.parts.part.description.images.set", ob_images_set}, /* dup */
770      {"collections.group.parts.part.description.images.set.image", ob_images_set_image}, /* dup */
771      {"collections.group.parts.part.description.fonts", NULL}, /* dup */
772      {"collections.group.parts.part.description.styles", NULL}, /* dup */
773      {"collections.group.parts.part.description.styles.style", ob_styles_style}, /* dup */
774      {"collections.group.parts.part.description.box", NULL},
775      {"collections.group.parts.part.description.table", NULL},
776      {"collections.group.parts.part.description.map", NULL},
777      {"collections.group.parts.part.description.map.rotation", NULL},
778      {"collections.group.parts.part.description.perspective", NULL},
779      {"collections.group.parts.part.description.params", NULL},
780      {"collections.group.parts.part.description.color_classes", NULL}, /* dup */
781      {"collections.group.parts.part.description.color_classes.color_class", ob_color_class}, /* dup */
782      {"collections.group.parts.part.description.program", ob_collections_group_programs_program}, /* dup */
783      {"collections.group.parts.part.description.program.script", ob_collections_group_programs_program_script}, /* dup */
784      {"collections.group.parts.part.description.programs", NULL}, /* dup */
785      {"collections.group.parts.part.description.programs.set", ob_images_set}, /* dup */
786      {"collections.group.parts.part.description.programs.set.image", ob_images_set_image}, /* dup */
787      {"collections.group.parts.part.description.programs.images", NULL}, /* dup */
788      {"collections.group.parts.part.description.programs.images.set", ob_images_set},
789      {"collections.group.parts.part.description.programs.images.set.image", ob_images_set_image}, /* dup */
790      {"collections.group.parts.part.description.programs.fonts", NULL}, /* dup */
791      {"collections.group.parts.part.description.programs.program", ob_collections_group_programs_program}, /* dup */
792      {"collections.group.parts.part.description.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
793      {"collections.group.parts.part.description.script", ob_collections_group_script}, /* dup */
794      {"collections.group.parts.part.program", ob_collections_group_programs_program}, /* dup */
795      {"collections.group.parts.part.program.script", ob_collections_group_programs_program_script}, /* dup */
796      {"collections.group.parts.part.programs", NULL}, /* dup */
797      {"collections.group.parts.part.programs.set", ob_images_set}, /* dup */
798      {"collections.group.parts.part.programs.set.image", ob_images_set_image}, /* dup */
799      {"collections.group.parts.part.programs.images", NULL}, /* dup */
800      {"collections.group.parts.part.programs.images.set", ob_images_set}, /* dup */
801      {"collections.group.parts.part.programs.images.set.image", ob_images_set_image}, /* dup */
802      {"collections.group.parts.part.programs.fonts", NULL}, /* dup */
803      {"collections.group.parts.part.programs.program", ob_collections_group_programs_program}, /* dup */
804      {"collections.group.parts.part.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
805      {"collections.group.parts.part.script", ob_collections_group_script}, /* dup */
806      {"collections.group.parts.program", ob_collections_group_programs_program}, /* dup */
807      {"collections.group.parts.program.script", ob_collections_group_programs_program_script}, /* dup */
808      {"collections.group.parts.programs", NULL}, /* dup */
809      {"collections.group.parts.programs.set", ob_images_set}, /* dup */
810      {"collections.group.parts.programs.set.image", ob_images_set_image}, /* dup */
811      {"collections.group.parts.programs.images", NULL}, /* dup */
812      {"collections.group.parts.programs.images.set", ob_images_set}, /* dup */
813      {"collections.group.parts.programs.images.set.image", ob_images_set_image}, /* dup */
814      {"collections.group.parts.programs.fonts", NULL}, /* dup */
815      {"collections.group.parts.programs.program", ob_collections_group_programs_program}, /* dup */
816      {"collections.group.parts.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
817      {"collections.group.parts.script", ob_collections_group_script}, /* dup */
818      {"collections.group.program", ob_collections_group_programs_program}, /* dup */
819      {"collections.group.program.script", ob_collections_group_programs_program_script}, /* dup */
820      {"collections.group.programs", NULL},
821      {"collections.group.programs.set", ob_images_set}, /* dup */
822      {"collections.group.programs.set.image", ob_images_set_image}, /* dup */
823      {"collections.group.programs.images", NULL}, /* dup */
824      {"collections.group.programs.images.set", ob_images_set}, /* dup */
825      {"collections.group.programs.images.set.image", ob_images_set_image}, /* dup */
826      {"collections.group.programs.fonts", NULL}, /* dup */
827      {"collections.group.programs.program", ob_collections_group_programs_program},
828      {"collections.group.programs.program.script", ob_collections_group_programs_program_script},
829      {"collections.group.programs.script", ob_collections_group_script} /* dup */
830 };
831
832 New_Nested_Handler nested_handlers[] = {
833      {"collections.group.parts", "part", NULL, edje_cc_handlers_hierarchy_pop }
834 };
835
836 /*****/
837
838 int
839 object_handler_num(void)
840 {
841    return sizeof(object_handlers) / sizeof (New_Object_Handler);
842 }
843
844 int
845 statement_handler_num(void)
846 {
847    return sizeof(statement_handlers) / sizeof (New_Object_Handler);
848 }
849
850 int
851 nested_handler_num(void)
852 {
853    return sizeof(nested_handlers) / sizeof (New_Nested_Handler);
854 }
855
856 static void
857 _edje_part_description_fill(Edje_Part_Description_Spec_Fill *fill)
858 {
859    fill->smooth = 1;
860    fill->pos_rel_x = FROM_DOUBLE(0.0);
861    fill->pos_abs_x = 0;
862    fill->rel_x = FROM_DOUBLE(1.0);
863    fill->abs_x = 0;
864    fill->pos_rel_y = FROM_DOUBLE(0.0);
865    fill->pos_abs_y = 0;
866    fill->rel_y = FROM_DOUBLE(1.0);
867    fill->abs_y = 0;
868    fill->angle = 0;
869    fill->spread = 0;
870    fill->type = EDJE_FILL_TYPE_SCALE;
871 }
872
873 static void
874 _edje_part_description_image_remove(Edje_Part_Description_Image *ed)
875 {
876    unsigned int j;
877
878    if (!ed) return;
879
880    data_queue_image_remove(&(ed->image.id), &(ed->image.set));
881
882    for (j = 0; j < ed->image.tweens_count; ++j)
883      data_queue_image_remove(&(ed->image.tweens[j]->id),
884                              &(ed->image.tweens[j]->set));
885 }
886
887 void
888 part_description_image_cleanup(Edje_Part *ep)
889 {
890    Edje_Part_Description_Image *ed;
891    unsigned int j;
892
893    if (ep->type != EDJE_PART_TYPE_IMAGE)
894      return ;
895
896    ed = (Edje_Part_Description_Image*) ep->default_desc;
897    _edje_part_description_image_remove(ed);
898
899    for (j = 0; j < ep->other.desc_count; j++)
900      {
901         ed = (Edje_Part_Description_Image*) ep->other.desc[j];
902         _edje_part_description_image_remove(ed);
903      }
904 }
905
906 static Edje_Part_Description_Common *
907 _edje_part_description_alloc(unsigned char type, const char *collection, const char *part)
908 {
909    Edje_Part_Description_Common *result = NULL;
910
911    switch (type)
912      {
913       case EDJE_PART_TYPE_SPACER:
914       case EDJE_PART_TYPE_RECTANGLE:
915       case EDJE_PART_TYPE_SWALLOW:
916       case EDJE_PART_TYPE_GROUP:
917          result = mem_alloc(SZ(Edje_Part_Description_Common));
918          break;
919       case EDJE_PART_TYPE_TEXT:
920       case EDJE_PART_TYPE_TEXTBLOCK:
921         {
922            Edje_Part_Description_Text *ed;
923
924            ed = mem_alloc(SZ(Edje_Part_Description_Text));
925
926            ed->text.color3.r = 0;
927            ed->text.color3.g = 0;
928            ed->text.color3.b = 0;
929            ed->text.color3.a = 128;
930            ed->text.align.x = FROM_DOUBLE(0.5);
931            ed->text.align.y = FROM_DOUBLE(0.5);
932            ed->text.id_source = -1;
933            ed->text.id_text_source = -1;
934
935            result = &ed->common;
936            break;
937         }
938       case EDJE_PART_TYPE_IMAGE:
939         {
940            Edje_Part_Description_Image *ed;
941
942            ed = mem_alloc(SZ(Edje_Part_Description_Image));
943
944            ed->image.id = -1;
945
946            _edje_part_description_fill(&ed->image.fill);
947
948            result = &ed->common;
949            break;
950         }
951       case EDJE_PART_TYPE_PROXY:
952         {
953            Edje_Part_Description_Proxy *ed;
954
955            ed = mem_alloc(SZ(Edje_Part_Description_Proxy));
956
957            ed->proxy.id = -1;
958
959            _edje_part_description_fill(&ed->proxy.fill);
960
961            result = &ed->common;
962            break;
963         }
964       case EDJE_PART_TYPE_BOX:
965         {
966            Edje_Part_Description_Box *ed;
967
968            ed = mem_alloc(SZ(Edje_Part_Description_Box));
969
970            ed->box.layout = NULL;
971            ed->box.alt_layout = NULL;
972            ed->box.align.x = FROM_DOUBLE(0.5);
973            ed->box.align.y = FROM_DOUBLE(0.5);
974            ed->box.padding.x = 0;
975            ed->box.padding.y = 0;
976
977            result = &ed->common;
978            break;
979         }
980       case EDJE_PART_TYPE_TABLE:
981         {
982            Edje_Part_Description_Table *ed;
983
984            ed = mem_alloc(SZ(Edje_Part_Description_Table));
985
986            ed->table.homogeneous = EDJE_OBJECT_TABLE_HOMOGENEOUS_NONE;
987            ed->table.align.x = FROM_DOUBLE(0.5);
988            ed->table.align.y = FROM_DOUBLE(0.5);
989            ed->table.padding.x = 0;
990            ed->table.padding.y = 0;
991
992            result = &ed->common;
993            break;
994         }
995       case EDJE_PART_TYPE_EXTERNAL:
996         {
997            Edje_Part_Description_External *ed;
998
999            ed = mem_alloc(SZ(Edje_Part_Description_External));
1000
1001            ed->external_params = NULL;
1002
1003            result = &ed->common;
1004            break;
1005         }
1006      }
1007
1008    if (!result)
1009      {
1010         ERR("Unknown type %i of part %s in collection %s.",
1011             type, part, collection);
1012         exit(-1);
1013      }
1014
1015    return result;
1016 }
1017
1018 static void
1019 _edje_program_check(const char *name, Edje_Program *me, Edje_Program **pgrms, unsigned int count)
1020 {
1021    Edje_Part_Collection *pc;
1022    unsigned int i;
1023    Edje_Program_Parser *epp;
1024
1025    pc = eina_list_data_get(eina_list_last(edje_collections));
1026
1027    for (i = 0; i < count; ++i)
1028      if (pgrms[i]->name)
1029        if (pgrms[i] != me && (!strcmp(name, pgrms[i]->name)))
1030          {
1031             epp = (Edje_Program_Parser *)pgrms[i];
1032             if (!epp->can_override)
1033               {
1034                  ERR("parse error %s:%i. There is already a program of the name %s",
1035                      file_in, line - 1, name);
1036                  exit(-1);
1037               }
1038             else
1039               {
1040                  _edje_program_remove(pc, me);
1041                  current_program = pgrms[i];
1042                  epp->can_override = EINA_FALSE;
1043                  return;
1044               }
1045          }
1046 }
1047
1048 static void
1049 _edje_program_copy(Edje_Program *ep, Edje_Program *ep2)
1050 {
1051    Edje_Part_Collection *pc;
1052    Edje_Program_Target *et, *et2;
1053    Edje_Program_After *pa, *pa2;
1054    Edje_Program_Parser *epp;
1055    Eina_List *l;
1056    char *name;
1057    char *copy;
1058
1059    pc = eina_list_data_get(eina_list_last(edje_collections));
1060
1061    #define STRDUP(x) x ? strdup(x) : NULL
1062    ep->name = STRDUP(ep2->name);
1063
1064    _edje_program_remove(pc, current_program);
1065    ep->signal = STRDUP(ep2->signal);
1066    ep->source = STRDUP(ep2->source);
1067    _edje_program_insert(pc, current_program);
1068
1069    ep->filter.part = STRDUP(ep2->filter.part);
1070    ep->filter.state = STRDUP(ep2->filter.state);
1071    ep->in.from = ep2->in.from;
1072    ep->in.range = ep2->in.range;
1073    ep->action = ep2->action;
1074    ep->state = STRDUP(ep2->state);
1075    ep->state2 = STRDUP(ep2->state2);
1076    ep->value = ep2->value;
1077    ep->value2 = ep2->value2;
1078    ep->tween.mode = ep2->tween.mode;
1079    ep->tween.time = ep2->tween.time;
1080    ep->tween.v1 = ep2->tween.v1;
1081    ep->tween.v2 = ep2->tween.v2;
1082    ep->sample_name = STRDUP(ep2->sample_name);
1083    ep->tone_name = STRDUP(ep2->tone_name);
1084    ep->duration = ep2->duration;
1085    ep->speed = ep2->speed;
1086
1087    EINA_LIST_FOREACH(ep2->targets, l, et2)
1088      {
1089         name = (char*) (et2 + 1);
1090         et = mem_alloc(SZ(Edje_Program_Target) + strlen(name) + 1);
1091         ep->targets = eina_list_append(ep->targets, et);
1092         copy = (char*) (et + 1);
1093
1094         memcpy(copy, name, strlen(name) + 1);
1095
1096         if (ep2->action == EDJE_ACTION_TYPE_STATE_SET)
1097           data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1098         else if (ep2->action == EDJE_ACTION_TYPE_ACTION_STOP)
1099           data_queue_copied_program_lookup(pc, &(et2->id), &(et->id));
1100         else if (ep2->action == EDJE_ACTION_TYPE_SCRIPT)
1101           data_queue_copied_program_lookup(pc, &(et2->id), &(et->id));
1102         else if (ep2->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
1103           data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1104         else if (ep2->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
1105           data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1106         else if (ep2->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
1107           data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1108         else if (ep2->action == EDJE_ACTION_TYPE_FOCUS_SET)
1109
1110           data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1111         else if (ep2->action == EDJE_ACTION_TYPE_FOCUS_OBJECT)
1112           data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1113         else
1114           {
1115              ERR("parse error %s:%i. target may only be used after action",
1116                  file_in, line - 1);
1117              exit(-1);
1118           }
1119      }
1120
1121    EINA_LIST_FOREACH(ep2->after, l, pa2)
1122      {
1123         name = (char*) (pa2 + 1);
1124         pa = mem_alloc(SZ(Edje_Program_After) + strlen(name) + 1);
1125         ep->after = eina_list_append(ep->after, pa);
1126         copy = (char*) (pa + 1);
1127         memcpy(copy, name, strlen(name) + 1);
1128         data_queue_copied_program_lookup(pc, &(pa2->id), &(pa->id));
1129      }
1130
1131    ep->api.name = STRDUP(ep2->api.name);
1132    ep->api.description = STRDUP(ep2->api.description);
1133    data_queue_copied_part_lookup(pc, &(ep2->param.src), &(ep->param.src));
1134    data_queue_copied_part_lookup(pc, &(ep2->param.dst), &(ep->param.dst));
1135
1136    epp = (Edje_Program_Parser *)ep;
1137    epp->can_override = EINA_TRUE;
1138
1139    #undef STRDUP
1140 }
1141
1142 /*****/
1143
1144 /**
1145    @edcsection{toplevel,Top-Level blocks}
1146  */
1147
1148 /**
1149     @page edcref
1150
1151     @block
1152         externals
1153     @context
1154         externals {
1155            external: "name";
1156         }
1157     @description
1158         The "externals" block is used to list each external module file that will be used in others
1159         programs.
1160     @endblock
1161
1162     @property
1163         external
1164     @parameters
1165         [external filename]
1166     @effect
1167         Used to add a file to the externals list.
1168     @endproperty
1169  */
1170 static void
1171 st_externals_external(void)
1172 {
1173    External *ex;
1174
1175    check_arg_count(1);
1176
1177    if (!edje_file->external_dir)
1178      edje_file->external_dir = mem_alloc(SZ(Edje_External_Directory));
1179
1180    ex = mem_alloc(SZ(External));
1181    ex->name = parse_str(0);
1182      {
1183         Eina_List *l;
1184         External *lex;
1185
1186         EINA_LIST_FOREACH(externals, l, lex)
1187           {
1188              if (!strcmp(lex->name, ex->name))
1189                {
1190                   free(ex->name);
1191                   free(ex);
1192                   return;
1193                }
1194           }
1195      }
1196    externals = eina_list_append(externals, ex);
1197
1198    if (edje_file->external_dir)
1199      {
1200         edje_file->external_dir->entries_count++;
1201         edje_file->external_dir->entries = realloc(edje_file->external_dir->entries,
1202                                                    sizeof (Edje_External_Directory) * edje_file->external_dir->entries_count);
1203         memset(edje_file->external_dir->entries + edje_file->external_dir->entries_count - 1,
1204                0, sizeof (Edje_External_Directory));
1205         if (!edje_file->external_dir->entries)
1206           {
1207              ERR("not enough memory");
1208              exit(-1);
1209           }
1210
1211         edje_file->external_dir->entries[edje_file->external_dir->entries_count - 1].entry = mem_strdup(ex->name);
1212      }
1213 }
1214
1215 /**
1216     @page edcref
1217
1218     @block
1219         images
1220     @context
1221         images {
1222             image: "filename1.ext" COMP;
1223             image: "filename2.ext" LOSSY 99;
1224             set {
1225                name: "image_name_used";
1226                image {
1227                   image: "filename3.ext" LOSSY 90;
1228                   size: 201 201 500 500;
1229                }
1230                image {
1231                   image: "filename4.ext" COMP;
1232                   size: 51 51 200 200;
1233                }
1234                image {
1235                   image: "filename5.ext" COMP;
1236                   size: 11 11 50 50;
1237                }
1238                image {
1239                   image: "filename6.ext" RAW;
1240                   size: 0 0 10 10;
1241                }
1242             }
1243             ..
1244         }
1245     @description
1246         The "images" block is used to list each image file that will be used in
1247         the theme along with its compression method (if any).
1248         Besides the document's root, additional "images" blocks can be
1249         included inside other blocks, normally "collections", "group" and
1250         "part", easing maintenance of the file list when the theme is split
1251         among multiple files.
1252     @endblock
1253
1254     @property
1255         image
1256     @parameters
1257         [image file] [compression method] (compression level)
1258     @effect
1259         Used to include each image file. The full path to the directory holding
1260         the images can be defined later with edje_cc's "-id" option.
1261         Compression methods:
1262         @li RAW: Uncompressed.
1263         @li COMP: Lossless compression.
1264         @li LOSSY [0-100]: Lossy compression with quality from 0 to 100.
1265         @li USER: Do not embed the file, refer to the external file instead.
1266     @endproperty
1267  */
1268 static void
1269 st_images_image(void)
1270 {
1271    Edje_Image_Directory_Entry *img;
1272    const char *tmp;
1273    unsigned int i;
1274    int v;
1275
1276    check_min_arg_count(2);
1277
1278    if (!edje_file->image_dir)
1279      edje_file->image_dir = mem_alloc(SZ(Edje_Image_Directory));
1280
1281    tmp = parse_str(0);
1282
1283    for (i = 0; i < edje_file->image_dir->entries_count; ++i)
1284      if (!strcmp(edje_file->image_dir->entries[i].entry, tmp))
1285        {
1286           free((char*) tmp);
1287           return;
1288        }
1289
1290    edje_file->image_dir->entries_count++;
1291    edje_file->image_dir->entries = realloc(edje_file->image_dir->entries,
1292                                            sizeof (Edje_Image_Directory_Entry) * edje_file->image_dir->entries_count);
1293    memset(edje_file->image_dir->entries + edje_file->image_dir->entries_count - 1,
1294           0, sizeof (Edje_Image_Directory_Entry));
1295    if (!edje_file->image_dir->entries)
1296      {
1297         ERR("No enough memory.");
1298         exit(-1);
1299      }
1300
1301    img = edje_file->image_dir->entries + edje_file->image_dir->entries_count - 1;
1302
1303    img->entry = tmp;
1304    img->id = edje_file->image_dir->entries_count - 1;
1305    v = parse_enum(1,
1306                   "RAW", 0,
1307                   "COMP", 1,
1308                   "LOSSY", 2,
1309                   "USER", 3,
1310                   NULL);
1311    if (v == 0)
1312      {
1313         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT;
1314         img->source_param = 0;
1315      }
1316    else if (v == 1)
1317      {
1318         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT;
1319         img->source_param = 1;
1320      }
1321    else if (v == 2)
1322      {
1323         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY;
1324         img->source_param = 0;
1325      }
1326    else if (v == 3)
1327      {
1328         img->source_type = EDJE_IMAGE_SOURCE_TYPE_EXTERNAL;
1329         img->source_param = 0;
1330      }
1331    if (img->source_type != EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY)
1332         check_arg_count(2);
1333    else
1334      {
1335         img->source_param = parse_int_range(2, 0, 100);
1336         check_arg_count(3);
1337      }
1338 }
1339
1340 /**
1341     @page edcref
1342
1343     @block
1344         set
1345     @context
1346     set {
1347        name: "image_name_used";
1348        image {
1349           image: "filename3.ext" LOSSY 90;
1350           size: 201 201 500 500;
1351        }
1352        image {
1353           image: "filename4.ext" COMP;
1354           size: 51 51 200 200;
1355        }
1356        image {
1357           image: "filename5.ext" COMP;
1358           size: 11 11 50 50;
1359        }
1360        image {
1361           image: "filename6.ext" RAW;
1362           size: 0 0 10 10;
1363        }
1364     }
1365     @description
1366         The "set" block is used to define an image with different content depending on their size.
1367         Besides the document's root, additional "set" blocks can be
1368         included inside other blocks, normally "collections", "group" and
1369         "part", easing maintenance of the file list when the theme is split
1370         among multiple files.
1371     @endblock
1372  */
1373 static void
1374 ob_images_set(void)
1375 {
1376    if (!edje_file->image_dir)
1377      edje_file->image_dir = mem_alloc(SZ(Edje_Image_Directory));
1378
1379    edje_file->image_dir->sets_count++;
1380    edje_file->image_dir->sets = realloc(edje_file->image_dir->sets,
1381                                         sizeof (Edje_Image_Directory_Set) * edje_file->image_dir->sets_count);
1382    memset(edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1,
1383           0, sizeof (Edje_Image_Directory_Set));
1384    if (!edje_file->image_dir->sets)
1385      {
1386         ERR("Not enough memory.");
1387         exit(-1);
1388      }
1389    edje_file->image_dir->sets[edje_file->image_dir->sets_count - 1].id = edje_file->image_dir->sets_count - 1;
1390 }
1391
1392 /**
1393     @page edcref
1394
1395     @property
1396         name
1397     @parameters
1398         [image name]
1399     @effect
1400         Define the name that refer to this image description.
1401     @endproperty
1402 */
1403 static void
1404 st_images_set_name(void)
1405 {
1406    check_arg_count(1);
1407
1408    edje_file->image_dir->sets[edje_file->image_dir->sets_count - 1].name = parse_str(0);
1409 }
1410
1411 /**
1412     @page edcref
1413
1414     @block
1415         image
1416     @description
1417         The "image" block inside a "set" block define the characteristic of an image.
1418         Every block will describe one image and the size rule to use it.
1419     @endblock
1420 **/
1421 static void
1422 ob_images_set_image(void)
1423 {
1424    Edje_Image_Directory_Set_Entry *entry;
1425    Edje_Image_Directory_Set *set;
1426
1427    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
1428
1429    entry = mem_alloc(SZ(Edje_Image_Directory_Set_Entry));
1430
1431    set->entries = eina_list_append(set->entries, entry);
1432 }
1433
1434 /**
1435     @page edcref
1436
1437     @property
1438         image
1439     @parameters
1440         [image file] [compression method] (compression level)
1441     @effect
1442         Used to include each image file. The full path to the directory holding
1443         the images can be defined later with edje_cc's "-id" option.
1444         Compression methods:
1445         @li RAW: Uncompressed.
1446         @li COMP: Lossless compression.
1447         @li LOSSY [0-100]: Lossy compression with quality from 0 to 100.
1448         @li USER: Do not embed the file, refer to the external file instead.
1449     @endproperty
1450 **/
1451 static void
1452 st_images_set_image_image(void)
1453 {
1454    Edje_Image_Directory_Set_Entry *entry;
1455    Edje_Image_Directory_Set *set;
1456    unsigned int i;
1457
1458    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
1459    entry = eina_list_data_get(eina_list_last(set->entries));
1460
1461    /* Add the image to the global pool with the same syntax. */
1462    st_images_image();
1463
1464    entry->name = parse_str(0);
1465
1466    for (i = 0; i < edje_file->image_dir->entries_count; ++i)
1467      if (!strcmp(edje_file->image_dir->entries[i].entry, entry->name))
1468        {
1469          entry->id = i;
1470          return;
1471        }
1472 }
1473
1474 /**
1475     @page edcref
1476
1477     @property
1478         size
1479     @parameters
1480         [minw minh maxw mawh]
1481     @effect
1482         Define the minimal and maximal size that will select the specified image.
1483     @endproperty
1484 */
1485 static void
1486 st_images_set_image_size(void)
1487 {
1488    Edje_Image_Directory_Set_Entry *entry;
1489    Edje_Image_Directory_Set *set;
1490
1491    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
1492    entry = eina_list_data_get(eina_list_last(set->entries));
1493
1494    entry->size.min.w = parse_int(0);
1495    entry->size.min.h = parse_int(1);
1496    entry->size.max.w = parse_int(2);
1497    entry->size.max.h = parse_int(3);
1498
1499    if (entry->size.min.w > entry->size.max.w
1500        || entry->size.min.h > entry->size.max.h)
1501      {
1502        ERR("parse error %s:%i. Image min and max size are not in the right order ([%i, %i] < [%i, %i])",
1503            file_in, line - 1,
1504            entry->size.min.w, entry->size.min.h,
1505            entry->size.max.w, entry->size.max.h);
1506        exit(-1);
1507      }
1508 }
1509
1510 /**
1511     @page edcref
1512
1513     @block
1514         fonts
1515     @context
1516         fonts {
1517             font: "filename1.ext" "fontname";
1518             font: "filename2.ext" "otherfontname";
1519             ..
1520         }
1521     @description
1522         The "fonts" block is used to list each font file with an alias used later
1523         in the theme. As with the "images" block, additional "fonts" blocks can
1524         be included inside other blocks.
1525     @endblock
1526
1527     @property
1528         font
1529     @parameters
1530         [font filename] [font alias]
1531     @effect
1532         Defines each font "file" and "alias", the full path to the directory
1533         holding the font files can be defined with edje_cc's "-fd" option.
1534     @endproperty
1535  */
1536 static void
1537 st_fonts_font(void)
1538 {
1539    Font *fn;
1540
1541    check_arg_count(2);
1542
1543    if (!edje_file->fonts)
1544      edje_file->fonts = eina_hash_string_small_new(free);
1545
1546    fn = mem_alloc(SZ(Font));
1547    fn->file = parse_str(0);
1548    fn->name = parse_str(1);
1549
1550    if (eina_hash_find(edje_file->fonts, fn->name))
1551      {
1552         free(fn->file);
1553         free(fn->name);
1554         free(fn);
1555         return;
1556      }
1557
1558    eina_hash_direct_add(edje_file->fonts, fn->name, fn);
1559 }
1560
1561 /**
1562     @page edcref
1563     @block
1564         data
1565     @context
1566         data {
1567             item: "key" "value";
1568             file: "otherkey" "filename.ext";
1569             ..
1570         }
1571     @description
1572         The "data" block is used to pass arbitrary parameters from the theme to
1573         the application. Unlike the "images" and "fonts" blocks, additional
1574         "data" blocks can only be included inside the "group" block.
1575     @endblock
1576
1577     @property
1578         item
1579     @parameters
1580         [parameter name] [parameter value]
1581     @effect
1582         Defines a new parameter, the value will be the string specified next to
1583         it.
1584     @endproperty
1585  */
1586 static void
1587 st_data_item(void)
1588 {
1589    Edje_String *es;
1590    char *key;
1591
1592    check_arg_count(2);
1593
1594    key = parse_str(0);
1595
1596    es = mem_alloc(SZ(Edje_String));
1597    es->str = parse_str(1);
1598
1599    if (!edje_file->data)
1600      edje_file->data = eina_hash_string_small_new(free);
1601
1602    /* FIXME: check if data already exist */
1603    eina_hash_direct_add(edje_file->data, key, es);
1604 }
1605
1606 /**
1607     @page edcref
1608     @property
1609         file
1610     @parameters
1611         [parameter name] [parameter filename]
1612     @effect
1613         Defines a new parameter, the value will be the contents of the
1614         specified file formated as a single string of text. This property only
1615         works with plain text files.
1616     @endproperty
1617  */
1618 static void
1619 st_data_file(void)
1620 {
1621    const char *data;
1622    const char *over;
1623    Edje_String *es;
1624    char *filename;
1625    char *value;
1626    char *key;
1627    int fd;
1628    int i;
1629    struct stat buf;
1630
1631    check_arg_count(2);
1632
1633    key = parse_str(0);
1634
1635    es = mem_alloc(SZ(Edje_String));
1636    filename = parse_str(1);
1637
1638    fd = open(filename, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR);
1639    if (fd < 0)
1640      {
1641         ERR("%s:%i when opening file \"%s\": \"%s\"",
1642             file_in, line, filename, strerror(errno));
1643         exit(-1);
1644      }
1645
1646    if (fstat(fd, &buf))
1647      {
1648         ERR("%s:%i when stating file \"%s\": \"%s\"",
1649             file_in, line, filename, strerror(errno));
1650         exit(-1);
1651      }
1652
1653    data = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
1654    if (data == MAP_FAILED)
1655      {
1656         ERR("%s:%i when mapping file \"%s\": \"%s\"",
1657             file_in, line, filename, strerror(errno));
1658         exit(-1);
1659      }
1660
1661    over = data;
1662    for (i = 0; i < buf.st_size; ++i, ++over)
1663      if (*over == '\0')
1664        {
1665           ERR("%s:%i file \"%s\" is a binary file.", file_in, line, filename);
1666           exit(-1);
1667        }
1668
1669    value = malloc(sizeof (char) * buf.st_size + 1);
1670    snprintf(value, buf.st_size + 1, "%s", data);
1671
1672    munmap((void*)data, buf.st_size);
1673    close(fd);
1674
1675    es->str = value;
1676
1677    eina_hash_direct_add(edje_file->data, key, es);
1678
1679    free(filename);
1680 }
1681
1682 /**
1683     @page edcref
1684     @block
1685         color_classes
1686     @context
1687         color_classes {
1688             color_class {
1689                 name:  "colorclassname";
1690                 color:  [0-255] [0-255] [0-255] [0-255];
1691                 color2: [0-255] [0-255] [0-255] [0-255];
1692                 color3: [0-255] [0-255] [0-255] [0-255]
1693             }
1694             ..
1695         }
1696     @description
1697         The "color_classes" block contains a list of one or more "color_class"
1698         blocks. Each "color_class" allows the designer to name an arbitrary
1699         group of colors to be used in the theme, the application can use that
1700         name to alter the color values at runtime.
1701     @endblock
1702 */
1703 static void
1704 ob_color_class(void)
1705 {
1706    Edje_Color_Class *cc;
1707
1708    cc = mem_alloc(SZ(Edje_Color_Class));
1709    edje_file->color_classes = eina_list_append(edje_file->color_classes, cc);
1710
1711    cc->r = 0;
1712    cc->g = 0;
1713    cc->b = 0;
1714    cc->a = 0;
1715    cc->r2 = 0;
1716    cc->g2 = 0;
1717    cc->b2 = 0;
1718    cc->a2 = 0;
1719    cc->r3 = 0;
1720    cc->g3 = 0;
1721    cc->b3 = 0;
1722    cc->a3 = 0;
1723 }
1724
1725 /**
1726     @page edcref
1727
1728     @property
1729         name
1730     @parameters
1731         [color class name]
1732     @effect
1733         Sets the name for the color class, used as reference by both the theme
1734         and the application.
1735     @endproperty
1736 */
1737 static void
1738 st_color_class_name(void)
1739 {
1740    Edje_Color_Class *cc, *tcc;
1741    Eina_List *l;
1742
1743    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
1744    cc->name = parse_str(0);
1745    EINA_LIST_FOREACH(edje_file->color_classes, l, tcc)
1746      {
1747         if ((cc != tcc) && (!strcmp(cc->name, tcc->name)))
1748           {
1749              ERR("parse error %s:%i. There is already a color class named \"%s\"",
1750                  file_in, line - 1, cc->name);
1751              exit(-1);
1752           }
1753      }
1754 }
1755
1756 /**
1757     @page edcref
1758     @property
1759         color
1760     @parameters
1761         [red] [green] [blue] [alpha]
1762     @effect
1763         The main color.
1764     @endproperty
1765 */
1766 static void
1767 st_color_class_color(void)
1768 {
1769    Edje_Color_Class *cc;
1770
1771    check_arg_count(4);
1772
1773    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
1774    cc->r = parse_int_range(0, 0, 255);
1775    cc->g = parse_int_range(1, 0, 255);
1776    cc->b = parse_int_range(2, 0, 255);
1777    cc->a = parse_int_range(3, 0, 255);
1778 }
1779
1780 /**
1781     @page edcref
1782     @property
1783         color2
1784     @parameters
1785         [red] [green] [blue] [alpha]
1786     @effect
1787         Used as shadow in text and textblock parts.
1788     @endproperty
1789 */
1790 static void
1791 st_color_class_color2(void)
1792 {
1793    Edje_Color_Class *cc;
1794
1795    check_arg_count(4);
1796
1797    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
1798    cc->r2 = parse_int_range(0, 0, 255);
1799    cc->g2 = parse_int_range(1, 0, 255);
1800    cc->b2 = parse_int_range(2, 0, 255);
1801    cc->a2 = parse_int_range(3, 0, 255);
1802 }
1803
1804 /**
1805     @page edcref
1806     @property
1807         color3
1808     @parameters
1809         [red] [green] [blue] [alpha]
1810     @effect
1811         Used as outline in text and textblock parts.
1812     @endproperty
1813 */
1814 static void
1815 st_color_class_color3(void)
1816 {
1817    Edje_Color_Class *cc;
1818
1819    check_arg_count(4);
1820
1821    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
1822    cc->r3 = parse_int_range(0, 0, 255);
1823    cc->g3 = parse_int_range(1, 0, 255);
1824    cc->b3 = parse_int_range(2, 0, 255);
1825    cc->a3 = parse_int_range(3, 0, 255);
1826 }
1827
1828 /**
1829     @page edcref
1830     @block
1831         styles
1832     @context
1833         styles {
1834             style {
1835                 name: "stylename";
1836                 base: "..default style properties..";
1837
1838                 tag:  "tagname" "..style properties..";
1839                 ..
1840             }
1841             ..
1842         }
1843     @description
1844         The "styles" block contains a list of one or more "style" blocks. A
1845         "style" block is used to create style \<tags\> for advanced TEXTBLOCK
1846         formatting.
1847     @endblock
1848 */
1849 static void
1850 ob_styles_style(void)
1851 {
1852    Edje_Style *stl;
1853
1854    stl = mem_alloc(SZ(Edje_Style));
1855    edje_file->styles = eina_list_append(edje_file->styles, stl);
1856 }
1857
1858 /**
1859     @page edcref
1860     @property
1861         name
1862     @parameters
1863         [style name]
1864     @effect
1865         The name of  the style to be used as reference later in the theme.
1866     @endproperty
1867 */
1868 static void
1869 st_styles_style_name(void)
1870 {
1871    Edje_Style *stl, *tstl;
1872    Eina_List *l;
1873
1874    stl = eina_list_data_get(eina_list_last(edje_file->styles));
1875    stl->name = parse_str(0);
1876    EINA_LIST_FOREACH(edje_file->styles, l, tstl)
1877      {
1878         if (stl->name && tstl->name && (stl != tstl) && (!strcmp(stl->name, tstl->name)))
1879           {
1880              ERR("parse error %s:%i. There is already a style named \"%s\"",
1881                  file_in, line - 1, stl->name);
1882              exit(-1);
1883           }
1884      }
1885 }
1886
1887 /**
1888     @page edcref
1889     @property
1890         base
1891     @parameters
1892         [style properties string]
1893     @effect
1894         The default style properties that will be applied to the complete
1895         text.
1896     @endproperty
1897 */
1898 static void
1899 st_styles_style_base(void)
1900 {
1901    Edje_Style *stl;
1902    Edje_Style_Tag *tag;
1903
1904    stl = eina_list_data_get(eina_list_last(edje_file->styles));
1905    if (stl->tags)
1906      {
1907         ERR("parse error %s:%i. There is already a basic format for the style",
1908             file_in, line - 1);
1909         exit(-1);
1910      }
1911    tag = mem_alloc(SZ(Edje_Style_Tag));
1912    tag->key = mem_strdup("DEFAULT");
1913    tag->value = parse_str(0);
1914    stl->tags = eina_list_append(stl->tags, tag);
1915 }
1916
1917 /**
1918     @page edcref
1919     @property
1920         tag
1921     @parameters
1922         [tag name] [style properties string]
1923     @effect
1924         Style to be applied only to text between style \<tags\>..\</tags\>.
1925         When creating "paired" tags, like \<bold\>\</bold\>, A '+' should be added at the start of the style properties of the first part (\<bold\>).
1926         If the second part (\</bold\>) is also defined, a '-' should be prepended to it's style properties.
1927         This only applies to paired tags; Single tags, like \<tab\>, must not include a starting '+'.
1928     @endproperty
1929 */
1930 static void
1931 st_styles_style_tag(void)
1932 {
1933    Edje_Style *stl;
1934    Edje_Style_Tag *tag;
1935
1936    stl = eina_list_data_get(eina_list_last(edje_file->styles));
1937    tag = mem_alloc(SZ(Edje_Style_Tag));
1938    tag->key = parse_str(0);
1939    tag->value = parse_str(1);
1940    stl->tags = eina_list_append(stl->tags, tag);
1941 }
1942
1943 /**
1944     @page edcref
1945     @block
1946         collections
1947     @context
1948         collections {
1949             ..
1950             group { }
1951             group { }
1952             sounds { }
1953             ..
1954         }
1955     @description
1956         The "collections" block is used to list the groups that compose the
1957         theme. Additional "collections" blocks do not prevent overriding group
1958         names. The "sounds" block comprises of all sound definitions.
1959     @endblock
1960 */
1961 static void
1962 ob_collections(void)
1963 {
1964    if (!edje_file->collection)
1965      {
1966         edje_file->collection = eina_hash_string_small_new(NULL);
1967         edje_collections_lookup = eina_hash_int32_new(NULL);
1968      }
1969 }
1970 /**
1971     @page edcref
1972     @block
1973         sounds
1974     @context
1975         sounds {
1976            sample {
1977               name: "sound_file1" COMP;
1978               source: "sound_file1.wav";
1979            }
1980            sample {
1981               name: "sound_file2" LOSSY 0.4;
1982               source: "sound_file2.wav";
1983            }
1984            tone: "tone-1"  2300;
1985         }
1986
1987     @description
1988         The "sounds" block contains a list of one or more sound sample and tones items.
1989     @endblock
1990     @block
1991         sample
1992     @context
1993        sample {
1994           name: "sound_file1" RAW;
1995           source: "sound_file1.wav";
1996        }
1997        sample {
1998           name: "sound_file2" LOSSY 0.5;
1999           source: "sound_file2.wav";
2000        }
2001        sample {
2002           name: "sound_file3" COMP;
2003           source: "sound_file3.wav";
2004        }
2005        sample {
2006           name: "sound_file4" AS_IS;
2007           source: "sound_file1.wav";
2008        }
2009     @description
2010         The sample block defines the sound sample.
2011     @endblock
2012     @property
2013         name
2014     @parameters
2015         [sample name] [compression type] [if lossy, then quality]
2016     @effect
2017         Used to include each sound file. The full path to the directory holding
2018         the sounds can be defined later with edje_cc's "-sd" option.
2019         @li RAW: Uncompressed.
2020         @li COMP: Lossless compression.
2021         @li LOSSY [-0.1  - 1.0]: Lossy compression with quality from 0 to 1.0.
2022         @li AS_IS: Check for re-encoding, no compression/encoding, just write the file information as it is.
2023     @endproperty
2024     @since 1.1.0
2025  */
2026 static void
2027 st_collections_group_sound_sample_name(void)
2028 {
2029    Edje_Sound_Sample *sample;
2030    const char *tmp;
2031    unsigned int i;
2032    
2033    if (!edje_file->sound_dir)
2034      edje_file->sound_dir = mem_alloc(SZ(Edje_Sound_Directory));
2035    
2036    tmp = parse_str(0);
2037    
2038    for (i = 0; i < edje_file->sound_dir->samples_count; i++)
2039      {
2040         if (!strcmp(edje_file->sound_dir->samples[i].name, tmp))
2041           {
2042              free((char *)tmp);
2043              return;
2044           }
2045      }
2046    
2047    edje_file->sound_dir->samples_count++;
2048    edje_file->sound_dir->samples = 
2049      realloc(edje_file->sound_dir->samples,
2050              sizeof(Edje_Sound_Sample) * 
2051              edje_file->sound_dir->samples_count);
2052
2053    if (!edje_file->sound_dir->samples)
2054      {
2055         ERR("No enough memory.");
2056         exit(-1);
2057      }
2058    
2059    sample =
2060      edje_file->sound_dir->samples +
2061      edje_file->sound_dir->samples_count - 1;
2062    memset(sample, 0, sizeof (Edje_Sound_Sample));
2063    
2064    sample->name = tmp;
2065    sample->id = edje_file->sound_dir->samples_count - 1;
2066    sample->compression = parse_enum(1,
2067                                     "RAW", EDJE_SOUND_SOURCE_TYPE_INLINE_RAW,
2068                                     "COMP", EDJE_SOUND_SOURCE_TYPE_INLINE_COMP,
2069                                     "LOSSY", EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY,
2070                                     "AS_IS", EDJE_SOUND_SOURCE_TYPE_INLINE_AS_IS,
2071                                     NULL);
2072    
2073    if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY)
2074      {
2075         sample->quality = parse_float_range(2, 45.0, 1000.0);
2076         check_arg_count(3);
2077      }
2078    else
2079      check_arg_count(2);
2080
2081 }
2082
2083 /**
2084     @page edcref
2085     @property
2086         source
2087     @parameters
2088         [sound file name]
2089     @effect
2090         The Sound source file name (Source can be mono/stereo WAV file.
2091         Only files with 44.1 KHz sample rate supported now)
2092     @endproperty
2093     @since 1.1.0
2094  */
2095 static void
2096 st_collections_group_sound_sample_source(void)
2097 {
2098    Edje_Sound_Sample *sample;
2099
2100    if (!edje_file->sound_dir->samples)
2101      {
2102         ERR("Invalid sound sample source definition.");
2103         exit(-1);
2104      }
2105    
2106    sample = 
2107      edje_file->sound_dir->samples +
2108      edje_file->sound_dir->samples_count - 1;
2109    
2110    if (!sample)
2111      {
2112         ERR("Invalid sound sample source definition.");
2113         exit(-1);
2114      }
2115    sample->snd_src = parse_str(0);
2116    check_arg_count(1);
2117 }
2118
2119 /**
2120     @page edcref
2121     @property
2122         tone
2123     @parameters
2124         [tone name] [frequency]
2125     @effect
2126         sound of specific frequency
2127     @endproperty
2128     @since 1.1.0
2129  */
2130 static void
2131 st_collections_group_sound_tone(void)
2132 {
2133    Edje_Sound_Tone *tone;
2134    const char *tmp;
2135    unsigned int i;
2136    int value;
2137
2138    check_arg_count(2);
2139    
2140    if (!edje_file->sound_dir)
2141      edje_file->sound_dir = mem_alloc(SZ(Edje_Sound_Directory));
2142    
2143    tmp = parse_str(0);
2144    /* Audible range 20 to 20KHz */
2145    value = parse_int_range(1, 20, 20000);
2146    
2147    /* Check for Tone duplication */
2148    for (i = 0; i < edje_file->sound_dir->tones_count; i++)
2149      {
2150         if (!strcmp(edje_file->sound_dir->tones[i].name, tmp))
2151           {
2152              ERR("Tone name: %s already exist.", tmp);
2153              free((char *)tmp);
2154              exit(-1);
2155           }
2156         if (edje_file->sound_dir->tones[i].value == value)
2157           {
2158              ERR("Tone name %s with same frequency %d exist.",
2159                  edje_file->sound_dir->tones[i].name, value);
2160              exit(-1);
2161           }
2162      }
2163    edje_file->sound_dir->tones_count++;
2164    edje_file->sound_dir->tones = 
2165      realloc(edje_file->sound_dir->tones,
2166              sizeof (Edje_Sound_Tone) * 
2167              edje_file->sound_dir->tones_count);
2168    
2169    if (!edje_file->sound_dir->tones)
2170      {
2171         ERR("No enough memory.");
2172         exit(-1);
2173      }
2174    
2175    tone = edje_file->sound_dir->tones + edje_file->sound_dir->tones_count - 1;
2176    memset(tone, 0, sizeof (Edje_Sound_Tone));
2177    
2178    tone->name = tmp;
2179    tone->value = value;
2180    tone->id = edje_file->sound_dir->tones_count - 1;
2181 }
2182 /**
2183    @edcsection{group,Group sub blocks}
2184  */
2185
2186 /**
2187     @page edcref
2188     @block
2189         group
2190     @context
2191         collections {
2192             ..
2193             group {
2194                 name: "nameusedbytheapplication";
2195                 alias: "anothername";
2196                 min: width height;
2197                 max: width height;
2198
2199                 data { }
2200                 script { }
2201                 parts { }
2202                 programs { }
2203             }
2204             ..
2205         }
2206     @description
2207         A "group" block contains the list of parts and programs that compose a
2208         given Edje Object.
2209     @endblock
2210 */
2211 static void
2212 ob_collections_group(void)
2213 {
2214    Edje_Part_Collection *pc;
2215    Code *cd;
2216
2217    if (current_de && !current_de->entry)
2218      {
2219         ERR("A collection without a name was detected, that's not allowed.");
2220         exit(-1);
2221      }
2222
2223    current_de = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
2224    current_de->id = eina_list_count(edje_collections);
2225
2226    eina_hash_add(edje_collections_lookup, &current_de->id, current_de);
2227
2228    pc = mem_alloc(SZ(Edje_Part_Collection));
2229    edje_collections = eina_list_append(edje_collections, pc);
2230    pc->id = current_de->id;
2231    pc->broadcast_signal = EINA_TRUE; /* This was the behaviour by default in Edje 1.1 */
2232
2233    cd = mem_alloc(SZ(Code));
2234    codes = eina_list_append(codes, cd);
2235 }
2236
2237 /**
2238     @page edcref
2239     @property
2240         name
2241     @parameters
2242         [group name]
2243     @effect
2244         The name that will be used by the application to load the resulting
2245         Edje object and to identify the group to swallow in a GROUP part. If a
2246         group with the same name exists already it will be completely overriden
2247         by the new group.
2248     @endproperty
2249 */
2250 static void
2251 st_collections_group_name(void)
2252 {
2253    Edje_Part_Collection_Directory_Entry *alias;
2254    Edje_Part_Collection_Directory_Entry *older;
2255    Edje_Part_Collection *current_pc;
2256    Eina_List *l = NULL;
2257
2258    check_arg_count(1);
2259
2260    current_pc = eina_list_data_get(eina_list_last(edje_collections));
2261
2262    current_de->entry = parse_str(0);
2263    current_pc->part = current_de->entry;
2264
2265    older = eina_hash_find(edje_file->collection, current_de->entry);
2266    if (older) eina_hash_del(edje_file->collection, current_de->entry, older);
2267    eina_hash_direct_add(edje_file->collection, current_de->entry, current_de);
2268    if (!older) return;
2269
2270    EINA_LIST_FOREACH(aliases, l, alias)
2271      if (strcmp(alias->entry, current_de->entry) == 0)
2272        {
2273           Edje_Part_Collection *pc;
2274
2275           pc = eina_list_nth(edje_collections, older->id);
2276           INF("overriding alias ('%s' => '%s') by group '%s'",
2277               alias->entry, pc->part,
2278               current_de->entry);
2279           aliases = eina_list_remove_list(aliases, l);
2280           free(alias);
2281           break;
2282        }
2283
2284 }
2285
2286 typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data;
2287 struct _Edje_List_Foreach_Data
2288 {
2289    Eina_List *list;
2290 };
2291
2292 static Eina_Bool
2293 _edje_data_item_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
2294 {
2295    Edje_List_Foreach_Data *fd;
2296
2297    fd = fdata;
2298    fd->list = eina_list_append(fd->list, strdup(key));
2299
2300    return EINA_TRUE;
2301 }
2302
2303 /**
2304     @page edcref
2305     @property
2306         inherit
2307     @parameters
2308         [parent group name]
2309     @effect
2310         Parent group name for inheritance.
2311         Group "inherit" is used to inherit any predefined group and change
2312         some property which belongs to "part", "description", "items" or "program".
2313         The child group has the same property as parent group. If you specify the
2314         type again in an inherited part, it will cause an error (unless you plan
2315         to fix that).
2316     @endproperty
2317     @since 1.1.0
2318 */
2319 static void
2320 st_collections_group_inherit(void)
2321 {
2322    Edje_Part_Collection *pc, *pc2;
2323    Edje_Part *ep, *ep2;
2324    Edje_Part_Parser *epp, *epp2;
2325    Edje_Pack_Element *item, *item2;
2326    Edje_Pack_Element_Parser *pitem;
2327    Edje_Part_Description_Common *ed, *ed2;
2328    Edje_List_Foreach_Data fdata;
2329    Eina_List *l;
2330    char *parent_name;
2331    unsigned int i, j;
2332
2333    check_arg_count(1);
2334
2335    pc = eina_list_data_get(eina_list_last(edje_collections));
2336
2337    parent_name = parse_str(0);
2338
2339    EINA_LIST_FOREACH(edje_collections, l, pc2)
2340      {
2341         if (!strcmp(parent_name, pc2->part))
2342           break;
2343      }
2344    if (!pc2)
2345      {
2346         ERR("parse error %s:%i. There isn't a group with the name %s",
2347             file_in, line - 1, parent_name);
2348         exit(-1);
2349      }
2350    if (pc2 == pc)
2351      {
2352         ERR("parse error %s:%i. You are trying to inherit '%s' from itself. That's not possible."
2353             "If there is another group of the same name, you want to inherit from that group and have the"
2354             "same name as that group, there is a trick ! Just put the inherit before the directive that set"
2355             "the name !", file_in, line - 1, parent_name);
2356         exit(-1);
2357      }
2358
2359    if (pc2->data)
2360      {
2361         char *key, *data;
2362
2363         memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
2364         eina_hash_foreach(pc2->data,
2365                      _edje_data_item_list_foreach, &fdata);
2366
2367         if (!pc->data) pc->data = eina_hash_string_small_new(free);
2368         EINA_LIST_FREE(fdata.list, key)
2369           {
2370              data = eina_hash_find(pc2->data, key);
2371              eina_hash_direct_add(pc->data, key, data);
2372           }
2373      }
2374
2375    if (pc2->alias)
2376      {
2377         char *key, *alias;
2378
2379         memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
2380         eina_hash_foreach(pc2->alias,
2381                      _edje_data_item_list_foreach, &fdata);
2382         if (!pc->alias) pc->alias = eina_hash_string_small_new(free);
2383         EINA_LIST_FREE(fdata.list, key)
2384           {
2385              alias = eina_hash_find(pc2->alias, key);
2386              eina_hash_direct_add(pc->alias, key, alias);
2387           }
2388      }
2389    if (pc2->aliased)
2390      {
2391         char *key, *aliased;
2392
2393         memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
2394         eina_hash_foreach(pc2->aliased,
2395                           _edje_data_item_list_foreach, &fdata);
2396         if (!pc->aliased) pc->aliased = eina_hash_string_small_new(free);
2397         EINA_LIST_FREE(fdata.list, key)
2398           {
2399              aliased = eina_hash_find(pc2->aliased, key);
2400              eina_hash_direct_add(pc->aliased, key, aliased);
2401           }
2402      }
2403
2404    pc->prop.min.w = pc2->prop.min.w;
2405    pc->prop.min.h = pc2->prop.min.h;
2406    pc->prop.orientation = pc2->prop.orientation;
2407
2408    pc->lua_script_only = pc2->lua_script_only;
2409
2410    #define STRDUP(x) x ? strdup(x) : NULL
2411    for (i = 0 ; i < pc2->parts_count ; i++)
2412      {
2413         // copy the part
2414         edje_cc_handlers_part_make();
2415         ep = pc->parts[i];
2416         ep2 = pc2->parts[i];
2417         ep->name = STRDUP(ep2->name);
2418         ep->source = STRDUP(ep2->source);
2419         ep->source2 = STRDUP(ep2->source2);
2420         ep->source3 = STRDUP(ep2->source3);
2421         ep->source4 = STRDUP(ep2->source4);
2422         ep->source5 = STRDUP(ep2->source5);
2423         ep->source6 = STRDUP(ep2->source6);
2424
2425         data_queue_copied_part_lookup(pc, &(ep2->clip_to_id), &(ep->clip_to_id));
2426
2427         ep->type = ep2->type;
2428         ep->mouse_events = ep2->mouse_events;
2429         ep->repeat_events = ep2->repeat_events;
2430         ep->ignore_flags = ep2->ignore_flags;
2431         ep->scale = ep2->scale;
2432         ep->pointer_mode = ep2->pointer_mode;
2433         ep->precise_is_inside = ep2->precise_is_inside;
2434         ep->use_alternate_font_metrics = ep2->use_alternate_font_metrics;
2435         ep->effect = ep2->effect;
2436         ep->entry_mode = ep2->entry_mode;
2437         ep->select_mode = ep2->select_mode;
2438         ep->cursor_mode = ep2->cursor_mode;
2439         ep->multiline = ep2->multiline;
2440         ep->access = ep2->access;
2441         ep->dragable.x = ep2->dragable.x;
2442         ep->dragable.step_x = ep2->dragable.step_x;
2443         ep->dragable.count_x = ep2->dragable.count_x;
2444         ep->dragable.y = ep2->dragable.y;
2445         ep->dragable.step_y = ep2->dragable.step_y;
2446         ep->dragable.count_y = ep2->dragable.count_y;
2447         ep->nested_children_count = ep2->nested_children_count;
2448
2449         data_queue_copied_part_lookup(pc, &(ep2->dragable.confine_id), &(ep->dragable.confine_id));
2450         data_queue_copied_part_lookup(pc, &(ep2->dragable.event_id), &(ep->dragable.event_id));
2451
2452         epp = (Edje_Part_Parser *)ep;
2453         epp2 = (Edje_Part_Parser *)ep2;
2454         epp->reorder.insert_before = STRDUP(epp2->reorder.insert_before);
2455         epp->reorder.insert_after = STRDUP(epp2->reorder.insert_after);
2456         epp->can_override = EINA_TRUE;
2457
2458         for (j = 0 ; j < ep2->items_count ; j++)
2459           {
2460              ob_collections_group_parts_part_box_items_item();
2461              item = ep->items[j];
2462              item2 = ep2->items[j];
2463              item->type = item2->type;
2464              item->name = STRDUP(item2->name);
2465              item->source = STRDUP(item2->source);
2466              item->min.w = item2->min.w;
2467              item->min.h = item2->min.h;
2468              item->prefer.w = item2->prefer.w;
2469              item->prefer.h = item2->prefer.h;
2470              item->max.w = item2->max.w;
2471              item->max.h = item2->max.h;
2472              item->padding.l = item2->padding.l;
2473              item->padding.r = item2->padding.r;
2474              item->padding.t = item2->padding.t;
2475              item->padding.b = item2->padding.b;
2476              item->align.x = item2->align.x;
2477              item->align.y = item2->align.y;
2478              item->weight.x = item2->weight.x;
2479              item->weight.y = item2->weight.y;
2480              item->aspect.w = item2->aspect.w;
2481              item->aspect.h = item2->aspect.h;
2482              item->aspect.mode = item2->aspect.mode;
2483              item->options = STRDUP(item2->options);
2484              item->col = item2->col;
2485              item->row = item2->row;
2486              item->colspan = item2->colspan;
2487              item->rowspan = item2->rowspan;
2488
2489              pitem = (Edje_Pack_Element_Parser *)item;
2490              pitem->can_override = EINA_TRUE;
2491           }
2492
2493         ep->api.name = STRDUP(ep2->api.name);
2494         if (ep2->api.description) ep->api.description = STRDUP(ep2->api.description);
2495
2496         // copy default description
2497         ob_collections_group_parts_part_description();
2498         ed = ep->default_desc;
2499         parent_desc = ed2 = ep2->default_desc;
2500         ed->state.name = STRDUP(ed2->state.name);
2501         ed->state.value = ed2->state.value;
2502         st_collections_group_parts_part_description_inherit();
2503         parent_desc = NULL;
2504
2505         // copy other description
2506         for (j = 0 ; j < ep2->other.desc_count ; j++)
2507           {
2508              ob_collections_group_parts_part_description();
2509              ed = ep->other.desc[j];
2510              parent_desc = ed2 = ep2->other.desc[j];
2511              ed->state.name = STRDUP(ed2->state.name);
2512              ed->state.value = ed2->state.value;
2513              st_collections_group_parts_part_description_inherit();
2514              parent_desc = NULL;
2515           }
2516      }
2517
2518    //copy programs
2519    for (j = 0 ; j < pc2->programs.fnmatch_count ; j++)
2520      {
2521         ob_collections_group_programs_program();
2522         _edje_program_copy(current_program, pc2->programs.fnmatch[j]);
2523      }
2524    for (j = 0 ; j < pc2->programs.strcmp_count ; j++)
2525      {
2526         ob_collections_group_programs_program();
2527         _edje_program_copy(current_program, pc2->programs.strcmp[j]);
2528      }
2529    for (j = 0 ; j < pc2->programs.strncmp_count ; j++)
2530      {
2531         ob_collections_group_programs_program();
2532         _edje_program_copy(current_program, pc2->programs.strncmp[j]);
2533      }
2534    for (j = 0 ; j < pc2->programs.strrncmp_count ; j++)
2535      {
2536         ob_collections_group_programs_program();
2537         _edje_program_copy(current_program, pc2->programs.strrncmp[j]);
2538      }
2539    for (j = 0 ; j < pc2->programs.nocmp_count ; j++)
2540      {
2541         ob_collections_group_programs_program();
2542         _edje_program_copy(current_program, pc2->programs.nocmp[j]);
2543      }
2544
2545    Code *cd, *cd2;
2546    Code_Program *cp, *cp2;
2547    Edje_Part_Collection_Directory_Entry *de;
2548
2549    de = eina_hash_find(edje_file->collection, pc2->part);
2550    cd2 = eina_list_nth(codes, de->id);
2551    cd = eina_list_data_get(eina_list_last(codes));
2552
2553    EINA_LIST_FOREACH(cd2->programs, l, cp2)
2554      {
2555         cp = mem_alloc(SZ(Code_Program));
2556
2557         cp->l1 = cp2->l1;
2558         cp->l2 = cp2->l2;
2559         cp->script = STRDUP(cp2->script);
2560         cd->is_lua = cd2->is_lua;
2561         cd->shared = cd2->shared;
2562         cd->programs = eina_list_append(cd->programs, cp);
2563         data_queue_copied_anonymous_lookup(pc, &(cp2->id), &(cp->id));
2564      }
2565
2566    free(parent_name);
2567    #undef STRDUP
2568 }
2569
2570 /**
2571     @page edcref
2572     @property
2573         script_only
2574     @parameters
2575         [on/off]
2576     @effect
2577         The flag (on/off) as to if this group is defined ONLY by script
2578         callbacks such as init(), resize() and shutdown()
2579     @endproperty
2580 */
2581 static void
2582 st_collections_group_script_only(void)
2583 {
2584    Edje_Part_Collection *pc;
2585
2586    check_arg_count(1);
2587
2588    pc = eina_list_data_get(eina_list_last(edje_collections));
2589    pc->lua_script_only = parse_bool(0);
2590 }
2591
2592 /**
2593     @page edcref
2594     @property
2595         alias
2596     @parameters
2597         [aditional group name]
2598     @effect
2599         Additional name to serve as identifier. Defining multiple aliases is
2600         supported.
2601     @endproperty
2602 */
2603 static void
2604 st_collections_group_alias(void)
2605 {
2606    Edje_Part_Collection_Directory_Entry *alias;
2607    Edje_Part_Collection_Directory_Entry *tmp;
2608    Eina_List *l;
2609
2610    check_arg_count(1);
2611
2612    alias = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
2613    alias->id = current_de->id;
2614    alias->entry = parse_str(0);
2615
2616    EINA_LIST_FOREACH(aliases, l, tmp)
2617      if (strcmp(alias->entry, tmp->entry) == 0)
2618        {
2619           Edje_Part_Collection *pc;
2620
2621           pc = eina_list_nth(edje_collections, tmp->id);
2622           INF("overriding alias ('%s' => '%s') to ('%s' => '%s')",
2623               tmp->entry, pc->part,
2624               alias->entry, current_de->entry);
2625           aliases = eina_list_remove_list(aliases, l);
2626           free(tmp);
2627           break;
2628        }
2629
2630    aliases = eina_list_append(aliases, alias);
2631 }
2632
2633 /**
2634     @page edcref
2635     @property
2636         min
2637     @parameters
2638         [width] [height]
2639     @effect
2640         The minimum size for the container defined by the composition of the
2641         parts. It is not enforced.
2642     @endproperty
2643 */
2644 static void
2645 st_collections_group_min(void)
2646 {
2647    Edje_Part_Collection *pc;
2648
2649    check_arg_count(2);
2650
2651    pc = eina_list_data_get(eina_list_last(edje_collections));
2652    pc->prop.min.w = parse_int_range(0, 0, 0x7fffffff);
2653    pc->prop.min.h = parse_int_range(1, 0, 0x7fffffff);
2654 }
2655
2656 /**
2657     @page edcref
2658     @property
2659         max
2660     @parameters
2661         [width] [height]
2662     @effect
2663         The maximum size for the container defined by the totality of the
2664         parts. It is not enforced.
2665     @endproperty
2666 */
2667 static void
2668 st_collections_group_max(void)
2669 {
2670    Edje_Part_Collection *pc;
2671
2672    check_arg_count(2);
2673
2674    pc = eina_list_data_get(eina_list_last(edje_collections));
2675    pc->prop.max.w = parse_int_range(0, 0, 0x7fffffff);
2676    pc->prop.max.h = parse_int_range(1, 0, 0x7fffffff);
2677 }
2678
2679 /**
2680    @page edcref
2681    @property
2682        broadcast_signal
2683    @parameters
2684        [broadcast]
2685    @effect
2686        Signal got automatically broadcasted to all sub group part. Default to
2687        true since 1.1.
2688    @endproperty
2689 */
2690 static void
2691 st_collections_group_broadcast_signal(void)
2692 {
2693    Edje_Part_Collection *pc;
2694
2695    check_arg_count(1);
2696
2697    pc = eina_list_data_get(eina_list_last(edje_collections));
2698    pc->broadcast_signal = parse_bool(0);
2699 }
2700
2701 /**
2702     @page edcref
2703     @block
2704         script
2705     @context
2706         ..
2707         group {
2708             script {
2709                 //embryo script
2710             }
2711             ..
2712             program {
2713                 script {
2714                     //embryo script
2715                 }
2716             }
2717             ..
2718         }
2719         ..
2720     @description
2721         This block is used to "inject" embryo scripts to a given Edje theme and
2722         it functions in two modalities. When it's included inside a "program"
2723         block, the script will be executed every time the program is run, on
2724         the other hand, when included directly into a "group", "part" or
2725         "description" block, it will be executed once at load time, in the
2726         load order.
2727     @endblock
2728 */
2729 static void
2730 ob_collections_group_script(void)
2731 {
2732    Code *cd;
2733
2734    cd = eina_list_data_get(eina_list_last(codes));
2735
2736    if (!is_verbatim()) track_verbatim(1);
2737    else
2738      {
2739         char *s;
2740
2741         s = get_verbatim();
2742         if (s)
2743           {
2744              cd->l1 = get_verbatim_line1();
2745              cd->l2 = get_verbatim_line2();
2746              if (cd->shared)
2747                {
2748                   ERR("parse error %s:%i. There is already an existing script section for the group",
2749                       file_in, line - 1);
2750                   exit(-1);
2751                }
2752              cd->shared = s;
2753              cd->original = strdup(s);
2754              cd->is_lua = 0;
2755              set_verbatim(NULL, 0, 0);
2756           }
2757      }
2758 }
2759
2760 static void
2761 ob_collections_group_lua_script(void)
2762 {
2763    Code *cd;
2764
2765    cd = eina_list_data_get(eina_list_last(codes));
2766
2767    if (!is_verbatim()) track_verbatim(1);
2768    else
2769      {
2770         char *s;
2771
2772         s = get_verbatim();
2773         if (s)
2774           {
2775              cd->l1 = get_verbatim_line1();
2776              cd->l2 = get_verbatim_line2();
2777              if (cd->shared)
2778                {
2779                   ERR("parse error %s:%i. There is already an existing script section for the group",
2780                       file_in, line - 1);
2781                   exit(-1);
2782                }
2783              cd->shared = s;
2784              cd->is_lua = 1;
2785              set_verbatim(NULL, 0, 0);
2786           }
2787      }
2788 }
2789
2790 static void
2791 st_collections_group_data_item(void)
2792 {
2793    Edje_Part_Collection *pc;
2794    Edje_String *es;
2795    char *key;
2796
2797    check_arg_count(2);
2798
2799    pc = eina_list_data_get(eina_list_last(edje_collections));
2800
2801    if (!pc->data)
2802      pc->data = eina_hash_string_small_new(free);
2803
2804    key = parse_str(0);
2805
2806    es = mem_alloc(SZ(Edje_String));
2807    es->str = parse_str(1);
2808
2809    if (eina_hash_find(pc->data, key))
2810      eina_hash_modify(pc->data, key, es);
2811    else
2812      eina_hash_direct_add(pc->data, key, es);
2813 }
2814
2815 /**
2816     @page edcref
2817     @property
2818         orientation
2819     @parameters
2820     enum AUTO, LTR, RTL
2821     @effect
2822         This defines GROUP orientation.
2823         This is useful if you want match interface orientation with language.
2824         AUTO  - Follow system defs.
2825         LTR  - suitable for Left To Right Languages (latin)
2826         RTL - suitable for Right To Left Languages (Hebrew, Arabic interface)
2827     @endproperty
2828 */
2829 static void
2830 st_collections_group_orientation(void)
2831 {
2832    Edje_Part_Collection *pc;
2833
2834    check_arg_count(1);
2835
2836    pc = eina_list_data_get(eina_list_last(edje_collections));
2837    pc->prop.orientation = parse_enum(0,
2838          "AUTO", EDJE_ORIENTATION_AUTO,
2839          "LTR", EDJE_ORIENTATION_LTR,
2840          "RTL", EDJE_ORIENTATION_RTL,
2841          NULL);
2842 }
2843
2844 /**
2845     @page edcref
2846     @block
2847         limits
2848     @context
2849         group {
2850             limits {
2851                 vertical: "limit_name" height_barrier;
2852                 horizontal: "limit_name" width_barrier;
2853                 ..
2854             }
2855             ..
2856         }
2857         ..
2858     @description
2859         This block is used to trigger some signal when the Edje object is resized.
2860     @endblock
2861
2862     @page edcref
2863     @property
2864         vertical
2865     @parameters
2866         [name] [height barrier]
2867     @effect
2868         It will send a signal: "limit,name,over" when the object is resized and pass
2869         the limit by growing over it. And it will send: "limit,name,below" when
2870         it pass below that limit.
2871         This limit will be applied on the y absis and is expressed in pixels.
2872     @endproperty
2873 */
2874 static void
2875 st_collections_group_limits_vertical(void)
2876 {
2877    Edje_Part_Collection *pc;
2878    Edje_Limit *el;
2879
2880    check_arg_count(2);
2881
2882    el = mem_alloc(SZ(Edje_Limit));
2883
2884    pc = eina_list_data_get(eina_list_last(edje_collections));
2885    pc->limits.vertical_count++;
2886    pc->limits.vertical = realloc(pc->limits.vertical, pc->limits.vertical_count * sizeof (Edje_Limit *));
2887    if (!pc->limits.vertical || !el)
2888      {
2889         ERR("Not enough memory.");
2890         exit(-1);
2891      }
2892
2893    pc->limits.vertical[pc->limits.vertical_count - 1] = el;
2894
2895    el->name = parse_str(0);
2896    el->value = parse_int_range(1, 1, 0xffff);
2897 }
2898
2899 /**
2900     @page edcref
2901     @property
2902         horizontal
2903     @parameters
2904         [name] [width barrier]
2905     @effect
2906         It will send a signal: "limit,name,over" when the object is resized and pass
2907         the limit by growing over it. And it will send: "limit,name,below" when
2908         it pass below that limit.
2909         This limit will be applied on the x absis and is expressed in pixels.
2910     @endproperty
2911 */
2912 static void
2913 st_collections_group_limits_horizontal(void)
2914 {
2915    Edje_Part_Collection *pc;
2916    Edje_Limit *el;
2917
2918    check_arg_count(2);
2919
2920    el = mem_alloc(SZ(Edje_Limit));
2921
2922    pc = eina_list_data_get(eina_list_last(edje_collections));
2923    pc->limits.horizontal_count++;
2924    pc->limits.horizontal = realloc(pc->limits.horizontal, pc->limits.horizontal_count * sizeof (Edje_Limit *));
2925    if (!pc->limits.horizontal || !el)
2926      {
2927         ERR("Not enough memory.");
2928         exit(-1);
2929      }
2930
2931    pc->limits.horizontal[pc->limits.horizontal_count - 1] = el;
2932
2933    el->name = parse_str(0);
2934    el->value = parse_int_range(1, 1, 0xffff);
2935 }
2936
2937 /**
2938     @page edcref
2939     @block
2940         parts
2941     @context
2942         group {
2943             parts {
2944                 alias: "theme_part_path" "real_part_path";
2945                 ..
2946             }
2947         }
2948     @description
2949         Alias of part give a chance to let the designer put the real one
2950         in a box or reuse one from a GROUP or inside a BOX.
2951     @endblock
2952 */
2953 static void
2954 st_collections_group_parts_alias(void)
2955 {
2956    Edje_Part_Collection *pc;
2957    const char *alias;
2958    const char *aliased;
2959
2960    check_arg_count(2);
2961
2962    pc = eina_list_data_get(eina_list_last(edje_collections));
2963
2964    alias = parse_str(0);
2965    aliased = parse_str(1);
2966
2967    if (!pc->alias) pc->alias = eina_hash_string_small_new(NULL);
2968    eina_hash_add(pc->alias, alias, aliased);
2969
2970    if (!pc->aliased) pc->aliased = eina_hash_string_small_new(NULL);
2971    eina_hash_add(pc->aliased, aliased, alias);
2972 }
2973
2974
2975 /**
2976     @page edcref
2977     @block
2978         part
2979     @context
2980         group {
2981             parts {
2982                 ..
2983                 part {
2984                     name: "partname";
2985                     type: IMAGE;
2986                     mouse_events:  1;
2987                     repeat_events: 0;
2988                     ignore_flags: NONE;
2989                     clip_to: "anotherpart";
2990                     source:  "groupname";
2991                     pointer_mode: AUTOGRAB;
2992                     use_alternate_font_metrics: 0;
2993
2994                     description { }
2995                     dragable { }
2996                     items { }
2997                 }
2998                 ..
2999             }
3000         }
3001     @description
3002         Parts are used to represent the most basic design elements of the
3003         theme, for example, a part can represent a line in a border or a label
3004         on a button.
3005     @endblock
3006 */
3007 static Edje_Part *
3008 edje_cc_handlers_part_make(void)
3009 {  /* Doing ob_collections_group_parts_part() job, without hierarchy */
3010    Edje_Part_Collection *pc;
3011    Edje_Part *ep;
3012    Edje_Part_Parser *epp;
3013
3014    ep = mem_alloc(SZ(Edje_Part_Parser));
3015
3016    pc = eina_list_data_get(eina_list_last(edje_collections));
3017    pc->parts_count++;
3018    pc->parts = realloc(pc->parts, pc->parts_count * sizeof (Edje_Part *));
3019    if (!pc->parts)
3020      {
3021         ERR("Not enough memory.");
3022         exit(-1);
3023      }
3024    current_part = pc->parts[pc->parts_count - 1] = ep;
3025
3026    ep->id = pc->parts_count - 1;
3027    ep->type = EDJE_PART_TYPE_IMAGE;
3028    ep->mouse_events = 1;
3029    ep->repeat_events = 0;
3030    ep->ignore_flags = EVAS_EVENT_FLAG_NONE;
3031    ep->scale = 0;
3032    ep->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
3033    ep->precise_is_inside = 0;
3034    ep->use_alternate_font_metrics = 0;
3035    ep->access = 0;
3036    ep->clip_to_id = -1;
3037    ep->dragable.confine_id = -1;
3038    ep->dragable.event_id = -1;
3039    ep->items = NULL;
3040    ep->nested_children_count = 0;
3041
3042    epp = (Edje_Part_Parser *)ep;
3043    epp->reorder.insert_before = NULL;
3044    epp->reorder.insert_after = NULL;
3045    epp->reorder.before = NULL;
3046    epp->reorder.after = NULL;
3047    epp->reorder.linked_prev = 0;
3048    epp->reorder.linked_next = 0;
3049    epp->reorder.done = EINA_FALSE;
3050    epp->can_override = EINA_FALSE;
3051
3052    return ep;
3053 }
3054
3055 static void
3056 ob_collections_group_parts_part(void)
3057 {
3058    Edje_Part *cp = current_part;  /* Save to restore on pop    */
3059    Edje_Part *ep = edje_cc_handlers_part_make(); /* This changes current_part */
3060    Edje_Part *prnt;
3061
3062    /* Add this new part to hierarchy stack (removed part finished parse) */
3063    edje_cc_handlers_hierarchy_push(ep, cp);
3064
3065    prnt = edje_cc_handlers_hierarchy_parent_get();
3066    if (prnt)  /* This is the child of parent in stack */
3067      prnt->nested_children_count++;
3068 }
3069
3070 /**
3071     @page edcref
3072     @property
3073         name
3074     @parameters
3075         [part name]
3076     @effect
3077         The part's name will be used as reference in the theme's relative
3078         positioning system, by programs and in some cases by the application.
3079         It must be unique within the group.
3080     @endproperty
3081 */
3082 static void
3083 st_collections_group_parts_part_name(void)
3084 {
3085    Edje_Part_Collection *pc;
3086    Edje_Part *ep;
3087    Edje_Part_Parser *epp;
3088
3089    check_arg_count(1);
3090
3091    pc = eina_list_data_get(eina_list_last(edje_collections));
3092    ep = current_part;
3093    ep->name = parse_str(0);
3094
3095    if (ep->name)
3096      {
3097         unsigned int i;
3098
3099         for (i = 0; i < (pc->parts_count - 1); i++)
3100           {  /* Compare name only if did NOT updated ep from hircy pop */
3101              if ((ep != pc->parts[i]) &&
3102                    (pc->parts[i]->name &&
3103                     (!strcmp(pc->parts[i]->name, ep->name))))
3104                {
3105                   epp = (Edje_Part_Parser *)pc->parts[i];
3106                   if (!epp->can_override)
3107                     {
3108                        ERR("parse error %s:%i. There is already a part of the name %s",
3109                            file_in, line - 1, ep->name);
3110                        exit(-1);
3111                     }
3112                   else
3113                     {
3114                        free(ep);
3115                        pc->parts_count--;
3116                        pc->parts = realloc(pc->parts, pc->parts_count * sizeof (Edje_Part *));
3117                        current_part = pc->parts[i];
3118                        edje_cc_handlers_hierarchy_rename(ep, current_part);
3119                        ep = current_part;
3120                        epp->can_override = EINA_FALSE;
3121                        break;
3122                     }
3123                }
3124           }
3125      }
3126 }
3127
3128 /**
3129     @page edcref
3130     @property
3131         type
3132     @parameters
3133         [TYPE]
3134     @effect
3135         Set the type (all caps) from among the available types, it's set to
3136         IMAGE by default. Valid types:
3137             @li RECT
3138             @li TEXT
3139             @li IMAGE
3140             @li SWALLOW
3141             @li TEXTBLOCK
3142             @li GROUP
3143             @li BOX
3144             @li TABLE
3145             @li EXTERNAL
3146             @li PROXY
3147             @li SPACER
3148     @endproperty
3149 */
3150 static void
3151 st_collections_group_parts_part_type(void)
3152 {
3153    unsigned int type;
3154
3155    check_arg_count(1);
3156
3157    type = parse_enum(0,
3158                      "NONE", EDJE_PART_TYPE_NONE,
3159                      "RECT", EDJE_PART_TYPE_RECTANGLE,
3160                      "TEXT", EDJE_PART_TYPE_TEXT,
3161                      "IMAGE", EDJE_PART_TYPE_IMAGE,
3162                      "SWALLOW", EDJE_PART_TYPE_SWALLOW,
3163                      "TEXTBLOCK", EDJE_PART_TYPE_TEXTBLOCK,
3164                      "GROUP", EDJE_PART_TYPE_GROUP,
3165                      "BOX", EDJE_PART_TYPE_BOX,
3166                      "TABLE", EDJE_PART_TYPE_TABLE,
3167                      "EXTERNAL", EDJE_PART_TYPE_EXTERNAL,
3168                      "PROXY", EDJE_PART_TYPE_PROXY,
3169                      "SPACER", EDJE_PART_TYPE_SPACER,
3170                      NULL);
3171
3172    /* handle type change of inherited part */
3173    if (type != current_part->type)
3174      {
3175         Edje_Part_Description_Common *new, *previous;
3176         Edje_Part_Collection *pc;
3177         Edje_Part *ep;
3178         unsigned int i;
3179
3180         /* we don't free old part as we don't remove all reference to them */
3181         part_description_image_cleanup(current_part);
3182
3183         pc = eina_list_data_get(eina_list_last(edje_collections));
3184         ep = current_part;
3185
3186         previous = ep->default_desc;
3187         if (previous)
3188           {
3189              new = _edje_part_description_alloc(type, pc->part, ep->name);
3190              memcpy(new, previous, sizeof (Edje_Part_Description_Common));
3191
3192              ep->default_desc = new;
3193           }
3194
3195         for (i = 0; i < ep->other.desc_count; i++)
3196           {
3197              previous = ep->other.desc[i];
3198              new = _edje_part_description_alloc(type, pc->part, ep->name);
3199              memcpy(new, previous, sizeof (Edje_Part_Description_Common));
3200              ep->other.desc[i] = new;
3201           }
3202      }
3203
3204    current_part->type = type;
3205 }
3206
3207 /**
3208     @page edcref
3209     @property
3210         part
3211     @parameters
3212         [part declaration]
3213     @effect
3214     @code
3215         group {
3216             parts {
3217                 part {
3218                     name: "parent_rect";
3219                     type: RECT;
3220                     description { }
3221                     part {
3222                         name: "nested_rect";
3223                         type: RECT;
3224                         description { }
3225                     }
3226                 }
3227                 ..
3228             }
3229         }
3230     @endcode
3231         Nested parts adds hierarchy to edje.
3232         Nested part inherits it's location relatively to the parent part.
3233         To declare a nested part just start a new part within current part decl.
3234         You must define parent part name before adding nested parts.
3235     @endproperty
3236     @since 1.7.0
3237 */
3238
3239 /**
3240     @page edcref
3241     @property
3242         insert_before
3243     @parameters
3244         [another part's name]
3245     @effect
3246         The part's name which this part is inserted before. One part cannot
3247         have both insert_before and insert_after. One part cannot refer
3248         more than one by insert_before.
3249     @endproperty
3250     @since 1.1.0
3251 */
3252 static void
3253 st_collections_group_parts_part_insert_before(void)
3254 {
3255    Edje_Part_Parser *epp;
3256    check_arg_count(1);
3257
3258    epp = (Edje_Part_Parser *)current_part;
3259    epp->reorder.insert_before = parse_str(0);
3260 }
3261
3262 /**
3263     @page edcref
3264     @property
3265         insert_after
3266     @parameters
3267         [another part's name]
3268     @effect
3269         The part's name which this part is inserted after. One part cannot
3270         have both insert_before and insert_after. One part cannot refer
3271         more than one by insert_after.
3272     @endproperty
3273     @since 1.1.0
3274 */
3275 static void
3276 st_collections_group_parts_part_insert_after(void)
3277 {
3278    Edje_Part_Parser *epp;
3279    check_arg_count(1);
3280
3281    epp = (Edje_Part_Parser *)current_part;
3282    epp->reorder.insert_after = parse_str(0);
3283 }
3284
3285 /**
3286     @page edcref
3287     @property
3288         mouse_events
3289     @parameters
3290         [1 or 0]
3291     @effect
3292         Specifies whether the part will emit signals, although it is named
3293         "mouse_events", disabling it (0) will prevent the part from emitting
3294         any type of signal at all. It's set to 1 by default.
3295     @endproperty
3296 */
3297 static void
3298 st_collections_group_parts_part_mouse_events(void)
3299 {
3300    check_arg_count(1);
3301
3302    current_part->mouse_events = parse_bool(0);
3303 }
3304
3305 /**
3306     @page edcref
3307     @property
3308         repeat_events
3309     @parameters
3310         [1 or 0]
3311     @effect
3312         Specifies whether a part echoes a mouse event to other parts below the
3313         pointer (1), or not (0). It's set to 0 by default.
3314     @endproperty
3315 */
3316 static void
3317 st_collections_group_parts_part_repeat_events(void)
3318 {
3319    check_arg_count(1);
3320
3321    current_part->repeat_events = parse_bool(0);
3322 }
3323
3324 /**
3325     @page edcref
3326     @property
3327         ignore_flags
3328     @parameters
3329         [FLAG] ...
3330     @effect
3331         Specifies whether events with the given flags should be ignored,
3332         i.e., will not have the signals emitted to the parts. Multiple flags
3333         must be separated by spaces, the effect will be ignoring all events
3334         with one of the flags specified. Possible flags:
3335             @li NONE (default value, no event will be ignored)
3336             @li ON_HOLD
3337     @endproperty
3338 */
3339 static void
3340 st_collections_group_parts_part_ignore_flags(void)
3341 {
3342    check_min_arg_count(1);
3343
3344    current_part->ignore_flags = parse_flags(0,
3345                                   "NONE", EVAS_EVENT_FLAG_NONE,
3346                                   "ON_HOLD", EVAS_EVENT_FLAG_ON_HOLD,
3347                                   NULL);
3348 }
3349
3350 /**
3351     @page edcref
3352     @property
3353         scale
3354     @parameters
3355         [1 or 0]
3356     @effect
3357         Specifies whether the part will scale its size with an edje scaling
3358         factor. By default scale is off (0) and the default scale factor is
3359         1.0 - that means no scaling. This would be used to scale properties
3360         such as font size, min/max size of the part, and possibly can be used
3361         to scale based on DPI of the target device. The reason to be selective
3362         is that some things work well being scaled, others do not, so the
3363         designer gets to choose what works best.
3364     @endproperty
3365 */
3366 static void
3367 st_collections_group_parts_part_scale(void)
3368 {
3369    check_arg_count(1);
3370
3371    current_part->scale = parse_bool(0);
3372 }
3373
3374 /**
3375     @page edcref
3376     @property
3377         pointer_mode
3378     @parameters
3379         [MODE]
3380     @effect
3381         Sets the mouse pointer behavior for a given part. The default value is
3382         AUTOGRAB. Aviable modes:
3383             @li AUTOGRAB, when the part is clicked and the button remains
3384                 pressed, the part will be the source of all future mouse
3385                 signals emitted, even outside the object, until the button is
3386                 released.
3387             @li NOGRAB, the effect will be limited to the part's container.
3388     @endproperty
3389 */
3390 static void
3391 st_collections_group_parts_part_pointer_mode(void)
3392 {
3393    check_arg_count(1);
3394
3395    current_part->pointer_mode = parse_enum(0,
3396                                  "AUTOGRAB", EVAS_OBJECT_POINTER_MODE_AUTOGRAB,
3397                                  "NOGRAB", EVAS_OBJECT_POINTER_MODE_NOGRAB,
3398                                  NULL);
3399 }
3400
3401 /**
3402     @page edcref
3403     @property
3404         precise_is_inside
3405     @parameters
3406         [1 or 0]
3407     @effect
3408         Enables precise point collision detection for the part, which is more
3409         resource intensive. Disabled by default.
3410     @endproperty
3411 */
3412 static void
3413 st_collections_group_parts_part_precise_is_inside(void)
3414 {
3415    check_arg_count(1);
3416
3417    current_part->precise_is_inside = parse_bool(0);
3418 }
3419
3420 /**
3421     @page edcref
3422     @property
3423         use_alternate_font_metrics
3424     @parameters
3425         [1 or 0]
3426     @effect
3427         Only affects text and textblock parts, when enabled Edje will use
3428         different size measurement functions. Disabled by default. (note from
3429         the author: I don't know what this is exactly useful for?)
3430     @endproperty
3431 */
3432 static void
3433 st_collections_group_parts_part_use_alternate_font_metrics(void)
3434 {
3435    check_arg_count(1);
3436
3437    current_part->use_alternate_font_metrics = parse_bool(0);
3438 }
3439
3440 /**
3441     @page edcref
3442     @property
3443         clip_to
3444     @parameters
3445         [another part's name]
3446     @effect
3447         Only renders the area of part that coincides with another part's
3448         container. Overflowing content will not be displayed. Note that
3449         the part being clipped to can only be a rectangle part.
3450     @endproperty
3451 */
3452 static void
3453 st_collections_group_parts_part_clip_to_id(void)
3454 {
3455    Edje_Part_Collection *pc;
3456
3457    check_arg_count(1);
3458
3459    pc = eina_list_data_get(eina_list_last(edje_collections));
3460      {
3461         char *name;
3462
3463         name = parse_str(0);
3464         data_queue_part_lookup(pc, name, &(current_part->clip_to_id));
3465         free(name);
3466      }
3467 }
3468
3469 /**
3470     @page edcref
3471     @property
3472         source
3473     @parameters
3474         [another group's name]
3475     @effect
3476         Only available to GROUP or TEXTBLOCK parts. Swallows the specified 
3477         group into the part's container if a GROUP. If TEXTBLOCK it is used
3478         for the group to be loaded and used for selection display UNDER the
3479         selected text. source2 is used for on top of the selected text, if
3480         source2 is specified.
3481     @endproperty
3482 */
3483 static void
3484 st_collections_group_parts_part_source(void)
3485 {
3486    check_arg_count(1);
3487
3488    //FIXME: validate this somehow (need to decide on the format also)
3489    current_part->source = parse_str(0);
3490    data_queue_group_lookup(current_part->source, current_part);
3491 }
3492
3493 /**
3494     @page edcref
3495     @property
3496         source2
3497     @parameters
3498         [another group's name]
3499     @effect
3500         Only available to TEXTBLOCK parts. It is used for the group to be 
3501         loaded and used for selection display OVER the selected text. source
3502         is used for under of the selected text, if source is specified.
3503     @endproperty
3504 */
3505 static void
3506 st_collections_group_parts_part_source2(void)
3507 {
3508    check_arg_count(1);
3509
3510    //FIXME: validate this somehow (need to decide on the format also)
3511    current_part->source2 = parse_str(0);
3512    data_queue_group_lookup(current_part->source2, current_part);
3513 }
3514
3515 /**
3516     @page edcref
3517     @property
3518         source3
3519     @parameters
3520         [another group's name]
3521     @effect
3522         Only available to TEXTBLOCK parts. It is used for the group to be 
3523         loaded and used for cursor display UNDER the cursor position. source4
3524         is used for over the cursor text, if source4 is specified.
3525     @endproperty
3526 */
3527 static void
3528 st_collections_group_parts_part_source3(void)
3529 {
3530    check_arg_count(1);
3531
3532    //FIXME: validate this somehow (need to decide on the format also)
3533    current_part->source3 = parse_str(0);
3534    data_queue_group_lookup(current_part->source3, current_part);
3535 }
3536
3537 /**
3538     @page edcref
3539     @property
3540         source4
3541     @parameters
3542         [another group's name]
3543     @effect
3544         Only available to TEXTBLOCK parts. It is used for the group to be 
3545         loaded and used for cursor display OVER the cursor position. source3
3546         is used for under the cursor text, if source4 is specified.
3547     @endproperty
3548 */
3549 static void
3550 st_collections_group_parts_part_source4(void)
3551 {
3552    check_arg_count(1);
3553
3554    //FIXME: validate this somehow (need to decide on the format also)
3555    current_part->source4 = parse_str(0);
3556    data_queue_group_lookup(current_part->source4, current_part);
3557 }
3558
3559 /**
3560     @page edcref
3561     @property
3562         source5
3563     @parameters
3564         [another group's name]
3565     @effect
3566         Only available to TEXTBLOCK parts. It is used for the group to be 
3567         loaded and used for anchors display UNDER the anchor position. source6
3568         is used for over the anchors text, if source6 is specified.
3569     @endproperty
3570 */
3571 static void
3572 st_collections_group_parts_part_source5(void)
3573 {
3574    check_arg_count(1);
3575
3576    //FIXME: validate this somehow (need to decide on the format also)
3577    current_part->source5 = parse_str(0);
3578    data_queue_group_lookup(current_part->source5, current_part);
3579 }
3580
3581 /**
3582     @page edcref
3583     @property
3584         source6
3585     @parameters
3586         [another group's name]
3587     @effect
3588         Only available to TEXTBLOCK parts. It is used for the group to be 
3589         loaded and used for anchor display OVER the anchor position. source5
3590         is used for under the anchor text, if source6 is specified.
3591     @endproperty
3592 */
3593 static void
3594 st_collections_group_parts_part_source6(void)
3595 {
3596    check_arg_count(1);
3597
3598    //FIXME: validate this somehow (need to decide on the format also)
3599    current_part->source6 = parse_str(0);
3600    data_queue_group_lookup(current_part->source6, current_part);
3601 }
3602
3603 /**
3604     @page edcref
3605
3606     @property
3607         effect
3608     @parameters
3609         [EFFECT]
3610         (optional) [SHADOW DIRECTION]
3611     @effect
3612         Causes Edje to draw the selected effect among:
3613         @li PLAIN
3614         @li OUTLINE
3615         @li SOFT_OUTLINE
3616         @li SHADOW
3617         @li SOFT_SHADOW
3618         @li OUTLINE_SHADOW
3619         @li OUTLINE_SOFT_SHADOW
3620         @li FAR_SHADOW
3621         @li FAR_SOFT_SHADOW
3622         @li GLOW
3623
3624         Shadow directions (default if not given is BOTTOM_RIGHT):
3625         @li BOTTOM_RIGHT
3626         @li BOTTOM
3627         @li BOTTOM_LEFT
3628         @li LEFT
3629         @li TOP_LEFT
3630         @li TOP
3631         @li TOP_RIGHT
3632         @li RIGHT
3633     @endproperty
3634 */
3635 static void
3636 st_collections_group_parts_part_effect(void)
3637 {
3638    check_min_arg_count(1);
3639
3640    current_part->effect = parse_enum(0,
3641                "NONE", EDJE_TEXT_EFFECT_NONE,
3642                "PLAIN", EDJE_TEXT_EFFECT_PLAIN,
3643                "OUTLINE", EDJE_TEXT_EFFECT_OUTLINE,
3644                "SOFT_OUTLINE", EDJE_TEXT_EFFECT_SOFT_OUTLINE,
3645                "SHADOW", EDJE_TEXT_EFFECT_SHADOW,
3646                "SOFT_SHADOW", EDJE_TEXT_EFFECT_SOFT_SHADOW,
3647                "OUTLINE_SHADOW", EDJE_TEXT_EFFECT_OUTLINE_SHADOW,
3648                "OUTLINE_SOFT_SHADOW", EDJE_TEXT_EFFECT_OUTLINE_SOFT_SHADOW,
3649                "FAR_SHADOW", EDJE_TEXT_EFFECT_FAR_SHADOW,
3650                "FAR_SOFT_SHADOW", EDJE_TEXT_EFFECT_FAR_SOFT_SHADOW,
3651                "GLOW", EDJE_TEXT_EFFECT_GLOW,
3652                NULL);
3653    if (get_arg_count() >= 2)
3654      {
3655         unsigned char shadow;
3656         
3657         shadow = parse_enum(1,
3658                "BOTTOM_RIGHT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_BOTTOM_RIGHT,
3659                "BOTTOM", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_BOTTOM,
3660                "BOTTOM_LEFT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_BOTTOM_LEFT,
3661                "LEFT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_LEFT,
3662                "TOP_LEFT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_TOP_LEFT,
3663                "TOP", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_TOP,
3664                "TOP_RIGHT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_TOP_RIGHT,
3665                "RIGHT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_RIGHT,
3666                NULL);
3667         EDJE_TEXT_EFFECT_SHADOW_DIRECTION_SET(current_part->effect, shadow);
3668      }
3669 }
3670
3671 /**
3672     @page edcref
3673     @property
3674         entry_mode
3675     @parameters
3676         [MODE]
3677     @effect
3678         Sets the edit mode for a textblock part to one of:
3679         @li NONE
3680         @li PLAIN
3681         @li EDITABLE
3682         @li PASSWORD
3683         It causes the part be editable if the edje object has the keyboard
3684         focus AND the part has the edje focus (or selectable always
3685         regardless of focus) and in the event of password mode, not
3686         selectable and all text chars replaced with *'s but editable and
3687         pastable.
3688     @endproperty
3689 */
3690 static void
3691 st_collections_group_parts_part_entry_mode(void)
3692 {
3693    check_arg_count(1);
3694
3695    current_part->entry_mode = parse_enum(0,
3696                                "NONE", EDJE_ENTRY_EDIT_MODE_NONE,
3697                                "PLAIN", EDJE_ENTRY_EDIT_MODE_SELECTABLE,
3698                                "EDITABLE", EDJE_ENTRY_EDIT_MODE_EDITABLE,
3699                                "PASSWORD", EDJE_ENTRY_EDIT_MODE_PASSWORD,
3700                                NULL);
3701 }
3702
3703 /**
3704     @page edcref
3705     @property
3706         select_mode
3707     @parameters
3708         [MODE]
3709     @effect
3710         Sets the selection mode for a textblock part to one of:
3711         @li DEFAULT selection mode is what you would expect on any desktop. Press
3712         mouse, drag and release to end.
3713         @li EXPLICIT mode requires the application
3714         controlling the edje object has to explicitly begin and end selection
3715         modes, and the selection itself is dragable at both ends.
3716     @endproperty
3717 */
3718 static void
3719 st_collections_group_parts_part_select_mode(void)
3720 {
3721    check_arg_count(1);
3722
3723    current_part->select_mode = parse_enum(0,
3724                                 "DEFAULT", EDJE_ENTRY_SELECTION_MODE_DEFAULT,
3725                                 "EXPLICIT", EDJE_ENTRY_SELECTION_MODE_EXPLICIT,
3726                                 "BLOCK_HANDLE", EDJE_ENTRY_SELECTION_MODE_BLOCK_HANDLE,
3727                                 NULL);
3728 }
3729
3730 /**
3731     @page edcref
3732     @property
3733         cursor_mode
3734     @parameters
3735         [MODE]
3736     @effect
3737         Sets the cursor mode for a textblock part to one of:
3738         @li UNDER cursor mode means the cursor will draw below the character pointed
3739         at. That's the default.
3740         @li BEFORE cursor mode means the cursor is drawn as a vertical line before
3741         the current character, just like many other GUI toolkits handle it.
3742     @endproperty
3743 */
3744 static void
3745 st_collections_group_parts_part_cursor_mode(void)
3746 {
3747    check_arg_count(1);
3748
3749    current_part->cursor_mode = parse_enum(0,
3750                                 "UNDER", EDJE_ENTRY_CURSOR_MODE_UNDER,
3751                                 "BEFORE", EDJE_ENTRY_CURSOR_MODE_BEFORE,
3752                                 NULL);
3753 }
3754
3755 /**
3756     @page edcref
3757     @property
3758         multiline
3759     @parameters
3760         [1 or 0]
3761     @effect
3762         It causes a textblock that is editable to allow multiple lines for
3763         editing.
3764     @endproperty
3765 */
3766 static void
3767 st_collections_group_parts_part_multiline(void)
3768 {
3769    check_arg_count(1);
3770
3771    current_part->multiline = parse_bool(0);
3772 }
3773
3774 /**
3775     @page edcref
3776     @property
3777         access 
3778     @parameters
3779         [1 or 0]
3780     @effect
3781         Specifies whether the part will use accessibility feature (1),
3782         or not (0). It's set to 0 by default.
3783     @endproperty
3784 */
3785 static void
3786 st_collections_group_parts_part_access(void)
3787 {
3788    check_arg_count(1);
3789
3790    current_part->access = parse_bool(0);
3791 }
3792
3793 /**
3794     @page edcref
3795     @block
3796         dragable
3797     @context
3798         part {
3799             ..
3800             dragable {
3801                 confine: "another part";
3802                 events:  "another dragable part";
3803                 x: 0 0 0;
3804                 y: 0 0 0;
3805             }
3806             ..
3807         }
3808     @description
3809         When this block is used the resulting part can be dragged around the
3810         interface, do not confuse with external drag & drop. By default Edje
3811         (and most applications) will attempt to use the minimal size possible
3812         for a dragable part. If the min property is not set in the description
3813         the part will be (most likely) set to 0px width and 0px height, thus
3814         invisible.
3815     @endblock
3816
3817     @property
3818         x
3819     @parameters
3820         [enable/disable] [step] [count]
3821     @effect
3822         Used to setup dragging events for the X axis. The first parameter is
3823         used to enable (1 or -1) and disable (0) dragging along the axis. When
3824         enabled, 1 will set the starting point at 0.0 and -1 at 1.0. The second
3825         parameter takes any integer and will limit movement to values
3826         divisible by it, causing the part to jump from position to position.
3827         The third parameter, (question from the author: What is count for?).
3828     @endproperty
3829 */
3830 static void
3831 st_collections_group_parts_part_dragable_x(void)
3832 {
3833    check_arg_count(3);
3834
3835    current_part->dragable.x = parse_int_range(0, -1, 1);
3836    current_part->dragable.step_x = parse_int_range(1, 0, 0x7fffffff);
3837    current_part->dragable.count_x = parse_int_range(2, 0, 0x7fffffff);
3838 }
3839
3840 /**
3841     @page edcref
3842     @property
3843         y
3844     @parameters
3845         [enable/disable] [step] [count]
3846     @effect
3847         Used to setup dragging events for the Y axis. The first parameter is
3848         used to enable (1 or -1) and disable (0) dragging along the axis. When
3849         enabled, 1 will set the starting point at 0.0 and -1 at 1.0. The second
3850         parameter takes any integer and will limit movement to values
3851         divisibles by it, causing the part to jump from position to position.
3852         The third parameter, (question from the author: What is count for?).
3853     @endproperty
3854 */
3855 static void
3856 st_collections_group_parts_part_dragable_y(void)
3857 {
3858    check_arg_count(3);
3859
3860    current_part->dragable.y = parse_int_range(0, -1, 1);
3861    current_part->dragable.step_y = parse_int_range(1, 0, 0x7fffffff);
3862    current_part->dragable.count_y = parse_int_range(2, 0, 0x7fffffff);
3863 }
3864
3865 /**
3866     @page edcref
3867     @property
3868         confine
3869     @parameters
3870         [another part's name]
3871     @effect
3872         When set, limits the movement of the dragged part to another part's
3873         container. When you use confine don't forget to set a min size for the
3874         part, or the draggie will not show up.
3875     @endproperty
3876 */
3877 static void
3878 st_collections_group_parts_part_dragable_confine(void)
3879 {
3880    Edje_Part_Collection *pc;
3881
3882    check_arg_count(1);
3883
3884    pc = eina_list_data_get(eina_list_last(edje_collections));
3885      {
3886         char *name;
3887
3888         name = parse_str(0);
3889         data_queue_part_lookup(pc, name, &(current_part->dragable.confine_id));
3890         free(name);
3891      }
3892 }
3893
3894 /**
3895     @page edcref
3896     @property
3897         events
3898     @parameters
3899         [another dragable part's name]
3900     @effect
3901         It causes the part to forward the drag events to another part, thus
3902         ignoring them for itself.
3903     @endproperty
3904 */
3905 static void
3906 st_collections_group_parts_part_dragable_events(void)
3907 {
3908    Edje_Part_Collection *pc;
3909
3910    check_arg_count(1);
3911
3912    pc = eina_list_data_get(eina_list_last(edje_collections));
3913      {
3914         char *name;
3915
3916         name = parse_str(0);
3917         data_queue_part_lookup(pc, name, &(current_part->dragable.event_id));
3918         free(name);
3919      }
3920 }
3921
3922 /**
3923     @page edcref
3924     @block
3925         items
3926     @context
3927         part {
3928             ..
3929             box {
3930                 items {
3931                     item {
3932                         type: TYPE;
3933                         source: "some source";
3934                         min: 1 1;
3935                         max: 100 100;
3936                         padding: 1 1 2 2;
3937                     }
3938                     item {
3939                         type: TYPE;
3940                         source: "some other source";
3941                         name: "some name";
3942                         align: 1.0 0.5;
3943                     }
3944                     ..
3945                 }
3946             }
3947             ..
3948         }
3949     @description
3950         On a part of type BOX, this block can be used to set other groups
3951         as elements of the box. These can be mixed with external objects set
3952         by the application through the edje_object_part_box_* API.
3953     @endblock
3954 */
3955 static void ob_collections_group_parts_part_box_items_item(void)
3956 {
3957    Edje_Part *ep;
3958    Edje_Pack_Element *item;
3959    Edje_Pack_Element_Parser *pitem;
3960
3961    ep = current_part;
3962
3963    if ((ep->type != EDJE_PART_TYPE_BOX) && (ep->type != EDJE_PART_TYPE_TABLE))
3964      {
3965         ERR("parse error %s:%i. box attributes in non-BOX or TABLE part.",
3966             file_in, line - 1);
3967         exit(-1);
3968      }
3969
3970    ep->items_count++;
3971    ep->items = realloc(ep->items, sizeof (Edje_Pack_Element*) * ep->items_count);
3972    if (!ep->items)
3973      {
3974         ERR("Not enough memory.");
3975         exit(-1);
3976      }
3977
3978    item = mem_alloc(SZ(Edje_Pack_Element_Parser));
3979    current_item = ep->items[ep->items_count - 1] = item;
3980    item->type = EDJE_PART_TYPE_GROUP;
3981    item->name = NULL;
3982    item->source = NULL;
3983    item->min.w = 0;
3984    item->min.h = 0;
3985    item->prefer.w = 0;
3986    item->prefer.h = 0;
3987    item->max.w = -1;
3988    item->max.h = -1;
3989    item->padding.l = 0;
3990    item->padding.r = 0;
3991    item->padding.t = 0;
3992    item->padding.b = 0;
3993    item->align.x = FROM_DOUBLE(0.5);
3994    item->align.y = FROM_DOUBLE(0.5);
3995    item->weight.x = FROM_DOUBLE(0.0);
3996    item->weight.y = FROM_DOUBLE(0.0);
3997    item->aspect.w = 0;
3998    item->aspect.h = 0;
3999    item->aspect.mode = EDJE_ASPECT_CONTROL_NONE;
4000    item->options = NULL;
4001    item->col = -1;
4002    item->row = -1;
4003    item->colspan = 1;
4004    item->rowspan = 1;
4005    pitem = (Edje_Pack_Element_Parser *)item;
4006    pitem->can_override = EINA_FALSE;
4007 }
4008
4009 /**
4010     @page edcref
4011     @property
4012         type
4013     @parameters
4014         Only GROUP for now (defaults to it)
4015     @effect
4016         Sets the type of the object this item will hold.
4017     @endproperty
4018 */
4019 static void st_collections_group_parts_part_box_items_item_type(void)
4020 {
4021    check_arg_count(1);
4022
4023      {
4024         char *s;
4025
4026         s = parse_str(0);
4027         if (strcmp(s, "GROUP"))
4028           {
4029              ERR("parse error %s:%i. token %s not one of: GROUP.",
4030                  file_in, line - 1, s);
4031              exit(-1);
4032           }
4033         /* FIXME: handle the enum, once everything else is supported */
4034         current_item->type = EDJE_PART_TYPE_GROUP;
4035      }
4036 }
4037
4038 /**
4039     @page edcref
4040     @property
4041         name
4042     @parameters
4043         [name for the object]
4044     @effect
4045         Sets the name of the object via evas_object_name_set().
4046     @endproperty
4047 */
4048 static void st_collections_group_parts_part_box_items_item_name(void)
4049 {
4050    Edje_Part *ep;
4051    Edje_Pack_Element *item;
4052    Edje_Pack_Element_Parser *pitem;
4053
4054    check_arg_count(1);
4055
4056    ep = current_part;
4057    item = ep->items[ep->items_count - 1];
4058
4059    item->name = parse_str(0);
4060
4061      {
4062         unsigned int i;
4063
4064         for (i = 0; i < ep->items_count - 1; ++i)
4065           {
4066              if (ep->items[i]->name && (!strcmp(ep->items[i]->name, item->name)))
4067                {
4068                   pitem = (Edje_Pack_Element_Parser *)ep->items[i];
4069                   if (!pitem->can_override)
4070                     {
4071                        ERR("parse error %s:%i. There is already a item of the name %s",
4072                            file_in, line - 1, item->name);
4073                        exit(-1);
4074                     }
4075                   else
4076                     {
4077                        free(item);
4078                        ep->items_count--;
4079                        ep->items = realloc(ep->items, ep->items_count * sizeof (Edje_Pack_Element *));
4080                        current_item = ep->items[i];
4081                        pitem->can_override = EINA_FALSE;
4082                     }
4083                }
4084           }
4085      }
4086 }
4087
4088 /**
4089     @page edcref
4090     @property
4091         source
4092     @parameters
4093         [another group's name]
4094     @effect
4095         Sets the group this object will be made from.
4096     @endproperty
4097 */
4098 static void st_collections_group_parts_part_box_items_item_source(void)
4099 {
4100    check_arg_count(1);
4101
4102    current_item->source = parse_str(0);
4103    data_queue_group_lookup(current_item->source, current_part);
4104 }
4105
4106 /**
4107     @page edcref
4108     @property
4109         min
4110     @parameters
4111         [width] [height]
4112     @effect
4113         Sets the minimum size hints for this object.
4114     @endproperty
4115 */
4116 static void st_collections_group_parts_part_box_items_item_min(void)
4117 {
4118    check_arg_count(2);
4119
4120    current_item->min.w = parse_int_range(0, 0, 0x7ffffff);
4121    current_item->min.h = parse_int_range(1, 0, 0x7ffffff);
4122 }
4123
4124 /**
4125     @page edcref
4126     @property
4127         prefer
4128     @parameters
4129         [width] [height]
4130     @effect
4131         Sets the preferred size hints for this object.
4132     @endproperty
4133 */
4134 static void st_collections_group_parts_part_box_items_item_prefer(void)
4135 {
4136    check_arg_count(2);
4137
4138    current_item->prefer.w = parse_int_range(0, 0, 0x7ffffff);
4139    current_item->prefer.h = parse_int_range(1, 0, 0x7ffffff);
4140 }
4141 /**
4142     @page edcref
4143     @property
4144         max
4145     @parameters
4146         [width] [height]
4147     @effect
4148         Sets the maximum size hints for this object.
4149     @endproperty
4150 */
4151 static void st_collections_group_parts_part_box_items_item_max(void)
4152 {
4153    check_arg_count(2);
4154
4155    current_item->max.w = parse_int_range(0, 0, 0x7ffffff);
4156    current_item->max.h = parse_int_range(1, 0, 0x7ffffff);
4157 }
4158
4159 /**
4160     @page edcref
4161     @property
4162         padding
4163     @parameters
4164         [left] [right] [top] [bottom]
4165     @effect
4166         Sets the padding hints for this object.
4167     @endproperty
4168 */
4169 static void st_collections_group_parts_part_box_items_item_padding(void)
4170 {
4171    check_arg_count(4);
4172
4173    current_item->padding.l = parse_int_range(0, 0, 0x7ffffff);
4174    current_item->padding.r = parse_int_range(1, 0, 0x7ffffff);
4175    current_item->padding.t = parse_int_range(2, 0, 0x7ffffff);
4176    current_item->padding.b = parse_int_range(3, 0, 0x7ffffff);
4177 }
4178
4179 /**
4180     @page edcref
4181     @property
4182         align
4183     @parameters
4184         [x] [y]
4185     @effect
4186         Sets the alignment hints for this object.
4187     @endproperty
4188 */
4189 static void st_collections_group_parts_part_box_items_item_align(void)
4190 {
4191    check_arg_count(2);
4192
4193    current_item->align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
4194    current_item->align.y = FROM_DOUBLE(parse_float_range(1, -1.0, 1.0));
4195 }
4196
4197 /**
4198     @page edcref
4199     @property
4200         weight
4201     @parameters
4202         [x] [y]
4203     @effect
4204         Sets the weight hints for this object.
4205     @endproperty
4206 */
4207 static void st_collections_group_parts_part_box_items_item_weight(void)
4208 {
4209    check_arg_count(2);
4210
4211    current_item->weight.x = FROM_DOUBLE(parse_float_range(0, 0.0, 99999.99));
4212    current_item->weight.y = FROM_DOUBLE(parse_float_range(1, 0.0, 99999.99));
4213 }
4214
4215 /**
4216     @page edcref
4217     @property
4218         aspect
4219     @parameters
4220         [w] [h]
4221     @effect
4222         Sets the aspect width and height hints for this object.
4223     @endproperty
4224 */
4225 static void st_collections_group_parts_part_box_items_item_aspect(void)
4226 {
4227    check_arg_count(2);
4228
4229    current_item->aspect.w = parse_int_range(0, 0, 0x7fffffff);
4230    current_item->aspect.h = parse_int_range(1, 0, 0x7fffffff);
4231 }
4232
4233 /**
4234     @page edcref
4235     @property
4236         aspect_mode
4237     @parameters
4238         NONE, NEITHER, HORIZONTAL, VERTICAL, BOTH
4239     @effect
4240         Sets the aspect control hints for this object.
4241     @endproperty
4242 */
4243 static void st_collections_group_parts_part_box_items_item_aspect_mode(void)
4244 {
4245    check_arg_count(1);
4246
4247    current_item->aspect.mode = parse_enum(0,
4248                                   "NONE", EDJE_ASPECT_CONTROL_NONE,
4249                                   "NEITHER", EDJE_ASPECT_CONTROL_NEITHER,
4250                                   "HORIZONTAL", EDJE_ASPECT_CONTROL_HORIZONTAL,
4251                                   "VERTICAL", EDJE_ASPECT_CONTROL_VERTICAL,
4252                                   "BOTH", EDJE_ASPECT_CONTROL_BOTH,
4253                                   NULL);
4254 }
4255
4256 /**
4257     @page edcref
4258     @property
4259         options
4260     @parameters
4261         [extra options]
4262     @effect
4263         Sets extra options for the object. Unused for now.
4264     @endproperty
4265 */
4266 static void st_collections_group_parts_part_box_items_item_options(void)
4267 {
4268    check_arg_count(1);
4269
4270    current_item->options = parse_str(0);
4271 }
4272
4273 /**
4274     @page edcref
4275     @property
4276         position
4277     @parameters
4278         [col] [row]
4279     @effect
4280         Sets the position this item will have in the table.
4281         This is required for parts of type TABLE.
4282     @endproperty
4283 */
4284 static void st_collections_group_parts_part_table_items_item_position(void)
4285 {
4286    check_arg_count(2);
4287
4288    if (current_part->type != EDJE_PART_TYPE_TABLE)
4289      {
4290         ERR("parse error %s:%i. table attributes in non-TABLE part.",
4291             file_in, line - 1);
4292         exit(-1);
4293      }
4294
4295    current_item->col = parse_int_range(0, 0, 0xffff);
4296    current_item->row = parse_int_range(1, 0, 0xffff);
4297 }
4298
4299 /**
4300     @page edcref
4301     @property
4302         span
4303     @parameters
4304         [col] [row]
4305     @effect
4306         Sets how many columns/rows this item will use.
4307         Defaults to 1 1.
4308     @endproperty
4309 */
4310 static void st_collections_group_parts_part_table_items_item_span(void)
4311 {
4312    check_arg_count(2);
4313
4314    if (current_part->type != EDJE_PART_TYPE_TABLE)
4315      {
4316         ERR("parse error %s:%i. table attributes in non-TABLE part.",
4317             file_in, line - 1);
4318         exit(-1);
4319      }
4320
4321    current_item->colspan = parse_int_range(0, 1, 0xffff);
4322    current_item->rowspan = parse_int_range(1, 1, 0xffff);
4323 }
4324
4325 /**
4326    @edcsection{description,State description sub blocks}
4327  */
4328
4329 /**
4330     @page edcref
4331     @block
4332         description
4333     @context
4334         description {
4335             inherit: "another_description" INDEX;
4336             state: "description_name" INDEX;
4337             visible: 1;
4338             min: 0 0;
4339             max: -1 -1;
4340             align: 0.5 0.5;
4341             fixed: 0 0;
4342             step: 0 0;
4343             aspect: 1 1;
4344
4345             rel1 {
4346                 ..
4347             }
4348
4349             rel2 {
4350                 ..
4351             }
4352         }
4353     @description
4354         Every part can have one or more description blocks. Each description is
4355         used to define style and layout properties of a part in a given
4356         "state".
4357     @endblock
4358 */
4359 static void
4360 ob_collections_group_parts_part_description(void)
4361 {  /* Allocate and set desc, set relative part hierarchy if needed */
4362    Edje_Part_Collection *pc;
4363    Edje_Part *ep;
4364    Edje_Part_Description_Common *ed;
4365
4366    pc = eina_list_data_get(eina_list_last(edje_collections));
4367    ep = current_part;
4368
4369    ed = _edje_part_description_alloc(ep->type, pc->part, ep->name);
4370
4371    ed->rel1.id_x = -1;
4372    ed->rel1.id_y = -1;
4373    ed->rel2.id_x = -1;
4374    ed->rel2.id_y = -1;
4375
4376    if (!ep->default_desc)
4377      {
4378         current_desc = ep->default_desc = ed;
4379
4380           {  /* Get the ptr of the part above current part in hierarchy */
4381              Edje_Part *node = edje_cc_handlers_hierarchy_parent_get();
4382              if (node)  /* Make relative according to part hierarchy */
4383                edje_cc_handlers_hierarchy_set(node);
4384           }
4385      }
4386    else
4387      {
4388         ep->other.desc_count++;
4389         ep->other.desc = realloc(ep->other.desc,
4390                                  sizeof (Edje_Part_Description_Common*) * ep->other.desc_count);
4391         current_desc = ep->other.desc[ep->other.desc_count - 1] = ed;
4392      }
4393
4394    ed->visible = 1;
4395    ed->limit = 0;
4396    ed->align.x = FROM_DOUBLE(0.5);
4397    ed->align.y = FROM_DOUBLE(0.5);
4398    ed->min.w = 0;
4399    ed->min.h = 0;
4400    ed->fixed.w = 0;
4401    ed->fixed.h = 0;
4402    ed->max.w = -1;
4403    ed->max.h = -1;
4404    ed->rel1.relative_x = FROM_DOUBLE(0.0);
4405    ed->rel1.relative_y = FROM_DOUBLE(0.0);
4406    ed->rel1.offset_x = 0;
4407    ed->rel1.offset_y = 0;
4408    ed->rel2.relative_x = FROM_DOUBLE(1.0);
4409    ed->rel2.relative_y = FROM_DOUBLE(1.0);
4410    ed->rel2.offset_x = -1;
4411    ed->rel2.offset_y = -1;
4412    ed->color_class = NULL;
4413    ed->color.r = 255;
4414    ed->color.g = 255;
4415    ed->color.b = 255;
4416    ed->color.a = 255;
4417    ed->color2.r = 0;
4418    ed->color2.g = 0;
4419    ed->color2.b = 0;
4420    ed->color2.a = 255;
4421    ed->map.id_persp = -1;
4422    ed->map.id_light = -1;
4423    ed->map.rot.id_center = -1;
4424    ed->map.rot.x = FROM_DOUBLE(0.0);
4425    ed->map.rot.y = FROM_DOUBLE(0.0);
4426    ed->map.rot.z = FROM_DOUBLE(0.0);
4427    ed->map.on = 0;
4428    ed->map.smooth = 1;
4429    ed->map.alpha = 1;
4430    ed->map.backcull = 0;
4431    ed->map.persp_on = 0;
4432    ed->persp.zplane = 0;
4433    ed->persp.focal = 1000;
4434    ed->minmul.have = 1;
4435    ed->minmul.w = FROM_INT(1);
4436    ed->minmul.h = FROM_INT(1);
4437 }
4438
4439 /**
4440     @page edcref
4441     @property
4442         inherit
4443     @parameters
4444         [another description's name] [another description's index]
4445     @effect
4446         When set, the description will inherit all the properties from the
4447         named description. The properties defined in this part will override
4448         the inherited properties, reducing the amount of necessary code for
4449         simple state changes. Note: inheritance in Edje is single level only.
4450     @endproperty
4451 */
4452 static void
4453 st_collections_group_parts_part_description_inherit(void)
4454 {
4455    Edje_Part_Collection *pc;
4456    Edje_Part *ep;
4457    Edje_Part_Description_Common *ed, *parent = NULL;
4458    Edje_Part_Image_Id *iid;
4459    char *parent_name;
4460    const char *state_name;
4461    double parent_val, state_val;
4462
4463    pc = eina_list_data_get(eina_list_last(edje_collections));
4464    ep = current_part;
4465    ed = current_desc;
4466
4467    if (!ed->state.name)
4468      {
4469         ERR("parse error %s:%i. inherit may only be used after state",
4470             file_in, line - 1);
4471         exit(-1);
4472      }
4473
4474    parent = parent_desc;
4475    if (!parent)
4476      {
4477         check_min_arg_count(1);
4478
4479         /* inherit may not be used in the default description */
4480         if (!ep->other.desc_count)
4481           {
4482              ERR("parse error %s:%i. "
4483                  "inherit may not be used in the default description",
4484                  file_in, line - 1);
4485              exit(-1);
4486           }
4487
4488         /* find the description that we inherit from */
4489         parent_name = parse_str(0);
4490         if (get_arg_count() == 2)
4491           parent_val = parse_float_range(1, 0.0, 1.0);
4492         else
4493           parent_val = 0.0;
4494
4495         if (!strcmp (parent_name, "default") && parent_val == 0.0)
4496           parent = ep->default_desc;
4497         else
4498           {
4499              Edje_Part_Description_Common *d;
4500              double min_dst = 999.0;
4501              unsigned int i;
4502
4503              if (!strcmp(parent_name, "default"))
4504                {
4505                   parent = ep->default_desc;
4506                   min_dst = ABS(ep->default_desc->state.value - parent_val);
4507                }
4508
4509              for (i = 0; i < ep->other.desc_count; ++i)
4510                {
4511                   d = ep->other.desc[i];
4512
4513                   if (!strcmp (d->state.name, parent_name))
4514                     {
4515
4516                        double dst;
4517
4518                        dst = ABS(d->state.value - parent_val);
4519                        if (dst < min_dst)
4520                          {
4521                             parent = d;
4522                             min_dst = dst;
4523                          }
4524                     }
4525                }
4526           }
4527
4528         if (!parent)
4529           {
4530              ERR("parse error %s:%i. "
4531                  "cannot find referenced part %s state %s %lf",
4532                  file_in, line - 1, ep->name, parent_name, parent_val);
4533              exit(-1);
4534           }
4535
4536         free(parent_name);
4537      }
4538    /* now do a full copy, only state info will be kept */
4539    state_name = ed->state.name;
4540    state_val = ed->state.value;
4541
4542    *ed = *parent;
4543
4544    ed->state.name = state_name;
4545    ed->state.value = state_val;
4546
4547    data_queue_copied_part_lookup(pc, &parent->rel1.id_x, &ed->rel1.id_x);
4548    data_queue_copied_part_lookup(pc, &parent->rel1.id_y, &ed->rel1.id_y);
4549    data_queue_copied_part_lookup(pc, &parent->rel2.id_x, &ed->rel2.id_x);
4550    data_queue_copied_part_lookup(pc, &parent->rel2.id_y, &ed->rel2.id_y);
4551
4552    data_queue_copied_part_lookup(pc, &parent->map.id_persp, &ed->map.id_persp);
4553    data_queue_copied_part_lookup(pc, &parent->map.id_light, &ed->map.id_light);
4554    data_queue_copied_part_lookup(pc, &parent->map.rot.id_center, &ed->map.rot.id_center);
4555
4556    /* make sure all the allocated memory is getting copied, not just
4557     * referenced
4558     */
4559 #define STRDUP(x) x ? strdup(x) : NULL
4560
4561    ed->color_class = STRDUP(ed->color_class);
4562    switch (ep->type)
4563      {
4564       case EDJE_PART_TYPE_SPACER:
4565       case EDJE_PART_TYPE_RECTANGLE:
4566       case EDJE_PART_TYPE_SWALLOW:
4567       case EDJE_PART_TYPE_GROUP:
4568          /* Nothing todo, this part only have a common description. */
4569          break;
4570       case EDJE_PART_TYPE_TEXT:
4571       case EDJE_PART_TYPE_TEXTBLOCK:
4572            {
4573               Edje_Part_Description_Text *ted = (Edje_Part_Description_Text*) ed;
4574               Edje_Part_Description_Text *tparent = (Edje_Part_Description_Text*) parent;
4575
4576               ted->text = tparent->text;
4577
4578               ted->text.text.str = STRDUP(ted->text.text.str);
4579               ted->text.text_class = STRDUP(ted->text.text_class);
4580               ted->text.font.str = STRDUP(ted->text.font.str);
4581
4582               data_queue_copied_part_lookup(pc, &(tparent->text.id_source), &(ted->text.id_source));
4583               data_queue_copied_part_lookup(pc, &(tparent->text.id_text_source), &(ted->text.id_text_source));
4584
4585               break;
4586            }
4587       case EDJE_PART_TYPE_IMAGE:
4588            {
4589               Edje_Part_Description_Image *ied = (Edje_Part_Description_Image *) ed;
4590               Edje_Part_Description_Image *iparent = (Edje_Part_Description_Image *) parent;
4591               unsigned int i;
4592
4593               ied->image = iparent->image;
4594
4595               data_queue_image_remove(&ied->image.id, &ied->image.set);
4596               data_queue_copied_image_lookup(&iparent->image.id, &ied->image.id, &ied->image.set);
4597
4598               ied->image.tweens = calloc(iparent->image.tweens_count,
4599                                          sizeof (Edje_Part_Image_Id*));
4600               for (i = 0; i < iparent->image.tweens_count; i++)
4601                 {
4602                    Edje_Part_Image_Id *iid_new;
4603
4604                    iid = iparent->image.tweens[i];
4605
4606                    iid_new = mem_alloc(SZ(Edje_Part_Image_Id));
4607                    data_queue_image_remove(&ied->image.id, &ied->image.set);
4608                    data_queue_copied_image_lookup(&(iid->id), &(iid_new->id), &(iid_new->set));
4609                    ied->image.tweens[i] = iid_new;
4610                 }
4611
4612               break;
4613            }
4614       case EDJE_PART_TYPE_PROXY:
4615            {
4616               Edje_Part_Description_Proxy *ped = (Edje_Part_Description_Proxy*) ed;
4617               Edje_Part_Description_Proxy *pparent = (Edje_Part_Description_Proxy*) parent;
4618
4619               data_queue_copied_part_lookup(pc, &(pparent->proxy.id), &(ped->proxy.id));
4620
4621               break;
4622            }
4623       case EDJE_PART_TYPE_BOX:
4624            {
4625               Edje_Part_Description_Box *bed = (Edje_Part_Description_Box *) ed;
4626               Edje_Part_Description_Box *bparent = (Edje_Part_Description_Box *) parent;
4627
4628               bed->box = bparent->box;
4629
4630               break;
4631            }
4632       case EDJE_PART_TYPE_TABLE:
4633            {
4634               Edje_Part_Description_Table *ted = (Edje_Part_Description_Table *) ed;
4635               Edje_Part_Description_Table *tparent = (Edje_Part_Description_Table *) parent;
4636
4637               ted->table = tparent->table;
4638
4639               break;
4640            }
4641       case EDJE_PART_TYPE_EXTERNAL:
4642            {
4643               Edje_Part_Description_External *eed = (Edje_Part_Description_External *) ed;
4644               Edje_Part_Description_External *eparent = (Edje_Part_Description_External *) parent;
4645
4646               if (eparent->external_params)
4647                 {
4648                    Eina_List *l;
4649                    Edje_External_Param *param, *new_param;
4650
4651                    eed->external_params = NULL;
4652                    EINA_LIST_FOREACH(eparent->external_params, l, param)
4653                      {
4654                         new_param = mem_alloc(SZ(Edje_External_Param));
4655                         *new_param = *param;
4656                         eed->external_params = eina_list_append(eed->external_params, new_param);
4657                      }
4658                 }
4659               break;
4660            }
4661      }
4662
4663 #undef STRDUP
4664 }
4665
4666 /**
4667     @page edcref
4668
4669     @property
4670         source
4671     @parameters
4672         [another part's name]
4673     @effect
4674         Causes the part to use another part content as the content of this part.
4675         Only work with PROXY part.
4676     @endproperty
4677 */
4678 static void
4679 st_collections_group_parts_part_description_source(void)
4680 {
4681    Edje_Part_Collection *pc;
4682    Edje_Part_Description_Proxy *ed;
4683    char *name;
4684
4685    check_arg_count(1);
4686
4687    pc = eina_list_data_get(eina_list_last(edje_collections));
4688
4689    if (current_part->type != EDJE_PART_TYPE_PROXY)
4690      {
4691         ERR("parse error %s:%i. source attributes in non-PROXY part.",
4692             file_in, line - 1);
4693         exit(-1);
4694      }
4695
4696    ed = (Edje_Part_Description_Proxy*) current_desc;
4697
4698    name = parse_str(0);
4699
4700    data_queue_part_lookup(pc, name, &(ed->proxy.id));
4701    free(name);
4702 }
4703
4704 /**
4705     @page edcref
4706     @property
4707         state
4708     @parameters
4709         [a name for the description] [an index]
4710     @effect
4711         Sets a name used to identify a description inside a given part.
4712         Multiple descriptions are used to declare different states of the same
4713         part, like "clicked" or "invisible". All states declarations are also
4714         coupled with an index number between 0.0 and 1.0. All parts must have
4715         at least one description named "default 0.0".
4716     @endproperty
4717 */
4718 static void
4719 st_collections_group_parts_part_description_state(void)
4720 {
4721    Edje_Part *ep;
4722    Edje_Part_Description_Common *ed;
4723    char *s;
4724
4725    check_min_arg_count(1);
4726
4727    ep = current_part;
4728
4729    ed = ep->default_desc;
4730    if (ep->other.desc_count) ed = ep->other.desc[ep->other.desc_count - 1];
4731
4732    s = parse_str(0);
4733    if (!strcmp (s, "custom"))
4734      {
4735         ERR("parse error %s:%i. invalid state name: '%s'.",
4736             file_in, line - 1, s);
4737         exit(-1);
4738      }
4739
4740    ed->state.name = s;
4741    if (get_arg_count() == 1)
4742      ed->state.value = 0.0;
4743    else
4744      ed->state.value = parse_float_range(1, 0.0, 1.0);
4745
4746    if (ed != ep->default_desc)
4747      {
4748         if ((ep->default_desc->state.name && !strcmp(s, ep->default_desc->state.name) && ed->state.value == ep->default_desc->state.value) ||
4749             (!ep->default_desc->state.name && !strcmp(s, "default") && ed->state.value == ep->default_desc->state.value))
4750           {
4751              if (ep->type == EDJE_PART_TYPE_IMAGE)
4752                _edje_part_description_image_remove((Edje_Part_Description_Image*) ed);
4753
4754              free(ed);
4755              ep->other.desc_count--;
4756              ep->other.desc = realloc(ep->other.desc,
4757                                       sizeof (Edje_Part_Description_Common*) * ep->other.desc_count);
4758              current_desc = ep->default_desc;
4759           }
4760         else if (ep->other.desc_count)
4761           {
4762              unsigned int i;
4763              for (i = 0; i < ep->other.desc_count - 1; ++i)
4764                {
4765                   if (!strcmp(s, ep->other.desc[i]->state.name) && ed->state.value == ep->other.desc[i]->state.value)
4766                     {
4767                        if (ep->type == EDJE_PART_TYPE_IMAGE)
4768                          _edje_part_description_image_remove((Edje_Part_Description_Image*) ed);
4769
4770                        free(ed);
4771                        ep->other.desc_count--;
4772                        ep->other.desc = realloc(ep->other.desc,
4773                                                 sizeof (Edje_Part_Description_Common*) * ep->other.desc_count);
4774                        current_desc = ep->other.desc[i];
4775                        break;
4776                     }
4777                }
4778           }
4779      }
4780 }
4781
4782 /**
4783     @page edcref
4784     @property
4785         visible
4786     @parameters
4787         [0 or 1]
4788     @effect
4789         Takes a boolean value specifying whether part is visible (1) or not
4790         (0). Non-visible parts do not emit signals. The default value is 1.
4791     @endproperty
4792 */
4793 static void
4794 st_collections_group_parts_part_description_visible(void)
4795 {
4796    check_arg_count(1);
4797
4798    if (current_part->type == EDJE_PART_TYPE_SPACER)
4799      {
4800        ERR("parse error %s:%i. SPACER part can't have a visibility defined",
4801            file_in, line - 1);
4802        exit(-1);
4803      }
4804
4805    current_desc->visible = parse_bool(0);
4806 }
4807 /**
4808     @page edcref
4809     @property
4810         limit
4811     @parameters
4812         [NONE, WIDTH, HEIGHT or BOTH]
4813     @effect
4814         Emit a signal when the part size change from zero or to a zero size
4815         ('limit,width,over', 'limit,width,zero'). By default no signal are
4816         emitted.
4817     @endproperty
4818     @since 1.7.0
4819 */
4820 static void
4821 st_collections_group_parts_part_description_limit(void)
4822 {
4823    check_arg_count(1);
4824
4825    current_desc->limit = parse_enum(0,
4826                                     "NONE", 0,
4827                                     "WIDTH", 1,
4828                                     "HEIGHT", 2,
4829                                     "BOTH", 3);
4830
4831    if (current_desc->limit)
4832      {
4833         Edje_Part_Collection *pc;
4834         int count;
4835
4836         pc = eina_list_data_get(eina_list_last(edje_collections));
4837         count = pc->limits.parts_count++;
4838         pc->limits.parts = realloc(pc->limits.parts,
4839                                    pc->limits.parts_count * sizeof (Edje_Part_Limit));
4840         data_queue_part_lookup(pc, current_part->name,
4841                                &(pc->limits.parts[count].part));
4842      }
4843 }
4844
4845 /**
4846     @page edcref
4847     @property
4848         align
4849     @parameters
4850         [X axis] [Y axis]
4851     @effect
4852         When the displayed object's size is smaller than its container, this
4853         property moves it relatively along both axis inside its container. The
4854         default value is "0.5 0.5".
4855     @endproperty
4856 */
4857 static void
4858 st_collections_group_parts_part_description_align(void)
4859 {
4860    check_arg_count(2);
4861
4862    current_desc->align.x = FROM_DOUBLE(parse_float_range(0, 0.0, 1.0));
4863    current_desc->align.y = FROM_DOUBLE(parse_float_range(1, 0.0, 1.0));
4864 }
4865
4866 /**
4867     @page edcref
4868     @property
4869         fixed
4870     @parameters
4871         [width, 0 or 1] [height, 0 or 1]
4872     @effect
4873         This affects the minimum size calculation. See
4874         edje_object_size_min_calc() and edje_object_size_min_restricted_calc().
4875         This tells the min size calculation routine that this part does not
4876         change size in width or height (1 for it doesn't, 0 for it does), so
4877         the routine should not try and expand or contract the part.
4878     @endproperty
4879 */
4880 static void
4881 st_collections_group_parts_part_description_fixed(void)
4882 {
4883    check_arg_count(2);
4884
4885    current_desc->fixed.w = parse_float_range(0, 0, 1);
4886    current_desc->fixed.h = parse_float_range(1, 0, 1);
4887 }
4888
4889 /**
4890     @page edcref
4891     @property
4892         min
4893     @parameters
4894         [width] [height] or SOURCE
4895     @effect
4896         The minimum size of the state.
4897
4898         When min is defined to SOURCE, it will look at the original
4899         image size and enforce it minimal size to match at least the
4900         original one. The part must be an IMAGE or a GROUP part.
4901     @endproperty
4902 */
4903 static void
4904 st_collections_group_parts_part_description_min(void)
4905 {
4906    check_min_arg_count(1);
4907
4908    if (is_param(1)) {
4909       current_desc->min.w = parse_float_range(0, 0, 0x7fffffff);
4910       current_desc->min.h = parse_float_range(1, 0, 0x7fffffff);
4911    } else {
4912       char *tmp;
4913
4914       tmp = parse_str(0);
4915       if ((current_part->type != EDJE_PART_TYPE_IMAGE && current_part->type != EDJE_PART_TYPE_GROUP) ||
4916           !tmp || strcmp(tmp, "SOURCE") != 0)
4917         {
4918            ERR("parse error %s:%i. "
4919                "Only IMAGE and GROUP part can have a min: SOURCE; defined",
4920                file_in, line - 1);
4921            exit(-1);
4922         }
4923
4924       current_desc->min.limit = EINA_TRUE;
4925    }
4926 }
4927
4928 /**
4929     @page edcref
4930     @property
4931         minmul
4932     @parameters
4933         [width multipler] [height multiplier]
4934     @effect
4935         A multiplier FORCIBLY applied to whatever minimum size is only during
4936         minimum size calculation.
4937     @endproperty
4938     @since 1.2
4939 */
4940 static void
4941 st_collections_group_parts_part_description_minmul(void)
4942 {
4943    check_arg_count(2);
4944
4945    current_desc->minmul.w = FROM_DOUBLE(parse_float_range(0, 0, 999999));
4946    current_desc->minmul.h = FROM_DOUBLE(parse_float_range(1, 0, 999999));
4947 }
4948
4949 /**
4950     @page edcref
4951     @property
4952         max
4953     @parameters
4954         [width] [height] or SOURCE
4955     @effect
4956         The maximum size of the state. A size of -1.0 means that it will be ignored in one direction.
4957
4958         When max is set to SOURCE, edje will enforce the part to be
4959         not more than the original image size. The part must be an
4960         IMAGE part.
4961     @endproperty
4962 */
4963 static void
4964 st_collections_group_parts_part_description_max(void)
4965 {
4966    check_min_arg_count(1);
4967
4968    if (is_param(1)) {
4969       current_desc->max.w = parse_float_range(0, -1.0, 0x7fffffff);
4970       current_desc->max.h = parse_float_range(1, -1.0, 0x7fffffff);
4971    } else {
4972       char *tmp;
4973
4974       tmp = parse_str(0);
4975       if (current_part->type != EDJE_PART_TYPE_IMAGE ||
4976           !tmp || strcmp(tmp, "SOURCE") != 0)
4977         {
4978            ERR("parse error %s:%i. "
4979                "Only IMAGE part can have a max: SOURCE; defined",
4980                file_in, line - 1);
4981            exit(-1);
4982         }
4983
4984       current_desc->max.limit = EINA_TRUE;
4985    }
4986 }
4987
4988 /**
4989     @page edcref
4990     @property
4991         step
4992     @parameters
4993         [width] [height]
4994     @effect
4995         Restricts resizing of each dimension to values divisibles by its value.
4996         This causes the part to jump from value to value while resizing. The
4997         default value is "0 0" disabling stepping.
4998     @endproperty
4999 */
5000 static void
5001 st_collections_group_parts_part_description_step(void)
5002 {
5003    check_arg_count(2);
5004
5005    current_desc->step.x = parse_float_range(0, 0, 0x7fffffff);
5006    current_desc->step.y = parse_float_range(1, 0, 0x7fffffff);
5007 }
5008
5009 /**
5010     @page edcref
5011     @property
5012         aspect
5013     @parameters
5014         [min] [max]
5015     @effect
5016         Normally width and height can be resized to any values independently.
5017         The aspect property forces the width to height ratio to be kept between
5018         the minimum and maximum set. For example, "1.0 1.0" will increase the
5019         width a pixel for every pixel added to height. The default value is
5020         "0.0 0.0" disabling aspect.
5021     @endproperty
5022 */
5023 static void
5024 st_collections_group_parts_part_description_aspect(void)
5025 {
5026    check_arg_count(2);
5027
5028    current_desc->aspect.min = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
5029    current_desc->aspect.max = FROM_DOUBLE(parse_float_range(1, 0.0, 999999999.0));
5030 }
5031
5032 /**
5033     @page edcref
5034     @property
5035         aspect_preference
5036     @parameters
5037         [DIMENSION]
5038     @effect
5039         Sets the scope of the "aspect" property to a given dimension. Available
5040         options are BOTH, VERTICAL, HORIZONTAL, SOURCE and NONE
5041     @endproperty
5042 */
5043 static void
5044 st_collections_group_parts_part_description_aspect_preference(void)
5045 {
5046    check_arg_count(1);
5047
5048    current_desc->aspect.prefer =  parse_enum(0,
5049                                    "NONE", EDJE_ASPECT_PREFER_NONE,
5050                                    "VERTICAL", EDJE_ASPECT_PREFER_VERTICAL,
5051                                    "HORIZONTAL", EDJE_ASPECT_PREFER_HORIZONTAL,
5052                                    "BOTH", EDJE_ASPECT_PREFER_BOTH,
5053                                    "SOURCE", EDJE_ASPECT_PREFER_SOURCE,
5054                                    NULL);
5055 }
5056
5057 /**
5058     @page edcref
5059     @property
5060         color_class
5061     @parameters
5062         [color class name]
5063     @effect
5064         The part will use the color values of the named color_class, these
5065         values can be overrided by the "color", "color2" and "color3"
5066         properties set below.
5067     @endproperty
5068 */
5069 static void
5070 st_collections_group_parts_part_description_color_class(void)
5071 {
5072    check_arg_count(1);
5073
5074    if (current_part->type == EDJE_PART_TYPE_SPACER)
5075      {
5076        ERR("parse error %s:%i. SPACER part can't have a color defined",
5077            file_in, line - 1);
5078        exit(-1);
5079      }
5080
5081    current_desc->color_class = parse_str(0);
5082 }
5083
5084 /**
5085     @page edcref
5086     @property
5087         color
5088     @parameters
5089         [red] [green] [blue] [alpha]
5090     @effect
5091         Sets the main color to the specified values (between 0 and 255).
5092     @endproperty
5093 */
5094 static void
5095 st_collections_group_parts_part_description_color(void)
5096 {
5097    check_arg_count(4);
5098
5099    if (current_part->type == EDJE_PART_TYPE_SPACER)
5100      {
5101        ERR("parse error %s:%i. SPACER part can't have a color defined",
5102            file_in, line - 1);
5103        exit(-1);
5104      }
5105
5106    current_desc->color.r = parse_int_range(0, 0, 255);
5107    current_desc->color.g = parse_int_range(1, 0, 255);
5108    current_desc->color.b = parse_int_range(2, 0, 255);
5109    current_desc->color.a = parse_int_range(3, 0, 255);
5110 }
5111
5112 /**
5113     @page edcref
5114     @property
5115         color2
5116     @parameters
5117         [red] [green] [blue] [alpha]
5118     @effect
5119         Sets the text shadow color to the specified values (0 to 255).
5120     @endproperty
5121 */
5122 static void
5123 st_collections_group_parts_part_description_color2(void)
5124 {
5125    check_arg_count(4);
5126
5127    if (current_part->type == EDJE_PART_TYPE_SPACER)
5128      {
5129        ERR("parse error %s:%i. SPACER part can't have a color defined",
5130            file_in, line - 1);
5131        exit(-1);
5132      }
5133
5134    current_desc->color2.r = parse_int_range(0, 0, 255);
5135    current_desc->color2.g = parse_int_range(1, 0, 255);
5136    current_desc->color2.b = parse_int_range(2, 0, 255);
5137    current_desc->color2.a = parse_int_range(3, 0, 255);
5138 }
5139
5140 /**
5141     @page edcref
5142     @property
5143         color3
5144     @parameters
5145         [red] [green] [blue] [alpha]
5146     @effect
5147         Sets the text outline color to the specified values (0 to 255).
5148     @endproperty
5149 */
5150 static void
5151 st_collections_group_parts_part_description_color3(void)
5152 {
5153    Edje_Part_Collection *pc;
5154    Edje_Part_Description_Text *ed;
5155
5156    check_arg_count(4);
5157
5158    pc = eina_list_data_get(eina_list_last(edje_collections));
5159
5160    if (current_part->type != EDJE_PART_TYPE_TEXT
5161        && current_part->type != EDJE_PART_TYPE_TEXTBLOCK)
5162      {
5163         ERR("Setting color3 in part %s from %s not of type TEXT or TEXTBLOCK.",
5164             current_part->name, pc->part);
5165         exit(-1);
5166      }
5167
5168    ed = (Edje_Part_Description_Text*)current_desc;
5169
5170    ed->text.color3.r = parse_int_range(0, 0, 255);
5171    ed->text.color3.g = parse_int_range(1, 0, 255);
5172    ed->text.color3.b = parse_int_range(2, 0, 255);
5173    ed->text.color3.a = parse_int_range(3, 0, 255);
5174 }
5175
5176 /**
5177     @page edcref
5178     @block
5179         rel1/rel2
5180     @context
5181         description {
5182             ..
5183             rel1 {
5184                 relative: 0.0 0.0;
5185                 offset:     0   0;
5186             }
5187             ..
5188             rel2 {
5189                 relative: 1.0 1.0;
5190                 offset:    -1  -1;
5191             }
5192             ..
5193         }
5194     @description
5195         The rel1 and rel2 blocks are used to define the position of each corner
5196         of the part's container. With rel1 being the left-up corner and rel2
5197         being the right-down corner.
5198     @endblock
5199
5200     @property
5201         relative
5202     @parameters
5203         [X axis] [Y axis]
5204     @effect
5205         Moves a corner to a relative position inside the container of the
5206         relative "to" part. Values from 0.0 (0%, beginning) to 1.0 (100%, end)
5207         of each axis.
5208     @endproperty
5209 */
5210 static void
5211 st_collections_group_parts_part_description_rel1_relative(void)
5212 {
5213    check_arg_count(2);
5214
5215    current_desc->rel1.relative_x = FROM_DOUBLE(parse_float(0));
5216    current_desc->rel1.relative_y = FROM_DOUBLE(parse_float(1));
5217 }
5218
5219 /**
5220     @page edcref
5221     @property
5222         offset
5223     @parameters
5224         [X axis] [Y axis]
5225     @effect
5226         Affects the corner position a fixed number of pixels along each axis.
5227     @endproperty
5228 */
5229 static void
5230 st_collections_group_parts_part_description_rel1_offset(void)
5231 {
5232    check_arg_count(2);
5233
5234    current_desc->rel1.offset_x = parse_int(0);
5235    current_desc->rel1.offset_y = parse_int(1);
5236 }
5237
5238 /**
5239     @page edcref
5240     @property
5241         to
5242     @parameters
5243         [another part's name]
5244     @effect
5245         Causes a corner to be positioned relatively to another part's
5246         container. Setting to "" will un-set this value for inherited
5247         parts.
5248     @endproperty
5249 */
5250 static void
5251 st_collections_group_parts_part_description_rel1_to_set(const char *name)
5252 {
5253    Edje_Part_Collection *pc;
5254    pc = eina_list_data_get(eina_list_last(edje_collections));
5255    data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
5256    data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
5257 }
5258
5259 static void
5260 st_collections_group_parts_part_description_rel1_to(void)
5261 {
5262    check_arg_count(1);
5263
5264    {
5265       char *name;
5266       name = parse_str(0);
5267       st_collections_group_parts_part_description_rel1_to_set(name);
5268       free(name);
5269    }
5270 }
5271
5272 /**
5273     @page edcref
5274     @property
5275         to_x
5276     @parameters
5277         [another part's name]
5278     @effect
5279         Causes a corner to be positioned relatively to the X axis of another
5280         part's container. Simply put affects the first parameter of "relative".
5281         Setting to "" will un-set this value for inherited parts.
5282     @endproperty
5283 */
5284 static void
5285 st_collections_group_parts_part_description_rel1_to_x(void)
5286 {
5287    Edje_Part_Collection *pc;
5288
5289    check_arg_count(1);
5290
5291    pc = eina_list_data_get(eina_list_last(edje_collections));
5292
5293    {
5294       char *name;
5295
5296       name = parse_str(0);
5297       data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
5298       free(name);
5299    }
5300 }
5301
5302 /**
5303     @page edcref
5304     @property
5305         to_y
5306     @parameters
5307         [another part's name]
5308     @effect
5309         Causes a corner to be positioned relatively to the Y axis of another
5310         part's container. Simply put, affects the second parameter of
5311         "relative". Setting to "" will un-set this value for inherited parts.
5312     @endproperty
5313 */
5314 static void
5315 st_collections_group_parts_part_description_rel1_to_y(void)
5316 {
5317    Edje_Part_Collection *pc;
5318
5319    check_arg_count(1);
5320
5321    pc = eina_list_data_get(eina_list_last(edje_collections));
5322
5323    {
5324       char *name;
5325
5326       name = parse_str(0);
5327       data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
5328       free(name);
5329    }
5330 }
5331
5332 static void
5333 st_collections_group_parts_part_description_rel2_relative(void)
5334 {
5335    check_arg_count(2);
5336
5337    current_desc->rel2.relative_x = FROM_DOUBLE(parse_float(0));
5338    current_desc->rel2.relative_y = FROM_DOUBLE(parse_float(1));
5339 }
5340
5341 static void
5342 st_collections_group_parts_part_description_rel2_offset(void)
5343 {
5344    check_arg_count(2);
5345
5346    current_desc->rel2.offset_x = parse_int(0);
5347    current_desc->rel2.offset_y = parse_int(1);
5348 }
5349
5350 static void
5351 st_collections_group_parts_part_description_rel2_to_set(const char *name)
5352 {
5353    Edje_Part_Collection *pc;
5354    pc = eina_list_data_get(eina_list_last(edje_collections));
5355    data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
5356    data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
5357 }
5358
5359 static void
5360 st_collections_group_parts_part_description_rel2_to(void)
5361 {
5362    check_arg_count(1);
5363
5364    {
5365       char *name;
5366       name = parse_str(0);
5367       st_collections_group_parts_part_description_rel2_to_set(name);
5368       free(name);
5369    }
5370 }
5371
5372 static void
5373 st_collections_group_parts_part_description_rel2_to_x(void)
5374 {
5375    Edje_Part_Collection *pc;
5376
5377    check_arg_count(1);
5378
5379    pc = eina_list_data_get(eina_list_last(edje_collections));
5380
5381    {
5382       char *name;
5383
5384       name = parse_str(0);
5385       data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
5386       free(name);
5387    }
5388 }
5389
5390 static void
5391 st_collections_group_parts_part_description_rel2_to_y(void)
5392 {
5393    Edje_Part_Collection *pc;
5394
5395    check_arg_count(1);
5396
5397    pc = eina_list_data_get(eina_list_last(edje_collections));
5398
5399    {
5400       char *name;
5401
5402       name = parse_str(0);
5403       data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
5404       free(name);
5405    }
5406 }
5407
5408 /**
5409    @edcsection{description_image,Image state description sub blocks}
5410  */
5411
5412 /**
5413     @page edcref
5414     @block
5415         image
5416     @context
5417         description {
5418             ..
5419             image {
5420                 normal: "filename.ext";
5421                 tween:  "filename2.ext";
5422                 ..
5423                 tween:  "filenameN.ext";
5424                 border:  left right top bottom;
5425                 middle:  0/1/NONE/DEFAULT/SOLID;
5426             }
5427             ..
5428         }
5429     @description
5430     @endblock
5431
5432     @property
5433         normal
5434     @parameters
5435         [image's filename]
5436     @effect
5437         Name of image to be used as previously declared in the  images block.
5438         In an animation, this is the first and last image displayed. It's
5439         required in any image part
5440     @endproperty
5441 */
5442 static void
5443 st_collections_group_parts_part_description_image_normal(void)
5444 {
5445    Edje_Part_Description_Image *ed;
5446
5447    check_arg_count(1);
5448
5449    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5450      {
5451         ERR("parse error %s:%i. "
5452             "image attributes in non-IMAGE part.",
5453             file_in, line - 1);
5454         exit(-1);
5455      }
5456
5457    ed = (Edje_Part_Description_Image*) current_desc;
5458
5459    {
5460       char *name;
5461
5462       name = parse_str(0);
5463       data_queue_image_remove(&(ed->image.id), &(ed->image.set));
5464       data_queue_image_lookup(name, &(ed->image.id), &(ed->image.set));
5465       free(name);
5466    }
5467 }
5468
5469 /**
5470     @page edcref
5471     @property
5472         tween
5473     @parameters
5474         [image's filename]
5475     @effect
5476         Name of an image to be used in an animation loop, an image block can
5477         have none, one or multiple tween declarations. Images are displayed in
5478         the order they are listed, during the transition to the state they are
5479         declared in; the "normal" image is the final state.
5480     @endproperty
5481 */
5482 static void
5483 st_collections_group_parts_part_description_image_tween(void)
5484 {
5485    Edje_Part_Description_Image *ed;
5486
5487    check_arg_count(1);
5488
5489    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5490      {
5491         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5492             file_in, line - 1);
5493         exit(-1);
5494      }
5495
5496    ed = (Edje_Part_Description_Image*) current_desc;
5497
5498    {
5499       char *name;
5500       Edje_Part_Image_Id *iid;
5501
5502       iid = mem_alloc(SZ(Edje_Part_Image_Id));
5503       ed->image.tweens_count++;
5504       ed->image.tweens = realloc(ed->image.tweens,
5505                                  sizeof (Edje_Part_Image_Id*) * ed->image.tweens_count);
5506       ed->image.tweens[ed->image.tweens_count - 1] = iid;
5507       name = parse_str(0);
5508       data_queue_image_remove(&(iid->id), &(iid->set));
5509       data_queue_image_lookup(name, &(iid->id), &(iid->set));
5510       free(name);
5511    }
5512 }
5513
5514 /**
5515     @page edcref
5516     @property
5517         border
5518     @parameters
5519         [left] [right] [top] [bottom]
5520     @effect
5521         If set, the area (in pixels) of each side of the image will be
5522         displayed as a fixed size border, from the side -> inwards, preventing
5523         the corners from being changed on a resize.
5524     @endproperty
5525 */
5526 static void
5527 st_collections_group_parts_part_description_image_border(void)
5528 {
5529    Edje_Part_Description_Image *ed;
5530
5531    check_arg_count(4);
5532
5533    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5534      {
5535         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5536             file_in, line - 1);
5537         exit(-1);
5538      }
5539
5540    ed = (Edje_Part_Description_Image*) current_desc;
5541
5542    ed->image.border.l = parse_int_range(0, 0, 0x7fffffff);
5543    ed->image.border.r = parse_int_range(1, 0, 0x7fffffff);
5544    ed->image.border.t = parse_int_range(2, 0, 0x7fffffff);
5545    ed->image.border.b = parse_int_range(3, 0, 0x7fffffff);
5546 }
5547
5548 /**
5549     @page edcref
5550     @property
5551         middle
5552     @parameters
5553         0, 1, NONE, DEFAULT, SOLID
5554     @effect
5555         If border is set, this value tells Edje if the rest of the
5556         image (not covered by the defined border) will be displayed or not
5557         or be assumed to be solid (without alpha). The default is 1/DEFAULT.
5558     @endproperty
5559 */
5560 static void
5561 st_collections_group_parts_part_description_image_middle(void)
5562 {
5563    Edje_Part_Description_Image *ed;
5564
5565    check_arg_count(1);
5566
5567    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5568      {
5569         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5570             file_in, line - 1);
5571         exit(-1);
5572      }
5573
5574    ed = (Edje_Part_Description_Image*) current_desc;
5575
5576    ed->image.border.no_fill =  parse_enum(0,
5577                                           "1", 0,
5578                                           "DEFAULT", 0,
5579                                           "0", 1,
5580                                           "NONE", 1,
5581                                           "SOLID", 2,
5582                                           NULL);
5583 }
5584
5585 /**
5586     @page edcref
5587     @property
5588         border_scale_by
5589     @parameters
5590         0.0 or bigger (0.0 or 1.0 to turn it off)
5591     @effect
5592         If border scaling is enabled then normally the OUTPUT border sizes
5593         (e.g. if 3 pixels on the left edge are set as a border, then normally
5594         at scale 1.0, those 3 columns will always be the exact 3 columns of
5595         output, or at scale 2.0 they will be 6 columns, or 0.33 they will merge
5596         into a single column). This property multiplies the input scale
5597         factor by this multiplier, allowing the creation of "supersampled"
5598         borders to make much higher resolution outputs possible by always using
5599         the highest resolution artwork and then runtime scaling it down.
5600     @endproperty
5601 */
5602 static void
5603 st_collections_group_parts_part_description_image_border_scale_by(void)
5604 {
5605    Edje_Part_Description_Image *ed;
5606
5607    check_arg_count(1);
5608
5609    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5610      {
5611         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5612             file_in, line - 1);
5613         exit(-1);
5614      }
5615
5616    ed = (Edje_Part_Description_Image*) current_desc;
5617
5618    ed->image.border.scale_by = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
5619 }
5620
5621 /**
5622     @page edcref
5623     @property
5624         border_scale
5625     @parameters
5626         0, 1
5627     @effect
5628         If border is set, this value tells Edje if the border should be scaled
5629         by the object/global edje scale factors
5630     @endproperty
5631 */
5632 static void
5633 st_collections_group_parts_part_description_image_border_scale(void)
5634 {
5635    Edje_Part_Description_Image *ed;
5636
5637    check_arg_count(1);
5638
5639    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5640      {
5641         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5642             file_in, line - 1);
5643         exit(-1);
5644      }
5645
5646    ed = (Edje_Part_Description_Image*) current_desc;
5647
5648    ed->image.border.scale =  parse_enum(0,
5649                                         "0", 0,
5650                                         "1", 1,
5651                                         NULL);
5652 }
5653
5654 /**
5655     @page edcref
5656     @property
5657         scale_hint
5658     @parameters
5659         0, NONE, DYNAMIC, STATIC
5660     @effect
5661         Sets the evas image scale hint letting the engine more effectively save
5662         cached copies of the scaled image if it makes sense
5663     @endproperty
5664 */
5665 static void
5666 st_collections_group_parts_part_description_image_scale_hint(void)
5667 {
5668    Edje_Part_Description_Image *ed;
5669
5670    check_arg_count(1);
5671
5672    if (current_part->type != EDJE_PART_TYPE_IMAGE)
5673      {
5674         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5675             file_in, line - 1);
5676         exit(-1);
5677      }
5678
5679    ed = (Edje_Part_Description_Image*) current_desc;
5680
5681    ed->image.scale_hint =  parse_enum(0,
5682                                       "NONE", EVAS_IMAGE_SCALE_HINT_NONE,
5683                                       "DYNAMIC", EVAS_IMAGE_SCALE_HINT_DYNAMIC,
5684                                       "STATIC", EVAS_IMAGE_SCALE_HINT_STATIC,
5685                                       "0", EVAS_IMAGE_SCALE_HINT_NONE,
5686                                       NULL);
5687 }
5688
5689 /**
5690     @page edcref
5691     @block
5692         fill
5693     @context
5694         description {
5695             ..
5696             fill {
5697                 smooth: 0-1;
5698                 origin {
5699                     relative: X-axis Y-axis;
5700                     offset:   X-axis Y-axis;
5701                 }
5702                 size {
5703                     relative: width  height;
5704                     offset:   width  height;
5705                 }
5706             }
5707             ..
5708         }
5709     @description
5710         The fill method is an optional block that defines the way an IMAGE part
5711         is going to be displayed inside its container.
5712         It can be used for tiling (repeating the image) or displaying only
5713         part of an image. See @ref evas_object_image_fill_set() documentation
5714         for more details.
5715     @endblock
5716
5717     @property
5718         smooth
5719     @parameters
5720         [0 or 1]
5721     @effect
5722         The smooth property takes a boolean value to decide if the image will
5723         be smoothed on scaling (1) or not (0). The default value is 1.
5724     @endproperty
5725 */
5726 static void
5727 st_collections_group_parts_part_description_fill_smooth(void)
5728 {
5729    Edje_Part_Description_Spec_Fill *fill;
5730
5731    check_arg_count(1);
5732
5733    switch (current_part->type)
5734      {
5735       case EDJE_PART_TYPE_IMAGE:
5736         {
5737            Edje_Part_Description_Image *ed;
5738
5739            ed = (Edje_Part_Description_Image*) current_desc;
5740
5741            fill = &ed->image.fill;
5742            break;
5743         }
5744       case EDJE_PART_TYPE_PROXY:
5745         {
5746            Edje_Part_Description_Proxy *ed;
5747
5748            ed = (Edje_Part_Description_Proxy*) current_desc;
5749
5750            fill = &ed->proxy.fill;
5751            break;
5752         }
5753       default:
5754         {
5755            ERR("parse error %s:%i. "
5756                "image and proxy attributes in non-IMAGE, non-PROXY `%s` part (%i).",
5757                file_in, line - 1, current_part->name, current_part->type);
5758            exit(-1);
5759         }
5760      }
5761
5762    fill->smooth = parse_bool(0);
5763 }
5764
5765 /**
5766     @page edcref
5767
5768     @property
5769         spread
5770     @parameters
5771         TODO
5772     @effect
5773         TODO
5774     @endproperty
5775 */
5776 static void
5777 st_collections_group_parts_part_description_fill_spread(void)
5778 {
5779 #if 0
5780    Edje_Part_Collection *pc;
5781    Edje_Part *ep;
5782    Edje_Part_Description_Image *ed;
5783 #endif
5784
5785    check_arg_count(1);
5786
5787    /* XXX this will need to include IMAGES when spread support is added to evas images */
5788    {
5789       ERR("parse error %s:%i. fill.spread not supported yet.",
5790           file_in, line - 1);
5791       exit(-1);
5792    }
5793
5794 #if 0
5795    pc = eina_list_data_get(eina_list_last(edje_collections));
5796
5797    ep = pc->parts[pc->parts_count - 1];
5798
5799    if (ep->type != EDJE_PART_TYPE_IMAGE)
5800      {
5801         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
5802             file_in, line - 1);
5803         exit(-1);
5804      }
5805
5806    ed = (Edje_Part_Description_Image*) ep->default_desc;
5807    if (ep->other.desc_count) ed = (Edje_Part_Description_Image*)  ep->other.desc[ep->other.desc_count - 1];
5808
5809    ed->image.fill.spread = parse_int_range(0, 0, 1);
5810 #endif
5811 }
5812
5813 /**
5814     @page edcref
5815
5816     @property
5817         type
5818     @parameters
5819         TODO
5820     @effect
5821         TODO
5822     @endproperty
5823 */
5824 static void
5825 st_collections_group_parts_part_description_fill_type(void)
5826 {
5827    Edje_Part_Description_Spec_Fill *fill;
5828
5829    check_arg_count(1);
5830
5831    switch (current_part->type)
5832      {
5833       case EDJE_PART_TYPE_IMAGE:
5834         {
5835            Edje_Part_Description_Image *ed;
5836
5837            ed = (Edje_Part_Description_Image*) current_desc;
5838
5839            fill = &ed->image.fill;
5840            break;
5841         }
5842       case EDJE_PART_TYPE_PROXY:
5843         {
5844            Edje_Part_Description_Proxy *ed;
5845
5846            ed = (Edje_Part_Description_Proxy*) current_desc;
5847
5848            fill = &ed->proxy.fill;
5849            break;
5850         }
5851       default:
5852         {
5853            ERR("parse error %s:%i. "
5854                "image and proxy attributes in non-IMAGE, non-PROXY part.",
5855                file_in, line - 1);
5856            exit(-1);
5857         }
5858      }
5859
5860    fill->type = parse_enum(0,
5861                            "SCALE", EDJE_FILL_TYPE_SCALE,
5862                            "TILE", EDJE_FILL_TYPE_TILE,
5863                            NULL);
5864 }
5865
5866 /**
5867     @page edcref
5868     @block
5869         origin
5870     @context
5871         description {
5872             ..
5873             fill {
5874                 ..
5875                 origin {
5876                     relative: 0.0 0.0;
5877                     offset:   0   0;
5878                 }
5879                 ..
5880             }
5881             ..
5882         }
5883     @description
5884         The origin block is used to place the starting point, inside the
5885         displayed element, that will be used to render the tile. By default,
5886         the origin is set at the element's left-up corner.
5887     @endblock
5888
5889     @property
5890         relative
5891     @parameters
5892         [X axis] [Y axis]
5893     @effect
5894         Sets the starting point relatively to displayed element's content.
5895     @endproperty
5896 */
5897 static void
5898 st_collections_group_parts_part_description_fill_origin_relative(void)
5899 {
5900    Edje_Part_Description_Spec_Fill *fill;
5901
5902    check_arg_count(2);
5903
5904    switch (current_part->type)
5905      {
5906       case EDJE_PART_TYPE_IMAGE:
5907         {
5908            Edje_Part_Description_Image *ed;
5909
5910            ed = (Edje_Part_Description_Image*) current_desc;
5911
5912            fill = &ed->image.fill;
5913            break;
5914         }
5915       case EDJE_PART_TYPE_PROXY:
5916         {
5917            Edje_Part_Description_Proxy *ed;
5918
5919            ed = (Edje_Part_Description_Proxy*) current_desc;
5920
5921            fill = &ed->proxy.fill;
5922            break;
5923         }
5924       default:
5925         {
5926            ERR("parse error %s:%i. "
5927                "image and proxy attributes in non-IMAGE, non-PROXY part.",
5928                file_in, line - 1);
5929            exit(-1);
5930         }
5931      }
5932
5933    fill->pos_rel_x = FROM_DOUBLE(parse_float_range(0, -999999999.0, 999999999.0));
5934    fill->pos_rel_y = FROM_DOUBLE(parse_float_range(1, -999999999.0, 999999999.0));
5935 }
5936
5937 /**
5938     @page edcref
5939     @property
5940         offset
5941     @parameters
5942         [X axis] [Y axis]
5943     @effect
5944         Affects the starting point a fixed number of pixels along each axis.
5945     @endproperty
5946 */
5947 static void
5948 st_collections_group_parts_part_description_fill_origin_offset(void)
5949 {
5950    Edje_Part_Description_Spec_Fill *fill;
5951
5952    check_arg_count(2);
5953
5954    switch (current_part->type)
5955      {
5956       case EDJE_PART_TYPE_IMAGE:
5957         {
5958            Edje_Part_Description_Image *ed;
5959
5960            ed = (Edje_Part_Description_Image*) current_desc;
5961
5962            fill = &ed->image.fill;
5963            break;
5964         }
5965       case EDJE_PART_TYPE_PROXY:
5966         {
5967            Edje_Part_Description_Proxy *ed;
5968
5969            ed = (Edje_Part_Description_Proxy*) current_desc;
5970
5971            fill = &ed->proxy.fill;
5972            break;
5973         }
5974       default:
5975         {
5976            ERR("parse error %s:%i. "
5977                "image and proxy attributes in non-IMAGE, non-PROXY part.",
5978                file_in, line - 1);
5979            exit(-1);
5980         }
5981      }
5982
5983    fill->pos_abs_x = parse_int(0);
5984    fill->pos_abs_y = parse_int(1);
5985 }
5986
5987 /**
5988     @page edcref
5989     @block
5990         size
5991     @context
5992         description {
5993             ..
5994             fill {
5995                 ..
5996                 size {
5997                     relative: 1.0 1.0;
5998                     offset:  -1  -1;
5999                 }
6000                 ..
6001             }
6002             ..
6003         }
6004     @description
6005         The size block defines the tile size of the content that will be
6006         displayed.
6007     @endblock
6008
6009     @property
6010         relative
6011     @parameters
6012         [width] [height]
6013     @effect
6014         Takes a pair of decimal values that represent the percentual value
6015         of the original size of the element. For example, "0.5 0.5" represents
6016         half the size, while "2.0 2.0" represents the double. The default
6017         value is "1.0 1.0".
6018     @endproperty
6019 */
6020 static void
6021 st_collections_group_parts_part_description_fill_size_relative(void)
6022 {
6023    Edje_Part_Description_Spec_Fill *fill;
6024
6025    check_arg_count(2);
6026
6027    switch (current_part->type)
6028      {
6029       case EDJE_PART_TYPE_IMAGE:
6030         {
6031            Edje_Part_Description_Image *ed;
6032
6033            ed = (Edje_Part_Description_Image*) current_desc;
6034
6035            fill = &ed->image.fill;
6036            break;
6037         }
6038       case EDJE_PART_TYPE_PROXY:
6039         {
6040            Edje_Part_Description_Proxy *ed;
6041
6042            ed = (Edje_Part_Description_Proxy*) current_desc;
6043
6044            fill = &ed->proxy.fill;
6045            break;
6046         }
6047       default:
6048         {
6049            ERR("parse error %s:%i. "
6050                "image and proxy attributes in non-IMAGE, non-PROXY part.",
6051                file_in, line - 1);
6052            exit(-1);
6053         }
6054      }
6055
6056    fill->rel_x = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
6057    fill->rel_y = FROM_DOUBLE(parse_float_range(1, 0.0, 999999999.0));
6058 }
6059
6060 /**
6061     @page edcref
6062     @property
6063         offset
6064     @parameters
6065         [X axis] [Y axis]
6066     @effect
6067         Affects the size of the tile a fixed number of pixels along each axis.
6068     @endproperty
6069 */
6070 static void
6071 st_collections_group_parts_part_description_fill_size_offset(void)
6072 {
6073    Edje_Part_Description_Spec_Fill *fill;
6074
6075    check_arg_count(2);
6076
6077    switch (current_part->type)
6078      {
6079       case EDJE_PART_TYPE_IMAGE:
6080         {
6081            Edje_Part_Description_Image *ed;
6082
6083            ed = (Edje_Part_Description_Image*) current_desc;
6084
6085            fill = &ed->image.fill;
6086            break;
6087         }
6088       case EDJE_PART_TYPE_PROXY:
6089         {
6090            Edje_Part_Description_Proxy *ed;
6091
6092            ed = (Edje_Part_Description_Proxy*) current_desc;
6093
6094            fill = &ed->proxy.fill;
6095            break;
6096         }
6097       default:
6098         {
6099            ERR("parse error %s:%i. "
6100                "image and proxy attributes in non-IMAGE, non-PROXY part.",
6101                file_in, line - 1);
6102            exit(-1);
6103         }
6104      }
6105
6106    fill->abs_x = parse_int(0);
6107    fill->abs_y = parse_int(1);
6108 }
6109
6110
6111 /**
6112    @edcsection{description_text,Text state description sub blocks}
6113  */
6114
6115 /**
6116     @page edcref
6117
6118     @block
6119         text
6120     @context
6121         part {
6122             description {
6123                 ..
6124                 text {
6125                     text:        "some string of text to display";
6126                     font:        "font_name";
6127                     size:         SIZE;
6128                     text_class:  "class_name";
6129                     fit:          horizontal vertical;
6130                     min:          horizontal vertical;
6131                     max:          horizontal vertical;
6132                     align:        X-axis     Y-axis;
6133                     source:      "part_name";
6134                     text_source: "text_part_name";
6135                     ellipsis:     0.0-1.0;
6136                     style:       "stylename";
6137                 }
6138                 ..
6139             }
6140         }
6141     @description
6142     @endblock
6143
6144     @property
6145         text
6146     @parameters
6147         [a string of text, or nothing]
6148     @effect
6149         Sets the default content of a text part, normally the application is
6150         the one changing its value.
6151     @endproperty
6152 */
6153 static void
6154 st_collections_group_parts_part_description_text_text(void)
6155 {
6156    Edje_Part_Description_Text *ed;
6157    char *str = NULL;
6158    int i;
6159
6160    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6161        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6162      {
6163         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6164             file_in, line - 1);
6165         exit(-1);
6166      }
6167
6168    ed = (Edje_Part_Description_Text*) current_desc;
6169
6170    for (i = 0; ;i++)
6171      {
6172         char *s;
6173
6174         if (!is_param(i)) break;
6175         s = parse_str(i);
6176         if (!str) str = s;
6177         else
6178           {
6179              str = realloc(str, strlen(str) + strlen(s) + 1);
6180              strcat(str, s);
6181              free(s);
6182           }
6183      }
6184    ed->text.text.str = str;
6185 }
6186
6187 /**
6188     @page edcref
6189
6190     @property
6191         text_class
6192     @parameters
6193         [text class name]
6194     @effect
6195         Similar to color_class, this is the name used by the application
6196         to alter the font family and size at runtime.
6197     @endproperty
6198 */
6199 static void
6200 st_collections_group_parts_part_description_text_text_class(void)
6201 {
6202    Edje_Part_Description_Text *ed;
6203
6204    check_arg_count(1);
6205
6206    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6207        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6208      {
6209         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6210             file_in, line - 1);
6211         exit(-1);
6212      }
6213
6214    ed = (Edje_Part_Description_Text*) current_desc;
6215
6216    ed->text.text_class = parse_str(0);
6217 }
6218
6219 /**
6220     @page edcref
6221
6222     @property
6223         font
6224     @parameters
6225         [font alias]
6226     @effect
6227         This sets the font family to one of the aliases set up in the "fonts"
6228         block. Can be overrided by the application.
6229     @endproperty
6230 */
6231 static void
6232 st_collections_group_parts_part_description_text_font(void)
6233 {
6234    Edje_Part_Description_Text *ed;
6235
6236    check_arg_count(1);
6237
6238    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6239        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6240      {
6241         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6242             file_in, line - 1);
6243         exit(-1);
6244      }
6245
6246    ed = (Edje_Part_Description_Text*) current_desc;
6247
6248    ed->text.font.str = parse_str(0);
6249 }
6250
6251 /**
6252     @page edcref
6253
6254     @property
6255         style
6256     @parameters
6257         [the style name]
6258     @effect
6259         Causes the part to use the default style and tags defined in the
6260         "style" block with the specified name.
6261     @endproperty
6262 */
6263 static void
6264 st_collections_group_parts_part_description_text_style(void)
6265 {
6266    Edje_Part_Description_Text *ed;
6267
6268    check_arg_count(1);
6269
6270    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6271        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6272      {
6273         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6274             file_in, line - 1);
6275         exit(-1);
6276      }
6277
6278    ed = (Edje_Part_Description_Text*) current_desc;
6279
6280    ed->text.style.str = parse_str(0);
6281 }
6282
6283 /**
6284     @page edcref
6285
6286     @property
6287         repch
6288     @parameters
6289         [the replacement character string]
6290     @effect
6291         If this is a textblock and is in PASSWORD mode this string is used
6292         to replace every character to hide the details of the entry. Normally
6293         you would use a "*", but you can use anything you like.
6294     @endproperty
6295 */
6296 static void
6297 st_collections_group_parts_part_description_text_repch(void)
6298 {
6299    Edje_Part_Description_Text *ed;
6300
6301    check_arg_count(1);
6302
6303    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6304        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6305      {
6306         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6307             file_in, line - 1);
6308         exit(-1);
6309      }
6310
6311    ed = (Edje_Part_Description_Text*) current_desc;
6312
6313    ed->text.repch.str = parse_str(0);
6314 }
6315
6316 /**
6317     @page edcref
6318
6319     @property
6320         size
6321     @parameters
6322         [font size in points (pt)]
6323     @effect
6324         Sets the default font size for the text part. Can be overrided by the
6325         application.
6326     @endproperty
6327 */
6328 static void
6329 st_collections_group_parts_part_description_text_size(void)
6330 {
6331    Edje_Part_Description_Text *ed;
6332
6333    check_arg_count(1);
6334
6335    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6336        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6337      {
6338         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6339             file_in, line - 1);
6340         exit(-1);
6341      }
6342
6343    ed = (Edje_Part_Description_Text*)current_desc;
6344
6345    ed->text.size = parse_int_range(0, 0, 255);
6346 }
6347
6348 /**
6349     @page edcref
6350
6351     @property
6352         size_range
6353     @parameters
6354         [font min size in points (pt)] [font max size in points (pt)]
6355     @effect
6356         Sets the allowed font size for the text part. Setting min and max to 0
6357         means we won't restrict the sizing (default).
6358     @endproperty
6359     @since 1.1.0
6360 */
6361 static void
6362 st_collections_group_parts_part_description_text_size_range(void)
6363 {
6364    Edje_Part_Description_Text *ed;
6365
6366    check_arg_count(2);
6367
6368    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6369        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6370      {
6371         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6372             file_in, line - 1);
6373         exit(-1);
6374      }
6375
6376    ed = (Edje_Part_Description_Text*) current_desc;
6377
6378    ed->text.size_range_min = parse_int_range(0, 0, 255);
6379    ed->text.size_range_max = parse_int_range(1, 0, 255);
6380    if (ed->text.size_range_min > ed->text.size_range_max)
6381      {
6382         ERR("parse error %s:%i. min size is bigger than max size.",
6383             file_in, line - 1);
6384         exit(-1);
6385      }
6386 }
6387
6388 /**
6389     @page edcref
6390
6391     @property
6392         fit
6393     @parameters
6394         [horizontal] [vertical]
6395     @effect
6396         When any of the parameters is set to 1 edje will resize the text for it
6397         to fit in it's container. Both are disabled by default.
6398     @endproperty
6399 */
6400 static void
6401 st_collections_group_parts_part_description_text_fit(void)
6402 {
6403    Edje_Part_Description_Text *ed;
6404
6405    check_arg_count(2);
6406
6407    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6408        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6409      {
6410         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6411             file_in, line - 1);
6412         exit(-1);
6413      }
6414
6415    ed = (Edje_Part_Description_Text*) current_desc;
6416
6417    ed->text.fit_x = parse_bool(0);
6418    ed->text.fit_y = parse_bool(1);
6419 }
6420
6421 /**
6422     @page edcref
6423
6424     @property
6425         min
6426     @parameters
6427         [horizontal] [vertical]
6428     @effect
6429         When any of the parameters is enabled (1) it forces the minimum size of
6430         the container to be equal to the minimum size of the text. The default
6431         value is "0 0".
6432     @endproperty
6433 */
6434 static void
6435 st_collections_group_parts_part_description_text_min(void)
6436 {
6437    Edje_Part_Description_Text *ed;
6438
6439    check_arg_count(2);
6440
6441    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6442        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6443      {
6444         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6445             file_in, line - 1);
6446         exit(-1);
6447      }
6448
6449    ed = (Edje_Part_Description_Text*)current_desc;
6450
6451    ed->text.min_x = parse_bool(0);
6452    ed->text.min_y = parse_bool(1);
6453 }
6454
6455 /**
6456     @page edcref
6457
6458     @property
6459         max
6460     @parameters
6461         [horizontal] [vertical]
6462     @effect
6463         When any of the parameters is enabled (1) it forces the maximum size of
6464         the container to be equal to the maximum size of the text. The default
6465         value is "0 0".
6466     @endproperty
6467 */
6468 static void
6469 st_collections_group_parts_part_description_text_max(void)
6470 {
6471    Edje_Part_Description_Text *ed;
6472
6473    check_arg_count(2);
6474
6475    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6476        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6477      {
6478         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6479             file_in, line - 1);
6480         exit(-1);
6481      }
6482
6483    ed = (Edje_Part_Description_Text*) current_desc;
6484
6485    ed->text.max_x = parse_bool(0);
6486    ed->text.max_y = parse_bool(1);
6487 }
6488
6489 /**
6490     @page edcref
6491
6492     @property
6493         align
6494     @parameters
6495         [horizontal] [vertical]
6496     @effect
6497         Change the position of the point of balance inside the container. The
6498         default value is 0.5 0.5.
6499     @endproperty
6500 */
6501 static void
6502 st_collections_group_parts_part_description_text_align(void)
6503 {
6504    Edje_Part_Description_Text *ed;
6505
6506    check_arg_count(2);
6507
6508    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6509        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6510      {
6511         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6512             file_in, line - 1);
6513         exit(-1);
6514      }
6515
6516    ed = (Edje_Part_Description_Text*) current_desc;
6517
6518    ed->text.align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
6519    ed->text.align.y = FROM_DOUBLE(parse_float_range(1, 0.0, 1.0));
6520 }
6521
6522 /**
6523     @page edcref
6524
6525     @property
6526         source
6527     @parameters
6528         [another TEXT part's name]
6529     @effect
6530         Causes the part to use the text properties (like font and size) of
6531         another part and update them as they change.
6532     @endproperty
6533 */
6534 static void
6535 st_collections_group_parts_part_description_text_source(void)
6536 {
6537    Edje_Part_Collection *pc;
6538    Edje_Part_Description_Text *ed;
6539
6540    check_arg_count(1);
6541
6542    pc = eina_list_data_get(eina_list_last(edje_collections));
6543
6544    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6545        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6546      {
6547         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6548             file_in, line - 1);
6549         exit(-1);
6550      }
6551
6552    ed = (Edje_Part_Description_Text*) current_desc;
6553
6554    {
6555       char *name;
6556
6557       name = parse_str(0);
6558       data_queue_part_lookup(pc, name, &(ed->text.id_source));
6559       free(name);
6560    }
6561 }
6562
6563 /**
6564     @page edcref
6565
6566     @property
6567         text_source
6568     @parameters
6569         [another TEXT part's name]
6570     @effect
6571         Causes the part to display the text content of another part and update
6572         them as they change.
6573     @endproperty
6574 */
6575 static void
6576 st_collections_group_parts_part_description_text_text_source(void)
6577 {
6578    Edje_Part_Collection *pc;
6579    Edje_Part_Description_Text *ed;
6580
6581    check_arg_count(1);
6582
6583    pc = eina_list_data_get(eina_list_last(edje_collections));
6584
6585    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6586        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6587      {
6588         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6589             file_in, line - 1);
6590         exit(-1);
6591      }
6592
6593    ed = (Edje_Part_Description_Text*) current_desc;
6594
6595    {
6596       char *name;
6597
6598       name = parse_str(0);
6599       data_queue_part_lookup(pc, name, &(ed->text.id_text_source));
6600       free(name);
6601    }
6602 }
6603
6604 /**
6605     @page edcref
6606
6607     @property
6608         ellipsis
6609     @parameters
6610         [point of balance]
6611     @effect
6612         Used to balance the text in a relative point from 0.0 to 1.0, this
6613         point is the last section of the string to be cut out in case of a
6614         resize that is smaller than the text itself. The default value is 0.0.
6615     @endproperty
6616 */
6617 static void
6618 st_collections_group_parts_part_description_text_elipsis(void)
6619 {
6620    Edje_Part_Description_Text *ed;
6621
6622    check_arg_count(1);
6623
6624    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
6625        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
6626      {
6627         ERR("parse error %s:%i. text attributes in non-TEXT part.",
6628             file_in, line - 1);
6629         exit(-1);
6630      }
6631
6632    ed = (Edje_Part_Description_Text*) current_desc;
6633
6634    ed->text.elipsis = parse_float_range(0, 0.0, 1.0);
6635 }
6636
6637
6638 /**
6639    @edcsection{description_box,Box state description sub blocks}
6640  */
6641
6642 /**
6643     @page edcref
6644
6645     @block
6646         box
6647     @context
6648         part {
6649             description {
6650                 ..
6651                 box {
6652                     layout: "vertical";
6653                     padding: 0 2;
6654                     align: 0.5 0.5;
6655                     min: 0 0;
6656                 }
6657                 ..
6658             }
6659         }
6660     @description
6661         A box block can contain other objects and display them in different
6662         layouts, any of the predefined set, or a custom one, set by the
6663         application.
6664     @endblock
6665
6666     @property
6667         layout
6668     @parameters
6669         [primary layout] [fallback layout]
6670     @effect
6671         Sets the layout for the box:
6672             @li horizontal (default)
6673             @li vertical
6674             @li horizontal_homogeneous
6675             @li vertical_homogeneous
6676             @li horizontal_max (homogeneous to the max sized child)
6677             @li vertical_max
6678             @li horizontal_flow
6679             @li vertical_flow
6680             @li stack
6681             @li some_other_custom_layout_set_by_the_application
6682         You could set a custom layout as fallback, it makes very
6683         very little sense though, and if that one fails, it will
6684         default to horizontal.
6685     @endproperty
6686
6687     @property
6688         align
6689     @parameters
6690         [horizontal] [vertical]
6691     @effect
6692         Change the position of the point of balance inside the container. The
6693         default value is 0.5 0.5.
6694     @endproperty
6695
6696     @property
6697         padding
6698     @parameters
6699         [horizontal] [vertical]
6700     @effect
6701         Sets the space between cells in pixels. Defaults to 0 0.
6702     @endproperty
6703
6704     @property
6705         min
6706     @parameters
6707         [horizontal] [vertical]
6708     @effect
6709         When any of the parameters is enabled (1) it forces the minimum size of
6710         the box to be equal to the minimum size of the items. The default
6711         value is "0 0".
6712     @endproperty
6713 */
6714 static void st_collections_group_parts_part_description_box_layout(void)
6715 {
6716    Edje_Part_Description_Box *ed;
6717
6718    check_min_arg_count(1);
6719
6720    if (current_part->type != EDJE_PART_TYPE_BOX)
6721      {
6722         ERR("parse error %s:%i. box attributes in non-BOX part.",
6723             file_in, line - 1);
6724         exit(-1);
6725      }
6726
6727    ed = (Edje_Part_Description_Box*) current_desc;
6728
6729    ed->box.layout = parse_str(0);
6730    if (is_param(1))
6731      ed->box.alt_layout = parse_str(1);
6732 }
6733
6734 static void st_collections_group_parts_part_description_box_align(void)
6735 {
6736    Edje_Part_Description_Box *ed;
6737
6738    check_arg_count(2);
6739
6740    if (current_part->type != EDJE_PART_TYPE_BOX)
6741      {
6742         ERR("parse error %s:%i. box attributes in non-BOX part.",
6743             file_in, line - 1);
6744         exit(-1);
6745      }
6746
6747    ed = (Edje_Part_Description_Box*) current_desc;
6748
6749    ed->box.align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
6750    ed->box.align.y = FROM_DOUBLE(parse_float_range(1, -1.0, 1.0));
6751 }
6752
6753 static void st_collections_group_parts_part_description_box_padding(void)
6754 {
6755    Edje_Part_Description_Box *ed;
6756
6757    check_arg_count(2);
6758
6759    if (current_part->type != EDJE_PART_TYPE_BOX)
6760      {
6761         ERR("parse error %s:%i. box attributes in non-BOX part.",
6762             file_in, line - 1);
6763         exit(-1);
6764      }
6765
6766    ed = (Edje_Part_Description_Box*) current_desc;
6767
6768    ed->box.padding.x = parse_int_range(0, 0, 0x7fffffff);
6769    ed->box.padding.y = parse_int_range(1, 0, 0x7fffffff);
6770 }
6771
6772 static void
6773 st_collections_group_parts_part_description_box_min(void)
6774 {
6775    Edje_Part_Description_Box *ed;
6776
6777    check_arg_count(2);
6778
6779    if (current_part->type != EDJE_PART_TYPE_BOX)
6780      {
6781         ERR("parse error %s:%i. box attributes in non-BOX part.",
6782             file_in, line - 1);
6783         exit(-1);
6784      }
6785
6786    ed = (Edje_Part_Description_Box*) current_desc;
6787
6788    ed->box.min.h = parse_bool(0);
6789    ed->box.min.v = parse_bool(1);
6790 }
6791
6792
6793 /**
6794    @edcsection{description_table,Table state description sub blocks}
6795  */
6796
6797 /**
6798     @page edcref
6799
6800     @block
6801         table
6802     @context
6803         part {
6804             description {
6805                 ..
6806                 table {
6807                     homogeneous: TABLE;
6808                     padding: 0 2;
6809                     align: 0.5 0.5;
6810                     min: 0 0;
6811                 }
6812                 ..
6813             }
6814         }
6815     @description
6816         A table block can contain other objects packed in multiple columns
6817         and rows, and each item can span across more than one column and/or
6818         row.
6819     @endblock
6820
6821     @property
6822         homogeneous
6823     @parameters
6824         [homogeneous mode]
6825     @effect
6826         Sets the homogeneous mode for the table:
6827             @li NONE (default)
6828             @li TABLE
6829             @li ITEM
6830     @endproperty
6831
6832     @property
6833         align
6834     @parameters
6835         [horizontal] [vertical]
6836     @effect
6837         Change the position of the point of balance inside the container. The
6838         default value is 0.5 0.5.
6839     @endproperty
6840
6841     @property
6842         padding
6843     @parameters
6844         [horizontal] [vertical]
6845     @effect
6846         Sets the space between cells in pixels. Defaults to 0 0.
6847     @endproperty
6848
6849     @property
6850         min
6851     @parameters
6852         [horizontal] [vertical]
6853     @effect
6854         When any of the parameters is enabled (1) it forces the minimum size of
6855         the table to be equal to the minimum size of the items. The default
6856         value is "0 0".
6857     @endproperty
6858 */
6859 static void st_collections_group_parts_part_description_table_homogeneous(void)
6860 {
6861    Edje_Part_Description_Table *ed;
6862
6863    check_min_arg_count(1);
6864
6865    if (current_part->type != EDJE_PART_TYPE_TABLE)
6866      {
6867         ERR("parse error %s:%i. table attributes in non-TABLE part.",
6868             file_in, line - 1);
6869         exit(-1);
6870      }
6871
6872    ed = (Edje_Part_Description_Table*) current_desc;
6873
6874    ed->table.homogeneous = parse_enum(0,
6875                                      "NONE", EDJE_OBJECT_TABLE_HOMOGENEOUS_NONE,
6876                                      "TABLE", EDJE_OBJECT_TABLE_HOMOGENEOUS_TABLE,
6877                                      "ITEM", EDJE_OBJECT_TABLE_HOMOGENEOUS_ITEM,
6878                                      NULL);
6879 }
6880
6881 static void st_collections_group_parts_part_description_table_align(void)
6882 {
6883    Edje_Part_Description_Table *ed;
6884
6885    check_arg_count(2);
6886
6887    if (current_part->type != EDJE_PART_TYPE_TABLE)
6888      {
6889         ERR("parse error %s:%i. table attributes in non-TABLE part.",
6890             file_in, line - 1);
6891         exit(-1);
6892      }
6893
6894    ed = (Edje_Part_Description_Table*) current_desc;
6895
6896    ed->table.align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
6897    ed->table.align.y = FROM_DOUBLE(parse_float_range(1, -1.0, 1.0));
6898 }
6899
6900 static void st_collections_group_parts_part_description_table_padding(void)
6901 {
6902    Edje_Part_Description_Table *ed;
6903
6904    check_arg_count(2);
6905
6906    if (current_part->type != EDJE_PART_TYPE_TABLE)
6907      {
6908         ERR("parse error %s:%i. table attributes in non-TABLE part.",
6909             file_in, line - 1);
6910         exit(-1);
6911      }
6912
6913    ed = (Edje_Part_Description_Table*) current_desc;
6914
6915    ed->table.padding.x = parse_int_range(0, 0, 0x7fffffff);
6916    ed->table.padding.y = parse_int_range(1, 0, 0x7fffffff);
6917 }
6918
6919 static void
6920 st_collections_group_parts_part_description_table_min(void)
6921 {
6922    Edje_Part_Description_Table *ed;
6923
6924    check_arg_count(2);
6925
6926    if (current_part->type != EDJE_PART_TYPE_TABLE)
6927      {
6928         ERR("parse error %s:%i. box attributes in non-TABLE part.",
6929             file_in, line - 1);
6930         exit(-1);
6931      }
6932
6933    ed = (Edje_Part_Description_Table*) current_desc;
6934
6935    ed->table.min.h = parse_bool(0);
6936    ed->table.min.v = parse_bool(1);
6937 }
6938
6939 /**
6940    @edcsection{description_map,Map state description sub blocks}
6941  */
6942
6943 /**
6944     @page edcref
6945     @block
6946         map
6947     @context
6948     description {
6949         ..
6950         map {
6951             perspective: "name";
6952             light: "name";
6953             on: 1;
6954             smooth: 1;
6955             perspective_on: 1;
6956             backface_cull: 1;
6957             alpha: 1;
6958             
6959             rotation {
6960                 ..
6961             }
6962         }
6963         ..
6964     }
6965     
6966     @description
6967     @endblock
6968     
6969     @property
6970         perspective
6971     @parameters
6972         [another part's name]
6973     @effect
6974         This sets the part that is used as the "perspective point" for giving
6975         a part a "3d look". The perspective point should have a perspective
6976         section that provides zplane and focal properties. The center of this
6977         part will be used as the focal point, so size, color and visibility
6978         etc. are not relevant just center point, zplane and focal are used.
6979         This also implicitly enables perspective transforms (see the on
6980         parameter for the map section).
6981     @endproperty
6982 */
6983 static void
6984 st_collections_group_parts_part_description_map_perspective(void)
6985 {
6986    Edje_Part_Collection *pc;
6987
6988    check_arg_count(1);
6989
6990    pc = eina_list_data_get(eina_list_last(edje_collections));
6991
6992    {
6993       char *name;
6994
6995       name = parse_str(0);
6996       data_queue_part_lookup(pc, name, &(current_desc->map.id_persp));
6997       free(name);
6998    }
6999
7000    current_desc->map.persp_on = 1;
7001 }
7002
7003 /**
7004     @page edcref
7005     @property
7006         light
7007     @parameters
7008         [another part's name]
7009     @effect
7010         This sets the part that is used as the "light" for calculating the
7011         brightness (based on how directly the part's surface is facing the
7012         light source point). Like the perspective point part, the center point
7013         is used and zplane is used for the z position (0 being the zero-plane
7014         where all 2D objects normally live) and positive values being further
7015         away into the distance. The light part color is used as the light
7016         color (alpha not used for light color). The color2 color is used for
7017         the ambient lighting when calculating brightness (alpha also not
7018         used).
7019     @endproperty
7020 */
7021 static void
7022 st_collections_group_parts_part_description_map_light(void)
7023 {
7024    Edje_Part_Collection *pc;
7025
7026    check_arg_count(1);
7027
7028    pc = eina_list_data_get(eina_list_last(edje_collections));
7029
7030    {
7031       char *name;
7032
7033       name = parse_str(0);
7034       data_queue_part_lookup(pc, name, &(current_desc->map.id_light));
7035       free(name);
7036    }
7037 }
7038
7039 /**
7040     @page edcref
7041     @property
7042         on
7043     @parameters
7044         [1 or 0]
7045     @effect
7046         This enables mapping for the part. Default is 0.
7047     @endproperty
7048 */
7049 static void
7050 st_collections_group_parts_part_description_map_on(void)
7051 {
7052    check_arg_count(1);
7053
7054    current_desc->map.on = parse_bool(0);
7055 }
7056
7057 /**
7058     @page edcref
7059     @property
7060         smooth
7061     @parameters
7062         [1 or 0]
7063     @effect
7064         This enable smooth map rendering. This may be linear interpolation,
7065         anisotropic filtering or anything the engine decides is "smooth".
7066         This is a best-effort hint and may not produce precisely the same
7067         results in all engines and situations. Default is 1
7068     @endproperty
7069 */
7070 static void
7071 st_collections_group_parts_part_description_map_smooth(void)
7072 {
7073    check_arg_count(1);
7074
7075    current_desc->map.smooth = parse_bool(0);
7076 }
7077
7078 /**
7079     @page edcref
7080     @property
7081         alpha
7082     @parameters
7083         [1 or 0]
7084     @effect
7085         This enable alpha channel when map rendering. Default is 1.
7086     @endproperty
7087 */
7088 static void
7089 st_collections_group_parts_part_description_map_alpha(void)
7090 {
7091    check_arg_count(1);
7092
7093    current_desc->map.alpha = parse_bool(0);
7094 }
7095
7096 /**
7097     @page edcref
7098     @property
7099         backface_cull
7100     @parameters
7101         [1 or 0]
7102     @effect
7103         This enables backface culling (when the rotated part that normally
7104         faces the camera is facing away after being rotated etc.). This means
7105         that the object will be hidden when "backface culled".
7106     @endproperty
7107 */
7108 static void
7109 st_collections_group_parts_part_description_map_backface_cull(void)
7110 {
7111    check_arg_count(1);
7112
7113    current_desc->map.backcull = parse_bool(0);
7114 }
7115
7116 /**
7117     @page edcref
7118     @property
7119         perspective_on
7120     @parameters
7121        [1 or 0]
7122     @effect
7123         Enable perspective when rotating even without a perspective point object.
7124         This would use perspective set for the object itself or for the
7125         canvas as a whole as the global perspective with 
7126         edje_perspective_set() and edje_perspective_global_set().
7127     @endproperty
7128 */
7129 static void
7130 st_collections_group_parts_part_description_map_perspective_on(void)
7131 {
7132    check_arg_count(1);
7133
7134    current_desc->map.persp_on = parse_bool(0);
7135 }
7136 /**
7137     @page edcref
7138     @block
7139         rotation
7140     @context
7141     map {
7142         ..
7143         rotation {
7144             center: "name";
7145             x: 45.0;
7146             y: 45.0;
7147             z: 45.0;
7148         }
7149         ..
7150     }
7151     @description
7152         Rotates the part, optionally with the center on another part.
7153     @endblock
7154     
7155     @property
7156         center
7157     @parameters
7158         [another part's name]
7159     @effect
7160         This sets the part that is used as the center of rotation when
7161         rotating the part with this description. The part's center point
7162         is used as the rotation center when applying rotation around the
7163         x, y and z axes. If no center is given, the parts original center
7164         itself is used for the rotation center.
7165     @endproperty
7166 */
7167 static void
7168 st_collections_group_parts_part_description_map_rotation_center(void)
7169 {
7170    Edje_Part_Collection *pc;
7171
7172    check_arg_count(1);
7173
7174    pc = eina_list_data_get(eina_list_last(edje_collections));
7175
7176    {
7177       char *name;
7178
7179       name = parse_str(0);
7180       data_queue_part_lookup(pc, name, &(current_desc->map.rot.id_center));
7181       free(name);
7182    }
7183 }
7184
7185 /**
7186     @page edcref
7187     @property
7188         x
7189     @parameters
7190         [X degrees]
7191     @effect
7192         This sets the rotation around the x axis of the part considering
7193         the center set. In degrees.
7194     @endproperty
7195 */
7196 static void
7197 st_collections_group_parts_part_description_map_rotation_x(void)
7198 {
7199    check_arg_count(1);
7200
7201    current_desc->map.rot.x = FROM_DOUBLE(parse_float(0));
7202 }
7203
7204 /**
7205     @page edcref
7206     @property
7207         y
7208     @parameters
7209         [Y degrees]
7210     @effect
7211         This sets the rotation around the y axis of the part considering
7212         the center set. In degrees.
7213     @endproperty
7214 */
7215 static void
7216 st_collections_group_parts_part_description_map_rotation_y(void)
7217 {
7218    check_arg_count(1);
7219
7220    current_desc->map.rot.y = FROM_DOUBLE(parse_float(0));
7221 }
7222
7223 /**
7224     @page edcref
7225     @property
7226         z
7227     @parameters
7228         [Z degrees]
7229     @effect
7230         This sets the rotation around the z axis of the part considering
7231         the center set. In degrees.
7232     @endproperty
7233 */
7234 static void
7235 st_collections_group_parts_part_description_map_rotation_z(void)
7236 {
7237    check_arg_count(1);
7238
7239    current_desc->map.rot.z = FROM_DOUBLE(parse_float(0));
7240 }
7241
7242 /**
7243     @page edcref
7244     @block
7245         perspective
7246     @context
7247     description {
7248         ..
7249         perspective {
7250             zplane: 0;
7251             focal: 1000;
7252         }
7253         ..
7254     }
7255     @description
7256         Adds focal and plane perspective to the part. Active if perspective_on is true.
7257         Must be provided if the part is being used by other part as it's perspective target.
7258     @endblock
7259     
7260     @property
7261         zplane
7262     @parameters
7263         [unscaled Z value]
7264     @effect
7265         This sets the z value that will not be scaled. Normally this is 0 as
7266         that is the z distance that all objects are at normally.
7267     @endproperty
7268 */
7269 static void
7270 st_collections_group_parts_part_description_perspective_zplane(void)
7271 {
7272    check_arg_count(1);
7273
7274    current_desc->persp.zplane = parse_int(0);
7275 }
7276
7277
7278 /**
7279     @page edcref
7280     @property
7281         focal
7282     @parameters
7283         [distance]
7284     @effect
7285         This sets the distance from the focal z plane (zplane) and the
7286         camera - i.e. very much equating to focal length of the camera
7287     @endproperty
7288 */
7289 static void
7290 st_collections_group_parts_part_description_perspective_focal(void)
7291 {
7292    check_arg_count(1);
7293
7294    current_desc->persp.focal = parse_int_range(0, 1, 0x7fffffff);
7295 }
7296
7297
7298 /**
7299    @edcsection{description_params,Params state description sub blocks}
7300  */
7301
7302 /**
7303     @page edcref
7304     @block
7305         params
7306     @context
7307     description {
7308         ..
7309         params {
7310             int: "name" 0;
7311             double: "other_name" 0.0;
7312             string: "another_name" "some text";
7313             bool: "name" 1;
7314             choice: "some_name" "value";
7315         }
7316         ..
7317     }
7318     @description
7319         Set parameters for EXTERNAL parts. The value overwrites previous
7320         definitions with the same name.
7321     @endblock
7322 */
7323 static void
7324 _st_collections_group_parts_part_description_params(Edje_External_Param_Type type)
7325 {
7326    Edje_Part_Description_External *ed;
7327    Edje_External_Param *param;
7328    Eina_List *l;
7329    const char *name;
7330    int found = 0;
7331
7332    check_arg_count(2);
7333
7334    if (current_part->type != EDJE_PART_TYPE_EXTERNAL)
7335      {
7336         ERR("parse error %s:%i. params in non-EXTERNAL part.",
7337             file_in, line - 1);
7338         exit(-1);
7339      }
7340
7341    ed = (Edje_Part_Description_External*) current_desc;
7342
7343    name = parse_str(0);
7344
7345    /* if a param with this name already exists, overwrite it */
7346    EINA_LIST_FOREACH(ed->external_params, l, param)
7347      {
7348         if (!strcmp(param->name, name))
7349           {
7350              found = 1;
7351              break;
7352           }
7353      }
7354
7355    if (!found)
7356      {
7357         param = mem_alloc(SZ(Edje_External_Param));
7358         param->name = name;
7359      }
7360
7361    param->type = type;
7362    param->i = 0;
7363    param->d = 0;
7364    param->s = NULL;
7365
7366    switch (type)
7367      {
7368       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
7369       case EDJE_EXTERNAL_PARAM_TYPE_INT:
7370          param->i = parse_int(1);
7371          break;
7372       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
7373          param->d = parse_float(1);
7374          break;
7375       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
7376       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
7377          param->s = parse_str(1);
7378          break;
7379       default:
7380          ERR("parse error %s:%i. Invalid param type.",
7381              file_in, line - 1);
7382          break;
7383      }
7384
7385    if (!found)
7386      ed->external_params = eina_list_append(ed->external_params, param);
7387 }
7388
7389 /**
7390     @page edcref
7391     @property
7392         int
7393     @parameters
7394         [param_name] [int_value]
7395     @effect
7396         Adds an integer parameter for an external object
7397     @endproperty
7398 */
7399 static void
7400 st_collections_group_parts_part_description_params_int(void)
7401 {
7402    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_INT);
7403 }
7404
7405 /**
7406     @page edcref
7407     @property
7408         double
7409     @parameters
7410         [param_name] [double_value]
7411     @effect
7412         Adds a double parameter for an external object
7413     @endproperty
7414 */
7415 static void
7416 st_collections_group_parts_part_description_params_double(void)
7417 {
7418    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_DOUBLE);
7419 }
7420
7421 /**
7422     @page edcref
7423     @property
7424         string
7425     @parameters
7426         [param_name] [string_value]
7427     @effect
7428         Adds a string parameter for an external object
7429     @endproperty
7430 */
7431 static void
7432 st_collections_group_parts_part_description_params_string(void)
7433 {
7434    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_STRING);
7435 }
7436
7437 /**
7438     @page edcref
7439     @property
7440         bool
7441     @parameters
7442         [param_name] [bool_value]
7443     @effect
7444         Adds an boolean parameter for an external object. Value must be 0 or 1.
7445     @endproperty
7446 */
7447 static void
7448 st_collections_group_parts_part_description_params_bool(void)
7449 {
7450    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_BOOL);
7451 }
7452
7453 /**
7454     @page edcref
7455     @property
7456         choice
7457     @parameters
7458         [param_name] [choice_string]
7459     @effect
7460         Adds a choice parameter for an external object. The possible
7461         choice values are defined by external type at their register time
7462         and will be validated at runtime.
7463     @endproperty
7464 */
7465 static void
7466 st_collections_group_parts_part_description_params_choice(void)
7467 {
7468    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_CHOICE);
7469 }
7470
7471
7472 /**
7473    @edcsection{program, Program block}
7474  */
7475
7476 /**
7477     @page edcref
7478     @block
7479         program
7480     @context
7481         group {
7482             programs {
7483                ..
7484                   program {
7485                      name: "programname";
7486                      signal: "signalname";
7487                      source: "partname";
7488                      filter: "partname" "statename";
7489                      in: 0.3 0.0;
7490                      action: STATE_SET "statename" state_value;
7491                      transition: LINEAR 0.5;
7492                      target: "partname";
7493                      target: "anotherpart";
7494                      after: "programname";
7495                      after: "anotherprogram";
7496                   }
7497                ..
7498             }
7499         }
7500     @description
7501         Programs define how your interface reacts to events.
7502         Programs can change the state of parts, react to events or trigger
7503         other events.
7504     @endblock
7505 */
7506 static void
7507 ob_collections_group_programs_program(void)
7508 {
7509    Edje_Part_Collection *pc;
7510    Edje_Program *ep;
7511    Edje_Program_Parser *epp;
7512
7513    pc = eina_list_data_get(eina_list_last(edje_collections));
7514
7515    ep = mem_alloc(SZ(Edje_Program_Parser));
7516    ep->id = -1;
7517    ep->tween.mode = EDJE_TWEEN_MODE_LINEAR;
7518    ep->after = NULL;
7519    epp = (Edje_Program_Parser *)ep;
7520    epp->can_override = EINA_FALSE;
7521
7522    _edje_program_insert(pc, ep);
7523
7524    current_program = ep;
7525 }
7526
7527 /**
7528     @page edcref
7529     @property
7530         name
7531     @parameters
7532         [program name]
7533     @effect
7534         Symbolic name of program as a unique identifier.
7535     @endproperty
7536 */
7537 static void
7538 st_collections_group_programs_program_name(void)
7539 {
7540    Edje_Part_Collection *pc;
7541
7542    check_arg_count(1);
7543
7544    pc = eina_list_data_get(eina_list_last(edje_collections));
7545    current_program->name = parse_str(0);
7546
7547    _edje_program_check(current_program->name, current_program, pc->programs.fnmatch, pc->programs.fnmatch_count);
7548    _edje_program_check(current_program->name, current_program, pc->programs.strcmp, pc->programs.strcmp_count);
7549    _edje_program_check(current_program->name, current_program, pc->programs.strncmp, pc->programs.strncmp_count);
7550    _edje_program_check(current_program->name, current_program, pc->programs.strrncmp, pc->programs.strrncmp_count);
7551    _edje_program_check(current_program->name, current_program, pc->programs.nocmp, pc->programs.nocmp_count);
7552 }
7553
7554 /**
7555     @page edcref
7556     @property
7557         signal
7558     @parameters
7559         [signal name]
7560     @effect
7561         Specifies signal(s) that should cause the program to run. The signal
7562         received must match the specified source to run.
7563         Signals may be globbed, but only one signal keyword per program
7564         may be used. ex: signal: "mouse,clicked,*"; (clicking any mouse button
7565         that matches source starts program).
7566     @endproperty
7567 */
7568 static void
7569 st_collections_group_programs_program_signal(void)
7570 {
7571    Edje_Part_Collection *pc;
7572
7573    check_arg_count(1);
7574
7575    pc = eina_list_data_get(eina_list_last(edje_collections));
7576
7577    _edje_program_remove(pc, current_program);
7578    current_program->signal = parse_str(0);
7579    _edje_program_insert(pc, current_program);
7580 }
7581
7582 /**
7583     @page edcref
7584     @property
7585         source
7586     @parameters
7587         [source name]
7588     @effect
7589         Source of accepted signal. Sources may be globbed, but only one source
7590         keyword per program may be used. ex:source: "button-*"; (Signals from
7591         any part or program named "button-*" are accepted).
7592     @endproperty
7593 */
7594 static void
7595 st_collections_group_programs_program_source(void)
7596 {
7597    Edje_Part_Collection *pc;
7598
7599    check_arg_count(1);
7600
7601    pc = eina_list_data_get(eina_list_last(edje_collections));
7602
7603    _edje_program_remove(pc, current_program);
7604    current_program->source = parse_str(0);
7605    _edje_program_insert(pc, current_program);
7606 }
7607
7608 /**
7609     @page edcref
7610     @property
7611         filter
7612     @parameters
7613         [part] [state]
7614     @effect
7615         Filter signals to be only accepted if the part [part] is in state named [state].
7616         Only one filter per program can be used. If [state] is not given, the source of
7617         the event will be used instead.
7618     @endproperty
7619 */
7620 static void
7621 st_collections_group_programs_program_filter(void)
7622 {
7623    check_min_arg_count(1);
7624
7625    if(is_param(1)) {
7626            current_program->filter.part = parse_str(0);
7627            current_program->filter.state = parse_str(1);
7628    } else {
7629            current_program->filter.state = parse_str(0);
7630    }
7631 }
7632
7633 /**
7634     @page edcref
7635     @property
7636         in
7637     @parameters
7638         [from] [range]
7639     @effect
7640         Wait 'from' seconds before executing the program. And add a random
7641         number of seconds (from 0 to 'range') to the total waiting time.
7642     @endproperty
7643 */
7644 static void
7645 st_collections_group_programs_program_in(void)
7646 {
7647    check_arg_count(2);
7648
7649    current_program->in.from = parse_float_range(0, 0.0, 999999999.0);
7650    current_program->in.range = parse_float_range(1, 0.0, 999999999.0);
7651 }
7652
7653 /**
7654     @page edcref
7655     @property
7656         action
7657     @parameters
7658         [type] [param1] [param2]
7659     @effect
7660         Action to be performed by the program. Valid actions are: STATE_SET,
7661         ACTION_STOP, SIGNAL_EMIT, DRAG_VAL_SET, DRAG_VAL_STEP, DRAG_VAL_PAGE,
7662         FOCUS_SET, PARAM_COPY, PARAM_SET, PLAY_SAMPLE, PLAY_TONE
7663         Only one action can be specified per program. Examples:\n
7664            action: STATE_SET "statename" 0.5;\n
7665            action: ACTION_STOP;\n
7666            action: SIGNAL_EMIT "signalname" "emitter";\n
7667            action: DRAG_VAL_SET 0.5 0.0;\n
7668            action: DRAG_VAL_STEP 1.0 0.0;\n
7669            action: DRAG_VAL_PAGE 0.0 0.0;\n
7670            action: FOCUS_SET;\n
7671            action: FOCUS_OBJECT;\n
7672            action: PARAM_COPY "src_part" "src_param" "dst_part" "dst_param";\n
7673            action: PARAM_SET "part" "param" "value";\n
7674            action: PLAY_SAMPLE "sample name";\n
7675            action: PLAY_TONE "tone name" duration in seconds ( Range 0.1 to 10.0 );\n
7676     @endproperty
7677 */
7678 static void
7679 st_collections_group_programs_program_action(void)
7680 {
7681    Edje_Part_Collection *pc;
7682    Edje_Program *ep;
7683    int i;
7684
7685    pc = eina_list_data_get(eina_list_last(edje_collections));
7686    ep = current_program;
7687    ep->action = parse_enum(0,
7688                            "STATE_SET", EDJE_ACTION_TYPE_STATE_SET,
7689                            "ACTION_STOP", EDJE_ACTION_TYPE_ACTION_STOP,
7690                            "SIGNAL_EMIT", EDJE_ACTION_TYPE_SIGNAL_EMIT,
7691                            "DRAG_VAL_SET", EDJE_ACTION_TYPE_DRAG_VAL_SET,
7692                            "DRAG_VAL_STEP", EDJE_ACTION_TYPE_DRAG_VAL_STEP,
7693                            "DRAG_VAL_PAGE", EDJE_ACTION_TYPE_DRAG_VAL_PAGE,
7694                            "SCRIPT", EDJE_ACTION_TYPE_SCRIPT,
7695                            "FOCUS_SET", EDJE_ACTION_TYPE_FOCUS_SET,
7696                            "FOCUS_OBJECT", EDJE_ACTION_TYPE_FOCUS_OBJECT,
7697                            "PARAM_COPY", EDJE_ACTION_TYPE_PARAM_COPY,
7698                            "PARAM_SET", EDJE_ACTION_TYPE_PARAM_SET,
7699                            "PLAY_SAMPLE", EDJE_ACTION_TYPE_SOUND_SAMPLE,
7700                            "PLAY_TONE", EDJE_ACTION_TYPE_SOUND_TONE,
7701                            NULL);
7702    if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
7703      {
7704         ep->state = parse_str(1);
7705         if (get_arg_count() == 1)
7706           ep->value = 0.0;
7707         else
7708           ep->value = parse_float_range(2, 0.0, 1.0);
7709      }
7710    else if (ep->action == EDJE_ACTION_TYPE_SIGNAL_EMIT)
7711      {
7712         ep->state = parse_str(1);
7713         ep->state2 = parse_str(2);
7714      }
7715    else if (ep->action == EDJE_ACTION_TYPE_SOUND_SAMPLE)
7716      {
7717         ep->sample_name = parse_str(1);
7718         for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
7719           {
7720              if (!strcmp(edje_file->sound_dir->samples[i].name, ep->sample_name))
7721                break;
7722              if (i == (int)(edje_file->sound_dir->samples_count - 1))
7723                {
7724                   ERR("No Sample name %s exist.", ep->sample_name);
7725                   exit(-1);
7726                }
7727           }
7728         ep->speed = parse_float_range(2, 0.0, 10.0);
7729      }
7730    else if (ep->action == EDJE_ACTION_TYPE_SOUND_TONE)
7731      {
7732         ep->tone_name = parse_str(1);
7733         for (i = 0; i < (int)edje_file->sound_dir->tones_count; i++)
7734           {
7735              if (!strcmp(edje_file->sound_dir->tones[i].name, ep->tone_name))
7736                break;
7737              if (i == (int)(edje_file->sound_dir->tones_count - 1))
7738                {
7739                   ERR("No Tone name %s exist.", ep->tone_name);
7740                   exit(-1);
7741                }
7742           }
7743         ep->duration = parse_float_range(2, 0.1, 10.0);
7744      }
7745    else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
7746      {
7747         ep->value = parse_float(1);
7748         ep->value2 = parse_float(2);
7749      }
7750    else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
7751      {
7752         ep->value = parse_float(1);
7753         ep->value2 = parse_float(2);
7754      }
7755    else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
7756      {
7757         ep->value = parse_float(1);
7758         ep->value2 = parse_float(2);
7759      }
7760    else if (ep->action == EDJE_ACTION_TYPE_PARAM_COPY)
7761      {
7762         char *src_part, *dst_part;
7763         
7764         src_part = parse_str(1);
7765         ep->state = parse_str(2);
7766         dst_part = parse_str(3);
7767         ep->state2 = parse_str(4);
7768         
7769         data_queue_part_lookup(pc, src_part, &(ep->param.src));
7770         data_queue_part_lookup(pc, dst_part, &(ep->param.dst));
7771         
7772         free(src_part);
7773         free(dst_part);
7774      }
7775    else if (ep->action == EDJE_ACTION_TYPE_PARAM_SET)
7776      {
7777         char *part;
7778         
7779         part = parse_str(1);
7780         ep->state = parse_str(2);
7781         ep->state2 = parse_str(3);
7782         
7783         data_queue_part_lookup(pc, part, &(ep->param.dst));
7784         free(part);
7785      }
7786    
7787    switch (ep->action)
7788      {
7789       case EDJE_ACTION_TYPE_ACTION_STOP:
7790         check_arg_count(1);
7791         break;
7792       case EDJE_ACTION_TYPE_SCRIPT:
7793         /* this is implicitly set by script {} so this is here just for
7794          * completeness */
7795         break;
7796       case EDJE_ACTION_TYPE_FOCUS_OBJECT:
7797       case EDJE_ACTION_TYPE_FOCUS_SET:
7798         check_arg_count(1);
7799         break;
7800       case EDJE_ACTION_TYPE_PARAM_COPY:
7801         check_arg_count(5);
7802         break;
7803       case EDJE_ACTION_TYPE_PARAM_SET:
7804         check_arg_count(4);
7805         break;
7806       case EDJE_ACTION_TYPE_SOUND_SAMPLE:
7807         check_arg_count(3);
7808         break;
7809       case EDJE_ACTION_TYPE_SOUND_TONE:
7810         check_arg_count(3);
7811         break;
7812       default:
7813         check_arg_count(3);
7814      }
7815 }
7816
7817 /**
7818     @page edcref
7819     @property
7820         transition
7821     @parameters
7822         [type] [length] [[interp val 1]] [[interp val 2]] [[option]]
7823     @effect
7824         Defines how transitions occur using STATE_SET action.\n
7825         Where 'type' is the style of the transition and 'length' is a double
7826         specifying the number of seconds in which to preform the transition.\n
7827         Valid types are: LIN or LINEAR, SIN or SINUSOIDAL, 
7828         ACCEL or ACCELERATE, DECEL or DECELERATE, 
7829         ACCEL_FAC or ACCELERATE_FACTOR, DECEL_FAC or DECELERATE_FACTOR,
7830         SIN_FAC or SINUSOIDAL_FACTOR, DIVIS or DIVISOR_INTERP,
7831         BOUNCE, SPRING.
7832         
7833         ACCEL_FAC, DECEL_FAC and SIN_FAC need the extra optional
7834         "interp val 1" to determine the "factor" of curviness. 1.0 is the same
7835         as their non-factor counterparts, where 0.0 is equal to linear.
7836         Numbers higher than one make the curve angles steeper with a more
7837         pronounced curve point.
7838         
7839         DIVIS, BOUNCE and SPRING also require "interp val 2" in addition
7840         to "interp val 1".
7841         
7842         DIVIS uses val 1 as the initial gradient start
7843         (0.0 is horizontal, 1.0 is diagonal (linear), 2.0 is twice the
7844         gradient of linear etc.). val 2 is interpreted as an integer factor
7845         defining how much the value swings "outside" the gradient only to come
7846         back to the final resting spot at the end. 0.0 for val 2 is equivalent
7847         to linear interpolation. Note that DIVIS can exceed 1.0
7848         
7849         BOUNCE uses val 2 as the number of bounces (so its rounded down to
7850         the nearest integer value), with val 1 determining how much the
7851         bounce decays, with 0.0 giving linear decay per bounce, and higher
7852         values giving much more decay.
7853
7854         SPRING is similar to bounce, where val 2 specifies the number of
7855         spring "swings" and val 1 specifies the decay, but it can exceed 1.0
7856         on the outer swings.
7857
7858         Valid option is CURRENT.
7859
7860         CURRENT is the option which causes the edje object to move from its current position.
7861         It can be used as the last parameter of any transition type. (@since 1.1.0)
7862
7863     @endproperty
7864 */
7865 static void
7866 st_collections_group_programs_program_transition(void)
7867 {
7868    check_min_arg_count(2);
7869
7870    current_program->tween.mode = parse_enum(0,
7871                                             // short names
7872                                             "LIN", EDJE_TWEEN_MODE_LINEAR,
7873                                             "SIN", EDJE_TWEEN_MODE_SINUSOIDAL,
7874                                             "ACCEL", EDJE_TWEEN_MODE_ACCELERATE,
7875                                             "DECEL", EDJE_TWEEN_MODE_DECELERATE,
7876                                             "ACCEL_FAC", EDJE_TWEEN_MODE_ACCELERATE_FACTOR,
7877                                             "DECEL_FAC", EDJE_TWEEN_MODE_DECELERATE_FACTOR,
7878                                             "SIN_FAC", EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR,
7879                                             "DIVIS", EDJE_TWEEN_MODE_DIVISOR_INTERP,
7880                                             
7881                                             // long/full names
7882                                             "LINEAR", EDJE_TWEEN_MODE_LINEAR,
7883                                             "SINUSOIDAL", EDJE_TWEEN_MODE_SINUSOIDAL,
7884                                             "ACCELERATE", EDJE_TWEEN_MODE_ACCELERATE,
7885                                             "DECELERATE", EDJE_TWEEN_MODE_DECELERATE,
7886                                             "ACCELERATE_FACTOR", EDJE_TWEEN_MODE_ACCELERATE_FACTOR,
7887                                             "DECELERATE_FACTOR", EDJE_TWEEN_MODE_DECELERATE_FACTOR,
7888                                             "SINUSOIDAL_FACTOR", EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR,
7889                                             "DIVISOR_INTERP", EDJE_TWEEN_MODE_DIVISOR_INTERP,
7890                                             
7891                                             // long/full is short enough
7892                                             "BOUNCE", EDJE_TWEEN_MODE_BOUNCE,
7893                                             "SPRING", EDJE_TWEEN_MODE_SPRING,
7894                                             NULL);
7895    current_program->tween.time = FROM_DOUBLE(parse_float_range(1, 0.0, 999999999.0));
7896    if ((current_program->tween.mode >= EDJE_TWEEN_MODE_LINEAR) &&
7897        (current_program->tween.mode <= EDJE_TWEEN_MODE_DECELERATE))
7898      {
7899         if ((get_arg_count() == 3) && (!strcmp(parse_str(2), "CURRENT")))
7900           current_program->tween.mode |= EDJE_TWEEN_MODE_OPT_FROM_CURRENT;
7901         else if (get_arg_count() != 2)
7902           {
7903              ERR("parse error %s:%i. Need 2rd parameter to set time",
7904                  file_in, line - 1);
7905              exit(-1);
7906           }
7907      }
7908    // the following need v1
7909    // EDJE_TWEEN_MODE_ACCELERATE_FACTOR
7910    // EDJE_TWEEN_MODE_DECELERATE_FACTOR
7911    // EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR
7912    // current_program->tween.v1
7913    else if ((current_program->tween.mode >= EDJE_TWEEN_MODE_ACCELERATE_FACTOR) &&
7914        (current_program->tween.mode <= EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR))
7915      {
7916         if ((get_arg_count() == 4) && (!strcmp(parse_str(3), "CURRENT")))
7917           current_program->tween.mode |= EDJE_TWEEN_MODE_OPT_FROM_CURRENT;
7918         else if (get_arg_count() != 3)
7919           {
7920              ERR("parse error %s:%i. Need 3rd parameter to set factor",
7921                  file_in, line - 1);
7922              exit(-1);
7923           }
7924         current_program->tween.v1 = FROM_DOUBLE(parse_float_range(2, 0.0, 999999999.0));
7925      }
7926    // the followjng also need v2
7927    // EDJE_TWEEN_MODE_DIVISOR_INTERP
7928    // EDJE_TWEEN_MODE_BOUNCE
7929    // EDJE_TWEEN_MODE_SPRING
7930    // current_program->tween.v2
7931    else if ((current_program->tween.mode >= EDJE_TWEEN_MODE_DIVISOR_INTERP) &&
7932             (current_program->tween.mode <= EDJE_TWEEN_MODE_SPRING))
7933      {
7934         if ((get_arg_count() == 5) && (!strcmp(parse_str(4), "CURRENT")))
7935           current_program->tween.mode |= EDJE_TWEEN_MODE_OPT_FROM_CURRENT;
7936         else if (get_arg_count() != 4)
7937           {
7938              ERR("parse error %s:%i. "
7939                  "Need 3rd and 4th parameters to set factor and counts",
7940                  file_in, line - 1);
7941              exit(-1);
7942           }
7943         current_program->tween.v1 = FROM_DOUBLE(parse_float_range(2, 0.0, 999999999.0));
7944         current_program->tween.v2 = FROM_DOUBLE(parse_float_range(3, 0.0, 999999999.0));
7945      }
7946 }
7947
7948 /**
7949     @page edcref
7950     @property
7951         target
7952     @parameters
7953         [target]
7954     @effect
7955         Program or part on which the specified action acts. Multiple target
7956         keywords may be specified, one per target. SIGNAL_EMITs do not have
7957         targets.
7958     @endproperty
7959 */
7960 static void
7961 st_collections_group_programs_program_target(void)
7962 {
7963    Edje_Part_Collection *pc;
7964    Edje_Program *ep;
7965
7966    check_arg_count(1);
7967
7968    pc = eina_list_data_get(eina_list_last(edje_collections));
7969    ep = current_program;
7970      {
7971         Edje_Program_Target *et;
7972         Edje_Program_Target *etw;
7973         Eina_List *l;
7974         char *name;
7975         char *copy;
7976
7977         name = parse_str(0);
7978         
7979         EINA_LIST_FOREACH(ep->targets, l, etw)
7980           {
7981              if (!strcmp(name, (char*) (etw + 1)))
7982                {
7983                   free(name);
7984                   return;
7985                }
7986           }
7987
7988         et = mem_alloc(SZ(Edje_Program_Target) + strlen(name) + 1);
7989         ep->targets = eina_list_append(ep->targets, et);
7990         copy = (char*) (et + 1);
7991
7992         memcpy(copy, name, strlen(name) + 1);
7993
7994         if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
7995           data_queue_part_lookup(pc, name, &(et->id));
7996         else if (ep->action == EDJE_ACTION_TYPE_ACTION_STOP)
7997           data_queue_program_lookup(pc, name, &(et->id));
7998         else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
7999           data_queue_part_lookup(pc, name, &(et->id));
8000         else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
8001           data_queue_part_lookup(pc, name, &(et->id));
8002         else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
8003           data_queue_part_lookup(pc, name, &(et->id));
8004         else if (ep->action == EDJE_ACTION_TYPE_FOCUS_SET)
8005           data_queue_part_lookup(pc, name, &(et->id));
8006         else if (ep->action == EDJE_ACTION_TYPE_FOCUS_OBJECT)
8007           data_queue_part_lookup(pc, name, &(et->id));
8008         else
8009           {
8010              ERR("parse error %s:%i. target may only be used after action",
8011                  file_in, line - 1);
8012              exit(-1);
8013           }
8014         free(name);
8015      }
8016 }
8017
8018 /**
8019     @page edcref
8020     @property
8021         after
8022     @parameters
8023         [after]
8024     @effect
8025         Specifies a program to run after the current program completes. The
8026         source and signal parameters of a program run as an "after" are ignored.
8027         Multiple "after" statements can be specified per program.
8028     @endproperty
8029 */
8030 static void
8031 st_collections_group_programs_program_after(void)
8032 {
8033    Edje_Part_Collection *pc;
8034    Edje_Program *ep;
8035
8036    check_arg_count(1);
8037
8038    pc = eina_list_data_get(eina_list_last(edje_collections));
8039    ep = current_program;
8040      {
8041         Edje_Program_After *pa;
8042         Edje_Program_After *pa2;
8043         Eina_List *l;
8044         char *name;
8045         char *copy;
8046
8047         name = parse_str(0);
8048
8049         EINA_LIST_FOREACH(ep->after, l, pa2)
8050           {
8051              if (!strcmp(name, (char*) (pa2 + 1)))
8052                {
8053                   free(name);
8054                   return;
8055                }
8056           }
8057
8058         pa = mem_alloc(SZ(Edje_Program_After) + strlen(name) + 1);
8059         pa->id = -1;
8060         ep->after = eina_list_append(ep->after, pa);
8061         copy = (char*)(pa + 1);
8062         memcpy(copy, name, strlen(name) + 1);
8063         data_queue_program_lookup(pc, name, &(pa->id));
8064         free(name);
8065      }
8066 }
8067
8068 /**
8069     @page edcref
8070     @property
8071         api
8072     @parameters
8073         [name] [description]
8074     @effect
8075         Specifies a hint to let applications (or IDE's) know how to bind
8076         things. The parameter name should contain the name of the function that
8077         the application should use, and description describes how it should
8078         be used.
8079     @endproperty
8080 */
8081 static void
8082 st_collections_group_programs_program_api(void)
8083 {
8084    check_min_arg_count(1);
8085
8086    current_program->api.name = parse_str(0);
8087
8088    if (is_param(1))
8089      {
8090        check_arg_count(2);
8091        current_program->api.description = parse_str(1);
8092      }
8093 }
8094
8095 static void
8096 st_collections_group_parts_part_api(void)
8097 {
8098    check_min_arg_count(1);
8099
8100    current_part->api.name = parse_str(0);
8101    if (is_param(1))
8102      {
8103        check_arg_count(2);
8104        current_part->api.description = parse_str(1);
8105      }
8106 }
8107
8108 static void
8109 ob_collections_group_programs_program_script(void)
8110 {
8111    Edje_Part_Collection *pc;
8112    Code *cd;
8113
8114    pc = eina_list_data_get(eina_list_last(edje_collections));
8115    cd = eina_list_data_get(eina_list_last(codes));
8116
8117    if (!is_verbatim()) track_verbatim(1);
8118    else
8119      {
8120         Eina_Bool empty = EINA_TRUE;
8121         char *s;
8122         int i, len;
8123
8124         s = get_verbatim();
8125         if (s)
8126           {
8127              Code_Program *cp;
8128
8129              /* FIXME: Need to store the script somewhere to be restored when using edje_edit API */
8130              cp = mem_alloc(SZ(Code_Program));
8131              cp->l1 = get_verbatim_line1();
8132              cp->l2 = get_verbatim_line2();
8133              cp->script = s;
8134              cp->original = strdup(s);
8135              if (cd->shared && cd->is_lua)
8136                {
8137                   ERR("parse error %s:%i. You're trying to mix Embryo and Lua scripting in the same group",
8138                       file_in, line - 1);
8139                   exit(-1);
8140                }
8141              cd->is_lua = 0;
8142
8143              len = strlen(cp->script);
8144              for (i = 0; i < len; i++)
8145                {
8146                   if (((cp->script[i] > 'a') && (cp->script[i] < 'z')) ||
8147                       ((cp->script[i] > 'A') && (cp->script[i] < 'Z')) ||
8148                       ((cp->script[i] > '0') && (cp->script[i] < '9')))
8149                     empty = EINA_FALSE;
8150                }
8151
8152              if (!empty)
8153                {
8154                   cd->programs = eina_list_append(cd->programs, cp);
8155                   data_queue_anonymous_lookup(pc, current_program, &(cp->id));
8156                   current_program->action = EDJE_ACTION_TYPE_SCRIPT;
8157                }
8158              else
8159                {
8160                   data_queue_anonymous_lookup(pc, current_program, NULL);
8161                   free(cp);
8162                   cp = NULL;
8163                }
8164
8165              set_verbatim(NULL, 0, 0);
8166           }
8167      }
8168 }
8169 /**
8170     @page edcref
8171     </table>
8172 */
8173
8174 static void
8175 edje_cc_handlers_hierarchy_set(Edje_Part *src)
8176 {  /* This funcion makes current part rel_1.id, rel_2.id relative to src */
8177    if (!src->name)
8178      {
8179         ERR("parse error %s:%i. You must set parent name before creating nested part",
8180             file_in, line - 1);
8181         exit(-1);
8182      }
8183    st_collections_group_parts_part_description_rel1_to_set(src->name);
8184    st_collections_group_parts_part_description_rel2_to_set(src->name);
8185 }
8186
8187 static Edje_Part *
8188 edje_cc_handlers_hierarchy_parent_get(void)
8189 {  /* Return the parent part pointer */
8190    int idx = eina_array_count(part_hierarchy) - 2;
8191    Edje_Cc_Handlers_Hierarchy_Info *info = (idx >= 0) ?
8192       eina_array_data_get(part_hierarchy, idx) : NULL;
8193
8194    return (info) ? info->ep : NULL;
8195 }
8196
8197 static void
8198 edje_cc_handlers_hierarchy_push(Edje_Part *ep, Edje_Part *cp)
8199 {  /* Remove part from hierarchy stack when finished parsing it */
8200    Edje_Cc_Handlers_Hierarchy_Info *info = malloc(sizeof(*info));
8201    info->current_de = current_de;
8202    info->current_part = cp;  /* current_part restored on pop */
8203    info->current_item = current_item;
8204    info->current_desc = current_desc;
8205    info->parent_desc = parent_desc;
8206    info->current_program = current_program;
8207    info->ep = ep;
8208
8209    eina_array_push(part_hierarchy, info);
8210 }
8211
8212 static void
8213 edje_cc_handlers_hierarchy_rename(Edje_Part *old, Edje_Part *new)
8214 {
8215    Edje_Cc_Handlers_Hierarchy_Info *item;
8216    Eina_Array_Iterator iterator;
8217    unsigned int i;       
8218
8219    EINA_ARRAY_ITER_NEXT(part_hierarchy, i, item, iterator)
8220      {
8221         if (item->ep == old) item->ep = new;
8222         if (item->current_part == old) item->current_part = new;
8223      }
8224 }
8225
8226 void
8227 edje_cc_handlers_hierarchy_alloc(void)
8228 {
8229    part_hierarchy = eina_array_new(8);
8230 }
8231
8232 void
8233 edje_cc_handlers_hierarchy_free(void)
8234 {
8235    eina_array_free(part_hierarchy);
8236    part_hierarchy = NULL;
8237 }
8238
8239 static void
8240 edje_cc_handlers_hierarchy_pop(void)
8241 {  /* Remove part from hierarchy stack when finished parsing it */
8242    Edje_Cc_Handlers_Hierarchy_Info *info = eina_array_pop(part_hierarchy);
8243
8244    if (info)
8245      {
8246         current_de = info->current_de;
8247         current_part = info->current_part;
8248         current_item = info->current_item;
8249         current_desc = info->current_desc;
8250         parent_desc = info->parent_desc;
8251         current_program = info->current_program;
8252
8253         free(info);
8254      }
8255 }