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