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