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    \@since X.X
17    \@endblock
18 
19    \@property
20         property name
21    \@parameters
22         property's parameter list
23    \@effect
24         the property description (lol)
25    \@since X.X
26    \@endproperty
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32 
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #ifdef _WIN32
40 # include <evil_private.h> /* mmap */
41 #else
42 # include <sys/mman.h>
43 #endif
44 
45 #include "edje_cc.h"
46 
47 /**
48  * @page edcref Edje Data Collection reference
49  *
50  * An Edje Data Collection, it's a plain text file (normally identified with the
51  * .edc extension), consisting of instructions for the Edje Compiler.
52  *
53  * The syntax for the edje data collection files follows a simple structure of
54  * "blocks { .. }" that can contain "properties: ..", more blocks, or both.
55  *
56  * @anchor sec_quickaccess Quick access to block descriptions:
57  * <ul>
58  *    <li>@ref sec_toplevel "Top-Level"</li>
59  *    <ul>
60  *      <li>@ref sec_toplevel_externals "Externals"</li>
61  *      <li>@ref sec_toplevel_images "Images"</li>
62  *      <ul>
63  *        <li>@ref sec_toplevel_images_set "Set"</li>
64  *        <ul>
65  *          <li>@ref sec_toplevel_images_set_image "Image"</li>
66  *        </ul>
67  *      </ul>
68  *      <li>@ref sec_toplevel_fonts "Fonts"</li>
69  *      <li>@ref sec_toplevel_data "Data"</li>
70  *      <li>@ref sec_toplevel_color_classes "Color Classes"</li>
71  *      <li>@ref sec_toplevel_styles "Styles"</li>
72  *      <li>@ref sec_collections_group_filters "Filters"</li>
73  *    </ul>
74  *    <li>@ref sec_collections "Collections"</li>
75  *    <ul>
76  *      <li>@ref sec_collections_sounds "Sounds"</li>
77  *      <ul>
78  *        <li>@ref sec_collections_sounds_sample "Sample"</li>
79  *      </ul>
80  *      <li>@ref sec_collections_group_filters "Filters"</li>
81  *      <li>@ref sec_collections_vibrations "Vibrations"</li>
82  *      <ul>
83  *        <li>@ref sec_collections_vibrations_sample "Sample"</li>
84  *      </ul>
85  *      <li>@ref sec_collections_group "Group"</li>
86  *      <ul>
87  *        <li>@ref sec_collections_group_script "Script"</li>
88  *        <li>@ref sec_collections_group_limits "Limits"</li>
89  *        <li>@ref sec_collections_group_data "Data"</li>
90  *        <li>@ref sec_collections_group_filters "Filters"</li>
91  *        <li>@ref sec_collections_group_parts "Parts"</li>
92  *        <ul>
93  *          <li>@ref sec_collections_group_parts_part "Part"</li>
94  *          <ul>
95  *            <li>@ref sec_collections_group_parts_dragable "Dragable"</li>
96  *            <li>@ref sec_collections_group_parts_items "Items"</li>
97  *            <li>@ref sec_collections_group_parts_description "Description"</li>
98  *            <ul>
99  *              <li>@ref sec_collections_group_parts_description_relatives "Relatives (rel1/rel2)"</li>
100  *              <li>@ref sec_collections_group_parts_description_image "Image"</li>
101  *              <li>@ref sec_collections_group_parts_description_proxy "Proxy"</li>
102  *              <li>@ref sec_collections_group_parts_description_fill "Fill"</li>
103  *              <ul>
104  *                <li>@ref sec_collections_group_parts_description_fill_origin "Origin"</li>
105  *                <li>@ref sec_collections_group_parts_description_fill_size "Size"</li>
106  *              </ul>
107  *              <li>@ref sec_collections_group_parts_description_text "Text"</li>
108  *              <li>@ref sec_collections_group_parts_description_box "Box"</li>
109  *              <ul>
110  *                <li>@ref sec_collections_group_parts_items "Items"</li>
111  *              </ul>
112  *              <li>@ref sec_collections_group_parts_description_table "Table"</li>
113  *              <li>@ref sec_collections_group_parts_description_physics "Physics"</li>
114  *              <ul>
115  *                  <li>@ref sec_collections_group_parts_description_physics_movement_freedom "Movement Freedom"</li>
116  *                  <li>@ref sec_collections_group_parts_description_physics_faces "Faces"</li>
117  *              </ul>
118  *              <li>@ref sec_collections_group_parts_description_map "Map (3d/transformations)"</li>
119  *              <ul>
120  *                <li>@ref sec_collections_group_parts_description_map_rotation "Rotation"</li>
121  *              </ul>
122  *              <li>@ref sec_collections_group_parts_description_perspective "Perspective"</li>
123  *              <li>@ref sec_collections_group_parts_descriptions_params "Params"</li>
124  *              <li>@ref sec_collections_group_parts_description_links "Links"</li>
125  *              <li>@ref sec_collections_group_parts_description_filter "Filter"</li>
126  *            </ul>
127  *          </ul>
128  *        </ul>
129  *        <li>@ref sec_collections_group_programs "Programs"</li>
130  *        <ul>
131  *          <li>@ref sec_collections_group_script "Script"</li>
132  *          <li>@ref sec_collections_group_programs_program "Program"</li>
133  *          <ul>
134  *            <li>@ref sec_collections_group_script "Script"</li>
135  *            <li>@ref sec_collections_group_program_sequence "Sequence"</li>
136  *            <ul>
137  *              <li>@ref sec_collections_group_script "Script"</li>
138  *            </ul>
139  *          </ul>
140  *          <li>@ref sec_collections_group_script "Script"</li>
141  *          <li>@ref sec_toplevel_fonts "Fonts"</li>
142  *        </ul>
143  *        <li>@ref sec_collections_group_physics "Physics"</li>
144  *        <ul>
145  *          <li>@ref sec_collections_group_physics_world "World"</li>
146  *        </ul>
147  *      </ul>
148  *    </ul>
149  *    <li>@ref sec_lazedc "LazEDC"</li>
150  *    <ul>
151  *       <li>@ref sec_lazedc_intro "Intro"</li>
152  *       <li>@ref sec_lazedc_synonyms "Synonyms"</li>
153  *       <li>@ref sec_lazedc_shorthand "Shorthand"</li>
154  *    </ul>
155  * </ul>
156  *
157  * @author Andres Blanc (dresb) andresblanc@gmail.com
158  *
159  * <table class="edcref" border="0">
160  */
161 
162 static Edje_Part_Collection_Directory_Entry *current_de = NULL;
163 static Edje_Part *current_part = NULL;
164 static Edje_Pack_Element *current_item = NULL;
165 static Edje_Part_Description_Common *current_desc = NULL;
166 static Edje_Part_Description_Common *parent_desc = NULL;
167 static Edje_Program *current_program = NULL;
168 static Eina_List *current_program_lookups = NULL;
169 Eina_Bool current_group_inherit = EINA_FALSE;
170 Eina_Bool script_is_replaceable = EINA_FALSE;
171 static Edje_Program *sequencing = NULL;
172 static Eina_List *sequencing_lookups = NULL;
173 static int *anonymous_delete = NULL;
174 static Edje_Part_Description_Anchors *current_anchors = NULL;
175 static Eina_Bool has_relatives = EINA_FALSE;
176 
177 Eina_List *po_files;
178 
179 static Eina_Hash *desc_hash = NULL;
180 
181 struct _Edje_Cc_Handlers_Hierarchy_Info /* Struct that keeps globals value to impl hierarchy */
182 {
183    Edje_Part_Collection_Directory_Entry *current_de;
184    Edje_Part                            *current_part;
185    Edje_Pack_Element                    *current_item;
186    Edje_Part_Description_Common         *current_desc;
187    Edje_Part_Description_Common         *parent_desc;
188    Edje_Program                         *current_program;
189    Edje_Part                            *ep;
190 };
191 typedef struct _Edje_Cc_Handlers_Hierarchy_Info Edje_Cc_Handlers_Hierarchy_Info;
192 
193 static Eina_Array *part_hierarchy = NULL; /* stack parts,support nested parts */
194 static void       edje_cc_handlers_hierarchy_set(Edje_Part *src);
195 static Edje_Part *edje_cc_handlers_hierarchy_parent_get(void);
196 static void       edje_cc_handlers_hierarchy_push(Edje_Part *ep, Edje_Part *cp);
197 static void       edje_cc_handlers_hierarchy_rename(Edje_Part *old, Edje_Part *new);
198 static void       edje_cc_handlers_hierarchy_pop(void);
199 
200 static void       _program_target_add(char *name);
201 static void       _program_after(const char *name);
202 static void       _program_free(Edje_Program *pr);
203 static Eina_Bool  _program_remove(const char *name, Edje_Program **pgrms, unsigned int count);
204 
205 static void      *_part_free(Edje_Part_Collection *pc, Edje_Part *ep);
206 
207 static void       check_has_anchors(void);
208 
209 static void       st_id(void);
210 static void       st_requires(void);
211 static void       st_efl_version(void);
212 static void       st_externals_external(void);
213 
214 static void       st_images_image(void);
215 static void       ob_images_set(void);
216 static void       st_images_set_name(void);
217 static void       ob_images_set_image(void);
218 static void       st_images_set_image_image(void);
219 static void       st_images_set_image_size(void);
220 static void       st_images_set_image_border(void);
221 static void       st_images_set_image_border_scale_by(void);
222 
223 static void       st_fonts_font(void);
224 
225 static void       st_data_item(void);
226 static void       st_data_file(void);
227 
228 static void       ob_styles_style(void);
229 static void       st_styles_style_name(void);
230 static void       st_styles_style_base(void);
231 static void       st_styles_style_tag(void);
232 
233 static void       ob_color_tree(void);
234 
235 static void       ob_color_class(void);
236 static void       st_color_class_name(void);
237 static void       st_color_class_color(void);
238 static void       st_color_class_color2(void);
239 static void       st_color_class_color3(void);
240 static void       st_color_class_desc(void);
241 
242 static void       ob_text_class(void);
243 static void       st_text_class_name(void);
244 static void       st_text_class_font(void);
245 static void       st_text_class_size(void);
246 
247 static void       ob_size_class(void);
248 static void       st_size_class_name(void);
249 static void       st_size_class_min(void);
250 static void       st_size_class_max(void);
251 
252 static void       ob_filters_filter(void);
253 static void       ob_filters_filter_script(void);
254 static void       st_filters_filter_file(void);
255 static void       st_filters_filter_name(void);
256 
257 static void       ob_collections(void);
258 static void       st_collections_base_scale(void);
259 
260 static void       ob_collections_group(void);
261 static void       st_collections_group_name(void);
262 static void       st_collections_group_skip_namespace_validation(void);
263 static void       st_collections_group_inherit_only(void);
264 static void       st_collections_group_inherit(void);
265 static void       st_collections_group_program_source(void);
266 static void       st_collections_group_part_remove(void);
267 static void       st_collections_group_program_remove(void);
268 static void       st_collections_group_lua_script_only(void);
269 static void       st_collections_group_script_recursion(void);
270 static void       st_collections_group_alias(void);
271 static void       st_collections_group_min(void);
272 static void       st_collections_group_max(void);
273 static void       st_collections_group_broadcast_signal(void);
274 static void       st_collections_group_data_item(void);
275 static void       st_collections_group_orientation(void);
276 static void       st_collections_group_mouse_events(void);
277 static void       st_collections_group_use_custom_seat_names(void);
278 static void       st_collections_group_inherit_script(void);
279 
280 static void       st_collections_group_limits_vertical(void);
281 static void       st_collections_group_limits_horizontal(void);
282 
283 static void       ob_collections_group_script(void);
284 static void       ob_collections_group_lua_script(void);
285 
286 static void       st_collections_group_parts_alias(void);
287 
288 static Edje_Part *edje_cc_handlers_part_make(int);
289 static void       ob_collections_group_parts_part(void);
290 static void       st_collections_group_parts_part_name(void);
291 static void       st_collections_group_parts_part_inherit(void);
292 static void       st_collections_group_parts_part_type(void);
293 #ifdef HAVE_EPHYSICS
294 static void       st_collections_group_parts_part_physics_body(void);
295 #endif
296 static void       st_collections_group_parts_part_insert_before(void);
297 static void       st_collections_group_parts_part_insert_after(void);
298 static void       st_collections_group_parts_part_effect(void);
299 static void       st_collections_group_parts_part_mouse_events(void);
300 static void       st_collections_group_parts_part_anti_alias(void);
301 static void       st_collections_group_parts_part_repeat_events(void);
302 static void       st_collections_group_parts_part_ignore_flags(void);
303 static void       st_collections_group_parts_part_mask_flags(void);
304 static void       st_collections_group_parts_part_scale(void);
305 static void       st_collections_group_parts_part_pointer_mode(void);
306 static void       st_collections_group_parts_part_precise_is_inside(void);
307 static void       st_collections_group_parts_part_use_alternate_font_metrics(void);
308 static void       st_collections_group_parts_part_clip_to_id(void);
309 static void       st_collections_group_parts_part_render(void);
310 static void       st_collections_group_parts_part_no_render(void);
311 static void       st_collections_group_parts_part_required(void);
312 static void       st_collections_group_parts_part_norequired(void);
313 static void       st_collections_group_parts_part_source(void);
314 static void       st_collections_group_parts_part_source2(void);
315 static void       st_collections_group_parts_part_source3(void);
316 static void       st_collections_group_parts_part_source4(void);
317 static void       st_collections_group_parts_part_source5(void);
318 static void       st_collections_group_parts_part_source6(void);
319 static void       st_collections_group_parts_part_entry_mode(void);
320 static void       st_collections_group_parts_part_select_mode(void);
321 static void       st_collections_group_parts_part_cursor_mode(void);
322 static void       st_collections_group_parts_part_multiline(void);
323 static void       st_collections_group_parts_part_access(void);
324 static void       st_collections_group_parts_part_dragable_x(void);
325 static void       st_collections_group_parts_part_dragable_y(void);
326 static void       st_collections_group_parts_part_dragable_confine(void);
327 static void       st_collections_group_parts_part_dragable_threshold(void);
328 static void       st_collections_group_parts_part_dragable_events(void);
329 static void       st_collections_group_parts_part_allowed_seats(void);
330 
331 /* box and table items share these */
332 static void       ob_collections_group_parts_part_box_items_item(void);
333 static void       st_collections_group_parts_part_box_items_item_type(void);
334 static void       st_collections_group_parts_part_box_items_item_name(void);
335 static void       st_collections_group_parts_part_box_items_item_source(void);
336 static void       st_collections_group_parts_part_box_items_item_min(void);
337 static void       st_collections_group_parts_part_box_items_item_spread(void);
338 static void       st_collections_group_parts_part_box_items_item_prefer(void);
339 static void       st_collections_group_parts_part_box_items_item_max(void);
340 static void       st_collections_group_parts_part_box_items_item_padding(void);
341 static void       st_collections_group_parts_part_box_items_item_align(void);
342 static void       st_collections_group_parts_part_box_items_item_weight(void);
343 static void       st_collections_group_parts_part_box_items_item_aspect(void);
344 static void       st_collections_group_parts_part_box_items_item_aspect_mode(void);
345 static void       st_collections_group_parts_part_box_items_item_options(void);
346 /* but these are only for table */
347 static void       st_collections_group_parts_part_table_items_item_position(void);
348 static void       st_collections_group_parts_part_table_items_item_span(void);
349 
350 static void       ob_collections_group_parts_part_description(void);
351 static void       ob_collections_group_parts_part_desc(void);
352 static void       st_collections_group_parts_part_description_inherit(void);
353 static void       ob_collections_group_parts_part_description_link(void);
354 static void       st_collections_group_parts_part_description_link_base(void);
355 static void       st_collections_group_parts_part_description_source(void);
356 static void       st_collections_group_parts_part_description_state(void);
357 static void       st_collections_group_parts_part_description_visible(void);
358 static void       st_collections_group_parts_part_description_no_render(void);
359 static void       st_collections_group_parts_part_description_limit(void);
360 static void       st_collections_group_parts_part_description_align(void);
361 static void       st_collections_group_parts_part_description_fixed(void);
362 static void       st_collections_group_parts_part_description_min(void);
363 static void       st_collections_group_parts_part_description_minmul(void);
364 static void       st_collections_group_parts_part_description_max(void);
365 static void       st_collections_group_parts_part_description_step(void);
366 static void       st_collections_group_parts_part_description_aspect(void);
367 static void       st_collections_group_parts_part_description_aspect_preference(void);
368 static void       st_collections_group_parts_part_description_rel_to(void);
369 static void       st_collections_group_parts_part_description_rel_to_x(void);
370 static void       st_collections_group_parts_part_description_rel_to_y(void);
371 static void       st_collections_group_parts_part_description_rel1_relative(void);
372 static void       st_collections_group_parts_part_description_rel1_offset(void);
373 static void       st_collections_group_parts_part_description_rel1_to_set(const char *name);
374 static void       st_collections_group_parts_part_description_rel1_to(void);
375 static void       st_collections_group_parts_part_description_rel1_to_x(void);
376 static void       st_collections_group_parts_part_description_rel1_to_y(void);
377 static void       st_collections_group_parts_part_description_rel2_relative(void);
378 static void       st_collections_group_parts_part_description_rel2_offset(void);
379 static void       st_collections_group_parts_part_description_rel2_to_set(const char *name);
380 static void       st_collections_group_parts_part_description_rel2_to(void);
381 static void       st_collections_group_parts_part_description_rel2_to_x(void);
382 static void       st_collections_group_parts_part_description_rel2_to_y(void);
383 static void       st_collections_group_parts_part_description_anchors_top(void);
384 static void       st_collections_group_parts_part_description_anchors_bottom(void);
385 static void       st_collections_group_parts_part_description_anchors_left(void);
386 static void       st_collections_group_parts_part_description_anchors_right(void);
387 static void       st_collections_group_parts_part_description_anchors_vertical_center(void);
388 static void       st_collections_group_parts_part_description_anchors_horizontal_center(void);
389 static void       st_collections_group_parts_part_description_anchors_fill(void);
390 static void       st_collections_group_parts_part_description_anchors_margin(void);
391 static void       st_collections_group_parts_part_description_clip_to_id(void);
392 static void       st_collections_group_parts_part_description_size_class(void);
393 static void       st_collections_group_parts_part_description_image_normal(void);
394 static void       st_collections_group_parts_part_description_image_tween(void);
395 static void       st_collections_group_parts_part_description_image_border(void);
396 static void       st_collections_group_parts_part_description_image_middle(void);
397 static void       st_collections_group_parts_part_description_image_border_scale(void);
398 static void       st_collections_group_parts_part_description_image_border_scale_by(void);
399 static void       st_collections_group_parts_part_description_image_scale_hint(void);
400 static void       st_collections_group_parts_part_description_fill_smooth(void);
401 static void       st_collections_group_parts_part_description_fill_origin_relative(void);
402 static void       st_collections_group_parts_part_description_fill_origin_offset(void);
403 static void       st_collections_group_parts_part_description_fill_size_relative(void);
404 static void       st_collections_group_parts_part_description_fill_size_offset(void);
405 static void       st_collections_group_parts_part_description_fill_type(void);
406 static void       st_collections_group_parts_part_description_color_class(void);
407 static void       st_collections_group_parts_part_description_color(void);
408 static void       st_collections_group_parts_part_description_color2(void);
409 static void       st_collections_group_parts_part_description_color3(void);
410 static void       st_collections_group_parts_part_description_text_text(void);
411 static void       st_collections_group_parts_part_description_text_domain(void);
412 static void       st_collections_group_parts_part_description_text_text_class(void);
413 static void       st_collections_group_parts_part_description_text_font(void);
414 static void       st_collections_group_parts_part_description_text_style(void);
415 static void       st_collections_group_parts_part_description_text_repch(void);
416 static void       st_collections_group_parts_part_description_text_size(void);
417 static void       st_collections_group_parts_part_description_text_size_range(void);
418 static void       st_collections_group_parts_part_description_text_fit(void);
419 static void       st_collections_group_parts_part_description_text_fit_step(void);
420 static void       st_collections_group_parts_part_description_text_fit_size_array(void);
421 static void       st_collections_group_parts_part_description_text_min(void);
422 static void       st_collections_group_parts_part_description_text_max(void);
423 static void       st_collections_group_parts_part_description_text_align(void);
424 static void       st_collections_group_parts_part_description_text_source(void);
425 static void       st_collections_group_parts_part_description_text_text_source(void);
426 static void       st_collections_group_parts_part_description_text_ellipsis(void);
427 static void       st_collections_group_parts_part_description_box_layout(void);
428 static void       st_collections_group_parts_part_description_box_align(void);
429 static void       st_collections_group_parts_part_description_box_padding(void);
430 static void       st_collections_group_parts_part_description_box_min(void);
431 static void       st_collections_group_parts_part_description_table_homogeneous(void);
432 static void       st_collections_group_parts_part_description_table_align(void);
433 static void       st_collections_group_parts_part_description_table_padding(void);
434 static void       st_collections_group_parts_part_description_table_min(void);
435 static void       st_collections_group_parts_part_description_proxy_source_visible(void);
436 static void       st_collections_group_parts_part_description_proxy_source_clip(void);
437 static void       st_collections_group_parts_part_description_offset_scale(void);
438 static void       st_collections_group_parts_part_description_filter_code(void);
439 static void       st_collections_group_parts_part_description_filter_source(void);
440 static void       st_collections_group_parts_part_description_filter_data(void);
441 
442 #ifdef HAVE_EPHYSICS
443 static void       st_collections_group_parts_part_description_physics_mass(void);
444 static void       st_collections_group_parts_part_description_physics_restitution(void);
445 static void       st_collections_group_parts_part_description_physics_friction(void);
446 static void       st_collections_group_parts_part_description_physics_damping(void);
447 static void       st_collections_group_parts_part_description_physics_sleep(void);
448 static void       st_collections_group_parts_part_description_physics_material(void);
449 static void       st_collections_group_parts_part_description_physics_density(void);
450 static void       st_collections_group_parts_part_description_physics_hardness(void);
451 static void       st_collections_group_parts_part_description_physics_ignore_part_pos(void);
452 static void       st_collections_group_parts_part_description_physics_light_on(void);
453 static void       st_collections_group_parts_part_description_physics_z(void);
454 static void       st_collections_group_parts_part_description_physics_depth(void);
455 static void       st_collections_group_parts_part_description_physics_movement_freedom_linear(void);
456 static void       st_collections_group_parts_part_description_physics_movement_freedom_angular(void);
457 static void       st_collections_group_parts_part_description_physics_backface_cull(void);
458 static void       st_collections_group_parts_part_description_physics_face(void);
459 static void       st_collections_group_parts_part_description_physics_face_type(void);
460 static void       st_collections_group_parts_part_description_physics_face_source(void);
461 #endif
462 static void       st_collections_group_parts_part_description_map_perspective(void);
463 static void       st_collections_group_parts_part_description_map_light(void);
464 static void       st_collections_group_parts_part_description_map_rotation_center(void);
465 static void       st_collections_group_parts_part_description_map_rotation_x(void);
466 static void       st_collections_group_parts_part_description_map_rotation_y(void);
467 static void       st_collections_group_parts_part_description_map_rotation_z(void);
468 static void       st_collections_group_parts_part_description_map_on(void);
469 static void       st_collections_group_parts_part_description_map_smooth(void);
470 static void       st_collections_group_parts_part_description_map_alpha(void);
471 static void       st_collections_group_parts_part_description_map_backface_cull(void);
472 static void       st_collections_group_parts_part_description_map_perspective_on(void);
473 static void       st_collections_group_parts_part_description_map_color(void);
474 static void       st_collections_group_parts_part_description_map_zoom_x(void);
475 static void       st_collections_group_parts_part_description_map_zoom_y(void);
476 static void       st_collections_group_parts_part_description_map_zoom_center(void);
477 static void       st_collections_group_parts_part_description_perspective_zplane(void);
478 static void       st_collections_group_parts_part_description_perspective_focal(void);
479 static void       st_collections_group_parts_part_api(void);
480 
481 /* external part parameters */
482 static void       st_collections_group_parts_part_description_params_int(void);
483 static void       st_collections_group_parts_part_description_params_double(void);
484 static void       st_collections_group_parts_part_description_params_string(void);
485 static void       st_collections_group_parts_part_description_params_bool(void);
486 static void       st_collections_group_parts_part_description_params_choice(void);
487 static void       st_collections_group_parts_part_description_params_smart(void);
488 
489 /* vector part parameter */
490 static void       st_collections_group_parts_part_description_vector_frame(void);
491 
492 static void       ob_collections_group_programs_program(void);
493 static void       st_collections_group_programs_program_name(void);
494 static void       st_collections_group_programs_program_signal(void);
495 static void       st_collections_group_programs_program_source(void);
496 static void       st_collections_group_programs_program_filter(void);
497 static void       st_collections_group_programs_program_in(void);
498 static void       st_collections_group_programs_program_action(void);
499 static void       st_collections_group_programs_program_transition(void);
500 static void       st_collections_group_programs_program_target(void);
501 static void       st_collections_group_programs_program_targets(void);
502 static void       st_collections_group_programs_program_target_groups(void);
503 static void       st_collections_group_programs_program_after(void);
504 static void       st_collections_group_programs_program_api(void);
505 static void       st_collections_group_target_group(void);
506 
507 static void       ob_collections_group_programs_program_sequence(void);
508 
509 static void       ob_collections_group_programs_program_script(void);
510 static void       st_collections_group_sound_sample_name(void);
511 static void       st_collections_group_sound_sample_source(void);
512 static void       st_collections_group_sound_tone(void);
513 static void       st_collections_group_vibration_sample_name(void);
514 static void       st_collections_group_vibration_sample_source(void);
515 
516 static void       st_collections_group_translation_file_locale(void);
517 static void       st_collections_group_translation_file_source(void);
518 #ifdef HAVE_EPHYSICS
519 static void       st_collections_group_physics_world_gravity(void);
520 static void       st_collections_group_physics_world_rate(void);
521 static void       st_collections_group_physics_world_z(void);
522 static void       st_collections_group_physics_world_depth(void);
523 #endif
524 
525 /* short */
526 static void       st_collections_group_parts_part_noscale(void);
527 static void       st_collections_group_parts_part_precise(void);
528 static void       st_collections_group_parts_part_noprecise(void);
529 static void       st_collections_group_parts_part_mouse(void);
530 static void       st_collections_group_parts_part_nomouse(void);
531 static void       st_collections_group_parts_part_repeat(void);
532 static void       st_collections_group_parts_part_norepeat(void);
533 static void       st_collections_group_parts_part_description_vis(void);
534 static void       st_collections_group_parts_part_description_hid(void);
535 static void       ob_collections_group_parts_part_short(void);
536 
537 static void       st_collections_group_mouse(void);
538 static void       st_collections_group_nomouse(void);
539 static void       st_collections_group_broadcast(void);
540 static void       st_collections_group_nobroadcast(void);
541 static void       st_collections_group_noinherit_script(void);
542 
543 static void       st_images_vector(void);
544 static void       _handle_vector_image(void);
545 
546 /*****/
547 
548 #define STRDUP(x) eina_strdup(x)
549 
550 #define IMAGE_STATEMENTS(PREFIX)                                  \
551   {PREFIX "images.image", st_images_image},                       \
552   {PREFIX "images.vector", st_images_vector},                     \
553   {PREFIX "images.set.name", st_images_set_name},                 \
554   {PREFIX "images.set.image.image", st_images_set_image_image},   \
555   {PREFIX "images.set.image.size", st_images_set_image_size},     \
556   {PREFIX "images.set.image.border", st_images_set_image_border}, \
557   {PREFIX "images.set.image.scale_by", st_images_set_image_border_scale_by},
558 
559 #define IMAGE_SET_STATEMENTS(PREFIX)                                    \
560   {PREFIX ".image", st_images_image},   /* dup */                       \
561   {PREFIX ".set.name", st_images_set_name},   /* dup */                 \
562   {PREFIX ".set.image.image", st_images_set_image_image},   /* dup */   \
563   {PREFIX ".set.image.size", st_images_set_image_size},   /* dup */     \
564   {PREFIX ".set.image.border", st_images_set_image_border},   /* dup */ \
565   {PREFIX ".set.image.scale_by", st_images_set_image_border_scale_by},   /* dup */
566 
567 #define FONT_STYLE_CC_STATEMENTS(PREFIX)                                             \
568   {PREFIX "fonts.font", st_fonts_font},   /* dup */                                  \
569   {PREFIX "styles.style.name", st_styles_style_name},   /* dup */                    \
570   {PREFIX "styles.style.base", st_styles_style_base},   /* dup */                    \
571   {PREFIX "styles.style.tag", st_styles_style_tag},   /* dup */                      \
572   {PREFIX "color_classes.color_class.name", st_color_class_name},   /* dup */        \
573   {PREFIX "color_classes.color_class.color", st_color_class_color},   /* dup */      \
574   {PREFIX "color_classes.color_class.color2", st_color_class_color2},   /* dup */    \
575   {PREFIX "color_classes.color_class.color3", st_color_class_color3},   /* dup */    \
576   {PREFIX "color_classes.color_class.description", st_color_class_desc},   /* dup */ \
577   {PREFIX "color_classes.color_class.desc", st_color_class_desc},   /* dup */
578 
579 #define TEXT_CLASS_STATEMENTS(PREFIX)                                      \
580   {PREFIX "text_classes.text_class.name", st_text_class_name},   /* dup */ \
581   {PREFIX "text_classes.text_class.font", st_text_class_font},   /* dup */ \
582   {PREFIX "text_classes.text_class.size", st_text_class_size},   /* dup */
583 
584 #define SIZE_CLASS_STATEMENTS(PREFIX)                                      \
585   {PREFIX "size_classes.size_class.name", st_size_class_name},   /* dup */ \
586   {PREFIX "size_classes.size_class.min", st_size_class_min},   /* dup */   \
587   {PREFIX "size_classes.size_class.max", st_size_class_max},   /* dup */
588 
589 #define PROGRAM_SEQUENCE(PREFIX, NAME, FN)  \
590   {PREFIX ".program."NAME, FN},   /* dup */ \
591   {PREFIX ".program.sequence."NAME, FN},   /* dup */
592 
593 #define PROGRAM_BASE(PREFIX)                                                                     \
594   PROGRAM_SEQUENCE(PREFIX, "name", st_collections_group_programs_program_name)                   \
595   PROGRAM_SEQUENCE(PREFIX, "signal", st_collections_group_programs_program_signal)               \
596   PROGRAM_SEQUENCE(PREFIX, "source", st_collections_group_programs_program_source)               \
597   PROGRAM_SEQUENCE(PREFIX, "in", st_collections_group_programs_program_in)                       \
598   PROGRAM_SEQUENCE(PREFIX, "action", st_collections_group_programs_program_action)               \
599   PROGRAM_SEQUENCE(PREFIX, "transition", st_collections_group_programs_program_transition)       \
600   PROGRAM_SEQUENCE(PREFIX, "target", st_collections_group_programs_program_target)               \
601   PROGRAM_SEQUENCE(PREFIX, "target_groups", st_collections_group_programs_program_target_groups) \
602   PROGRAM_SEQUENCE(PREFIX, "groups", st_collections_group_programs_program_target_groups)        \
603   PROGRAM_SEQUENCE(PREFIX, "targets", st_collections_group_programs_program_targets)             \
604   PROGRAM_SEQUENCE(PREFIX, "after", st_collections_group_programs_program_after)                 \
605   PROGRAM_SEQUENCE(PREFIX, "api", st_collections_group_programs_program_api)                     \
606   PROGRAM_SEQUENCE(PREFIX, "filter", st_collections_group_programs_program_filter)
607 
608 #define PROGRAM_STATEMENTS(PREFIX)                            \
609   IMAGE_SET_STATEMENTS(PREFIX ".programs")                    \
610   IMAGE_STATEMENTS(PREFIX ".programs.")                       \
611   IMAGE_SET_STATEMENTS(PREFIX ".programs")                    \
612   {PREFIX ".programs.font", st_fonts_font},   /* dup */       \
613   {PREFIX ".programs.fonts.font", st_fonts_font},   /* dup */ \
614   PROGRAM_BASE(PREFIX)                                        \
615   PROGRAM_BASE(PREFIX ".programs")
616 
617 #define FILTERS_STATEMENTS(PREFIX)                        \
618   {PREFIX "filters.filter.file", st_filters_filter_file}, \
619   {PREFIX "filters.filter.name", st_filters_filter_name},
620 
621 New_Statement_Handler statement_handlers[] =
622 {
623    {"id", st_id},
624    {"requires", st_requires},
625    {"efl_version", st_efl_version},
626    {"externals.external", st_externals_external},
627    IMAGE_STATEMENTS("")
628    FONT_STYLE_CC_STATEMENTS("")
629    TEXT_CLASS_STATEMENTS("")
630    SIZE_CLASS_STATEMENTS("")
631    {
632       "data.item", st_data_item
633    },
634    {"data.file", st_data_file},
635    FILTERS_STATEMENTS("")
636    {
637       "collections.externals.external", st_externals_external
638    },                                                           /* dup */
639    IMAGE_STATEMENTS("collections.")
640    IMAGE_SET_STATEMENTS("collections")
641    {
642       "collections.font", st_fonts_font
643    },                                     /* dup */
644    FONT_STYLE_CC_STATEMENTS("collections.")
645    TEXT_CLASS_STATEMENTS("collections.")
646    SIZE_CLASS_STATEMENTS("collections.")
647    {
648       "collections.base_scale", st_collections_base_scale
649    },
650    {"collections.translation.file.locale", st_collections_group_translation_file_locale},
651    {"collections.translation.file.source", st_collections_group_translation_file_source},
652    {"collections.group.translation.file.locale", st_collections_group_translation_file_locale},
653    {"collections.group.translation.file.source", st_collections_group_translation_file_source},
654 
655    {"collections.sounds.sample.name", st_collections_group_sound_sample_name},
656    {"collections.sounds.sample.source", st_collections_group_sound_sample_source},
657    {"collections.group.sounds.sample.name", st_collections_group_sound_sample_name},   /* dup */
658    {"collections.group.sounds.sample.source", st_collections_group_sound_sample_source},   /* dup */
659    {"collections.sounds.tone", st_collections_group_sound_tone},
660    {"collections.group.sounds.tone", st_collections_group_sound_tone},   /* dup */
661    {"collections.vibrations.sample.name", st_collections_group_vibration_sample_name},
662    {"collections.vibrations.sample.source", st_collections_group_vibration_sample_source},
663    FILTERS_STATEMENTS("collections.")   /* dup */
664    {
665       "collections.group.vibrations.sample.name", st_collections_group_vibration_sample_name
666    },                                                                                          /* dup */
667    {"collections.group.vibrations.sample.source", st_collections_group_vibration_sample_source},   /* dup */
668    {"collections.group.name", st_collections_group_name},
669    {"collections.group.skip_namespace_validation", st_collections_group_skip_namespace_validation},
670    {"collections.group.program_source", st_collections_group_program_source},
671    {"collections.group.inherit", st_collections_group_inherit},
672    {"collections.group.inherit_only", st_collections_group_inherit_only},
673    {"collections.group.use_custom_seat_names", st_collections_group_use_custom_seat_names},
674    {"collections.group.target_group", st_collections_group_target_group},   /* dup */
675    {"collections.group.part_remove", st_collections_group_part_remove},
676    {"collections.group.program_remove", st_collections_group_program_remove},
677    {"collections.group.lua_script_only", st_collections_group_lua_script_only},
678    {"collections.group.script_recursion", st_collections_group_script_recursion},
679    {"collections.group.alias", st_collections_group_alias},
680    {"collections.group.min", st_collections_group_min},
681    {"collections.group.max", st_collections_group_max},
682    {"collections.group.broadcast_signal", st_collections_group_broadcast_signal},
683    {"collections.group.orientation", st_collections_group_orientation},
684    {"collections.group.mouse_events", st_collections_group_mouse_events},
685    {"collections.group.inherit_script", st_collections_group_inherit_script},
686    {"collections.group.data.item", st_collections_group_data_item},
687    {"collections.group.limits.horizontal", st_collections_group_limits_horizontal},
688    {"collections.group.limits.vertical", st_collections_group_limits_vertical},
689    {"collections.group.externals.external", st_externals_external},   /* dup */
690    {"collections.group.programs.target_group", st_collections_group_target_group},   /* dup */
691    IMAGE_SET_STATEMENTS("collections.group")
692    IMAGE_STATEMENTS("collections.group.")
693    {"collections.group.font", st_fonts_font},   /* dup */
694    FONT_STYLE_CC_STATEMENTS("collections.group.")
695    TEXT_CLASS_STATEMENTS("collections.group.")
696    SIZE_CLASS_STATEMENTS("collections.group.")
697    {
698       "collections.group.parts.alias", st_collections_group_parts_alias
699    },
700    IMAGE_SET_STATEMENTS("collections.group.parts")
701    IMAGE_STATEMENTS("collections.group.parts.")
702    {
703       "collections.group.parts.font", st_fonts_font
704    },                                                 /* dup */
705    FONT_STYLE_CC_STATEMENTS("collections.group.parts.")
706    TEXT_CLASS_STATEMENTS("collections.group.parts.")
707    SIZE_CLASS_STATEMENTS("collections.group.parts.")
708    {
709       "collections.group.parts.target_group", st_collections_group_target_group
710    },                                                                             /* dup */
711    {"collections.group.parts.part.name", st_collections_group_parts_part_name},
712    {"collections.group.parts.part.target_group", st_collections_group_target_group},   /* dup */
713    {"collections.group.parts.part.inherit", st_collections_group_parts_part_inherit},
714    {"collections.group.parts.part.api", st_collections_group_parts_part_api},
715    {"collections.group.parts.part.type", st_collections_group_parts_part_type},
716 #ifdef HAVE_EPHYSICS
717    {"collections.group.parts.part.physics_body", st_collections_group_parts_part_physics_body},
718 #endif
719    {"collections.group.parts.part.insert_before", st_collections_group_parts_part_insert_before},
720    {"collections.group.parts.part.insert_after", st_collections_group_parts_part_insert_after},
721    {"collections.group.parts.part.effect", st_collections_group_parts_part_effect},
722    {"collections.group.parts.part.mouse_events", st_collections_group_parts_part_mouse_events},
723    {"collections.group.parts.part.anti_alias", st_collections_group_parts_part_anti_alias},
724    {"collections.group.parts.part.repeat_events", st_collections_group_parts_part_repeat_events},
725    {"collections.group.parts.part.ignore_flags", st_collections_group_parts_part_ignore_flags},
726    {"collections.group.parts.part.mask_flags", st_collections_group_parts_part_mask_flags},
727    {"collections.group.parts.part.scale", st_collections_group_parts_part_scale},
728    {"collections.group.parts.part.pointer_mode", st_collections_group_parts_part_pointer_mode},
729    {"collections.group.parts.part.precise_is_inside", st_collections_group_parts_part_precise_is_inside},
730    {"collections.group.parts.part.use_alternate_font_metrics", st_collections_group_parts_part_use_alternate_font_metrics},
731    {"collections.group.parts.part.clip_to", st_collections_group_parts_part_clip_to_id},
732    {"collections.group.parts.part.no_render", st_collections_group_parts_part_no_render},
733    {"collections.group.parts.part.required", st_collections_group_parts_part_required},
734    {"collections.group.parts.part.source", st_collections_group_parts_part_source},
735    {"collections.group.parts.part.source2", st_collections_group_parts_part_source2},
736    {"collections.group.parts.part.source3", st_collections_group_parts_part_source3},
737    {"collections.group.parts.part.source4", st_collections_group_parts_part_source4},
738    {"collections.group.parts.part.source5", st_collections_group_parts_part_source5},
739    {"collections.group.parts.part.source6", st_collections_group_parts_part_source6},
740    {"collections.group.parts.part.dragable.x", st_collections_group_parts_part_dragable_x},
741    {"collections.group.parts.part.dragable.y", st_collections_group_parts_part_dragable_y},
742    {"collections.group.parts.part.dragable.confine", st_collections_group_parts_part_dragable_confine},
743    {"collections.group.parts.part.dragable.threshold", st_collections_group_parts_part_dragable_threshold},
744    {"collections.group.parts.part.dragable.events", st_collections_group_parts_part_dragable_events},
745    {"collections.group.parts.part.entry_mode", st_collections_group_parts_part_entry_mode},
746    {"collections.group.parts.part.select_mode", st_collections_group_parts_part_select_mode},
747    {"collections.group.parts.part.cursor_mode", st_collections_group_parts_part_cursor_mode},
748    {"collections.group.parts.part.multiline", st_collections_group_parts_part_multiline},
749    {"collections.group.parts.part.access", st_collections_group_parts_part_access},
750    {"collections.group.parts.part.allowed_seats", st_collections_group_parts_part_allowed_seats},
751    IMAGE_SET_STATEMENTS("collections.group.parts.part")
752    IMAGE_STATEMENTS("collections.group.parts.part.")
753    {
754       "collections.group.parts.part.font", st_fonts_font
755    },                                                      /* dup */
756    FONT_STYLE_CC_STATEMENTS("collections.group.parts.part.")
757    TEXT_CLASS_STATEMENTS("collections.group.parts.part.")
758    SIZE_CLASS_STATEMENTS("collections.group.parts.part.")
759    {
760       "collections.group.parts.part.box.items.item.type", st_collections_group_parts_part_box_items_item_type
761    },
762    {"collections.group.parts.part.box.items.item.name", st_collections_group_parts_part_box_items_item_name},
763    {"collections.group.parts.part.box.items.item.source", st_collections_group_parts_part_box_items_item_source},
764    {"collections.group.parts.part.box.items.item.min", st_collections_group_parts_part_box_items_item_min},
765    {"collections.group.parts.part.box.items.item.spread", st_collections_group_parts_part_box_items_item_spread},
766    {"collections.group.parts.part.box.items.item.prefer", st_collections_group_parts_part_box_items_item_prefer},
767    {"collections.group.parts.part.box.items.item.max", st_collections_group_parts_part_box_items_item_max},
768    {"collections.group.parts.part.box.items.item.padding", st_collections_group_parts_part_box_items_item_padding},
769    {"collections.group.parts.part.box.items.item.align", st_collections_group_parts_part_box_items_item_align},
770    {"collections.group.parts.part.box.items.item.weight", st_collections_group_parts_part_box_items_item_weight},
771    {"collections.group.parts.part.box.items.item.aspect", st_collections_group_parts_part_box_items_item_aspect},
772    {"collections.group.parts.part.box.items.item.aspect_mode", st_collections_group_parts_part_box_items_item_aspect_mode},
773    {"collections.group.parts.part.box.items.item.options", st_collections_group_parts_part_box_items_item_options},
774    {"collections.group.parts.part.table.items.item.type", st_collections_group_parts_part_box_items_item_type},   /* dup */
775    {"collections.group.parts.part.table.items.item.name", st_collections_group_parts_part_box_items_item_name},   /* dup */
776    {"collections.group.parts.part.table.items.item.source", st_collections_group_parts_part_box_items_item_source},   /* dup */
777    {"collections.group.parts.part.table.items.item.min", st_collections_group_parts_part_box_items_item_min},   /* dup */
778    {"collections.group.parts.part.table.items.item.spread", st_collections_group_parts_part_box_items_item_spread},   /* dup */
779    {"collections.group.parts.part.table.items.item.prefer", st_collections_group_parts_part_box_items_item_prefer},   /* dup */
780    {"collections.group.parts.part.table.items.item.max", st_collections_group_parts_part_box_items_item_max},   /* dup */
781    {"collections.group.parts.part.table.items.item.padding", st_collections_group_parts_part_box_items_item_padding},   /* dup */
782    {"collections.group.parts.part.table.items.item.align", st_collections_group_parts_part_box_items_item_align},   /* dup */
783    {"collections.group.parts.part.table.items.item.weight", st_collections_group_parts_part_box_items_item_weight},   /* dup */
784    {"collections.group.parts.part.table.items.item.aspect", st_collections_group_parts_part_box_items_item_aspect},   /* dup */
785    {"collections.group.parts.part.table.items.item.aspect_mode", st_collections_group_parts_part_box_items_item_aspect_mode},   /* dup */
786    {"collections.group.parts.part.table.items.item.options", st_collections_group_parts_part_box_items_item_options},   /* dup */
787    {"collections.group.parts.part.table.items.item.position", st_collections_group_parts_part_table_items_item_position},
788    {"collections.group.parts.part.table.items.item.span", st_collections_group_parts_part_table_items_item_span},
789    {"collections.group.parts.part.description.target_group", st_collections_group_target_group},   /* dup */
790    {"collections.group.parts.part.description.inherit", st_collections_group_parts_part_description_inherit},
791    {"collections.group.parts.part.description.link.base", st_collections_group_parts_part_description_link_base},
792    {"collections.group.parts.part.description.link.transition", st_collections_group_programs_program_transition},
793    {"collections.group.parts.part.description.link.after", st_collections_group_programs_program_after},
794    {"collections.group.parts.part.description.link.in", st_collections_group_programs_program_in},
795    {"collections.group.parts.part.description.source", st_collections_group_parts_part_description_source},
796    {"collections.group.parts.part.description.state", st_collections_group_parts_part_description_state},
797    {"collections.group.parts.part.description.visible", st_collections_group_parts_part_description_visible},
798    {"collections.group.parts.part.description.limit", st_collections_group_parts_part_description_limit},
799    {"collections.group.parts.part.description.no_render", st_collections_group_parts_part_description_no_render},
800    {"collections.group.parts.part.description.align", st_collections_group_parts_part_description_align},
801    {"collections.group.parts.part.description.fixed", st_collections_group_parts_part_description_fixed},
802    {"collections.group.parts.part.description.min", st_collections_group_parts_part_description_min},
803    {"collections.group.parts.part.description.minmul", st_collections_group_parts_part_description_minmul},
804    {"collections.group.parts.part.description.max", st_collections_group_parts_part_description_max},
805    {"collections.group.parts.part.description.step", st_collections_group_parts_part_description_step},
806    {"collections.group.parts.part.description.aspect", st_collections_group_parts_part_description_aspect},
807    {"collections.group.parts.part.description.aspect_preference", st_collections_group_parts_part_description_aspect_preference},
808    {"collections.group.parts.part.description.rel.to", st_collections_group_parts_part_description_rel_to},
809    {"collections.group.parts.part.description.rel.to_x", st_collections_group_parts_part_description_rel_to_x},
810    {"collections.group.parts.part.description.rel.to_y", st_collections_group_parts_part_description_rel_to_y},
811    {"collections.group.parts.part.description.rel1.relative", st_collections_group_parts_part_description_rel1_relative},
812    {"collections.group.parts.part.description.rel1.offset", st_collections_group_parts_part_description_rel1_offset},
813    {"collections.group.parts.part.description.rel1.to", st_collections_group_parts_part_description_rel1_to},
814    {"collections.group.parts.part.description.rel1.to_x", st_collections_group_parts_part_description_rel1_to_x},
815    {"collections.group.parts.part.description.rel1.to_y", st_collections_group_parts_part_description_rel1_to_y},
816    {"collections.group.parts.part.description.rel2.relative", st_collections_group_parts_part_description_rel2_relative},
817    {"collections.group.parts.part.description.rel2.offset", st_collections_group_parts_part_description_rel2_offset},
818    {"collections.group.parts.part.description.rel2.to", st_collections_group_parts_part_description_rel2_to},
819    {"collections.group.parts.part.description.rel2.to_x", st_collections_group_parts_part_description_rel2_to_x},
820    {"collections.group.parts.part.description.rel2.to_y", st_collections_group_parts_part_description_rel2_to_y},
821    {"collections.group.parts.part.description.offset_scale", st_collections_group_parts_part_description_offset_scale},
822    {"collections.group.parts.part.description.anchors.top", st_collections_group_parts_part_description_anchors_top},
823    {"collections.group.parts.part.description.anchors.bottom", st_collections_group_parts_part_description_anchors_bottom},
824    {"collections.group.parts.part.description.anchors.left", st_collections_group_parts_part_description_anchors_left},
825    {"collections.group.parts.part.description.anchors.right", st_collections_group_parts_part_description_anchors_right},
826    {"collections.group.parts.part.description.anchors.vertical_center", st_collections_group_parts_part_description_anchors_vertical_center},
827    {"collections.group.parts.part.description.anchors.horizontal_center", st_collections_group_parts_part_description_anchors_horizontal_center},
828    {"collections.group.parts.part.description.anchors.fill", st_collections_group_parts_part_description_anchors_fill},
829    {"collections.group.parts.part.description.anchors.margin", st_collections_group_parts_part_description_anchors_margin},
830    {"collections.group.parts.part.description.clip_to", st_collections_group_parts_part_description_clip_to_id},
831    {"collections.group.parts.part.description.size_class", st_collections_group_parts_part_description_size_class},
832    {"collections.group.parts.part.description.image.normal", st_collections_group_parts_part_description_image_normal},
833    {"collections.group.parts.part.description.image.tween", st_collections_group_parts_part_description_image_tween},
834    IMAGE_SET_STATEMENTS("collections.group.parts.part.description.image")
835    IMAGE_STATEMENTS("collections.group.parts.part.description.image.")
836    {
837       "collections.group.parts.part.description.image.border", st_collections_group_parts_part_description_image_border
838    },
839    {"collections.group.parts.part.description.image.middle", st_collections_group_parts_part_description_image_middle},
840    {"collections.group.parts.part.description.image.border_scale", st_collections_group_parts_part_description_image_border_scale},
841    {"collections.group.parts.part.description.image.border_scale_by", st_collections_group_parts_part_description_image_border_scale_by},
842    {"collections.group.parts.part.description.image.scale_hint", st_collections_group_parts_part_description_image_scale_hint},
843    {"collections.group.parts.part.description.fill.smooth", st_collections_group_parts_part_description_fill_smooth},
844    {"collections.group.parts.part.description.fill.origin.relative", st_collections_group_parts_part_description_fill_origin_relative},
845    {"collections.group.parts.part.description.fill.origin.offset", st_collections_group_parts_part_description_fill_origin_offset},
846    {"collections.group.parts.part.description.fill.size.relative", st_collections_group_parts_part_description_fill_size_relative},
847    {"collections.group.parts.part.description.fill.size.offset", st_collections_group_parts_part_description_fill_size_offset},
848    {"collections.group.parts.part.description.fill.type", st_collections_group_parts_part_description_fill_type},
849    {"collections.group.parts.part.description.color_class", st_collections_group_parts_part_description_color_class},
850    {"collections.group.parts.part.description.color", st_collections_group_parts_part_description_color},
851    {"collections.group.parts.part.description.color2", st_collections_group_parts_part_description_color2},
852    {"collections.group.parts.part.description.color3", st_collections_group_parts_part_description_color3},
853    {"collections.group.parts.part.description.text.text", st_collections_group_parts_part_description_text_text},
854    {"collections.group.parts.part.description.text.domain", st_collections_group_parts_part_description_text_domain},
855    {"collections.group.parts.part.description.text.text_class", st_collections_group_parts_part_description_text_text_class},
856    {"collections.group.parts.part.description.text.font", st_collections_group_parts_part_description_text_font},
857    {"collections.group.parts.part.description.text.style", st_collections_group_parts_part_description_text_style},
858    {"collections.group.parts.part.description.text.repch", st_collections_group_parts_part_description_text_repch},
859    {"collections.group.parts.part.description.text.size", st_collections_group_parts_part_description_text_size},
860    {"collections.group.parts.part.description.text.size_range", st_collections_group_parts_part_description_text_size_range},
861    {"collections.group.parts.part.description.text.fit", st_collections_group_parts_part_description_text_fit},
862    {"collections.group.parts.part.description.text.fit_step", st_collections_group_parts_part_description_text_fit_step},
863    {"collections.group.parts.part.description.text.fit_size_array", st_collections_group_parts_part_description_text_fit_size_array},
864    {"collections.group.parts.part.description.text.min", st_collections_group_parts_part_description_text_min},
865    {"collections.group.parts.part.description.text.max", st_collections_group_parts_part_description_text_max},
866    {"collections.group.parts.part.description.text.align", st_collections_group_parts_part_description_text_align},
867    {"collections.group.parts.part.description.text.source", st_collections_group_parts_part_description_text_source},
868    {"collections.group.parts.part.description.text.text_source", st_collections_group_parts_part_description_text_text_source},
869    {"collections.group.parts.part.description.text.font", st_fonts_font},   /* dup */
870    {"collections.group.parts.part.description.text.fonts.font", st_fonts_font},   /* dup */
871    {"collections.group.parts.part.description.text.elipsis", st_collections_group_parts_part_description_text_ellipsis},
872    {"collections.group.parts.part.description.text.ellipsis", st_collections_group_parts_part_description_text_ellipsis},
873    {"collections.group.parts.part.description.text.filter", st_collections_group_parts_part_description_filter_code},   /* dup */
874    {"collections.group.parts.part.description.box.layout", st_collections_group_parts_part_description_box_layout},
875    {"collections.group.parts.part.description.box.align", st_collections_group_parts_part_description_box_align},
876    {"collections.group.parts.part.description.box.padding", st_collections_group_parts_part_description_box_padding},
877    {"collections.group.parts.part.description.box.min", st_collections_group_parts_part_description_box_min},
878    {"collections.group.parts.part.description.table.homogeneous", st_collections_group_parts_part_description_table_homogeneous},
879    {"collections.group.parts.part.description.table.align", st_collections_group_parts_part_description_table_align},
880    {"collections.group.parts.part.description.table.padding", st_collections_group_parts_part_description_table_padding},
881    {"collections.group.parts.part.description.table.min", st_collections_group_parts_part_description_table_min},
882    {"collections.group.parts.part.description.proxy.source_visible", st_collections_group_parts_part_description_proxy_source_visible},
883    {"collections.group.parts.part.description.proxy.source_clip", st_collections_group_parts_part_description_proxy_source_clip},
884    {"collections.group.parts.part.description.filter.code", st_collections_group_parts_part_description_filter_code},
885    {"collections.group.parts.part.description.filter.source", st_collections_group_parts_part_description_filter_source},
886    {"collections.group.parts.part.description.filter.data", st_collections_group_parts_part_description_filter_data},
887 
888 #ifdef HAVE_EPHYSICS
889    {"collections.group.parts.part.description.physics.mass", st_collections_group_parts_part_description_physics_mass},
890    {"collections.group.parts.part.description.physics.restitution", st_collections_group_parts_part_description_physics_restitution},
891    {"collections.group.parts.part.description.physics.friction", st_collections_group_parts_part_description_physics_friction},
892    {"collections.group.parts.part.description.physics.damping", st_collections_group_parts_part_description_physics_damping},
893    {"collections.group.parts.part.description.physics.sleep", st_collections_group_parts_part_description_physics_sleep},
894    {"collections.group.parts.part.description.physics.material", st_collections_group_parts_part_description_physics_material},
895    {"collections.group.parts.part.description.physics.density", st_collections_group_parts_part_description_physics_density},
896    {"collections.group.parts.part.description.physics.hardness", st_collections_group_parts_part_description_physics_hardness},
897    {"collections.group.parts.part.description.physics.movement_freedom.linear", st_collections_group_parts_part_description_physics_movement_freedom_linear},
898    {"collections.group.parts.part.description.physics.movement_freedom.angular", st_collections_group_parts_part_description_physics_movement_freedom_angular},
899    {"collections.group.parts.part.description.physics.ignore_part_pos", st_collections_group_parts_part_description_physics_ignore_part_pos},
900    {"collections.group.parts.part.description.physics.light_on", st_collections_group_parts_part_description_physics_light_on},
901    {"collections.group.parts.part.description.physics.z", st_collections_group_parts_part_description_physics_z},
902    {"collections.group.parts.part.description.physics.depth", st_collections_group_parts_part_description_physics_depth},
903    {"collections.group.parts.part.description.physics.backface_cull", st_collections_group_parts_part_description_physics_backface_cull},
904    {"collections.group.parts.part.description.physics.faces.face.type", st_collections_group_parts_part_description_physics_face_type},
905    {"collections.group.parts.part.description.physics.faces.face.source", st_collections_group_parts_part_description_physics_face_source},
906 #endif
907    {"collections.group.parts.part.description.map.perspective", st_collections_group_parts_part_description_map_perspective},
908    {"collections.group.parts.part.description.map.light", st_collections_group_parts_part_description_map_light},
909    {"collections.group.parts.part.description.map.rotation.center", st_collections_group_parts_part_description_map_rotation_center},
910    {"collections.group.parts.part.description.map.rotation.x", st_collections_group_parts_part_description_map_rotation_x},
911    {"collections.group.parts.part.description.map.rotation.y", st_collections_group_parts_part_description_map_rotation_y},
912    {"collections.group.parts.part.description.map.rotation.z", st_collections_group_parts_part_description_map_rotation_z},
913    {"collections.group.parts.part.description.map.on", st_collections_group_parts_part_description_map_on},
914    {"collections.group.parts.part.description.map.smooth", st_collections_group_parts_part_description_map_smooth},
915    {"collections.group.parts.part.description.map.alpha", st_collections_group_parts_part_description_map_alpha},
916    {"collections.group.parts.part.description.map.backface_cull", st_collections_group_parts_part_description_map_backface_cull},
917    {"collections.group.parts.part.description.map.perspective_on", st_collections_group_parts_part_description_map_perspective_on},
918    {"collections.group.parts.part.description.map.color", st_collections_group_parts_part_description_map_color},
919    {"collections.group.parts.part.description.map.zoom.x", st_collections_group_parts_part_description_map_zoom_x},
920    {"collections.group.parts.part.description.map.zoom.y", st_collections_group_parts_part_description_map_zoom_y},
921    {"collections.group.parts.part.description.map.zoom.center", st_collections_group_parts_part_description_map_zoom_center},
922    {"collections.group.parts.part.description.perspective.zplane", st_collections_group_parts_part_description_perspective_zplane},
923    {"collections.group.parts.part.description.perspective.focal", st_collections_group_parts_part_description_perspective_focal},
924    {"collections.group.parts.part.description.params.int", st_collections_group_parts_part_description_params_int},
925    {"collections.group.parts.part.description.params.double", st_collections_group_parts_part_description_params_double},
926    {"collections.group.parts.part.description.params.string", st_collections_group_parts_part_description_params_string},
927    {"collections.group.parts.part.description.params.bool", st_collections_group_parts_part_description_params_bool},
928    {"collections.group.parts.part.description.params.choice", st_collections_group_parts_part_description_params_choice},
929    {"collections.group.parts.part.description.params.*", st_collections_group_parts_part_description_params_smart},
930    {"collections.group.parts.part.description.vector.frame", st_collections_group_parts_part_description_vector_frame},
931    IMAGE_STATEMENTS("collections.group.parts.part.description.")
932    {
933       "collections.group.parts.part.description.font", st_fonts_font
934    },                                                                  /* dup */
935    FONT_STYLE_CC_STATEMENTS("collections.group.parts.part.description.")
936    TEXT_CLASS_STATEMENTS("collections.group.parts.part.description.")
937    SIZE_CLASS_STATEMENTS("collections.group.parts.part.description.")
938 #ifdef HAVE_EPHYSICS
939    {
940       "collections.group.physics.world.gravity", st_collections_group_physics_world_gravity
941    },
942    {"collections.group.physics.world.rate", st_collections_group_physics_world_rate},
943    {"collections.group.physics.world.z", st_collections_group_physics_world_z},
944    {"collections.group.physics.world.depth", st_collections_group_physics_world_depth},
945 #endif
946    FILTERS_STATEMENTS("collections.group.")   /* dup */
947    PROGRAM_STATEMENTS("collections.group.parts.part.description")
948    PROGRAM_STATEMENTS("collections.group.parts.part")
949    PROGRAM_STATEMENTS("collections.group.parts")
950    PROGRAM_STATEMENTS("collections.group")
951 };
952 
953 /** @edcsection{lazedc,
954  *              LazEDC} */
955 
956 /** @edcsubsection{lazedc_intro,
957  *                 LazEDC Intro} */
958 
959 /**
960     @page edcref
961     @block
962         LazEDC
963     @context
964         ..
965         collections.group { "test";
966            parts {
967               rect { "clip"; }
968               rect { "test"; nomouse; repeat; precise;
969                  clip: "clip";
970                  desc { "default";
971                     color: 255 0 0 255;
972                     rel2.relative: 0.5 1;
973                  }
974               }
975               rect { "test2"; inherit: "test";
976                  clip: "clip";
977                  desc { "default";
978                     rel1.relative: 0.5 0;
979                     rel2.relative: 1 1;
980                  }
981                  desc { "t2";
982                     inherit: "default";
983                     color: 0 255 0 255;
984                  }
985                  desc { "t3";
986                     inherit; // "default" can be omitted.
987                     color: 0 0 255 255;
988                  }
989               }
990               program { signal: "load"; name: "start";
991                  sequence {
992                     action: STATE_SET "t2";
993                     target: "test2";
994                     transition: LINEAR 0.6;
995                     in: 0.5 0;
996                     action: STATE_SET "t3";
997                     target: "test2";
998                     transition: LINEAR 0.3;
999                     name: "del";
1000                  }
1001               }
1002            }
1003         }
1004         ..
1005     @description
1006         LazEDC is an advanced form of EDC which allows the developer to
1007         leave out or shorten various forms. Parts can be created by using
1008         their type names, and the "name" and "state" keywords can be omitted entirely.
1009         Additionally, default description blocks will be automatically created with default
1010         values even if the description isn't explicitly specified.
1011         @note Failing to use quotes for block names will trigger syntax errors
1012         if a block name is the same as an existing EDC keyword.
1013     @since 1.10
1014     @endblock
1015  */
1016 
1017 /** @edcsubsection{lazedc_synonyms,
1018  *                 LazEDC Synonyms} */
1019 
1020 /**
1021     @page edcref
1022     @block
1023         Synonyms
1024     @context
1025     group {
1026        parts {
1027           part {
1028              before -> insert_before
1029              after -> insert_after
1030              ignore -> ignore_flags
1031              mask -> mask_flags
1032              pointer -> pointer_mode
1033              alt_font -> use_alternate_font_metrics
1034              clip -> clip_to
1035              desc {
1036                 clip -> clip_to
1037              }
1038           }
1039        }
1040     }
1041     color_class {
1042        desc -> description
1043        @since 1.14
1044     }
1045 
1046     @description
1047         These statements on the left are identical to their original keywords on the right.
1048     @since 1.10
1049     @endblock
1050  */
1051 
1052 New_Statement_Handler statement_handlers_short[] =
1053 {
1054    {"collections.group.parts.part.before", st_collections_group_parts_part_insert_before},
1055    {"collections.group.parts.part.after", st_collections_group_parts_part_insert_after},
1056    {"collections.group.parts.part.ignore", st_collections_group_parts_part_ignore_flags},
1057    {"collections.group.parts.part.mask", st_collections_group_parts_part_mask_flags},
1058    {"collections.group.parts.part.pointer", st_collections_group_parts_part_pointer_mode},
1059    {"collections.group.parts.part.alt_font", st_collections_group_parts_part_use_alternate_font_metrics},
1060    {"collections.group.parts.part.clip", st_collections_group_parts_part_clip_to_id},
1061    {"collections.group.parts.part.description.clip", st_collections_group_parts_part_description_clip_to_id},
1062 };
1063 
1064 /** @edcsubsection{lazedc_shorthand,
1065  *                 LazEDC Shorthand} */
1066 
1067 /**
1068     @page edcref
1069     @block
1070         Shorthand
1071     @context
1072     group {
1073        broadcast; -> broadcast_signal: 1;
1074        nobroadcast; -> broadcast_signal: 0;
1075        mouse; -> mouse_events: 1;
1076        nomouse; -> mouse_events: 0;
1077        inherit_script; -> inherit_script: 1;
1078        noinherit_script; -> inherit_script: 0;
1079        parts {
1080           part {
1081              mouse; -> mouse_events: 1;
1082              nomouse; -> mouse_events: 0;
1083              repeat; -> repeat_events: 1;
1084              norepeat; -> repeat_events: 0;
1085              precise; -> precise_is_inside: 1;
1086              noprecise; -> precise_is_inside: 0;
1087              render; -> no_render: 0;
1088              norender; -> no_render: 1;
1089              required; -> required: 1;
1090              norequired; -> required: 0;
1091              scale; -> scale: 1;
1092              noscale; -> scale: 0;
1093              desc {
1094                 vis; -> visible: 1;
1095                 hid; -> visible: 0;
1096                 offscale; -> offset_scale: 1;
1097              }
1098           }
1099        }
1100     }
1101 
1102     @description
1103         These statements on the left have the same meaning as statements on the right,
1104         but they are shorter.
1105     @since 1.10
1106     @endblock
1107  */
1108 New_Statement_Handler statement_handlers_short_single[] =
1109 {
1110    {"collections.group.parts.part.mouse", st_collections_group_parts_part_mouse},
1111    {"collections.group.parts.part.nomouse", st_collections_group_parts_part_nomouse},
1112    {"collections.group.parts.part.repeat", st_collections_group_parts_part_repeat},
1113    {"collections.group.parts.part.norepeat", st_collections_group_parts_part_norepeat},
1114    {"collections.group.parts.part.precise", st_collections_group_parts_part_precise},
1115    {"collections.group.parts.part.noprecise", st_collections_group_parts_part_noprecise},
1116    {"collections.group.parts.part.scale", st_collections_group_parts_part_scale},
1117    {"collections.group.parts.part.noscale", st_collections_group_parts_part_noscale},
1118    {"collections.group.parts.part.render", st_collections_group_parts_part_render},
1119    {"collections.group.parts.part.norender", st_collections_group_parts_part_no_render},
1120    {"collections.group.parts.part.required", st_collections_group_parts_part_required},
1121    {"collections.group.parts.part.norequired", st_collections_group_parts_part_norequired},
1122    {"collections.group.parts.part.description.vis", st_collections_group_parts_part_description_vis},
1123    {"collections.group.parts.part.description.hid", st_collections_group_parts_part_description_hid},
1124    {"collections.group.parts.part.description.offscale", st_collections_group_parts_part_description_offset_scale},
1125    {"collections.group.mouse", st_collections_group_mouse},
1126    {"collections.group.nomouse", st_collections_group_nomouse},
1127    {"collections.group.broadcast", st_collections_group_broadcast},
1128    {"collections.group.nobroadcast", st_collections_group_nobroadcast},
1129    {"collections.group.inherit_script", st_collections_group_inherit_script},
1130    {"collections.group.noinherit_script", st_collections_group_noinherit_script},
1131    {"collections.group.parts.part.description.inherit", st_collections_group_parts_part_description_inherit},
1132 };
1133 
1134 /** @edcsubsection{lazedc_external_params,
1135  *                 LazEDC Group.Parts.External.Desc.Params} */
1136 
1137 /**
1138     @page edcref
1139     @block
1140        params
1141     @context
1142        ...
1143        external {
1144           desc { "default";
1145              params {
1146                 number: 10;       -> int: "number" 10;
1147                 number2: 1.1;     -> double: "number2" 1.1;
1148                 label: "OK";      -> string: "label" "OK";
1149                 check: true;      -> bool: "check" 1;
1150                 check2: false;    -> bool: "check2" 0;
1151                 text_wrap: mixed; -> choice: "text_wrap" "mixed";
1152              }
1153           }
1154        }
1155        ...
1156     @description
1157        The name of parameter can be used as a statement keyword in params block.
1158        The type of parameter is determined automatically by the value,
1159        so it should follow the next rules.
1160        Number without decimal point is considered as an integer.
1161        Number with decimal point is considered as a double.
1162        Double-quoted string is considered as a string.
1163        'true' or 'false' without quotes is considred as a boolean.
1164        String without quotes except for 'true' or 'false' is considered as a choice.
1165     @since 1.18
1166     @endblock
1167  */
1168 static Edje_External_Param_Type
_parse_external_param_type(char * token)1169 _parse_external_param_type(char *token)
1170 {
1171    Eina_Bool num, point;
1172    char *s;
1173 
1174    if (param_had_quote(0))
1175      return EDJE_EXTERNAL_PARAM_TYPE_STRING;
1176 
1177    num = EINA_TRUE;
1178    point = EINA_FALSE;
1179    s = token;
1180 
1181    while (*s)
1182      {
1183         if ((*s < '0') || (*s > '9'))
1184           {
1185              if ((!point) && (*s == '.'))
1186                {
1187                   point = EINA_TRUE;
1188                }
1189              else
1190                {
1191                   num = EINA_FALSE;
1192                   break;
1193                }
1194           }
1195         s++;
1196      }
1197 
1198    if (num)
1199      {
1200         if (!point)
1201           return EDJE_EXTERNAL_PARAM_TYPE_INT;
1202         else
1203           return EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1204      }
1205    else
1206      {
1207         if (!strcmp(token, "true") || !strcmp(token, "false"))
1208           return EDJE_EXTERNAL_PARAM_TYPE_BOOL;
1209         else
1210           return EDJE_EXTERNAL_PARAM_TYPE_CHOICE;
1211      }
1212 }
1213 
1214 static void
st_collections_group_parts_part_description_params_smart(void)1215 st_collections_group_parts_part_description_params_smart(void)
1216 {
1217    Edje_Part_Description_External *ed;
1218    Edje_External_Param *param;
1219    Eina_List *l;
1220    char *last, *name, *token;
1221    int found = 0;
1222 
1223    check_arg_count(1);
1224 
1225    if (current_part->type != EDJE_PART_TYPE_EXTERNAL)
1226      {
1227         ERR("parse error %s:%i. params in non-EXTERNAL part.",
1228             file_in, line - 1);
1229         exit(-1);
1230      }
1231 
1232    ed = (Edje_Part_Description_External *)current_desc;
1233 
1234    last = eina_list_last_data_get(stack);
1235    if (!strncmp(last, "params.", strlen("params.")))
1236      name = strdup(last + strlen("params."));
1237    else
1238      name = strdup(last);
1239 
1240    /* if a param with this name already exists, overwrite it */
1241    EINA_LIST_FOREACH(ed->external_params, l, param)
1242      {
1243         if (!strcmp(param->name, name))
1244           {
1245              found = 1;
1246              free(name);
1247              break;
1248           }
1249      }
1250 
1251    if (!found)
1252      {
1253         param = mem_alloc(SZ(Edje_External_Param));
1254         param->name = name;
1255      }
1256 
1257    token = parse_str(0);
1258 
1259    param->type = _parse_external_param_type(token);
1260    param->i = 0;
1261    param->d = 0;
1262    param->s = NULL;
1263 
1264    switch (param->type)
1265      {
1266       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1267         if (!strcmp(token, "true"))
1268           param->i = 1;
1269         else if (!strcmp(token, "false"))
1270           param->i = 0;
1271         break;
1272 
1273       case EDJE_EXTERNAL_PARAM_TYPE_INT:
1274         param->i = parse_int(0);
1275         break;
1276 
1277       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1278         param->d = parse_float(0);
1279         break;
1280 
1281       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1282       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1283         param->s = parse_str(0);
1284         break;
1285 
1286       default:
1287         ERR("parse error %s:%i. Invalid param type.",
1288             file_in, line - 1);
1289         break;
1290      }
1291 
1292    if (!found)
1293      ed->external_params = eina_list_append(ed->external_params, param);
1294 
1295    free(token);
1296 }
1297 
1298 #define PROGRAM_OBJECTS(PREFIX)                                                                           \
1299   {PREFIX ".program", ob_collections_group_programs_program},   /* dup */                                 \
1300   {PREFIX ".program.script", ob_collections_group_programs_program_script},   /* dup */                   \
1301   {PREFIX ".program.sequence.script", ob_collections_group_programs_program_script},   /* dup */          \
1302   {PREFIX ".program.sequence", ob_collections_group_programs_program_sequence},   /* dup */               \
1303   {PREFIX ".programs", NULL},   /* dup */                                                                 \
1304   {PREFIX ".programs.set", ob_images_set},   /* dup */                                                    \
1305   {PREFIX ".programs.set.image", ob_images_set_image},   /* dup */                                        \
1306   {PREFIX ".programs.images", NULL},   /* dup */                                                          \
1307   {PREFIX ".programs.images.set", ob_images_set},   /* dup */                                             \
1308   {PREFIX ".programs.images.set.image", ob_images_set_image},   /* dup */                                 \
1309   {PREFIX ".programs.fonts", NULL},   /* dup */                                                           \
1310   {PREFIX ".programs.program", ob_collections_group_programs_program},   /* dup */                        \
1311   {PREFIX ".programs.program.script", ob_collections_group_programs_program_script},   /* dup */          \
1312   {PREFIX ".programs.program.sequence", ob_collections_group_programs_program_sequence},   /* dup */      \
1313   {PREFIX ".programs.program.sequence.script", ob_collections_group_programs_program_script},   /* dup */ \
1314   {PREFIX ".programs.script", ob_collections_group_script},   /* dup */                                   \
1315   {PREFIX ".script", ob_collections_group_script},   /* dup */
1316 
1317 New_Object_Handler object_handlers[] =
1318 {
1319    {"externals", NULL},
1320    {"images", NULL},
1321    {"images.set", ob_images_set},
1322    {"images.set.image", ob_images_set_image},
1323    {"fonts", NULL},
1324    {"data", NULL},
1325    {"styles", NULL},
1326    {"styles.style", ob_styles_style},
1327    {"color_tree", ob_color_tree},
1328    {"color_classes", NULL},
1329    {"color_classes.color_class", ob_color_class},
1330    {"text_classes", NULL},
1331    {"text_classes.text_class", ob_text_class},
1332    {"size_classes", NULL},
1333    {"size_classes.size_class", ob_size_class},
1334    {"spectra", NULL},
1335    {"filters", NULL},
1336    {"filters.filter", ob_filters_filter},
1337    {"filters.filter.script", ob_filters_filter_script},
1338    {"collections", ob_collections},
1339    {"collections.externals", NULL},   /* dup */
1340    {"collections.set", ob_images_set},   /* dup */
1341    {"collections.set.image", ob_images_set_image},   /* dup */
1342    {"collections.images", NULL},   /* dup */
1343    {"collections.images.set", ob_images_set},   /* dup */
1344    {"collections.images.set.image", ob_images_set_image},   /* dup */
1345    {"collections.fonts", NULL},   /* dup */
1346    {"collections.styles", NULL},   /* dup */
1347    {"collections.styles.style", ob_styles_style},   /* dup */
1348    {"collections.color_tree", ob_color_tree},   /* dup */
1349    {"collections.color_classes", NULL},   /* dup */
1350    {"collections.color_classes.color_class", ob_color_class},   /* dup */
1351    {"collections.text_classes", NULL},
1352    {"collections.text_classes.text_class", ob_text_class},   /* dup */
1353    {"collections.size_classes", NULL},   /* dup */
1354    {"collections.size_classes.size_class", ob_size_class},   /* dup */
1355    {"collections.sounds", NULL},
1356    {"collections.group.sounds", NULL},   /* dup */
1357    {"collections.sounds.sample", NULL},
1358    {"collections.translation", NULL},
1359    {"collections.translation.file", NULL},
1360    {"collections.group.translation", NULL},  /*dup*/
1361    {"collections.group.translation.file", NULL},  /*dup*/
1362    {"collections.group.sounds.sample", NULL},   /* dup */
1363    {"collections.vibrations", NULL},
1364    {"collections.group.vibrations", NULL},   /* dup */
1365    {"collections.vibrations.sample", NULL},
1366    {"collections.filters", NULL},
1367    {"collections.filters.filter", ob_filters_filter},   /* dup */
1368    {"collections.filters.filter.script", ob_filters_filter_script},   /* dup */
1369    {"collections.group.vibrations.sample", NULL},   /* dup */
1370    {"collections.group", ob_collections_group},
1371    {"collections.group.data", NULL},
1372    {"collections.group.limits", NULL},
1373    {"collections.group.script", ob_collections_group_script},
1374    {"collections.group.lua_script", ob_collections_group_lua_script},
1375    {"collections.group.externals", NULL},   /* dup */
1376    {"collections.group.set", ob_images_set},   /* dup */
1377    {"collections.group.set.image", ob_images_set_image},   /* dup */
1378    {"collections.group.images", NULL},   /* dup */
1379    {"collections.group.images.set", ob_images_set},   /* dup */
1380    {"collections.group.images.set.image", ob_images_set_image},   /* dup */
1381    {"collections.group.fonts", NULL},   /* dup */
1382    {"collections.group.styles", NULL},   /* dup */
1383    {"collections.group.styles.style", ob_styles_style},   /* dup */
1384    {"collections.group.color_tree", ob_color_tree},   /* dup */
1385    {"collections.group.color_classes", NULL},   /* dup */
1386    {"collections.group.color_classes.color_class", ob_color_class},   /* dup */
1387    {"collections.group.text_classes", NULL},
1388    {"collections.group.text_classes.text_class", ob_text_class},   /* dup */
1389    {"collections.group.size_classes", NULL},   /* dup */
1390    {"collections.group.size_classes.size_class", ob_size_class},   /* dup */
1391    {"collections.group.filters", NULL},
1392    {"collections.group.filters.filter", ob_filters_filter},   /* dup */
1393    {"collections.group.filters.filter.script", ob_filters_filter_script},   /* dup */
1394    {"collections.group.parts", NULL},
1395    {"collections.group.parts.set", ob_images_set},   /* dup */
1396    {"collections.group.parts.set.image", ob_images_set_image},   /* dup */
1397    {"collections.group.parts.images", NULL},   /* dup */
1398    {"collections.group.parts.images.set", ob_images_set},   /* dup */
1399    {"collections.group.parts.images.set.image", ob_images_set_image},   /* dup */
1400    {"collections.group.parts.fonts", NULL},   /* dup */
1401    {"collections.group.parts.styles", NULL},   /* dup */
1402    {"collections.group.parts.styles.style", ob_styles_style},   /* dup */
1403    {"collections.group.parts.color_classes", NULL},   /* dup */
1404    {"collections.group.parts.color_classes.color_class", ob_color_class},   /* dup */
1405    {"collections.group.parts.text_classes", NULL},
1406    {"collections.group.parts.text_classes.text_class", ob_text_class},   /* dup */
1407    {"collections.group.parts.size_classes", NULL},   /* dup */
1408    {"collections.group.parts.size_classes.size_class", ob_size_class},   /* dup */
1409    {"collections.group.parts.part", ob_collections_group_parts_part},
1410    {"collections.group.parts.part.dragable", NULL},
1411    {"collections.group.parts.part.set", ob_images_set},   /* dup */
1412    {"collections.group.parts.part.set.image", ob_images_set_image},   /* dup */
1413    {"collections.group.parts.part.images", NULL},   /* dup */
1414    {"collections.group.parts.part.images.set", ob_images_set},   /* dup */
1415    {"collections.group.parts.part.images.set.image", ob_images_set_image},   /* dup */
1416    {"collections.group.parts.part.fonts", NULL},   /* dup */
1417    {"collections.group.parts.part.styles", NULL},   /* dup */
1418    {"collections.group.parts.part.styles.style", ob_styles_style},   /* dup */
1419    {"collections.group.parts.part.color_classes", NULL},   /* dup */
1420    {"collections.group.parts.part.color_classes.color_class", ob_color_class},   /* dup */
1421    {"collections.group.parts.part.text_classes", NULL},
1422    {"collections.group.parts.part.text_classes.text_class", ob_text_class},   /* dup */
1423    {"collections.group.parts.part.size_classes", NULL},   /* dup */
1424    {"collections.group.parts.part.size_classes.size_class", ob_size_class},   /* dup */
1425    {"collections.group.parts.part.box", NULL},
1426    {"collections.group.parts.part.box.items", NULL},
1427    {"collections.group.parts.part.box.items.item", ob_collections_group_parts_part_box_items_item},
1428    {"collections.group.parts.part.table", NULL},
1429    {"collections.group.parts.part.table.items", NULL},
1430    {"collections.group.parts.part.table.items.item", ob_collections_group_parts_part_box_items_item},   /* dup */
1431    {"collections.group.parts.part.description", ob_collections_group_parts_part_description},
1432    {"collections.group.parts.part.description.link", ob_collections_group_parts_part_description_link},
1433    {"collections.group.parts.part.description.rel1", NULL},
1434    {"collections.group.parts.part.description.rel2", NULL},
1435    {"collections.group.parts.part.description.anchors", NULL},
1436    {"collections.group.parts.part.description.image", NULL},   /* dup */
1437    {"collections.group.parts.part.description.image.set", ob_images_set},   /* dup */
1438    {"collections.group.parts.part.description.image.set.image", ob_images_set_image},   /* dup */
1439    {"collections.group.parts.part.description.image.images", NULL},   /* dup */
1440    {"collections.group.parts.part.description.image.images.set", ob_images_set},   /* dup */
1441    {"collections.group.parts.part.description.image.images.set.image", ob_images_set_image},   /* dup */
1442    {"collections.group.parts.part.description.fill", NULL},
1443    {"collections.group.parts.part.description.fill.origin", NULL},
1444    {"collections.group.parts.part.description.fill.size", NULL},
1445    {"collections.group.parts.part.description.text", NULL},
1446    {"collections.group.parts.part.description.text.fonts", NULL},   /* dup */
1447    {"collections.group.parts.part.description.images", NULL},   /* dup */
1448    {"collections.group.parts.part.description.images.set", ob_images_set},   /* dup */
1449    {"collections.group.parts.part.description.images.set.image", ob_images_set_image},   /* dup */
1450    {"collections.group.parts.part.description.fonts", NULL},   /* dup */
1451    {"collections.group.parts.part.description.styles", NULL},   /* dup */
1452    {"collections.group.parts.part.description.styles.style", ob_styles_style},   /* dup */
1453    {"collections.group.parts.part.description.box", NULL},
1454    {"collections.group.parts.part.description.table", NULL},
1455    {"collections.group.parts.part.description.filter", NULL},
1456    {"collections.group.parts.part.description.proxy", NULL},
1457 #ifdef HAVE_EPHYSICS
1458    {"collections.group.parts.part.description.physics", NULL},
1459    {"collections.group.parts.part.description.physics.movement_freedom", NULL},
1460    {"collections.group.parts.part.description.physics.faces", NULL},
1461    {"collections.group.parts.part.description.physics.faces.face", st_collections_group_parts_part_description_physics_face},
1462 #endif
1463    {"collections.group.parts.part.description.map", NULL},
1464    {"collections.group.parts.part.description.map.rotation", NULL},
1465    {"collections.group.parts.part.description.map.zoom", NULL},
1466    {"collections.group.parts.part.description.perspective", NULL},
1467    {"collections.group.parts.part.description.params", NULL},
1468    {"collections.group.parts.part.description.vector", NULL},
1469    {"collections.group.parts.part.description.color_classes", NULL},   /* dup */
1470    {"collections.group.parts.part.description.color_classes.color_class", ob_color_class},   /* dup */
1471    {"collections.group.parts.part.description.text_classes", NULL},   /* dup */
1472    {"collections.group.parts.part.description.text_classes.text_class", ob_text_class},   /* dup */
1473    {"collections.group.parts.part.description.size_classes", NULL},   /* dup */
1474    {"collections.group.parts.part.description.size_classes.size_class", ob_size_class},   /* dup */
1475 #ifdef HAVE_EPHYSICS
1476    {"collections.group.physics", NULL},
1477    {"collections.group.physics.world", NULL},
1478 #endif
1479    PROGRAM_OBJECTS("collections.group.parts.part.description")
1480    PROGRAM_OBJECTS("collections.group.parts.part")
1481    PROGRAM_OBJECTS("collections.group.parts")
1482    PROGRAM_OBJECTS("collections.group")
1483 };
1484 
1485 /** @edcsubsection{lazedc_blocks,
1486  *                 LazEDC Blocks} */
1487 
1488 /**
1489     @page edcref
1490     @block
1491         Blocks
1492     @context
1493     parts {
1494        rect{}
1495        text{}
1496        image{}
1497        swallow{}
1498        textblock{}
1499        group{}
1500        box{}
1501        table{}
1502        external{}
1503        proxy{}
1504        spacer{}
1505        snapshot{}
1506        vector{}
1507        part {
1508           desc {
1509           }
1510        }
1511     }
1512 
1513     @description
1514         Lowercase part types can be specified as blocks with the same effect as part { type: TYPE; }
1515         The "description" block can also be shortened to "desc".
1516 
1517     @since 1.10
1518     @endblock
1519  */
1520 New_Object_Handler object_handlers_short[] =
1521 {
1522    {"collections.group.parts.rect", ob_collections_group_parts_part_short},
1523    {"collections.group.parts.text", ob_collections_group_parts_part_short},
1524    {"collections.group.parts.image", ob_collections_group_parts_part_short},
1525    {"collections.group.parts.swallow", ob_collections_group_parts_part_short},
1526    {"collections.group.parts.textblock", ob_collections_group_parts_part_short},
1527    {"collections.group.parts.group", ob_collections_group_parts_part_short},
1528    {"collections.group.parts.box", ob_collections_group_parts_part_short},
1529    {"collections.group.parts.table", ob_collections_group_parts_part_short},
1530    {"collections.group.parts.external", ob_collections_group_parts_part_short},
1531    {"collections.group.parts.proxy", ob_collections_group_parts_part_short},
1532    {"collections.group.parts.spacer", ob_collections_group_parts_part_short},
1533    {"collections.group.parts.snapshot", ob_collections_group_parts_part_short},
1534    {"collections.group.parts.part.desc", ob_collections_group_parts_part_desc},
1535    {"collections.group.parts.vector", ob_collections_group_parts_part_short},
1536 };
1537 
1538 New_Nested_Handler nested_handlers[] = {
1539    {"collections.group.parts", "part", NULL, edje_cc_handlers_hierarchy_pop }
1540 };
1541 
1542 New_Nested_Handler nested_handlers_short[] = {
1543    {"collections.group.parts", "rect", NULL, edje_cc_handlers_hierarchy_pop },
1544    {"collections.group.parts", "text", NULL, edje_cc_handlers_hierarchy_pop },
1545    {"collections.group.parts", "image", NULL, edje_cc_handlers_hierarchy_pop },
1546    {"collections.group.parts", "swallow", NULL, edje_cc_handlers_hierarchy_pop },
1547    {"collections.group.parts", "textblock", NULL, edje_cc_handlers_hierarchy_pop },
1548    {"collections.group.parts", "group", NULL, edje_cc_handlers_hierarchy_pop },
1549    {"collections.group.parts", "box", NULL, edje_cc_handlers_hierarchy_pop },
1550    {"collections.group.parts", "table", NULL, edje_cc_handlers_hierarchy_pop },
1551    {"collections.group.parts", "external", NULL, edje_cc_handlers_hierarchy_pop },
1552    {"collections.group.parts", "proxy", NULL, edje_cc_handlers_hierarchy_pop },
1553    {"collections.group.parts", "spacer", NULL, edje_cc_handlers_hierarchy_pop },
1554    {"collections.group.parts", "vector", NULL, edje_cc_handlers_hierarchy_pop },
1555 };
1556 
1557 /*****/
1558 
1559 int
object_handler_num(void)1560 object_handler_num(void)
1561 {
1562    return sizeof(object_handlers) / sizeof (New_Object_Handler);
1563 }
1564 
1565 int
object_handler_short_num(void)1566 object_handler_short_num(void)
1567 {
1568    return sizeof(object_handlers_short) / sizeof (New_Object_Handler);
1569 }
1570 
1571 int
statement_handler_num(void)1572 statement_handler_num(void)
1573 {
1574    return sizeof(statement_handlers) / sizeof (New_Object_Handler);
1575 }
1576 
1577 int
statement_handler_short_num(void)1578 statement_handler_short_num(void)
1579 {
1580    return sizeof(statement_handlers_short) / sizeof (New_Object_Handler);
1581 }
1582 
1583 int
statement_handler_short_single_num(void)1584 statement_handler_short_single_num(void)
1585 {
1586    return sizeof(statement_handlers_short_single) / sizeof (New_Object_Handler);
1587 }
1588 
1589 int
nested_handler_num(void)1590 nested_handler_num(void)
1591 {
1592    return sizeof(nested_handlers) / sizeof (New_Nested_Handler);
1593 }
1594 
1595 int
nested_handler_short_num(void)1596 nested_handler_short_num(void)
1597 {
1598    return sizeof(nested_handlers_short) / sizeof (New_Nested_Handler);
1599 }
1600 
1601 static void
_edje_part_description_fill(Edje_Part_Description_Spec_Fill * fill)1602 _edje_part_description_fill(Edje_Part_Description_Spec_Fill *fill)
1603 {
1604    fill->smooth = 1;
1605    fill->pos_rel_x = FROM_DOUBLE(0.0);
1606    fill->pos_abs_x = 0;
1607    fill->rel_x = FROM_DOUBLE(1.0);
1608    fill->abs_x = 0;
1609    fill->pos_rel_y = FROM_DOUBLE(0.0);
1610    fill->pos_abs_y = 0;
1611    fill->rel_y = FROM_DOUBLE(1.0);
1612    fill->abs_y = 0;
1613    fill->type = EDJE_FILL_TYPE_SCALE;
1614 }
1615 
1616 static void
_edje_part_description_image_remove(Edje_Part_Description_Image * ed)1617 _edje_part_description_image_remove(Edje_Part_Description_Image *ed)
1618 {
1619    unsigned int j;
1620 
1621    if (!ed) return;
1622 
1623    data_queue_image_remove(&(ed->image.id), &(ed->image.set));
1624 
1625    for (j = 0; j < ed->image.tweens_count; ++j)
1626      data_queue_image_remove(&(ed->image.tweens[j]->id),
1627                              &(ed->image.tweens[j]->set));
1628 }
1629 
1630 void
part_description_image_cleanup(Edje_Part * ep)1631 part_description_image_cleanup(Edje_Part *ep)
1632 {
1633    Edje_Part_Description_Image *ed;
1634    unsigned int j;
1635 
1636    if (ep->type != EDJE_PART_TYPE_IMAGE)
1637      return;
1638 
1639    ed = (Edje_Part_Description_Image *)ep->default_desc;
1640    _edje_part_description_image_remove(ed);
1641 
1642    for (j = 0; j < ep->other.desc_count; j++)
1643      {
1644         ed = (Edje_Part_Description_Image *)ep->other.desc[j];
1645         _edje_part_description_image_remove(ed);
1646      }
1647 }
1648 
1649 static Edje_Part_Description_Common *
_edje_part_description_alloc(unsigned char type,const char * collection,const char * part)1650 _edje_part_description_alloc(unsigned char type, const char *collection, const char *part)
1651 {
1652    Edje_Part_Description_Common *result = NULL;
1653 
1654    switch (type)
1655      {
1656       case EDJE_PART_TYPE_SPACER:
1657       case EDJE_PART_TYPE_RECTANGLE:
1658       case EDJE_PART_TYPE_SWALLOW:
1659       case EDJE_PART_TYPE_GROUP:
1660         result = mem_alloc(SZ(Edje_Part_Description_Common));
1661         break;
1662 
1663       case EDJE_PART_TYPE_TEXT:
1664       case EDJE_PART_TYPE_TEXTBLOCK:
1665       {
1666          Edje_Part_Description_Text *ed;
1667 
1668          ed = mem_alloc(SZ(Edje_Part_Description_Text));
1669 
1670          ed->text.color3.r = 0;
1671          ed->text.color3.g = 0;
1672          ed->text.color3.b = 0;
1673          ed->text.color3.a = 128;
1674          ed->text.align.x = FROM_DOUBLE(0.5);
1675          ed->text.align.y = FROM_DOUBLE(0.5);
1676          ed->text.id_source = -1;
1677          ed->text.id_text_source = -1;
1678 
1679          result = &ed->common;
1680          break;
1681       }
1682 
1683       case EDJE_PART_TYPE_IMAGE:
1684       {
1685          Edje_Part_Description_Image *ed;
1686 
1687          ed = mem_alloc(SZ(Edje_Part_Description_Image));
1688 
1689          ed->image.id = -1;
1690 
1691          _edje_part_description_fill(&ed->image.fill);
1692 
1693          result = &ed->common;
1694          break;
1695       }
1696 
1697       case EDJE_PART_TYPE_SNAPSHOT:
1698       {
1699          Edje_Part_Description_Snapshot *ed;
1700 
1701          ed = mem_alloc(SZ(Edje_Part_Description_Snapshot));
1702 
1703          result = &ed->common;
1704          break;
1705       }
1706 
1707       case EDJE_PART_TYPE_PROXY:
1708       {
1709          Edje_Part_Description_Proxy *ed;
1710 
1711          ed = mem_alloc(SZ(Edje_Part_Description_Proxy));
1712 
1713          ed->proxy.id = -1;
1714          ed->proxy.source_visible = EINA_TRUE;
1715          ed->proxy.source_clip = EINA_TRUE;
1716          _edje_part_description_fill(&ed->proxy.fill);
1717 
1718          result = &ed->common;
1719          break;
1720       }
1721 
1722       case EDJE_PART_TYPE_BOX:
1723       {
1724          Edje_Part_Description_Box *ed;
1725 
1726          ed = mem_alloc(SZ(Edje_Part_Description_Box));
1727 
1728          ed->box.layout = NULL;
1729          ed->box.alt_layout = NULL;
1730          ed->box.align.x = FROM_DOUBLE(0.5);
1731          ed->box.align.y = FROM_DOUBLE(0.5);
1732          ed->box.padding.x = 0;
1733          ed->box.padding.y = 0;
1734 
1735          result = &ed->common;
1736          break;
1737       }
1738 
1739       case EDJE_PART_TYPE_TABLE:
1740       {
1741          Edje_Part_Description_Table *ed;
1742 
1743          ed = mem_alloc(SZ(Edje_Part_Description_Table));
1744 
1745          ed->table.homogeneous = EDJE_OBJECT_TABLE_HOMOGENEOUS_NONE;
1746          ed->table.align.x = FROM_DOUBLE(0.5);
1747          ed->table.align.y = FROM_DOUBLE(0.5);
1748          ed->table.padding.x = 0;
1749          ed->table.padding.y = 0;
1750 
1751          result = &ed->common;
1752          break;
1753       }
1754 
1755       case EDJE_PART_TYPE_EXTERNAL:
1756       {
1757          Edje_Part_Description_External *ed;
1758 
1759          ed = mem_alloc(SZ(Edje_Part_Description_External));
1760 
1761          ed->external_params = NULL;
1762 
1763          result = &ed->common;
1764          break;
1765       }
1766 
1767       case EDJE_PART_TYPE_VECTOR:
1768       {
1769          Edje_Part_Description_Vector *ed;
1770 
1771          ed = mem_alloc(SZ(Edje_Part_Description_Vector));
1772 
1773          result = &ed->common;
1774          break;
1775       }
1776      }
1777 
1778    if (!result)
1779      {
1780         ERR("Unknown type %i of part %s in collection %s.",
1781             type, part, collection);
1782         exit(-1);
1783      }
1784 
1785 #ifdef HAVE_EPHYSICS
1786    result->physics.mass = FROM_DOUBLE(1.0);
1787    result->physics.friction = FROM_DOUBLE(0.5);
1788    result->physics.sleep.linear = FROM_DOUBLE(24);
1789    result->physics.sleep.angular = FROM_DOUBLE(57.29);
1790    result->physics.hardness = FROM_DOUBLE(1.0);
1791    result->physics.ignore_part_pos = 1;
1792    result->physics.mov_freedom.lin.x = 1;
1793    result->physics.mov_freedom.lin.y = 1;
1794    result->physics.mov_freedom.ang.z = 1;
1795    result->physics.z = -15;
1796    result->physics.depth = 30;
1797 #endif
1798 
1799    result->clip_to_id = -1;
1800    return result;
1801 }
1802 
1803 static void
_edje_program_check(const char * name,Edje_Program * me,Edje_Program ** pgrms,unsigned int count)1804 _edje_program_check(const char *name, Edje_Program *me, Edje_Program **pgrms, unsigned int count)
1805 {
1806    Edje_Part_Collection *pc;
1807    unsigned int i;
1808    Edje_Program_Parser *epp;
1809 
1810    pc = eina_list_data_get(eina_list_last(edje_collections));
1811 
1812    for (i = 0; i < count; ++i)
1813      if (pgrms[i]->name)
1814        if (pgrms[i] != me && (!strcmp(name, pgrms[i]->name)))
1815          {
1816             epp = (Edje_Program_Parser *)pgrms[i];
1817             if (!epp->can_override)
1818               {
1819                  ERR("parse error %s:%i. There is already a program of the name %s",
1820                      file_in, line - 1, name);
1821                  exit(-1);
1822               }
1823             else
1824               {
1825                  _edje_program_remove(pc, me);
1826                  current_program = pgrms[i];
1827                  if (pgrms[i]->action == EDJE_ACTION_TYPE_SCRIPT)
1828                    copied_program_anonymous_lookup_delete(pc, &pgrms[i]->id);
1829                  epp->can_override = EINA_FALSE;
1830                  return;
1831               }
1832          }
1833 }
1834 
1835 static void
_edje_program_copy(Edje_Program * ep,Edje_Program * ep2)1836 _edje_program_copy(Edje_Program *ep, Edje_Program *ep2)
1837 {
1838    Edje_Part_Collection *pc;
1839    Edje_Program_Target *et, *et2;
1840    Edje_Program_After *pa, *pa2;
1841    Edje_Program_Parser *epp;
1842    Eina_List *l;
1843    char *name;
1844    char *copy;
1845 
1846    pc = eina_list_data_get(eina_list_last(edje_collections));
1847 
1848    ep->name = STRDUP(ep2->name);
1849 
1850    _edje_program_remove(pc, current_program);
1851    ep->signal = STRDUP(ep2->signal);
1852    ep->source = STRDUP(ep2->source);
1853    _edje_program_insert(pc, current_program);
1854 
1855    ep->filter.part = STRDUP(ep2->filter.part);
1856    ep->filter.state = STRDUP(ep2->filter.state);
1857    ep->in.from = ep2->in.from;
1858    ep->in.range = ep2->in.range;
1859    ep->action = ep2->action;
1860    ep->seat = STRDUP(ep2->seat);
1861    ep->state = STRDUP(ep2->state);
1862    ep->state2 = STRDUP(ep2->state2);
1863    ep->value = ep2->value;
1864    ep->value2 = ep2->value2;
1865    ep->tween.mode = ep2->tween.mode;
1866    ep->tween.time = ep2->tween.time;
1867    ep->tween.v1 = ep2->tween.v1;
1868    ep->tween.v2 = ep2->tween.v2;
1869    ep->tween.v3 = ep2->tween.v3;
1870    ep->tween.v4 = ep2->tween.v4;
1871    ep->tween.use_duration_factor = ep2->tween.use_duration_factor;
1872    ep->sample_name = STRDUP(ep2->sample_name);
1873    ep->tone_name = STRDUP(ep2->tone_name);
1874    ep->duration = ep2->duration;
1875    ep->speed = ep2->speed;
1876    ep->channel = ep2->channel;
1877 
1878    EINA_LIST_FOREACH(ep2->targets, l, et2)
1879      {
1880         name = (char *)(et2 + 1);
1881         et = mem_alloc(SZ(Edje_Program_Target) + strlen(name) + 1);
1882         ep->targets = eina_list_append(ep->targets, et);
1883         copy = (char *)(et + 1);
1884 
1885         memcpy(copy, name, strlen(name) + 1);
1886 
1887         switch (ep2->action)
1888           {
1889            case EDJE_ACTION_TYPE_STATE_SET:
1890            case EDJE_ACTION_TYPE_SIGNAL_EMIT:
1891            case EDJE_ACTION_TYPE_DRAG_VAL_SET:
1892            case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
1893            case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
1894            case EDJE_ACTION_TYPE_FOCUS_SET:
1895            case EDJE_ACTION_TYPE_FOCUS_OBJECT:
1896              if (current_group_inherit)
1897                data_queue_part_lookup(pc, name, &et->id);
1898              else
1899                data_queue_copied_part_lookup(pc, &(et2->id), &(et->id));
1900              break;
1901 
1902            case EDJE_ACTION_TYPE_ACTION_STOP:
1903            case EDJE_ACTION_TYPE_SCRIPT:
1904              if (current_group_inherit)
1905                data_queue_program_lookup(pc, name, &et->id);
1906              else
1907                data_queue_copied_program_lookup(pc, &(et2->id), &(et->id));
1908              break;
1909 
1910            default:
1911              ERR("parse error %s:%i. target may only be used after action",
1912                  file_in, line - 1);
1913              exit(-1);
1914           }
1915      }
1916 
1917    EINA_LIST_FOREACH(ep2->after, l, pa2)
1918      {
1919         name = (char *)(pa2 + 1);
1920         pa = mem_alloc(SZ(Edje_Program_After) + strlen(name) + 1);
1921         ep->after = eina_list_append(ep->after, pa);
1922         copy = (char *)(pa + 1);
1923         memcpy(copy, name, strlen(name) + 1);
1924         if (!data_queue_copied_program_lookup(pc, &(pa2->id), &(pa->id)))
1925           data_queue_program_lookup(pc, copy, &(pa->id));
1926      }
1927 
1928    ep->api.name = STRDUP(ep2->api.name);
1929    ep->api.description = STRDUP(ep2->api.description);
1930    data_queue_copied_part_lookup(pc, &(ep2->param.src), &(ep->param.src));
1931    data_queue_copied_part_lookup(pc, &(ep2->param.dst), &(ep->param.dst));
1932 
1933    epp = (Edje_Program_Parser *)ep;
1934    epp->can_override = EINA_TRUE;
1935 }
1936 
1937 /*****/
1938 
1939 /** @edcsection{toplevel,Top-Level blocks} */
1940 
1941 /** @edcsubsection{toplevel_efl_version,
1942  *                 Efl_version} */
1943 
1944 /**
1945     @page edcref
1946 
1947     @property
1948         efl_version
1949     @parameters
1950         [major] [minor]
1951     @effect
1952         Used to show which version of EFL is used for developing a edje file.
1953     @endproperty
1954  */
1955 static void
st_efl_version(void)1956 st_efl_version(void)
1957 {
1958    check_arg_count(2);
1959 
1960    edje_file->efl_version.major = parse_int(0);
1961    edje_file->efl_version.minor = parse_int(1);
1962 }
1963 
1964 /** @edcsubsection{toplevel_id,
1965  *                 id} */
1966 
1967 /**
1968     @page edcref
1969 
1970     @property
1971         id
1972     @parameters
1973         [name]
1974     @effect
1975         A string which is used to identify the edje file.
1976     @since 1.21
1977     @endproperty
1978  */
1979 static void
st_id(void)1980 st_id(void)
1981 {
1982    Eina_Array_Iterator it;
1983    unsigned int i;
1984    char *str, *id;
1985 
1986    check_arg_count(1);
1987    id = parse_str(0);
1988 
1989    EINA_ARRAY_ITER_NEXT(requires, i, str, it)
1990      if (eina_streq(str, id))
1991        error_and_abort(NULL, "Cannot use same id for file as one of its required files!");
1992    free((void*)edje_file->id);
1993    edje_file->id = id;
1994 }
1995 
1996 /** @edcsubsection{toplevel_requires,
1997  *                 requires} */
1998 
1999 /**
2000     @page edcref
2001 
2002     @property
2003         requires
2004     @parameters
2005         [name]
2006     @effect
2007         Specifying this property informs edje not to close the
2008         file with the corresponding id property for as long as this
2009         file is open. Multiple requires properties can be individually specified.
2010     @since 1.21
2011     @endproperty
2012  */
2013 static void
st_requires(void)2014 st_requires(void)
2015 {
2016    char *str;
2017    check_arg_count(1);
2018 
2019    str = parse_str(0);
2020    if (eina_streq(str, edje_file->id))
2021      error_and_abort(NULL, "Cannot require the current file!");
2022    eina_array_push(requires, str);
2023 }
2024 
2025 /** @edcsubsection{toplevel_externals,
2026  *                 Externals} */
2027 
2028 /**
2029     @page edcref
2030 
2031     @block
2032         externals
2033     @context
2034         externals {
2035            external: "name";
2036         }
2037     @description
2038         The "externals" block is used to list each external module file that will be used in others
2039         programs.
2040     @endblock
2041 
2042     @property
2043         external
2044     @parameters
2045         [external filename]
2046     @effect
2047         Used to add a file to the externals list.
2048     @endproperty
2049  */
2050 static void
st_externals_external(void)2051 st_externals_external(void)
2052 {
2053    External *ex;
2054 
2055    check_arg_count(1);
2056 
2057    if (!edje_file->external_dir)
2058      edje_file->external_dir = mem_alloc(SZ(Edje_External_Directory));
2059 
2060    ex = mem_alloc(SZ(External));
2061    ex->name = parse_str(0);
2062    {
2063       Eina_List *l;
2064       External *lex;
2065 
2066       EINA_LIST_FOREACH(externals, l, lex)
2067         {
2068            if (!strcmp(lex->name, ex->name))
2069              {
2070                 free(ex->name);
2071                 free(ex);
2072                 return;
2073              }
2074         }
2075    }
2076    externals = eina_list_append(externals, ex);
2077 
2078    if (edje_file->external_dir)
2079      {
2080         Edje_External_Directory_Entry *entries;
2081 
2082         edje_file->external_dir->entries_count++;
2083         entries = realloc(edje_file->external_dir->entries,
2084                           sizeof (Edje_External_Directory_Entry) * edje_file->external_dir->entries_count);
2085         if (!entries)
2086           {
2087              ERR("not enough memory");
2088              exit(-1);
2089           }
2090         edje_file->external_dir->entries = entries;
2091         memset(edje_file->external_dir->entries + edje_file->external_dir->entries_count - 1,
2092                0, sizeof (Edje_External_Directory_Entry));
2093 
2094         edje_file->external_dir->entries[edje_file->external_dir->entries_count - 1].entry = mem_strdup(ex->name);
2095      }
2096 }
2097 
2098 /** @edcsubsection{toplevel_images,
2099  *                 Images} */
2100 
2101 /**
2102     @page edcref
2103 
2104     @block
2105         images
2106     @context
2107         images {
2108             image: "filename1.ext" COMP;
2109             image: "filename2.ext" LOSSY 99;
2110             image: "filename2.ext" LOSSY_ETC1 50;
2111             set { }
2112             set { }
2113             ..
2114         }
2115     @description
2116         The "images" block is used to list each image file that will be used in
2117         the theme along with its compression method (if any).
2118         Besides the document's root, additional "images" blocks can be
2119         included inside other blocks, normally "collections", "group" and
2120         "part", easing maintenance of the file list when the theme is split
2121         among multiple files.
2122         @note if svg file use as image, not vector, it will be converted to bitmap
2123         and '.png' will be add to file name.
2124     @endblock
2125 
2126     @property
2127         image
2128     @parameters
2129         [image file] [compression method] (compression level)(edje file id)
2130     @effect
2131         Used to include each image file. The full path to the directory holding
2132         the images can be defined later with edje_cc's "-id" option.
2133         Compression methods:
2134         @li RAW: Uncompressed.
2135         @li COMP: Lossless compression.
2136         @li LOSSY [0-100]: JPEG lossy compression with quality from 0 to 100.
2137         @li LOSSY_ETC1 [0-100]: ETC1 lossy texture compression with quality from 0 to 100.
2138         @li LOSSY_ETC2 [0-100]: ETC2 lossy texture compression with quality from 0 to 100 (supports alpha).
2139         @li USER: Do not embed the file, refer to the external file instead.
2140         @li EXTERNAL: The file exists in the edje file with the specified id.
2141 
2142         Defaults: compression level for lossy methods is 90.
2143     @endproperty
2144  */
2145 static void
st_images_image(void)2146 st_images_image(void)
2147 {
2148    /* NOTE: if you implement any changes with image_id mechanic don't forget
2149     * to update following functions: edje_edit_image_replace,
2150     * edje_edit_image_usage_list_get, edje_edit_image_del, _data_image_id_update
2151     */
2152    Edje_Image_Directory_Entry *img;
2153    const char *tmp;
2154    unsigned int i;
2155    int v;
2156 
2157    check_min_arg_count(2);
2158 
2159    if (!edje_file->image_dir)
2160      edje_file->image_dir = mem_alloc(SZ(Edje_Image_Directory));
2161 
2162    tmp = parse_str(0);
2163 
2164    for (i = 0; i < edje_file->image_dir->entries_count; ++i)
2165      if (!strcmp(edje_file->image_dir->entries[i].entry, tmp))
2166        {
2167           free((char *)tmp);
2168           return;
2169        }
2170 
2171    edje_file->image_dir->entries_count++;
2172    img = realloc(edje_file->image_dir->entries,
2173                  sizeof (Edje_Image_Directory_Entry) * edje_file->image_dir->entries_count);
2174    if (!img)
2175      {
2176         ERR("No enough memory.");
2177         exit(-1);
2178      }
2179    edje_file->image_dir->entries = img;
2180    memset(edje_file->image_dir->entries + edje_file->image_dir->entries_count - 1,
2181           0, sizeof (Edje_Image_Directory_Entry));
2182 
2183    img = edje_file->image_dir->entries + edje_file->image_dir->entries_count - 1;
2184 
2185    img->entry = tmp;
2186    img->id = edje_file->image_dir->entries_count - 1;
2187    v = parse_enum(1,
2188                   "RAW", 0,
2189                   "COMP", 1,
2190                   "LOSSY", 2,
2191                   "LOSSY_ETC1", 3,
2192                   "LOSSY_ETC2", 4,
2193                   "USER", 5,
2194                   "EXTERNAL", 6,
2195                   NULL);
2196    if (v == 0)
2197      {
2198         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT;
2199         img->source_param = 0;
2200      }
2201    else if (v == 1)
2202      {
2203         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT;
2204         img->source_param = 1;
2205      }
2206    else if (v == 2)
2207      {
2208         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY;
2209         img->source_param = 0;
2210      }
2211    else if (v == 3)
2212      {
2213         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC1;
2214         img->source_param = 0;
2215      }
2216    else if (v == 4)
2217      {
2218         img->source_type = EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC2;
2219         img->source_param = 0;
2220      }
2221    else if (v == 5)
2222      {
2223         img->source_type = EDJE_IMAGE_SOURCE_TYPE_USER;
2224         img->source_param = 0;
2225      }
2226    else if (v == 6)
2227      {
2228         img->source_type = EDJE_IMAGE_SOURCE_TYPE_EXTERNAL;
2229         img->source_param = 0;
2230         img->external_id = parse_str(2);
2231      }
2232    if ((img->source_type < EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY) ||
2233        (img->source_type == EDJE_IMAGE_SOURCE_TYPE_USER))
2234      check_arg_count(2);
2235    else if (img->source_type != EDJE_IMAGE_SOURCE_TYPE_EXTERNAL)
2236      {
2237         if (check_range_arg_count(2, 3) > 2)
2238           img->source_param = parse_int_range(2, 0, 100);
2239         else
2240           img->source_param = 90;
2241      }
2242    if (!edje_file->image_id_hash)
2243      edje_file->image_id_hash = eina_hash_string_superfast_new(free);
2244    {
2245       Edje_Image_Hash *eih = mem_alloc(SZ(Edje_Image_Hash));
2246       eih->id = img->id;
2247       eina_hash_add(edje_file->image_id_hash, tmp, eih);
2248    }
2249 }
2250 
2251 static void
_handle_vector_image(void)2252 _handle_vector_image(void)
2253 {
2254    Edje_Part_Description_Vector *ed;
2255    unsigned int i = 0;
2256    char *name;
2257 
2258    ed = (Edje_Part_Description_Vector *)current_desc;
2259 
2260    name = parse_str(0);
2261 
2262    ed->vg.id = -1;
2263 
2264    for (i = 0; i < edje_file->image_dir->vectors_count; ++i)
2265      {
2266         if (!strcmp(edje_file->image_dir->vectors[i].entry, name))
2267           {
2268              ed->vg.set = EINA_TRUE;
2269              ed->vg.id = edje_file->image_dir->vectors[i].id;
2270              ed->vg.type = edje_file->image_dir->vectors[i].type;
2271              break;
2272           }
2273      }
2274 
2275    if (ed->vg.id < 0)
2276      error_and_abort(NULL, "Failed to find the vector resource :%s", name);
2277 
2278    free(name);
2279 }
2280 
2281 /** @edcsubsection{toplevel_images2,
2282  *                 Images} */
2283 
2284 /**
2285     @page edcref
2286 
2287     @block
2288         images
2289     @context
2290         images {
2291             vector: "filename1.svg";
2292             vector: "filename2.svg";
2293             vector: "filename3.svg";
2294             ..
2295         }
2296     @description
2297         The "vector" context in the "images" block is used to list each svg image file that will be used in
2298         the theme.
2299     @endblock
2300 
2301     @property
2302         vector
2303     @parameters
2304         [image file]
2305     @endproperty
2306  */
2307 static void
st_images_vector(void)2308 st_images_vector(void)
2309 {
2310    Edje_Vector_Directory_Entry *vector;
2311    const char *tmp;
2312    unsigned int i;
2313    size_t entry_len;
2314 
2315    check_min_arg_count(1);
2316 
2317    if (!edje_file->image_dir)
2318      edje_file->image_dir = mem_alloc(SZ(Edje_Image_Directory));
2319 
2320    tmp = parse_str(0);
2321 
2322    for (i = 0; i < edje_file->image_dir->vectors_count; ++i)
2323      if (!strcmp(edje_file->image_dir->vectors[i].entry, tmp))
2324        {
2325           free((char *)tmp);
2326           return;
2327        }
2328 
2329    edje_file->image_dir->vectors_count++;
2330    vector = realloc(edje_file->image_dir->vectors,
2331                     sizeof (Edje_Vector_Directory_Entry) * edje_file->image_dir->vectors_count);
2332    if (!vector)
2333      {
2334         ERR("No enough memory.");
2335         exit(-1);
2336      }
2337    edje_file->image_dir->vectors = vector;
2338    memset(edje_file->image_dir->vectors + edje_file->image_dir->vectors_count - 1,
2339           0, sizeof (Edje_Vector_Directory_Entry));
2340 
2341    vector = edje_file->image_dir->vectors + edje_file->image_dir->vectors_count - 1;
2342 
2343    vector->entry = tmp;
2344    vector->id = edje_file->image_dir->vectors_count - 1;
2345 
2346    entry_len = strlen(vector->entry);
2347    if ((entry_len > 5) && !strncmp(vector->entry + entry_len - 5, ".json", 5))
2348      {
2349         vector->type = EDJE_VECTOR_FILE_TYPE_LOTTIE;
2350      }
2351    else
2352      {
2353         vector->type = EDJE_VECTOR_FILE_TYPE_SVG;
2354      }
2355 }
2356 
2357 /** @edcsubsection{toplevel_images_set,
2358  *                 Images.Set} */
2359 
2360 /**
2361     @page edcref
2362 
2363     @block
2364         set
2365     @context
2366         images {
2367             ..
2368             set {
2369                 name: "image_name_used";
2370                 image { }
2371                 image { }
2372                 ...
2373             }
2374         }
2375     @description
2376         The "set" block is used to define an image with different content
2377         depending on their size. Besides the document's root, additional
2378         "set" blocks can be included inside other blocks, normally
2379         "collections", "group" and "part", easing maintenance of the file
2380         list when the theme is split among multiple files.
2381     @endblock
2382  */
2383 static void
ob_images_set(void)2384 ob_images_set(void)
2385 {
2386    Edje_Image_Directory_Set *sets;
2387 
2388    if (!edje_file->image_dir)
2389      edje_file->image_dir = mem_alloc(SZ(Edje_Image_Directory));
2390 
2391    edje_file->image_dir->sets_count++;
2392    sets = realloc(edje_file->image_dir->sets,
2393                   sizeof (Edje_Image_Directory_Set) * edje_file->image_dir->sets_count);
2394    if (!sets)
2395      {
2396         ERR("Not enough memory.");
2397         exit(-1);
2398      }
2399    edje_file->image_dir->sets = sets;
2400    memset(edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1,
2401           0, sizeof (Edje_Image_Directory_Set));
2402 
2403    edje_file->image_dir->sets[edje_file->image_dir->sets_count - 1].id = edje_file->image_dir->sets_count - 1;
2404 }
2405 
2406 /**
2407     @page edcref
2408 
2409     @property
2410         name
2411     @parameters
2412         [image name]
2413     @effect
2414         Define the name that refer to this image description.
2415     @endproperty
2416  */
2417 static void
st_images_set_name(void)2418 st_images_set_name(void)
2419 {
2420    check_arg_count(1);
2421 
2422    edje_file->image_dir->sets[edje_file->image_dir->sets_count - 1].name = parse_str(0);
2423 }
2424 
2425 /**  @edcsubsection{toplevel_images_set_image,
2426  *                  Images.Set.Image} */
2427 
2428 /**
2429     @page edcref
2430 
2431     @block
2432         image
2433     @context
2434         images {
2435             ..
2436             set {
2437                 ..
2438                 image {
2439                    image: "filename4.ext" COMP;
2440                    size: 51 51 200 200;
2441                    border: 0 0 0 0;
2442                    border_scale_by: 0.0;
2443                 }
2444                 ..
2445             }
2446         }
2447     @description
2448         The "image" block inside a "set" block define the characteristic of an image.
2449         Every block will describe one image and the size rule to use it.
2450     @endblock
2451  **/
2452 static void
ob_images_set_image(void)2453 ob_images_set_image(void)
2454 {
2455    Edje_Image_Directory_Set_Entry *entry;
2456    Edje_Image_Directory_Set *set;
2457 
2458    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
2459 
2460    entry = mem_alloc(SZ(Edje_Image_Directory_Set_Entry));
2461 
2462    set->entries = eina_list_append(set->entries, entry);
2463 }
2464 
2465 /**
2466     @page edcref
2467 
2468     @property
2469         image
2470     @parameters
2471         [image file] [compression method] (compression level)(edje file id)
2472     @effect
2473         Used to include each image file. The full path to the directory holding
2474         the images can be defined later with edje_cc's "-id" option.
2475         Compression methods:
2476         @li RAW: Uncompressed.
2477         @li COMP: Lossless compression.
2478         @li LOSSY [0-100]: JPEG lossy compression with quality from 0 to 100.
2479         @li LOSSY_ETC1 [0-100]: ETC1 lossy texture compression with quality from 0 to 100.
2480         @li LOSSY_ETC2 [0-100]: ETC2 lossy texture compression with quality from 0 to 100 (supports alpha).
2481         @li USER: Do not embed the file, refer to the external file instead.
2482         @li EXTERNAL: The file exists in the edje file with the specified id.
2483 
2484         Defaults: compression level for lossy methods is 90.
2485     @endproperty
2486  **/
2487 static void
st_images_set_image_image(void)2488 st_images_set_image_image(void)
2489 {
2490    Edje_Image_Directory_Set_Entry *entry;
2491    Edje_Image_Directory_Set *set;
2492    unsigned int i;
2493 
2494    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
2495    entry = eina_list_data_get(eina_list_last(set->entries));
2496 
2497    /* Add the image to the global pool with the same syntax. */
2498    st_images_image();
2499 
2500    entry->name = parse_str(0);
2501 
2502    for (i = 0; i < edje_file->image_dir->entries_count; ++i)
2503      if (!strcmp(edje_file->image_dir->entries[i].entry, entry->name))
2504        {
2505           entry->id = i;
2506           return;
2507        }
2508 }
2509 
2510 /**
2511     @page edcref
2512 
2513     @property
2514         size
2515     @parameters
2516         [minw] [minh] [maxw] [maxh]
2517     @effect
2518         Define the minimal and maximal size that will select the specified image.
2519 
2520         Defaults: 0 0 0 0
2521     @endproperty
2522  */
2523 static void
st_images_set_image_size(void)2524 st_images_set_image_size(void)
2525 {
2526    Edje_Image_Directory_Set_Entry *entry;
2527    Edje_Image_Directory_Set *set;
2528 
2529    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
2530    entry = eina_list_data_get(eina_list_last(set->entries));
2531 
2532    entry->size.min.w = parse_int(0);
2533    entry->size.min.h = parse_int(1);
2534    entry->size.max.w = parse_int(2);
2535    entry->size.max.h = parse_int(3);
2536 
2537    if (entry->size.min.w > entry->size.max.w
2538        || entry->size.min.h > entry->size.max.h)
2539      {
2540         ERR("parse error %s:%i. Image min and max size are not in the right order ([%i, %i] < [%i, %i])",
2541             file_in, line - 1,
2542             entry->size.min.w, entry->size.min.h,
2543             entry->size.max.w, entry->size.max.h);
2544         exit(-1);
2545      }
2546 }
2547 
2548 /**
2549     @page edcref
2550     @property
2551         border
2552     @parameters
2553         [left] [right] [top] [bottom]
2554     @effect
2555         If set, the area (in pixels) of each side of the image will be
2556         displayed as a fixed size border, from the side -> inwards, preventing
2557         the corners from being changed on a resize.
2558 
2559         Defaults: 0 0 0 0
2560     @since 1.8
2561     @endproperty
2562  */
2563 static void
st_images_set_image_border(void)2564 st_images_set_image_border(void)
2565 {
2566    Edje_Image_Directory_Set_Entry *entry;
2567    Edje_Image_Directory_Set *set;
2568 
2569    set = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
2570    entry = eina_list_data_get(eina_list_last(set->entries));
2571 
2572    entry->border.l = parse_int_range(0, 0, 0x7fffffff);
2573    entry->border.r = parse_int_range(1, 0, 0x7fffffff);
2574    entry->border.t = parse_int_range(2, 0, 0x7fffffff);
2575    entry->border.b = parse_int_range(3, 0, 0x7fffffff);
2576 }
2577 
2578 /**
2579     @page edcref
2580     @property
2581         border_scale_by
2582     @parameters
2583         [value]
2584     @effect
2585         If border scaling is enabled then normally the OUTPUT border sizes
2586         (e.g. if 3 pixels on the left edge are set as a border, then normally
2587         at scale 1.0, those 3 columns will always be the exact 3 columns of
2588         output, or at scale 2.0 they will be 6 columns, or 0.33 they will merge
2589         into a single column). This property multiplies the input scale
2590         factor by this multiplier, allowing the creation of "supersampled"
2591         borders to make much higher resolution outputs possible by always using
2592         the highest resolution artwork and then runtime scaling it down.
2593 
2594         Valid values are: 0.0 or bigger (0.0 or 1.0 to turn it off)
2595 
2596         Defaults: 0.0
2597     @since 1.8
2598     @endproperty
2599  */
2600 static void
st_images_set_image_border_scale_by(void)2601 st_images_set_image_border_scale_by(void)
2602 {
2603    Edje_Part_Description_Image *ed;
2604 
2605    check_arg_count(1);
2606 
2607    if (current_part->type != EDJE_PART_TYPE_IMAGE)
2608      {
2609         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
2610             file_in, line - 1);
2611         exit(-1);
2612      }
2613 
2614    ed = (Edje_Part_Description_Image *)current_desc;
2615 
2616    ed->image.border.scale_by = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
2617 }
2618 
2619 /** @edcsubsection{toplevel_fonts,
2620  *                 Fonts} */
2621 
2622 /**
2623     @page edcref
2624 
2625     @block
2626         fonts
2627     @context
2628         fonts {
2629             font: "filename1.ext" "fontname";
2630             font: "filename2.ext" "otherfontname";
2631             ..
2632         }
2633     @description
2634         The "fonts" block is used to list each font file with an alias used later
2635         in the theme. As with the "images" block, additional "fonts" blocks can
2636         be included inside other blocks.
2637     @endblock
2638 
2639     @property
2640         font
2641     @parameters
2642         [font filename] [font alias]
2643     @effect
2644         Defines each font "file" and "alias", the full path to the directory
2645         holding the font files can be defined with edje_cc's "-fd" option.
2646     @endproperty
2647  */
2648 static void
st_fonts_font(void)2649 st_fonts_font(void)
2650 {
2651    Edje_Font *fn;
2652 
2653    check_arg_count(2);
2654 
2655    if (!edje_file->fonts)
2656      edje_file->fonts = eina_hash_string_small_new(free);
2657 
2658    fn = mem_alloc(SZ(Edje_Font));
2659    fn->file = parse_str(0);
2660    fn->name = parse_str(1);
2661 
2662    if (eina_hash_find(edje_file->fonts, fn->name))
2663      {
2664         free(fn->file);
2665         free(fn->name);
2666         free(fn);
2667         return;
2668      }
2669 
2670    eina_hash_direct_add(edje_file->fonts, fn->name, fn);
2671 }
2672 
2673 /** @edcsubsection{toplevel_data,
2674  *                 Data} */
2675 
2676 /**
2677     @page edcref
2678     @block
2679         data
2680     @context
2681         data {
2682             item: "key" "value";
2683             file: "otherkey" "filename.ext";
2684             ..
2685         }
2686     @description
2687         The "data" block is used to pass arbitrary parameters from the theme to
2688         the application. Unlike the "images" and "fonts" blocks, additional
2689         "data" blocks can only be included inside the "group" block.
2690     @endblock
2691 
2692     @property
2693         item
2694     @parameters
2695         [parameter name] [parameter value]
2696     @effect
2697         Defines a new parameter, the value will be the string specified next to
2698         it.
2699     @endproperty
2700  */
2701 static void
st_data_item(void)2702 st_data_item(void)
2703 {
2704    Edje_String *es;
2705    char *key;
2706 
2707    check_arg_count(2);
2708 
2709    key = parse_str(0);
2710 
2711    es = mem_alloc(SZ(Edje_String));
2712    es->str = parse_str(1);
2713 
2714    if (!edje_file->data)
2715      edje_file->data = eina_hash_string_small_new(free);
2716    else
2717      {
2718         if (eina_hash_find(edje_file->data, key))
2719           {
2720              ERR("parse error %s:%i. There is already a data.item of the name %s",
2721                  file_in, line - 1, key);
2722              exit(-1);
2723           }
2724      }
2725 
2726    eina_hash_direct_add(edje_file->data, key, es);
2727 }
2728 
2729 /**
2730     @page edcref
2731     @property
2732         file
2733     @parameters
2734         [parameter name] [parameter filename]
2735     @effect
2736         Defines a new parameter, the value will be the contents of the
2737         specified file formatted as a single string of text. This property only
2738         works with plain text files.
2739     @endproperty
2740  */
2741 static void
st_data_file(void)2742 st_data_file(void)
2743 {
2744    const char *data;
2745    const char *over;
2746    Edje_String *es;
2747    char *filename;
2748    char *value;
2749    char *key;
2750    int fd;
2751    int i;
2752    struct stat buf;
2753 
2754    check_arg_count(2);
2755 
2756    key = parse_str(0);
2757 
2758    es = mem_alloc(SZ(Edje_String));
2759    filename = parse_str(1);
2760 
2761    fd = open(filename, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR);
2762    if (fd < 0)
2763      {
2764         char path[PATH_MAX], *dir;
2765         Eina_List *l;
2766         EINA_LIST_FOREACH(data_dirs, l, dir)
2767           {
2768              snprintf(path, sizeof(path), "%s/%s", dir, filename);
2769              fd = open(path, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR);
2770              if (fd >= 0)
2771                break;
2772           }
2773 
2774         if (fd < 0)
2775           {
2776              ERR("%s:%i when opening file \"%s\": \"%s\"",
2777                  file_in, line, filename, strerror(errno));
2778              exit(-1);
2779           }
2780      }
2781 
2782    if (fstat(fd, &buf))
2783      {
2784         ERR("%s:%i when stating file \"%s\": \"%s\"",
2785             file_in, line, filename, strerror(errno));
2786         exit(-1);
2787      }
2788 
2789    data = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
2790    if (data == MAP_FAILED)
2791      {
2792         ERR("%s:%i when mapping file \"%s\": \"%s\"",
2793             file_in, line, filename, strerror(errno));
2794         exit(-1);
2795      }
2796 
2797    over = data;
2798    for (i = 0; i < buf.st_size; ++i, ++over)
2799      if (*over == '\0')
2800        {
2801           ERR("%s:%i file \"%s\" is a binary file.", file_in, line, filename);
2802           exit(-1);
2803        }
2804 
2805    value = malloc(sizeof (char) * buf.st_size + 1);
2806    snprintf(value, buf.st_size + 1, "%s", data);
2807 
2808    munmap((void *)data, buf.st_size);
2809    close(fd);
2810 
2811    es->str = value;
2812 
2813    if (!edje_file->data)
2814      edje_file->data = eina_hash_string_small_new(free);
2815 
2816    eina_hash_direct_add(edje_file->data, key, es);
2817 
2818    free(filename);
2819 }
2820 
2821 /** @edcsubsection{toplevel_color_tree,
2822  *                 Color Tree} */
2823 
2824 /**
2825     @page edcref
2826     @block
2827         color_tree
2828     @context
2829         color_tree {
2830             "color_class_0" {
2831                 "color_class_3";
2832                 "color_class_4" {
2833                     "color_class_5";
2834                     "color_class_6";
2835                 }
2836             }
2837             "color_class_1";
2838             "color_class_2";
2839             ..
2840         }
2841     @description
2842         The "color_tree" block contains color tree node blocks.
2843         Each node block begins with the name of color class and enclosed with braces.
2844         Node block can be placed within another node block.
2845     @endblock
2846  */
2847 static void
ob_color_tree(void)2848 ob_color_tree(void)
2849 {
2850    if (!is_verbatim()) track_verbatim(1);
2851    else
2852      {
2853         char *s;
2854 
2855         s = get_verbatim();
2856         if (s)
2857           {
2858              process_color_tree(s, file_in, get_verbatim_line1());
2859              set_verbatim(NULL, 0, 0);
2860           }
2861      }
2862 }
2863 
2864 /** @edcsubsection{toplevel_color_classes,
2865  *                 Color Classes} */
2866 
2867 /**
2868     @page edcref
2869     @block
2870         color_classes
2871     @context
2872         color_classes {
2873             color_class {
2874                 name:  "colorclassname";
2875                 color:  255 0 0 255;
2876                 color2: "#0F0F";
2877                 color3: "#0000FFFF";
2878             }
2879             ..
2880         }
2881     @description
2882         The "color_classes" block contains a list of one or more "color_class"
2883         blocks. Each "color_class" allows the designer to name an arbitrary
2884         group of colors to be used in the theme, the application can use that
2885         name to alter the color values at runtime.
2886     @endblock
2887  */
2888 static void
ob_color_class(void)2889 ob_color_class(void)
2890 {
2891    Edje_Color_Class *cc;
2892 
2893    cc = mem_alloc(SZ(Edje_Color_Class));
2894    edje_file->color_classes = eina_list_append(edje_file->color_classes, cc);
2895 
2896    cc->r = 0;
2897    cc->g = 0;
2898    cc->b = 0;
2899    cc->a = 0;
2900    cc->r2 = 0;
2901    cc->g2 = 0;
2902    cc->b2 = 0;
2903    cc->a2 = 0;
2904    cc->r3 = 0;
2905    cc->g3 = 0;
2906    cc->b3 = 0;
2907    cc->a3 = 0;
2908 }
2909 
2910 static void
_color_class_name(char * name)2911 _color_class_name(char *name)
2912 {
2913    Edje_Color_Class *cc, *tcc;
2914    Eina_List *l;
2915 
2916    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
2917    cc->name = name;
2918    EINA_LIST_FOREACH(edje_file->color_classes, l, tcc)
2919      {
2920         if ((cc != tcc) && (!strcmp(cc->name, tcc->name)))
2921           {
2922              ERR("parse error %s:%i. There is already a color class named \"%s\"",
2923                  file_in, line - 1, cc->name);
2924              exit(-1);
2925           }
2926      }
2927 }
2928 
2929 /**
2930     @page edcref
2931 
2932     @property
2933         name
2934     @parameters
2935         [color class name]
2936     @effect
2937         Sets the name for the color class, used as reference by both the theme
2938         and the application.
2939     @endproperty
2940  */
2941 static void
st_color_class_name(void)2942 st_color_class_name(void)
2943 {
2944    Edje_Color_Class *cc, *tcc;
2945    Eina_List *l;
2946 
2947    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
2948    cc->name = parse_str(0);
2949    EINA_LIST_FOREACH(edje_file->color_classes, l, tcc)
2950      {
2951         if ((cc != tcc) && (!strcmp(cc->name, tcc->name)))
2952           {
2953              ERR("parse error %s:%i. There is already a color class named \"%s\"",
2954                  file_in, line - 1, cc->name);
2955              exit(-1);
2956           }
2957      }
2958 }
2959 
2960 static void
parse_color(unsigned int first_arg,void * base)2961 parse_color(unsigned int first_arg, void *base)
2962 {
2963    Edje_Color *color = (Edje_Color *)base;
2964    int r, g, b, a;
2965    char *str;
2966 
2967    switch (get_arg_count() - first_arg)
2968      {
2969       case 1:
2970         str = parse_str(first_arg);
2971         convert_color_code(str, &r, &g, &b, &a);
2972         color->r = r;
2973         color->g = g;
2974         color->b = b;
2975         color->a = a;
2976         break;
2977 
2978       case 4:
2979         color->r = parse_int_range(first_arg + 0, 0, 255);
2980         color->g = parse_int_range(first_arg + 1, 0, 255);
2981         color->b = parse_int_range(first_arg + 2, 0, 255);
2982         color->a = parse_int_range(first_arg + 3, 0, 255);
2983         break;
2984 
2985       default:
2986         ERR("%s:%i. color code should be a string or a set of 4 integers.",
2987             file_in, line - 1);
2988         exit(-1);
2989      }
2990 }
2991 
2992 /**
2993     @page edcref
2994     @property
2995         color
2996     @parameters
2997         [red] [green] [blue] [alpha] or "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
2998     @effect
2999         The main color.
3000 
3001         Format:
3002         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
3003         RGBA channel, i.e. 255 0 0 255
3004         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
3005         i.e "#FF0000FF" or "#FF0000"
3006         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
3007         i.e "#F00F" or "#F00".\n
3008         In string format you can omit alpha channel and it will be set to FF.
3009 
3010         Defaults: 0 0 0 0
3011     @endproperty
3012  */
3013 static void
st_color_class_color(void)3014 st_color_class_color(void)
3015 {
3016    Edje_Color_Class *cc;
3017 
3018    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
3019 
3020    parse_color(0, &(cc->r));
3021 }
3022 
3023 /**
3024     @page edcref
3025     @property
3026         color2
3027     @parameters
3028         [red] [green] [blue] [alpha] or "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
3029     @effect
3030         Used as outline in text and textblock parts.
3031 
3032         Format:
3033         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
3034         RGBA channel, i.e. 255 0 0 255
3035         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
3036         i.e "#FF0000FF" or "#FF0000"
3037         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
3038         i.e "#F00F" or "#F00".\n
3039         In string format you can omit alpha channel and it will be set to FF.
3040 
3041         Defaults: 0 0 0 0
3042     @endproperty
3043  */
3044 static void
st_color_class_color2(void)3045 st_color_class_color2(void)
3046 {
3047    Edje_Color_Class *cc;
3048 
3049    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
3050 
3051    parse_color(0, &(cc->r2));
3052 }
3053 
3054 /**
3055     @page edcref
3056     @property
3057         color3
3058     @parameters
3059         [red] [green] [blue] [alpha] or "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
3060     @effect
3061         Used as shadow in text and textblock parts.
3062 
3063         Format:
3064         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
3065         RGBA channel, i.e. 255 0 0 255
3066         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
3067         i.e "#FF0000FF" or "#FF0000"
3068         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
3069         i.e "#F00F" or "#F00".\n
3070         In string format you can omit alpha channel and it will be set to FF.
3071 
3072         Defaults: 0 0 0 0
3073     @endproperty
3074  */
3075 static void
st_color_class_color3(void)3076 st_color_class_color3(void)
3077 {
3078    Edje_Color_Class *cc;
3079 
3080    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
3081 
3082    parse_color(0, &(cc->r3));
3083 }
3084 
3085 /**
3086     @page edcref
3087     @property
3088         description
3089     @parameters
3090         [color class description]
3091     @effect
3092         Provides a descriptive name for the effect of the color class
3093         @since 1.14
3094     @endproperty
3095  */
3096 static void
st_color_class_desc(void)3097 st_color_class_desc(void)
3098 {
3099    Edje_Color_Class *cc;
3100 
3101    check_arg_count(1);
3102 
3103    cc = eina_list_data_get(eina_list_last(edje_file->color_classes));
3104    cc->desc = parse_str(0);
3105 }
3106 
3107 /** @edcsubsection{toplevel_styles,
3108  *                 Styles} */
3109 
3110 /**
3111     @page edcref
3112     @block
3113         styles
3114     @context
3115         styles {
3116             style {
3117                 name: "stylename";
3118                 base: "..default style properties..";
3119 
3120                 tag:  "tagname" "..style properties..";
3121                 ..
3122             }
3123             ..
3124         }
3125     @description
3126         The "styles" block contains a list of one or more "style" blocks. A
3127         "style" block is used to create style \<tags\> for advanced TEXTBLOCK
3128         formatting.
3129     @endblock
3130  */
3131 static void
ob_styles_style(void)3132 ob_styles_style(void)
3133 {
3134    Edje_Style *stl;
3135 
3136    stl = mem_alloc(SZ(Edje_Style));
3137    edje_file->styles = eina_list_append(edje_file->styles, stl);
3138 }
3139 
3140 static void
_style_name(char * name)3141 _style_name(char *name)
3142 {
3143    Edje_Style *stl, *tstl;
3144    Eina_List *l;
3145 
3146    stl = eina_list_last_data_get(edje_file->styles);
3147    free(stl->name);
3148    stl->name = name;
3149    EINA_LIST_FOREACH(edje_file->styles, l, tstl)
3150      {
3151         if (stl->name && tstl->name && (stl != tstl) && (!strcmp(stl->name, tstl->name)))
3152           {
3153              ERR("parse error %s:%i. There is already a style named \"%s\"",
3154                  file_in, line - 1, stl->name);
3155              exit(-1);
3156           }
3157      }
3158 }
3159 
3160 /**
3161     @page edcref
3162     @property
3163         name
3164     @parameters
3165         [style name]
3166     @effect
3167         The name of  the style to be used as reference later in the theme.
3168     @endproperty
3169  */
3170 static void
st_styles_style_name(void)3171 st_styles_style_name(void)
3172 {
3173    _style_name(parse_str(0));
3174 }
3175 
3176 /**
3177     @page edcref
3178     @property
3179         base
3180     @parameters
3181         [style properties string]
3182     @effect
3183         The default style properties that will be applied to the complete
3184         text.
3185     @endproperty
3186  */
3187 static void
st_styles_style_base(void)3188 st_styles_style_base(void)
3189 {
3190    Edje_Style *stl;
3191    Edje_Style_Tag *tag;
3192 
3193    stl = eina_list_data_get(eina_list_last(edje_file->styles));
3194    if (stl->tags)
3195      {
3196         ERR("parse error %s:%i. There is already a basic format for the style",
3197             file_in, line - 1);
3198         exit(-1);
3199      }
3200    tag = mem_alloc(SZ(Edje_Style_Tag));
3201    tag->key = mem_strdup("DEFAULT");
3202    tag->value = parse_str(0);
3203    stl->tags = eina_list_append(stl->tags, tag);
3204 }
3205 
3206 /**
3207     @page edcref
3208     @property
3209         tag
3210     @parameters
3211         [tag name] [style properties string]
3212     @effect
3213         Style to be applied only to text between style \<tags\>..\</tags\>.
3214         When creating "paired" tags, like \<bold\>\</bold\>, A '+' should be added at the start of the style properties of the first part (\<bold\>).
3215         If the second part (\</bold\>) is also defined, a '-' should be prepended to it's style properties.
3216         This only applies to paired tags; Single tags, like \<tab\>, must not include a starting '+'.
3217     @endproperty
3218  */
3219 static void
st_styles_style_tag(void)3220 st_styles_style_tag(void)
3221 {
3222    Edje_Style *stl;
3223    Edje_Style_Tag *tag;
3224 
3225    stl = eina_list_data_get(eina_list_last(edje_file->styles));
3226    tag = mem_alloc(SZ(Edje_Style_Tag));
3227    tag->key = parse_str(0);
3228    tag->value = parse_str(1);
3229    stl->tags = eina_list_append(stl->tags, tag);
3230 }
3231 
3232 /** @edcsubsection{toplevel_text_classes,
3233  *                 Text Classes} */
3234 
3235 /**
3236     @page edcref
3237     @block
3238         text_classes
3239     @context
3240         text_classes {
3241            text_class {
3242               name: "text_class name";
3243               font: "font name";
3244               size: SIZE";
3245            }
3246             ..
3247         }
3248     @description
3249         The "text_classes" block contains a list of one or more "text_class"
3250         blocks. Each "text_class" allows the designer to name an arbitrary
3251         group of font and size to be used in the theme, the application can
3252         use that name to alter the font and its size at runtime.
3253     @endblock
3254  */
3255 static void
ob_text_class(void)3256 ob_text_class(void)
3257 {
3258    Edje_Text_Class *tc;
3259 
3260    tc = mem_alloc(SZ(Edje_Text_Class));
3261    edje_file->text_classes = eina_list_append(edje_file->text_classes, tc);
3262 
3263    tc->font = NULL;
3264    tc->size = 0;
3265 }
3266 
3267 static void
_text_class_name(char * name)3268 _text_class_name(char *name)
3269 {
3270    Edje_Text_Class *tc, *ttc;
3271    Eina_List *l;
3272 
3273    tc = eina_list_data_get(eina_list_last(edje_file->text_classes));
3274    tc->name = name;
3275    EINA_LIST_FOREACH(edje_file->text_classes, l, ttc)
3276      {
3277         if ((tc != ttc) && (!strcmp(tc->name, ttc->name)))
3278           {
3279              ERR("parse error %s:%i. There is already a text class named \"%s\"",
3280                  file_in, line - 1, tc->name);
3281              exit(-1);
3282           }
3283      }
3284 }
3285 
3286 /**
3287     @page edcref
3288 
3289     @property
3290         name
3291     @parameters
3292         [text class name]
3293     @effect
3294         Sets the name for the text class, used as reference by both the theme
3295         and the application.
3296     @endproperty
3297  */
3298 static void
st_text_class_name(void)3299 st_text_class_name(void)
3300 {
3301    Edje_Text_Class *tc, *ttc;
3302    Eina_List *l;
3303 
3304    tc = eina_list_data_get(eina_list_last(edje_file->text_classes));
3305    tc->name = parse_str(0);
3306    EINA_LIST_FOREACH(edje_file->text_classes, l, ttc)
3307      {
3308         if ((tc != ttc) && (!strcmp(tc->name, ttc->name)))
3309           {
3310              ERR("parse error %s:%i. There is already a text class named \"%s\"",
3311                  file_in, line - 1, tc->name);
3312              exit(-1);
3313           }
3314      }
3315 }
3316 
3317 /**
3318     @page edcref
3319 
3320     @property
3321         font
3322     @parameters
3323         [font name]
3324     @effect
3325         Sets the font family for the text class.
3326     @endproperty
3327  */
3328 static void
st_text_class_font(void)3329 st_text_class_font(void)
3330 {
3331    Edje_Text_Class *tc;
3332 
3333    check_arg_count(1);
3334 
3335    tc = eina_list_data_get(eina_list_last(edje_file->text_classes));
3336    tc->font = parse_str(0);
3337 }
3338 
3339 /**
3340     @page edcref
3341 
3342     @property
3343         size
3344     @parameters
3345         [font size in points (pt)]
3346     @effect
3347         Sets the font size for the text class.
3348 
3349         Defaults: 0
3350     @endproperty
3351  */
3352 static void
st_text_class_size(void)3353 st_text_class_size(void)
3354 {
3355    Edje_Text_Class *tc;
3356 
3357    check_arg_count(1);
3358 
3359    tc = eina_list_data_get(eina_list_last(edje_file->text_classes));
3360    tc->size = parse_int_range(0, 0, 255);
3361 }
3362 
3363 /** @edcsubsection{toplevel_size_classes,
3364  *                 Size Classes} */
3365 
3366 /**
3367     @page edcref
3368     @block
3369         size_classes
3370     @context
3371         size_classes {
3372            size_class {
3373               name:  "sizeclassname";
3374               min: width height;
3375               max: width height;
3376            }
3377             ..
3378         }
3379     @description
3380         The "size_classes" block contains a list of one or more "size_class"
3381         blocks. Each "size_class" allows the designer to name an arbitrary
3382         group of size to be used in the theme, the application can use that
3383         name to alter the min and max size values at runtime.
3384     @endblock
3385  */
3386 static void
ob_size_class(void)3387 ob_size_class(void)
3388 {
3389    Edje_Size_Class *sc;
3390 
3391    sc = mem_alloc(SZ(Edje_Size_Class));
3392    edje_file->size_classes = eina_list_append(edje_file->size_classes, sc);
3393 
3394    sc->minw = 0;
3395    sc->minh = 0;
3396    sc->maxw = -1;
3397    sc->maxh = -1;
3398 }
3399 
3400 static void
_size_class_name(char * name)3401 _size_class_name(char *name)
3402 {
3403    Edje_Size_Class *sc, *tsc;
3404    Eina_List *l;
3405 
3406    sc = eina_list_data_get(eina_list_last(edje_file->size_classes));
3407    sc->name = name;
3408    EINA_LIST_FOREACH(edje_file->size_classes, l, tsc)
3409      {
3410         if ((sc != tsc) && (!strcmp(sc->name, tsc->name)))
3411           {
3412              ERR("parse error %s:%i. There is already a size class named \"%s\"",
3413                  file_in, line - 1, sc->name);
3414              exit(-1);
3415           }
3416      }
3417 }
3418 
3419 /**
3420     @page edcref
3421 
3422     @property
3423         name
3424     @parameters
3425         [size class name]
3426     @effect
3427         Sets the name for the size class, used as reference by both the theme
3428         and the application.
3429     @endproperty
3430  */
3431 static void
st_size_class_name(void)3432 st_size_class_name(void)
3433 {
3434    Edje_Size_Class *sc, *tsc;
3435    Eina_List *l;
3436 
3437    sc = eina_list_data_get(eina_list_last(edje_file->size_classes));
3438    sc->name = parse_str(0);
3439    EINA_LIST_FOREACH(edje_file->size_classes, l, tsc)
3440      {
3441         if ((sc != tsc) && (!strcmp(sc->name, tsc->name)))
3442           {
3443              ERR("parse error %s:%i. There is already a size class named \"%s\"",
3444                  file_in, line - 1, sc->name);
3445              exit(-1);
3446           }
3447      }
3448 }
3449 
3450 /**
3451     @page edcref
3452     @property
3453         min
3454     @parameters
3455         [width] [height]
3456     @effect
3457         The minimum size.
3458 
3459         Defaults: 0 0
3460     @endproperty
3461  */
3462 static void
st_size_class_min(void)3463 st_size_class_min(void)
3464 {
3465    Edje_Size_Class *sc;
3466 
3467    check_arg_count(2);
3468 
3469    sc = eina_list_data_get(eina_list_last(edje_file->size_classes));
3470    sc->minw = parse_int_range(0, 0, 0x7fffffff);
3471    sc->minh = parse_int_range(1, 0, 0x7fffffff);
3472 }
3473 
3474 /**
3475     @page edcref
3476     @property
3477         max
3478     @parameters
3479         [width] [height]
3480     @effect
3481         The maximum size.
3482 
3483         Defaults: -1 -1
3484     @endproperty
3485  */
3486 static void
st_size_class_max(void)3487 st_size_class_max(void)
3488 {
3489    Edje_Size_Class *sc;
3490 
3491    check_arg_count(2);
3492 
3493    sc = eina_list_data_get(eina_list_last(edje_file->size_classes));
3494    sc->maxw = parse_int_range(0, -1, 0x7fffffff);
3495    sc->maxh = parse_int_range(1, -1, 0x7fffffff);
3496 }
3497 
3498 /** @edcsection{collections,Collections Blocks} */
3499 
3500 /** @edcsubsection{sub_collections,
3501  *                 Collections} */
3502 
3503 /**
3504     @page edcref
3505     @block
3506         collections
3507     @context
3508         collections {
3509             base_scale: 1.2;
3510             sounds { }
3511             vibrations { }
3512             group { }
3513             group { }
3514             ..
3515         }
3516     @description
3517         The "collections" block is used to list the groups that compose the
3518         theme. Additional "collections" blocks do not prevent overriding group
3519         names. The "sounds" block comprises of all sound definitions. The "vibrations"
3520         block compriese all vibration definitions.
3521     @endblock
3522  */
3523 static void
ob_collections(void)3524 ob_collections(void)
3525 {
3526    if (!edje_file->collection)
3527      {
3528         edje_file->collection = eina_hash_string_small_new(NULL);
3529         edje_collections_lookup = eina_hash_int32_new(NULL);
3530         desc_hash = eina_hash_pointer_new(NULL);
3531      }
3532 }
3533 
3534 /**
3535     @page edcref
3536     @property
3537         base_scale
3538     @parameters
3539         [scale val]
3540     @effect
3541         The base_scale is the standard scale value of the collection.
3542         The default base_scale is 1.0. It means the collection is made in the environment
3543         which is same with a desktop(The monitor has 96 dpi).
3544         If you make a collection in another environment(ex: 115 dpi), you have to
3545         set the base_scale(ex: 1.2). Then it will be shown same size in the desktop.
3546 
3547         Defaults: 1.0
3548     @since 1.11
3549     @endproperty
3550  */
3551 static void
st_collections_base_scale(void)3552 st_collections_base_scale(void)
3553 {
3554    check_min_arg_count(1);
3555 
3556    edje_file->base_scale = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
3557    if (EQ(edje_file->base_scale, ZERO))
3558      {
3559         ERR("The base_scale is 0.0. The value should be bigger than 0.0.");
3560         exit(-1);
3561      }
3562 }
3563 
3564 /** @edcsubsection{collections_sounds,
3565  *                 Sounds} */
3566 
3567 /**
3568     @page edcref
3569     @block
3570         sounds
3571     @context
3572         sounds {
3573             tone: "tone-1"  2300;
3574             tone: "tone-2"  2300;
3575             sample { }
3576             sample { }
3577             ..
3578         }
3579     @description
3580         The "sounds" block contains a list of one or more sound sample and tones items.
3581     @endblock
3582  */
3583 
3584 /**
3585     @page edcref
3586     @property
3587         tone
3588     @parameters
3589         [tone name] [frequency]
3590     @effect
3591         sound of specific frequency
3592     @since 1.1
3593     @endproperty
3594  */
3595 static void
st_collections_group_sound_tone(void)3596 st_collections_group_sound_tone(void)
3597 {
3598    Edje_Sound_Tone *tone;
3599    const char *tmp;
3600    unsigned int i;
3601    int value;
3602 
3603    check_arg_count(2);
3604 
3605    if (!edje_file->sound_dir)
3606      edje_file->sound_dir = mem_alloc(SZ(Edje_Sound_Directory));
3607 
3608    tmp = parse_str(0);
3609    /* Audible range 20 to 20KHz */
3610    value = parse_int_range(1, 20, 20000);
3611 
3612    /* Check for Tone duplication */
3613    for (i = 0; i < edje_file->sound_dir->tones_count; i++)
3614      {
3615         if (!strcmp(edje_file->sound_dir->tones[i].name, tmp))
3616           {
3617              ERR("Tone name: %s already exist.", tmp);
3618              free((char *)tmp);
3619              exit(-1);
3620           }
3621         if (edje_file->sound_dir->tones[i].value == value)
3622           {
3623              ERR("Tone name %s with same frequency %d exist.",
3624                  edje_file->sound_dir->tones[i].name, value);
3625              exit(-1);
3626           }
3627      }
3628    edje_file->sound_dir->tones_count++;
3629    tone = realloc(edje_file->sound_dir->tones,
3630                   sizeof (Edje_Sound_Tone) *
3631                   edje_file->sound_dir->tones_count);
3632    if (!tone)
3633      {
3634         ERR("No enough memory.");
3635         exit(-1);
3636      }
3637    edje_file->sound_dir->tones = tone;
3638 
3639    tone = edje_file->sound_dir->tones + edje_file->sound_dir->tones_count - 1;
3640    memset(tone, 0, sizeof (Edje_Sound_Tone));
3641 
3642    tone->name = tmp;
3643    tone->value = value;
3644    tone->id = edje_file->sound_dir->tones_count - 1;
3645 }
3646 
3647 /** @edcsubsection{collections_sounds_sample,
3648  *                 Sounds.Sample} */
3649 
3650 /**
3651     @page edcref
3652     @block
3653         sample
3654     @context
3655         sounds {
3656             ..
3657             sample {
3658                 name: "sound_file1" RAW;
3659                 source: "sound_file1.wav";
3660             }
3661             sample {
3662                 name: "sound_file2" LOSSY 0.5;
3663                 source: "sound_file2.wav";
3664             }
3665         }
3666     @description
3667         The sample block defines the sound sample.
3668     @endblock
3669     @property
3670         name
3671     @parameters
3672         [sample name] [compression type] (quality)
3673     @effect
3674         Used to include each sound file. The full path to the directory holding
3675         the sounds can be defined later with edje_cc's "-sd" option.
3676         Valid types are:
3677         @li RAW: Uncompressed.
3678         @li COMP: Lossless compression.
3679         @li LOSSY [45.0  - 1000.0]: Lossy compression with quality from 45.0 to 1000.0.
3680         @li AS_IS: Check for re-encoding, no compression/encoding, just write the file information as it is.
3681 
3682     @since 1.1
3683     @endproperty
3684  */
3685 static void
st_collections_group_sound_sample_name(void)3686 st_collections_group_sound_sample_name(void)
3687 {
3688    Edje_Sound_Sample *sample;
3689    const char *tmp;
3690    unsigned int i;
3691 
3692    if (!edje_file->sound_dir)
3693      edje_file->sound_dir = mem_alloc(SZ(Edje_Sound_Directory));
3694 
3695    tmp = parse_str(0);
3696 
3697    for (i = 0; i < edje_file->sound_dir->samples_count; i++)
3698      {
3699         if (!strcmp(edje_file->sound_dir->samples[i].name, tmp))
3700           {
3701              free((char *)tmp);
3702              return;
3703           }
3704      }
3705 
3706    edje_file->sound_dir->samples_count++;
3707    sample = realloc(edje_file->sound_dir->samples,
3708                     sizeof(Edje_Sound_Sample) *
3709                     edje_file->sound_dir->samples_count);
3710    if (!sample)
3711      {
3712         ERR("No enough memory.");
3713         exit(-1);
3714      }
3715    edje_file->sound_dir->samples = sample;
3716 
3717    sample =
3718      edje_file->sound_dir->samples +
3719      edje_file->sound_dir->samples_count - 1;
3720    memset(sample, 0, sizeof (Edje_Sound_Sample));
3721 
3722    sample->name = tmp;
3723    sample->id = edje_file->sound_dir->samples_count - 1;
3724    sample->compression = parse_enum(1,
3725                                     "RAW", EDJE_SOUND_SOURCE_TYPE_INLINE_RAW,
3726                                     "COMP", EDJE_SOUND_SOURCE_TYPE_INLINE_COMP,
3727                                     "LOSSY", EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY,
3728                                     "AS_IS", EDJE_SOUND_SOURCE_TYPE_INLINE_AS_IS,
3729                                     NULL);
3730 
3731    if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY)
3732      {
3733         sample->quality = parse_float_range(2, 45.0, 1000.0);
3734         check_arg_count(3);
3735      }
3736    else
3737      check_arg_count(2);
3738 }
3739 
3740 /**
3741     @page edcref
3742     @property
3743         source
3744     @parameters
3745         [sound file name]
3746     @effect
3747         The Sound source file name (Source can be mono/stereo WAV file.
3748         Only files with 44.1 KHz sample rate supported now)
3749     @since 1.1
3750     @endproperty
3751  */
3752 static void
st_collections_group_sound_sample_source(void)3753 st_collections_group_sound_sample_source(void)
3754 {
3755    Edje_Sound_Sample *sample;
3756 
3757    if (!edje_file->sound_dir->samples)
3758      {
3759         ERR("Invalid sound sample source definition.");
3760         exit(-1);
3761      }
3762 
3763    sample =
3764      edje_file->sound_dir->samples +
3765      edje_file->sound_dir->samples_count - 1;
3766    sample->snd_src = parse_str(0);
3767    check_arg_count(1);
3768 }
3769 
3770 /** @edcsubsection{collections_vibrations,
3771  *                 Vibrations} */
3772 
3773 /**
3774     @page edcref
3775     @block
3776         vibrations
3777     @context
3778         vibrations {
3779            sample { }
3780            sample { }
3781            ..
3782         }
3783 
3784     @description
3785         The "vibrations" block contains a list of one or more vibration sample.
3786     @since 1.10
3787     @endblock
3788  */
3789 
3790 /** @edcsubsection{collections_vibrations_sample,
3791  *                 Vibrations.Sample} */
3792 
3793 /**
3794     @page edcref
3795     @block
3796         sample
3797     @context
3798         vibrations {
3799             sample {
3800                 name: "vibration_file1";
3801                 source: "vibration_file1.xxx";
3802             }
3803             ..
3804         }
3805     @description
3806         The sample block defines the vibration sample.
3807     @endblock
3808     @property
3809         name
3810     @parameters
3811         [sample name]
3812     @effect
3813         Used to include each vibration file. The full path to the directory holding
3814         the vibrations can be defined later with edje_cc's "-vd" option.
3815     @since 1.10
3816     @endproperty
3817  */
3818 static void
st_collections_group_vibration_sample_name(void)3819 st_collections_group_vibration_sample_name(void)
3820 {
3821    Edje_Vibration_Sample *sample;
3822    const char *tmp;
3823    unsigned int i;
3824 
3825    if (!edje_file->vibration_dir)
3826      edje_file->vibration_dir = mem_alloc(SZ(Edje_Vibration_Directory));
3827 
3828    tmp = parse_str(0);
3829 
3830    for (i = 0; i < edje_file->vibration_dir->samples_count; i++)
3831      {
3832         if (!strcmp(edje_file->vibration_dir->samples[i].name, tmp))
3833           {
3834              free((char *)tmp);
3835              return;
3836           }
3837      }
3838 
3839    edje_file->vibration_dir->samples_count++;
3840    sample = realloc(edje_file->vibration_dir->samples,
3841                     sizeof(Edje_Vibration_Sample) *
3842                     edje_file->vibration_dir->samples_count);
3843    if (!sample)
3844      {
3845         ERR("No enough memory.");
3846         exit(-1);
3847      }
3848    edje_file->vibration_dir->samples = sample;
3849 
3850    sample =
3851      edje_file->vibration_dir->samples +
3852      edje_file->vibration_dir->samples_count - 1;
3853    memset(sample, 0, sizeof(Edje_Vibration_Sample));
3854 
3855    sample->name = tmp;
3856    sample->id = edje_file->vibration_dir->samples_count - 1;
3857 
3858    check_arg_count(1);
3859 }
3860 
3861 /**
3862     @page edcref
3863     @property
3864         source
3865     @parameters
3866         [vibration file name]
3867     @effect
3868         The Vibration source file name
3869     @since 1.10
3870     @endproperty
3871  */
3872 static void
st_collections_group_vibration_sample_source(void)3873 st_collections_group_vibration_sample_source(void)
3874 {
3875    Edje_Vibration_Sample *sample;
3876 
3877    if (!edje_file->vibration_dir->samples)
3878      {
3879         ERR("Invalid vibration sample source definition.");
3880         exit(-1);
3881      }
3882 
3883    sample =
3884      edje_file->vibration_dir->samples +
3885      edje_file->vibration_dir->samples_count - 1;
3886    sample->src = parse_str(0);
3887    check_arg_count(1);
3888 }
3889 
3890 /** @edcsubsection{collections_translation_file,
3891  *                 translation.file} */
3892 
3893 /**
3894     @page edcref
3895     @block
3896         file
3897     @context
3898         translation {
3899             ..
3900             file {
3901                 locale: "en_IN";
3902                 source: "domain_name.po";
3903             }
3904             file {
3905                 locale: "en_US";
3906                 source: "domain_name.po";
3907             }
3908         }
3909     @description
3910         The file block defines the po or mo file.
3911     @endblock
3912     @property
3913         name
3914     @parameters
3915         [locale name]
3916     @effect
3917         Used to include each po or mo file. The full path to the directory holding
3918         the po or mo file can be defined later with edje_cc's "-md" option.
3919 
3920     @since 1.15
3921     @endproperty
3922  */
3923 static void
st_collections_group_translation_file_locale(void)3924 st_collections_group_translation_file_locale(void)
3925 {
3926    Edje_Mo *mo_entry;
3927    const char *tmp;
3928    unsigned int i;
3929 
3930    check_arg_count(1);
3931 
3932    if (!edje_file->mo_dir)
3933      edje_file->mo_dir = mem_alloc(SZ(Edje_Mo_Directory));
3934 
3935    tmp = parse_str(0);
3936 
3937    for (i = 0; i < edje_file->mo_dir->mo_entries_count; i++)
3938      {
3939         if (!strcmp(edje_file->mo_dir->mo_entries[i].locale, tmp))
3940           {
3941              free((char *)tmp);
3942              return;
3943           }
3944      }
3945 
3946    edje_file->mo_dir->mo_entries_count++;
3947    mo_entry = realloc(edje_file->mo_dir->mo_entries, sizeof(Edje_Mo) * edje_file->mo_dir->mo_entries_count);
3948 
3949    if (!mo_entry)
3950      {
3951         ERR("No enough memory.");
3952         exit(-1);
3953      }
3954    edje_file->mo_dir->mo_entries = mo_entry;
3955 
3956    mo_entry = edje_file->mo_dir->mo_entries + edje_file->mo_dir->mo_entries_count - 1;
3957    memset(mo_entry, 0, sizeof (Edje_Mo));
3958 
3959    mo_entry->locale = tmp;
3960    mo_entry->id = edje_file->mo_dir->mo_entries_count - 1;
3961 }
3962 
3963 /**
3964     @page edcref
3965     @property
3966         source
3967     @parameters
3968         [po file name or Mo file name]
3969     @effect
3970         The po or mo source file name (Source should be a valid po or mo file.
3971         Only po or mo files are supported now)
3972     @since 1.15
3973     @endproperty
3974  */
3975 
3976 static void
st_collections_group_translation_file_source(void)3977 st_collections_group_translation_file_source(void)
3978 {
3979    Edje_Mo *mo_entry;
3980 
3981    check_arg_count(1);
3982 
3983    if (!edje_file->mo_dir->mo_entries)
3984      {
3985         ERR("Invalid mo source definition.");
3986         exit(-1);
3987      }
3988 
3989    mo_entry = edje_file->mo_dir->mo_entries + edje_file->mo_dir->mo_entries_count - 1;
3990    mo_entry->mo_src = parse_str(0);
3991 }
3992 
3993 static void
_link_combine(void)3994 _link_combine(void)
3995 {
3996    Edje_Part_Collection *pc;
3997    Edje_Part_Collection_Parser *pcp;
3998    Eina_Iterator *it;
3999    Eina_Hash_Tuple *tup;
4000 
4001    pc = eina_list_last_data_get(edje_collections);
4002    pcp = eina_list_last_data_get(edje_collections);
4003 
4004    if (!pcp->link_hash) return;
4005    it = eina_hash_iterator_tuple_new(pcp->link_hash);
4006    EINA_ITERATOR_FOREACH(it, tup)
4007      {
4008         while (tup->data)
4009           {
4010              Edje_Part_Description_Link *el, *ell;
4011              Eina_List *l, *ll, *combine = NULL;
4012 
4013              el = eina_list_data_get(tup->data);
4014              tup->data = eina_list_remove_list(tup->data, tup->data);
4015              EINA_LIST_FOREACH_SAFE(tup->data, l, ll, ell)
4016                {
4017                   if (ell->pr->tween.mode != el->pr->tween.mode) continue;
4018                   if (!EQ(ell->pr->tween.time, el->pr->tween.time)) continue;
4019                   if (!EQ(ell->pr->tween.v1, el->pr->tween.v1)) continue;
4020                   if (!EQ(ell->pr->tween.v2, el->pr->tween.v2)) continue;
4021                   if (!EQ(ell->pr->tween.v3, el->pr->tween.v3)) continue;
4022                   if (!EQ(ell->pr->tween.v4, el->pr->tween.v4)) continue;
4023                   if (!EQ(ell->ed->state.value, el->ed->state.value)) continue;
4024                   if ((!!ell->ed->state.name) != (!!el->ed->state.name))
4025                     {
4026                        if (((!!ell->ed->state.name) && strcmp(ell->ed->state.name, "default")) ||
4027                            ((!!el->ed->state.name) && strcmp(el->ed->state.name, "default")))
4028                          continue;
4029                     }
4030                   else if (ell->ed->state.name && strcmp(ell->ed->state.name, el->ed->state.name))
4031                     continue;
4032                   eina_list_move_list(&combine, (Eina_List **)&tup->data, l);
4033                }
4034              current_program = el->pr;
4035              if (!el->epp->common.name)
4036                {
4037                   ERR("A part without a name was detected.");
4038                   exit(-1);
4039                }
4040              _program_target_add(strdup(el->epp->common.name));
4041              EINA_LIST_FREE(combine, ell)
4042                {
4043                   char *name;
4044 
4045                   _program_target_add(strdup(ell->epp->common.name));
4046                   EINA_LIST_FOREACH(ell->pr->after, l, name)
4047                     _program_after(name);
4048                   _program_free(ell->pr);
4049                   free(ell);
4050                }
4051              _edje_program_insert(pc, current_program);
4052           }
4053      }
4054    eina_iterator_free(it);
4055    eina_hash_free(pcp->link_hash);
4056    pcp->links = eina_list_free(pcp->links);
4057    current_program = NULL;
4058 }
4059 
4060 /** @edcsubsection{collections_group,
4061  *                 Group} */
4062 
4063 /**
4064     @page edcref
4065     @block
4066         group
4067     @context
4068         collections {
4069             ..
4070             group {
4071                 name: "nameusedbytheapplication";
4072                 alias: "anothername";
4073                 min: width height;
4074                 max: width height;
4075 
4076                 script { }
4077                 limits { }
4078                 data { }
4079                 parts { }
4080                 programs { }
4081             }
4082             ..
4083         }
4084     @description
4085         A "group" block contains the list of parts and programs that compose a
4086         given Edje Object.
4087     @endblock
4088  */
4089 static void
ob_collections_group(void)4090 ob_collections_group(void)
4091 {
4092    Edje_Part_Collection *pc;
4093    Edje_Part_Collection_Parser *pcp;
4094    Code *cd;
4095 
4096    if (current_de && !current_de->entry)
4097      {
4098         ERR("A collection without a name was detected, that's not allowed.");
4099         exit(-1);
4100      }
4101    current_program = NULL;
4102    current_part = NULL;
4103    current_desc = NULL;
4104 
4105    current_group_inherit = EINA_FALSE;
4106    script_is_replaceable = EINA_FALSE;
4107 
4108    current_de = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
4109    current_de->id = eina_list_count(edje_collections);
4110 
4111    if (!edje_collections_lookup)
4112      ob_collections();
4113    eina_hash_add(edje_collections_lookup, &current_de->id, current_de);
4114 
4115    pc = mem_alloc(SZ(Edje_Part_Collection_Parser));
4116    edje_collections = eina_list_append(edje_collections, pc);
4117    pc->id = current_de->id;
4118    pc->broadcast_signal = EINA_TRUE; /* This was the behaviour by default in Edje 1.1 */
4119 
4120    cd = mem_alloc(SZ(Code));
4121    codes = eina_list_append(codes, cd);
4122 
4123    pcp = (Edje_Part_Collection_Parser *)pc;
4124    pcp->default_mouse_events = 1;
4125    pcp->inherit_script = EINA_FALSE;
4126 
4127 #ifdef HAVE_EPHYSICS
4128    pc->physics.world.gravity.x = 0;
4129    pc->physics.world.gravity.y = 294;
4130    pc->physics.world.gravity.z = 0;
4131    pc->physics.world.depth = 100;
4132    pc->physics.world.z = -50;
4133    pc->physics.world.rate = FROM_DOUBLE(30);
4134 #endif
4135 }
4136 
4137 static void
_group_name(char * name)4138 _group_name(char *name)
4139 {
4140    Edje_Part_Collection_Directory_Entry *alias;
4141    Edje_Part_Collection_Directory_Entry *older;
4142    Edje_Part_Collection *current_pc;
4143    Eina_List *l = NULL;
4144 
4145    current_pc = eina_list_data_get(eina_list_last(edje_collections));
4146 
4147    if (current_de->entry)
4148      goto double_named_group;
4149 
4150    current_de->entry = name;
4151    current_pc->part = current_de->entry;
4152 
4153    older = eina_hash_find(edje_file->collection, current_de->entry);
4154    if (older) eina_hash_del(edje_file->collection, current_de->entry, older);
4155    eina_hash_direct_add(edje_file->collection, current_de->entry, current_de);
4156    if (!older) return;
4157 
4158    EINA_LIST_FOREACH(aliases, l, alias)
4159      if (strcmp(alias->entry, current_de->entry) == 0)
4160        {
4161           Edje_Part_Collection *pc;
4162 
4163           pc = eina_list_nth(edje_collections, older->id);
4164           INF("overriding alias ('%s' => '%s') by group '%s'",
4165               alias->entry, pc->part,
4166               current_de->entry);
4167           aliases = eina_list_remove_list(aliases, l);
4168           free(alias);
4169           break;
4170        }
4171 
4172 double_named_group:
4173    ERR("Invalid group '%s', only a single name statement is valid for group,"
4174        "use alias instead.", current_de->entry);
4175    exit(-1);
4176 }
4177 
4178 /**
4179     @page edcref
4180     @property
4181         name
4182     @parameters
4183         [group name]
4184     @effect
4185         The name that will be used by the application to load the resulting
4186         Edje object and to identify the group to swallow in a GROUP part. If
4187         group with the same name exists already, it won't be compiled.
4188         Only a single name statement is valid for group, use alias instead if
4189         you want to give additional names.
4190     @endproperty
4191  */
4192 static void
st_collections_group_name(void)4193 st_collections_group_name(void)
4194 {
4195    check_arg_count(1);
4196    _group_name(parse_str(0));
4197 }
4198 
4199 /**
4200     @page edcref
4201     @property
4202         skip_namespace_validation
4203     @parameters
4204         [1 or 0]
4205     @effect
4206         This disables namespace validation for the current group if validation has
4207         been enabled with edje_cc's -N option.
4208         This property can be inherited.
4209         Defaults: 0
4210 
4211     @warning Your edc file should always wrap this keyword with <tt>\#ifdef HAVE_SKIP_NAMESPACE_VALIDATION</tt>
4212     @since 1.21
4213     @endproperty
4214  */
4215 static void
st_collections_group_skip_namespace_validation(void)4216 st_collections_group_skip_namespace_validation(void)
4217 {
4218    Edje_Part_Collection_Parser *pcp = eina_list_last_data_get(edje_collections);
4219    check_arg_count(1);
4220    pcp->skip_namespace_validation = parse_bool(0);
4221 }
4222 
4223 typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data;
4224 struct _Edje_List_Foreach_Data
4225 {
4226    Eina_List *list;
4227 };
4228 
4229 static Eina_Bool
_edje_data_item_list_foreach(const Eina_Hash * hash EINA_UNUSED,const void * key,void * data EINA_UNUSED,void * fdata)4230 _edje_data_item_list_foreach(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata)
4231 {
4232    Edje_List_Foreach_Data *fd;
4233 
4234    fd = fdata;
4235    fd->list = eina_list_append(fd->list, strdup(key));
4236 
4237    return EINA_TRUE;
4238 }
4239 
4240 static void
_filter_copy(Edje_Part_Description_Spec_Filter * ed,const Edje_Part_Description_Spec_Filter * parent)4241 _filter_copy(Edje_Part_Description_Spec_Filter *ed, const Edje_Part_Description_Spec_Filter *parent)
4242 {
4243    ed->code = STRDUP(parent->code);
4244    if (ed->code)
4245      {
4246         const char *name;
4247         Eina_List *l;
4248         unsigned k;
4249 
4250         ed->name = STRDUP(parent->name);
4251         ed->sources = NULL;
4252         EINA_LIST_FOREACH(parent->sources, l, name)
4253           ed->sources = eina_list_append(ed->sources, STRDUP(name));
4254         ed->data = NULL;
4255         ed->data_count = 0;
4256         if (parent->data)
4257           {
4258              ed->data = mem_alloc(parent->data_count * sizeof(*parent->data));
4259              ed->data_count = parent->data_count;
4260              for (k = 0; k < parent->data_count; k++)
4261                {
4262                   ed->data[k].name = STRDUP(parent->data[k].name);
4263                   ed->data[k].value = STRDUP(parent->data[k].value);
4264                }
4265           }
4266      }
4267    else memset(ed, 0, sizeof(*ed));
4268 }
4269 
4270 static void
_parts_count_update(unsigned int type,int inc)4271 _parts_count_update(unsigned int type, int inc)
4272 {
4273    switch (type)
4274      {
4275       case EDJE_PART_TYPE_RECTANGLE:
4276         current_de->count.RECTANGLE += inc;
4277         break;
4278 
4279       case EDJE_PART_TYPE_TEXT:
4280         current_de->count.TEXT += inc;
4281         break;
4282 
4283       case EDJE_PART_TYPE_IMAGE:
4284         current_de->count.IMAGE += inc;
4285         break;
4286 
4287       case EDJE_PART_TYPE_SWALLOW:
4288         current_de->count.SWALLOW += inc;
4289         break;
4290 
4291       case EDJE_PART_TYPE_TEXTBLOCK:
4292         current_de->count.TEXTBLOCK += inc;
4293         break;
4294 
4295       case EDJE_PART_TYPE_GROUP:
4296         current_de->count.GROUP += inc;
4297         break;
4298 
4299       case EDJE_PART_TYPE_BOX:
4300         current_de->count.BOX += inc;
4301         break;
4302 
4303       case EDJE_PART_TYPE_TABLE:
4304         current_de->count.TABLE += inc;
4305         break;
4306 
4307       case EDJE_PART_TYPE_EXTERNAL:
4308         current_de->count.EXTERNAL += inc;
4309         break;
4310 
4311       case EDJE_PART_TYPE_PROXY:
4312         current_de->count.PROXY += inc;
4313         break;
4314 
4315       case EDJE_PART_TYPE_SPACER:
4316         current_de->count.SPACER += inc;
4317         break;
4318 
4319       case EDJE_PART_TYPE_SNAPSHOT:
4320         current_de->count.SNAPSHOT += inc;
4321         break;
4322 
4323       case EDJE_PART_TYPE_VECTOR:
4324         current_de->count.VECTOR += inc;
4325         break;
4326      }
4327    current_de->count.part += inc;
4328 }
4329 
4330 static void
_part_copy(Edje_Part * ep,Edje_Part * ep2)4331 _part_copy(Edje_Part *ep, Edje_Part *ep2)
4332 {
4333    Edje_Part_Collection *pc;
4334    Edje_Part_Parser *epp, *epp2;
4335    Edje_Pack_Element *item, *item2;
4336    Edje_Pack_Element_Parser *pitem;
4337    Edje_Part_Description_Common *ed, *ed2;
4338    unsigned int j;
4339 
4340    pc = eina_list_last_data_get(edje_collections);
4341 
4342    ep->name = STRDUP(ep2->name);
4343    ep->source = STRDUP(ep2->source);
4344    ep->source2 = STRDUP(ep2->source2);
4345    ep->source3 = STRDUP(ep2->source3);
4346    ep->source4 = STRDUP(ep2->source4);
4347    ep->source5 = STRDUP(ep2->source5);
4348    ep->source6 = STRDUP(ep2->source6);
4349 
4350    data_queue_copied_part_lookup(pc, &(ep2->clip_to_id), &(ep->clip_to_id));
4351 
4352    ep->type = ep2->type;
4353    ep->mouse_events = ep2->mouse_events;
4354    ep->anti_alias = ep2->anti_alias;
4355    ep->repeat_events = ep2->repeat_events;
4356    ep->ignore_flags = ep2->ignore_flags;
4357    ep->mask_flags = ep2->mask_flags;
4358    ep->scale = ep2->scale;
4359    ep->pointer_mode = ep2->pointer_mode;
4360    ep->precise_is_inside = ep2->precise_is_inside;
4361    ep->use_alternate_font_metrics = ep2->use_alternate_font_metrics;
4362    ep->effect = ep2->effect;
4363    ep->entry_mode = ep2->entry_mode;
4364    ep->select_mode = ep2->select_mode;
4365    ep->cursor_mode = ep2->cursor_mode;
4366    ep->multiline = ep2->multiline;
4367    ep->access = ep2->access;
4368    ep->no_render = ep2->no_render;
4369    ep->required = ep2->required;
4370    ep->dragable.x = ep2->dragable.x;
4371    ep->dragable.step_x = ep2->dragable.step_x;
4372    ep->dragable.count_x = ep2->dragable.count_x;
4373    ep->dragable.y = ep2->dragable.y;
4374    ep->dragable.step_y = ep2->dragable.step_y;
4375    ep->dragable.count_y = ep2->dragable.count_y;
4376    ep->nested_children_count = ep2->nested_children_count;
4377 
4378    if (ep2->allowed_seats)
4379      {
4380         Edje_Part_Allowed_Seat *seat;
4381         unsigned int s;
4382 
4383         ep->allowed_seats_count = ep2->allowed_seats_count;
4384         ep->allowed_seats = calloc(ep2->allowed_seats_count,
4385                                    sizeof(Edje_Part_Allowed_Seat *));
4386         if (!ep->allowed_seats)
4387           {
4388              ERR("Not enough memory.");
4389              exit(-1);
4390           }
4391 
4392         for (s = 0; s < ep->allowed_seats_count; s++)
4393           {
4394              seat = mem_alloc(SZ(Edje_Part_Allowed_Seat));
4395              if (ep2->allowed_seats[s]->name)
4396                {
4397                   seat->name = strdup(ep2->allowed_seats[s]->name);
4398                   if (!seat->name)
4399                     {
4400                        ERR("Not enough memory.");
4401                        exit(-1);
4402                     }
4403                }
4404              ep->allowed_seats[s] = seat;
4405           }
4406      }
4407 
4408    data_queue_copied_part_lookup(pc, &(ep2->dragable.confine_id), &(ep->dragable.confine_id));
4409    data_queue_copied_part_lookup(pc, &(ep2->dragable.threshold_id), &(ep->dragable.threshold_id));
4410    data_queue_copied_part_lookup(pc, &(ep2->dragable.event_id), &(ep->dragable.event_id));
4411 
4412    epp = (Edje_Part_Parser *)ep;
4413    epp2 = (Edje_Part_Parser *)ep2;
4414    epp->reorder.insert_before = STRDUP(epp2->reorder.insert_before);
4415    epp->reorder.insert_after = STRDUP(epp2->reorder.insert_after);
4416    epp->can_override = EINA_TRUE;
4417 
4418    for (j = 0; j < ep2->items_count; j++)
4419      {
4420         ob_collections_group_parts_part_box_items_item();
4421         item = ep->items[j];
4422         item2 = ep2->items[j];
4423         item->type = item2->type;
4424         item->name = STRDUP(item2->name);
4425         item->source = STRDUP(item2->source);
4426         item->min.w = item2->min.w;
4427         item->min.h = item2->min.h;
4428         item->prefer.w = item2->prefer.w;
4429         item->prefer.h = item2->prefer.h;
4430         item->max.w = item2->max.w;
4431         item->max.h = item2->max.h;
4432         item->padding.l = item2->padding.l;
4433         item->padding.r = item2->padding.r;
4434         item->padding.t = item2->padding.t;
4435         item->padding.b = item2->padding.b;
4436         item->align.x = item2->align.x;
4437         item->align.y = item2->align.y;
4438         item->weight.x = item2->weight.x;
4439         item->weight.y = item2->weight.y;
4440         item->aspect.w = item2->aspect.w;
4441         item->aspect.h = item2->aspect.h;
4442         item->aspect.mode = item2->aspect.mode;
4443         item->options = STRDUP(item2->options);
4444         item->col = item2->col;
4445         item->row = item2->row;
4446         item->colspan = item2->colspan;
4447         item->rowspan = item2->rowspan;
4448         item->spread.w = item2->spread.w;
4449         item->spread.h = item2->spread.h;
4450 
4451         pitem = (Edje_Pack_Element_Parser *)item;
4452         pitem->can_override = EINA_TRUE;
4453 
4454         _parts_count_update(item->type, 1);
4455      }
4456 
4457    ep->api.name = STRDUP(ep2->api.name);
4458    if (ep2->api.description) ep->api.description = STRDUP(ep2->api.description);
4459 
4460    // copy default description
4461    ob_collections_group_parts_part_description();
4462    ed = ep->default_desc;
4463    parent_desc = ed2 = ep2->default_desc;
4464    free((void *)ed->state.name);
4465    ed->state.name = STRDUP(ed2->state.name);
4466    ed->state.value = ed2->state.value;
4467    st_collections_group_parts_part_description_inherit();
4468    parent_desc = NULL;
4469 
4470    // copy other description
4471    for (j = 0; j < ep2->other.desc_count; j++)
4472      {
4473         ob_collections_group_parts_part_description();
4474         ed = ep->other.desc[j];
4475         parent_desc = ed2 = ep2->other.desc[j];
4476         ed->state.name = STRDUP(ed2->state.name);
4477         ed->state.value = ed2->state.value;
4478         st_collections_group_parts_part_description_inherit();
4479         parent_desc = NULL;
4480      }
4481 }
4482 
4483 /**
4484     @page edcref
4485     @property
4486         inherit_only
4487     @parameters
4488         [1 or 0]
4489     @effect
4490         This flags a group as being used only for inheriting, which
4491         will inhibit edje_cc resolving of programs and parts that may
4492         not exist in this group, but are located in the group which is inheriting
4493         this group.
4494 
4495         Defaults: 0
4496     @since 1.10
4497     @endproperty
4498  */
4499 static void
st_collections_group_inherit_only(void)4500 st_collections_group_inherit_only(void)
4501 {
4502    Edje_Part_Collection_Parser *pcp;
4503 
4504    check_arg_count(1);
4505 
4506    pcp = eina_list_data_get(eina_list_last(edje_collections));
4507    pcp->inherit_only = parse_bool(0);
4508 }
4509 
4510 /**
4511     @page edcref
4512     @property
4513         use_custom_seat_names
4514     @parameters
4515         [1 or 0]
4516     @effect
4517         This flags a group as designed to listen for multiseat signals
4518         following a custom naming instead of default Edje naming.
4519         Seats are named on Edje as "seat1", "seat2", etc, in an incremental
4520         way and never are changed.
4521 
4522         But on Evas, names may be set on different places
4523         (Evas, Ecore Evas backends, the application itself)
4524         and name changes are allowed.
4525         So custom names come from system at first, but can be overriden with
4526         evas_device_name_set().
4527         Also Evas seat names don't need to follow any pattern.
4528 
4529         It's useful for cases where there is control of the
4530         system, as seat names, or when the application
4531         sets the devices names to guarantee they'll match
4532         seat names on EDC.
4533 
4534         Defaults: 0
4535     @since 1.19
4536     @endproperty
4537  */
4538 static void
st_collections_group_use_custom_seat_names(void)4539 st_collections_group_use_custom_seat_names(void)
4540 {
4541    Edje_Part_Collection *pc;
4542 
4543    check_arg_count(1);
4544 
4545    pc = eina_list_data_get(eina_list_last(edje_collections));
4546    pc->use_custom_seat_names = parse_bool(0);
4547 }
4548 
4549 /**
4550     @page edcref
4551     @property
4552         part_remove
4553     @parameters
4554         [part name] (part name) (part name) ...
4555     @effect
4556         Removes the listed parts from an inherited group. Removing nonexistent
4557         parts is not allowed.
4558     @since 1.10
4559     @endproperty
4560  */
4561 static void
st_collections_group_part_remove(void)4562 st_collections_group_part_remove(void)
4563 {
4564    unsigned int n, argc, orig_count, part_type;
4565    Edje_Part_Collection *pc;
4566 
4567    check_min_arg_count(1);
4568 
4569    if (!current_group_inherit)
4570      {
4571         ERR("Cannot remove parts from non-inherited group '%s'", current_de->entry);
4572         exit(-1);
4573      }
4574 
4575    pc = eina_list_last_data_get(edje_collections);
4576    orig_count = pc->parts_count;
4577 
4578    for (n = 0, argc = get_arg_count(); n < argc; n++)
4579      {
4580         char *name;
4581         unsigned int j, cur_count = pc->parts_count;
4582 
4583         name = parse_str(n);
4584 
4585         for (j = 0; j < pc->parts_count; j++)
4586           {
4587              unsigned int i;
4588 
4589              if (strcmp(pc->parts[j]->name, name)) continue;
4590 
4591              part_type = pc->parts[j]->type;
4592              pc->parts[j] = _part_free(pc, pc->parts[j]);
4593              for (i = j; i < pc->parts_count - 1; i++)
4594                {
4595                   if (!pc->parts[i + 1]) break;
4596                   pc->parts[i] = pc->parts[i + 1];
4597                }
4598              pc->parts_count--;
4599              _parts_count_update(part_type, -1);
4600              break;
4601           }
4602         if (cur_count == pc->parts_count)
4603           {
4604              ERR("Attempted removal of nonexistent part '%s' in group '%s'.",
4605                  name, current_de->entry);
4606              exit(-1);
4607           }
4608         free(name);
4609      }
4610    if (orig_count == pc->parts_count) return;
4611    if (pc->parts_count)
4612      pc->parts = realloc(pc->parts, pc->parts_count * sizeof(Edje_Part *));
4613    else
4614      {
4615         free(pc->parts);
4616         pc->parts = NULL;
4617      }
4618 }
4619 
4620 /**
4621     @page edcref
4622     @property
4623         program_remove
4624     @parameters
4625         [program name] (program name) (program name) ...
4626     @effect
4627         Removes the listed programs from an inherited group. Removing nonexistent
4628         programs is not allowed.
4629         This will break program sequences if a program in the middle of the sequence is removed.
4630     @since 1.10
4631     @endproperty
4632  */
4633 static void
st_collections_group_program_remove(void)4634 st_collections_group_program_remove(void)
4635 {
4636    unsigned int n, argc;
4637    Edje_Part_Collection *pc;
4638 
4639    check_min_arg_count(1);
4640 
4641    if (!current_group_inherit)
4642      {
4643         ERR("Cannot remove programs from non-inherited group '%s'", current_de->entry);
4644         exit(-1);
4645      }
4646 
4647    pc = eina_list_last_data_get(edje_collections);
4648 
4649    for (n = 0, argc = get_arg_count(); n < argc; n++)
4650      {
4651         char *name;
4652         Eina_Bool success = EINA_FALSE;
4653 
4654         name = parse_str(n);
4655 
4656         success |= _program_remove(name, pc->programs.fnmatch, pc->programs.fnmatch_count);
4657         success |= _program_remove(name, pc->programs.strcmp, pc->programs.strcmp_count);
4658         success |= _program_remove(name, pc->programs.strncmp, pc->programs.strncmp_count);
4659         success |= _program_remove(name, pc->programs.strrncmp, pc->programs.strrncmp_count);
4660         success |= _program_remove(name, pc->programs.nocmp, pc->programs.nocmp_count);
4661 
4662         if (anonymous_delete)
4663           {
4664              copied_program_anonymous_lookup_delete(pc, anonymous_delete);
4665              anonymous_delete = NULL;
4666           }
4667         if (!success)
4668           {
4669              ERR("Attempted removal of nonexistent program '%s' in group '%s'.",
4670                  name, current_de->entry);
4671              exit(-1);
4672           }
4673         free(name);
4674      }
4675 }
4676 
4677 /**
4678     @page edcref
4679     @property
4680         target_group
4681     @parameters
4682         [name] [part or program] (part or program) (part or program) ...
4683     @effect
4684         This creates a group of parts/programs which can then be referenced
4685         by a single 'groups' or 'target_groups' statement inside a program.
4686         The resulting program will have all of the parts/programs within the specified
4687         group added as targets.
4688     @since 1.10
4689     @endproperty
4690  */
4691 static void
st_collections_group_target_group(void)4692 st_collections_group_target_group(void)
4693 {
4694    int n, argc;
4695    Edje_Part_Collection_Parser *pc;
4696    char *name;
4697    Eina_List *l;
4698    Edje_Target_Group *tg;
4699 
4700    check_min_arg_count(2);
4701 
4702    pc = eina_list_last_data_get(edje_collections);
4703    name = parse_str(0);
4704    EINA_LIST_FOREACH(pc->target_groups, l, tg)
4705      if (!strcmp(tg->name, name))
4706        {
4707           ERR("parse error %s:%i. There is already a target_group with the name '%s'",
4708               file_in, line - 1, name);
4709           exit(-1);
4710        }
4711    tg = malloc(sizeof(Edje_Target_Group));
4712    pc->target_groups = eina_list_append(pc->target_groups, tg);
4713    tg->name = name;
4714    argc = get_arg_count();
4715    tg->targets = calloc(argc, sizeof(char *));
4716 
4717    for (n = 1; n < argc; n++)
4718      tg->targets[n - 1] = parse_str(n);
4719 }
4720 
4721 /**
4722     @page edcref
4723     @property
4724         inherit
4725     @parameters
4726         [parent group name]
4727     @effect
4728         Parent group name for inheritance.
4729         Group "inherit" is used to inherit any predefined group and change
4730         some property which belongs to "part", "description", "items" or "program".
4731         The child group has the same property as parent group. If you specify the
4732         type again in an inherited part, it will cause an error (unless you plan
4733         to fix that).
4734         @warning When inheriting any parts, descriptions without state names are NOT
4735         allowed.
4736     @since 1.10
4737     @endproperty
4738  */
4739 static void
st_collections_group_inherit(void)4740 st_collections_group_inherit(void)
4741 {
4742    Edje_Part_Collection_Directory_Entry *alias;
4743    Edje_Part_Collection *pc, *pc2 = NULL;
4744    Edje_Part_Collection_Parser *pcp, *pcp2;
4745    Edje_Part *ep, *ep2;
4746    Edje_List_Foreach_Data fdata;
4747    Eina_List *l;
4748    char *parent_name;
4749    unsigned int i, j, offset;
4750 
4751    check_arg_count(1);
4752 
4753    pc = eina_list_data_get(eina_list_last(edje_collections));
4754 
4755    parent_name = parse_str(0);
4756 
4757    EINA_LIST_FOREACH(aliases, l, alias)
4758      {
4759         if (alias->group_alias &&
4760             !strcmp(alias->entry, parent_name))
4761           {
4762              free(parent_name);
4763              pc2 = eina_list_nth(edje_collections, alias->id);
4764              parent_name = strdup(pc2->part);
4765              break;
4766           }
4767      }
4768 
4769    if (!pc2)
4770      {
4771         EINA_LIST_FOREACH(edje_collections, l, pc2)
4772           {
4773              if (!strcmp(parent_name, pc2->part))
4774                break;
4775           }
4776      }
4777 
4778    if (!pc2)
4779      {
4780         ERR("parse error %s:%i. There isn't a group with the name %s",
4781             file_in, line - 1, parent_name);
4782         exit(-1);
4783      }
4784 
4785    if (pc2 == pc)
4786      {
4787         ERR("parse error %s:%i. You are trying to inherit '%s' from itself. That's not possible."
4788             "If there is another group of the same name, you want to inherit from that group and have the"
4789             "same name as that group, there is a trick ! Just put the inherit before the directive that set"
4790             "the name !", file_in, line - 1, parent_name);
4791         exit(-1);
4792      }
4793    current_group_inherit = EINA_TRUE;
4794 
4795    if (pc2->data)
4796      {
4797         char *key, *data;
4798 
4799         memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
4800         eina_hash_foreach(pc2->data,
4801                           _edje_data_item_list_foreach, &fdata);
4802 
4803         if (!pc->data) pc->data = eina_hash_string_small_new(free);
4804         EINA_LIST_FREE(fdata.list, key)
4805           {
4806              data = eina_hash_find(pc2->data, key);
4807              eina_hash_direct_add(pc->data, key, data);
4808           }
4809      }
4810 
4811    if (pc2->alias)
4812      {
4813         char *key;
4814 
4815         memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
4816         eina_hash_foreach(pc2->alias,
4817                           _edje_data_item_list_foreach, &fdata);
4818         if (!pc->alias) pc->alias = eina_hash_string_small_new(free);
4819         EINA_LIST_FREE(fdata.list, key)
4820           {
4821              char *tmp;
4822              tmp = eina_hash_find(pc2->alias, key);
4823              eina_hash_direct_add(pc->alias, key, tmp);
4824           }
4825      }
4826    if (pc2->aliased)
4827      {
4828         char *key, *aliased;
4829 
4830         memset(&fdata, 0, sizeof(Edje_List_Foreach_Data));
4831         eina_hash_foreach(pc2->aliased,
4832                           _edje_data_item_list_foreach, &fdata);
4833         if (!pc->aliased) pc->aliased = eina_hash_string_small_new(free);
4834         EINA_LIST_FREE(fdata.list, key)
4835           {
4836              aliased = eina_hash_find(pc2->aliased, key);
4837              eina_hash_direct_add(pc->aliased, key, aliased);
4838           }
4839      }
4840 
4841 #ifdef HAVE_EPHYSICS
4842    pc->physics.world.gravity.x = pc2->physics.world.gravity.x;
4843    pc->physics.world.gravity.y = pc2->physics.world.gravity.y;
4844    pc->physics.world.gravity.z = pc2->physics.world.gravity.z;
4845    pc->physics.world.depth = pc2->physics.world.depth;
4846    pc->physics.world.z = pc2->physics.world.z;
4847    pc->physics.world.rate = pc2->physics.world.rate;
4848 #endif
4849 
4850    pc->prop.min.w = pc2->prop.min.w;
4851    pc->prop.min.h = pc2->prop.min.h;
4852    pc->prop.orientation = pc2->prop.orientation;
4853 
4854    pc->lua_script_only = pc2->lua_script_only;
4855    pc->use_custom_seat_names = pc2->use_custom_seat_names;
4856 
4857    pcp = (Edje_Part_Collection_Parser *)pc;
4858    pcp2 = (Edje_Part_Collection_Parser *)pc2;
4859    pcp->default_mouse_events = pcp2->default_mouse_events;
4860    pcp->skip_namespace_validation = pcp2->skip_namespace_validation;
4861    if (pcp2->inherit_script)
4862      pcp->inherit_script = pcp2->inherit_script;
4863 
4864    /* as of 7 April 2014, target groups cannot be modified and are not freed.
4865     * this code will break if that ever changes.
4866     *
4867     * BORKER CERTIFICATION: BRONZE
4868     */
4869    if (pcp2->target_groups)
4870      pcp->target_groups = eina_list_clone(pcp2->target_groups);
4871 
4872    if (pcp2->default_source)
4873      {
4874         free(pcp->default_source);
4875         pcp->default_source = strdup(pcp2->default_source);
4876      }
4877 
4878    if (pc2->limits.vertical_count || pc2->limits.horizontal_count)
4879      {
4880         Edje_Limit **elp;
4881 
4882         if (pc2->limits.vertical_count)
4883           {
4884              elp = realloc(pc->limits.vertical,
4885                            pc->limits.vertical_count + pc2->limits.vertical_count * sizeof(Edje_Limit *));
4886              if (!elp)
4887                {
4888                   ERR("Not enough memory.");
4889                   exit(-1);
4890                }
4891              pc->limits.vertical = elp;
4892              offset = pc->limits.vertical_count;
4893              for (i = 0; i < pc2->limits.vertical_count; i++)
4894                {
4895                   Edje_Limit *el;
4896 
4897                   el = mem_alloc(SZ(Edje_Limit));
4898                   if (!el)
4899                     {
4900                        ERR("Not enough memory.");
4901                        exit(-1);
4902                     }
4903 
4904                   pc->limits.vertical[i + offset] = el;
4905 
4906                   el->name = STRDUP(pc2->limits.vertical[i]->name);
4907                   el->value = pc2->limits.vertical[i]->value;
4908                   pc->limits.vertical_count++;
4909                }
4910           }
4911 
4912         if (pc2->limits.horizontal_count)
4913           {
4914              elp = realloc(pc->limits.horizontal,
4915                            pc->limits.horizontal_count + pc2->limits.horizontal_count * sizeof(Edje_Limit *));
4916              if (!elp)
4917                {
4918                   ERR("Not enough memory.");
4919                   exit(-1);
4920                }
4921              pc->limits.horizontal = elp;
4922              offset = pc->limits.horizontal_count;
4923              for (i = 0; i < pc2->limits.horizontal_count; i++)
4924                {
4925                   Edje_Limit *el;
4926 
4927                   el = mem_alloc(SZ(Edje_Limit));
4928                   if (!el)
4929                     {
4930                        ERR("Not enough memory.");
4931                        exit(-1);
4932                     }
4933 
4934                   pc->limits.horizontal[i + offset] = el;
4935 
4936                   el->name = STRDUP(pc2->limits.horizontal[i]->name);
4937                   el->value = pc2->limits.horizontal[i]->value;
4938                   pc->limits.horizontal_count++;
4939                }
4940           }
4941      }
4942 
4943    offset = pc->parts_count;
4944    for (i = 0; i < pc2->parts_count; i++)
4945      {
4946         // copy the part
4947         edje_cc_handlers_part_make(-1);
4948         ep = pc->parts[i + offset];
4949         ep2 = pc2->parts[i];
4950         _part_copy(ep, ep2);
4951      }
4952 
4953    //copy programs
4954    for (j = 0; j < pc2->programs.fnmatch_count; j++)
4955      {
4956         ob_collections_group_programs_program();
4957         _edje_program_copy(current_program, pc2->programs.fnmatch[j]);
4958      }
4959    for (j = 0; j < pc2->programs.strcmp_count; j++)
4960      {
4961         ob_collections_group_programs_program();
4962         _edje_program_copy(current_program, pc2->programs.strcmp[j]);
4963      }
4964    for (j = 0; j < pc2->programs.strncmp_count; j++)
4965      {
4966         ob_collections_group_programs_program();
4967         _edje_program_copy(current_program, pc2->programs.strncmp[j]);
4968      }
4969    for (j = 0; j < pc2->programs.strrncmp_count; j++)
4970      {
4971         ob_collections_group_programs_program();
4972         _edje_program_copy(current_program, pc2->programs.strrncmp[j]);
4973      }
4974    for (j = 0; j < pc2->programs.nocmp_count; j++)
4975      {
4976         ob_collections_group_programs_program();
4977         _edje_program_copy(current_program, pc2->programs.nocmp[j]);
4978      }
4979 
4980    Code *cd, *cd2;
4981    Code_Program *cp, *cp2;
4982    Edje_Part_Collection_Directory_Entry *de;
4983 
4984    de = eina_hash_find(edje_file->collection, pc2->part);
4985    cd2 = eina_list_nth(codes, de->id);
4986    cd = eina_list_data_get(eina_list_last(codes));
4987 
4988    cd->is_lua = cd2->is_lua;
4989    if (!cd2->is_lua)
4990      pcp->base_codes = eina_list_append(pcp->base_codes, cd2);
4991 
4992    if (cd2->shared)
4993      {
4994         if (cd->shared)
4995           {
4996              WRN("%s:%i. script block in group \"%s\" will be overwritten by inheriting "
4997                  "from group \"%s\".", file_in, line - 1, pc->part, pc2->part);
4998              free(cd->shared);
4999           }
5000         if (cd->original)
5001           free(cd->original);
5002 
5003         cd->shared = STRDUP(cd2->shared);
5004         cd->original = STRDUP(cd2->original);
5005 
5006         script_is_replaceable = EINA_TRUE;
5007      }
5008 
5009    EINA_LIST_FOREACH(cd2->programs, l, cp2)
5010      {
5011         cp = mem_alloc(SZ(Code_Program));
5012 
5013         cp->l1 = cp2->l1;
5014         cp->l2 = cp2->l2;
5015         cp->script = STRDUP(cp2->script);
5016         cp->original = STRDUP(cp2->original);
5017         cd->programs = eina_list_append(cd->programs, cp);
5018         data_queue_copied_anonymous_lookup(pc, &(cp2->id), &(cp->id));
5019      }
5020 
5021    free(parent_name);
5022 }
5023 
5024 /**
5025     @page edcref
5026     @property
5027         lua_script_only
5028     @parameters
5029         [on/off]
5030     @effect
5031         The flag (on/off) as to if this group is defined ONLY by script
5032         callbacks such as init(), resize() and shutdown()
5033 
5034         Defaults: off
5035     @endproperty
5036  */
5037 static void
st_collections_group_lua_script_only(void)5038 st_collections_group_lua_script_only(void)
5039 {
5040    Edje_Part_Collection *pc;
5041 
5042    check_arg_count(1);
5043 
5044    pc = eina_list_data_get(eina_list_last(edje_collections));
5045    pc->lua_script_only = parse_bool(0);
5046 }
5047 
5048 /**
5049     @page edcref
5050     @property
5051         script_recursion
5052     @parameters
5053         [1/0]
5054     @effect
5055         This flag (1/0) determines whether to error on unsafe calls when
5056         recursively running Embryo programs.
5057         For example, running an Embryo script which calls EDC which has a
5058         script{} block is unsafe, and the outer-most (first) Embryo stack is GUARANTEED
5059         to be corrupted. Only use this flag if you are sure that you know what you are doing.
5060 
5061         Defaults: 0
5062     @since 1.10
5063     @endproperty
5064  */
5065 static void
st_collections_group_script_recursion(void)5066 st_collections_group_script_recursion(void)
5067 {
5068    Edje_Part_Collection *pc;
5069 
5070    check_arg_count(1);
5071 
5072    pc = eina_list_data_get(eina_list_last(edje_collections));
5073    pc->script_recursion = parse_bool(0);
5074 }
5075 
5076 /**
5077     @page edcref
5078     @property
5079         alias
5080     @parameters
5081         [aditional group name]
5082     @effect
5083         Additional name to serve as identifier. Defining multiple aliases is
5084         supported.
5085     @endproperty
5086  */
5087 static void
st_collections_group_alias(void)5088 st_collections_group_alias(void)
5089 {
5090    Edje_Part_Collection_Directory_Entry *alias;
5091    Edje_Part_Collection_Directory_Entry *tmp;
5092    Eina_List *l;
5093 
5094    check_arg_count(1);
5095 
5096    alias = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
5097    alias->id = current_de->id;
5098    alias->entry = parse_str(0);
5099    alias->group_alias = EINA_TRUE;
5100 
5101    EINA_LIST_FOREACH(aliases, l, tmp)
5102      if (strcmp(alias->entry, tmp->entry) == 0)
5103        {
5104           Edje_Part_Collection *pc;
5105 
5106           pc = eina_list_nth(edje_collections, tmp->id);
5107           INF("overriding alias ('%s' => '%s') to ('%s' => '%s')",
5108               tmp->entry, pc->part,
5109               alias->entry, current_de->entry);
5110           aliases = eina_list_remove_list(aliases, l);
5111           free(tmp);
5112           break;
5113        }
5114 
5115    aliases = eina_list_append(aliases, alias);
5116 }
5117 
5118 /**
5119     @page edcref
5120     @property
5121         min
5122     @parameters
5123         [width] [height]
5124     @effect
5125         The minimum size for the container defined by the composition of the
5126         parts. It is not enforced.
5127 
5128         Defaults: 0 0
5129     @endproperty
5130  */
5131 static void
st_collections_group_min(void)5132 st_collections_group_min(void)
5133 {
5134    Edje_Part_Collection *pc;
5135 
5136    check_arg_count(2);
5137 
5138    pc = eina_list_data_get(eina_list_last(edje_collections));
5139    pc->prop.min.w = parse_int_range(0, 0, 0x7fffffff);
5140    pc->prop.min.h = parse_int_range(1, 0, 0x7fffffff);
5141 }
5142 
5143 /**
5144     @page edcref
5145     @property
5146         max
5147     @parameters
5148         [width] [height]
5149     @effect
5150         The maximum size for the container defined by the totality of the
5151         parts. It is not enforced.
5152 
5153         Defaults: 0 0
5154     @endproperty
5155  */
5156 static void
st_collections_group_max(void)5157 st_collections_group_max(void)
5158 {
5159    Edje_Part_Collection *pc;
5160 
5161    check_arg_count(2);
5162 
5163    pc = eina_list_data_get(eina_list_last(edje_collections));
5164    pc->prop.max.w = parse_int_range(0, 0, 0x7fffffff);
5165    pc->prop.max.h = parse_int_range(1, 0, 0x7fffffff);
5166 }
5167 
5168 /**
5169    @page edcref
5170    @property
5171        broadcast_signal
5172    @parameters
5173        [on/off]
5174    @effect
5175        Signal got automatically broadcasted to all sub group part.
5176 
5177        Defaults: true
5178    @since 1.1
5179    @endproperty
5180  */
5181 static void
st_collections_group_broadcast_signal(void)5182 st_collections_group_broadcast_signal(void)
5183 {
5184    Edje_Part_Collection *pc;
5185 
5186    check_arg_count(1);
5187 
5188    pc = eina_list_data_get(eina_list_last(edje_collections));
5189    pc->broadcast_signal = parse_bool(0);
5190 }
5191 
5192 static void
st_collections_group_broadcast(void)5193 st_collections_group_broadcast(void)
5194 {
5195    Edje_Part_Collection *pc;
5196 
5197    check_arg_count(0);
5198 
5199    pc = eina_list_data_get(eina_list_last(edje_collections));
5200    pc->broadcast_signal = 1;
5201 }
5202 
5203 static void
st_collections_group_nobroadcast(void)5204 st_collections_group_nobroadcast(void)
5205 {
5206    Edje_Part_Collection *pc;
5207 
5208    check_arg_count(0);
5209 
5210    pc = eina_list_data_get(eina_list_last(edje_collections));
5211    pc->broadcast_signal = 0;
5212 }
5213 
5214 /**
5215     @page edcref
5216     @property
5217         orientation
5218     @parameters
5219         [AUTO/LTR/RTL]
5220     @effect
5221         This defines GROUP orientation.
5222         This is useful if you want match interface orientation with language.
5223         @li AUTO  - Follow system defs.
5224         @li LTR  - suitable for Left To Right Languages (latin)
5225         @li RTL - suitable for Right To Left Languages (Hebrew, Arabic interface)
5226 
5227         Defaults: AUTO
5228     @endproperty
5229  */
5230 static void
st_collections_group_orientation(void)5231 st_collections_group_orientation(void)
5232 {
5233    Edje_Part_Collection *pc;
5234 
5235    check_arg_count(1);
5236 
5237    pc = eina_list_data_get(eina_list_last(edje_collections));
5238    pc->prop.orientation = parse_enum(0,
5239                                      "AUTO", EDJE_ORIENTATION_AUTO,
5240                                      "LTR", EDJE_ORIENTATION_LTR,
5241                                      "RTL", EDJE_ORIENTATION_RTL,
5242                                      NULL);
5243 }
5244 
5245 /**
5246     @page edcref
5247     @property
5248         mouse_events
5249     @parameters
5250         [1 or 0]
5251     @effect
5252         Change the default value of mouse_events for every part in this group.
5253 
5254         Defaults: 1 (to maintain compatibility)
5255     @endproperty
5256  */
5257 static void
st_collections_group_mouse_events(void)5258 st_collections_group_mouse_events(void)
5259 {
5260    Edje_Part_Collection_Parser *pcp;
5261 
5262    check_arg_count(1);
5263 
5264    pcp = eina_list_data_get(eina_list_last(edje_collections));
5265    pcp->default_mouse_events = parse_bool(0);
5266 }
5267 
5268 static void
st_collections_group_mouse(void)5269 st_collections_group_mouse(void)
5270 {
5271    Edje_Part_Collection_Parser *pcp;
5272 
5273    check_arg_count(0);
5274 
5275    pcp = eina_list_data_get(eina_list_last(edje_collections));
5276    pcp->default_mouse_events = 1;
5277 }
5278 
5279 static void
st_collections_group_nomouse(void)5280 st_collections_group_nomouse(void)
5281 {
5282    Edje_Part_Collection_Parser *pcp;
5283 
5284    check_arg_count(0);
5285 
5286    pcp = eina_list_data_get(eina_list_last(edje_collections));
5287    pcp->default_mouse_events = 0;
5288 }
5289 
5290 /**
5291     @page edcref
5292     @property
5293         inherit_script
5294     @parameters
5295         [1 or 0]
5296     @effect
5297         Determine whether to inherit script block from parent group.
5298         If it is set to 0, script from parent group will be replaced with
5299         new script block.
5300         Defaults to 0 if not set, to maintain compatibility.
5301     @endproperty
5302  */
5303 static void
st_collections_group_inherit_script(void)5304 st_collections_group_inherit_script(void)
5305 {
5306    Edje_Part_Collection_Parser *pcp;
5307 
5308    pcp = eina_list_last_data_get(edje_collections);
5309 
5310    if (get_arg_count() == 1)
5311      pcp->inherit_script = parse_bool(0);
5312    else
5313      pcp->inherit_script = EINA_TRUE;
5314 }
5315 
5316 static void
st_collections_group_noinherit_script(void)5317 st_collections_group_noinherit_script(void)
5318 {
5319    Edje_Part_Collection_Parser *pcp;
5320 
5321    check_arg_count(0);
5322 
5323    pcp = eina_list_last_data_get(edje_collections);
5324    pcp->inherit_script = EINA_FALSE;
5325 }
5326 
5327 static void
_script_flush(void)5328 _script_flush(void)
5329 {
5330    Edje_Part_Collection_Parser *pcp;
5331    Code *code;
5332 
5333    pcp = eina_list_last_data_get(edje_collections);
5334    code = eina_list_last_data_get(codes);
5335 
5336    if (!pcp->inherit_script || code->is_lua) return;
5337 
5338    // If script is replaceable and overridable, code->shared will be inherited
5339    // script. Free it to avoid duplication.
5340    if (script_is_replaceable)
5341      {
5342         if (code->shared)
5343           {
5344              free(code->shared);
5345              code->shared = NULL;
5346           }
5347         if (code->original)
5348           {
5349              free(code->original);
5350              code->original = NULL;
5351           }
5352      }
5353 
5354    script_rewrite(code);
5355 
5356    eina_list_free(pcp->base_codes);
5357 }
5358 
5359 /**
5360     @page edcref
5361     @property
5362         program_source
5363     @parameters
5364         [source name]
5365     @effect
5366         Change the default value of source for every program in the current group
5367         which is declared after this value is set.
5368 
5369         Defaults: an unset value (to maintain compatibility)
5370     @since 1.10
5371     @endproperty
5372  */
5373 static void
st_collections_group_program_source(void)5374 st_collections_group_program_source(void)
5375 {
5376    Edje_Part_Collection_Parser *pcp;
5377 
5378    check_arg_count(1);
5379 
5380    pcp = eina_list_last_data_get(edje_collections);
5381    free(pcp->default_source);
5382    pcp->default_source = parse_str(0);
5383 }
5384 
5385 /** @edcsubsection{collections_group_script,
5386  *                 Group.Script} */
5387 
5388 /**
5389     @page edcref
5390     @block
5391         script
5392     @context
5393         ..
5394         group {
5395             script {
5396                 //embryo script
5397             }
5398             ..
5399             program {
5400                 script {
5401                     //embryo script
5402                 }
5403             }
5404             ..
5405         }
5406         ..
5407     @description
5408         This block is used to "inject" embryo scripts to a given Edje theme and
5409         it functions in two modalities. When it's included inside a "program"
5410         block, the script will be executed every time the program is run, on
5411         the other hand, when included directly into a "group", "part" or
5412         "description" block, it will be executed once at load time, in the
5413         load order.
5414     @endblock
5415  */
5416 static void
ob_collections_group_script(void)5417 ob_collections_group_script(void)
5418 {
5419    Code *cd;
5420 
5421    cd = eina_list_data_get(eina_list_last(codes));
5422 
5423    if (!is_verbatim()) track_verbatim(1);
5424    else
5425      {
5426         char *s;
5427 
5428         s = get_verbatim();
5429         if (s)
5430           {
5431              cd->l1 = get_verbatim_line1();
5432              cd->l2 = get_verbatim_line2();
5433              if (cd->shared)
5434                {
5435                   if (script_is_replaceable)
5436                     {
5437                        free(cd->shared);
5438                        free(cd->original);
5439                        script_is_replaceable = EINA_FALSE;
5440                     }
5441                   else
5442                     {
5443                        ERR("parse error %s:%i. There is already an existing script section for the group",
5444                            file_in, line - 1);
5445                        exit(-1);
5446                     }
5447                }
5448              cd->shared = s;
5449              cd->original = strdup(s);
5450              cd->is_lua = 0;
5451              set_verbatim(NULL, 0, 0);
5452           }
5453      }
5454 }
5455 
5456 static void
ob_collections_group_lua_script(void)5457 ob_collections_group_lua_script(void)
5458 {
5459    Code *cd;
5460 
5461    cd = eina_list_data_get(eina_list_last(codes));
5462 
5463    if (!is_verbatim()) track_verbatim(1);
5464    else
5465      {
5466         char *s;
5467 
5468         s = get_verbatim();
5469         if (s)
5470           {
5471              cd->l1 = get_verbatim_line1();
5472              cd->l2 = get_verbatim_line2();
5473              if (cd->shared)
5474                {
5475                   ERR("parse error %s:%i. There is already an existing script section for the group",
5476                       file_in, line - 1);
5477                   exit(-1);
5478                }
5479              cd->shared = s;
5480              cd->is_lua = 1;
5481              set_verbatim(NULL, 0, 0);
5482           }
5483      }
5484 }
5485 
5486 /** @edcsubsection{collections_group_data,
5487  *                 Group.Data} */
5488 
5489 /**
5490     @page edcref
5491     @block
5492         data
5493     @context
5494         data {
5495             item: "key" "value";
5496             ..
5497         }
5498     @description
5499         The "data" block is used to pass arbitrary parameters from the theme to
5500         the application. Unlike the toplevel data block, this block Group.Data
5501         can only store inline items (not files).
5502         See also the toplevel @ref sec_toplevel_data "Data" section.
5503     @endblock
5504 
5505     @property
5506         item
5507     @parameters
5508         [parameter name] [parameter value]
5509     @effect
5510         Defines a new parameter, the value will be the string specified next to
5511         it.
5512     @endproperty
5513  */
5514 
5515 static void
st_collections_group_data_item(void)5516 st_collections_group_data_item(void)
5517 {
5518    Edje_Part_Collection *pc;
5519    Edje_String *es;
5520    char *key;
5521 
5522    check_arg_count(2);
5523 
5524    pc = eina_list_data_get(eina_list_last(edje_collections));
5525 
5526    if (!pc->data)
5527      pc->data = eina_hash_string_small_new(free);
5528 
5529    key = parse_str(0);
5530 
5531    es = mem_alloc(SZ(Edje_String));
5532    es->str = parse_str(1);
5533 
5534    if (eina_hash_find(pc->data, key))
5535      eina_hash_modify(pc->data, key, es);
5536    else
5537      eina_hash_direct_add(pc->data, key, es);
5538 }
5539 
5540 /** @edcsubsection{collections_group_filters,
5541  *                 Group.Filters} */
5542 
5543 /**
5544     @page edcref
5545     @block
5546         filters
5547     @context
5548         // (toplevel)
5549         // collections
5550         // collections.group
5551         filters {
5552             // Inline as script block:
5553             filter {
5554                name: "myfilter1";
5555                script {
5556                   -- Some Lua code here, eg:
5557                   blend { color = 'red' }
5558                }
5559             // Imported from an external file:
5560             filter {
5561                name: "myfilter2";
5562                file: "filename.lua";
5563             }
5564         }
5565     @description
5566         The "filter" block lets you embed filter scripts into an EDC group,
5567         that can then be referred to in the
5568         @ref sec_collections_group_parts_description_filter "Text.Filter"
5569         or @ref sec_collections_group_parts_description_filter "Image.Filter"
5570         statements.
5571 
5572         In a similar way to the toplevel @ref sec_toplevel_data "Data" section,
5573         it is possible to embed filters from a external file inside the final EDJ.
5574 
5575         Note that filters are defined globally, even if they appear inside a
5576         specific group (as of EFL 1.19).
5577 
5578         Please also refer to @ref evasfiltersref "Evas filters reference".
5579     @endblock
5580 
5581     @property
5582         name
5583     @parameters
5584         [name]
5585     @effect
5586         Creates a new named filter. This filter can then be used in image, text
5587         or textblock parts by name.
5588     @endproperty
5589 
5590     @property
5591         script
5592     @parameters
5593         [Lua script]
5594     @effect
5595         A block of Lua code contained inside {}. Example: script { blur{5} }
5596     @endproperty
5597 
5598     @property
5599         file
5600     @parameters
5601         [Path to Lua file]
5602     @effect
5603         Includes an external file to define a new Lua script used for filtering.
5604         The file must be in the data path passed to edje_cc (-dd argument).
5605     @endproperty
5606  */
5607 
5608 static Edje_Gfx_Filter *current_filter = NULL;
5609 
5610 static void
_filters_filter_sort(void)5611 _filters_filter_sort(void)
5612 {
5613    Edje_Gfx_Filter *array, current;
5614    int new_pos, i, cur_pos;
5615 
5616    if (!current_filter)
5617      return;
5618 
5619    if (!current_filter->name)
5620      {
5621         ERR("parse error %s:%i. Filter has no name.",
5622             file_in, line - 1);
5623         exit(-1);
5624      }
5625 
5626    array = edje_file->filter_dir->filters;
5627    cur_pos = (current_filter - array);
5628 
5629    // find position in sorted array
5630    for (new_pos = 0; new_pos < edje_file->filter_dir->filters_count - 1; new_pos++)
5631      {
5632         int cmp;
5633         if (cur_pos == new_pos)
5634           continue;
5635         cmp = strcmp(current_filter->name, array[new_pos].name);
5636         if (cmp == 0)
5637           {
5638              ERR("parse error %s:%i. Another filter named '%s' already exists.",
5639                  file_in, line - 1, array[new_pos].name);
5640              exit(-1);
5641           }
5642         else if (cmp < 0)
5643           break;
5644      }
5645 
5646    if (new_pos > cur_pos)
5647      new_pos--;
5648 
5649    if (cur_pos == new_pos)
5650      return;
5651 
5652    current = *current_filter;
5653 
5654    // move up
5655    for (i = cur_pos - 1; i >= new_pos; i--)
5656      array[i + 1] = array[i];
5657 
5658    // move down
5659    for (i = cur_pos; i < new_pos; i++)
5660      array[i] = array[i + 1];
5661 
5662    array[new_pos] = current;
5663    current_filter = &array[new_pos];
5664 }
5665 
5666 static void
ob_filters_filter(void)5667 ob_filters_filter(void)
5668 {
5669    Edje_Gfx_Filter *array;
5670 
5671    _filters_filter_sort();
5672    if (!edje_file->filter_dir)
5673      edje_file->filter_dir = mem_alloc(sizeof(Edje_Gfx_Filter_Directory));
5674 
5675    array = realloc(edje_file->filter_dir->filters,
5676                    sizeof(Edje_Gfx_Filter) * (edje_file->filter_dir->filters_count + 1));
5677    if (!array)
5678      {
5679         ERR("Memory allocation failed (array grow)");
5680         exit(-1);
5681      }
5682 
5683    current_filter = &array[edje_file->filter_dir->filters_count];
5684    memset(current_filter, 0, sizeof(Edje_Gfx_Filter));
5685    edje_file->filter_dir->filters_count++;
5686    edje_file->filter_dir->filters = array;
5687 }
5688 
5689 static void
ob_filters_filter_script(void)5690 ob_filters_filter_script(void)
5691 {
5692    char *script;
5693 
5694    if (!current_filter)
5695      ob_filters_filter();
5696 
5697    if (!current_filter->name)
5698      {
5699         ERR("parse error %s:%i. Name for inline filter must be specified first.",
5700             file_in, line - 1);
5701         exit(-1);
5702      }
5703 
5704    if (current_filter->script)
5705      {
5706         ERR("parse error %s:%i. Script for filter '%s' is already defined.",
5707             file_in, line - 1, current_filter->name);
5708         exit(-1);
5709      }
5710 
5711    if (!is_verbatim())
5712      track_verbatim(1);
5713    else
5714      {
5715         script = get_verbatim();
5716         if (script)
5717           {
5718              //current_filter->verb_l1 = get_verbatim_line1();
5719              //current_filter->verb_l2 = get_verbatim_line2();
5720              current_filter->script = strdup(script);
5721              set_verbatim(NULL, 0, 0);
5722              _filters_filter_sort();
5723              current_filter = NULL;
5724           }
5725      }
5726 }
5727 
5728 static void
st_filters_filter_file(void)5729 st_filters_filter_file(void)
5730 {
5731    char *file, *script;
5732    Eina_File *f;
5733    size_t sz;
5734 
5735    if (!current_filter)
5736      ob_filters_filter();
5737 
5738    if (current_filter->script)
5739      {
5740         ERR("parse error %s:%i. Script for filter '%s' is already defined.",
5741             file_in, line - 1, current_filter->name);
5742         exit(-1);
5743      }
5744 
5745    check_arg_count(1);
5746 
5747    file = parse_str(0);
5748    f = eina_file_open(file, EINA_FALSE);
5749    if (!f)
5750      {
5751         char path[PATH_MAX], *dir;
5752         Eina_List *l;
5753         // TODO: Introduce special filters_dir? needs new edje_cc argument :(
5754         EINA_LIST_FOREACH(data_dirs, l, dir)
5755           {
5756              snprintf(path, sizeof(path), "%s/%s", dir, file);
5757              f = eina_file_open(path, EINA_FALSE);
5758              if (f) break;
5759           }
5760         if (!f)
5761           {
5762              ERR("parse error %s:%i. Could not open filter script file '%s'",
5763                  file_in, line - 1, file);
5764              exit(-1);
5765           }
5766      }
5767 
5768    script = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
5769    if (!script)
5770      {
5771         ERR("parse error %s:%i. Could not read filter script file %s",
5772             file_in, line - 1, file);
5773         exit(-1);
5774      }
5775 
5776    sz = eina_file_size_get(f);
5777    if (sz > (10 * 1024 * 1024))
5778      {
5779         ERR("parse error %s:%i. Filter file '%s' is unreasonably large, abort.",
5780             file_in, line - 1, file);
5781         exit(-1);
5782      }
5783 
5784    current_filter->script = (char *)eina_memdup((unsigned char *)script, sz, 1);
5785    eina_file_map_free(f, script);
5786    eina_file_close(f);
5787 
5788    if (!current_filter->name)
5789      {
5790         current_filter->name = file;
5791         _filters_filter_sort();
5792      }
5793    else
5794      {
5795         free(file);
5796         _filters_filter_sort();
5797         current_filter = NULL;
5798      }
5799 }
5800 
5801 static void
st_filters_filter_name(void)5802 st_filters_filter_name(void)
5803 {
5804    if (!current_filter)
5805      ob_filters_filter();
5806 
5807    check_arg_count(1);
5808 
5809    current_filter->name = parse_str(0);
5810 
5811    _filters_filter_sort();
5812 }
5813 
5814 /** @edcsubsection{collections_group_limits,
5815  *                 Group.Limits} */
5816 
5817 /**
5818     @page edcref
5819     @block
5820         limits
5821     @context
5822         group {
5823             limits {
5824                 vertical: "limit_name" height_barrier;
5825                 horizontal: "limit_name" width_barrier;
5826                 ..
5827             }
5828             ..
5829         }
5830         ..
5831     @description
5832         This block is used to trigger some signal when the Edje object is resized.
5833     @endblock
5834 
5835     @page edcref
5836     @property
5837         vertical
5838     @parameters
5839         [name] [height barrier]
5840     @effect
5841         It will send a signal: "limit,name,over" when the object is resized and pass
5842         the limit by growing over it. And it will send: "limit,name,below" when
5843         it pass below that limit.
5844         This limit will be applied on the y absis and is expressed in pixels.
5845     @endproperty
5846  */
5847 static void
st_collections_group_limits_vertical(void)5848 st_collections_group_limits_vertical(void)
5849 {
5850    Edje_Part_Collection *pc;
5851    Edje_Limit *el, **elp;
5852 
5853    check_arg_count(2);
5854 
5855    pc = eina_list_data_get(eina_list_last(edje_collections));
5856    pc->limits.vertical_count++;
5857    elp = realloc(pc->limits.vertical,
5858                  pc->limits.vertical_count * sizeof (Edje_Limit *));
5859    if (!elp)
5860      {
5861         ERR("Not enough memory.");
5862         exit(-1);
5863      }
5864    pc->limits.vertical = elp;
5865 
5866    el = mem_alloc(SZ(Edje_Limit));
5867    if (!el)
5868      {
5869         ERR("Not enough memory.");
5870         exit(-1);
5871      }
5872 
5873    pc->limits.vertical[pc->limits.vertical_count - 1] = el;
5874 
5875    el->name = parse_str(0);
5876    el->value = parse_int_range(1, 1, 0xffff);
5877 }
5878 
5879 /**
5880     @page edcref
5881     @property
5882         horizontal
5883     @parameters
5884         [name] [width barrier]
5885     @effect
5886         It will send a signal: "limit,name,over" when the object is resized and pass
5887         the limit by growing over it. And it will send: "limit,name,below" when
5888         it pass below that limit.
5889         This limit will be applied on the x axis and is expressed in pixels.
5890     @endproperty
5891  */
5892 static void
st_collections_group_limits_horizontal(void)5893 st_collections_group_limits_horizontal(void)
5894 {
5895    Edje_Part_Collection *pc;
5896    Edje_Limit *el;
5897 
5898    check_arg_count(2);
5899 
5900    el = mem_alloc(SZ(Edje_Limit));
5901 
5902    pc = eina_list_data_get(eina_list_last(edje_collections));
5903    pc->limits.horizontal_count++;
5904    pc->limits.horizontal = realloc(pc->limits.horizontal, pc->limits.horizontal_count * sizeof (Edje_Limit *));
5905    if (!pc->limits.horizontal || !el)
5906      {
5907         ERR("Not enough memory.");
5908         exit(-1);
5909      }
5910 
5911    pc->limits.horizontal[pc->limits.horizontal_count - 1] = el;
5912 
5913    el->name = parse_str(0);
5914    el->value = parse_int_range(1, 1, 0xffff);
5915 }
5916 
5917 /** @edcsubsection{collections_group_parts,
5918  *                 Group.Parts} */
5919 
5920 /**
5921     @page edcref
5922     @block
5923         parts
5924     @context
5925         group {
5926             parts {
5927                 alias: "theme_part_path" "somegroup:real_part_path";
5928                 part { "theme_part_path"; }
5929                 part {  }
5930                 ..
5931             }
5932         }
5933     @description
5934         The parts block is the container for all the parts in the group.
5935 
5936     @property
5937         alias
5938     @parameters
5939         [alias name] [other_group:part name]
5940     @effect
5941         Allows for a part to be referenced externally as though
5942         it had the name of the alias.
5943         In the above example, swallowing an object into part "theme_part_path"
5944         will result in the object actually being swallowed into the part
5945         "real_part_path" in the "somegroup" group.
5946     @endproperty
5947     @endblock
5948  */
5949 static void
st_collections_group_parts_alias(void)5950 st_collections_group_parts_alias(void)
5951 {
5952    Edje_Part_Collection *pc;
5953    const char *alias;
5954    const char *aliased;
5955 
5956    check_arg_count(2);
5957 
5958    pc = eina_list_data_get(eina_list_last(edje_collections));
5959 
5960    alias = parse_str(0);
5961    aliased = parse_str(1);
5962 
5963    if (!pc->alias) pc->alias = eina_hash_string_small_new(NULL);
5964    eina_hash_add(pc->alias, alias, aliased);
5965 
5966    if (!pc->aliased) pc->aliased = eina_hash_string_small_new(NULL);
5967    eina_hash_add(pc->aliased, aliased, alias);
5968 }
5969 
5970 /** @edcsubsection{collections_group_parts_part,
5971  *                 Group.Parts.Part} */
5972 
5973 /**
5974     @page edcref
5975     @block
5976         part
5977     @context
5978         group {
5979             parts {
5980                 ..
5981                 part {
5982                     name: "partname";
5983                     type: IMAGE;
5984                     mouse_events:  1;
5985                     repeat_events: 0;
5986                     ignore_flags: NONE;
5987                     mask_flags: NONE;
5988                     clip_to: "anotherpart";
5989                     source:  "groupname";
5990                     pointer_mode: AUTOGRAB;
5991                     use_alternate_font_metrics: 0;
5992                     no_render: 0;
5993 
5994                     dragable { }
5995                     items { }
5996                     description { }
5997                 }
5998                 ..
5999             }
6000         }
6001     @description
6002         Parts are used to represent the most basic design elements of the
6003         theme, for example, a part can represent a line in a border or a label
6004         on a button.
6005     @endblock
6006  */
6007 static Edje_Part *
edje_cc_handlers_part_make(int id)6008 edje_cc_handlers_part_make(int id)
6009 {  /* Doing ob_collections_group_parts_part() job, without hierarchy */
6010   Edje_Part_Collection *pc;
6011   Edje_Part_Collection_Parser *pcp;
6012   Edje_Part *ep;
6013   Edje_Part_Parser *epp;
6014 
6015   ep = mem_alloc(SZ(Edje_Part_Parser));
6016 
6017   pc = eina_list_data_get(eina_list_last(edje_collections));
6018   if (id < 0)
6019     {
6020        pc->parts_count++;
6021        pc->parts = realloc(pc->parts, pc->parts_count * sizeof (Edje_Part *));
6022        if (!pc->parts)
6023          {
6024             ERR("Not enough memory.");
6025             exit(-1);
6026          }
6027        id = pc->parts_count - 1;
6028     }
6029 
6030   current_part = pc->parts[id] = ep;
6031   pcp = (Edje_Part_Collection_Parser *)pc;
6032 
6033   ep->id = id;
6034   ep->type = EDJE_PART_TYPE_IMAGE;
6035   ep->mouse_events = pcp->default_mouse_events;
6036   ep->anti_alias = 1;
6037   ep->repeat_events = 0;
6038   ep->ignore_flags = EVAS_EVENT_FLAG_NONE;
6039   ep->mask_flags = EVAS_EVENT_FLAG_NONE;
6040   ep->scale = 0;
6041   ep->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
6042   ep->precise_is_inside = 0;
6043   ep->use_alternate_font_metrics = 0;
6044   ep->access = 0;
6045   ep->clip_to_id = -1;
6046   ep->no_render = 0;
6047   ep->required = 0;
6048   ep->dragable.confine_id = -1;
6049   ep->dragable.threshold_id = -1;
6050   ep->dragable.event_id = -1;
6051   ep->items = NULL;
6052   ep->nested_children_count = 0;
6053 
6054   ep->allowed_seats = NULL;
6055   ep->allowed_seats_count = 0;
6056 
6057   epp = (Edje_Part_Parser *)ep;
6058   epp->reorder.insert_before = NULL;
6059   epp->reorder.insert_after = NULL;
6060   epp->reorder.before = NULL;
6061   epp->reorder.after = NULL;
6062   epp->reorder.linked_prev = 0;
6063   epp->reorder.linked_next = 0;
6064   epp->reorder.done = EINA_FALSE;
6065   epp->can_override = EINA_FALSE;
6066 
6067   return ep;
6068 }
6069 
6070 static void *
_part_desc_free(Edje_Part_Collection * pc,Edje_Part * ep,Edje_Part_Description_Common * ed)6071 _part_desc_free(Edje_Part_Collection *pc,
6072                 Edje_Part *ep,
6073                 Edje_Part_Description_Common *ed)
6074 {
6075    if (!ed) return NULL;
6076 
6077    eina_hash_del_by_key(desc_hash, &ed);
6078 
6079    part_lookup_del(pc, &(ed->rel1.id_x));
6080    part_lookup_del(pc, &(ed->rel1.id_y));
6081    part_lookup_del(pc, &(ed->rel2.id_x));
6082    part_lookup_del(pc, &(ed->rel2.id_y));
6083    part_lookup_del(pc, &(ed->clip_to_id));
6084    part_lookup_del(pc, &(ed->map.id_persp));
6085    part_lookup_del(pc, &(ed->map.id_light));
6086    part_lookup_del(pc, &(ed->map.rot.id_center));
6087    part_lookup_del(pc, &(ed->map.zoom.id_center));
6088 
6089    switch (ep->type)
6090      {
6091       case EDJE_PART_TYPE_SPACER:
6092       case EDJE_PART_TYPE_RECTANGLE:
6093       case EDJE_PART_TYPE_SWALLOW:
6094       case EDJE_PART_TYPE_GROUP:
6095         /* Nothing todo, this part only have a common description. */
6096         break;
6097 
6098       case EDJE_PART_TYPE_BOX:
6099       case EDJE_PART_TYPE_TABLE:
6100       case EDJE_PART_TYPE_IMAGE:
6101       case EDJE_PART_TYPE_SNAPSHOT:
6102       case EDJE_PART_TYPE_VECTOR:
6103         /* Nothing todo here */
6104         break;
6105 
6106       case EDJE_PART_TYPE_TEXT:
6107       case EDJE_PART_TYPE_TEXTBLOCK:
6108       {
6109          Edje_Part_Description_Text *ted = (Edje_Part_Description_Text *)ed;
6110 
6111          part_lookup_del(pc, &(ted->text.id_source));
6112          part_lookup_del(pc, &(ted->text.id_text_source));
6113          break;
6114       }
6115 
6116       case EDJE_PART_TYPE_PROXY:
6117       {
6118          Edje_Part_Description_Proxy *ped = (Edje_Part_Description_Proxy *)ed;
6119 
6120          part_lookup_del(pc, &(ped->proxy.id));
6121          break;
6122       }
6123      }
6124 
6125    free((void *)ed->state.name);
6126    free(ed);
6127    return NULL;
6128 }
6129 
6130 static void
_part_type_set(unsigned int type)6131 _part_type_set(unsigned int type)
6132 {
6133    /* handle type change of inherited part */
6134    if (type != current_part->type)
6135      {
6136         Edje_Part_Description_Common *new, *previous, *cur;
6137         Edje_Part_Collection *pc;
6138         Edje_Part *ep, *dummy;
6139         unsigned int i;
6140 
6141         /* we don't free old part as we don't remove all reference to them */
6142         part_description_image_cleanup(current_part);
6143         current_part->type = type;
6144 
6145         pc = eina_list_data_get(eina_list_last(edje_collections));
6146         ep = current_part;
6147 
6148         previous = ep->default_desc;
6149         cur = current_desc;
6150         dummy = mem_alloc(SZ(Edje_Part));
6151         /* ensure type is incompatible with new type */
6152         dummy->type = ep->type + 2;
6153         if (previous)
6154           {
6155              new = _edje_part_description_alloc(type, pc->part, ep->name);
6156              eina_hash_add(desc_hash, &new, ep);
6157              eina_hash_set(desc_hash, &previous, dummy);
6158              parent_desc = previous;
6159              current_desc = new;
6160              new->state.name = strdup(previous->state.name);
6161              new->state.value = previous->state.value;
6162              st_collections_group_parts_part_description_inherit();
6163              parent_desc = NULL;
6164              _part_desc_free(pc, ep, previous);
6165 
6166              ep->default_desc = new;
6167           }
6168 
6169         for (i = 0; i < ep->other.desc_count; i++)
6170           {
6171              previous = ep->other.desc[i];
6172              new = _edje_part_description_alloc(type, pc->part, ep->name);
6173              eina_hash_add(desc_hash, &new, ep);
6174              eina_hash_set(desc_hash, &previous, dummy);
6175              parent_desc = previous;
6176              current_desc = new;
6177              new->state.name = strdup(previous->state.name);
6178              new->state.value = previous->state.value;
6179              st_collections_group_parts_part_description_inherit();
6180              parent_desc = NULL;
6181              _part_desc_free(pc, ep, previous);
6182              ep->other.desc[i] = new;
6183           }
6184         free(dummy);
6185         current_desc = cur;
6186      }
6187 
6188    _parts_count_update(current_part->type, 1);
6189 }
6190 
6191 static void
_part_create(void)6192 _part_create(void)
6193 {
6194    Edje_Part *cp = current_part;  /* Save to restore on pop    */
6195    Edje_Part *ep = edje_cc_handlers_part_make(-1); /* This changes current_part */
6196    Edje_Part *prnt;
6197 
6198    /* Add this new part to hierarchy stack (removed part finished parse) */
6199    edje_cc_handlers_hierarchy_push(ep, cp);
6200 
6201    prnt = edje_cc_handlers_hierarchy_parent_get();
6202    if (prnt) /* This is the child of parent in stack */
6203      prnt->nested_children_count++;
6204 }
6205 
6206 static void
ob_collections_group_parts_part_short(void)6207 ob_collections_group_parts_part_short(void)
6208 {
6209    unsigned int type;
6210 
6211    type = parse_enum(-1,
6212                      "none", EDJE_PART_TYPE_NONE,
6213                      "rect", EDJE_PART_TYPE_RECTANGLE,
6214                      "text", EDJE_PART_TYPE_TEXT,
6215                      "image", EDJE_PART_TYPE_IMAGE,
6216                      "swallow", EDJE_PART_TYPE_SWALLOW,
6217                      "textblock", EDJE_PART_TYPE_TEXTBLOCK,
6218                      "group", EDJE_PART_TYPE_GROUP,
6219                      "box", EDJE_PART_TYPE_BOX,
6220                      "table", EDJE_PART_TYPE_TABLE,
6221                      "external", EDJE_PART_TYPE_EXTERNAL,
6222                      "proxy", EDJE_PART_TYPE_PROXY,
6223                      "spacer", EDJE_PART_TYPE_SPACER,
6224                      "snapshot", EDJE_PART_TYPE_SNAPSHOT,
6225                      "vector", EDJE_PART_TYPE_VECTOR,
6226                      NULL);
6227 
6228    stack_replace_quick("part");
6229    _part_create();
6230    _part_type_set(type);
6231 }
6232 
6233 static void
ob_collections_group_parts_part(void)6234 ob_collections_group_parts_part(void)
6235 {
6236    _part_create();
6237 }
6238 
6239 static void *
_part_free(Edje_Part_Collection * pc,Edje_Part * ep)6240 _part_free(Edje_Part_Collection *pc, Edje_Part *ep)
6241 {
6242    Edje_Part_Parser *epp = (Edje_Part_Parser *)ep;
6243    unsigned int j;
6244 
6245    part_lookup_del(pc, &(ep->clip_to_id));
6246    part_lookup_del(pc, &(ep->dragable.confine_id));
6247    part_lookup_del(pc, &(ep->dragable.threshold_id));
6248    part_lookup_del(pc, &(ep->dragable.event_id));
6249 
6250    _part_desc_free(pc, ep, ep->default_desc);
6251    for (j = 0; j < ep->other.desc_count; j++)
6252      _part_desc_free(pc, ep, ep->other.desc[j]);
6253 
6254    for (j = 0; j < ep->items_count; j++)
6255      free(ep->items[j]);
6256    free(ep->items);
6257 
6258    for (j = 0; j < ep->allowed_seats_count; j++)
6259      {
6260         free((void *)(ep->allowed_seats[j]->name));
6261         free(ep->allowed_seats[j]);
6262      }
6263    free(ep->allowed_seats);
6264 
6265    free((void *)ep->name);
6266    free((void *)ep->source);
6267    free((void *)ep->source2);
6268    free((void *)ep->source3);
6269    free((void *)ep->source4);
6270    free((void *)ep->source5);
6271    free((void *)ep->source6);
6272 
6273    free((void *)epp->reorder.insert_before);
6274    free((void *)epp->reorder.insert_after);
6275 
6276    free((void *)ep->api.name);
6277    free((void *)ep->api.description);
6278 
6279    free(ep->other.desc);
6280    free(ep);
6281    return NULL;
6282 }
6283 
6284 /**
6285     @page edcref
6286     @property
6287         inherit
6288     @parameters
6289         [part name]
6290     @effect
6291         Copies all attributes except part name from referenced part into current part.
6292         ALL existing attributes, except part name, are overwritten.
6293         @warning When inheriting any parts, descriptions without state names are NOT
6294         allowed.
6295     @since 1.10
6296     @endproperty
6297  */
6298 static void
st_collections_group_parts_part_inherit(void)6299 st_collections_group_parts_part_inherit(void)
6300 {
6301    char *name;
6302    Edje_Part_Collection *pc;
6303    unsigned int i;
6304 
6305    check_arg_count(1);
6306 
6307    name = parse_str(0);
6308    pc = eina_list_data_get(eina_list_last(edje_collections));
6309    for (i = 0; i < pc->parts_count; i++)
6310      {
6311         int id = current_part->id;
6312         const char *pname;
6313 
6314         if (strcmp(pc->parts[i]->name, name)) continue;
6315         if (pc->parts[i] == current_part)
6316           {
6317              ERR("Cannot inherit from same part '%s' in group '%s'", name, current_de->entry);
6318              free(name);
6319              exit(-1);
6320           }
6321         pname = current_part->name;
6322         current_part->name = NULL;
6323         current_part = _part_free(pc, current_part);
6324         edje_cc_handlers_part_make(id);
6325         _part_copy(current_part, pc->parts[i]);
6326         free((void *)current_part->name);
6327         current_part->name = pname;
6328         free(name);
6329         return;
6330      }
6331 
6332    ERR("Cannot inherit non-existing part '%s' in group '%s'", name, current_de->entry);
6333    free(name);
6334    exit(-1);
6335 }
6336 
6337 static void
_program_free(Edje_Program * pr)6338 _program_free(Edje_Program *pr)
6339 {
6340    Edje_Part_Collection *pc;
6341    Edje_Program_Target *prt;
6342    Edje_Program_After *pa;
6343 
6344    pc = eina_list_last_data_get(edje_collections);
6345 
6346    free((void *)pr->name);
6347    free((void *)pr->signal);
6348    free((void *)pr->source);
6349    free((void *)pr->filter.part);
6350    free((void *)pr->filter.state);
6351    free((void *)pr->seat);
6352    free((void *)pr->state);
6353    free((void *)pr->state2);
6354    free((void *)pr->sample_name);
6355    free((void *)pr->tone_name);
6356    EINA_LIST_FREE(pr->targets, prt)
6357      {
6358         part_lookup_del(pc, &prt->id);
6359         free(prt);
6360      }
6361    EINA_LIST_FREE(pr->after, pa)
6362      free(pa);
6363    free(pr);
6364 }
6365 
6366 static Eina_Bool
_program_remove(const char * name,Edje_Program ** pgrms,unsigned int count)6367 _program_remove(const char *name, Edje_Program **pgrms, unsigned int count)
6368 {
6369    unsigned int i;
6370    Edje_Part_Collection *pc;
6371 
6372    pc = eina_list_last_data_get(edje_collections);
6373 
6374    for (i = 0; i < count; ++i)
6375      if (pgrms[i]->name && (!strcmp(name, pgrms[i]->name)))
6376        {
6377           Edje_Program *pr = pgrms[i];
6378 
6379           if (pr->after)
6380             {
6381                Eina_List *l;
6382                Edje_Program_After *pa;
6383 
6384                EINA_LIST_FOREACH(pr->after, l, pa)
6385                  {
6386                     copied_program_lookup_delete(pc, (char *)(pa + 1));
6387                  }
6388             }
6389 
6390           _edje_program_remove(pc, pr);
6391 
6392           if (pr->action == EDJE_ACTION_TYPE_SCRIPT)
6393             {
6394                anonymous_delete = &pr->id;
6395             }
6396 
6397           _program_free(pr);
6398           return EINA_TRUE;
6399        }
6400    return EINA_FALSE;
6401 }
6402 
6403 static Eina_Bool
_part_name_check(void)6404 _part_name_check(void)
6405 {
6406    unsigned int i;
6407    Edje_Part_Collection *pc;
6408    Edje_Part *ep = current_part;
6409 
6410    if (!ep->name) return EINA_FALSE;
6411 
6412    pc = eina_list_data_get(eina_list_last(edje_collections));
6413 
6414    for (i = 0; i < (pc->parts_count - 1); i++)
6415      {  /* Compare name only if did NOT updated ep from hircy pop */
6416        if ((ep != pc->parts[i]) &&
6417            (pc->parts[i]->name &&
6418             (!strcmp(pc->parts[i]->name, ep->name))))
6419          {
6420             Edje_Part_Parser *epp;
6421 
6422             epp = (Edje_Part_Parser *)pc->parts[i];
6423             if (!epp->can_override)
6424               {
6425                  ERR("parse error %s:%i. There is already a part of the name %s",
6426                      file_in, line - 1, ep->name);
6427                  exit(-1);
6428               }
6429             else
6430               {
6431                  pc->parts_count--;
6432                  pc->parts = realloc(pc->parts, pc->parts_count * sizeof (Edje_Part *));
6433                  current_part = pc->parts[i];
6434                  edje_cc_handlers_hierarchy_rename(ep, current_part);
6435                  free(ep);
6436                  epp->can_override = EINA_FALSE;
6437                  break;
6438               }
6439          }
6440      }
6441    return EINA_TRUE;
6442 }
6443 
6444 /**
6445     @page edcref
6446     @property
6447         name
6448     @parameters
6449         [part name]
6450     @effect
6451         The part's name will be used as reference in the theme's relative
6452         positioning system, by programs and in some cases by the application.
6453         It must be unique within the group.
6454     @endproperty
6455  */
6456 static void
st_collections_group_parts_part_name(void)6457 st_collections_group_parts_part_name(void)
6458 {
6459    Edje_Part *ep;
6460 
6461    check_arg_count(1);
6462 
6463    ep = current_part;
6464    ep->name = parse_str(0);
6465    _part_name_check();
6466 }
6467 
6468 /**
6469     @page edcref
6470     @property
6471         type
6472     @parameters
6473         [TYPE]
6474     @effect
6475         Set the type (all caps) from among the available types, it's set to
6476         IMAGE by default. Valid types:
6477             @li RECT
6478             @li TEXT
6479             @li IMAGE
6480             @li SWALLOW
6481             @li TEXTBLOCK
6482             @li GROUP
6483             @li BOX
6484             @li TABLE
6485             @li EXTERNAL
6486             @li PROXY
6487             @li SPACER
6488             @li SNAPSHOT
6489 
6490          Defaults: IMAGE
6491     @endproperty
6492  */
6493 static void
st_collections_group_parts_part_type(void)6494 st_collections_group_parts_part_type(void)
6495 {
6496    unsigned int type;
6497 
6498    check_arg_count(1);
6499 
6500    type = parse_enum(0,
6501                      "NONE", EDJE_PART_TYPE_NONE,
6502                      "RECT", EDJE_PART_TYPE_RECTANGLE,
6503                      "TEXT", EDJE_PART_TYPE_TEXT,
6504                      "IMAGE", EDJE_PART_TYPE_IMAGE,
6505                      "SWALLOW", EDJE_PART_TYPE_SWALLOW,
6506                      "TEXTBLOCK", EDJE_PART_TYPE_TEXTBLOCK,
6507                      "GROUP", EDJE_PART_TYPE_GROUP,
6508                      "BOX", EDJE_PART_TYPE_BOX,
6509                      "TABLE", EDJE_PART_TYPE_TABLE,
6510                      "EXTERNAL", EDJE_PART_TYPE_EXTERNAL,
6511                      "PROXY", EDJE_PART_TYPE_PROXY,
6512                      "SPACER", EDJE_PART_TYPE_SPACER,
6513                      "SNAPSHOT", EDJE_PART_TYPE_SNAPSHOT,
6514                      "VECTOR", EDJE_PART_TYPE_VECTOR,
6515                      NULL);
6516 
6517    _part_type_set(type);
6518 }
6519 
6520 /**
6521     @page edcref
6522     @property
6523         physics_body
6524     @parameters
6525         [TYPE]
6526     @effect
6527         Set the type (all caps) from among the available types of physics
6528         body, it's set to NONE by default. If type is NONE no physics
6529         will be applied and physics block inside part will be discarded.
6530         Valid types:
6531             @li NONE
6532             @li RIGID_BOX
6533             @li RIGID_SPHERE
6534             @li RIGID_CYLINDER
6535             @li SOFT_BOX
6536             @li SOFT_SPHERE
6537             @li SOFT_CYLINDER
6538             @li CLOTH
6539             @li BOUNDARY_TOP
6540             @li BOUNDARY_BOTTOM
6541             @li BOUNDARY_RIGHT
6542             @li BOUNDARY_LEFT
6543             @li BOUNDARY_FRONT
6544             @li BOUNDARY_BACK
6545 
6546         Defaults: NONE
6547     @since 1.8
6548     @endproperty
6549  */
6550 #ifdef HAVE_EPHYSICS
6551 static void
st_collections_group_parts_part_physics_body(void)6552 st_collections_group_parts_part_physics_body(void)
6553 {
6554    unsigned int body;
6555 
6556    check_arg_count(1);
6557 
6558    body = parse_enum(0,
6559                      "NONE", EDJE_PART_PHYSICS_BODY_NONE,
6560                      "RIGID_BOX", EDJE_PART_PHYSICS_BODY_RIGID_BOX,
6561                      "RIGID_SPHERE", EDJE_PART_PHYSICS_BODY_RIGID_SPHERE,
6562                      "RIGID_CYLINDER", EDJE_PART_PHYSICS_BODY_RIGID_CYLINDER,
6563                      "SOFT_BOX", EDJE_PART_PHYSICS_BODY_SOFT_BOX,
6564                      "SOFT_SPHERE", EDJE_PART_PHYSICS_BODY_SOFT_SPHERE,
6565                      "SOFT_CYLINDER", EDJE_PART_PHYSICS_BODY_SOFT_CYLINDER,
6566                      "CLOTH", EDJE_PART_PHYSICS_BODY_CLOTH,
6567                      "BOUNDARY_TOP", EDJE_PART_PHYSICS_BODY_BOUNDARY_TOP,
6568                      "BOUNDARY_BOTTOM", EDJE_PART_PHYSICS_BODY_BOUNDARY_BOTTOM,
6569                      "BOUNDARY_RIGHT", EDJE_PART_PHYSICS_BODY_BOUNDARY_RIGHT,
6570                      "BOUNDARY_LEFT", EDJE_PART_PHYSICS_BODY_BOUNDARY_LEFT,
6571                      "BOUNDARY_FRONT", EDJE_PART_PHYSICS_BODY_BOUNDARY_FRONT,
6572                      "BOUNDARY_BACK", EDJE_PART_PHYSICS_BODY_BOUNDARY_BACK,
6573                      NULL);
6574 
6575    current_part->physics_body = body;
6576 
6577    if (body)
6578      {
6579         Edje_Part_Collection *pc;
6580         pc = eina_list_data_get(eina_list_last(edje_collections));
6581         pc->physics_enabled = 1;
6582      }
6583 }
6584 
6585 #endif
6586 
6587 /**
6588     @page edcref
6589     @property
6590         part
6591     @parameters
6592         [part declaration]
6593     @effect
6594     @code
6595         group {
6596             parts {
6597                 part {
6598                     name: "parent_rect";
6599                     type: RECT;
6600                     description { }
6601                     part {
6602                         name: "nested_rect";
6603                         type: RECT;
6604                         description { }
6605                     }
6606                 }
6607                 ..
6608             }
6609         }
6610     @endcode
6611         Nested parts adds hierarchy to edje.
6612         Nested part inherits it's location relatively to the parent part.
6613         To declare a nested part just start a new part within current part decl.
6614         You must define parent part name before adding nested parts.
6615     @since 1.7
6616     @endproperty
6617  */
6618 
6619 /**
6620     @page edcref
6621     @property
6622         insert_before
6623     @parameters
6624         [another part's name]
6625     @effect
6626         The part's name which this part is inserted before. One part cannot
6627         have both insert_before and insert_after. One part cannot refer
6628         more than one by insert_before.
6629     @since 1.1
6630     @endproperty
6631  */
6632 static void
st_collections_group_parts_part_insert_before(void)6633 st_collections_group_parts_part_insert_before(void)
6634 {
6635    Edje_Part_Parser *epp;
6636 
6637    check_arg_count(1);
6638 
6639    epp = (Edje_Part_Parser *)current_part;
6640    epp->reorder.insert_before = parse_str(0);
6641 }
6642 
6643 /**
6644     @page edcref
6645     @property
6646         insert_after
6647     @parameters
6648         [another part's name]
6649     @effect
6650         The part's name which this part is inserted after. One part cannot
6651         have both insert_before and insert_after. One part cannot refer
6652         more than one by insert_after.
6653     @since 1.1
6654     @endproperty
6655  */
6656 static void
st_collections_group_parts_part_insert_after(void)6657 st_collections_group_parts_part_insert_after(void)
6658 {
6659    Edje_Part_Parser *epp;
6660 
6661    check_arg_count(1);
6662 
6663    epp = (Edje_Part_Parser *)current_part;
6664    epp->reorder.insert_after = parse_str(0);
6665 }
6666 
6667 /**
6668     @page edcref
6669     @property
6670         mouse_events
6671     @parameters
6672         [1 or 0]
6673     @effect
6674         Specifies whether the part will emit signals, although it is named
6675         "mouse_events", disabling it (0) will prevent the part from emitting
6676         any type of signal at all.
6677 
6678         Defaults: group.mouse_events
6679     @endproperty
6680  */
6681 static void
st_collections_group_parts_part_mouse_events(void)6682 st_collections_group_parts_part_mouse_events(void)
6683 {
6684    check_arg_count(1);
6685 
6686    current_part->mouse_events = parse_bool(0);
6687 }
6688 
6689 static void
st_collections_group_parts_part_mouse(void)6690 st_collections_group_parts_part_mouse(void)
6691 {
6692    check_arg_count(0);
6693    current_part->mouse_events = 1;
6694 }
6695 
6696 static void
st_collections_group_parts_part_nomouse(void)6697 st_collections_group_parts_part_nomouse(void)
6698 {
6699    check_arg_count(0);
6700    current_part->mouse_events = 0;
6701 }
6702 
6703 /**
6704     @page edcref
6705     @property
6706         anti_alias
6707     @parameters
6708         [1 or 0]
6709     @effect
6710         Takes a boolean value specifying whether part is anti_alias (1) or not (0).
6711 
6712         Defaults: 1
6713     @endproperty
6714  */
6715 static void
st_collections_group_parts_part_anti_alias(void)6716 st_collections_group_parts_part_anti_alias(void)
6717 {
6718    check_arg_count(1);
6719    current_part->anti_alias = parse_bool(0);
6720 }
6721 
6722 /**
6723     @page edcref
6724     @property
6725         repeat_events
6726     @parameters
6727         [1 or 0]
6728     @effect
6729         Specifies whether a part echoes a mouse event to other parts below the
6730         pointer (1), or not (0)
6731 
6732         Defaults: 0
6733     @endproperty
6734  */
6735 static void
st_collections_group_parts_part_repeat_events(void)6736 st_collections_group_parts_part_repeat_events(void)
6737 {
6738    check_arg_count(1);
6739 
6740    current_part->repeat_events = parse_bool(0);
6741 }
6742 
6743 static void
st_collections_group_parts_part_repeat(void)6744 st_collections_group_parts_part_repeat(void)
6745 {
6746    check_arg_count(0);
6747 
6748    current_part->repeat_events = 1;
6749 }
6750 
6751 static void
st_collections_group_parts_part_norepeat(void)6752 st_collections_group_parts_part_norepeat(void)
6753 {
6754    check_arg_count(0);
6755 
6756    current_part->repeat_events = 0;
6757 }
6758 
6759 /**
6760     @page edcref
6761     @property
6762         ignore_flags
6763     @parameters
6764         [FLAG] ...
6765     @effect
6766         Specifies whether events with the given flags should be ignored,
6767         i.e., will not have the signals emitted to the parts. Multiple flags
6768         must be separated by spaces, the effect will be ignoring all events
6769         with one of the flags specified.
6770         Possible flags:
6771             @li NONE (no event will be ignored)
6772             @li ON_HOLD
6773 
6774         Defaults: NONE
6775     @endproperty
6776  */
6777 static void
st_collections_group_parts_part_ignore_flags(void)6778 st_collections_group_parts_part_ignore_flags(void)
6779 {
6780    check_min_arg_count(1);
6781 
6782    current_part->ignore_flags = parse_flags(0,
6783                                             "NONE", EVAS_EVENT_FLAG_NONE,
6784                                             "ON_HOLD", EVAS_EVENT_FLAG_ON_HOLD,
6785                                             NULL);
6786 }
6787 
6788 /**
6789     @page edcref
6790     @property
6791         mask_flags
6792     @parameters
6793         [FLAG] ...
6794     @effect
6795         Masks event flags with the given value, so that the event can be repeated
6796         to the lower object along with masked event flags.
6797         Possible flags:
6798             @li NONE (no event will be masked)
6799             @li ON_HOLD
6800 
6801         Defaults: NONE
6802     @endproperty
6803  */
6804 static void
st_collections_group_parts_part_mask_flags(void)6805 st_collections_group_parts_part_mask_flags(void)
6806 {
6807    check_min_arg_count(1);
6808 
6809    current_part->mask_flags = parse_flags(0,
6810                                           "NONE", EVAS_EVENT_FLAG_NONE,
6811                                           "ON_HOLD", EVAS_EVENT_FLAG_ON_HOLD,
6812                                           NULL);
6813 }
6814 
6815 /**
6816     @page edcref
6817     @property
6818         scale
6819     @parameters
6820         [1 or 0]
6821     @effect
6822         Specifies whether the part will scale its size with an edje scaling
6823         factor. By default scale is off (0) and the default scale factor is
6824         1.0 - that means no scaling. This would be used to scale properties
6825         such as font size, min/max size of the part, and possibly can be used
6826         to scale based on DPI of the target device. The reason to be selective
6827         is that some things work well being scaled, others do not, so the
6828         designer gets to choose what works best. For MESH_NODE parts three
6829         parameters specify how much the part will stretched along each axis.
6830 
6831         Defaults: 0
6832     @endproperty
6833  */
6834 static void
st_collections_group_parts_part_scale(void)6835 st_collections_group_parts_part_scale(void)
6836 {
6837    if (get_arg_count() == 1)
6838      current_part->scale = parse_bool(0);
6839    else
6840      current_part->scale = 1;
6841 }
6842 
6843 static void
st_collections_group_parts_part_noscale(void)6844 st_collections_group_parts_part_noscale(void)
6845 {
6846    check_arg_count(0);
6847    current_part->scale = 0;
6848 }
6849 
6850 /**
6851     @page edcref
6852     @property
6853         pointer_mode
6854     @parameters
6855         [MODE]
6856     @effect
6857         Sets the mouse pointer behavior for a given part. Aviable modes:
6858             @li AUTOGRAB, when the part is clicked and the button remains
6859                 pressed, the part will be the source of all future mouse
6860                 signals emitted, even outside the object, until the button is
6861                 released.
6862             @li NOGRAB, the effect will be limited to the part's container.
6863 
6864         Defaults: AUTOGRAB
6865     @endproperty
6866  */
6867 static void
st_collections_group_parts_part_pointer_mode(void)6868 st_collections_group_parts_part_pointer_mode(void)
6869 {
6870    check_arg_count(1);
6871 
6872    current_part->pointer_mode = parse_enum(0,
6873                                            "AUTOGRAB", EVAS_OBJECT_POINTER_MODE_AUTOGRAB,
6874                                            "NOGRAB", EVAS_OBJECT_POINTER_MODE_NOGRAB,
6875                                            NULL);
6876 }
6877 
6878 /**
6879     @page edcref
6880     @property
6881         precise_is_inside
6882     @parameters
6883         [1 or 0]
6884     @effect
6885         Enables precise point collision detection for the part, which is more
6886         resource intensive.
6887 
6888         Defaults: 0
6889     @endproperty
6890  */
6891 static void
st_collections_group_parts_part_precise_is_inside(void)6892 st_collections_group_parts_part_precise_is_inside(void)
6893 {
6894    check_arg_count(1);
6895 
6896    current_part->precise_is_inside = parse_bool(0);
6897 }
6898 
6899 static void
st_collections_group_parts_part_precise(void)6900 st_collections_group_parts_part_precise(void)
6901 {
6902    check_arg_count(0);
6903 
6904    current_part->precise_is_inside = 1;
6905 }
6906 
6907 static void
st_collections_group_parts_part_noprecise(void)6908 st_collections_group_parts_part_noprecise(void)
6909 {
6910    check_arg_count(0);
6911 
6912    current_part->precise_is_inside = 0;
6913 }
6914 
6915 /**
6916     @page edcref
6917     @property
6918         use_alternate_font_metrics
6919     @parameters
6920         [1 or 0]
6921     @effect
6922         Only affects text and textblock parts, when enabled Edje will use
6923         different size measurement functions. Disabled by default. (note from
6924         the author: I don't know what this is exactly useful for?)
6925 
6926         Defaults: 0
6927     @endproperty
6928  */
6929 static void
st_collections_group_parts_part_use_alternate_font_metrics(void)6930 st_collections_group_parts_part_use_alternate_font_metrics(void)
6931 {
6932    check_arg_count(1);
6933 
6934    current_part->use_alternate_font_metrics = parse_bool(0);
6935 }
6936 
6937 /**
6938     @page edcref
6939     @property
6940         clip_to
6941     @parameters
6942         [another part's name]
6943     @effect
6944         Only renders the area of part that coincides with another part's
6945         container. Overflowing content will not be displayed. Note that
6946         the part being clipped to can only be a rectangle part.
6947     @endproperty
6948  */
6949 static void
st_collections_group_parts_part_clip_to_id(void)6950 st_collections_group_parts_part_clip_to_id(void)
6951 {
6952    Edje_Part_Collection *pc;
6953 
6954    check_arg_count(1);
6955 
6956    pc = eina_list_data_get(eina_list_last(edje_collections));
6957    {
6958       char *name;
6959 
6960       name = parse_str(0);
6961       data_queue_part_lookup(pc, name, &(current_part->clip_to_id));
6962       free(name);
6963    }
6964 }
6965 
6966 /**
6967     @page edcref
6968     @property
6969         no_render
6970     @parameters
6971         [1 or 0]
6972     @effect
6973         Setting the no_render flag on an object will make it never render
6974         directly on the canvas, regardless of the visible and color properties.
6975         But the object will still be rendered in a dedicated surface when
6976         required if it is a proxy source or a mask (clipper).
6977         Strongly recommended for use with mask objects and proxy sources
6978         (instead of setting "source_visible" on the proxy itself).
6979 
6980         Defaults: 0
6981     @endproperty
6982  */
6983 static void
st_collections_group_parts_part_no_render(void)6984 st_collections_group_parts_part_no_render(void)
6985 {
6986    if (check_range_arg_count(0, 1) == 1)
6987      current_part->no_render = parse_bool(0);
6988    else /* lazEDC form */
6989      current_part->no_render = EINA_TRUE;
6990 }
6991 
6992 static void
st_collections_group_parts_part_render(void)6993 st_collections_group_parts_part_render(void)
6994 {
6995    current_part->no_render = EINA_FALSE;
6996 }
6997 
6998 /**
6999     @page edcref
7000     @property
7001         required
7002     @parameters
7003         [1 or 0]
7004     @effect
7005         If the required flag is set, this part will be considered
7006         stable and it is safe to use by any application."
7007 
7008         Defaults: 0
7009     @since 1.18
7010     @endproperty
7011  */
7012 static void
st_collections_group_parts_part_required(void)7013 st_collections_group_parts_part_required(void)
7014 {
7015    if (check_range_arg_count(0, 1) == 1)
7016      current_part->required = parse_bool(0);
7017    else /* lazEDC form */
7018      current_part->required = EINA_TRUE;
7019 }
7020 
7021 static void
st_collections_group_parts_part_norequired(void)7022 st_collections_group_parts_part_norequired(void)
7023 {
7024    current_part->required = EINA_FALSE;
7025 }
7026 
7027 /**
7028     @page edcref
7029     @property
7030         source
7031     @parameters
7032         [another group's name]
7033     @effect
7034         Only available to GROUP or TEXTBLOCK parts. Swallows the specified
7035         group into the part's container if a GROUP. If TEXTBLOCK it is used
7036         for the group to be loaded and used for selection display UNDER the
7037         selected text. source2 is used for on top of the selected text, if
7038         source2 is specified.
7039     @endproperty
7040  */
7041 static void
st_collections_group_parts_part_source(void)7042 st_collections_group_parts_part_source(void)
7043 {
7044    check_arg_count(1);
7045 
7046    //FIXME: validate this somehow (need to decide on the format also)
7047    current_part->source = parse_str(0);
7048    data_queue_group_lookup(current_part->source, current_part);
7049 }
7050 
7051 /**
7052     @page edcref
7053     @property
7054         source2
7055     @parameters
7056         [another group's name]
7057     @effect
7058         Only available to TEXTBLOCK parts. It is used for the group to be
7059         loaded and used for selection display OVER the selected text. source
7060         is used for under of the selected text, if source is specified.
7061     @endproperty
7062  */
7063 static void
st_collections_group_parts_part_source2(void)7064 st_collections_group_parts_part_source2(void)
7065 {
7066    check_arg_count(1);
7067 
7068    //FIXME: validate this somehow (need to decide on the format also)
7069    current_part->source2 = parse_str(0);
7070    data_queue_group_lookup(current_part->source2, current_part);
7071 }
7072 
7073 /**
7074     @page edcref
7075     @property
7076         source3
7077     @parameters
7078         [another group's name]
7079     @effect
7080         Only available to TEXTBLOCK parts. It is used for the group to be
7081         loaded and used for cursor display UNDER the cursor position. source4
7082         is used for over the cursor text, if source4 is specified.
7083     @endproperty
7084  */
7085 static void
st_collections_group_parts_part_source3(void)7086 st_collections_group_parts_part_source3(void)
7087 {
7088    check_arg_count(1);
7089 
7090    //FIXME: validate this somehow (need to decide on the format also)
7091    current_part->source3 = parse_str(0);
7092    data_queue_group_lookup(current_part->source3, current_part);
7093 }
7094 
7095 /**
7096     @page edcref
7097     @property
7098         source4
7099     @parameters
7100         [another group's name]
7101     @effect
7102         Only available to TEXTBLOCK parts. It is used for the group to be
7103         loaded and used for cursor display OVER the cursor position. source3
7104         is used for under the cursor text, if source4 is specified.
7105     @endproperty
7106  */
7107 static void
st_collections_group_parts_part_source4(void)7108 st_collections_group_parts_part_source4(void)
7109 {
7110    check_arg_count(1);
7111 
7112    //FIXME: validate this somehow (need to decide on the format also)
7113    current_part->source4 = parse_str(0);
7114    data_queue_group_lookup(current_part->source4, current_part);
7115 }
7116 
7117 /**
7118     @page edcref
7119     @property
7120         source5
7121     @parameters
7122         [another group's name]
7123     @effect
7124         Only available to TEXTBLOCK parts. It is used for the group to be
7125         loaded and used for anchors display UNDER the anchor position. source6
7126         is used for over the anchors text, if source6 is specified.
7127     @endproperty
7128  */
7129 static void
st_collections_group_parts_part_source5(void)7130 st_collections_group_parts_part_source5(void)
7131 {
7132    check_arg_count(1);
7133 
7134    //FIXME: validate this somehow (need to decide on the format also)
7135    current_part->source5 = parse_str(0);
7136    data_queue_group_lookup(current_part->source5, current_part);
7137 }
7138 
7139 /**
7140     @page edcref
7141     @property
7142         source6
7143     @parameters
7144         [another group's name]
7145     @effect
7146         Only available to TEXTBLOCK parts. It is used for the group to be
7147         loaded and used for anchor display OVER the anchor position. source5
7148         is used for under the anchor text, if source6 is specified.
7149     @endproperty
7150  */
7151 static void
st_collections_group_parts_part_source6(void)7152 st_collections_group_parts_part_source6(void)
7153 {
7154    check_arg_count(1);
7155 
7156    //FIXME: validate this somehow (need to decide on the format also)
7157    current_part->source6 = parse_str(0);
7158    data_queue_group_lookup(current_part->source6, current_part);
7159 }
7160 
7161 /**
7162     @page edcref
7163 
7164     @property
7165         effect
7166     @parameters
7167         [effect]
7168         (shadow direction)
7169     @effect
7170         Causes Edje to draw the selected effect among:
7171         @li PLAIN
7172         @li OUTLINE
7173         @li SOFT_OUTLINE
7174         @li SHADOW
7175         @li SOFT_SHADOW
7176         @li OUTLINE_SHADOW
7177         @li OUTLINE_SOFT_SHADOW
7178         @li FAR_SHADOW
7179         @li FAR_SOFT_SHADOW
7180         @li GLOW
7181 
7182         Shadow directions (default if not given is BOTTOM_RIGHT):
7183         @li BOTTOM_RIGHT
7184         @li BOTTOM
7185         @li BOTTOM_LEFT
7186         @li LEFT
7187         @li TOP_LEFT
7188         @li TOP
7189         @li TOP_RIGHT
7190         @li RIGHT
7191 
7192         Defaults: PLAIN
7193     @endproperty
7194  */
7195 static void
st_collections_group_parts_part_effect(void)7196 st_collections_group_parts_part_effect(void)
7197 {
7198    check_min_arg_count(1);
7199 
7200    current_part->effect = parse_enum(0,
7201                                      "NONE", EDJE_TEXT_EFFECT_NONE,
7202                                      "PLAIN", EDJE_TEXT_EFFECT_PLAIN,
7203                                      "OUTLINE", EDJE_TEXT_EFFECT_OUTLINE,
7204                                      "SOFT_OUTLINE", EDJE_TEXT_EFFECT_SOFT_OUTLINE,
7205                                      "SHADOW", EDJE_TEXT_EFFECT_SHADOW,
7206                                      "SOFT_SHADOW", EDJE_TEXT_EFFECT_SOFT_SHADOW,
7207                                      "OUTLINE_SHADOW", EDJE_TEXT_EFFECT_OUTLINE_SHADOW,
7208                                      "OUTLINE_SOFT_SHADOW", EDJE_TEXT_EFFECT_OUTLINE_SOFT_SHADOW,
7209                                      "FAR_SHADOW", EDJE_TEXT_EFFECT_FAR_SHADOW,
7210                                      "FAR_SOFT_SHADOW", EDJE_TEXT_EFFECT_FAR_SOFT_SHADOW,
7211                                      "GLOW", EDJE_TEXT_EFFECT_GLOW,
7212                                      NULL);
7213    if (get_arg_count() >= 2)
7214      {
7215         unsigned char shadow;
7216 
7217         shadow = parse_enum(1,
7218                             "BOTTOM_RIGHT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_BOTTOM_RIGHT,
7219                             "BOTTOM", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_BOTTOM,
7220                             "BOTTOM_LEFT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_BOTTOM_LEFT,
7221                             "LEFT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_LEFT,
7222                             "TOP_LEFT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_TOP_LEFT,
7223                             "TOP", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_TOP,
7224                             "TOP_RIGHT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_TOP_RIGHT,
7225                             "RIGHT", EDJE_TEXT_EFFECT_SHADOW_DIRECTION_RIGHT,
7226                             NULL);
7227         EDJE_TEXT_EFFECT_SHADOW_DIRECTION_SET(current_part->effect, shadow);
7228      }
7229 }
7230 
7231 /**
7232     @page edcref
7233     @property
7234         entry_mode
7235     @parameters
7236         [mode]
7237     @effect
7238         Sets the edit mode for a textblock part to one of:
7239         @li NONE
7240         @li PLAIN
7241         @li EDITABLE
7242         @li PASSWORD
7243 
7244         It causes the part be editable if the edje object has the keyboard
7245         focus AND the part has the edje focus (or selectable always
7246         regardless of focus) and in the event of password mode, not
7247         selectable and all text chars replaced with *'s but editable and
7248         pastable.
7249 
7250         Defaults: NONE
7251     @endproperty
7252  */
7253 static void
st_collections_group_parts_part_entry_mode(void)7254 st_collections_group_parts_part_entry_mode(void)
7255 {
7256    check_arg_count(1);
7257 
7258    current_part->entry_mode = parse_enum(0,
7259                                          "NONE", EDJE_ENTRY_EDIT_MODE_NONE,
7260                                          "PLAIN", EDJE_ENTRY_EDIT_MODE_SELECTABLE,
7261                                          "EDITABLE", EDJE_ENTRY_EDIT_MODE_EDITABLE,
7262                                          "PASSWORD", EDJE_ENTRY_EDIT_MODE_PASSWORD,
7263                                          NULL);
7264 }
7265 
7266 /**
7267     @page edcref
7268     @property
7269         select_mode
7270     @parameters
7271         [mode]
7272     @effect
7273         Sets the selection mode for a textblock part to one of:
7274         @li DEFAULT selection mode is what you would expect on any desktop. Press
7275         mouse, drag and release to end.
7276         @li EXPLICIT mode requires the application
7277         controlling the edje object has to explicitly begin and end selection
7278         modes, and the selection itself is draggable at both ends.
7279     @endproperty
7280  */
7281 static void
st_collections_group_parts_part_select_mode(void)7282 st_collections_group_parts_part_select_mode(void)
7283 {
7284    check_arg_count(1);
7285 
7286    current_part->select_mode = parse_enum(0,
7287                                           "DEFAULT", EDJE_ENTRY_SELECTION_MODE_DEFAULT,
7288                                           "EXPLICIT", EDJE_ENTRY_SELECTION_MODE_EXPLICIT,
7289                                           NULL);
7290 }
7291 
7292 /**
7293     @page edcref
7294     @property
7295         cursor_mode
7296     @parameters
7297         [mode]
7298     @effect
7299         Sets the cursor mode for a textblock part to one of:
7300         @li UNDER cursor mode means the cursor will draw below the character pointed at.
7301         @li BEFORE cursor mode means the cursor is drawn as a vertical line before
7302         the current character, just like many other GUI toolkits handle it.
7303 
7304         Defaults: UNDER
7305     @endproperty
7306  */
7307 static void
st_collections_group_parts_part_cursor_mode(void)7308 st_collections_group_parts_part_cursor_mode(void)
7309 {
7310    check_arg_count(1);
7311 
7312    current_part->cursor_mode = parse_enum(0,
7313                                           "UNDER", EDJE_ENTRY_CURSOR_MODE_UNDER,
7314                                           "BEFORE", EDJE_ENTRY_CURSOR_MODE_BEFORE,
7315                                           NULL);
7316 }
7317 
7318 /**
7319     @page edcref
7320     @property
7321         multiline
7322     @parameters
7323         [1 or 0]
7324     @effect
7325         It causes a textblock that is editable to allow multiple lines for
7326         editing.
7327 
7328         Defaults: 0
7329     @endproperty
7330  */
7331 static void
st_collections_group_parts_part_multiline(void)7332 st_collections_group_parts_part_multiline(void)
7333 {
7334    check_arg_count(1);
7335 
7336    current_part->multiline = parse_bool(0);
7337 }
7338 
7339 /**
7340     @page edcref
7341     @property
7342         access
7343     @parameters
7344         [1 or 0]
7345     @effect
7346         Specifies whether the part will use accessibility feature (1), or not (0).
7347 
7348         Defaults: 0
7349     @endproperty
7350  */
7351 static void
st_collections_group_parts_part_access(void)7352 st_collections_group_parts_part_access(void)
7353 {
7354    check_arg_count(1);
7355 
7356    current_part->access = parse_bool(0);
7357 }
7358 
7359 /** @edcsubsection{collections_group_parts_dragable,
7360  *                 Group.Parts.Part.Dragable} */
7361 
7362 /**
7363     @page edcref
7364     @block
7365         dragable
7366     @context
7367         part {
7368             ..
7369             dragable {
7370                 confine: "another part";
7371                 threshold: "another part";
7372                 events:  "another dragable part";
7373                 x: 0 0 0;
7374                 y: 0 0 0;
7375             }
7376             ..
7377         }
7378     @description
7379         When this block is used the resulting part can be dragged around the
7380         interface, do not confuse with external drag & drop. By default Edje
7381         (and most applications) will attempt to use the minimal size possible
7382         for a dragable part. If the min property is not set in the description
7383         the part will be (most likely) set to 0px width and 0px height, thus
7384         invisible.
7385     @endblock
7386 
7387     @property
7388         x
7389     @parameters
7390         [enable/disable] [step] [count]
7391     @effect
7392         Used to setup dragging events for the X axis. The first parameter is
7393         used to enable (1 or -1) and disable (0) dragging along the axis. When
7394         enabled, 1 will set the starting point at 0.0 and -1 at 1.0. The second
7395         parameter takes any integer and will limit movement to values
7396         divisible by it, causing the part to jump from position to position.
7397         If step is set to 0 it is calculated as width of confine part divided by
7398         count.
7399 
7400         Defaults: 0 0 0
7401     @endproperty
7402  */
7403 static void
st_collections_group_parts_part_dragable_x(void)7404 st_collections_group_parts_part_dragable_x(void)
7405 {
7406    check_arg_count(3);
7407 
7408    current_part->dragable.x = parse_int_range(0, -1, 1);
7409    current_part->dragable.step_x = parse_int_range(1, 0, 0x7fffffff);
7410    current_part->dragable.count_x = parse_int_range(2, 0, 0x7fffffff);
7411 }
7412 
7413 /**
7414     @page edcref
7415     @property
7416         y
7417     @parameters
7418         [enable/disable] [step] [count]
7419     @effect
7420         Used to setup dragging events for the Y axis. The first parameter is
7421         used to enable (1 or -1) and disable (0) dragging along the axis. When
7422         enabled, 1 will set the starting point at 0.0 and -1 at 1.0. The second
7423         parameter takes any integer and will limit movement to values
7424         divisible by it, causing the part to jump from position to position.
7425         If step is set to 0 it is calculated as height of confine part divided by
7426         count.
7427 
7428         Defaults: 0 0 0
7429     @endproperty
7430  */
7431 static void
st_collections_group_parts_part_dragable_y(void)7432 st_collections_group_parts_part_dragable_y(void)
7433 {
7434    check_arg_count(3);
7435 
7436    current_part->dragable.y = parse_int_range(0, -1, 1);
7437    current_part->dragable.step_y = parse_int_range(1, 0, 0x7fffffff);
7438    current_part->dragable.count_y = parse_int_range(2, 0, 0x7fffffff);
7439 }
7440 
7441 /**
7442     @page edcref
7443     @property
7444         confine
7445     @parameters
7446         [another part's name]
7447     @effect
7448         When set, limits the movement of the dragged part to another part's
7449         container. When you use confine don't forget to set a min size for the
7450         part, or the draggie will not show up.
7451     @endproperty
7452  */
7453 static void
st_collections_group_parts_part_dragable_confine(void)7454 st_collections_group_parts_part_dragable_confine(void)
7455 {
7456    Edje_Part_Collection *pc;
7457 
7458    check_arg_count(1);
7459 
7460    pc = eina_list_data_get(eina_list_last(edje_collections));
7461    {
7462       char *name;
7463 
7464       name = parse_str(0);
7465       data_queue_part_lookup(pc, name, &(current_part->dragable.confine_id));
7466       free(name);
7467    }
7468 }
7469 
7470 /**
7471     @page edcref
7472     @property
7473         threshold
7474     @parameters
7475         [another part's name]
7476     @effect
7477         When set, the movement of the dragged part can only start when it get
7478         moved enough to be outside of the threshold part.
7479     @endproperty
7480  */
7481 static void
st_collections_group_parts_part_dragable_threshold(void)7482 st_collections_group_parts_part_dragable_threshold(void)
7483 {
7484    Edje_Part_Collection *pc;
7485 
7486    check_arg_count(1);
7487 
7488    pc = eina_list_data_get(eina_list_last(edje_collections));
7489    {
7490       char *name;
7491 
7492       name = parse_str(0);
7493       data_queue_part_lookup(pc, name, &(current_part->dragable.threshold_id));
7494       free(name);
7495    }
7496 }
7497 
7498 /**
7499     @page edcref
7500     @property
7501         events
7502     @parameters
7503         [another dragable part's name]
7504     @effect
7505         It causes the part to forward the drag events to another part, thus
7506         ignoring them for itself.
7507     @endproperty
7508  */
7509 static void
st_collections_group_parts_part_dragable_events(void)7510 st_collections_group_parts_part_dragable_events(void)
7511 {
7512    Edje_Part_Collection *pc;
7513 
7514    check_arg_count(1);
7515 
7516    pc = eina_list_data_get(eina_list_last(edje_collections));
7517    {
7518       char *name;
7519 
7520       name = parse_str(0);
7521       data_queue_part_lookup(pc, name, &(current_part->dragable.event_id));
7522       free(name);
7523    }
7524 }
7525 
7526 /**
7527     @page edcref
7528     @property
7529         allowed_seats
7530     @parameters
7531         [seat1] [seat2] [seat3] ...
7532     @effect
7533         List of seat names allowed to interact with the part.
7534 
7535         If no list is defined all seats are allowed. It's the
7536         default behaviour.
7537 
7538         If a seat isn't allowed, no signals will be emitted
7539         related to its actions, as mouse and focus events.
7540         Also it won't be able to focus this part.
7541     @since 1.19
7542     @endproperty
7543  */
7544 static void
st_collections_group_parts_part_allowed_seats(void)7545 st_collections_group_parts_part_allowed_seats(void)
7546 {
7547    Edje_Part_Allowed_Seat *seat;
7548    Edje_Part *ep;
7549    int n, argc;
7550 
7551    check_min_arg_count(1);
7552 
7553    ep = current_part;
7554    argc = get_arg_count();
7555 
7556    ep->allowed_seats = calloc(argc, sizeof(Edje_Part_Allowed_Seat *));
7557    if (!ep->allowed_seats)
7558      {
7559         ERR("Not enough memory.");
7560         exit(-1);
7561      }
7562 
7563    for (n = 0; n < argc; n++)
7564      {
7565         seat = mem_alloc(SZ(Edje_Part_Allowed_Seat));
7566         seat->name = parse_str(n);
7567         ep->allowed_seats[n] = seat;
7568      }
7569 
7570    ep->allowed_seats_count = argc;
7571 }
7572 
7573 /** @edcsubsection{collections_group_parts_items,
7574  *                 Group.Parts.Part.Box/Table.Items} */
7575 
7576 /**
7577     @page edcref
7578     @block
7579         items
7580     @context
7581         part {
7582             ..
7583             box/table {
7584                 items {
7585                     item {
7586                         type: TYPE;
7587                         source: "some source";
7588                         min: 1 1;
7589                         max: 100 100;
7590                         padding: 1 1 2 2;
7591                     }
7592                     item {
7593                         type: TYPE;
7594                         source: "some other source";
7595                         name: "some name";
7596                         align: 1.0 0.5;
7597                     }
7598                     ..
7599                 }
7600             }
7601             ..
7602         }
7603     @description
7604         On a part of type BOX, this block can be used to set other groups
7605         as elements of the box. These can be mixed with external objects set
7606         by the application through the edje_object_part_box_* API.
7607     @endblock
7608  */
7609 static void
ob_collections_group_parts_part_box_items_item(void)7610 ob_collections_group_parts_part_box_items_item(void)
7611 {
7612    Edje_Part *ep;
7613    Edje_Pack_Element *item;
7614    Edje_Pack_Element_Parser *pitem;
7615 
7616    ep = current_part;
7617 
7618    if ((ep->type != EDJE_PART_TYPE_BOX) && (ep->type != EDJE_PART_TYPE_TABLE))
7619      {
7620         ERR("parse error %s:%i. box attributes in non-BOX or TABLE part.",
7621             file_in, line - 1);
7622         exit(-1);
7623      }
7624 
7625    ep->items_count++;
7626    ep->items = realloc(ep->items, sizeof (Edje_Pack_Element *) * ep->items_count);
7627    if (!ep->items)
7628      {
7629         ERR("Not enough memory.");
7630         exit(-1);
7631      }
7632 
7633    item = mem_alloc(SZ(Edje_Pack_Element_Parser));
7634    current_item = ep->items[ep->items_count - 1] = item;
7635    item->type = EDJE_PART_TYPE_GROUP;
7636    item->name = NULL;
7637    item->source = NULL;
7638    item->min.w = 0;
7639    item->min.h = 0;
7640    item->prefer.w = 0;
7641    item->prefer.h = 0;
7642    item->max.w = -1;
7643    item->max.h = -1;
7644    item->padding.l = 0;
7645    item->padding.r = 0;
7646    item->padding.t = 0;
7647    item->padding.b = 0;
7648    item->align.x = FROM_DOUBLE(0.5);
7649    item->align.y = FROM_DOUBLE(0.5);
7650    item->weight.x = FROM_DOUBLE(0.0);
7651    item->weight.y = FROM_DOUBLE(0.0);
7652    item->aspect.w = 0;
7653    item->aspect.h = 0;
7654    item->aspect.mode = EDJE_ASPECT_CONTROL_NONE;
7655    item->options = NULL;
7656    item->col = -1;
7657    item->row = -1;
7658    item->colspan = 1;
7659    item->rowspan = 1;
7660    item->spread.w = 1;
7661    item->spread.h = 1;
7662    pitem = (Edje_Pack_Element_Parser *)item;
7663    pitem->can_override = EINA_FALSE;
7664 }
7665 
7666 #define CURRENT_ITEM_CHECK                                       \
7667   if (!current_item)                                             \
7668     {                                                            \
7669        ERR("parse error %s:%i. Item not defined at this stage.", \
7670            file_in, line - 1);                                   \
7671        exit(-1);                                                 \
7672     }
7673 
7674 /**
7675     @page edcref
7676     @property
7677         type
7678     @parameters
7679         [item type]
7680     @effect
7681         Sets the type of the object this item will hold.
7682         Supported types are:
7683         @li GROUP
7684     @endproperty
7685  */
7686 static void
st_collections_group_parts_part_box_items_item_type(void)7687 st_collections_group_parts_part_box_items_item_type(void)
7688 {
7689    CURRENT_ITEM_CHECK;
7690 
7691    check_arg_count(1);
7692 
7693    {
7694       char *s;
7695 
7696       s = parse_str(0);
7697       if (strcmp(s, "GROUP"))
7698         {
7699            ERR("parse error %s:%i. token %s not one of: GROUP.",
7700                file_in, line - 1, s);
7701            free(s);
7702            exit(-1);
7703         }
7704       free(s);
7705       /* FIXME: handle the enum, once everything else is supported */
7706       current_item->type = EDJE_PART_TYPE_GROUP;
7707    }
7708 }
7709 
7710 /**
7711     @page edcref
7712     @property
7713         name
7714     @parameters
7715         [name for the object]
7716     @effect
7717         Sets the name of the object via evas_object_name_set().
7718     @endproperty
7719  */
7720 static void
st_collections_group_parts_part_box_items_item_name(void)7721 st_collections_group_parts_part_box_items_item_name(void)
7722 {
7723    Edje_Part *ep;
7724    Edje_Pack_Element *item;
7725    Edje_Pack_Element_Parser *pitem;
7726 
7727    CURRENT_ITEM_CHECK;
7728 
7729    check_arg_count(1);
7730 
7731    ep = current_part;
7732    item = ep->items[ep->items_count - 1];
7733 
7734    item->name = parse_str(0);
7735 
7736    {
7737       unsigned int i;
7738 
7739       for (i = 0; i < ep->items_count - 1; ++i)
7740         {
7741            if (ep->items[i]->name && (!strcmp(ep->items[i]->name, item->name)))
7742              {
7743                 pitem = (Edje_Pack_Element_Parser *)ep->items[i];
7744                 if (!pitem->can_override)
7745                   {
7746                      ERR("parse error %s:%i. There is already a item of the name %s",
7747                          file_in, line - 1, item->name);
7748                      exit(-1);
7749                   }
7750                 else
7751                   {
7752                      free(item);
7753                      ep->items_count--;
7754                      ep->items = realloc(ep->items, ep->items_count * sizeof (Edje_Pack_Element *));
7755                      current_item = ep->items[i];
7756                      pitem->can_override = EINA_FALSE;
7757                      break;
7758                   }
7759              }
7760         }
7761    }
7762 }
7763 
7764 /**
7765     @page edcref
7766     @property
7767         source
7768     @parameters
7769         [another group's name]
7770     @effect
7771         Sets the group this object will be made from.
7772     @endproperty
7773  */
7774 static void
st_collections_group_parts_part_box_items_item_source(void)7775 st_collections_group_parts_part_box_items_item_source(void)
7776 {
7777    CURRENT_ITEM_CHECK;
7778 
7779    check_arg_count(1);
7780 
7781    current_item->source = parse_str(0);
7782    data_queue_group_lookup(current_item->source, current_part);
7783 }
7784 
7785 /**
7786     @page edcref
7787     @property
7788         min
7789     @parameters
7790         [width] [height]
7791     @effect
7792         Sets the minimum size hints for this object.
7793 
7794         Defaults: 0 0
7795     @endproperty
7796  */
7797 static void
st_collections_group_parts_part_box_items_item_min(void)7798 st_collections_group_parts_part_box_items_item_min(void)
7799 {
7800    CURRENT_ITEM_CHECK;
7801 
7802    check_arg_count(2);
7803 
7804    current_item->min.w = parse_int_range(0, 0, 0x7ffffff);
7805    current_item->min.h = parse_int_range(1, 0, 0x7ffffff);
7806 }
7807 
7808 /**
7809    @page edcref
7810    @property
7811        spread
7812    @parameters
7813        [width] [height]
7814    @effect
7815        Will replicate the item in a rectangle of size width x height
7816        box starting from the defined position of this item.
7817 
7818        Defaults: 1 1
7819    @endproperty
7820  */
7821 static void
st_collections_group_parts_part_box_items_item_spread(void)7822 st_collections_group_parts_part_box_items_item_spread(void)
7823 {
7824    CURRENT_ITEM_CHECK;
7825 
7826    check_arg_count(2);
7827 
7828    current_item->spread.w = parse_int_range(0, 1, 0x7ffffff);
7829    current_item->spread.h = parse_int_range(1, 1, 0x7ffffff);
7830 }
7831 
7832 /**
7833     @page edcref
7834     @property
7835         prefer
7836     @parameters
7837         [width] [height]
7838     @effect
7839         Sets the preferred size hints for this object.
7840 
7841         Defaults: 0 0
7842     @endproperty
7843  */
7844 static void
st_collections_group_parts_part_box_items_item_prefer(void)7845 st_collections_group_parts_part_box_items_item_prefer(void)
7846 {
7847    CURRENT_ITEM_CHECK;
7848 
7849    check_arg_count(2);
7850 
7851    current_item->prefer.w = parse_int_range(0, 0, 0x7ffffff);
7852    current_item->prefer.h = parse_int_range(1, 0, 0x7ffffff);
7853 }
7854 
7855 /**
7856     @page edcref
7857     @property
7858         max
7859     @parameters
7860         [width] [height]
7861     @effect
7862         Sets the maximum size hints for this object.
7863 
7864         Defaults: -1 -1
7865     @endproperty
7866  */
7867 static void
st_collections_group_parts_part_box_items_item_max(void)7868 st_collections_group_parts_part_box_items_item_max(void)
7869 {
7870    CURRENT_ITEM_CHECK;
7871 
7872    check_arg_count(2);
7873 
7874    current_item->max.w = parse_int_range(0, -1, 0x7ffffff);
7875    current_item->max.h = parse_int_range(1, -1, 0x7ffffff);
7876 }
7877 
7878 /**
7879     @page edcref
7880     @property
7881         padding
7882     @parameters
7883         [left] [right] [top] [bottom]
7884     @effect
7885         Sets the padding hints for this object.
7886 
7887         Defaults: 0 0 0 0
7888     @endproperty
7889  */
7890 static void
st_collections_group_parts_part_box_items_item_padding(void)7891 st_collections_group_parts_part_box_items_item_padding(void)
7892 {
7893    CURRENT_ITEM_CHECK;
7894 
7895    check_arg_count(4);
7896 
7897    current_item->padding.l = parse_int_range(0, 0, 0x7ffffff);
7898    current_item->padding.r = parse_int_range(1, 0, 0x7ffffff);
7899    current_item->padding.t = parse_int_range(2, 0, 0x7ffffff);
7900    current_item->padding.b = parse_int_range(3, 0, 0x7ffffff);
7901 }
7902 
7903 /**
7904     @page edcref
7905     @property
7906         align
7907     @parameters
7908         [x] [y]
7909     @effect
7910         Sets the alignment [-1.0 - 1.0] hints for this object.
7911 
7912         Defaults: 0.5
7913     @endproperty
7914  */
7915 static void
st_collections_group_parts_part_box_items_item_align(void)7916 st_collections_group_parts_part_box_items_item_align(void)
7917 {
7918    CURRENT_ITEM_CHECK;
7919 
7920    check_arg_count(2);
7921 
7922    current_item->align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
7923    current_item->align.y = FROM_DOUBLE(parse_float_range(1, -1.0, 1.0));
7924 }
7925 
7926 /**
7927     @page edcref
7928     @property
7929         weight
7930     @parameters
7931         [x] [y]
7932     @effect
7933         Sets the weight hints for this object.
7934 
7935         Defaults: 0.0 0.0
7936     @endproperty
7937  */
7938 static void
st_collections_group_parts_part_box_items_item_weight(void)7939 st_collections_group_parts_part_box_items_item_weight(void)
7940 {
7941    CURRENT_ITEM_CHECK;
7942 
7943    check_arg_count(2);
7944 
7945    current_item->weight.x = FROM_DOUBLE(parse_float_range(0, 0.0, 99999.99));
7946    current_item->weight.y = FROM_DOUBLE(parse_float_range(1, 0.0, 99999.99));
7947 }
7948 
7949 /**
7950     @page edcref
7951     @property
7952         aspect
7953     @parameters
7954         [w] [h]
7955     @effect
7956         Sets the aspect width and height hints for this object.
7957 
7958         Defaults: 0 0
7959     @endproperty
7960  */
7961 static void
st_collections_group_parts_part_box_items_item_aspect(void)7962 st_collections_group_parts_part_box_items_item_aspect(void)
7963 {
7964    CURRENT_ITEM_CHECK;
7965 
7966    check_arg_count(2);
7967 
7968    current_item->aspect.w = parse_int_range(0, 0, 0x7fffffff);
7969    current_item->aspect.h = parse_int_range(1, 0, 0x7fffffff);
7970 }
7971 
7972 /**
7973     @page edcref
7974     @property
7975         aspect_mode
7976     @parameters
7977         [mode]
7978     @effect
7979         Sets the aspect control hints for this object. Mode can be one of:
7980         @li NONE
7981         @li NEITHER
7982         @li HORIZONTAL
7983         @li VERTICAL
7984         @li BOTH
7985 
7986         Defaults: NONE
7987     @endproperty
7988  */
7989 static void
st_collections_group_parts_part_box_items_item_aspect_mode(void)7990 st_collections_group_parts_part_box_items_item_aspect_mode(void)
7991 {
7992    CURRENT_ITEM_CHECK;
7993 
7994    check_arg_count(1);
7995 
7996    current_item->aspect.mode = parse_enum(0,
7997                                           "NONE", EDJE_ASPECT_CONTROL_NONE,
7998                                           "NEITHER", EDJE_ASPECT_CONTROL_NEITHER,
7999                                           "HORIZONTAL", EDJE_ASPECT_CONTROL_HORIZONTAL,
8000                                           "VERTICAL", EDJE_ASPECT_CONTROL_VERTICAL,
8001                                           "BOTH", EDJE_ASPECT_CONTROL_BOTH,
8002                                           NULL);
8003 }
8004 
8005 /**
8006     @page edcref
8007     @property
8008         options
8009     @parameters
8010         [extra options]
8011     @effect
8012         Sets extra options for the object. Unused for now.
8013     @endproperty
8014  */
8015 static void
st_collections_group_parts_part_box_items_item_options(void)8016 st_collections_group_parts_part_box_items_item_options(void)
8017 {
8018    CURRENT_ITEM_CHECK;
8019 
8020    check_arg_count(1);
8021 
8022    current_item->options = parse_str(0);
8023 }
8024 
8025 /**
8026     @page edcref
8027     @property
8028         position
8029     @parameters
8030         [col] [row]
8031     @effect
8032         Sets the position this item will have in the table.
8033         This is required for parts of type TABLE.
8034     @endproperty
8035  */
8036 static void
st_collections_group_parts_part_table_items_item_position(void)8037 st_collections_group_parts_part_table_items_item_position(void)
8038 {
8039    CURRENT_ITEM_CHECK;
8040 
8041    check_arg_count(2);
8042 
8043    if (current_part->type != EDJE_PART_TYPE_TABLE)
8044      {
8045         ERR("parse error %s:%i. table attributes in non-TABLE part.",
8046             file_in, line - 1);
8047         exit(-1);
8048      }
8049 
8050    current_item->col = parse_int_range(0, 0, 0xffff);
8051    current_item->row = parse_int_range(1, 0, 0xffff);
8052 }
8053 
8054 /**
8055     @page edcref
8056     @property
8057         span
8058     @parameters
8059         [col] [row]
8060     @effect
8061         Sets how many columns/rows this item will use.
8062 
8063         Defaults: 1 1
8064     @endproperty
8065  */
8066 static void
st_collections_group_parts_part_table_items_item_span(void)8067 st_collections_group_parts_part_table_items_item_span(void)
8068 {
8069    CURRENT_ITEM_CHECK;
8070 
8071    check_arg_count(2);
8072 
8073    if (current_part->type != EDJE_PART_TYPE_TABLE)
8074      {
8075         ERR("parse error %s:%i. table attributes in non-TABLE part.",
8076             file_in, line - 1);
8077         exit(-1);
8078      }
8079 
8080    current_item->colspan = parse_int_range(0, 1, 0xffff);
8081    current_item->rowspan = parse_int_range(1, 1, 0xffff);
8082 }
8083 
8084 static Edje_Map_Color **
_copied_map_colors_get(Edje_Part_Description_Common * parent)8085 _copied_map_colors_get(Edje_Part_Description_Common *parent)
8086 {
8087    Edje_Map_Color **colors;
8088    Edje_Map_Color *color;
8089    int i;
8090 
8091    if (parent->map.colors_count == 0) return NULL;
8092    colors = mem_alloc(sizeof(Edje_Map_Color *) * parent->map.colors_count);
8093 
8094    for (i = 0; i < (int)parent->map.colors_count; i++)
8095      {
8096         color = parent->map.colors[i];
8097 
8098         Edje_Map_Color *c = mem_alloc(SZ(Edje_Map_Color));
8099         if (!color)
8100           {
8101              ERR("Could not find allocated source when copying map colors");
8102              exit(-1);
8103              return NULL;
8104           }
8105         memcpy(c, color, sizeof(Edje_Map_Color));
8106         colors[i] = c;
8107      }
8108    return colors;
8109 }
8110 
8111 /** @edcsubsection{collections_group_parts_description,
8112  *                 Group.Parts.Part.Description} */
8113 
8114 /**
8115     @page edcref
8116     @block
8117         description
8118     @context
8119         description {
8120             inherit: "another_description" INDEX;
8121             state: "description_name" INDEX;
8122             visible: 1;
8123             min: 0 0;
8124             max: -1 -1;
8125             align: 0.5 0.5;
8126             fixed: 0 0;
8127             step: 0 0;
8128             aspect: 1 1;
8129             clip_to: "clip_override_part_name";
8130             no_render: 0;
8131             offset_scale: 0;
8132 
8133             rel1 {
8134                 ..
8135             }
8136 
8137             rel2 {
8138                 ..
8139             }
8140         }
8141     @description
8142         Every part can have one or more description blocks. Each description is
8143         used to define style and layout properties of a part in a given
8144         "state".
8145     @endblock
8146  */
8147 static void
ob_collections_group_parts_part_description(void)8148 ob_collections_group_parts_part_description(void)
8149 {  /* Allocate and set desc, set relative part hierarchy if needed */
8150   Edje_Part_Collection *pc;
8151   Edje_Part *ep;
8152   Edje_Part_Description_Common *ed;
8153 
8154   pc = eina_list_data_get(eina_list_last(edje_collections));
8155   ep = current_part;
8156 
8157   ed = _edje_part_description_alloc(ep->type, pc->part, ep->name);
8158   eina_hash_add(desc_hash, &ed, ep);
8159 
8160   ed->rel1.id_x = -1;
8161   ed->rel1.id_y = -1;
8162   ed->rel2.id_x = -1;
8163   ed->rel2.id_y = -1;
8164   ed->clip_to_id = -1;
8165 
8166   if (!ep->default_desc)
8167     {
8168        current_desc = ep->default_desc = ed;
8169        ed->state.name = strdup("default");
8170 
8171        {     /* Get the ptr of the part above current part in hierarchy */
8172          Edje_Part *node = edje_cc_handlers_hierarchy_parent_get();
8173          if (node) /* Make relative according to part hierarchy */
8174            edje_cc_handlers_hierarchy_set(node);
8175        }
8176     }
8177   else
8178     {
8179        ep->other.desc_count++;
8180        ep->other.desc = realloc(ep->other.desc,
8181                                 sizeof (Edje_Part_Description_Common *) * ep->other.desc_count);
8182        current_desc = ep->other.desc[ep->other.desc_count - 1] = ed;
8183     }
8184 
8185   ed->visible = 1;
8186   ed->limit = 0;
8187   ed->no_render = 0;
8188   ed->align.x = FROM_DOUBLE(0.5);
8189   ed->align.y = FROM_DOUBLE(0.5);
8190   ed->min.w = 0;
8191   ed->min.h = 0;
8192   ed->fixed.w = 0;
8193   ed->fixed.h = 0;
8194   ed->max.w = -1;
8195   ed->max.h = -1;
8196   ed->size_class = NULL;
8197   ed->rel1.relative_x = FROM_DOUBLE(0.0);
8198   ed->rel1.relative_y = FROM_DOUBLE(0.0);
8199   ed->rel1.offset_x = 0;
8200   ed->rel1.offset_y = 0;
8201   ed->rel2.relative_x = FROM_DOUBLE(1.0);
8202   ed->rel2.relative_y = FROM_DOUBLE(1.0);
8203   ed->rel2.offset_x = -1;
8204   ed->rel2.offset_y = -1;
8205   ed->color_class = NULL;
8206   ed->color.r = 255;
8207   ed->color.g = 255;
8208   ed->color.b = 255;
8209   ed->color.a = 255;
8210   ed->color2.r = 0;
8211   ed->color2.g = 0;
8212   ed->color2.b = 0;
8213   ed->color2.a = 255;
8214   ed->map.id_persp = -1;
8215   ed->map.id_light = -1;
8216   ed->map.rot.id_center = -1;
8217   ed->map.zoom.id_center = -1;
8218   ed->map.rot.x = FROM_DOUBLE(0.0);
8219   ed->map.rot.y = FROM_DOUBLE(0.0);
8220   ed->map.rot.z = FROM_DOUBLE(0.0);
8221   ed->map.on = 0;
8222   ed->map.smooth = 1;
8223   ed->map.alpha = 1;
8224   ed->map.backcull = 0;
8225   ed->map.persp_on = 0;
8226   ed->map.colors = NULL;
8227   ed->map.zoom.x = FROM_DOUBLE(1.0);
8228   ed->map.zoom.y = FROM_DOUBLE(1.0);
8229   ed->persp.zplane = 0;
8230   ed->persp.focal = 1000;
8231   ed->minmul.have = 1;
8232   ed->minmul.w = FROM_DOUBLE(1.0);
8233   ed->minmul.h = FROM_DOUBLE(1.0);
8234 }
8235 
8236 static void
ob_collections_group_parts_part_desc(void)8237 ob_collections_group_parts_part_desc(void)
8238 {
8239    stack_replace_quick("description");
8240    ob_collections_group_parts_part_description();
8241 }
8242 
8243 /**
8244     @page edcref
8245     @property
8246         inherit
8247     @parameters
8248         [another description's name] [another description's index]
8249     @effect
8250         When set, the description will inherit all the properties from the
8251         named description. The properties defined in this part will override
8252         the inherited properties, reducing the amount of necessary code for
8253         simple state changes. Note: inheritance in Edje is single level only.
8254         @since 1.14 omitting both the description name and index will inherit the default 0.0 description.
8255     @endproperty
8256  */
8257 static void
st_collections_group_parts_part_description_inherit(void)8258 st_collections_group_parts_part_description_inherit(void)
8259 {
8260    Edje_Part_Collection *pc;
8261    Edje_Part *ep, *parent_ep = NULL;
8262    Edje_Part_Description_Common *ed, *parent = NULL;
8263    Edje_Part_Image_Id *iid;
8264    char *parent_name;
8265    const char *state_name;
8266    double parent_val = 0.0, state_val;
8267 
8268    pc = eina_list_data_get(eina_list_last(edje_collections));
8269    ep = current_part;
8270    ed = current_desc;
8271 
8272    parent = parent_desc;
8273    if (parent)
8274      parent_ep = eina_hash_find(desc_hash, &parent);
8275    else
8276      {
8277         /* inherit may not be used in the default description */
8278         if (!ep->other.desc_count)
8279           {
8280              ERR("parse error %s:%i. "
8281                  "inherit may not be used in the default description",
8282                  file_in, line - 1);
8283              exit(-1);
8284           }
8285 
8286         /* find the description that we inherit from */
8287         switch (get_arg_count())
8288           {
8289            case 0:
8290              parent_name = strdup("default");
8291              break;
8292 
8293            case 2:
8294              parent_val = parse_float_range(1, 0.0, 1.0);
8295              EINA_FALLTHROUGH;
8296 
8297            case 1:
8298              parent_name = parse_str(0);
8299              break;
8300 
8301            default:
8302              ERR("parse error %s:%i. too many parameters",
8303                  file_in, line - 1);
8304              exit(-1);
8305           }
8306 
8307         if (!strcmp(parent_name, "default") && EINA_DBL_EQ(parent_val, 0.0))
8308           parent = ep->default_desc;
8309         else
8310           {
8311              Edje_Part_Description_Common *d;
8312              double min_dst = 999.0;
8313              unsigned int i;
8314 
8315              if (!strcmp(parent_name, "default"))
8316                {
8317                   parent = ep->default_desc;
8318                   min_dst = ABS(ep->default_desc->state.value - parent_val);
8319                }
8320 
8321              for (i = 0; i < ep->other.desc_count; ++i)
8322                {
8323                   d = ep->other.desc[i];
8324 
8325                   if (!strcmp(d->state.name, parent_name))
8326                     {
8327                        double dst;
8328 
8329                        dst = ABS(d->state.value - parent_val);
8330                        if (dst < min_dst)
8331                          {
8332                             parent = d;
8333                             min_dst = dst;
8334                          }
8335                     }
8336                }
8337 
8338              if (EINA_DBL_NONZERO(min_dst))
8339                {
8340                   WRN("%s:%i: couldn't find an exact match in part '%s' when looking for '%s' %lf. Falling back to nearest one '%s' %lf.",
8341                       file_in, line - 1, ep->name, parent_name, parent_val, parent ? parent->state.name : NULL, parent ? parent->state.value : 0);
8342                }
8343           }
8344 
8345         if (!parent)
8346           {
8347              ERR("parse error %s:%i. "
8348                  "cannot find referenced part %s state %s %lf",
8349                  file_in, line - 1, ep->name, parent_name, parent_val);
8350              exit(-1);
8351           }
8352 
8353         free(parent_name);
8354      }
8355    /* now do a full copy, only state info will be kept */
8356    state_name = ed->state.name;
8357    state_val = ed->state.value;
8358 
8359    *ed = *parent;
8360 
8361    ed->state.name = state_name;
8362    ed->state.value = state_val;
8363 
8364    data_queue_copied_part_lookup(pc, &parent->rel1.id_x, &ed->rel1.id_x);
8365    data_queue_copied_part_lookup(pc, &parent->rel1.id_y, &ed->rel1.id_y);
8366    data_queue_copied_part_lookup(pc, &parent->rel2.id_x, &ed->rel2.id_x);
8367    data_queue_copied_part_lookup(pc, &parent->rel2.id_y, &ed->rel2.id_y);
8368 
8369    data_queue_copied_part_lookup(pc, &parent->clip_to_id, &ed->clip_to_id);
8370 
8371    data_queue_copied_part_lookup(pc, &parent->map.id_persp, &ed->map.id_persp);
8372    data_queue_copied_part_lookup(pc, &parent->map.id_light, &ed->map.id_light);
8373    data_queue_copied_part_lookup(pc, &parent->map.rot.id_center, &ed->map.rot.id_center);
8374    data_queue_copied_part_lookup(pc, &parent->map.zoom.id_center, &ed->map.zoom.id_center);
8375 
8376    /* make sure all the allocated memory is getting copied, not just
8377     * referenced
8378     */
8379 
8380    ed->size_class = STRDUP(ed->size_class);
8381    ed->color_class = STRDUP(ed->color_class);
8382    ed->map.colors = _copied_map_colors_get(parent);
8383 
8384    if (parent_ep && (parent_ep->type != ep->type))
8385      {
8386         /* ensure parent's owner is a compatible type of part */
8387         if (((ep->type != EDJE_PART_TYPE_TEXT) && (ep->type != EDJE_PART_TYPE_TEXTBLOCK)) ||
8388             ((parent_ep->type != EDJE_PART_TYPE_TEXT) && (parent_ep->type != EDJE_PART_TYPE_TEXTBLOCK)))
8389           return;
8390      }
8391 
8392    switch (ep->type)
8393      {
8394       case EDJE_PART_TYPE_SPACER:
8395       case EDJE_PART_TYPE_RECTANGLE:
8396       case EDJE_PART_TYPE_SWALLOW:
8397       case EDJE_PART_TYPE_GROUP:
8398         /* Nothing todo, this part only have a common description. */
8399         break;
8400 
8401       case EDJE_PART_TYPE_TEXT:
8402       case EDJE_PART_TYPE_TEXTBLOCK:
8403       {
8404          Edje_Part_Description_Text *ted = (Edje_Part_Description_Text *)ed;
8405          Edje_Part_Description_Text *tparent = (Edje_Part_Description_Text *)parent;
8406 
8407          ted->text = tparent->text;
8408 
8409          ted->text.text.str = STRDUP(ted->text.text.str);
8410          ted->text.domain = STRDUP(ted->text.domain);
8411          ted->text.text_class = STRDUP(ted->text.text_class);
8412          ted->text.font.str = STRDUP(ted->text.font.str);
8413 
8414          _filter_copy(&ted->filter, &tparent->filter);
8415          data_queue_copied_part_nest_lookup(pc, &(tparent->text.id_source), &(ted->text.id_source), &ted->text.id_source_part);
8416          data_queue_copied_part_nest_lookup(pc, &(tparent->text.id_text_source), &(ted->text.id_text_source), &ted->text.id_text_source_part);
8417 
8418          break;
8419       }
8420 
8421       case EDJE_PART_TYPE_IMAGE:
8422       {
8423          Edje_Part_Description_Image *ied = (Edje_Part_Description_Image *)ed;
8424          Edje_Part_Description_Image *iparent = (Edje_Part_Description_Image *)parent;
8425          unsigned int i;
8426 
8427          ied->image = iparent->image;
8428 
8429          data_queue_image_remove(&ied->image.id, &ied->image.set);
8430          data_queue_copied_image_lookup(&iparent->image.id, &ied->image.id, &ied->image.set);
8431 
8432          ied->image.tweens = calloc(iparent->image.tweens_count,
8433                                     sizeof (Edje_Part_Image_Id *));
8434          for (i = 0; i < iparent->image.tweens_count; i++)
8435            {
8436               Edje_Part_Image_Id *iid_new;
8437 
8438               iid = iparent->image.tweens[i];
8439 
8440               iid_new = mem_alloc(SZ(Edje_Part_Image_Id));
8441               data_queue_image_remove(&ied->image.id, &ied->image.set);
8442               data_queue_copied_image_lookup(&(iid->id), &(iid_new->id), &(iid_new->set));
8443               ied->image.tweens[i] = iid_new;
8444            }
8445 
8446          _filter_copy(&ied->filter, &iparent->filter);
8447 
8448          break;
8449       }
8450 
8451       case EDJE_PART_TYPE_SNAPSHOT:
8452       {
8453          Edje_Part_Description_Snapshot *sed = (Edje_Part_Description_Snapshot *)ed;
8454          Edje_Part_Description_Snapshot *sparent = (Edje_Part_Description_Snapshot *)parent;
8455 
8456          _filter_copy(&sed->filter, &sparent->filter);
8457 
8458          break;
8459       }
8460 
8461       case EDJE_PART_TYPE_PROXY:
8462       {
8463          Edje_Part_Description_Proxy *ped = (Edje_Part_Description_Proxy *)ed;
8464          Edje_Part_Description_Proxy *pparent = (Edje_Part_Description_Proxy *)parent;
8465 
8466          data_queue_copied_part_lookup(pc, &(pparent->proxy.id), &(ped->proxy.id));
8467          ped->proxy.source_clip = pparent->proxy.source_clip;
8468          ped->proxy.source_visible = pparent->proxy.source_visible;
8469          _filter_copy(&ped->filter, &pparent->filter);
8470 
8471          break;
8472       }
8473 
8474       case EDJE_PART_TYPE_BOX:
8475       {
8476          Edje_Part_Description_Box *bed = (Edje_Part_Description_Box *)ed;
8477          Edje_Part_Description_Box *bparent = (Edje_Part_Description_Box *)parent;
8478 
8479          bed->box = bparent->box;
8480 
8481          break;
8482       }
8483 
8484       case EDJE_PART_TYPE_TABLE:
8485       {
8486          Edje_Part_Description_Table *ted = (Edje_Part_Description_Table *)ed;
8487          Edje_Part_Description_Table *tparent = (Edje_Part_Description_Table *)parent;
8488 
8489          ted->table = tparent->table;
8490 
8491          break;
8492       }
8493 
8494       case EDJE_PART_TYPE_EXTERNAL:
8495       {
8496          Edje_Part_Description_External *eed = (Edje_Part_Description_External *)ed;
8497          Edje_Part_Description_External *eparent = (Edje_Part_Description_External *)parent;
8498 
8499          if (eparent->external_params)
8500            {
8501               Eina_List *l;
8502               Edje_External_Param *param, *new_param;
8503 
8504               eed->external_params = NULL;
8505               EINA_LIST_FOREACH(eparent->external_params, l, param)
8506                 {
8507                    new_param = mem_alloc(SZ(Edje_External_Param));
8508                    *new_param = *param;
8509                    eed->external_params = eina_list_append(eed->external_params, new_param);
8510                 }
8511            }
8512          break;
8513       }
8514 
8515       case EDJE_PART_TYPE_VECTOR:
8516       {
8517          Edje_Part_Description_Vector *ied = (Edje_Part_Description_Vector *)ed;
8518          Edje_Part_Description_Vector *iparent = (Edje_Part_Description_Vector *)parent;
8519          ied->vg.set = iparent->vg.set;
8520          ied->vg.id = iparent->vg.id;
8521          ied->vg.type = iparent->vg.type;
8522          ied->vg.frame = iparent->vg.frame;
8523          break;
8524       }
8525      }
8526 }
8527 
8528 /**
8529     @page edcref
8530 
8531     @property
8532         source
8533     @parameters
8534         [another part's name]
8535     @effect
8536         Causes the part to use another part content as the content of this part.
8537         Only work with PROXY part.
8538     @endproperty
8539  */
8540 static void
st_collections_group_parts_part_description_source(void)8541 st_collections_group_parts_part_description_source(void)
8542 {
8543    Edje_Part_Collection *pc;
8544    Edje_Part_Description_Proxy *ed;
8545    char *name;
8546 
8547    check_arg_count(1);
8548 
8549    pc = eina_list_data_get(eina_list_last(edje_collections));
8550 
8551    if (current_part->type != EDJE_PART_TYPE_PROXY)
8552      {
8553         ERR("parse error %s:%i. source attributes in non-PROXY part.",
8554             file_in, line - 1);
8555         exit(-1);
8556      }
8557 
8558    ed = (Edje_Part_Description_Proxy *)current_desc;
8559 
8560    name = parse_str(0);
8561 
8562    data_queue_part_lookup(pc, name, &(ed->proxy.id));
8563    free(name);
8564 }
8565 
8566 static void
_part_description_state_update(Edje_Part_Description_Common * ed)8567 _part_description_state_update(Edje_Part_Description_Common *ed)
8568 {
8569    Edje_Part *ep = current_part;
8570 
8571    if (ed == ep->default_desc) return;
8572    if ((ep->default_desc->state.name && !strcmp(ed->state.name, ep->default_desc->state.name) && EINA_DBL_EQ(ed->state.value, ep->default_desc->state.value)) ||
8573        (!ep->default_desc->state.name && !strcmp(ed->state.name, "default") && EINA_DBL_EQ(ed->state.value, ep->default_desc->state.value)))
8574      {
8575         if (ep->type == EDJE_PART_TYPE_IMAGE)
8576           _edje_part_description_image_remove((Edje_Part_Description_Image *)ed);
8577 
8578         free(ed);
8579         ep->other.desc_count--;
8580         ep->other.desc = realloc(ep->other.desc,
8581                                  sizeof (Edje_Part_Description_Common *) * ep->other.desc_count);
8582         current_desc = ep->default_desc;
8583      }
8584    else if (ep->other.desc_count)
8585      {
8586         unsigned int i;
8587         for (i = 0; i < ep->other.desc_count - 1; ++i)
8588           {
8589              if (!strcmp(ed->state.name, ep->other.desc[i]->state.name) && EINA_DBL_EQ(ed->state.value, ep->other.desc[i]->state.value))
8590                {
8591                   if (ep->type == EDJE_PART_TYPE_IMAGE)
8592                     _edje_part_description_image_remove((Edje_Part_Description_Image *)ed);
8593 
8594                   free(ed);
8595                   ep->other.desc_count--;
8596                   ep->other.desc = realloc(ep->other.desc,
8597                                            sizeof (Edje_Part_Description_Common *) * ep->other.desc_count);
8598                   current_desc = ep->other.desc[i];
8599                   break;
8600                }
8601           }
8602      }
8603 }
8604 
8605 /**
8606     @page edcref
8607     @property
8608         state
8609     @parameters
8610         [name for the description] [index]
8611     @effect
8612         Sets a name used to identify a description inside a given part.
8613         Multiple descriptions are used to declare different states of the same
8614         part, like "clicked" or "invisible". All states declarations are also
8615         coupled with an index number between 0.0 and 1.0.
8616         First description in part must always be "default" 0.0.
8617 
8618         @warning state name "custom" is reserved and can't be used in edc.
8619 
8620         Defaults: "default" 0.0
8621     @endproperty
8622  */
8623 static void
st_collections_group_parts_part_description_state(void)8624 st_collections_group_parts_part_description_state(void)
8625 {
8626    Edje_Part *ep;
8627    Edje_Part_Description_Common *ed;
8628    char *s;
8629    double val;
8630 
8631    check_min_arg_count(1);
8632 
8633    ep = current_part;
8634 
8635    s = parse_str(0);
8636    if (!strcmp(s, "custom"))
8637      {
8638         ERR("parse error %s:%i. invalid state name: '%s'.",
8639             file_in, line - 1, s);
8640         exit(-1);
8641      }
8642    if (get_arg_count() == 1)
8643      val = 0.0;
8644    else
8645      val = parse_float_range(1, 0.0, 1.0);
8646 
8647    /* if only default desc exists and current desc is not default, commence paddling */
8648    if ((!ep->other.desc_count) && (EINA_DBL_NONZERO(val) || (!eina_streq(s, "default"))))
8649      {
8650         ERR("parse error %s:%i. invalid state name: '%s'. \"default\" state must always be first.",
8651             file_in, line - 1, s);
8652         exit(-1);
8653      }
8654    ed = ep->default_desc;
8655    if (ep->other.desc_count) ed = ep->other.desc[ep->other.desc_count - 1];
8656 
8657    free((void *)ed->state.name);
8658    ed->state.name = s;
8659    ed->state.value = val;
8660 
8661    _part_description_state_update(ed);
8662 }
8663 
8664 /**
8665     @page edcref
8666     @property
8667         visible
8668     @parameters
8669         [0 or 1]
8670     @effect
8671         Takes a boolean value specifying whether part is visible (1) or not
8672         (0). Non-visible parts do not emit signals.
8673 
8674         Defaults: 1
8675     @endproperty
8676  */
8677 static void
st_collections_group_parts_part_description_visible(void)8678 st_collections_group_parts_part_description_visible(void)
8679 {
8680    check_arg_count(1);
8681 
8682    if (current_part->type == EDJE_PART_TYPE_SPACER)
8683      {
8684         ERR("parse error %s:%i. SPACER part can't have a visibility defined",
8685             file_in, line - 1);
8686         exit(-1);
8687      }
8688 
8689    current_desc->visible = parse_bool(0);
8690 }
8691 
8692 static void
st_collections_group_parts_part_description_vis(void)8693 st_collections_group_parts_part_description_vis(void)
8694 {
8695    check_arg_count(0);
8696 
8697    if (current_part->type == EDJE_PART_TYPE_SPACER)
8698      {
8699         ERR("parse error %s:%i. SPACER part can't have a visibility defined",
8700             file_in, line - 1);
8701         exit(-1);
8702      }
8703 
8704    current_desc->visible = 1;
8705 }
8706 
8707 static void
st_collections_group_parts_part_description_hid(void)8708 st_collections_group_parts_part_description_hid(void)
8709 {
8710    check_arg_count(0);
8711 
8712    if (current_part->type == EDJE_PART_TYPE_SPACER)
8713      {
8714         ERR("parse error %s:%i. SPACER part can't have a visibility defined",
8715             file_in, line - 1);
8716         exit(-1);
8717      }
8718 
8719    current_desc->visible = 0;
8720 }
8721 
8722 /**
8723     @page edcref
8724     @property
8725         no_render
8726     @parameters
8727         [0 or 1]
8728     @effect
8729         Same as setting no_render in part, but can be changed in different states.
8730 
8731         Defaults: 0
8732     @since 1.19
8733     @endproperty
8734  */
8735 static void
st_collections_group_parts_part_description_no_render(void)8736 st_collections_group_parts_part_description_no_render(void)
8737 {
8738    if (current_part->type == EDJE_PART_TYPE_SPACER)
8739      {
8740         ERR("parse error %s:%i. SPACER part can't be marked as no_render",
8741             file_in, line - 1);
8742         exit(-1);
8743      }
8744 
8745    if (check_range_arg_count(0, 1) == 1)
8746      EDJE_DESC_NO_RENDER_SET(current_desc, parse_bool(0));
8747    else /* lazEDC form */
8748      EDJE_DESC_NO_RENDER_SET(current_desc, 1);
8749 }
8750 
8751 /**
8752     @page edcref
8753     @property
8754         limit
8755     @parameters
8756         [mode]
8757     @effect
8758         Emit a signal when the part size change from zero or to a zero size
8759         ('limit,width,over', 'limit,width,zero'). By default no signal are
8760         emitted. Valid values are:
8761         @li NONE
8762         @li WIDTH
8763         @li HEIGHT
8764         @li BOTH
8765 
8766         Defaults: NONE
8767     @since 1.7
8768     @endproperty
8769  */
8770 static void
st_collections_group_parts_part_description_limit(void)8771 st_collections_group_parts_part_description_limit(void)
8772 {
8773    check_arg_count(1);
8774 
8775    current_desc->limit = parse_enum(0,
8776                                     "NONE", 0,
8777                                     "WIDTH", 1,
8778                                     "HEIGHT", 2,
8779                                     "BOTH", 3);
8780 
8781    if (current_desc->limit)
8782      {
8783         Edje_Part_Collection *pc;
8784         int count;
8785 
8786         pc = eina_list_data_get(eina_list_last(edje_collections));
8787         count = pc->limits.parts_count++;
8788         pc->limits.parts = realloc(pc->limits.parts,
8789                                    pc->limits.parts_count * sizeof (Edje_Part_Limit));
8790         data_queue_part_reallocated_lookup(pc, current_part->name,
8791                                            (unsigned char **)&(pc->limits.parts),
8792                                            (unsigned char *)&pc->limits.parts[count].part - (unsigned char *)pc->limits.parts); //fixme
8793      }
8794 }
8795 
8796 /**
8797     @page edcref
8798     @property
8799         align
8800     @parameters
8801         [X axis] [Y axis]
8802     @effect
8803         When the displayed object's size is smaller (or bigger) than
8804         its container, this property moves it relatively along both
8805         axis inside its container. @c "0.0" means left/top edges of
8806         the object touching container's respective ones, while @c
8807         "1.0" stands for right/bottom edges of the object (on
8808         horizontal/vertical axis, respectively).
8809 
8810         Defaults: 0.5 0.5
8811     @endproperty
8812  */
8813 static void
st_collections_group_parts_part_description_align(void)8814 st_collections_group_parts_part_description_align(void)
8815 {
8816    check_has_anchors();
8817    check_arg_count(2);
8818 
8819    current_desc->align.x = FROM_DOUBLE(parse_float_range(0, 0.0, 1.0));
8820    current_desc->align.y = FROM_DOUBLE(parse_float_range(1, 0.0, 1.0));
8821 }
8822 
8823 /**
8824     @page edcref
8825     @property
8826         fixed
8827     @parameters
8828         [width, 0 or 1] [height, 0 or 1]
8829     @effect
8830         This affects the minimum size calculation. See
8831         edje_object_size_min_calc() and edje_object_size_min_restricted_calc().
8832         This tells the min size calculation routine that this part does not
8833         change group size in width or height (1 for it doesn't, 0 for it does),
8834         so the routine should not try and expand or contract the group.
8835 
8836         Defaults: 0 0
8837     @endproperty
8838  */
8839 static void
st_collections_group_parts_part_description_fixed(void)8840 st_collections_group_parts_part_description_fixed(void)
8841 {
8842    check_has_anchors();
8843    check_arg_count(2);
8844 
8845    current_desc->fixed.w = parse_bool(0);
8846    current_desc->fixed.h = parse_bool(1);
8847 
8848    current_desc->user_set.fixed = EINA_TRUE;
8849 }
8850 
8851 /**
8852     @page edcref
8853     @property
8854         min
8855     @parameters
8856         [width] [height] or SOURCE
8857     @effect
8858         The minimum size of the state.
8859 
8860         When min is defined to SOURCE, it will look at the original
8861         image size and enforce it minimal size to match at least the
8862         original one. The part must be an IMAGE or a GROUP part.
8863 
8864         Defaults: 0 0
8865     @endproperty
8866  */
8867 static void
st_collections_group_parts_part_description_min(void)8868 st_collections_group_parts_part_description_min(void)
8869 {
8870    check_min_arg_count(1);
8871 
8872    if (is_param(1))
8873      {
8874         current_desc->min.w = parse_int_range(0, 0, 0x7fffffff);
8875         current_desc->min.h = parse_int_range(1, 0, 0x7fffffff);
8876      }
8877    else
8878      {
8879         char *tmp;
8880 
8881         tmp = parse_str(0);
8882         if ((current_part->type != EDJE_PART_TYPE_IMAGE && current_part->type != EDJE_PART_TYPE_GROUP) ||
8883             !tmp || strcmp(tmp, "SOURCE") != 0)
8884           {
8885              free(tmp);
8886              ERR("parse error %s:%i. "
8887                  "Only IMAGE and GROUP part can have a min: SOURCE; defined",
8888                  file_in, line - 1);
8889              exit(-1);
8890           }
8891         free(tmp);
8892 
8893         current_desc->min.limit = EINA_TRUE;
8894      }
8895 }
8896 
8897 /**
8898     @page edcref
8899     @property
8900         minmul
8901     @parameters
8902         [width multiplier] [height multiplier]
8903     @effect
8904         A multiplier FORCIBLY applied to whatever minimum size is only during
8905         minimum size calculation.
8906 
8907         Defaults: 1.0 1.0
8908     @since 1.2
8909     @endproperty
8910  */
8911 static void
st_collections_group_parts_part_description_minmul(void)8912 st_collections_group_parts_part_description_minmul(void)
8913 {
8914    check_arg_count(2);
8915 
8916    current_desc->minmul.w = FROM_DOUBLE(parse_float_range(0, 0, 999999));
8917    current_desc->minmul.h = FROM_DOUBLE(parse_float_range(1, 0, 999999));
8918 }
8919 
8920 /**
8921     @page edcref
8922     @property
8923         max
8924     @parameters
8925         [width] [height] or SOURCE
8926     @effect
8927         The maximum size of the state. A size of -1 means that it will be ignored in one direction.
8928 
8929         When max is set to SOURCE, edje will enforce the part to be
8930         not more than the original image size. The part must be an
8931         IMAGE part.
8932 
8933         Defaults: -1 -1
8934     @endproperty
8935  */
8936 static void
st_collections_group_parts_part_description_max(void)8937 st_collections_group_parts_part_description_max(void)
8938 {
8939    check_min_arg_count(1);
8940 
8941    if (is_param(1))
8942      {
8943         current_desc->max.w = parse_int_range(0, -1, 0x7fffffff);
8944         current_desc->max.h = parse_int_range(1, -1, 0x7fffffff);
8945      }
8946    else
8947      {
8948         char *tmp;
8949 
8950         tmp = parse_str(0);
8951         if (current_part->type != EDJE_PART_TYPE_IMAGE ||
8952             !tmp || strcmp(tmp, "SOURCE") != 0)
8953           {
8954              free(tmp);
8955              ERR("parse error %s:%i. "
8956                  "Only IMAGE part can have a max: SOURCE; defined",
8957                  file_in, line - 1);
8958              exit(-1);
8959           }
8960         free(tmp);
8961 
8962         current_desc->max.limit = EINA_TRUE;
8963      }
8964 }
8965 
8966 /**
8967    @page edcref
8968    @property
8969       size_class
8970    @parameters
8971       [size class name]
8972    @effect
8973       The part will have the min and max size defined in the size class.
8974       "min" and "max" property in description can be overridden by the size class
8975       at runtime.
8976    @endproperty
8977  */
8978 static void
st_collections_group_parts_part_description_size_class(void)8979 st_collections_group_parts_part_description_size_class(void)
8980 {
8981    check_arg_count(1);
8982 
8983    current_desc->size_class = parse_str(0);
8984 }
8985 
8986 /**
8987     @page edcref
8988     @property
8989         step
8990     @parameters
8991         [width] [height]
8992     @effect
8993         Restricts resizing of each dimension to values divisible by its value.
8994         This causes the part to jump from value to value while resizing. The
8995         default value is "0 0" disabling stepping.
8996 
8997         Defaults: 0.0 0.0
8998     @endproperty
8999  */
9000 static void
st_collections_group_parts_part_description_step(void)9001 st_collections_group_parts_part_description_step(void)
9002 {
9003    check_arg_count(2);
9004 
9005    current_desc->step.x = parse_float_range(0, 0, 0x7fffffff);
9006    current_desc->step.y = parse_float_range(1, 0, 0x7fffffff);
9007 }
9008 
9009 /**
9010     @page edcref
9011     @property
9012         aspect
9013     @parameters
9014         [min] [max]
9015     @effect
9016         Normally width and height can be resized to any values independently.
9017         The aspect property forces the width to height ratio to be kept between
9018         the minimum and maximum set. For example, "1.0 1.0" will increase the
9019         width a pixel for every pixel added to height. The default value is
9020         "0.0 0.0" disabling aspect.
9021 
9022         Defaults: 0.0 0.0
9023     @endproperty
9024  */
9025 static void
st_collections_group_parts_part_description_aspect(void)9026 st_collections_group_parts_part_description_aspect(void)
9027 {
9028    check_arg_count(2);
9029 
9030    current_desc->aspect.min = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
9031    current_desc->aspect.max = FROM_DOUBLE(parse_float_range(1, 0.0, 999999999.0));
9032 }
9033 
9034 /**
9035     @page edcref
9036     @property
9037         aspect_preference
9038     @parameters
9039         [DIMENSION]
9040     @effect
9041         Sets the scope of the "aspect" property to a given dimension. Available
9042         options are BOTH, VERTICAL, HORIZONTAL, SOURCE and NONE
9043 
9044         Defaults: NONE
9045     @endproperty
9046  */
9047 static void
st_collections_group_parts_part_description_aspect_preference(void)9048 st_collections_group_parts_part_description_aspect_preference(void)
9049 {
9050    check_arg_count(1);
9051 
9052    current_desc->aspect.prefer = parse_enum(0,
9053                                             "NONE", EDJE_ASPECT_PREFER_NONE,
9054                                             "VERTICAL", EDJE_ASPECT_PREFER_VERTICAL,
9055                                             "HORIZONTAL", EDJE_ASPECT_PREFER_HORIZONTAL,
9056                                             "BOTH", EDJE_ASPECT_PREFER_BOTH,
9057                                             "SOURCE", EDJE_ASPECT_PREFER_SOURCE,
9058                                             NULL);
9059 }
9060 
9061 /**
9062     @page edcref
9063     @property
9064         color_class
9065     @parameters
9066         [color class name]
9067     @effect
9068         The part will use the color values of the named color_class, these
9069         values can be modified by the "color", "color2" and "color3"
9070         properties set below.
9071     @endproperty
9072  */
9073 static void
st_collections_group_parts_part_description_color_class(void)9074 st_collections_group_parts_part_description_color_class(void)
9075 {
9076    check_arg_count(1);
9077 
9078    if (current_part->type == EDJE_PART_TYPE_SPACER)
9079      {
9080         ERR("parse error %s:%i. SPACER part can't have a color defined",
9081             file_in, line - 1);
9082         exit(-1);
9083      }
9084 
9085    current_desc->color_class = parse_str(0);
9086 }
9087 
9088 /**
9089     @page edcref
9090     @property
9091         color
9092     @parameters
9093         [red] [green] [blue] [alpha] or "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
9094     @effect
9095         Sets the main color.
9096 
9097         Format:
9098         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
9099         RGBA channel, i.e. 255 0 0 255
9100         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
9101         i.e "#FF0000FF" or "#FF0000"
9102         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
9103         i.e "#F00F" or "#F00".\n
9104         In string format you can omit alpha channel and it will be set to FF.
9105 
9106         If color_class is set resulting color channel values will be (color * color_class / 255)
9107 
9108         Defaults: 255 255 255 255
9109     @endproperty
9110  */
9111 static void
st_collections_group_parts_part_description_color(void)9112 st_collections_group_parts_part_description_color(void)
9113 {
9114    if (current_part->type == EDJE_PART_TYPE_SPACER)
9115      {
9116         ERR("parse error %s:%i. SPACER part can't have a color defined",
9117             file_in, line - 1);
9118         exit(-1);
9119      }
9120 
9121    parse_color(0, &(current_desc->color.r));
9122 }
9123 
9124 /**
9125     @page edcref
9126     @property
9127         color2
9128     @parameters
9129         [red] [green] [blue] [alpha] or "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
9130     @effect
9131         Sets the text outline color.
9132 
9133         Format:
9134         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
9135         RGBA channel, i.e. 255 0 0 255
9136         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
9137         i.e "#FF0000FF" or "#FF0000"
9138         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
9139         i.e "#F00F" or "#F00".\n
9140         In string format you can omit alpha channel and it will be set to FF.
9141 
9142         If color_class is set resulting color channel values will be (color * color_class / 255)
9143 
9144         Defaults: 0 0 0 255
9145     @endproperty
9146  */
9147 static void
st_collections_group_parts_part_description_color2(void)9148 st_collections_group_parts_part_description_color2(void)
9149 {
9150    if (current_part->type == EDJE_PART_TYPE_SPACER)
9151      {
9152         ERR("parse error %s:%i. SPACER part can't have a color defined",
9153             file_in, line - 1);
9154         exit(-1);
9155      }
9156 
9157    parse_color(0, &(current_desc->color2.r));
9158 }
9159 
9160 /**
9161     @page edcref
9162     @property
9163         color3
9164     @parameters
9165         [red] [green] [blue] [alpha] or "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
9166     @effect
9167         Sets the text shadow color.
9168 
9169         Format:
9170         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
9171         RGBA channel, i.e. 255 0 0 255
9172         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
9173         i.e "#FF0000FF" or "#FF0000"
9174         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
9175         i.e "#F00F" or "#F00".\n
9176         In string format you can omit alpha channel and it will be set to FF.
9177 
9178         If color_class is set resulting color channel values will be (color * color_class / 255)
9179 
9180         Defaults: 0 0 0 128
9181     @endproperty
9182  */
9183 static void
st_collections_group_parts_part_description_color3(void)9184 st_collections_group_parts_part_description_color3(void)
9185 {
9186    Edje_Part_Collection *pc;
9187    Edje_Part_Description_Text *ed;
9188 
9189    pc = eina_list_data_get(eina_list_last(edje_collections));
9190 
9191    if (current_part->type != EDJE_PART_TYPE_TEXT
9192        && current_part->type != EDJE_PART_TYPE_TEXTBLOCK)
9193      {
9194         ERR("Setting color3 in part %s from %s not of type TEXT or TEXTBLOCK.",
9195             current_part->name, pc->part);
9196         exit(-1);
9197      }
9198 
9199    ed = (Edje_Part_Description_Text *)current_desc;
9200 
9201    parse_color(0, &(ed->text.color3.r));
9202 }
9203 
9204 /**
9205     @page edcref
9206     @property
9207         clip_to
9208     @parameters
9209         [another part's name]
9210     @effect
9211         Overrides the 'clip_to' property of this part. This allows switching
9212         clippers (or masks) at runtime by changing this part's state. When
9213         transitioning between two states, the switch of the clipper shall
9214         happen at the end of the animation, when the new state is finally set
9215         (this is similar to the 'visible' flag).
9216     @endproperty
9217  */
9218 static void
st_collections_group_parts_part_description_clip_to_id(void)9219 st_collections_group_parts_part_description_clip_to_id(void)
9220 {
9221    Edje_Part_Collection *pc;
9222 
9223    check_arg_count(1);
9224 
9225    pc = eina_list_data_get(eina_list_last(edje_collections));
9226    {
9227       char *name;
9228 
9229       name = parse_str(0);
9230       data_queue_part_lookup(pc, name, &(current_desc->clip_to_id));
9231       free(name);
9232    }
9233 }
9234 
9235 /**
9236     @page edcref
9237     @property
9238         offset_scale
9239     @parameters
9240         [1 or 0]
9241     @effect
9242         Makes rel1/2 offset values scale by scale factor like min/max if set
9243         to 1, otherwise 0 means they will not scale. Note that the part
9244         as a whole has to be set to scale too like:
9245 
9246             part { name: "partname"; scale: 1;
9247             ...
9248 
9249         Defaults: 0
9250     @endproperty
9251  */
9252 static void
st_collections_group_parts_part_description_offset_scale(void)9253 st_collections_group_parts_part_description_offset_scale(void)
9254 {
9255    if (get_arg_count() == 1)
9256      current_desc->offset_is_scaled = parse_bool(0);
9257    else
9258      current_desc->offset_is_scaled = EINA_TRUE;
9259 }
9260 
9261 /** @edcsubsection{collections_group_parts_description_relatives,
9262  *                 Group.Parts.Part.Description.Relatives (rel1/rel2)} */
9263 
9264 /**
9265     @page edcref
9266     @block
9267         rel1/rel2/rel
9268     @context
9269         description {
9270             ..
9271             rel1 {
9272                 relative: 0.0 0.0;
9273                 offset:     0   0;
9274             }
9275             ..
9276             rel2 {
9277                 relative: 1.0 1.0;
9278                 offset:    -1  -1;
9279             }
9280             ..
9281             rel {
9282                 to: "somepart";
9283             }
9284             ..
9285         }
9286     @description
9287         The rel1 and rel2 blocks are used to define the position of each corner
9288         of the part's container. With rel1 being the left-up corner and rel2
9289         being the right-down corner; rel (no number) is equivalent to setting both
9290         rel1 AND rel2 since 1.14.
9291     @endblock
9292 
9293     @property
9294         relative
9295     @parameters
9296         [X axis] [Y axis]
9297     @effect
9298         Moves a corner to a relative position inside the container of the
9299         relative "to" part. Values from 0.0 (0%, beginning) to 1.0 (100%, end)
9300         of each axis.
9301 
9302         Defaults:
9303         @li rel1.relative: 0.0 0.0
9304         @li rel2.relative: 1.0 1.0
9305     @endproperty
9306  */
9307 static void
st_collections_group_parts_part_description_rel1_relative(void)9308 st_collections_group_parts_part_description_rel1_relative(void)
9309 {
9310    check_has_anchors();
9311    check_arg_count(2);
9312 
9313    current_desc->rel1.relative_x = FROM_DOUBLE(parse_float(0));
9314    current_desc->rel1.relative_y = FROM_DOUBLE(parse_float(1));
9315 }
9316 
9317 /**
9318     @page edcref
9319     @property
9320         offset
9321     @parameters
9322         [X axis] [Y axis]
9323     @effect
9324         Affects the corner position a fixed number of pixels along each axis.
9325 
9326         Defaults:
9327         @li rel1.offset: 0 0
9328         @li rel2.offset: -1 -1
9329     @endproperty
9330  */
9331 static void
st_collections_group_parts_part_description_rel1_offset(void)9332 st_collections_group_parts_part_description_rel1_offset(void)
9333 {
9334    check_has_anchors();
9335    check_arg_count(2);
9336 
9337    current_desc->rel1.offset_x = parse_int(0);
9338    current_desc->rel1.offset_y = parse_int(1);
9339 }
9340 
9341 /**
9342     @page edcref
9343     @property
9344         to
9345     @parameters
9346         [another part's name]
9347     @effect
9348         Causes a corner to be positioned relatively to another part's
9349         container. Setting to "" will unset this value for inherited
9350         parts.
9351     @endproperty
9352  */
9353 static void
st_collections_group_parts_part_description_rel1_to_set(const char * name)9354 st_collections_group_parts_part_description_rel1_to_set(const char *name)
9355 {
9356    Edje_Part_Collection *pc;
9357    pc = eina_list_data_get(eina_list_last(edje_collections));
9358    data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
9359    data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
9360 }
9361 
9362 static void
st_collections_group_parts_part_description_rel_to(void)9363 st_collections_group_parts_part_description_rel_to(void)
9364 {
9365    check_has_anchors();
9366    check_arg_count(1);
9367 
9368    {
9369       char *name;
9370       name = parse_str(0);
9371       st_collections_group_parts_part_description_rel1_to_set(name);
9372       st_collections_group_parts_part_description_rel2_to_set(name);
9373       free(name);
9374    }
9375 }
9376 
9377 static void
st_collections_group_parts_part_description_rel1_to(void)9378 st_collections_group_parts_part_description_rel1_to(void)
9379 {
9380    check_has_anchors();
9381    check_arg_count(1);
9382 
9383    {
9384       char *name;
9385       name = parse_str(0);
9386       st_collections_group_parts_part_description_rel1_to_set(name);
9387       free(name);
9388    }
9389 }
9390 
9391 /**
9392     @page edcref
9393     @property
9394         to_x
9395     @parameters
9396         [another part's name]
9397     @effect
9398         Causes a corner to be positioned relatively to the X axis of another
9399         part's container. Simply put affects the first parameter of "relative".
9400         Setting to "" will unset this value for inherited parts.
9401     @endproperty
9402  */
9403 static void
st_collections_group_parts_part_description_rel_to_x(void)9404 st_collections_group_parts_part_description_rel_to_x(void)
9405 {
9406    Edje_Part_Collection *pc;
9407 
9408    check_has_anchors();
9409    check_arg_count(1);
9410 
9411    pc = eina_list_data_get(eina_list_last(edje_collections));
9412 
9413    {
9414       char *name;
9415 
9416       name = parse_str(0);
9417       data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
9418       data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
9419       free(name);
9420    }
9421 }
9422 
9423 static void
st_collections_group_parts_part_description_rel1_to_x(void)9424 st_collections_group_parts_part_description_rel1_to_x(void)
9425 {
9426    Edje_Part_Collection *pc;
9427 
9428    check_has_anchors();
9429    check_arg_count(1);
9430 
9431    pc = eina_list_data_get(eina_list_last(edje_collections));
9432 
9433    {
9434       char *name;
9435 
9436       name = parse_str(0);
9437       data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
9438       free(name);
9439    }
9440 }
9441 
9442 /**
9443     @page edcref
9444     @property
9445         to_y
9446     @parameters
9447         [another part's name]
9448     @effect
9449         Causes a corner to be positioned relatively to the Y axis of another
9450         part's container. Simply put, affects the second parameter of
9451         "relative". Setting to "" will unset this value for inherited parts.
9452     @endproperty
9453  */
9454 static void
st_collections_group_parts_part_description_rel_to_y(void)9455 st_collections_group_parts_part_description_rel_to_y(void)
9456 {
9457    Edje_Part_Collection *pc;
9458 
9459    check_has_anchors();
9460    check_arg_count(1);
9461 
9462    pc = eina_list_data_get(eina_list_last(edje_collections));
9463 
9464    {
9465       char *name;
9466 
9467       name = parse_str(0);
9468       data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
9469       data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
9470       free(name);
9471    }
9472 }
9473 
9474 static void
st_collections_group_parts_part_description_rel1_to_y(void)9475 st_collections_group_parts_part_description_rel1_to_y(void)
9476 {
9477    Edje_Part_Collection *pc;
9478 
9479    check_has_anchors();
9480    check_arg_count(1);
9481 
9482    pc = eina_list_data_get(eina_list_last(edje_collections));
9483 
9484    {
9485       char *name;
9486 
9487       name = parse_str(0);
9488       data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
9489       free(name);
9490    }
9491 }
9492 
9493 static void
st_collections_group_parts_part_description_rel2_relative(void)9494 st_collections_group_parts_part_description_rel2_relative(void)
9495 {
9496    check_has_anchors();
9497    check_arg_count(2);
9498 
9499    current_desc->rel2.relative_x = FROM_DOUBLE(parse_float(0));
9500    current_desc->rel2.relative_y = FROM_DOUBLE(parse_float(1));
9501 }
9502 
9503 static void
st_collections_group_parts_part_description_rel2_offset(void)9504 st_collections_group_parts_part_description_rel2_offset(void)
9505 {
9506    check_has_anchors();
9507    check_arg_count(2);
9508 
9509    current_desc->rel2.offset_x = parse_int(0);
9510    current_desc->rel2.offset_y = parse_int(1);
9511 }
9512 
9513 static void
st_collections_group_parts_part_description_rel2_to_set(const char * name)9514 st_collections_group_parts_part_description_rel2_to_set(const char *name)
9515 {
9516    Edje_Part_Collection *pc;
9517    pc = eina_list_data_get(eina_list_last(edje_collections));
9518    data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
9519    data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
9520 }
9521 
9522 static void
st_collections_group_parts_part_description_rel2_to(void)9523 st_collections_group_parts_part_description_rel2_to(void)
9524 {
9525    check_has_anchors();
9526    check_arg_count(1);
9527 
9528    {
9529       char *name;
9530       name = parse_str(0);
9531       st_collections_group_parts_part_description_rel2_to_set(name);
9532       free(name);
9533    }
9534 }
9535 
9536 static void
st_collections_group_parts_part_description_rel2_to_x(void)9537 st_collections_group_parts_part_description_rel2_to_x(void)
9538 {
9539    Edje_Part_Collection *pc;
9540 
9541    check_has_anchors();
9542    check_arg_count(1);
9543 
9544    pc = eina_list_data_get(eina_list_last(edje_collections));
9545 
9546    {
9547       char *name;
9548 
9549       name = parse_str(0);
9550       data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
9551       free(name);
9552    }
9553 }
9554 
9555 static void
st_collections_group_parts_part_description_rel2_to_y(void)9556 st_collections_group_parts_part_description_rel2_to_y(void)
9557 {
9558    Edje_Part_Collection *pc;
9559 
9560    check_has_anchors();
9561    check_arg_count(1);
9562 
9563    pc = eina_list_data_get(eina_list_last(edje_collections));
9564 
9565    {
9566       char *name;
9567 
9568       name = parse_str(0);
9569       data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
9570       free(name);
9571    }
9572 }
9573 
9574 /** @edcsubsection{collections_group_parts_description_anchors,
9575  *                 Group.Parts.Part.Description.Anchors} */
9576 
9577 /**
9578     @page edcref
9579     @block
9580         anchors
9581     @context
9582         // This part will be expanded from the top-left corner of edje group
9583         part { name : "part1";
9584             description { state: "default" 0.0;
9585                 anchors {
9586                     top: GROUP TOP;
9587                     left: GROUP; // This means 'left: GROUP LEFT;'
9588                 }
9589                 min: 50 50;
9590             }
9591         }
9592         // This part will be expanded from the bottom-right corner of "part1"
9593         // to the bottom-right
9594         part { name: "part2";
9595             description { state: "default" 0.0;
9596                 anchors {
9597                     top: "part1" BOTTOM;
9598                     left: "part1"; // This means 'left: "part1" RIGHT;'
9599                 }
9600                 min: 50 50;
9601             }
9602         }
9603         // This part will be expanded from the right edje of "part2" to the right
9604         part { name: "part3";
9605             description { state: "default" 0.0;
9606                 anchors {
9607                     left: "part2";
9608                     fill: "part2" VERTICAL;
9609                 }
9610                 min: 100 0; // The height will be determined by the height of "part2"
9611             }
9612         }
9613         // This part will be expanded from the center of right edge of "part3"
9614         // to the bottom-right corner of edje group
9615         part { name: "part4";
9616             description { state: "default" 0.0;
9617                 anchors {
9618                     top: "part3" VERTICAL_CENTER;
9619                     left: "part3";
9620                     right: GROUP;
9621                     bottom: GROUP;
9622                 }
9623             }
9624         }
9625     @description
9626         The anchors blocks are used to define the position of each edge of
9627         the part's container. Anchors will change relative, align and fixed
9628         attributes internally, so setting both of them is not allowed.
9629         When the second parameter of position enumeration is omitted, anchoring
9630         a part to the other part will put the part adjacent to the given part.
9631         However, if the part is anchored to edje group, the part will be contained
9632         inside the group.
9633     @endblock
9634 
9635     @property
9636         anchors
9637     @parameters
9638         [partname] [the edge of other part]
9639     @effect
9640         Moves an edge of the part to the position of the edge of given part or
9641         whole edje group. (GROUP means edje group that the part belong to)
9642     @endproperty
9643  */
9644 
9645 static void
check_has_anchors(void)9646 check_has_anchors(void)
9647 {
9648    if (current_anchors)
9649      {
9650         ERR("parse error %s:%i. Anchors and Relatives(rel/align/fixed) cannot be used at the same time.",
9651             file_in, line - 1);
9652         exit(-1);
9653      }
9654 
9655    has_relatives = EINA_TRUE;
9656 }
9657 
9658 static void
check_has_relatives(void)9659 check_has_relatives(void)
9660 {
9661    if (!beta)
9662      error_and_abort(NULL, "Anchors are currently a beta feature, please enable them by running edje_cc with -beta.");
9663 
9664    if (has_relatives)
9665      {
9666         ERR("parse error %s:%i. Anchors and Relatives(rel/align/fixed) cannot be used at the same time.",
9667             file_in, line - 1);
9668         exit(-1);
9669      }
9670 
9671    current_desc->offset_is_scaled = EINA_TRUE;
9672 }
9673 
9674 static void
parse_anchor_line(Edje_Part_Anchor * anchor,Edje_Part_Anchor_Line undefined)9675 parse_anchor_line(Edje_Part_Anchor *anchor, Edje_Part_Anchor_Line undefined)
9676 {
9677    int nargs;
9678    char *name;
9679 
9680    nargs = get_arg_count();
9681    if (!nargs || (nargs > 2))
9682      {
9683         ERR("parse error %s:%i. Anchors should have a name of part and base line.",
9684             file_in, line - 1);
9685         exit(-1);
9686      }
9687 
9688    name = parse_str(0);
9689    anchor->set = EINA_TRUE;
9690 
9691    if (nargs == 2)
9692      anchor->base.line = parse_enum(1,
9693                                     "TOP", EDJE_PART_ANCHOR_LINE_TOP,
9694                                     "BOTTOM", EDJE_PART_ANCHOR_LINE_BOTTOM,
9695                                     "LEFT", EDJE_PART_ANCHOR_LINE_LEFT,
9696                                     "RIGHT", EDJE_PART_ANCHOR_LINE_RIGHT,
9697                                     "VERTICAL_CENTER", EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER,
9698                                     "HORIZONTAL_CENTER", EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER,
9699                                     "*", EDJE_PART_ANCHOR_LINE_RELATIVE,
9700                                     NULL);
9701    else if (strcmp(name, "GROUP") || param_had_quote(0))
9702      anchor->base.line = undefined;
9703 
9704    free(name);
9705 }
9706 
9707 static void
parse_anchor_fill(Edje_Part_Anchor * anchor)9708 parse_anchor_fill(Edje_Part_Anchor *anchor)
9709 {
9710    int nargs;
9711 
9712    nargs = get_arg_count();
9713    if (!nargs || (nargs > 2))
9714      {
9715         ERR("parse error %s:%i. Anchors should have a name of part and base line.",
9716             file_in, line - 1);
9717         exit(-1);
9718      }
9719 
9720    anchor->set = EINA_TRUE;
9721 
9722    if (nargs == 2)
9723      anchor->base.fill = parse_enum(1,
9724                                     "BOTH", EDJE_PART_ANCHOR_FILL_BOTH,
9725                                     "HORIZONTAL", EDJE_PART_ANCHOR_FILL_HORIZONTAL,
9726                                     "VERTICAL", EDJE_PART_ANCHOR_FILL_VERTICAL,
9727                                     NULL);
9728    else
9729      anchor->base.fill = EDJE_PART_ANCHOR_FILL_BOTH;
9730 }
9731 
9732 static void
anchor_queue_part_lookup(int * part,int * counterpart,Eina_Bool counterpart_is_set)9733 anchor_queue_part_lookup(int *part, int *counterpart, Eina_Bool counterpart_is_set)
9734 {
9735    Edje_Part_Collection *pc;
9736    char *name;
9737 
9738    pc = eina_list_data_get(eina_list_last(edje_collections));
9739 
9740    name = parse_str(0);
9741    if (!strcmp(name, "GROUP") && !param_had_quote(0))
9742      goto end;
9743 
9744    data_queue_part_lookup(pc, name, part);
9745 
9746    if (!counterpart_is_set)
9747      data_queue_part_lookup(pc, name, counterpart);
9748 
9749 end:
9750    free(name);
9751 }
9752 
9753 static void
anchor_dequeue_part_lookup(int * part,Eina_Bool counterpart_is_set)9754 anchor_dequeue_part_lookup(int *part, Eina_Bool counterpart_is_set)
9755 {
9756    Edje_Part_Collection *pc;
9757 
9758    pc = eina_list_data_get(eina_list_last(edje_collections));
9759 
9760    if (counterpart_is_set && part)
9761      part_lookup_del(pc, part);
9762 }
9763 
9764 static void
anchor_adjust_align(FLOAT_T * align,FLOAT_T val,unsigned char * fixed,Eina_Bool counterpart_is_set)9765 anchor_adjust_align(FLOAT_T *align, FLOAT_T val, unsigned char *fixed, Eina_Bool counterpart_is_set)
9766 {
9767    if (counterpart_is_set)
9768      {
9769         *align = 0.5;
9770         *fixed = 0;
9771      }
9772    else
9773      {
9774         *align = val;
9775         *fixed = 1;
9776      }
9777 }
9778 
9779 static void
anchor_adjust_relative(const Edje_Part_Anchor_Line * anchor_lines,FLOAT_T * rel,FLOAT_T * relc,Edje_Part_Anchor_Line anchor_line,Edje_Part_Anchor_Line base,Eina_Bool counterpart_is_set)9780 anchor_adjust_relative(const Edje_Part_Anchor_Line *anchor_lines, FLOAT_T *rel, FLOAT_T *relc, Edje_Part_Anchor_Line anchor_line, Edje_Part_Anchor_Line base, Eina_Bool counterpart_is_set)
9781 {
9782    if (anchor_line == EDJE_PART_ANCHOR_LINE_NONE)
9783      anchor_line = base;
9784 
9785    if (anchor_line == anchor_lines[0])
9786      {
9787         *rel = FROM_DOUBLE(0.0);
9788         if (!counterpart_is_set)
9789           *relc = FROM_DOUBLE(0.0);
9790      }
9791    else if (anchor_line == anchor_lines[1])
9792      {
9793         *rel = FROM_DOUBLE(1.0);
9794         if (!counterpart_is_set)
9795           *relc = FROM_DOUBLE(1.0);
9796      }
9797    else if (anchor_line == anchor_lines[2])
9798      {
9799         *rel = FROM_DOUBLE(0.5);
9800         if (!counterpart_is_set)
9801           *relc = FROM_DOUBLE(0.5);
9802      }
9803    else if (anchor_line == EDJE_PART_ANCHOR_LINE_RELATIVE)
9804      {
9805         *rel = FROM_DOUBLE(parse_float(1));
9806         if (!counterpart_is_set)
9807           *relc = FROM_DOUBLE(parse_float(1));
9808      }
9809    else
9810      {
9811         ERR("parse error %s:%i. Edje part is anchored to wrong position.",
9812             file_in, line - 1);
9813         exit(-1);
9814      }
9815 }
9816 
9817 static void
anchor_adjust_relative_vertical(FLOAT_T * rel,FLOAT_T * relc,Edje_Part_Anchor_Line anchor_line,Edje_Part_Anchor_Line base,Eina_Bool counterpart_is_set)9818 anchor_adjust_relative_vertical(FLOAT_T *rel, FLOAT_T *relc, Edje_Part_Anchor_Line anchor_line, Edje_Part_Anchor_Line base, Eina_Bool counterpart_is_set)
9819 {
9820    static const Edje_Part_Anchor_Line anchor_lines[] = {
9821       EDJE_PART_ANCHOR_LINE_TOP,
9822       EDJE_PART_ANCHOR_LINE_BOTTOM,
9823       EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER
9824    };
9825 
9826    anchor_adjust_relative(anchor_lines, rel, relc, anchor_line, base, counterpart_is_set);
9827 }
9828 
9829 static void
anchor_adjust_relative_horizontal(FLOAT_T * rel,FLOAT_T * relc,Edje_Part_Anchor_Line anchor_line,Edje_Part_Anchor_Line base,Eina_Bool counterpart_is_set)9830 anchor_adjust_relative_horizontal(FLOAT_T *rel, FLOAT_T *relc, Edje_Part_Anchor_Line anchor_line, Edje_Part_Anchor_Line base, Eina_Bool counterpart_is_set)
9831 {
9832    static const Edje_Part_Anchor_Line anchor_lines[] = {
9833       EDJE_PART_ANCHOR_LINE_LEFT,
9834       EDJE_PART_ANCHOR_LINE_RIGHT,
9835       EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER
9836    };
9837 
9838    anchor_adjust_relative(anchor_lines, rel, relc, anchor_line, base, counterpart_is_set);
9839 }
9840 
9841 /**
9842     @page edcref
9843     @property
9844         top
9845     @parameters
9846         [partname] [TOP/BOTTOM/VERTICAL_CENTER]
9847     @effect
9848         Causes top edge to be positioned to the edge of another part's container.
9849         Setting to GROUP will indicate edje group instead of another part.
9850         If bottom anchor is not set, edje part will be expanded to the bottom.
9851         The second parameter of position enumeration can be omitted. (Default
9852         value is BOTTOM, but TOP when the part is anchored to edje group)
9853     @endproperty
9854  */
9855 static void
st_collections_group_parts_part_description_anchors_top(void)9856 st_collections_group_parts_part_description_anchors_top(void)
9857 {
9858    Eina_Bool counterpart_is_set;
9859 
9860    check_has_relatives();
9861 
9862    if (!current_anchors)
9863      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
9864 
9865    counterpart_is_set = current_anchors->bottom.set;
9866 
9867    parse_anchor_line(&(current_anchors->top), EDJE_PART_ANCHOR_LINE_BOTTOM);
9868 
9869    anchor_dequeue_part_lookup(&(current_desc->rel1.id_y), counterpart_is_set);
9870    anchor_queue_part_lookup(&(current_desc->rel1.id_y), &(current_desc->rel2.id_y), counterpart_is_set);
9871 
9872    anchor_adjust_align(&(current_desc->align.y), 0.0, &(current_desc->fixed.h), counterpart_is_set);
9873    anchor_adjust_relative_vertical(&(current_desc->rel1.relative_y), &(current_desc->rel2.relative_y), current_anchors->top.base.line, EDJE_PART_ANCHOR_LINE_TOP, counterpart_is_set);
9874 }
9875 
9876 /**
9877     @page edcref
9878     @property
9879         bottom
9880     @parameters
9881         [partname] [TOP/BOTTOM/VERTICAL_CENTER]
9882     @effect
9883         Causes bottom edge to be positioned to the edge of another part's container.
9884         Setting to GROUP will indicate edje group instead of another part.
9885         If top anchor is not set, edje part will be expanded to the top.
9886         The second parameter of position enumeration can be omitted. (Default
9887         value is TOP, but BOTTOM when the part is anchored to edje group)
9888     @endproperty
9889  */
9890 static void
st_collections_group_parts_part_description_anchors_bottom(void)9891 st_collections_group_parts_part_description_anchors_bottom(void)
9892 {
9893    Eina_Bool counterpart_is_set;
9894 
9895    check_has_relatives();
9896 
9897    if (!current_anchors)
9898      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
9899 
9900    counterpart_is_set = current_anchors->top.set;
9901 
9902    parse_anchor_line(&(current_anchors->bottom), EDJE_PART_ANCHOR_LINE_TOP);
9903 
9904    anchor_dequeue_part_lookup(&(current_desc->rel2.id_y), counterpart_is_set);
9905    anchor_queue_part_lookup(&(current_desc->rel2.id_y), &(current_desc->rel1.id_y), counterpart_is_set);
9906 
9907    anchor_adjust_align(&(current_desc->align.y), 1.0, &(current_desc->fixed.h), counterpart_is_set);
9908    anchor_adjust_relative_vertical(&(current_desc->rel2.relative_y), &(current_desc->rel1.relative_y), current_anchors->bottom.base.line, EDJE_PART_ANCHOR_LINE_BOTTOM, counterpart_is_set);
9909 }
9910 
9911 /**
9912     @page edcref
9913     @property
9914         left
9915     @parameters
9916         [partname] [LEFT/RIGHT/HORIZONTAL_CENTER]
9917     @effect
9918         Causes left edge to be positioned to the edge of another part's container.
9919         Setting to GROUP will indicate edje group instead of another part.
9920         If right anchor is not set, edje part will be expanded to the right.
9921         The second parameter of position enumeration can be omitted. (Default
9922         value is RIGHT, but LEFT when the part is anchored to edje group)
9923     @endproperty
9924  */
9925 static void
st_collections_group_parts_part_description_anchors_left(void)9926 st_collections_group_parts_part_description_anchors_left(void)
9927 {
9928    Eina_Bool counterpart_is_set;
9929 
9930    check_has_relatives();
9931 
9932    if (!current_anchors)
9933      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
9934 
9935    counterpart_is_set = current_anchors->right.set;
9936 
9937    parse_anchor_line(&(current_anchors->left), EDJE_PART_ANCHOR_LINE_RIGHT);
9938 
9939    anchor_dequeue_part_lookup(&(current_desc->rel1.id_x), counterpart_is_set);
9940    anchor_queue_part_lookup(&(current_desc->rel1.id_x), &(current_desc->rel2.id_x), counterpart_is_set);
9941 
9942    anchor_adjust_align(&(current_desc->align.x), 0.0, &(current_desc->fixed.w), counterpart_is_set);
9943    anchor_adjust_relative_horizontal(&(current_desc->rel1.relative_x), &(current_desc->rel2.relative_x), current_anchors->left.base.line, EDJE_PART_ANCHOR_LINE_LEFT, counterpart_is_set);
9944 }
9945 
9946 /**
9947     @page edcref
9948     @property
9949         right
9950     @parameters
9951         [partname] [LEFT/RIGHT/HORIZONTAL_CENTER]
9952     @effect
9953         Causes right edge to be positioned to the edge of another part's container.
9954         Setting to GROUP will indicate edje group instead of another part.
9955         If left anchor is not set, edje part will be expanded to the left.
9956         The second parameter of position enumeration can be omitted. (Default
9957         value is LEFT, but RIGHT when the part is anchored to edje group)
9958     @endproperty
9959  */
9960 static void
st_collections_group_parts_part_description_anchors_right(void)9961 st_collections_group_parts_part_description_anchors_right(void)
9962 {
9963    Eina_Bool counterpart_is_set;
9964 
9965    check_has_relatives();
9966 
9967    if (!current_anchors)
9968      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
9969 
9970    counterpart_is_set = current_anchors->left.set;
9971 
9972    parse_anchor_line(&(current_anchors->right), EDJE_PART_ANCHOR_LINE_LEFT);
9973 
9974    anchor_dequeue_part_lookup(&(current_desc->rel2.id_x), counterpart_is_set);
9975    anchor_queue_part_lookup(&(current_desc->rel2.id_x), &(current_desc->rel1.id_x), counterpart_is_set);
9976 
9977    anchor_adjust_align(&(current_desc->align.x), 1.0, &(current_desc->fixed.w), counterpart_is_set);
9978    anchor_adjust_relative_horizontal(&(current_desc->rel2.relative_x), &(current_desc->rel1.relative_x), current_anchors->right.base.line, EDJE_PART_ANCHOR_LINE_RIGHT, counterpart_is_set);
9979 }
9980 
9981 /**
9982     @page edcref
9983     @property
9984         vertical_center
9985     @parameters
9986         [partname] [TOP/BOTTOM/VERTICAL_CENTER]
9987     @effect
9988         Causes (virtual) vertical center line to be positioned to the edge of
9989         another part's container. Setting to GROUP will indicate edje group instead
9990         of another part.
9991         This part will be expanded vertically in both directions, so do not
9992         set top or bottom anchor with vertical_center anchor.
9993         The second parameter of position enumeration can be omitted. (Default
9994         value is VERTICAL_CENTER)
9995     @endproperty
9996  */
9997 static void
st_collections_group_parts_part_description_anchors_vertical_center(void)9998 st_collections_group_parts_part_description_anchors_vertical_center(void)
9999 {
10000    check_has_relatives();
10001 
10002    if (!current_anchors)
10003      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
10004 
10005    parse_anchor_line(&(current_anchors->vertical_center), EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER);
10006 
10007    anchor_queue_part_lookup(&(current_desc->rel1.id_y), &(current_desc->rel2.id_y), EINA_FALSE);
10008 
10009    anchor_adjust_align(&(current_desc->align.y), 0.5, &(current_desc->fixed.h), EINA_FALSE);
10010    anchor_adjust_relative_vertical(&(current_desc->rel1.relative_y), &(current_desc->rel2.relative_y), current_anchors->vertical_center.base.line, EDJE_PART_ANCHOR_LINE_VERTICAL_CENTER, EINA_FALSE);
10011 }
10012 
10013 /**
10014     @page edcref
10015     @property
10016         horizontal_center
10017     @parameters
10018         [partname] [LEFT/RIGHT/HORIZONTAL_CENTER]
10019     @effect
10020         Causes (virtual) horizontal center line to be positioned to the edge of
10021         another part's container. Setting to GROUP will indicate edje group instead
10022         of another part.
10023         This part will be expanded horizontally in both directions, so do not
10024         set left or right anchor with vertical_center anchor.
10025         The second parameter of position enumeration can be omitted. (Default
10026         value is HORIZONTAL_CENTER)
10027     @endproperty
10028  */
10029 static void
st_collections_group_parts_part_description_anchors_horizontal_center(void)10030 st_collections_group_parts_part_description_anchors_horizontal_center(void)
10031 {
10032    check_has_relatives();
10033 
10034    if (!current_anchors)
10035      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
10036 
10037    parse_anchor_line(&(current_anchors->horizontal_center), EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER);
10038 
10039    anchor_queue_part_lookup(&(current_desc->rel1.id_x), &(current_desc->rel2.id_x), EINA_FALSE);
10040 
10041    anchor_adjust_align(&(current_desc->align.x), 0.5, &(current_desc->fixed.w), EINA_FALSE);
10042    anchor_adjust_relative_horizontal(&(current_desc->rel1.relative_x), &(current_desc->rel2.relative_x), current_anchors->horizontal_center.base.line, EDJE_PART_ANCHOR_LINE_HORIZONTAL_CENTER, EINA_FALSE);
10043 }
10044 
10045 /**
10046     @page edcref
10047     @property
10048         fill
10049     @parameters
10050         [partname] [BOTH/HORIZONTAL/VERTICAL]
10051     @effect
10052         Causes the part's container to expand to the width or height of another
10053         part's container. Setting to GROUP will indicate edje group instead of another part.
10054         Setting horizontal fill has same effect to setting top and bottom anchors
10055         to the same part.
10056         (setting vertical fill means left and right anchors to the same part)
10057         The second parameter of direction enumeration can be omitted. (Default
10058         value is BOTH)
10059     @endproperty
10060  */
10061 static void
st_collections_group_parts_part_description_anchors_fill(void)10062 st_collections_group_parts_part_description_anchors_fill(void)
10063 {
10064    Edje_Part_Collection *pc;
10065    char *name;
10066 
10067    pc = eina_list_last_data_get(edje_collections);
10068 
10069    check_has_relatives();
10070 
10071    if (!current_anchors)
10072      current_anchors = mem_alloc(SZ(Edje_Part_Description_Anchors));
10073 
10074    parse_anchor_fill(&(current_anchors->fill));
10075 
10076    name = parse_str(0);
10077 
10078    switch (current_anchors->fill.base.fill)
10079      {
10080       case EDJE_PART_ANCHOR_FILL_BOTH:
10081         if (strcmp("GROUP", name) || param_had_quote(0))
10082           {
10083              data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
10084              data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
10085              data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
10086              data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
10087           }
10088         current_desc->align.x = 0.5;
10089         current_desc->align.y = 0.5;
10090         current_desc->fixed.w = 0;
10091         current_desc->fixed.h = 0;
10092         break;
10093 
10094       case EDJE_PART_ANCHOR_FILL_HORIZONTAL:
10095         if (strcmp("GROUP", name) || param_had_quote(0))
10096           {
10097              data_queue_part_lookup(pc, name, &(current_desc->rel1.id_x));
10098              data_queue_part_lookup(pc, name, &(current_desc->rel2.id_x));
10099           }
10100         current_desc->align.x = 0.5;
10101         current_desc->fixed.w = 0;
10102         break;
10103 
10104       case EDJE_PART_ANCHOR_FILL_VERTICAL:
10105         if (strcmp("GROUP", name) || param_had_quote(0))
10106           {
10107              data_queue_part_lookup(pc, name, &(current_desc->rel1.id_y));
10108              data_queue_part_lookup(pc, name, &(current_desc->rel2.id_y));
10109           }
10110         current_desc->align.y = 0.5;
10111         current_desc->fixed.h = 0;
10112         break;
10113      }
10114 
10115    free(name);
10116 }
10117 
10118 /**
10119     @page edcref
10120     @property
10121         margin
10122     @parameters
10123         [left] [right] [top] [bottom]
10124     @effect
10125         Affects the edge position a fixed number of pixels along each direction.
10126         Margins will scale its size with an edje scaling factor.
10127     @endproperty
10128  */
10129 static void
st_collections_group_parts_part_description_anchors_margin(void)10130 st_collections_group_parts_part_description_anchors_margin(void)
10131 {
10132    check_has_relatives();
10133    check_arg_count(4);
10134 
10135    current_desc->rel1.offset_x = parse_int(0);
10136    current_desc->rel2.offset_x = -parse_int(1) - 1;
10137    current_desc->rel1.offset_y = parse_int(2);
10138    current_desc->rel2.offset_y = -parse_int(3) - 1;
10139 }
10140 
10141 static void
free_anchors(void)10142 free_anchors(void)
10143 {
10144    has_relatives = EINA_FALSE;
10145 
10146    if (!current_anchors) return;
10147 
10148    free(current_anchors);
10149    current_anchors = NULL;
10150 }
10151 
10152 /** @edcsubsection{collections_group_parts_description_image,
10153  *                 Group.Parts.Part.Description.Image} */
10154 
10155 /**
10156     @page edcref
10157     @block
10158         image
10159     @context
10160         description {
10161             ..
10162             image {
10163                 normal: "filename.ext";
10164                 normal: "filename.svg";
10165                 tween:  "filename2.ext";
10166                 ..
10167                 tween:  "filenameN.ext";
10168                 border:  left right top bottom;
10169                 middle:  0/1/NONE/DEFAULT/SOLID;
10170                 fill { }
10171             }
10172             ..
10173         }
10174     @description
10175     @endblock
10176 
10177     @property
10178         normal
10179     @parameters
10180         [image's filename]
10181     @effect
10182         Name of image to be used as previously declared in the  images block.
10183         In an animation, this is the first and last image displayed. It's
10184         required in any image part
10185     @endproperty
10186  */
10187 static void
st_collections_group_parts_part_description_image_normal(void)10188 st_collections_group_parts_part_description_image_normal(void)
10189 {
10190    Edje_Part_Description_Image *ed;
10191 
10192    check_arg_count(1);
10193 
10194    if (current_part->type == EDJE_PART_TYPE_VECTOR)
10195      {
10196         return _handle_vector_image();
10197      }
10198 
10199    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10200      {
10201         ERR("parse error %s:%i. "
10202             "image attributes in non-IMAGE part.",
10203             file_in, line - 1);
10204         exit(-1);
10205      }
10206 
10207    ed = (Edje_Part_Description_Image *)current_desc;
10208 
10209    {
10210       char *name;
10211 
10212       if (current_part->type == EDJE_PART_TYPE_MESH_NODE)
10213         ed->image.set = EINA_TRUE;
10214 
10215       name = parse_str(0);
10216       data_queue_image_remove(&(ed->image.id), &(ed->image.set));
10217       data_queue_image_lookup(name, &(ed->image.id), &(ed->image.set));
10218       free(name);
10219    }
10220 }
10221 
10222 /**
10223     @page edcref
10224     @property
10225         tween
10226     @parameters
10227         [image's filename]
10228     @effect
10229         Name of an image to be used in an animation loop, an image block can
10230         have none, one or multiple tween declarations. Images are displayed in
10231         the order they are listed, during the transition to the state they are
10232         declared in; the "normal" image is the final state.
10233     @endproperty
10234  */
10235 static void
st_collections_group_parts_part_description_image_tween(void)10236 st_collections_group_parts_part_description_image_tween(void)
10237 {
10238    Edje_Part_Description_Image *ed;
10239 
10240    check_arg_count(1);
10241 
10242    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10243      {
10244         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
10245             file_in, line - 1);
10246         exit(-1);
10247      }
10248 
10249    ed = (Edje_Part_Description_Image *)current_desc;
10250 
10251    {
10252       char *name;
10253       Edje_Part_Image_Id *iid;
10254 
10255       iid = mem_alloc(SZ(Edje_Part_Image_Id));
10256       ed->image.tweens_count++;
10257       ed->image.tweens = realloc(ed->image.tweens,
10258                                  sizeof (Edje_Part_Image_Id *) * ed->image.tweens_count);
10259       ed->image.tweens[ed->image.tweens_count - 1] = iid;
10260       name = parse_str(0);
10261       data_queue_image_remove(&(iid->id), &(iid->set));
10262       data_queue_image_lookup(name, &(iid->id), &(iid->set));
10263       free(name);
10264    }
10265 }
10266 
10267 /**
10268     @page edcref
10269     @property
10270         border
10271     @parameters
10272         [left] [right] [top] [bottom]
10273     @effect
10274         If set, the area (in pixels) of each side of the image will be
10275         displayed as a fixed size border, from the side -> inwards, preventing
10276         the corners from being changed on a resize.
10277 
10278         Defaults: 0 0 0 0
10279     @endproperty
10280  */
10281 static void
st_collections_group_parts_part_description_image_border(void)10282 st_collections_group_parts_part_description_image_border(void)
10283 {
10284    Edje_Part_Description_Image *ed;
10285 
10286    check_arg_count(4);
10287 
10288    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10289      {
10290         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
10291             file_in, line - 1);
10292         exit(-1);
10293      }
10294 
10295    ed = (Edje_Part_Description_Image *)current_desc;
10296 
10297    ed->image.border.l = parse_int_range(0, 0, 0x7fffffff);
10298    ed->image.border.r = parse_int_range(1, 0, 0x7fffffff);
10299    ed->image.border.t = parse_int_range(2, 0, 0x7fffffff);
10300    ed->image.border.b = parse_int_range(3, 0, 0x7fffffff);
10301 }
10302 
10303 /**
10304     @page edcref
10305     @property
10306         middle
10307     @parameters
10308         [mode]
10309     @effect
10310         If border is set, this value tells Edje if the rest of the
10311         image (not covered by the defined border) will be displayed or not
10312         or be assumed to be solid (without alpha). The default is 1/DEFAULT.
10313         Valid values are:
10314         @li 0 or NONE
10315         @li 1 or DEFAULT
10316         @li SOLID
10317     @endproperty
10318  */
10319 static void
st_collections_group_parts_part_description_image_middle(void)10320 st_collections_group_parts_part_description_image_middle(void)
10321 {
10322    Edje_Part_Description_Image *ed;
10323 
10324    check_arg_count(1);
10325 
10326    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10327      {
10328         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
10329             file_in, line - 1);
10330         exit(-1);
10331      }
10332 
10333    ed = (Edje_Part_Description_Image *)current_desc;
10334 
10335    ed->image.border.no_fill = parse_enum(0,
10336                                          "1", 0,
10337                                          "DEFAULT", 0,
10338                                          "0", 1,
10339                                          "NONE", 1,
10340                                          "SOLID", 2,
10341                                          NULL);
10342 }
10343 
10344 /**
10345     @page edcref
10346     @property
10347         border_scale_by
10348     @parameters
10349         [value]
10350     @effect
10351         If border scaling is enabled then normally the OUTPUT border sizes
10352         (e.g. if 3 pixels on the left edge are set as a border, then normally
10353         at scale 1.0, those 3 columns will always be the exact 3 columns of
10354         output, or at scale 2.0 they will be 6 columns, or 0.33 they will merge
10355         into a single column). This property multiplies the input scale
10356         factor by this multiplier, allowing the creation of "supersampled"
10357         borders to make much higher resolution outputs possible by always using
10358         the highest resolution artwork and then runtime scaling it down.
10359 
10360         value can be: 0.0 or bigger (0.0 or 1.0 to turn it off)
10361 
10362         Defaults: 0.0
10363     @endproperty
10364  */
10365 static void
st_collections_group_parts_part_description_image_border_scale_by(void)10366 st_collections_group_parts_part_description_image_border_scale_by(void)
10367 {
10368    Edje_Part_Description_Image *ed;
10369 
10370    check_arg_count(1);
10371 
10372    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10373      {
10374         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
10375             file_in, line - 1);
10376         exit(-1);
10377      }
10378 
10379    ed = (Edje_Part_Description_Image *)current_desc;
10380 
10381    ed->image.border.scale_by = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
10382 }
10383 
10384 /**
10385     @page edcref
10386     @property
10387         border_scale
10388     @parameters
10389         [0/1]
10390     @effect
10391         If border is set, this value tells Edje if the border should be scaled
10392         by the object/global edje scale factors
10393 
10394         Defaults: 0
10395     @endproperty
10396  */
10397 static void
st_collections_group_parts_part_description_image_border_scale(void)10398 st_collections_group_parts_part_description_image_border_scale(void)
10399 {
10400    Edje_Part_Description_Image *ed;
10401 
10402    check_arg_count(1);
10403 
10404    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10405      {
10406         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
10407             file_in, line - 1);
10408         exit(-1);
10409      }
10410 
10411    ed = (Edje_Part_Description_Image *)current_desc;
10412 
10413    ed->image.border.scale = parse_bool(0);
10414 }
10415 
10416 /**
10417     @page edcref
10418     @property
10419         scale_hint
10420     @parameters
10421         [mode]
10422     @effect
10423         Sets the evas image scale hint letting the engine more effectively save
10424         cached copies of the scaled image if it makes sense.
10425         Valid values are:
10426         @li 0 or NONE
10427         @li DYNAMIC
10428         @li STATIC
10429 
10430         Defaults: NONE
10431     @endproperty
10432  */
10433 static void
st_collections_group_parts_part_description_image_scale_hint(void)10434 st_collections_group_parts_part_description_image_scale_hint(void)
10435 {
10436    Edje_Part_Description_Image *ed;
10437 
10438    check_arg_count(1);
10439 
10440    if (current_part->type != EDJE_PART_TYPE_IMAGE)
10441      {
10442         ERR("parse error %s:%i. image attributes in non-IMAGE part.",
10443             file_in, line - 1);
10444         exit(-1);
10445      }
10446 
10447    ed = (Edje_Part_Description_Image *)current_desc;
10448 
10449    ed->image.scale_hint = parse_enum(0,
10450                                      "NONE", EVAS_IMAGE_SCALE_HINT_NONE,
10451                                      "DYNAMIC", EVAS_IMAGE_SCALE_HINT_DYNAMIC,
10452                                      "STATIC", EVAS_IMAGE_SCALE_HINT_STATIC,
10453                                      "0", EVAS_IMAGE_SCALE_HINT_NONE,
10454                                      NULL);
10455 }
10456 
10457 /** @edcsubsection{collections_group_parts_description_fill,
10458  *                 Group.Parts.Part.Description.Fill} */
10459 
10460 /**
10461     @page edcref
10462     @block
10463         fill
10464     @context
10465         part { type: [IMAGE or PROXY];
10466             description {
10467                 ..
10468                 fill {
10469                     type: SCALE;
10470                     smooth: 0-1;
10471                     origin { }
10472                     size { }
10473                 }
10474                 ..
10475             }
10476             ..
10477         }
10478     @description
10479         The fill method is an optional block that defines the way an IMAGE or
10480         PROXY part is going to be displayed inside its container.
10481         It can be used for tiling (repeating the image) or displaying only
10482         part of an image. See evas_object_image_fill_set() documentation
10483         for more details.
10484     @endblock
10485 
10486     @property
10487         smooth
10488     @parameters
10489         [0 or 1]
10490     @effect
10491         The smooth property takes a boolean value to decide if the image will
10492         be smoothed on scaling (1) or not (0).
10493 
10494         Defaults: 1
10495     @endproperty
10496  */
10497 static void
st_collections_group_parts_part_description_fill_smooth(void)10498 st_collections_group_parts_part_description_fill_smooth(void)
10499 {
10500    Edje_Part_Description_Spec_Fill *fill;
10501 
10502    check_arg_count(1);
10503 
10504    switch (current_part->type)
10505      {
10506       case EDJE_PART_TYPE_IMAGE:
10507       {
10508          Edje_Part_Description_Image *ed;
10509 
10510          ed = (Edje_Part_Description_Image *)current_desc;
10511 
10512          fill = &ed->image.fill;
10513          break;
10514       }
10515 
10516       case EDJE_PART_TYPE_PROXY:
10517       {
10518          Edje_Part_Description_Proxy *ed;
10519 
10520          ed = (Edje_Part_Description_Proxy *)current_desc;
10521 
10522          fill = &ed->proxy.fill;
10523          break;
10524       }
10525 
10526       default:
10527       {
10528          ERR("parse error %s:%i. "
10529              "image and proxy attributes in non-IMAGE, non-PROXY `%s` part (%i).",
10530              file_in, line - 1, current_part->name, current_part->type);
10531          exit(-1);
10532       }
10533      }
10534 
10535    fill->smooth = parse_bool(0);
10536 }
10537 
10538 /**
10539     @page edcref
10540     @property
10541         type
10542     @parameters
10543         [fill type]
10544     @effect
10545         Sets the image fill type. SCALE - image will be scaled accordingly params
10546         value 'relative' and 'offset' from 'origin' and 'size' blocks.
10547         TILE - image will be tiled accordingly params value 'relative' and
10548         'offset' from 'origin' and 'size' blocks. Important: the part parameter
10549         'min' must be setted, it's size of tiled image. If parameter 'max' setted
10550         tiled area will has the size accordingly 'max' values.
10551 
10552         Valid values are:
10553         @li SCALE
10554         @li TILE
10555 
10556         Defaults: SCALE
10557     @endproperty
10558  */
10559 static void
st_collections_group_parts_part_description_fill_type(void)10560 st_collections_group_parts_part_description_fill_type(void)
10561 {
10562    Edje_Part_Description_Spec_Fill *fill;
10563 
10564    check_arg_count(1);
10565 
10566    switch (current_part->type)
10567      {
10568       case EDJE_PART_TYPE_IMAGE:
10569       {
10570          Edje_Part_Description_Image *ed;
10571 
10572          ed = (Edje_Part_Description_Image *)current_desc;
10573 
10574          fill = &ed->image.fill;
10575          break;
10576       }
10577 
10578       case EDJE_PART_TYPE_PROXY:
10579       {
10580          Edje_Part_Description_Proxy *ed;
10581 
10582          ed = (Edje_Part_Description_Proxy *)current_desc;
10583 
10584          fill = &ed->proxy.fill;
10585          break;
10586       }
10587 
10588       default:
10589       {
10590          ERR("parse error %s:%i. "
10591              "image and proxy attributes in non-IMAGE, non-PROXY part.",
10592              file_in, line - 1);
10593          exit(-1);
10594       }
10595      }
10596 
10597    fill->type = parse_enum(0,
10598                            "SCALE", EDJE_FILL_TYPE_SCALE,
10599                            "TILE", EDJE_FILL_TYPE_TILE,
10600                            NULL);
10601 }
10602 
10603 /** @edcsubsection{collections_group_parts_description_fill_origin,
10604  *                 Group.Parts.Part.Description.Fill.Origin} */
10605 
10606 /**
10607     @page edcref
10608     @block
10609         origin
10610     @context
10611         image {
10612             ..
10613             fill {
10614                 ..
10615                 origin {
10616                     relative: 0.0 0.0;
10617                     offset:   0   0;
10618                 }
10619                 ..
10620             }
10621             ..
10622         }
10623     @description
10624         The origin block is used to place the starting point, inside the
10625         displayed element, that will be used to render the tile. By default,
10626         the origin is set at the element's left-up corner.
10627     @endblock
10628 
10629     @property
10630         relative
10631     @parameters
10632         [X axis] [Y axis]
10633     @effect
10634         Sets the starting point relatively to displayed element's content.
10635 
10636         Defaults: 0.0 0.0
10637     @endproperty
10638  */
10639 static void
st_collections_group_parts_part_description_fill_origin_relative(void)10640 st_collections_group_parts_part_description_fill_origin_relative(void)
10641 {
10642    Edje_Part_Description_Spec_Fill *fill;
10643 
10644    check_arg_count(2);
10645 
10646    switch (current_part->type)
10647      {
10648       case EDJE_PART_TYPE_IMAGE:
10649       {
10650          Edje_Part_Description_Image *ed;
10651 
10652          ed = (Edje_Part_Description_Image *)current_desc;
10653 
10654          fill = &ed->image.fill;
10655          break;
10656       }
10657 
10658       case EDJE_PART_TYPE_PROXY:
10659       {
10660          Edje_Part_Description_Proxy *ed;
10661 
10662          ed = (Edje_Part_Description_Proxy *)current_desc;
10663 
10664          fill = &ed->proxy.fill;
10665          break;
10666       }
10667 
10668       default:
10669       {
10670          ERR("parse error %s:%i. "
10671              "image and proxy attributes in non-IMAGE, non-PROXY part.",
10672              file_in, line - 1);
10673          exit(-1);
10674       }
10675      }
10676 
10677    fill->pos_rel_x = FROM_DOUBLE(parse_float_range(0, -999999999.0, 999999999.0));
10678    fill->pos_rel_y = FROM_DOUBLE(parse_float_range(1, -999999999.0, 999999999.0));
10679 }
10680 
10681 /**
10682     @page edcref
10683     @property
10684         offset
10685     @parameters
10686         [X axis] [Y axis]
10687     @effect
10688         Affects the starting point a fixed number of pixels along each axis.
10689 
10690         Defaults: 0 0
10691     @endproperty
10692  */
10693 static void
st_collections_group_parts_part_description_fill_origin_offset(void)10694 st_collections_group_parts_part_description_fill_origin_offset(void)
10695 {
10696    Edje_Part_Description_Spec_Fill *fill;
10697 
10698    check_arg_count(2);
10699 
10700    switch (current_part->type)
10701      {
10702       case EDJE_PART_TYPE_IMAGE:
10703       {
10704          Edje_Part_Description_Image *ed;
10705 
10706          ed = (Edje_Part_Description_Image *)current_desc;
10707 
10708          fill = &ed->image.fill;
10709          break;
10710       }
10711 
10712       case EDJE_PART_TYPE_PROXY:
10713       {
10714          Edje_Part_Description_Proxy *ed;
10715 
10716          ed = (Edje_Part_Description_Proxy *)current_desc;
10717 
10718          fill = &ed->proxy.fill;
10719          break;
10720       }
10721 
10722       default:
10723       {
10724          ERR("parse error %s:%i. "
10725              "image and proxy attributes in non-IMAGE, non-PROXY part.",
10726              file_in, line - 1);
10727          exit(-1);
10728       }
10729      }
10730 
10731    fill->pos_abs_x = parse_int(0);
10732    fill->pos_abs_y = parse_int(1);
10733 }
10734 
10735 /** @edcsubsection{collections_group_parts_description_fill_size,
10736  *                 Group.Parts.Part.Description.Fill.Size} */
10737 
10738 /**
10739     @page edcref
10740     @block
10741         size
10742     @context
10743         image {
10744             ..
10745             fill {
10746                 ..
10747                 size {
10748                     relative: 1.0 1.0;
10749                     offset:  -1  -1;
10750                 }
10751                 ..
10752             }
10753             ..
10754         }
10755     @description
10756         The size block defines the tile size of the content that will be
10757         displayed.
10758     @endblock
10759 
10760     @property
10761         relative
10762     @parameters
10763         [width] [height]
10764     @effect
10765         Takes a pair of decimal values that represent the percentual value
10766         of the original size of the element. For example, "0.5 0.5" represents
10767         half the size, while "2.0 2.0" represents the double.
10768 
10769         Defaults: 1.0 1.0
10770     @endproperty
10771  */
10772 static void
st_collections_group_parts_part_description_fill_size_relative(void)10773 st_collections_group_parts_part_description_fill_size_relative(void)
10774 {
10775    Edje_Part_Description_Spec_Fill *fill;
10776 
10777    check_arg_count(2);
10778 
10779    switch (current_part->type)
10780      {
10781       case EDJE_PART_TYPE_IMAGE:
10782       {
10783          Edje_Part_Description_Image *ed;
10784 
10785          ed = (Edje_Part_Description_Image *)current_desc;
10786 
10787          fill = &ed->image.fill;
10788          break;
10789       }
10790 
10791       case EDJE_PART_TYPE_PROXY:
10792       {
10793          Edje_Part_Description_Proxy *ed;
10794 
10795          ed = (Edje_Part_Description_Proxy *)current_desc;
10796 
10797          fill = &ed->proxy.fill;
10798          break;
10799       }
10800 
10801       default:
10802       {
10803          ERR("parse error %s:%i. "
10804              "image and proxy attributes in non-IMAGE, non-PROXY part.",
10805              file_in, line - 1);
10806          exit(-1);
10807       }
10808      }
10809 
10810    fill->rel_x = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
10811    fill->rel_y = FROM_DOUBLE(parse_float_range(1, 0.0, 999999999.0));
10812 }
10813 
10814 /**
10815     @page edcref
10816     @property
10817         offset
10818     @parameters
10819         [X axis] [Y axis]
10820     @effect
10821         Affects the size of the tile a fixed number of pixels along each axis.
10822 
10823         Defaults: 0 0
10824     @endproperty
10825  */
10826 static void
st_collections_group_parts_part_description_fill_size_offset(void)10827 st_collections_group_parts_part_description_fill_size_offset(void)
10828 {
10829    Edje_Part_Description_Spec_Fill *fill;
10830 
10831    check_arg_count(2);
10832 
10833    switch (current_part->type)
10834      {
10835       case EDJE_PART_TYPE_IMAGE:
10836       {
10837          Edje_Part_Description_Image *ed;
10838 
10839          ed = (Edje_Part_Description_Image *)current_desc;
10840 
10841          fill = &ed->image.fill;
10842          break;
10843       }
10844 
10845       case EDJE_PART_TYPE_PROXY:
10846       {
10847          Edje_Part_Description_Proxy *ed;
10848 
10849          ed = (Edje_Part_Description_Proxy *)current_desc;
10850 
10851          fill = &ed->proxy.fill;
10852          break;
10853       }
10854 
10855       default:
10856       {
10857          ERR("parse error %s:%i. "
10858              "image and proxy attributes in non-IMAGE, non-PROXY part.",
10859              file_in, line - 1);
10860          exit(-1);
10861       }
10862      }
10863 
10864    fill->abs_x = parse_int(0);
10865    fill->abs_y = parse_int(1);
10866 }
10867 
10868 /** @edcsubsection{collections_group_parts_description_text,
10869  *                 Group.Parts.Part.Description.Text} */
10870 
10871 /**
10872     @page edcref
10873 
10874     @block
10875         text
10876     @context
10877         part {
10878             description {
10879                 ..
10880                 text {
10881                     text:        "some string of text to display";
10882                     domain:      "domain_name";
10883                     font:        "font_name";
10884                     size:         SIZE;
10885                     text_class:  "class_name";
10886                     fit:          horizontal vertical;
10887                     min:          horizontal vertical;
10888                     max:          horizontal vertical;
10889                     align:        X-axis     Y-axis;
10890                     source:      "part_name";
10891                     text_source: "text_part_name";
10892                     ellipsis:     -1.0 (since 1.8), 0.0-1.0;
10893                     style:       "stylename";
10894                 }
10895                 ..
10896             }
10897         }
10898     @description
10899     @endblock
10900 
10901     @property
10902         text
10903     @parameters
10904         [a string of text, or nothing]
10905     @effect
10906         Sets the default content of a text part, normally the application is
10907         the one changing its value.
10908     @endproperty
10909  */
10910 static void
st_collections_group_parts_part_description_text_text(void)10911 st_collections_group_parts_part_description_text_text(void)
10912 {
10913    Edje_Part_Description_Text *ed;
10914    char *str = NULL;
10915    int i;
10916 
10917    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
10918        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
10919      {
10920         ERR("parse error %s:%i. text attributes in non-TEXT part.",
10921             file_in, line - 1);
10922         exit(-1);
10923      }
10924 
10925    ed = (Edje_Part_Description_Text *)current_desc;
10926 
10927    for (i = 0;; i++)
10928      {
10929         char *s;
10930 
10931         if (!is_param(i)) break;
10932         s = parse_str(i);
10933         if (!str) str = s;
10934         else
10935           {
10936              str = realloc(str, strlen(str) + strlen(s) + 1);
10937              strcat(str, s);
10938              free(s);
10939           }
10940      }
10941    ed->text.text.str = str;
10942 }
10943 
10944 /**
10945     @page edcref
10946 
10947     @property
10948         domain
10949     @parameters
10950         [domain name]
10951     @effect
10952         This is the domain name of the .mo file which has to be checked
10953         for translation.
10954     @endproperty
10955  */
10956 static void
st_collections_group_parts_part_description_text_domain(void)10957 st_collections_group_parts_part_description_text_domain(void)
10958 {
10959    Edje_Part_Description_Text *ed;
10960 
10961    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
10962        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
10963      {
10964         ERR("parse error %s:%i. text attributes in non-TEXT part.",
10965             file_in, line - 1);
10966         exit(-1);
10967      }
10968 
10969    ed = (Edje_Part_Description_Text *)current_desc;
10970 
10971    ed->text.domain = parse_str(0);
10972 }
10973 
10974 /**
10975     @page edcref
10976 
10977     @property
10978         text_class
10979     @parameters
10980         [text class name]
10981     @effect
10982         Similar to color_class, this is the name used by the application
10983         to alter the font family and size at runtime.
10984     @endproperty
10985  */
10986 static void
st_collections_group_parts_part_description_text_text_class(void)10987 st_collections_group_parts_part_description_text_text_class(void)
10988 {
10989    Edje_Part_Description_Text *ed;
10990 
10991    check_arg_count(1);
10992 
10993    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
10994        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
10995      {
10996         ERR("parse error %s:%i. text attributes in non-TEXT part.",
10997             file_in, line - 1);
10998         exit(-1);
10999      }
11000 
11001    ed = (Edje_Part_Description_Text *)current_desc;
11002 
11003    ed->text.text_class = parse_str(0);
11004 }
11005 
11006 /**
11007     @page edcref
11008 
11009     @property
11010         font
11011     @parameters
11012         [font alias]
11013     @effect
11014         This sets the font family to one of the aliases set up in the "fonts"
11015         block. Can be overridden by the application.
11016     @endproperty
11017  */
11018 static void
st_collections_group_parts_part_description_text_font(void)11019 st_collections_group_parts_part_description_text_font(void)
11020 {
11021    Edje_Part_Description_Text *ed;
11022 
11023    check_arg_count(1);
11024 
11025    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11026        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11027      {
11028         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11029             file_in, line - 1);
11030         exit(-1);
11031      }
11032 
11033    ed = (Edje_Part_Description_Text *)current_desc;
11034 
11035    ed->text.font.str = parse_str(0);
11036 }
11037 
11038 /**
11039     @page edcref
11040 
11041     @property
11042         style
11043     @parameters
11044         [the style name]
11045     @effect
11046         Causes the part to use the default style and tags defined in the
11047         "style" block with the specified name.
11048     @endproperty
11049  */
11050 static void
st_collections_group_parts_part_description_text_style(void)11051 st_collections_group_parts_part_description_text_style(void)
11052 {
11053    Edje_Part_Description_Text *ed;
11054 
11055    check_arg_count(1);
11056 
11057    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11058        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11059      {
11060         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11061             file_in, line - 1);
11062         exit(-1);
11063      }
11064 
11065    ed = (Edje_Part_Description_Text *)current_desc;
11066 
11067    ed->text.style.str = parse_str(0);
11068 }
11069 
11070 /**
11071     @page edcref
11072 
11073     @property
11074         repch
11075     @parameters
11076         [the replacement character string]
11077     @effect
11078         If this is a textblock and is in PASSWORD mode this string is used
11079         to replace every character to hide the details of the entry. Normally
11080         you would use a "*", but you can use anything you like.
11081     @endproperty
11082  */
11083 static void
st_collections_group_parts_part_description_text_repch(void)11084 st_collections_group_parts_part_description_text_repch(void)
11085 {
11086    Edje_Part_Description_Text *ed;
11087 
11088    check_arg_count(1);
11089 
11090    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11091        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11092      {
11093         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11094             file_in, line - 1);
11095         exit(-1);
11096      }
11097 
11098    ed = (Edje_Part_Description_Text *)current_desc;
11099 
11100    ed->text.repch.str = parse_str(0);
11101 }
11102 
11103 /**
11104     @page edcref
11105 
11106     @property
11107         size
11108     @parameters
11109         [font size in points (pt) 0 - 255]
11110     @effect
11111         Sets the default font size for the text part. Can be overridden by the
11112         application.
11113 
11114         Defaults: 0
11115     @endproperty
11116  */
11117 static void
st_collections_group_parts_part_description_text_size(void)11118 st_collections_group_parts_part_description_text_size(void)
11119 {
11120    Edje_Part_Description_Text *ed;
11121 
11122    check_arg_count(1);
11123 
11124    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11125        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11126      {
11127         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11128             file_in, line - 1);
11129         exit(-1);
11130      }
11131 
11132    ed = (Edje_Part_Description_Text *)current_desc;
11133 
11134    ed->text.size = parse_int_range(0, 0, 255);
11135 }
11136 
11137 /**
11138     @page edcref
11139 
11140     @property
11141         size_range
11142     @parameters
11143         [font min size in points (pt) 0 - 255] [font max size in points (pt) 0 - 255]
11144     @effect
11145         Sets the allowed font size for the text part. Setting min and max to 0
11146         means we won't restrict the sizing.
11147 
11148         Defaults: 0 0
11149     @since 1.1
11150     @endproperty
11151  */
11152 static void
st_collections_group_parts_part_description_text_size_range(void)11153 st_collections_group_parts_part_description_text_size_range(void)
11154 {
11155    Edje_Part_Description_Text *ed;
11156 
11157    check_arg_count(2);
11158 
11159    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11160        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11161      {
11162         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11163             file_in, line - 1);
11164         exit(-1);
11165      }
11166 
11167    ed = (Edje_Part_Description_Text *)current_desc;
11168 
11169    ed->text.size_range_min = parse_int_range(0, 0, 255);
11170    ed->text.size_range_max = parse_int_range(1, 0, 255);
11171    if (ed->text.size_range_min > ed->text.size_range_max)
11172      {
11173         ERR("parse error %s:%i. min size is bigger than max size.",
11174             file_in, line - 1);
11175         exit(-1);
11176      }
11177 }
11178 
11179 /**
11180     @page edcref
11181 
11182     @property
11183         fit
11184     @parameters
11185         [horizontal] [vertical]
11186     @effect
11187         When any of the parameters is set to 1 edje will resize the text for it
11188         to fit in it's container. Both are disabled by default.
11189 
11190         Defaults: 0 0
11191     @endproperty
11192  */
11193 static void
st_collections_group_parts_part_description_text_fit(void)11194 st_collections_group_parts_part_description_text_fit(void)
11195 {
11196    Edje_Part_Description_Text *ed;
11197 
11198    check_arg_count(2);
11199 
11200    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11201        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11202      {
11203         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11204             file_in, line - 1);
11205         exit(-1);
11206      }
11207 
11208    ed = (Edje_Part_Description_Text *)current_desc;
11209 
11210    ed->text.fit_x = parse_bool(0);
11211    ed->text.fit_y = parse_bool(1);
11212 }
11213 
11214 
11215 /**
11216     @page edcref
11217 
11218     @property
11219         fit_step
11220     @parameters
11221         [font step size in points (pt)]
11222     @effect
11223         Sets the font step size for the text part. when fitting text
11224 
11225         Defaults: 1
11226     @since 1.24.0
11227     @endproperty
11228  */
11229 static void
st_collections_group_parts_part_description_text_fit_step(void)11230 st_collections_group_parts_part_description_text_fit_step(void)
11231 {
11232    Edje_Part_Description_Text *ed;
11233 
11234    check_arg_count(1);
11235 
11236    if (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)
11237      {
11238         ERR("parse error %s:%i. text attributes in non-TEXTBLOCK part.",
11239             file_in, line - 1);
11240         exit(-1);
11241      }
11242 
11243    ed = (Edje_Part_Description_Text *)current_desc;
11244 
11245    ed->text.fit_step = parse_int(0);
11246 
11247    if (ed->text.fit_step < 1)
11248      {
11249           ERR("parse error %s:%i. fit step less than 1.",
11250             file_in, line - 1);
11251         exit(-1);
11252      }
11253 }
11254 
11255 /**
11256     @page edcref
11257 
11258     @property
11259         fit
11260     @parameters
11261         [Array of font sizes in points]
11262     @effect
11263         Sets the allowed font sizes array for the text part.
11264     @since 1.24.0
11265     @endproperty
11266  */
11267 static void
st_collections_group_parts_part_description_text_fit_size_array(void)11268 st_collections_group_parts_part_description_text_fit_size_array(void)
11269 {
11270    int n, argc;
11271    Edje_Part_Description_Text *ed;
11272 
11273    if (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)
11274      {
11275         ERR("parse error %s:%i. text attributes in non-TEXTBLOCK part.",
11276             file_in, line - 1);
11277         exit(-1);
11278      }
11279 
11280    ed = (Edje_Part_Description_Text *)current_desc;
11281    check_min_arg_count(1);
11282 
11283    for (n = 0, argc = get_arg_count(); n < argc; n++)
11284      {
11285         unsigned int *value = malloc(sizeof(unsigned int));
11286         if (value) *value = (unsigned int) parse_int(n);
11287         ed->text.fit_size_array = eina_list_append(ed->text.fit_size_array, value);
11288      }
11289 }
11290 
11291 /**
11292     @page edcref
11293 
11294     @property
11295         min
11296     @parameters
11297         [horizontal] [vertical]
11298     @effect
11299         When any of the parameters is enabled (1) it forces the minimum size of
11300         the container to be equal to the minimum size of the text.
11301 
11302         Defaults: 0 0
11303     @endproperty
11304  */
11305 static void
st_collections_group_parts_part_description_text_min(void)11306 st_collections_group_parts_part_description_text_min(void)
11307 {
11308    Edje_Part_Description_Text *ed;
11309 
11310    check_arg_count(2);
11311 
11312    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11313        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11314      {
11315         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11316             file_in, line - 1);
11317         exit(-1);
11318      }
11319 
11320    ed = (Edje_Part_Description_Text *)current_desc;
11321 
11322    ed->text.min_x = parse_bool(0);
11323    ed->text.min_y = parse_bool(1);
11324 
11325    if (current_part->type == EDJE_PART_TYPE_TEXTBLOCK)
11326      edje_file->has_textblock_min_max = EINA_TRUE;
11327 }
11328 
11329 /**
11330     @page edcref
11331 
11332     @property
11333         max
11334     @parameters
11335         [horizontal] [vertical]
11336     @effect
11337         When any of the parameters is enabled (1) it forces the maximum size of
11338         the container to be equal to the maximum size of the text.
11339 
11340         Defaults: 0 0
11341     @endproperty
11342  */
11343 static void
st_collections_group_parts_part_description_text_max(void)11344 st_collections_group_parts_part_description_text_max(void)
11345 {
11346    Edje_Part_Description_Text *ed;
11347 
11348    check_arg_count(2);
11349 
11350    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11351        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11352      {
11353         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11354             file_in, line - 1);
11355         exit(-1);
11356      }
11357 
11358    ed = (Edje_Part_Description_Text *)current_desc;
11359 
11360    ed->text.max_x = parse_bool(0);
11361    ed->text.max_y = parse_bool(1);
11362 
11363    if (current_part->type == EDJE_PART_TYPE_TEXTBLOCK)
11364      edje_file->has_textblock_min_max = EINA_TRUE;
11365 }
11366 
11367 /**
11368     @page edcref
11369 
11370     @property
11371         align
11372     @parameters
11373         [horizontal] [vertical]
11374     @effect
11375         Change the alignment of the text [0.0(left) - 1.0(right)].
11376         You can set horizontal alignment to -1.0 to use bidirectional based alignment(
11377         0.0 for LTR content or 1.0 for RTL)
11378 
11379         Defaults: 0.5 0.5
11380     @endproperty
11381  */
11382 static void
st_collections_group_parts_part_description_text_align(void)11383 st_collections_group_parts_part_description_text_align(void)
11384 {
11385    Edje_Part_Description_Text *ed;
11386 
11387    check_arg_count(2);
11388 
11389    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11390        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11391      {
11392         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11393             file_in, line - 1);
11394         exit(-1);
11395      }
11396 
11397    ed = (Edje_Part_Description_Text *)current_desc;
11398 
11399    ed->text.align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
11400    ed->text.align.y = FROM_DOUBLE(parse_float_range(1, 0.0, 1.0));
11401 }
11402 
11403 /**
11404     @page edcref
11405 
11406     @property
11407         source
11408     @parameters
11409         [another TEXT part's name]
11410     @effect
11411         Causes the part to use the text properties (like font and size) of
11412         another part and update them as they change.
11413     @endproperty
11414  */
11415 static void
st_collections_group_parts_part_description_text_source(void)11416 st_collections_group_parts_part_description_text_source(void)
11417 {
11418    Edje_Part_Collection *pc;
11419    Edje_Part_Description_Text *ed;
11420 
11421    check_arg_count(1);
11422 
11423    pc = eina_list_data_get(eina_list_last(edje_collections));
11424 
11425    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11426        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11427      {
11428         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11429             file_in, line - 1);
11430         exit(-1);
11431      }
11432 
11433    ed = (Edje_Part_Description_Text *)current_desc;
11434 
11435    {
11436       char *name;
11437 
11438       name = parse_str(0);
11439       data_queue_part_nest_lookup(pc, name, &(ed->text.id_source), &ed->text.id_source_part);
11440       free(name);
11441    }
11442 }
11443 
11444 /**
11445     @page edcref
11446 
11447     @property
11448         text_source
11449     @parameters
11450         [another TEXT part's name]
11451     @effect
11452         Causes the part to display the text content of another part and update
11453         them as they change.
11454     @endproperty
11455  */
11456 static void
st_collections_group_parts_part_description_text_text_source(void)11457 st_collections_group_parts_part_description_text_text_source(void)
11458 {
11459    Edje_Part_Collection *pc;
11460    Edje_Part_Description_Text *ed;
11461 
11462    check_arg_count(1);
11463 
11464    pc = eina_list_data_get(eina_list_last(edje_collections));
11465 
11466    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11467        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11468      {
11469         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11470             file_in, line - 1);
11471         exit(-1);
11472      }
11473 
11474    ed = (Edje_Part_Description_Text *)current_desc;
11475 
11476    {
11477       char *name;
11478 
11479       name = parse_str(0);
11480       data_queue_part_nest_lookup(pc, name, &(ed->text.id_text_source), &ed->text.id_text_source_part);
11481       free(name);
11482    }
11483 }
11484 
11485 /**
11486     @page edcref
11487 
11488     @property
11489         ellipsis
11490     @parameters
11491         [point of balance]
11492     @effect
11493         Used to balance the text in a relative point from 0.0 to 1.0, this
11494         point is the last section of the string to be cut out in case of a
11495         resize that is smaller than the text itself.
11496         Setting -1.0 will disable text cutting.
11497 
11498         Defaults: 0.0
11499     @endproperty
11500  */
11501 static void
st_collections_group_parts_part_description_text_ellipsis(void)11502 st_collections_group_parts_part_description_text_ellipsis(void)
11503 {
11504    Edje_Part_Description_Text *ed;
11505 
11506    check_arg_count(1);
11507 
11508    if ((current_part->type != EDJE_PART_TYPE_TEXT) &&
11509        (current_part->type != EDJE_PART_TYPE_TEXTBLOCK))
11510      {
11511         ERR("parse error %s:%i. text attributes in non-TEXT part.",
11512             file_in, line - 1);
11513         exit(-1);
11514      }
11515 
11516    ed = (Edje_Part_Description_Text *)current_desc;
11517 
11518    ed->text.ellipsis = parse_float_range(0, -1.0, 1.0);
11519 }
11520 
11521 /** @edcsubsection{collections_group_parts_description_box,
11522  *                 Group.Parts.Part.Description.Box} */
11523 
11524 /**
11525     @page edcref
11526 
11527     @block
11528         box
11529     @context
11530         part {
11531             description {
11532                 ..
11533                 box {
11534                     layout: "vertical";
11535                     padding: 0 2;
11536                     align: 0.5 0.5;
11537                     min: 0 0;
11538                 }
11539                 ..
11540             }
11541         }
11542     @description
11543         A box block can contain other objects and display them in different
11544         layouts, any of the predefined set, or a custom one, set by the
11545         application.
11546     @endblock
11547 
11548     @property
11549         layout
11550     @parameters
11551         [primary layout] (fallback layout)
11552     @effect
11553         Sets the layout for the box:
11554             @li horizontal
11555             @li vertical
11556             @li horizontal_homogeneous
11557             @li vertical_homogeneous
11558             @li horizontal_max (homogeneous to the max sized child)
11559             @li vertical_max
11560             @li horizontal_flow
11561             @li vertical_flow
11562             @li stack
11563             @li some_other_custom_layout_set_by_the_application
11564         You could set a custom layout as fallback, it makes very
11565         very little sense though, and if that one fails, it will
11566         default to horizontal.
11567 
11568         Defaults: "horizontal"
11569     @endproperty
11570  */
11571 static void
st_collections_group_parts_part_description_box_layout(void)11572 st_collections_group_parts_part_description_box_layout(void)
11573 {
11574    Edje_Part_Description_Box *ed;
11575 
11576    check_min_arg_count(1);
11577 
11578    if (current_part->type != EDJE_PART_TYPE_BOX)
11579      {
11580         ERR("parse error %s:%i. box attributes in non-BOX part.",
11581             file_in, line - 1);
11582         exit(-1);
11583      }
11584 
11585    ed = (Edje_Part_Description_Box *)current_desc;
11586 
11587    ed->box.layout = parse_str(0);
11588    if (is_param(1))
11589      ed->box.alt_layout = parse_str(1);
11590 }
11591 
11592 /**
11593     @page edcref
11594     @property
11595         align
11596     @parameters
11597         [horizontal] [vertical]
11598     @effect
11599         Change the position of the point of balance inside the box [-1.0 - 1.0].
11600 
11601         Defaults: 0.5 0.5
11602     @endproperty
11603  */
11604 static void
st_collections_group_parts_part_description_box_align(void)11605 st_collections_group_parts_part_description_box_align(void)
11606 {
11607    Edje_Part_Description_Box *ed;
11608 
11609    check_arg_count(2);
11610 
11611    if (current_part->type != EDJE_PART_TYPE_BOX)
11612      {
11613         ERR("parse error %s:%i. box attributes in non-BOX part.",
11614             file_in, line - 1);
11615         exit(-1);
11616      }
11617 
11618    ed = (Edje_Part_Description_Box *)current_desc;
11619 
11620    ed->box.align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
11621    ed->box.align.y = FROM_DOUBLE(parse_float_range(1, -1.0, 1.0));
11622 }
11623 
11624 /**
11625     @page edcref
11626     @property
11627         padding
11628     @parameters
11629         [horizontal] [vertical]
11630     @effect
11631         Sets the space between box items in pixels.
11632 
11633         Defaults: 0 0
11634     @endproperty
11635  */
11636 static void
st_collections_group_parts_part_description_box_padding(void)11637 st_collections_group_parts_part_description_box_padding(void)
11638 {
11639    Edje_Part_Description_Box *ed;
11640 
11641    check_arg_count(2);
11642 
11643    if (current_part->type != EDJE_PART_TYPE_BOX)
11644      {
11645         ERR("parse error %s:%i. box attributes in non-BOX part.",
11646             file_in, line - 1);
11647         exit(-1);
11648      }
11649 
11650    ed = (Edje_Part_Description_Box *)current_desc;
11651 
11652    ed->box.padding.x = parse_int_range(0, 0, 0x7fffffff);
11653    ed->box.padding.y = parse_int_range(1, 0, 0x7fffffff);
11654 }
11655 
11656 /**
11657     @page edcref
11658     @property
11659         min
11660     @parameters
11661         [horizontal] [vertical]
11662     @effect
11663         When any of the parameters is enabled (1) it forces the minimum size of
11664         the box to be equal to the minimum size of the items.
11665 
11666         Defaults: 0 0
11667     @endproperty
11668  */
11669 static void
st_collections_group_parts_part_description_box_min(void)11670 st_collections_group_parts_part_description_box_min(void)
11671 {
11672    Edje_Part_Description_Box *ed;
11673 
11674    check_arg_count(2);
11675 
11676    if (current_part->type != EDJE_PART_TYPE_BOX)
11677      {
11678         ERR("parse error %s:%i. box attributes in non-BOX part.",
11679             file_in, line - 1);
11680         exit(-1);
11681      }
11682 
11683    ed = (Edje_Part_Description_Box *)current_desc;
11684 
11685    ed->box.min.h = parse_bool(0);
11686    ed->box.min.v = parse_bool(1);
11687 }
11688 
11689 /** @edcsubsection{collections_group_parts_description_table,
11690  *                 Group.Parts.Part.Description.Table} */
11691 
11692 /**
11693     @page edcref
11694 
11695     @block
11696         table
11697     @context
11698         part {
11699             description {
11700                 ..
11701                 table {
11702                     homogeneous: TABLE;
11703                     padding: 0 2;
11704                     align: 0.5 0.5;
11705                     min: 0 0;
11706                 }
11707                 ..
11708             }
11709         }
11710     @description
11711         A table block can contain other objects packed in multiple columns
11712         and rows, and each item can span across more than one column and/or
11713         row.
11714     @endblock
11715 
11716     @property
11717         homogeneous
11718     @parameters
11719         [homogeneous mode]
11720     @effect
11721         Sets the homogeneous mode for the table:
11722             @li NONE
11723             @li TABLE
11724             @li ITEM
11725 
11726         Defaults: NONE
11727     @endproperty
11728  */
11729 static void
st_collections_group_parts_part_description_table_homogeneous(void)11730 st_collections_group_parts_part_description_table_homogeneous(void)
11731 {
11732    Edje_Part_Description_Table *ed;
11733 
11734    check_min_arg_count(1);
11735 
11736    if (current_part->type != EDJE_PART_TYPE_TABLE)
11737      {
11738         ERR("parse error %s:%i. table attributes in non-TABLE part.",
11739             file_in, line - 1);
11740         exit(-1);
11741      }
11742 
11743    ed = (Edje_Part_Description_Table *)current_desc;
11744 
11745    ed->table.homogeneous = parse_enum(0,
11746                                       "NONE", EDJE_OBJECT_TABLE_HOMOGENEOUS_NONE,
11747                                       "TABLE", EDJE_OBJECT_TABLE_HOMOGENEOUS_TABLE,
11748                                       "ITEM", EDJE_OBJECT_TABLE_HOMOGENEOUS_ITEM,
11749                                       NULL);
11750 }
11751 
11752 /**
11753     @page edcref
11754     @property
11755         align
11756     @parameters
11757         [horizontal] [vertical]
11758     @effect
11759         Change the position of the point of balance inside the table [-1.0 - 1.0].
11760 
11761         Defaults: 0.5 0.5
11762     @endproperty
11763  */
11764 static void
st_collections_group_parts_part_description_table_align(void)11765 st_collections_group_parts_part_description_table_align(void)
11766 {
11767    Edje_Part_Description_Table *ed;
11768 
11769    check_arg_count(2);
11770 
11771    if (current_part->type != EDJE_PART_TYPE_TABLE)
11772      {
11773         ERR("parse error %s:%i. table attributes in non-TABLE part.",
11774             file_in, line - 1);
11775         exit(-1);
11776      }
11777 
11778    ed = (Edje_Part_Description_Table *)current_desc;
11779 
11780    ed->table.align.x = FROM_DOUBLE(parse_float_range(0, -1.0, 1.0));
11781    ed->table.align.y = FROM_DOUBLE(parse_float_range(1, -1.0, 1.0));
11782 }
11783 
11784 /**
11785     @page edcref
11786     @property
11787         padding
11788     @parameters
11789         [horizontal] [vertical]
11790     @effect
11791         Sets the space between table cells in pixels.
11792 
11793         Defaults: 0 0
11794     @endproperty
11795  */
11796 static void
st_collections_group_parts_part_description_table_padding(void)11797 st_collections_group_parts_part_description_table_padding(void)
11798 {
11799    Edje_Part_Description_Table *ed;
11800 
11801    check_arg_count(2);
11802 
11803    if (current_part->type != EDJE_PART_TYPE_TABLE)
11804      {
11805         ERR("parse error %s:%i. table attributes in non-TABLE part.",
11806             file_in, line - 1);
11807         exit(-1);
11808      }
11809 
11810    ed = (Edje_Part_Description_Table *)current_desc;
11811 
11812    ed->table.padding.x = parse_int_range(0, 0, 0x7fffffff);
11813    ed->table.padding.y = parse_int_range(1, 0, 0x7fffffff);
11814 }
11815 
11816 /**
11817     @page edcref
11818     @property
11819         min
11820     @parameters
11821         [horizontal] [vertical]
11822     @effect
11823         When any of the parameters is enabled (1) it forces the minimum size of
11824         the table to be equal to the minimum size of the items.
11825 
11826         Defaults: 0 0
11827     @endproperty
11828  */
11829 static void
st_collections_group_parts_part_description_table_min(void)11830 st_collections_group_parts_part_description_table_min(void)
11831 {
11832    Edje_Part_Description_Table *ed;
11833 
11834    check_arg_count(2);
11835 
11836    if (current_part->type != EDJE_PART_TYPE_TABLE)
11837      {
11838         ERR("parse error %s:%i. table attributes in non-TABLE part.",
11839             file_in, line - 1);
11840         exit(-1);
11841      }
11842 
11843    ed = (Edje_Part_Description_Table *)current_desc;
11844 
11845    ed->table.min.h = parse_bool(0);
11846    ed->table.min.v = parse_bool(1);
11847 }
11848 
11849 /**
11850    @edcsubsection{collections_group_parts_description_proxy,
11851                   Group.Parts.Part.Description.Proxy}
11852  */
11853 
11854 /**
11855     @page edcref
11856 
11857     @block
11858         proxy
11859     @context
11860         part { type: PROXY;
11861             description {
11862                 ..
11863                 proxy {
11864                     source_clip:    1;
11865                     source_visible: 1;
11866                 }
11867                 ..
11868             }
11869         }
11870     @description
11871         State flags used for proxy objects.
11872     @endblock
11873 
11874     @property
11875         source_clip
11876     @parameters
11877         [0 or 1]
11878     @effect
11879         Sets the 'source_clip' property on this PROXY object. True by default,
11880         this means the proxy will be clipped by its source clipper. False
11881         means the source clipper is ignored when rendering the proxy.
11882 
11883         Defaults: 1
11884     @endproperty
11885 
11886     @property
11887         source_visible
11888     @parameters
11889         [0 or 1]
11890     @effect
11891         Sets the 'source_visible' property on this PROXY object. True by
11892         default, meaning both the proxy and its source object will be visible.
11893         If false, the source object will not be visible. False is equivalent
11894         to setting the 'no_render' flag on the source object itself.
11895 
11896         Defaults: 1
11897     @endproperty
11898  */
11899 static void
st_collections_group_parts_part_description_proxy_source_clip(void)11900 st_collections_group_parts_part_description_proxy_source_clip(void)
11901 {
11902    Edje_Part_Description_Proxy *ed;
11903 
11904    check_arg_count(1);
11905 
11906    if (current_part->type != EDJE_PART_TYPE_PROXY)
11907      {
11908         ERR("parse error %s:%i. proxy attributes in non-PROXY part.",
11909             file_in, line - 1);
11910         exit(-1);
11911      }
11912 
11913    ed = (Edje_Part_Description_Proxy *)current_desc;
11914    ed->proxy.source_clip = parse_bool(0);
11915 }
11916 
11917 static void
st_collections_group_parts_part_description_proxy_source_visible(void)11918 st_collections_group_parts_part_description_proxy_source_visible(void)
11919 {
11920    Edje_Part_Description_Proxy *ed;
11921 
11922    check_arg_count(1);
11923 
11924    if (current_part->type != EDJE_PART_TYPE_PROXY)
11925      {
11926         ERR("parse error %s:%i. proxy attributes in non-PROXY part.",
11927             file_in, line - 1);
11928         exit(-1);
11929      }
11930 
11931    ed = (Edje_Part_Description_Proxy *)current_desc;
11932    ed->proxy.source_visible = parse_bool(0);
11933 }
11934 
11935 
11936 /** @edcsubsection{collections_group_parts_description_physics,
11937  *                 Group.Parts.Part.Description.Physics} */
11938 
11939 /**
11940     @page edcref
11941     @block
11942         physics
11943     @context
11944     description {
11945         ..
11946         physics {
11947             ignore_part_pos: 1;
11948             mass: 5.31;
11949             friction: 0.5;
11950             restitution: 0.82;
11951             damping: 0.4 0.24;
11952             sleep: 32 18.9;
11953             material: IRON;
11954             density: 3.2;
11955             hardness: 0.42;
11956             light_on: 1;
11957             z: -15;
11958             depth: 30;
11959             movement_freedom { }
11960             faces { }
11961         }
11962         ..
11963     }
11964 
11965     @description
11966         Physics block should be used to configure the body associated to the
11967         part. The part's property physics_body needs to be set to something
11968         different from NONE, otherwise the properties inside physics block
11969         won't have any effect.
11970         It's possible to set body's material, mass, restitution, friction,
11971         allow / disallow movement in specific axes, etc.
11972     @endblock
11973 
11974     @property
11975         mass
11976     @parameters
11977         [body's mass in kilograms]
11978     @effect
11979         Double value used to set inertial mass of the body.
11980         It is a quantitative measure of an object's resistance to the change of
11981         its speed. If mass is set to 0 the body will have infinite mass,
11982         so it will be immovable, static.
11983     @since 1.8
11984     @endproperty
11985  */
11986 
11987 #ifdef HAVE_EPHYSICS
11988 static void
st_collections_group_parts_part_description_physics_mass(void)11989 st_collections_group_parts_part_description_physics_mass(void)
11990 {
11991    check_arg_count(1);
11992 
11993    current_desc->physics.mass = parse_float(0);
11994 }
11995 
11996 #endif
11997 
11998 /**
11999     @page edcref
12000     @property
12001         restitution
12002     @parameters
12003         [body's restitution]
12004     @effect
12005         The coefficient of restitution is proporcion between speed after and
12006         before a collision. It's 0 by default.
12007 
12008         COR = relative speed after collision / relative speed before collision
12009 
12010         @li elastically collide for COR == 1;
12011         @li inelastically collide for 0 < COR < 1;
12012         @li completelly stop (no bouncing at all) for COR == 0.
12013 
12014     @since 1.8
12015     @endproperty
12016  */
12017 
12018 #ifdef HAVE_EPHYSICS
12019 static void
st_collections_group_parts_part_description_physics_restitution(void)12020 st_collections_group_parts_part_description_physics_restitution(void)
12021 {
12022    check_arg_count(1);
12023 
12024    current_desc->physics.restitution = parse_float(0);
12025 }
12026 
12027 #endif
12028 
12029 /**
12030     @page edcref
12031     @property
12032         friction
12033     @parameters
12034         [body's friction]
12035     @effect
12036         Friction is used to make objects slide along each ot
12037 
12038         The friction parameter is usually set between 0 and 1, but can be any
12039         non-negative value. A friction value of 0 turns off friction and a value
12040         of 1 makes the friction strong.
12041 
12042         By default friction value is 0.5 and simulation resulsts will be better
12043         when friction in non-zero.
12044 
12045     @since 1.8
12046     @endproperty
12047  */
12048 
12049 #ifdef HAVE_EPHYSICS
12050 static void
st_collections_group_parts_part_description_physics_friction(void)12051 st_collections_group_parts_part_description_physics_friction(void)
12052 {
12053    check_arg_count(1);
12054 
12055    current_desc->physics.friction = parse_float(0);
12056 }
12057 
12058 #endif
12059 
12060 /**
12061     @page edcref
12062     @property
12063         ignore_part_pos
12064     @parameters
12065         [1 or 0]
12066     @effect
12067         If enabled, the body won't be positioned following rel1/rel2.
12068         It will keep its position updated only by physics calculations.
12069         If disabled, when the state is set, the body will be moved to
12070         the position described by the blocks rel1/rel2.
12071         Default is 1 (enabled).
12072     @since 1.8
12073     @endproperty
12074  */
12075 #ifdef HAVE_EPHYSICS
12076 static void
st_collections_group_parts_part_description_physics_ignore_part_pos(void)12077 st_collections_group_parts_part_description_physics_ignore_part_pos(void)
12078 {
12079    check_arg_count(1);
12080 
12081    current_desc->physics.ignore_part_pos = parse_bool(0);
12082 }
12083 
12084 #endif
12085 
12086 /**
12087     @page edcref
12088     @property
12089         damping
12090     @parameters
12091         [linear damping] [angular damping]
12092     @effect
12093         Damping(linear and angular) values are applied to body's linear and
12094         angular velocity.
12095         By applying a bodies damping factor the user will face a velocity
12096         reduction, with a force applied to it - "like" air resistance.
12097         The force is applied to slow it down.
12098         Values should be between 0.0 and 1.0, and are set to 0 by default.
12099     @since 1.8
12100     @endproperty
12101  */
12102 #ifdef HAVE_EPHYSICS
12103 static void
st_collections_group_parts_part_description_physics_damping(void)12104 st_collections_group_parts_part_description_physics_damping(void)
12105 {
12106    check_arg_count(2);
12107 
12108    current_desc->physics.damping.linear = parse_float_range(0, 0, 1.0);
12109    current_desc->physics.damping.angular = parse_float_range(1, 0, 1.0);
12110 }
12111 
12112 #endif
12113 
12114 /**
12115     @page edcref
12116     @property
12117         sleep
12118     @parameters
12119         [linear sleeping threshold] [angular sleeping threshold]
12120     @effect
12121         Sleeping threshold factors are used to determine whenever a rigid body
12122         is supposed to increment the sleeping time. Linear threshold is
12123         measured in Evas coordinates per second and angular threshold is
12124         measured in degrees per second.
12125         After every tick the sleeping time is incremented, if the body's
12126         linear and angular speed is less than the respective thresholds
12127         the sleeping time is incremented by the current time step (delta time).
12128         Reaching the max sleeping time the body is marked to sleep, that means
12129         the rigid body is to be deactivated.
12130         By default linear threshold is 24 pixels / second and angular is
12131         57.29 degrees / sec (1 rad/sec).
12132     @since 1.8
12133     @endproperty
12134  */
12135 #ifdef HAVE_EPHYSICS
12136 static void
st_collections_group_parts_part_description_physics_sleep(void)12137 st_collections_group_parts_part_description_physics_sleep(void)
12138 {
12139    check_arg_count(2);
12140 
12141    current_desc->physics.sleep.linear = parse_float(0);
12142    current_desc->physics.sleep.angular = parse_float(1);
12143 }
12144 
12145 #endif
12146 
12147 /**
12148     @page edcref
12149     @property
12150         material
12151     @parameters
12152         [body's material]
12153     @effect
12154         Set the type (all caps) from among the available material types,
12155         it's set to CUSTOM by default.
12156         Each material has specific properties to be
12157         applied on the body, as density, friction and restitution.
12158         So if a material different of CUSTOM is set, the properties cited above
12159         won't be considered.
12160         Valid types:
12161           @li CUSTOM
12162           @li CONCRETE
12163           @li IRON
12164           @li PLASTIC
12165           @li POLYSTYRENE
12166           @li RUBBER
12167           @li WOOD
12168 
12169     @since 1.8
12170     @endproperty
12171  */
12172 #ifdef HAVE_EPHYSICS
12173 static void
st_collections_group_parts_part_description_physics_material(void)12174 st_collections_group_parts_part_description_physics_material(void)
12175 {
12176    check_arg_count(1);
12177 
12178    current_desc->physics.material = parse_enum(0,
12179                                                "CUSTOM", EPHYSICS_BODY_MATERIAL_CUSTOM,
12180                                                "CONCRETE", EPHYSICS_BODY_MATERIAL_CONCRETE,
12181                                                "IRON", EPHYSICS_BODY_MATERIAL_IRON,
12182                                                "PLASTIC", EPHYSICS_BODY_MATERIAL_PLASTIC,
12183                                                "POLYSTYRENE", EPHYSICS_BODY_MATERIAL_POLYSTYRENE,
12184                                                "RUBBER", EPHYSICS_BODY_MATERIAL_RUBBER,
12185                                                "WOOD", EPHYSICS_BODY_MATERIAL_WOOD,
12186                                                NULL);
12187 }
12188 
12189 #endif
12190 
12191 /**
12192     @page edcref
12193     @property
12194         density
12195     @parameters
12196         [body's material density]
12197     @effect
12198         It will set the body mass considering its volume. While a density is
12199         set, resizing a body will always recalculate its mass.
12200         When a mass is explicitely set the density will be unset.
12201     @since 1.8
12202     @endproperty
12203  */
12204 #ifdef HAVE_EPHYSICS
12205 static void
st_collections_group_parts_part_description_physics_density(void)12206 st_collections_group_parts_part_description_physics_density(void)
12207 {
12208    check_arg_count(1);
12209 
12210    current_desc->physics.density = parse_float(0);
12211 }
12212 
12213 #endif
12214 
12215 /**
12216     @page edcref
12217     @property
12218         hardness
12219     @parameters
12220         [soft body or cloth hardness]
12221     @effect
12222         The hardness is set with a double value (0.0 - 1.0), defining
12223         how the soft body is supposed to deform.
12224         Its default is set to 1.0. The soft body mass will also interfere on
12225         soft body deformation, so bare in mind that the bodies mass must also
12226         be changed to have different deformation results.
12227         Valid values vary from 0.0 to 1.0. Only works on soft bodies and cloths.
12228     @since 1.8
12229     @endproperty
12230  */
12231 #ifdef HAVE_EPHYSICS
12232 static void
st_collections_group_parts_part_description_physics_hardness(void)12233 st_collections_group_parts_part_description_physics_hardness(void)
12234 {
12235    check_arg_count(1);
12236 
12237    current_desc->physics.hardness = parse_float_range(0, 0, 1.0);
12238 }
12239 
12240 #endif
12241 
12242 /**
12243     @page edcref
12244     @property
12245         light_on
12246     @parameters
12247         [1 or 0]
12248     @effect
12249         Set body to be affected by world's light or not.
12250         It won't be respected if world's property "all_bodies" is enabled.
12251         Disabled by default (0).
12252     @since 1.8
12253     @endproperty
12254  */
12255 #ifdef HAVE_EPHYSICS
12256 static void
st_collections_group_parts_part_description_physics_light_on(void)12257 st_collections_group_parts_part_description_physics_light_on(void)
12258 {
12259    check_arg_count(1);
12260 
12261    current_desc->physics.light_on = parse_bool(0);
12262 }
12263 
12264 #endif
12265 
12266 /**
12267     @page edcref
12268     @property
12269         z
12270     @parameters
12271         [body position in z axis]
12272     @effect
12273         Defines body position in z axis. It's set to -15 by default.
12274     @since 1.8
12275     @endproperty
12276  */
12277 #ifdef HAVE_EPHYSICS
12278 static void
st_collections_group_parts_part_description_physics_z(void)12279 st_collections_group_parts_part_description_physics_z(void)
12280 {
12281    check_arg_count(1);
12282 
12283    current_desc->physics.z = parse_int(0);
12284 }
12285 
12286 #endif
12287 
12288 /**
12289     @page edcref
12290     @property
12291         depth
12292     @parameters
12293         [body's depth]
12294     @effect
12295         Defines body's depth (z axis). It's set to 30 by default.
12296     @since 1.8
12297     @endproperty
12298  */
12299 #ifdef HAVE_EPHYSICS
12300 static void
st_collections_group_parts_part_description_physics_depth(void)12301 st_collections_group_parts_part_description_physics_depth(void)
12302 {
12303    check_arg_count(1);
12304 
12305    current_desc->physics.depth = parse_int(0);
12306 }
12307 
12308 #endif
12309 
12310 /**
12311     @page edcref
12312     @property
12313         backface_cull
12314     @parameters
12315         [1 or 0]
12316     @effect
12317         This enables backface culling (when the rotated part that normally faces
12318         the camera is facing away after being rotated etc.).
12319         This means that the object will be hidden when "backface culled".
12320     @since 1.8
12321     @endproperty
12322  */
12323 #ifdef HAVE_EPHYSICS
12324 static void
st_collections_group_parts_part_description_physics_backface_cull(void)12325 st_collections_group_parts_part_description_physics_backface_cull(void)
12326 {
12327    check_arg_count(1);
12328 
12329    current_desc->physics.backcull = parse_bool(0);
12330 }
12331 
12332 #endif
12333 
12334 /** @edcsubsection{collections_group_parts_description_physics_movement_freedom,
12335  *                 Group.Parts.Part.Description.Physics.Movement_Freedom} */
12336 
12337 /**
12338     @page edcref
12339     @block
12340         movement_freedom
12341     @context
12342         physics {
12343             ...
12344             movement_freedom {
12345                 linear: 1 1 0;
12346                 angular: 0 0 1;
12347             }
12348         }
12349         ..
12350     @description
12351         The "movement_freedom" block consists of two blocks to describe all
12352         the allowed movements for a body.
12353         It's set by default to allow just 2D movement (linear moves on
12354         x and y axis and rotations on x-y plane).
12355     @endblock
12356 
12357     @property
12358         linear
12359     @parameters
12360         [x-axis (1 or 0)] [y-axis (1 or 0)] [z-axis (1 or 0)]
12361     @effect
12362         Block "linear" can be used to allow linear movements in the three
12363         axes. Allowed values are 0 or 1.
12364         Axes x and y are enabled by default.
12365     @since 1.8
12366     @endproperty
12367  */
12368 #ifdef HAVE_EPHYSICS
12369 static void
st_collections_group_parts_part_description_physics_movement_freedom_linear(void)12370 st_collections_group_parts_part_description_physics_movement_freedom_linear(void)
12371 {
12372    check_arg_count(3);
12373 
12374    current_desc->physics.mov_freedom.lin.x = parse_bool(0);
12375    current_desc->physics.mov_freedom.lin.y = parse_bool(1);
12376    current_desc->physics.mov_freedom.lin.z = parse_bool(2);
12377 }
12378 
12379 #endif
12380 
12381 /**
12382     @page edcref
12383     @property
12384         angular
12385     @parameters
12386         [x-axis (1 or 0)] [y-axis (1 or 0)] [z-axis (1 or 0)]
12387     @effect
12388         Block "angular" can be used to allow angular movements around the three
12389         axes. Allowed values are 0 or 1.
12390         Z axis is enabled by default.
12391     @since 1.8
12392     @endproperty
12393  */
12394 #ifdef HAVE_EPHYSICS
12395 static void
st_collections_group_parts_part_description_physics_movement_freedom_angular(void)12396 st_collections_group_parts_part_description_physics_movement_freedom_angular(void)
12397 {
12398    check_arg_count(3);
12399 
12400    current_desc->physics.mov_freedom.ang.x = parse_bool(0);
12401    current_desc->physics.mov_freedom.ang.y = parse_bool(1);
12402    current_desc->physics.mov_freedom.ang.z = parse_bool(2);
12403 }
12404 
12405 #endif
12406 
12407 /** @edcsubsection{collections_group_parts_description_physics_faces,
12408  *                 Group.Parts.Part.Description.Physics.Faces} */
12409 
12410 /**
12411     @page edcref
12412     @block
12413         faces
12414     @context
12415         physics {
12416             ...
12417             faces {
12418                 face {
12419                     type: BOX_FRONT;
12420                     source:  "groupname";
12421                 }
12422                 ..
12423             }
12424             ..
12425         }
12426     @description
12427         The "faces" block contains a list of one or more "face" blocks.
12428         The "faces" block is used to list the faces that compose the body.
12429         Each face is described by a "face" block, that associates a part
12430         to a specific face of the body's shape.
12431         Only the "faces" block declared in the "default" description
12432         will be considered.
12433     @endblock
12434  */
12435 #ifdef HAVE_EPHYSICS
12436 static void
st_collections_group_parts_part_description_physics_face(void)12437 st_collections_group_parts_part_description_physics_face(void)
12438 {
12439    Edje_Physics_Face *pface;
12440 
12441    pface = mem_alloc(SZ(Edje_Physics_Face));
12442    current_desc->physics.faces = eina_list_append(current_desc->physics.faces,
12443                                                   pface);
12444    pface->type = 0;
12445    pface->source = NULL;
12446 }
12447 
12448 #endif
12449 
12450 /**
12451     @page edcref
12452     @property
12453         type
12454     @parameters
12455         [FACE]
12456     @effect
12457         Set the face (all caps) from among the available body's shape faces.
12458         Valid faces:
12459             @li BOX_MIDDLE_FRONT
12460             @li BOX_MIDDLE_BACK
12461             @li BOX_FRONT
12462             @li BOX_BACK
12463             @li BOX_LEFT
12464             @li BOX_RIGHT
12465             @li BOX_TOP
12466             @li BOX_BOTTOM
12467             @li CLOTH_FRONT
12468             @li CLOTH_BACK
12469             @li CYLINDER_MIDDLE_FRONT
12470             @li CYLINDER_MIDDLE_BACK
12471             @li CYLINDER_FRONT
12472             @li CYLINDER_BACK
12473             @li CYLINDER_CURVED
12474             @li SPHERE_FRONT
12475             @li SPHERE_BACK
12476     @endproperty
12477  */
12478 #ifdef HAVE_EPHYSICS
12479 static void
st_collections_group_parts_part_description_physics_face_type(void)12480 st_collections_group_parts_part_description_physics_face_type(void)
12481 {
12482    Edje_Physics_Face *pface, *pface2;
12483    Eina_List *l;
12484 
12485    pface = eina_list_data_get(eina_list_last(current_desc->physics.faces));
12486    pface->type = parse_enum(0,
12487                             "BOX_MIDDLE_FRONT", EPHYSICS_BODY_BOX_FACE_MIDDLE_FRONT,
12488                             "BOX_MIDDLE_BACK", EPHYSICS_BODY_BOX_FACE_MIDDLE_BACK,
12489                             "BOX_FRONT", EPHYSICS_BODY_BOX_FACE_FRONT,
12490                             "BOX_BACK", EPHYSICS_BODY_BOX_FACE_BACK,
12491                             "BOX_LEFT", EPHYSICS_BODY_BOX_FACE_LEFT,
12492                             "BOX_RIGHT", EPHYSICS_BODY_BOX_FACE_RIGHT,
12493                             "BOX_TOP", EPHYSICS_BODY_BOX_FACE_TOP,
12494                             "BOX_BOTTOM", EPHYSICS_BODY_BOX_FACE_BOTTOM,
12495                             "CLOTH_FRONT", EPHYSICS_BODY_CLOTH_FACE_FRONT,
12496                             "CLOTH_BACK", EPHYSICS_BODY_CLOTH_FACE_BACK,
12497                             "CYLINDER_MIDDLE_FRONT", EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_FRONT,
12498                             "CYLINDER_MIDDLE_BACK", EPHYSICS_BODY_CYLINDER_FACE_MIDDLE_BACK,
12499                             "CYLINDER_FRONT", EPHYSICS_BODY_CYLINDER_FACE_FRONT,
12500                             "CYLINDER_BACK", EPHYSICS_BODY_CYLINDER_FACE_BACK,
12501                             "CYLINDER_CURVED", EPHYSICS_BODY_CYLINDER_FACE_CURVED,
12502                             "SPHERE_FRONT", EPHYSICS_BODY_SPHERE_FACE_FRONT,
12503                             "SPHERE_BACK", EPHYSICS_BODY_SPHERE_FACE_BACK,
12504                             NULL);
12505 
12506    EINA_LIST_FOREACH(current_desc->physics.faces, l, pface2)
12507      {
12508         if ((pface != pface2) && (pface->type == pface2->type))
12509           {
12510              ERR("parse error %s:%i. There is already a face of type \"%i\"",
12511                  file_in, line - 1, pface->type);
12512              exit(-1);
12513           }
12514      }
12515 }
12516 
12517 #endif
12518 
12519 /**
12520     @page edcref
12521     @property
12522         source
12523     @parameters
12524         [another group's name]
12525     @effect
12526         This sets the group that is used as the object representing the physics
12527         body face.
12528     @endproperty
12529  */
12530 #ifdef HAVE_EPHYSICS
12531 static void
st_collections_group_parts_part_description_physics_face_source(void)12532 st_collections_group_parts_part_description_physics_face_source(void)
12533 {
12534    Edje_Physics_Face *pface;
12535 
12536    pface = eina_list_data_get(eina_list_last(current_desc->physics.faces));
12537    check_arg_count(1);
12538 
12539    pface->source = parse_str(0);
12540    data_queue_face_group_lookup(pface->source);
12541 }
12542 
12543 #endif
12544 
12545 /** @edcsubsection{collections_group_parts_description_map,
12546  *                 Group.Parts.Part.Description.Map} */
12547 
12548 /**
12549     @page edcref
12550     @block
12551         map
12552     @context
12553     description {
12554         ..
12555         map {
12556             perspective: "name";
12557             light: "name";
12558             on: 1;
12559             smooth: 1;
12560             perspective_on: 1;
12561             backface_cull: 1;
12562             alpha: 1;
12563 
12564             rotation {
12565                 ..
12566             }
12567         }
12568         ..
12569     }
12570 
12571     @description
12572     @endblock
12573 
12574     @property
12575         perspective
12576     @parameters
12577         [another part's name]
12578     @effect
12579         This sets the part that is used as the "perspective point" for giving
12580         a part a "3d look". The perspective point should have a perspective
12581         section that provides zplane and focal properties. The center of this
12582         part will be used as the focal point, so size, color and visibility
12583         etc. are not relevant just center point, zplane and focal are used.
12584         This also implicitly enables perspective transforms (see the on
12585         parameter for the map section).
12586     @endproperty
12587  */
12588 static void
st_collections_group_parts_part_description_map_perspective(void)12589 st_collections_group_parts_part_description_map_perspective(void)
12590 {
12591    Edje_Part_Collection *pc;
12592 
12593    check_arg_count(1);
12594 
12595    pc = eina_list_data_get(eina_list_last(edje_collections));
12596 
12597    {
12598       char *name;
12599 
12600       name = parse_str(0);
12601       data_queue_part_lookup(pc, name, &(current_desc->map.id_persp));
12602       free(name);
12603    }
12604 
12605    current_desc->map.persp_on = 1;
12606 }
12607 
12608 /**
12609     @page edcref
12610     @property
12611         light
12612     @parameters
12613         [another part's name]
12614     @effect
12615         This sets the part that is used as the "light" for calculating the
12616         brightness (based on how directly the part's surface is facing the
12617         light source point). Like the perspective point part, the center point
12618         is used and zplane is used for the z position (0 being the zero-plane
12619         where all 2D objects normally live) and positive values being further
12620         away into the distance. The light part color is used as the light
12621         color (alpha not used for light color). The color2 color is used for
12622         the ambient lighting when calculating brightness (alpha also not
12623         used).
12624     @endproperty
12625  */
12626 static void
st_collections_group_parts_part_description_map_light(void)12627 st_collections_group_parts_part_description_map_light(void)
12628 {
12629    Edje_Part_Collection *pc;
12630 
12631    check_arg_count(1);
12632 
12633    pc = eina_list_data_get(eina_list_last(edje_collections));
12634 
12635    {
12636       char *name;
12637 
12638       name = parse_str(0);
12639       data_queue_part_lookup(pc, name, &(current_desc->map.id_light));
12640       free(name);
12641    }
12642 }
12643 
12644 /** @edcsubsection{collections_group_parts_description_map_zoom,
12645  *                 Group.Parts.Part.Description.Map.Zoom} */
12646 
12647 /**
12648     @page edcref
12649     @block
12650         rotation
12651     @context
12652     map {
12653         ..
12654         zoom {
12655             center: "name";
12656             x: 1.0;
12657             y: 1.0;
12658         }
12659         ..
12660     }
12661     @description
12662         Zooms the part, optionally from the center on another part.
12663     @endblock
12664 
12665     @property
12666         center
12667     @parameters
12668         [another part's name]
12669     @effect
12670         This sets the part that is used as the center of zoom when
12671         zooming the part with this description. The part's center point
12672         is used as the zoom center when applying zoom from the
12673         x and y axes. If no center is given, the parts original center
12674         itself is used for the zoom center.
12675     @endproperty
12676 */
12677 static void
st_collections_group_parts_part_description_map_zoom_center(void)12678 st_collections_group_parts_part_description_map_zoom_center(void)
12679 {
12680    Edje_Part_Collection *pc;
12681 
12682    check_arg_count(1);
12683 
12684    pc = eina_list_data_get(eina_list_last(edje_collections));
12685 
12686    {
12687       char *name;
12688 
12689       name = parse_str(0);
12690       data_queue_part_lookup(pc, name, &(current_desc->map.zoom.id_center));
12691       free(name);
12692    }
12693 }
12694 
12695 /**
12696     @page edcref
12697     @property
12698         on
12699     @parameters
12700         [1 or 0]
12701     @effect
12702         This enables mapping for the part.
12703 
12704         Defaults: 0
12705     @endproperty
12706  */
12707 static void
st_collections_group_parts_part_description_map_on(void)12708 st_collections_group_parts_part_description_map_on(void)
12709 {
12710    check_arg_count(1);
12711 
12712    current_desc->map.on = parse_bool(0);
12713 }
12714 
12715 /**
12716     @page edcref
12717     @property
12718         smooth
12719     @parameters
12720         [1 or 0]
12721     @effect
12722         This enable smooth map rendering. This may be linear interpolation,
12723         anisotropic filtering or anything the engine decides is "smooth".
12724         This is a best-effort hint and may not produce precisely the same
12725         results in all engines and situations.
12726 
12727         Defaults: 1
12728     @endproperty
12729  */
12730 static void
st_collections_group_parts_part_description_map_smooth(void)12731 st_collections_group_parts_part_description_map_smooth(void)
12732 {
12733    check_arg_count(1);
12734 
12735    current_desc->map.smooth = parse_bool(0);
12736 }
12737 
12738 /**
12739     @page edcref
12740     @property
12741         alpha
12742     @parameters
12743         [1 or 0]
12744     @effect
12745         This enable alpha channel when map rendering.
12746 
12747         Defaults: 1
12748     @endproperty
12749  */
12750 static void
st_collections_group_parts_part_description_map_alpha(void)12751 st_collections_group_parts_part_description_map_alpha(void)
12752 {
12753    check_arg_count(1);
12754 
12755    current_desc->map.alpha = parse_bool(0);
12756 }
12757 
12758 /**
12759     @page edcref
12760     @property
12761         backface_cull
12762     @parameters
12763         [1 or 0]
12764     @effect
12765         This enables backface culling (when the rotated part that normally
12766         faces the camera is facing away after being rotated etc.). This means
12767         that the object will be hidden when "backface culled".
12768 
12769         Defaults: 0
12770     @endproperty
12771  */
12772 static void
st_collections_group_parts_part_description_map_backface_cull(void)12773 st_collections_group_parts_part_description_map_backface_cull(void)
12774 {
12775    check_arg_count(1);
12776 
12777    current_desc->map.backcull = parse_bool(0);
12778 }
12779 
12780 /**
12781     @page edcref
12782     @property
12783         perspective_on
12784     @parameters
12785        [1 or 0]
12786     @effect
12787         Enable perspective when rotating even without a perspective point object.
12788         This would use perspective set for the object itself or for the
12789         canvas as a whole as the global perspective with
12790         edje_perspective_set() and edje_perspective_global_set().
12791 
12792         Defaults: 0
12793     @endproperty
12794  */
12795 static void
st_collections_group_parts_part_description_map_perspective_on(void)12796 st_collections_group_parts_part_description_map_perspective_on(void)
12797 {
12798    check_arg_count(1);
12799 
12800    current_desc->map.persp_on = parse_bool(0);
12801 }
12802 
12803 /**
12804     @page edcref
12805     @property
12806         color
12807     @parameters
12808         [point] [red] [green] [blue] [alpha] or
12809         [point] "#[RR][GG][BB](AA)" or "#[R][G][B](A)"
12810     @effect
12811         Set the color of a vertex in the map.
12812         Colors will be linearly interpolated between vertex points through the map.
12813         The default color of a vertex in a map is white solid (255, 255, 255, 255)
12814         which means it will have no affect on modifying the part pixels.
12815         Currently only four points are supported:
12816         @li 0 - Left-Top point of a part.
12817         @li 1 - Right-Top point of a part.
12818         @li 2 - Left-Bottom point of a part.
12819         @li 3 - Right-Bottom point of a part.
12820 
12821         Color format:
12822         @li [red] [green] [blue] [alpha]: one integer [0-255] for each
12823         RGBA channel, i.e. 255 0 0 255
12824         @li "#[RR][GG][BB](AA)": string with two hex values per RGBA channel,
12825         i.e "#FF0000FF" or "#FF0000"
12826         @li "#[R][G][B](A)": string with one hex value per RGBA channel,
12827         i.e "#F00F" or "#F00".\n
12828         In string format you can omit alpha channel and it will be set to FF.
12829 
12830         Defaults: 255 255 255 255
12831     @endproperty
12832  */
12833 static void
st_collections_group_parts_part_description_map_color(void)12834 st_collections_group_parts_part_description_map_color(void)
12835 {
12836    Edje_Map_Color *color;
12837    Edje_Map_Color tmp = { 0 };
12838    int i;
12839 
12840    check_min_arg_count(2);
12841 
12842    tmp.idx = parse_int(0);
12843    parse_color(1, &tmp.r);
12844 
12845    for (i = 0; i < (int)current_desc->map.colors_count; i++)
12846      {
12847         color = current_desc->map.colors[i];
12848         if (color->idx != tmp.idx) continue;
12849         color->r = tmp.r;
12850         color->g = tmp.g;
12851         color->b = tmp.b;
12852         color->a = tmp.a;
12853         return;
12854      }
12855    color = mem_alloc(SZ(Edje_Map_Color));
12856    if (!color)
12857      {
12858         ERR("not enough memory");
12859         exit(-1);
12860      }
12861 
12862    *color = tmp;
12863    current_desc->map.colors_count++;
12864    current_desc->map.colors =
12865      realloc(current_desc->map.colors,
12866              sizeof(Edje_Map_Color *) * current_desc->map.colors_count);
12867    current_desc->map.colors[current_desc->map.colors_count - 1] = color;
12868 }
12869 
12870 /**
12871     @page edcref
12872     @property
12873         zoom.x
12874     @parameters
12875         [X horizontal zoom to use]
12876     @effect
12877         This sets the zoom rate of the horizontal
12878 
12879         Defaults: 1.0
12880     @endproperty
12881  */
12882 static void
st_collections_group_parts_part_description_map_zoom_x(void)12883 st_collections_group_parts_part_description_map_zoom_x(void)
12884 {
12885    check_arg_count(1);
12886 
12887    current_desc->map.zoom.x = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
12888 }
12889 
12890 /**
12891     @page edcref
12892     @property
12893         zoom.y
12894     @parameters
12895         [Y vertical zoom to use]
12896     @effect
12897         This sets the zoom rate of vertical
12898 
12899         Defaults: 1.0
12900     @endproperty
12901  */
12902 static void
st_collections_group_parts_part_description_map_zoom_y(void)12903 st_collections_group_parts_part_description_map_zoom_y(void)
12904 {
12905    check_arg_count(1);
12906 
12907    current_desc->map.zoom.y = FROM_DOUBLE(parse_float_range(0, 0.0, 999999999.0));
12908 }
12909 
12910 /** @edcsubsection{collections_group_parts_description_map_rotation,
12911  *                 Group.Parts.Part.Description.Map.Rotation} */
12912 
12913 /**
12914     @page edcref
12915     @block
12916         rotation
12917     @context
12918     map {
12919         ..
12920         rotation {
12921             center: "name";
12922             x: 45.0;
12923             y: 45.0;
12924             z: 45.0;
12925         }
12926         ..
12927     }
12928     @description
12929         Rotates the part, optionally with the center on another part.
12930     @endblock
12931 
12932     @property
12933         center
12934     @parameters
12935         [another part's name]
12936     @effect
12937         This sets the part that is used as the center of rotation when
12938         rotating the part with this description. The part's center point
12939         is used as the rotation center when applying rotation around the
12940         x, y and z axes. If no center is given, the parts original center
12941         itself is used for the rotation center.
12942     @endproperty
12943  */
12944 static void
st_collections_group_parts_part_description_map_rotation_center(void)12945 st_collections_group_parts_part_description_map_rotation_center(void)
12946 {
12947    Edje_Part_Collection *pc;
12948 
12949    check_arg_count(1);
12950 
12951    pc = eina_list_data_get(eina_list_last(edje_collections));
12952 
12953    {
12954       char *name;
12955 
12956       name = parse_str(0);
12957       data_queue_part_lookup(pc, name, &(current_desc->map.rot.id_center));
12958       free(name);
12959    }
12960 }
12961 
12962 /**
12963     @page edcref
12964     @property
12965         x
12966     @parameters
12967         [X degrees]
12968     @effect
12969         This sets the rotation around the x axis of the part considering
12970         the center set. In degrees.
12971 
12972         Defaults: 0.0
12973     @endproperty
12974  */
12975 static void
st_collections_group_parts_part_description_map_rotation_x(void)12976 st_collections_group_parts_part_description_map_rotation_x(void)
12977 {
12978    check_arg_count(1);
12979 
12980    current_desc->map.rot.x = FROM_DOUBLE(parse_float(0));
12981 }
12982 
12983 /**
12984     @page edcref
12985     @property
12986         y
12987     @parameters
12988         [Y degrees]
12989     @effect
12990         This sets the rotation around the y axis of the part considering
12991         the center set. In degrees.
12992 
12993         Defaults: 0.0
12994     @endproperty
12995  */
12996 static void
st_collections_group_parts_part_description_map_rotation_y(void)12997 st_collections_group_parts_part_description_map_rotation_y(void)
12998 {
12999    check_arg_count(1);
13000 
13001    current_desc->map.rot.y = FROM_DOUBLE(parse_float(0));
13002 }
13003 
13004 /**
13005     @page edcref
13006     @property
13007         z
13008     @parameters
13009         [Z degrees]
13010     @effect
13011         This sets the rotation around the z axis of the part considering
13012         the center set. In degrees.
13013 
13014         Defaults: 0.0
13015     @endproperty
13016  */
13017 static void
st_collections_group_parts_part_description_map_rotation_z(void)13018 st_collections_group_parts_part_description_map_rotation_z(void)
13019 {
13020    check_arg_count(1);
13021 
13022    current_desc->map.rot.z = FROM_DOUBLE(parse_float(0));
13023 }
13024 
13025 /** @edcsubsection{collections_group_parts_description_perspective,
13026  *                 Group.Parts.Part.Description.Perspective} */
13027 
13028 /**
13029     @page edcref
13030     @block
13031         perspective
13032     @context
13033     description {
13034         ..
13035         perspective {
13036             zplane: 0;
13037             focal: 1000;
13038         }
13039         ..
13040     }
13041     @description
13042         Adds focal and plane perspective to the part. Active if perspective_on is true.
13043         Must be provided if the part is being used by other part as it's perspective target.
13044     @endblock
13045 
13046     @property
13047         zplane
13048     @parameters
13049         [unscaled Z value]
13050     @effect
13051         This sets the z value that will not be scaled. Normally this is 0 as
13052         that is the z distance that all objects are at normally.
13053 
13054         Defaults: 0
13055     @endproperty
13056  */
13057 static void
st_collections_group_parts_part_description_perspective_zplane(void)13058 st_collections_group_parts_part_description_perspective_zplane(void)
13059 {
13060    check_arg_count(1);
13061 
13062    current_desc->persp.zplane = parse_int(0);
13063 }
13064 
13065 /**
13066     @page edcref
13067     @property
13068         focal
13069     @parameters
13070         [distance]
13071     @effect
13072         This sets the distance from the focal z plane (zplane) and the
13073         camera - i.e. very much equating to focal length of the camera
13074 
13075         Defaults: 1000
13076     @endproperty
13077  */
13078 static void
st_collections_group_parts_part_description_perspective_focal(void)13079 st_collections_group_parts_part_description_perspective_focal(void)
13080 {
13081    check_arg_count(1);
13082 
13083    current_desc->persp.focal = parse_int_range(0, 1, 0x7fffffff);
13084 }
13085 
13086 /** @edcsubsection{collections_group_parts_description_filter,
13087  *                 Group.Parts.Part.Description.Filter} */
13088 
13089 /**
13090     @page edcref
13091     @block
13092         filter
13093     @context
13094         part {
13095             type: [IMAGE or TEXT or PROXY or SNAPSHOT];
13096             ..
13097             description {
13098                 ..
13099                 filter {
13100                    code: "blend {}";
13101                    // or:
13102                    code: "filter_name";
13103                    source: "part1" "buf";
13104                    source: "part2" "otherbuf";
13105                    source: "part3";
13106                    ..
13107                    data: "the_answer" "42";
13108                    data: "something" "anything";
13109                    data: "mycc" "color_class('my_color_class')";
13110                    ..
13111                 }
13112                 // or:
13113                 text.filter: "blend {} -- ...";
13114                 ..
13115             }
13116         }
13117     @description
13118         Applies a series of image filters to a TEXT, IMAGE, PROXY or SNAPSHOT part.
13119         For more information, please refer to the page
13120         @ref evasfiltersref "Evas filters reference".
13121     @endblock
13122 
13123     @property
13124         filter.code
13125     @parameters
13126         [filter script or filter name]
13127     @effect
13128         The argument to this field is the source code of a Lua script as defined
13129         @ref evasfiltersref "here" or a filter name defined in the
13130         @ref sec_collections_group_filters "Filters" section.
13131     @endproperty
13132  */
13133 static void
st_collections_group_parts_part_description_filter_code(void)13134 st_collections_group_parts_part_description_filter_code(void)
13135 {
13136    Edje_Part_Description_Spec_Filter *filter;
13137 
13138    check_arg_count(1);
13139 
13140    if (current_part->type == EDJE_PART_TYPE_TEXT)
13141      filter = &(((Edje_Part_Description_Text *)current_desc)->filter);
13142    else if (current_part->type == EDJE_PART_TYPE_IMAGE)
13143      filter = &(((Edje_Part_Description_Image *)current_desc)->filter);
13144    else if (current_part->type == EDJE_PART_TYPE_PROXY)
13145      filter = &(((Edje_Part_Description_Proxy *)current_desc)->filter);
13146    else if (current_part->type == EDJE_PART_TYPE_SNAPSHOT)
13147      filter = &(((Edje_Part_Description_Snapshot *)current_desc)->filter);
13148    else
13149      {
13150         ERR("parse error %s:%i. filter only supported for: TEXT, IMAGE, PROXY, SNAPSHOT.",
13151             file_in, line - 1);
13152         exit(-1);
13153      }
13154 
13155    free((void *)filter->code);
13156    filter->code = parse_str(0);
13157 }
13158 
13159 /**
13160     @page edcref
13161 
13162     @property
13163         filter.source
13164     @parameters
13165         [another part's name] [(optional) buffer name for filter program]
13166     @effect
13167         Binds another part as an image source (like a proxy source) for a
13168         text or image filter operation. Optionally, a buffer name may be
13169         specified, so the same filter code can be used with different sources.
13170     @endproperty
13171  */
13172 static void
st_collections_group_parts_part_description_filter_source(void)13173 st_collections_group_parts_part_description_filter_source(void)
13174 {
13175    Edje_Part_Description_Spec_Filter *filter;
13176    Edje_Part_Collection *pc;
13177    char *name, *part, *str;
13178    size_t sn = 0, sp, k;
13179    int *part_key;
13180    int args;
13181 
13182    static const char allowed_name_chars[] =
13183      "abcdefghijklmnopqrstuvwxyzABCDEFGHJIKLMNOPQRSTUVWXYZ0123456789_";
13184 
13185    if (current_part->type == EDJE_PART_TYPE_TEXT)
13186      filter = &(((Edje_Part_Description_Text *)current_desc)->filter);
13187    else if (current_part->type == EDJE_PART_TYPE_IMAGE)
13188      filter = &(((Edje_Part_Description_Image *)current_desc)->filter);
13189    else if (current_part->type == EDJE_PART_TYPE_PROXY)
13190      filter = &(((Edje_Part_Description_Proxy *)current_desc)->filter);
13191    else if (current_part->type == EDJE_PART_TYPE_SNAPSHOT)
13192      filter = &(((Edje_Part_Description_Snapshot *)current_desc)->filter);
13193    else
13194      {
13195         ERR("parse error %s:%i. filter only supported for: TEXT, IMAGE, PROXY, SNAPSHOT.",
13196             file_in, line - 1);
13197         exit(-1);
13198      }
13199 
13200    args = check_range_arg_count(1, 2);
13201    pc = eina_list_data_get(eina_list_last(edje_collections));
13202 
13203    part = parse_str(0);
13204    sp = strlen(part);
13205 
13206    if (args > 1)
13207      {
13208         name = parse_str(1);
13209         if (name) sn = strlen(name);
13210         if (!name || (strspn(name, allowed_name_chars) != sn))
13211           {
13212              ERR("parse error %s:%i. invalid name for a filter buffer: '%s'",
13213                  file_in, line - 1, name);
13214              exit(-1);
13215           }
13216      }
13217    else
13218      name = NULL;
13219 
13220    if (!name && (strspn(part, allowed_name_chars) == sp))
13221      str = strdup(part);
13222    else
13223      {
13224         if (!name)
13225           {
13226              // name = part so we replace all invalid chars by '_'
13227              name = strdup(part);
13228              sn = strlen(name);
13229              for (k = 0; k < sn; k++)
13230                {
13231                   if (!strchr(allowed_name_chars, name[k]))
13232                     name[k] = '_';
13233                }
13234           }
13235         sn += sp + 1;
13236         str = malloc(sn + 1);
13237         if (!str) exit(-1);
13238         strncpy(str, name, sn);
13239         strncat(str, ":", sn);
13240         strncat(str, part, sn);
13241         str[sn] = '\0';
13242      }
13243    filter->sources = eina_list_append(filter->sources, str);
13244 
13245    // note: this is leaked. not a big deal.
13246    part_key = malloc(sizeof(int));
13247    *part_key = -1;
13248    data_queue_part_lookup(pc, part, part_key);
13249 
13250    free(part);
13251    free(name);
13252 }
13253 
13254 /**
13255     @page edcref
13256 
13257     @property
13258         filter.data
13259     @parameters
13260         [name] [content]
13261     @effect
13262         Pass extra data to the Lua filter program. All data passed will
13263         be strings, except for the special case of color classes:
13264         @code
13265         filter.data: "mycc" "color_class('my_color_class')";
13266         @endcode
13267         Those will appear to Lua as a table of the following structure:
13268         @code
13269         -- Lua code
13270         mycc = { r = 255, g = 0, b, a, r2, g2, b2, a2, r3, g3, b3, a3 }
13271         @endcode
13272     @endproperty
13273  */
13274 static void
st_collections_group_parts_part_description_filter_data(void)13275 st_collections_group_parts_part_description_filter_data(void)
13276 {
13277    Edje_Part_Description_Spec_Filter_Data *array;
13278    Edje_Part_Description_Spec_Filter *filter;
13279    char *name, *value;
13280    unsigned k;
13281 
13282    if (current_part->type == EDJE_PART_TYPE_TEXT)
13283      filter = &(((Edje_Part_Description_Text *)current_desc)->filter);
13284    else if (current_part->type == EDJE_PART_TYPE_IMAGE)
13285      filter = &(((Edje_Part_Description_Image *)current_desc)->filter);
13286    else if (current_part->type == EDJE_PART_TYPE_PROXY)
13287      filter = &(((Edje_Part_Description_Proxy *)current_desc)->filter);
13288    else if (current_part->type == EDJE_PART_TYPE_SNAPSHOT)
13289      filter = &(((Edje_Part_Description_Snapshot *)current_desc)->filter);
13290    else
13291      {
13292         ERR("parse error %s:%i. filter only supported for: TEXT, IMAGE, PROXY, SNAPSHOT.",
13293             file_in, line - 1);
13294         exit(-1);
13295      }
13296 
13297    check_arg_count(2);
13298 
13299    name = parse_str(0);
13300    value = parse_str(1);
13301    for (k = 0; k < filter->data_count; k++)
13302      if (!strcmp(filter->data[k].name, name))
13303        {
13304           ERR("parse error %s:%i. filter.data '%s' already exists in this context",
13305               file_in, line - 1, name);
13306           exit(-1);
13307        }
13308 
13309    filter->data_count++;
13310    array = realloc(filter->data, sizeof(Edje_Part_Description_Spec_Filter_Data) * filter->data_count);
13311    array[filter->data_count - 1].name = name;
13312    array[filter->data_count - 1].value = value;
13313    filter->data = array;
13314 }
13315 
13316 /** @edcsubsection{collections_group_parts_descriptions_params,
13317  *                 Group.Parts.Part.Description.Params} */
13318 
13319 /**
13320     @page edcref
13321     @block
13322         params
13323     @context
13324         description {
13325             ..
13326             params {
13327                 int: "name" 0;
13328                 double: "other_name" 0.0;
13329                 string: "another_name" "some text";
13330                 bool: "name" 1;
13331                 choice: "some_name" "value";
13332             }
13333             ..
13334         }
13335     @description
13336         Set parameters for EXTERNAL parts. The value overwrites previous
13337         definitions with the same name.
13338     @endblock
13339  */
13340 static void
_st_collections_group_parts_part_description_params(Edje_External_Param_Type type)13341 _st_collections_group_parts_part_description_params(Edje_External_Param_Type type)
13342 {
13343    Edje_Part_Description_External *ed;
13344    Edje_External_Param *param;
13345    Eina_List *l;
13346    char *name;
13347    int found = 0;
13348 
13349    check_arg_count(2);
13350 
13351    if (current_part->type != EDJE_PART_TYPE_EXTERNAL)
13352      {
13353         ERR("parse error %s:%i. params in non-EXTERNAL part.",
13354             file_in, line - 1);
13355         exit(-1);
13356      }
13357 
13358    ed = (Edje_Part_Description_External *)current_desc;
13359 
13360    name = parse_str(0);
13361 
13362    /* if a param with this name already exists, overwrite it */
13363    EINA_LIST_FOREACH(ed->external_params, l, param)
13364      {
13365         if (!strcmp(param->name, name))
13366           {
13367              found = 1;
13368              free(name);
13369              break;
13370           }
13371      }
13372 
13373    if (!found)
13374      {
13375         param = mem_alloc(SZ(Edje_External_Param));
13376         param->name = name;
13377      }
13378 
13379    param->type = type;
13380    param->i = 0;
13381    param->d = 0;
13382    param->s = NULL;
13383 
13384    switch (type)
13385      {
13386       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
13387         param->i = parse_bool(1);
13388         break;
13389 
13390       case EDJE_EXTERNAL_PARAM_TYPE_INT:
13391         param->i = parse_int(1);
13392         break;
13393 
13394       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
13395         param->d = parse_float(1);
13396         break;
13397 
13398       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
13399       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
13400         param->s = parse_str(1);
13401         break;
13402 
13403       default:
13404         ERR("parse error %s:%i. Invalid param type.",
13405             file_in, line - 1);
13406         break;
13407      }
13408 
13409    if (!found)
13410      ed->external_params = eina_list_append(ed->external_params, param);
13411 }
13412 
13413 /**
13414     @page edcref
13415     @property
13416         int
13417     @parameters
13418         [param_name] [int_value]
13419     @effect
13420         Adds an integer parameter for an external object
13421     @endproperty
13422  */
13423 static void
st_collections_group_parts_part_description_params_int(void)13424 st_collections_group_parts_part_description_params_int(void)
13425 {
13426    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_INT);
13427 }
13428 
13429 /**
13430     @page edcref
13431     @property
13432         double
13433     @parameters
13434         [param_name] [double_value]
13435     @effect
13436         Adds a double parameter for an external object
13437     @endproperty
13438  */
13439 static void
st_collections_group_parts_part_description_params_double(void)13440 st_collections_group_parts_part_description_params_double(void)
13441 {
13442    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_DOUBLE);
13443 }
13444 
13445 /**
13446     @page edcref
13447     @property
13448         string
13449     @parameters
13450         [param_name] [string_value]
13451     @effect
13452         Adds a string parameter for an external object
13453     @endproperty
13454  */
13455 static void
st_collections_group_parts_part_description_params_string(void)13456 st_collections_group_parts_part_description_params_string(void)
13457 {
13458    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_STRING);
13459 }
13460 
13461 /**
13462     @page edcref
13463     @property
13464         bool
13465     @parameters
13466         [param_name] [bool_value]
13467     @effect
13468         Adds an boolean parameter for an external object.
13469     @endproperty
13470  */
13471 static void
st_collections_group_parts_part_description_params_bool(void)13472 st_collections_group_parts_part_description_params_bool(void)
13473 {
13474    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_BOOL);
13475 }
13476 
13477 /**
13478     @page edcref
13479     @property
13480         choice
13481     @parameters
13482         [param_name] [choice_string]
13483     @effect
13484         Adds a choice parameter for an external object. The possible
13485         choice values are defined by external type at their register time
13486         and will be validated at runtime.
13487     @endproperty
13488  */
13489 static void
st_collections_group_parts_part_description_params_choice(void)13490 st_collections_group_parts_part_description_params_choice(void)
13491 {
13492    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_CHOICE);
13493 }
13494 
13495 static void
st_collections_group_parts_part_description_vector_frame(void)13496 st_collections_group_parts_part_description_vector_frame(void)
13497 {
13498    Edje_Part_Description_Vector *ed;
13499 
13500    check_arg_count(1);
13501 
13502    if (current_part->type != EDJE_PART_TYPE_VECTOR)
13503      {
13504         ERR("parse error %s:%i. vector attributes in non-VECTOR part.",
13505             file_in, line - 1);
13506         exit(-1);
13507      }
13508 
13509    ed = (Edje_Part_Description_Vector *)current_desc;
13510 
13511    ed->vg.frame = parse_float_range(0, 0.0, 1.0);
13512 }
13513 
13514 /** @edcsubsection{collections_group_parts_description_links,
13515  *                 Group.Parts.Part.Description.Links} */
13516 
13517 /**
13518     @page edcref
13519     @block
13520         link
13521     @context
13522         description {
13523             ..
13524             link {
13525                 base: "edje,signal" "edje";
13526                 transition: LINEAR 0.2;
13527                 in: 0.5 0.1;
13528                 after: "some_program";
13529             }
13530             ..
13531         }
13532     @description
13533         The link block can be used to create transitions to the enclosing part description state.
13534         The result of the above block is identical to creating a program with
13535         action: STATE_SET "default";
13536         signal: "edje,signal"; source: "edje";
13537     @since 1.10
13538     @endblock
13539  */
13540 static void
ob_collections_group_parts_part_description_link(void)13541 ob_collections_group_parts_part_description_link(void)
13542 {
13543    Edje_Part_Collection_Parser *pcp;
13544    Edje_Part_Parser *epp;
13545    Edje_Part_Description_Link *el;
13546    const char *nm;
13547 
13548    pcp = eina_list_last_data_get(edje_collections);
13549    epp = (Edje_Part_Parser *)current_part;
13550 
13551    ob_collections_group_programs_program();
13552    _edje_program_remove((Edje_Part_Collection *)pcp, current_program);
13553    el = mem_alloc(SZ(Edje_Part_Description_Link));
13554    el->pr = current_program;
13555    el->ed = current_desc;
13556    el->epp = epp;
13557    pcp->links = eina_list_append(pcp->links, el);
13558    current_program->action = EDJE_ACTION_TYPE_STATE_SET;
13559    nm = current_desc->state.name;
13560    current_program->state = strdup(nm ? nm : "default");
13561    current_program->value = current_desc->state.value;
13562 }
13563 
13564 static void
list_free(void * list)13565 list_free(void *list)
13566 {
13567    eina_list_free(list);
13568 }
13569 
13570 /**
13571     @page edcref
13572     @property
13573         base
13574     @parameters
13575         [signal] [source]
13576     @effect
13577         Defines the signal and source which will trigger the transition to this state.
13578         The source parameter is optional here and will be filled with the current group's
13579         default value if it is not provided.
13580     @since 1.10
13581     @endproperty
13582  */
13583 static void
st_collections_group_parts_part_description_link_base(void)13584 st_collections_group_parts_part_description_link_base(void)
13585 {
13586    char *name;
13587    char buf[4096];
13588    Edje_Part_Collection_Parser *pcp;
13589    Edje_Part_Description_Link *el, *ell;
13590    Eina_List *l;
13591 
13592    pcp = eina_list_last_data_get(edje_collections);
13593    el = eina_list_last_data_get(pcp->links);
13594 
13595    if ((!el) || (el->pr != current_program) ||
13596        (el->ed != current_desc) || (el->epp != (Edje_Part_Parser *)current_part) ||
13597        el->pr->source)
13598      ob_collections_group_parts_part_description_link();
13599    el = eina_list_last_data_get(pcp->links);
13600 
13601    check_min_arg_count(1);
13602    name = parse_str(0);
13603    if (current_program->signal && pcp->link_hash)
13604      {
13605         snprintf(buf, sizeof(buf), "%s\"\"\"%s", current_program->signal,
13606                  current_program->source ? current_program->source : "");
13607         eina_hash_list_remove(pcp->link_hash, buf, el);
13608      }
13609    if (!pcp->link_hash)
13610      pcp->link_hash = eina_hash_string_superfast_new(list_free);
13611    free((void *)current_program->signal);
13612    current_program->signal = name;
13613    if (get_arg_count() == 2)
13614      {
13615         name = parse_str(1);
13616         free((void *)current_program->source);
13617         current_program->source = name;
13618      }
13619    snprintf(buf, sizeof(buf), "%s\"\"\"%s", current_program->signal,
13620             current_program->source ? current_program->source : "");
13621    EINA_LIST_FOREACH(eina_hash_find(pcp->link_hash, buf), l, ell)
13622      {
13623         if (ell->epp == el->epp)
13624           {
13625              ERR("parse error %s:%i. "
13626                  "cannot have multiple links with the same signal on the same part",
13627                  file_in, line - 1);
13628              exit(-1);
13629           }
13630      }
13631    eina_hash_list_append(pcp->link_hash, buf, el);
13632 }
13633 
13634 /** @edcsubsection{collections_group_programs,
13635  *                 Group.Programs} */
13636 
13637 /**
13638     @page edcref
13639     @block
13640         programs
13641     @context
13642         group {
13643             programs {
13644                 ..
13645                 program { }
13646                 program { }
13647                 program { }
13648                 ..
13649             }
13650         }
13651     @description
13652         The programs group contain one ore more program.
13653     @endblock
13654  */
13655 static void
_program_sequence_check(void)13656 _program_sequence_check(void)
13657 {
13658    if (sequencing != current_program) return;
13659    ERR("parse error %s:%i. cannot set sequence parent program attributes within sequence block",
13660        file_in, line - 1);
13661    exit(-1);
13662 }
13663 
13664 static void
_program_after(const char * name)13665 _program_after(const char *name)
13666 {
13667    Edje_Part_Collection *pc;
13668    Edje_Program *ep;
13669    Edje_Program_After *pa;
13670    Edje_Program_After *pa2;
13671    Eina_List *l;
13672    char *copy;
13673    void *pl;
13674 
13675    pc = eina_list_data_get(eina_list_last(edje_collections));
13676    ep = current_program;
13677 
13678    EINA_LIST_FOREACH(ep->after, l, pa2)
13679      {
13680         if (!strcmp(name, (char *)(pa2 + 1)))
13681           return;
13682      }
13683 
13684    pa = mem_alloc(SZ(Edje_Program_After) + strlen(name) + 1);
13685    pa->id = -1;
13686    ep->after = eina_list_append(ep->after, pa);
13687    copy = (char *)(pa + 1);
13688    memcpy(copy, name, strlen(name) + 1);
13689    pl = data_queue_program_lookup(pc, name, &(pa->id));
13690    if (pl)
13691      current_program_lookups = eina_list_append(current_program_lookups, pl);
13692 }
13693 
13694 static Edje_Program *
_program_sequence_new(void)13695 _program_sequence_new(void)
13696 {
13697    Edje_Program *ep, *pr = current_program;
13698 
13699    /* sequence a new program after current */
13700    ob_collections_group_programs_program();
13701    ep = current_program;
13702    current_program = pr;
13703    _program_after(ep->name);
13704    return current_program = ep;
13705 }
13706 
13707 /** @edcsubsection{collections_group_programs_program,
13708  *                 Group.Programs.Program} */
13709 
13710 /**
13711     @page edcref
13712     @block
13713         program
13714     @context
13715         programs {
13716             ..
13717             program {
13718                 name: "programname";
13719                 signal: "signalname";
13720                 source: "partname";
13721                 filter: "partname" "statename";
13722                 in: 0.3 0.0;
13723                 action: STATE_SET "statename" state_value;
13724                 transition: LINEAR 0.5;
13725                 target: "partname";
13726                 target: "anotherpart";
13727                 after: "programname";
13728                 after: "anotherprogram";
13729             }
13730             ..
13731         }
13732     @description
13733         Programs define how your interface reacts to events.
13734         Programs can change the state of parts, react to events or trigger
13735         other events.
13736     @endblock
13737  */
13738 static void
ob_collections_group_programs_program(void)13739 ob_collections_group_programs_program(void)
13740 {
13741    Edje_Part_Collection *pc;
13742    Edje_Part_Collection_Parser *pcp;
13743    Edje_Program *ep;
13744    Edje_Program_Parser *epp;
13745    char *def_name;
13746 
13747    current_program_lookups = eina_list_free(current_program_lookups);
13748 
13749    pc = eina_list_data_get(eina_list_last(edje_collections));
13750    pcp = eina_list_data_get(eina_list_last(edje_collections));
13751 
13752    ep = mem_alloc(SZ(Edje_Program_Parser));
13753    ep->id = -1;
13754    ep->tween.mode = EDJE_TWEEN_MODE_LINEAR;
13755    ep->tween.use_duration_factor = EINA_FALSE;
13756    ep->after = NULL;
13757    epp = (Edje_Program_Parser *)ep;
13758    epp->can_override = EINA_FALSE;
13759 
13760    /* generate new name */
13761    def_name = alloca(strlen("program_") + strlen("FFFFFFFFFFFFFFFF") + 1);
13762    sprintf(def_name, "program_%X", pc->programs.total_count);
13763    ep->name = strdup(def_name);
13764    if (pcp->default_source)
13765      ep->source = strdup(pcp->default_source);
13766    _edje_program_insert(pc, ep);
13767 
13768    current_program = ep;
13769    pc->programs.total_count++;
13770 }
13771 
13772 static void
_program_name(char * name)13773 _program_name(char *name)
13774 {
13775    Edje_Part_Collection *pc;
13776    Eina_List *l;
13777    void *pl;
13778 
13779    pc = eina_list_data_get(eina_list_last(edje_collections));
13780    free((void *)current_program->name);
13781    current_program->name = name;
13782 
13783    _edje_program_check(current_program->name, current_program, pc->programs.fnmatch, pc->programs.fnmatch_count);
13784    _edje_program_check(current_program->name, current_program, pc->programs.strcmp, pc->programs.strcmp_count);
13785    _edje_program_check(current_program->name, current_program, pc->programs.strncmp, pc->programs.strncmp_count);
13786    _edje_program_check(current_program->name, current_program, pc->programs.strrncmp, pc->programs.strrncmp_count);
13787    _edje_program_check(current_program->name, current_program, pc->programs.nocmp, pc->programs.nocmp_count);
13788 
13789    EINA_LIST_FOREACH(current_program_lookups, l, pl)
13790      program_lookup_rename(pl, name);
13791 }
13792 
13793 /**
13794     @page edcref
13795     @property
13796         name
13797     @parameters
13798         [program name]
13799     @effect
13800         Symbolic name of program as a unique identifier.
13801     @endproperty
13802  */
13803 static void
st_collections_group_programs_program_name(void)13804 st_collections_group_programs_program_name(void)
13805 {
13806    check_arg_count(1);
13807    _program_sequence_check();
13808    _program_name(parse_str(0));
13809 }
13810 
13811 /**
13812     @page edcref
13813     @property
13814         signal
13815     @parameters
13816         [signal name]
13817     @effect
13818         Specifies signal(s) that should cause the program to run. The signal
13819         received must match the specified source to run.
13820         Signals may be globbed, but only one signal keyword per program
13821         may be used. ex: signal: "mouse,clicked,*"; (clicking any mouse button
13822         that matches source starts program).
13823         A list of global signal, that edje provide:
13824           - hold,on;
13825           - hold,off;
13826           - mouse,in;
13827           - mouse,out;
13828           - mouse,pressed,in;
13829           - mouse,pressed,out;
13830           - mouse,down,N: where N - mouse button number;
13831           - mouse,down,N,double: where N - mouse button number;
13832           - mouse,down,N,triple: where N - mouse button number;
13833           - mouse,up,N: where N - mouse button number;
13834           - mouse,clicked,N: where N - mouse button number;
13835           - mouse,move;
13836           - mouse,wheel,N,M: where N - the direction (by default is 0),
13837             M - 1 if wheel scrolled up and -1 if down;
13838           - drag,start;
13839           - drag;
13840           - drag,stop;
13841           - focus,part,in;
13842           - focus,part,out.
13843     @endproperty
13844  */
13845 static void
st_collections_group_programs_program_signal(void)13846 st_collections_group_programs_program_signal(void)
13847 {
13848    Edje_Part_Collection *pc;
13849 
13850    check_arg_count(1);
13851 
13852    _program_sequence_check();
13853 
13854    pc = eina_list_data_get(eina_list_last(edje_collections));
13855 
13856    _edje_program_remove(pc, current_program);
13857    current_program->signal = parse_str(0);
13858    _edje_program_insert(pc, current_program);
13859 }
13860 
13861 /**
13862     @page edcref
13863     @property
13864         source
13865     @parameters
13866         [source name]
13867     @effect
13868         Source of accepted signal. Sources may be globbed, but only one source
13869         keyword per program may be used. ex: source: "button-*"; (Signals from
13870         any part or program named "button-*" are accepted).
13871     @endproperty
13872  */
13873 static void
st_collections_group_programs_program_source(void)13874 st_collections_group_programs_program_source(void)
13875 {
13876    Edje_Part_Collection *pc;
13877 
13878    check_arg_count(1);
13879 
13880    _program_sequence_check();
13881 
13882    pc = eina_list_data_get(eina_list_last(edje_collections));
13883 
13884    _edje_program_remove(pc, current_program);
13885    free((void *)current_program->source);
13886    current_program->source = parse_str(0);
13887    _edje_program_insert(pc, current_program);
13888 }
13889 
13890 /**
13891     @page edcref
13892     @property
13893         filter
13894     @parameters
13895         [part] [state]
13896     @effect
13897         Filter signals to be only accepted if the part [part] is in state named [state].
13898         Only one filter per program can be used. If [part] is not given, the source of
13899         the event will be used instead.
13900     @endproperty
13901  */
13902 static void
st_collections_group_programs_program_filter(void)13903 st_collections_group_programs_program_filter(void)
13904 {
13905    check_min_arg_count(1);
13906 
13907    _program_sequence_check();
13908 
13909    if (is_param(1))
13910      {
13911         current_program->filter.part = parse_str(0);
13912         current_program->filter.state = parse_str(1);
13913      }
13914    else
13915      {
13916         current_program->filter.state = parse_str(0);
13917      }
13918 }
13919 
13920 /**
13921     @page edcref
13922     @property
13923         in
13924     @parameters
13925         [from] [range]
13926     @effect
13927         Wait 'from' seconds before executing the program. And add a random
13928         number of seconds (from 0 to 'range') to the total waiting time.
13929 
13930         Defaults: 0.0 0.0
13931     @endproperty
13932  */
13933 static void
st_collections_group_programs_program_in(void)13934 st_collections_group_programs_program_in(void)
13935 {
13936    check_arg_count(2);
13937 
13938    _program_sequence_check();
13939 
13940    current_program->in.from = parse_float_range(0, 0.0, 999999999.0);
13941    current_program->in.range = parse_float_range(1, 0.0, 999999999.0);
13942 }
13943 
13944 /**
13945     @page edcref
13946     @property
13947         action
13948     @parameters
13949         [type] (param1) (param2) (param3) (param4)
13950     @effect
13951         Action to be performed by the program. Valid actions are:
13952         @li STATE_SET "state name" (state value)
13953         @li ACTION_STOP
13954         @li SIGNAL_EMIT "signalname" "emitter"
13955         @li DRAG_VAL_SET 0.5 0.0
13956         @li DRAG_VAL_STEP 1.0 0.0
13957         @li DRAG_VAL_PAGE 0.0 0.0
13958         @li FOCUS_SET ("seat")
13959         @li FOCUS_OBJECT ("seat")
13960         @li PARAM_COPY "src_part" "src_param" "dst_part" "dst_param"
13961         @li PARAM_SET "part" "param" "value"
13962         @li PLAY_SAMPLE "sample name" speed (channel)
13963         @li PLAY_TONE "tone name" duration_in_seconds( Range 0.1 to 10.0 )
13964         @li PLAY_VIBRATION "sample name" repeat (repeat count)
13965         @li PHYSICS_IMPULSE 10 -23.4 0
13966         @li PHYSICS_TORQUE_IMPULSE 0 2.1 0.95
13967         @li PHYSICS_FORCE -20.8 0 30.85
13968         @li PHYSICS_TORQUE 0 0 4.8
13969         @li PHYSICS_FORCES_CLEAR
13970         @li PHYSICS_VEL_SET 40.9 0 0
13971         @li PHYSICS_ANG_VEL_SET 12.4 0 0.66
13972         @li PHYSICS_STOP
13973         @li PHYSICS_ROT_SET 0.707 0 0 0.707
13974 
13975         Only one action can be specified per program.
13976 
13977         PLAY_SAMPLE (optional) channel can be one of:
13978         @li EFFECT/FX
13979         @li BACKGROUND/BG
13980         @li MUSIC/MUS
13981         @li FOREGROUND/FG
13982         @li INTERFACE/UI
13983         @li INPUT
13984         @li ALERT
13985 
13986     @endproperty
13987  */
13988 static void
st_collections_group_programs_program_action(void)13989 st_collections_group_programs_program_action(void)
13990 {
13991    Edje_Part_Collection *pc;
13992    Edje_Program *ep;
13993    int i;
13994    Eina_Bool found = EINA_FALSE;
13995 
13996    pc = eina_list_data_get(eina_list_last(edje_collections));
13997    if (sequencing)
13998      ep = _program_sequence_new();
13999    else
14000      ep = current_program;
14001    ep->action = parse_enum(0,
14002                            "STATE_SET", EDJE_ACTION_TYPE_STATE_SET,
14003                            "ACTION_STOP", EDJE_ACTION_TYPE_ACTION_STOP,
14004                            "SIGNAL_EMIT", EDJE_ACTION_TYPE_SIGNAL_EMIT,
14005                            "DRAG_VAL_SET", EDJE_ACTION_TYPE_DRAG_VAL_SET,
14006                            "DRAG_VAL_STEP", EDJE_ACTION_TYPE_DRAG_VAL_STEP,
14007                            "DRAG_VAL_PAGE", EDJE_ACTION_TYPE_DRAG_VAL_PAGE,
14008                            "SCRIPT", EDJE_ACTION_TYPE_SCRIPT,
14009                            "FOCUS_SET", EDJE_ACTION_TYPE_FOCUS_SET,
14010                            "FOCUS_OBJECT", EDJE_ACTION_TYPE_FOCUS_OBJECT,
14011                            "PARAM_COPY", EDJE_ACTION_TYPE_PARAM_COPY,
14012                            "PARAM_SET", EDJE_ACTION_TYPE_PARAM_SET,
14013                            "PLAY_SAMPLE", EDJE_ACTION_TYPE_SOUND_SAMPLE,
14014                            "PLAY_TONE", EDJE_ACTION_TYPE_SOUND_TONE,
14015                            "PHYSICS_IMPULSE", EDJE_ACTION_TYPE_PHYSICS_IMPULSE,
14016                            "PHYSICS_TORQUE_IMPULSE", EDJE_ACTION_TYPE_PHYSICS_TORQUE_IMPULSE,
14017                            "PHYSICS_FORCE", EDJE_ACTION_TYPE_PHYSICS_FORCE,
14018                            "PHYSICS_TORQUE", EDJE_ACTION_TYPE_PHYSICS_TORQUE,
14019                            "PHYSICS_FORCES_CLEAR", EDJE_ACTION_TYPE_PHYSICS_FORCES_CLEAR,
14020                            "PHYSICS_VEL_SET", EDJE_ACTION_TYPE_PHYSICS_VEL_SET,
14021                            "PHYSICS_ANG_VEL_SET", EDJE_ACTION_TYPE_PHYSICS_ANG_VEL_SET,
14022                            "PHYSICS_STOP", EDJE_ACTION_TYPE_PHYSICS_STOP,
14023                            "PHYSICS_ROT_SET", EDJE_ACTION_TYPE_PHYSICS_ROT_SET,
14024                            "PLAY_VIBRATION", EDJE_ACTION_TYPE_VIBRATION_SAMPLE,
14025                            "VG_ANIM_STOP", EDJE_ACTION_TYPE_VG_ANIM_STOP,
14026                            "VG_ANIM_PAUSE", EDJE_ACTION_TYPE_VG_ANIM_PAUSE,
14027                            "VG_ANIM_RESUME", EDJE_ACTION_TYPE_VG_ANIM_RESUME,
14028                            "VG_ANIM_PLAY", EDJE_ACTION_TYPE_VG_ANIM_PLAY,
14029                            "VG_ANIM_REWIND", EDJE_ACTION_TYPE_VG_ANIM_REWIND,
14030                            "VG_ANIM_LOOP", EDJE_ACTION_TYPE_VG_ANIM_LOOP,
14031                            NULL);
14032    if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
14033      {
14034         ep->state = parse_str(1);
14035         if (get_arg_count() == 2)
14036           ep->value = 0.0;
14037         else
14038           ep->value = parse_float_range(2, 0.0, 1.0);
14039      }
14040    else if ((ep->action == EDJE_ACTION_TYPE_FOCUS_SET) ||
14041             (ep->action == EDJE_ACTION_TYPE_FOCUS_OBJECT))
14042      {
14043         if (get_arg_count() == 1)
14044           ep->seat = NULL;
14045         else
14046           ep->seat = parse_str(1);
14047      }
14048    else if (ep->action == EDJE_ACTION_TYPE_SIGNAL_EMIT)
14049      {
14050         ep->state = parse_str(1);
14051         ep->state2 = parse_str(2);
14052      }
14053    else if (ep->action == EDJE_ACTION_TYPE_SOUND_SAMPLE)
14054      {
14055         ep->sample_name = parse_str(1);
14056         if (edje_file->sound_dir)
14057           {
14058              for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
14059                {
14060                   if (!strcmp(edje_file->sound_dir->samples[i].name, ep->sample_name))
14061                     {
14062                        found = EINA_TRUE;
14063                        break;
14064                     }
14065                }
14066           }
14067         if (!found)
14068           {
14069              ERR("No Sample name %s exist.", ep->sample_name);
14070              exit(-1);
14071           }
14072         ep->speed = parse_float_range(2, 0.0, 100.0);
14073         if (get_arg_count() >= 4)
14074           ep->channel = parse_enum(3,
14075                                    "EFFECT", 0, "FX", 0,
14076                                    "BACKGROUND", 1, "BG", 1,
14077                                    "MUSIC", 2, "MUS", 2,
14078                                    "FOREGROUND", 3, "FG", 3,
14079                                    "INTERFACE", 4, "UI", 4,
14080                                    "INPUT", 5,
14081                                    "ALERT", 6,
14082                                    NULL);
14083      }
14084    else if (ep->action == EDJE_ACTION_TYPE_SOUND_TONE)
14085      {
14086         ep->tone_name = parse_str(1);
14087         if (edje_file->sound_dir)
14088           {
14089              for (i = 0; i < (int)edje_file->sound_dir->tones_count; i++)
14090                {
14091                   if (!strcmp(edje_file->sound_dir->tones[i].name, ep->tone_name))
14092                     {
14093                        found = EINA_TRUE;
14094                        break;
14095                     }
14096                }
14097           }
14098         if (!found)
14099           {
14100              ERR("No Tone name %s exist.", ep->tone_name);
14101              exit(-1);
14102           }
14103         ep->duration = parse_float_range(2, 0.1, 10.0);
14104      }
14105    else if (ep->action == EDJE_ACTION_TYPE_VIBRATION_SAMPLE)
14106      {
14107         ep->vibration_name = parse_str(1);
14108         for (i = 0; i < (int)edje_file->vibration_dir->samples_count; i++)
14109           {
14110              if (!strcmp(edje_file->vibration_dir->samples[i].name, ep->vibration_name))
14111                break;
14112              if (i == (int)(edje_file->vibration_dir->samples_count - 1))
14113                {
14114                   ERR("No Vibration Sample name %s exist.", ep->vibration_name);
14115                   exit(-1);
14116                }
14117           }
14118         ep->vibration_repeat = parse_int(2);
14119      }
14120    else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
14121      {
14122         ep->value = parse_float(1);
14123         ep->value2 = parse_float(2);
14124      }
14125    else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_STEP)
14126      {
14127         ep->value = parse_float(1);
14128         ep->value2 = parse_float(2);
14129      }
14130    else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_PAGE)
14131      {
14132         ep->value = parse_float(1);
14133         ep->value2 = parse_float(2);
14134      }
14135    else if (ep->action == EDJE_ACTION_TYPE_PARAM_COPY)
14136      {
14137         char *src_part, *dst_part;
14138 
14139         src_part = parse_str(1);
14140         ep->state = parse_str(2);
14141         dst_part = parse_str(3);
14142         ep->state2 = parse_str(4);
14143 
14144         data_queue_part_lookup(pc, src_part, &(ep->param.src));
14145         data_queue_part_lookup(pc, dst_part, &(ep->param.dst));
14146 
14147         free(src_part);
14148         free(dst_part);
14149      }
14150    else if (ep->action == EDJE_ACTION_TYPE_PARAM_SET)
14151      {
14152         char *part;
14153 
14154         part = parse_str(1);
14155         ep->state = parse_str(2);
14156         ep->state2 = parse_str(3);
14157 
14158         data_queue_part_lookup(pc, part, &(ep->param.dst));
14159         free(part);
14160      }
14161 #ifdef HAVE_EPHYSICS
14162    else if ((ep->action == EDJE_ACTION_TYPE_PHYSICS_IMPULSE) ||
14163             (ep->action == EDJE_ACTION_TYPE_PHYSICS_TORQUE_IMPULSE) ||
14164             (ep->action == EDJE_ACTION_TYPE_PHYSICS_FORCE) ||
14165             (ep->action == EDJE_ACTION_TYPE_PHYSICS_TORQUE) ||
14166             (ep->action == EDJE_ACTION_TYPE_PHYSICS_VEL_SET) ||
14167             (ep->action == EDJE_ACTION_TYPE_PHYSICS_ANG_VEL_SET))
14168      {
14169         ep->physics.x = parse_float(1);
14170         ep->physics.y = parse_float(2);
14171         ep->physics.z = parse_float(3);
14172      }
14173    else if (ep->action == EDJE_ACTION_TYPE_PHYSICS_ROT_SET)
14174      {
14175         ep->physics.w = parse_float(1);
14176         ep->physics.x = parse_float(2);
14177         ep->physics.y = parse_float(3);
14178         ep->physics.z = parse_float(4);
14179      }
14180 #endif
14181 
14182    switch (ep->action)
14183      {
14184       case EDJE_ACTION_TYPE_SCRIPT:
14185         /* this is implicitly set by script {} so this is here just for
14186          * completeness */
14187         break;
14188 
14189       case EDJE_ACTION_TYPE_ACTION_STOP:
14190       case EDJE_ACTION_TYPE_PHYSICS_FORCES_CLEAR:
14191       case EDJE_ACTION_TYPE_PHYSICS_STOP:
14192       case EDJE_ACTION_TYPE_VG_ANIM_STOP:
14193       case EDJE_ACTION_TYPE_VG_ANIM_PAUSE:
14194       case EDJE_ACTION_TYPE_VG_ANIM_RESUME:
14195       case EDJE_ACTION_TYPE_VG_ANIM_PLAY:
14196       case EDJE_ACTION_TYPE_VG_ANIM_REWIND:
14197       case EDJE_ACTION_TYPE_VG_ANIM_LOOP:
14198         check_arg_count(1);
14199         break;
14200 
14201       case EDJE_ACTION_TYPE_PARAM_SET:
14202       case EDJE_ACTION_TYPE_PHYSICS_IMPULSE:
14203       case EDJE_ACTION_TYPE_PHYSICS_TORQUE_IMPULSE:
14204       case EDJE_ACTION_TYPE_PHYSICS_FORCE:
14205       case EDJE_ACTION_TYPE_PHYSICS_TORQUE:
14206       case EDJE_ACTION_TYPE_PHYSICS_VEL_SET:
14207       case EDJE_ACTION_TYPE_PHYSICS_ANG_VEL_SET:
14208         check_arg_count(4);
14209         break;
14210 
14211       case EDJE_ACTION_TYPE_PARAM_COPY:
14212       case EDJE_ACTION_TYPE_PHYSICS_ROT_SET:
14213         check_arg_count(5);
14214         break;
14215 
14216       case EDJE_ACTION_TYPE_SOUND_SAMPLE:
14217       case EDJE_ACTION_TYPE_VIBRATION_SAMPLE:
14218         break;
14219 
14220       case EDJE_ACTION_TYPE_STATE_SET:
14221         check_min_arg_count(2);
14222         break;
14223 
14224       case EDJE_ACTION_TYPE_FOCUS_SET:
14225       case EDJE_ACTION_TYPE_FOCUS_OBJECT:
14226         check_min_arg_count(1);
14227         break;
14228 
14229       default:
14230         check_arg_count(3);
14231      }
14232 }
14233 
14234 /**
14235     @page edcref
14236     @property
14237         transition
14238     @parameters
14239         [type] [length] (interp val 1) (interp val 2) (option)
14240     @effect
14241         Defines how transitions occur using STATE_SET action.\n
14242         Where 'type' is the style of the transition and 'length' is a double
14243         specifying the number of seconds in which to preform the transition.\n
14244         Valid types are:
14245         @li LIN or LINEAR
14246         @li SIN or SINUSOIDAL
14247         @li ACCEL or ACCELERATE
14248         @li DECEL or DECELERATE
14249         @li ACCEL_FAC or ACCELERATE_FACTOR
14250         @li DECEL_FAC or DECELERATE_FACTOR
14251         @li SIN_FAC or SINUSOIDAL_FACTOR
14252         @li DIVIS or DIVISOR_INTERP
14253         @li BOUNCE
14254         @li SPRING
14255         @li CUBIC_BEZIER
14256 
14257         ACCEL_FAC, DECEL_FAC and SIN_FAC need the extra optional
14258         "interp val 1" to determine the "factor" of curviness. 1.0 is the same
14259         as their non-factor counterparts, where 0.0 is equal to linear.
14260         Numbers higher than one make the curve angles steeper with a more
14261         pronounced curve point.
14262 
14263         DIVIS, BOUNCE and SPRING also require "interp val 2" in addition
14264         to "interp val 1".
14265 
14266         DIVIS uses val 1 as the initial gradient start
14267         (0.0 is horizontal, 1.0 is diagonal (linear), 2.0 is twice the
14268         gradient of linear etc.). val 2 is interpreted as an integer factor
14269         defining how much the value swings "outside" the gradient only to come
14270         back to the final resting spot at the end. 0.0 for val 2 is equivalent
14271         to linear interpolation. Note that DIVIS can exceed 1.0
14272 
14273         BOUNCE uses val 2 as the number of bounces (so its rounded down to
14274         the nearest integer value), with val 1 determining how much the
14275         bounce decays, with 0.0 giving linear decay per bounce, and higher
14276         values giving much more decay.
14277 
14278         SPRING is similar to bounce, where val 2 specifies the number of
14279         spring "swings" and val 1 specifies the decay, but it can exceed 1.0
14280         on the outer swings.
14281 
14282         Valid options are:
14283         @li CURRENT causes the object to move from its current position.
14284         Can be used as the last parameter of any transition type. (since 1.1.0)
14285 
14286     @endproperty
14287  */
14288 static void
st_collections_group_programs_program_transition(void)14289 st_collections_group_programs_program_transition(void)
14290 {
14291    int current = -1, index = -1;
14292    unsigned int required_args = 0;
14293 
14294    check_min_arg_count(2);
14295 
14296    _program_sequence_check();
14297 
14298    current_program->tween.v1 = current_program->tween.v2 =
14299        current_program->tween.v3 = current_program->tween.v4 = 0.0;
14300 
14301    current_program->tween.mode = parse_enum(0,
14302      // short names
14303                                             "LIN", EDJE_TWEEN_MODE_LINEAR,
14304                                             "SIN", EDJE_TWEEN_MODE_SINUSOIDAL,
14305                                             "ACCEL", EDJE_TWEEN_MODE_ACCELERATE,
14306                                             "DECEL", EDJE_TWEEN_MODE_DECELERATE,
14307                                             "ACCEL_FAC", EDJE_TWEEN_MODE_ACCELERATE_FACTOR,
14308                                             "DECEL_FAC", EDJE_TWEEN_MODE_DECELERATE_FACTOR,
14309                                             "SIN_FAC", EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR,
14310                                             "DIVIS", EDJE_TWEEN_MODE_DIVISOR_INTERP,
14311 
14312      // long/full names
14313                                             "LINEAR", EDJE_TWEEN_MODE_LINEAR,
14314                                             "SINUSOIDAL", EDJE_TWEEN_MODE_SINUSOIDAL,
14315                                             "CUBIC_BEZIER", EDJE_TWEEN_MODE_CUBIC_BEZIER,
14316                                             "ACCELERATE", EDJE_TWEEN_MODE_ACCELERATE,
14317                                             "DECELERATE", EDJE_TWEEN_MODE_DECELERATE,
14318                                             "ACCELERATE_FACTOR", EDJE_TWEEN_MODE_ACCELERATE_FACTOR,
14319                                             "DECELERATE_FACTOR", EDJE_TWEEN_MODE_DECELERATE_FACTOR,
14320                                             "SINUSOIDAL_FACTOR", EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR,
14321                                             "DIVISOR_INTERP", EDJE_TWEEN_MODE_DIVISOR_INTERP,
14322 
14323      // long/full is short enough
14324                                             "BOUNCE", EDJE_TWEEN_MODE_BOUNCE,
14325                                             "SPRING", EDJE_TWEEN_MODE_SPRING,
14326                                             NULL);
14327    current_program->tween.time = FROM_DOUBLE(parse_float_range(1, 0.0, 999999999.0));
14328 
14329    //Check the index of params not related to tweenmode's param
14330    //This index use for count of the tweenmode's param
14331    if ((index = get_param_index("USE_DURATION_FACTOR")) != -1)
14332      {
14333         current_program->tween.use_duration_factor = parse_bool(index + 1);
14334         required_args += 2;
14335      }
14336    if ((current = get_param_index("CURRENT")) != -1)
14337      {
14338         if (index == -1 || current < index)
14339           index = current;
14340         required_args++;
14341      }
14342    switch (current_program->tween.mode)
14343      {
14344       case EDJE_TWEEN_MODE_LINEAR:
14345       case EDJE_TWEEN_MODE_SINUSOIDAL:
14346       case EDJE_TWEEN_MODE_ACCELERATE:
14347       case EDJE_TWEEN_MODE_DECELERATE:
14348       {
14349          required_args += 2;
14350          check_arg_count(required_args);
14351       }
14352       break;
14353 
14354       // the following need v1
14355       case EDJE_TWEEN_MODE_ACCELERATE_FACTOR:
14356       case EDJE_TWEEN_MODE_DECELERATE_FACTOR:
14357       case EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR:
14358       {
14359          required_args += 3;
14360          check_arg_count(required_args);
14361          if (index == -1 || index > 2)
14362            {
14363               current_program->tween.v1 =
14364                 FROM_DOUBLE(parse_float_range(2, -999999999.0, 999999999.0));
14365               break;
14366            }
14367          else
14368            {
14369               ERR("parse error %s:%i. Need 3rd parameter to set factor",
14370                   file_in, line - 1);
14371               exit(-1);
14372            }
14373       }
14374 
14375       case EDJE_TWEEN_MODE_DIVISOR_INTERP:
14376       case EDJE_TWEEN_MODE_BOUNCE:
14377       case EDJE_TWEEN_MODE_SPRING:
14378       {
14379          required_args += 4;
14380          check_arg_count(required_args);
14381          if (index == -1 || index > 3)
14382            {
14383               current_program->tween.v1 =
14384                 FROM_DOUBLE(parse_float_range(2, -999999999.0, 999999999.0));
14385               current_program->tween.v2 =
14386                 FROM_DOUBLE(parse_float_range(3, -999999999.0, 999999999.0));
14387               break;
14388            }
14389          else
14390            {
14391               ERR("parse error %s:%i. "
14392                   "Need 3rd and 4th parameters to set factor and counts",
14393                   file_in, line - 1);
14394               exit(-1);
14395            }
14396       }
14397 
14398       case EDJE_TWEEN_MODE_CUBIC_BEZIER:
14399       {
14400          required_args += 6;
14401          check_arg_count(required_args);
14402          if (index == -1 || index > 5)
14403            {
14404               current_program->tween.v1 =
14405                 FROM_DOUBLE(parse_float_range(2, -999999999.0, 999999999.0));
14406               current_program->tween.v2 =
14407                 FROM_DOUBLE(parse_float_range(3, -999999999.0, 999999999.0));
14408               current_program->tween.v3 =
14409                 FROM_DOUBLE(parse_float_range(4, -999999999.0, 999999999.0));
14410               current_program->tween.v4 =
14411                 FROM_DOUBLE(parse_float_range(5, -999999999.0, 999999999.0));
14412               break;
14413            }
14414          else
14415            {
14416               ERR("parse error %s:%i. "
14417                   "Need 3rd, 4th, 5th and 6th parameters to set x1, y1, x2 and y2",
14418                   file_in, line - 1);
14419               exit(-1);
14420            }
14421       }
14422      }
14423    if (current > 0)
14424      current_program->tween.mode |= EDJE_TWEEN_MODE_OPT_FROM_CURRENT;
14425 }
14426 
14427 static void
_program_target_add(char * name)14428 _program_target_add(char *name)
14429 {
14430    Edje_Part_Collection *pc;
14431    Edje_Program *ep;
14432    Edje_Program_Target *et;
14433    Edje_Program_Target *etw;
14434    Eina_List *l;
14435    char *copy;
14436 
14437    pc = eina_list_data_get(eina_list_last(edje_collections));
14438    ep = current_program;
14439 
14440    EINA_LIST_FOREACH(ep->targets, l, etw)
14441      {
14442         if (!strcmp(name, (char *)(etw + 1)))
14443           {
14444              free(name);
14445              return;
14446           }
14447      }
14448 
14449    et = mem_alloc(SZ(Edje_Program_Target) + strlen(name) + 1);
14450    ep->targets = eina_list_append(ep->targets, et);
14451    copy = (char *)(et + 1);
14452    memcpy(copy, name, strlen(name) + 1);
14453    switch (ep->action)
14454      {
14455       case EDJE_ACTION_TYPE_ACTION_STOP:
14456         data_queue_program_lookup(pc, name, &(et->id));
14457         break;
14458 
14459       case EDJE_ACTION_TYPE_STATE_SET:
14460       case EDJE_ACTION_TYPE_SIGNAL_EMIT:
14461       case EDJE_ACTION_TYPE_DRAG_VAL_SET:
14462       case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
14463       case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
14464       case EDJE_ACTION_TYPE_FOCUS_SET:
14465       case EDJE_ACTION_TYPE_FOCUS_OBJECT:
14466 #ifdef HAVE_EPHYSICS
14467       case EDJE_ACTION_TYPE_PHYSICS_IMPULSE:
14468       case EDJE_ACTION_TYPE_PHYSICS_TORQUE_IMPULSE:
14469       case EDJE_ACTION_TYPE_PHYSICS_FORCE:
14470       case EDJE_ACTION_TYPE_PHYSICS_TORQUE:
14471       case EDJE_ACTION_TYPE_PHYSICS_FORCES_CLEAR:
14472       case EDJE_ACTION_TYPE_PHYSICS_VEL_SET:
14473       case EDJE_ACTION_TYPE_PHYSICS_ANG_VEL_SET:
14474       case EDJE_ACTION_TYPE_PHYSICS_STOP:
14475       case EDJE_ACTION_TYPE_PHYSICS_ROT_SET:
14476 #endif
14477       case EDJE_ACTION_TYPE_VG_ANIM_STOP:
14478       case EDJE_ACTION_TYPE_VG_ANIM_PAUSE:
14479       case EDJE_ACTION_TYPE_VG_ANIM_RESUME:
14480       case EDJE_ACTION_TYPE_VG_ANIM_PLAY:
14481       case EDJE_ACTION_TYPE_VG_ANIM_REWIND:
14482       case EDJE_ACTION_TYPE_VG_ANIM_LOOP:
14483         data_queue_part_lookup(pc, name, &(et->id));
14484         break;
14485 
14486       default:
14487         ERR("parse error %s:%i. target may only be used after action",
14488             file_in, line - 1);
14489         exit(-1);
14490      }
14491    free(name);
14492 }
14493 
14494 /**
14495     @page edcref
14496     @property
14497         target
14498     @parameters
14499         [target]
14500     @effect
14501         Program or part on which the specified action acts. Multiple target
14502         keywords may be specified, one per target. SIGNAL_EMITs can have
14503         targets.
14504     @endproperty
14505  */
14506 static void
st_collections_group_programs_program_target(void)14507 st_collections_group_programs_program_target(void)
14508 {
14509    check_arg_count(1);
14510 
14511    _program_sequence_check();
14512 
14513    _program_target_add(parse_str(0));
14514 }
14515 
14516 /**
14517     @page edcref
14518     @property
14519         targets
14520     @parameters
14521         [target1] [target2] [target3] ...
14522     @effect
14523         Programs or parts upon which the specified action will act. Multiple
14524         target or targets keywords may be specified. SIGNAL_EMITs can have
14525         targets.
14526     @since 1.10
14527     @endproperty
14528  */
14529 static void
st_collections_group_programs_program_targets(void)14530 st_collections_group_programs_program_targets(void)
14531 {
14532    int n, argc;
14533 
14534    check_min_arg_count(1);
14535 
14536    _program_sequence_check();
14537 
14538    for (n = 0, argc = get_arg_count(); n < argc; n++)
14539      _program_target_add(parse_str(n));
14540 }
14541 
14542 /**
14543     @page edcref
14544     @property
14545         target_groups
14546         groups
14547     @parameters
14548         [group1] [group2] [group3] ...
14549     @effect
14550         Groups of programs or parts upon which the specified action will act. Multiple 'groups', 'target',
14551         and 'targets' keywords may be specified. SIGNAL_EMITs can have targets.
14552     @since 1.10
14553     @endproperty
14554  */
14555 static void
st_collections_group_programs_program_target_groups(void)14556 st_collections_group_programs_program_target_groups(void)
14557 {
14558    int n, argc;
14559    Edje_Part_Collection_Parser *pc;
14560 
14561    check_min_arg_count(1);
14562 
14563    pc = eina_list_last_data_get(edje_collections);
14564    for (n = 0, argc = get_arg_count(); n < argc; n++)
14565      {
14566         Eina_List *l;
14567         Edje_Target_Group *tg;
14568         char *name;
14569         Eina_Bool found = EINA_FALSE;
14570 
14571         name = parse_str(n);
14572         EINA_LIST_FOREACH(pc->target_groups, l, tg)
14573           if (!strcmp(tg->name, name))
14574             {
14575                char **t;
14576 
14577                for (t = tg->targets; *t; t++)
14578                  _program_target_add(strdup(*t));
14579                found = EINA_TRUE;
14580             }
14581         if (found)
14582           {
14583              free(name);
14584              continue;
14585           }
14586         ERR("parse error %s:%i. There is no target_group with the name '%s'",
14587             file_in, line - 1, name);
14588         exit(-1);
14589      }
14590 }
14591 
14592 /**
14593     @page edcref
14594     @property
14595         after
14596     @parameters
14597         [after]
14598     @effect
14599         Specifies a program to run after the current program completes. The
14600         source and signal parameters of a program run as an "after" are ignored.
14601         Multiple "after" statements can be specified per program.
14602     @endproperty
14603  */
14604 static void
st_collections_group_programs_program_after(void)14605 st_collections_group_programs_program_after(void)
14606 {
14607    char *name;
14608 
14609    check_arg_count(1);
14610    _program_sequence_check();
14611    name = parse_str(0);
14612    _program_after(name);
14613    free(name);
14614 }
14615 
14616 /**
14617     @page edcref
14618     @property
14619         api
14620     @parameters
14621         [name] [description]
14622     @effect
14623         Specifies a hint to let applications (or IDE's) know how to bind
14624         things. The parameter name should contain the name of the function that
14625         the application should use, and description describes how it should
14626         be used.
14627     @endproperty
14628  */
14629 static void
st_collections_group_programs_program_api(void)14630 st_collections_group_programs_program_api(void)
14631 {
14632    check_min_arg_count(1);
14633 
14634    _program_sequence_check();
14635 
14636    current_program->api.name = parse_str(0);
14637 
14638    if (is_param(1))
14639      {
14640         check_arg_count(2);
14641         current_program->api.description = parse_str(1);
14642      }
14643 }
14644 
14645 /** @edcsubsection{collections_group_program_sequence,
14646  *                 Group.Programs.Program.Sequence} */
14647 
14648 /**
14649     @page edcref
14650     @block
14651         sequence
14652     @context
14653        ..
14654           program {
14655              name: "programname";
14656              signal: "signalname";
14657              source: "partname";
14658              filter: "partname" "statename";
14659              in: 0.3 0.0;
14660              action: STATE_SET "statename" state_value;
14661              transition: LINEAR 0.5;
14662              targets: "partname" "anotherpart";
14663              sequence {
14664                 action: SIGNAL_EMIT "signal" "source";
14665                 action: STATE_SET "somestate";
14666                 transition: SINUSOIDAL 0.4;
14667                 targets: "partname" "anotherpart";
14668                 signal: "also,runs"; source: "on,signals";
14669                 name: "runs_after_programname";
14670 
14671                 action: STATE_SET "someotherstate";
14672                 transition: DECELERATE 4.0;
14673                 in: 0.2 0.0;
14674                 targets: "partname" "anotherpart";
14675                 name: "runs_after_runs_after_programname";
14676                 after: "coolprogram1337";
14677                 filter: "partname" "goodstate";
14678              }
14679           }
14680        ..
14681     @description
14682         Sequences allow quick, easy chaining of programs.
14683         Each "action" keyword within the sequence will start a new program definition.
14684         Programs defined in sequences can be used as regular programs in every way,
14685         but they will automatically set up sequence chains which run after the originating program.
14686         After the sequence block is closed, the original program can continue to be
14687         modified.
14688         Scripts are allowed within sequences: each script block will be treated as a newly
14689         sequenced program.
14690         @since 1.10
14691     @endblock
14692  */
14693 static void
ob_collections_group_programs_program_sequence(void)14694 ob_collections_group_programs_program_sequence(void)
14695 {
14696    sequencing = current_program;
14697    sequencing_lookups = current_program_lookups;
14698    current_program_lookups = NULL;
14699    ((Edje_Program_Parser *)sequencing)->can_override = EINA_FALSE;
14700 }
14701 
14702 static void
st_collections_group_parts_part_api(void)14703 st_collections_group_parts_part_api(void)
14704 {
14705    check_min_arg_count(1);
14706 
14707    current_part->api.name = parse_str(0);
14708    if (is_param(1))
14709      {
14710         check_arg_count(2);
14711         current_part->api.description = parse_str(1);
14712      }
14713 }
14714 
14715 static void
ob_collections_group_programs_program_script(void)14716 ob_collections_group_programs_program_script(void)
14717 {
14718    Edje_Part_Collection *pc;
14719    Code *cd;
14720 
14721    pc = eina_list_data_get(eina_list_last(edje_collections));
14722    cd = eina_list_data_get(eina_list_last(codes));
14723 
14724    if (!is_verbatim()) track_verbatim(1);
14725    else
14726      {
14727         Eina_Bool empty = EINA_TRUE;
14728         char *s;
14729         int i, len;
14730 
14731         s = get_verbatim();
14732         if (s)
14733           {
14734              Code_Program *cp;
14735 
14736              /* FIXME: Need to store the script somewhere to be restored when using edje_edit API */
14737              cp = mem_alloc(SZ(Code_Program));
14738              cp->l1 = get_verbatim_line1();
14739              cp->l2 = get_verbatim_line2();
14740              cp->script = s;
14741              cp->original = strdup(s);
14742              if (cd->shared && cd->is_lua)
14743                {
14744                   ERR("parse error %s:%i. You're trying to mix Embryo and Lua scripting in the same group",
14745                       file_in, line - 1);
14746                   exit(-1);
14747                }
14748              cd->is_lua = 0;
14749 
14750              len = strlen(cp->script);
14751              for (i = 0; empty && i < len; i++)
14752                {
14753                   if (((cp->script[i] > 'a') && (cp->script[i] < 'z')) ||
14754                       ((cp->script[i] > 'A') && (cp->script[i] < 'Z')) ||
14755                       ((cp->script[i] > '0') && (cp->script[i] < '9')))
14756                     empty = EINA_FALSE;
14757                }
14758 
14759              if (sequencing)
14760                _program_sequence_new();
14761              if (!empty)
14762                {
14763                   cd->programs = eina_list_append(cd->programs, cp);
14764                   data_queue_anonymous_lookup(pc, current_program, &(cp->id));
14765                   current_program->action = EDJE_ACTION_TYPE_SCRIPT;
14766                }
14767              else
14768                {
14769                   data_queue_anonymous_lookup(pc, current_program, NULL);
14770                   free(cp->original);
14771                   free(cp);
14772                   cp = NULL;
14773                }
14774 
14775              set_verbatim(NULL, 0, 0);
14776           }
14777      }
14778 }
14779 
14780 /** @edcsubsection{collections_group_physics,
14781  *                 Group.Physics} */
14782 
14783 /**
14784     @page edcref
14785     @block
14786         physics
14787     @context
14788        group {
14789            ..
14790            physics {
14791                world {
14792                    ..
14793                }
14794            }
14795            ..
14796        }
14797     @description
14798         The "physics" block consists of blocks related to physics but
14799         not to configure a body. By now, it only has a "world" block.
14800     @endblock
14801  */
14802 
14803 /** @edcsubsection{collections_group_physics_world,
14804  *                Group.Physics.World} */
14805 
14806 /**
14807     @page edcref
14808     @block
14809         world
14810     @context
14811         physics {
14812             world {
14813                gravity: 0 294 0;
14814                rate: 30;
14815                z: -50;
14816                depth: 100;
14817             }
14818         }
14819     @description
14820         The "world" block configures the physics world. It's the
14821         environment where the part's bodies will be simulated.
14822         It can be used to customize gravity, rate, depth and others.
14823     @endblock
14824 
14825     @property
14826         gravity
14827     @parameters
14828         [x-axis] [y-axis] [z-axis]
14829     @effect
14830         Three double values defining the gravity vector.
14831         Each one is the component of this same vector over each axis.
14832         Its unit is Evas Coordinates per second ^ 2.
14833         The default value is 0, 294, 0, since we've a default rate of
14834         30 pixels.
14835     @since 1.8
14836     @endproperty
14837  */
14838 #ifdef HAVE_EPHYSICS
14839 static void
st_collections_group_physics_world_gravity(void)14840 st_collections_group_physics_world_gravity(void)
14841 {
14842    Edje_Part_Collection *pc;
14843 
14844    pc = eina_list_data_get(eina_list_last(edje_collections));
14845    check_arg_count(3);
14846 
14847    pc->physics.world.gravity.x = parse_int(0);
14848    pc->physics.world.gravity.y = parse_int(1);
14849    pc->physics.world.gravity.z = parse_int(2);
14850 }
14851 
14852 #endif
14853 
14854 /**
14855     @page edcref
14856     @property
14857         rate
14858     @parameters
14859         [rate pixels / meter]
14860     @effect
14861         Set rate between pixels on evas canvas and meters on physics world.
14862         It will be used by automatic updates of evas objects associated to
14863         physics bodies.
14864         By default rate is 30 pixels per meter.
14865     @since 1.8
14866     @endproperty
14867  */
14868 #ifdef HAVE_EPHYSICS
14869 static void
st_collections_group_physics_world_rate(void)14870 st_collections_group_physics_world_rate(void)
14871 {
14872    Edje_Part_Collection *pc;
14873 
14874    pc = eina_list_data_get(eina_list_last(edje_collections));
14875    check_arg_count(1);
14876 
14877    pc->physics.world.rate = parse_float(0);
14878 }
14879 
14880 #endif
14881 
14882 /**
14883     @page edcref
14884     @property
14885         depth
14886     @parameters
14887         [depth in pixels]
14888     @effect
14889         World's depth, in pixels. It's only relevant if boundaries are used,
14890         since their size depends on this.
14891         By default world's depth is 100 pixels.
14892     @since 1.8
14893     @endproperty
14894  */
14895 #ifdef HAVE_EPHYSICS
14896 static void
st_collections_group_physics_world_depth(void)14897 st_collections_group_physics_world_depth(void)
14898 {
14899    Edje_Part_Collection *pc;
14900 
14901    pc = eina_list_data_get(eina_list_last(edje_collections));
14902    check_arg_count(1);
14903 
14904    pc->physics.world.depth = parse_int(0);
14905 }
14906 
14907 #endif
14908 
14909 /**
14910     @page edcref
14911     @property
14912         z
14913     @parameters
14914         [world's front border position]
14915     @effect
14916         Position in z axis, in pixels.
14917         It's only relevant if boundaries are used, since their position
14918         depends on this.
14919         By default world's z is -50 pixels.
14920     @since 1.8
14921     @endproperty
14922  */
14923 #ifdef HAVE_EPHYSICS
14924 static void
st_collections_group_physics_world_z(void)14925 st_collections_group_physics_world_z(void)
14926 {
14927    Edje_Part_Collection *pc;
14928 
14929    pc = eina_list_data_get(eina_list_last(edje_collections));
14930    check_arg_count(1);
14931 
14932    pc->physics.world.z = parse_int(0);
14933 }
14934 
14935 #endif
14936 
14937 /**
14938     @page edcref
14939     </table>
14940  */
14941 
14942 void
edje_cc_handlers_pop_notify(const char * token)14943 edje_cc_handlers_pop_notify(const char *token)
14944 {
14945    if (sequencing && (!strcmp(token, "sequence")))
14946      {
14947         current_program = sequencing;
14948         ((Edje_Program_Parser *)sequencing)->can_override = EINA_TRUE;
14949         eina_list_free(current_program_lookups);
14950         current_program_lookups = sequencing_lookups;
14951         sequencing_lookups = NULL;
14952         sequencing = NULL;
14953      }
14954    else if (current_program && (!strcmp(token, "link")))
14955      current_program = NULL;
14956    else if (current_de && (!strcmp(token, "group")))
14957      {
14958         _link_combine();
14959         _script_flush();
14960      }
14961    else if (current_desc && (!strcmp(token, "description")))
14962      free_anchors();
14963 }
14964 
14965 static void
edje_cc_handlers_hierarchy_set(Edje_Part * src)14966 edje_cc_handlers_hierarchy_set(Edje_Part *src)
14967 {  /* This funcion makes current part rel_1.id, rel_2.id relative to src */
14968   if (!src->name)
14969     {
14970        ERR("parse error %s:%i. You must set parent name before creating nested part",
14971            file_in, line - 1);
14972        exit(-1);
14973     }
14974   st_collections_group_parts_part_description_rel1_to_set(src->name);
14975   st_collections_group_parts_part_description_rel2_to_set(src->name);
14976 }
14977 
14978 static Edje_Part *
edje_cc_handlers_hierarchy_parent_get(void)14979 edje_cc_handlers_hierarchy_parent_get(void)
14980 {  /* Return the parent part pointer */
14981   int idx = eina_array_count(part_hierarchy) - 2;
14982   Edje_Cc_Handlers_Hierarchy_Info *info = (idx >= 0) ?
14983     eina_array_data_get(part_hierarchy, idx) : NULL;
14984 
14985   return (info) ? info->ep : NULL;
14986 }
14987 
14988 static void
edje_cc_handlers_hierarchy_push(Edje_Part * ep,Edje_Part * cp)14989 edje_cc_handlers_hierarchy_push(Edje_Part *ep, Edje_Part *cp)
14990 {  /* Remove part from hierarchy stack when finished parsing it */
14991   Edje_Cc_Handlers_Hierarchy_Info *info = malloc(sizeof(*info));
14992   info->current_de = current_de;
14993   info->current_part = cp;   /* current_part restored on pop */
14994   info->current_item = current_item;
14995   info->current_desc = current_desc;
14996   info->parent_desc = parent_desc;
14997   info->current_program = current_program;
14998   info->ep = ep;
14999 
15000   eina_array_push(part_hierarchy, info);
15001 }
15002 
15003 static void
edje_cc_handlers_hierarchy_rename(Edje_Part * old,Edje_Part * new)15004 edje_cc_handlers_hierarchy_rename(Edje_Part *old, Edje_Part *new)
15005 {
15006    Edje_Cc_Handlers_Hierarchy_Info *item;
15007    Eina_Array_Iterator iterator;
15008    unsigned int i;
15009 
15010    EINA_ARRAY_ITER_NEXT(part_hierarchy, i, item, iterator)
15011    {
15012       if (item->ep == old) item->ep = new;
15013       if (item->current_part == old) item->current_part = new;
15014    }
15015 }
15016 
15017 void
edje_cc_handlers_hierarchy_alloc(void)15018 edje_cc_handlers_hierarchy_alloc(void)
15019 {
15020    part_hierarchy = eina_array_new(8);
15021 }
15022 
15023 void
edje_cc_handlers_hierarchy_free(void)15024 edje_cc_handlers_hierarchy_free(void)
15025 {
15026    eina_array_free(part_hierarchy);
15027    part_hierarchy = NULL;
15028 }
15029 
15030 static void
edje_cc_handlers_hierarchy_pop(void)15031 edje_cc_handlers_hierarchy_pop(void)
15032 {  /* Remove part from hierarchy stack when finished parsing it */
15033   Edje_Cc_Handlers_Hierarchy_Info *info = eina_array_pop(part_hierarchy);
15034 
15035   if (current_part)
15036     {
15037        unsigned int i;
15038 
15039        if (!current_part->name)
15040          {
15041             WRN("Parse error near %s:%i. Unnamed part exists in Group \"%s\".",
15042                 file_in, line - 1, current_de->entry);
15043          }
15044 
15045        for (i = 0; i < current_part->other.desc_count; i++)
15046          {
15047             if (!current_part->other.desc[i]->state.name)
15048               {
15049                  ERR("syntax error near %s:%i. Non-default or inherited parts are required to have state names for all descriptions (Group '%s', part '%s' has missing description state names)",
15050                      file_in, line - 1, current_de->entry, current_part->name);
15051                  exit(-1);
15052               }
15053          }
15054 
15055        /* auto-add default desc if it was omitted */
15056        if (!current_part->default_desc)
15057          ob_collections_group_parts_part_description();
15058     }
15059 
15060   if (info)
15061     {
15062        current_de = info->current_de;
15063        current_part = info->current_part;
15064        current_item = info->current_item;
15065        current_desc = info->current_desc;
15066        parent_desc = info->parent_desc;
15067        current_program = info->current_program;
15068 
15069        free(info);
15070     }
15071 }
15072 
15073 Eina_Bool
edje_cc_handlers_wildcard(void)15074 edje_cc_handlers_wildcard(void)
15075 {
15076    char *token, *last;
15077 
15078    token = eina_list_last_data_get(stack);
15079    last = eina_list_data_get(eina_list_prev(eina_list_last(stack)));
15080    if (!last) return EINA_FALSE;
15081    if (last)
15082      {
15083         char *end;
15084 
15085         end = strrchr(last, '.');
15086         if (end) last = end + 1;
15087      }
15088    if (current_part)
15089      {
15090         if ((!strcmp(last, "part")) && (!current_part->name))
15091           {
15092              Eina_Bool ret;
15093 
15094              if (!had_quote) return EINA_FALSE;
15095              current_part->name = token;
15096              ret = _part_name_check();
15097              if (ret)
15098                stack_pop_quick(EINA_FALSE, EINA_FALSE);
15099              return ret;
15100           }
15101         if (current_desc && ((!strcmp(last, "desc")) || (!strcmp(last, "description"))))
15102           {
15103              double st;
15104              char *end;
15105 
15106              if (had_quote)
15107                {
15108                   if ((!current_desc->state.name) || strcmp(current_desc->state.name, token))
15109                     {
15110                        free((char *)current_desc->state.name);
15111                        current_desc->state.name = token;
15112                        _part_description_state_update(current_desc);
15113                     }
15114                   stack_pop_quick(EINA_FALSE, current_desc->state.name != token);
15115                   return EINA_TRUE;
15116                }
15117 
15118              if (!isdigit(token[0])) return EINA_FALSE;
15119              st = strtod(token, &end);
15120              if ((end && end[0]) || (fabs(current_desc->state.value) > DBL_EPSILON))
15121                return EINA_FALSE;
15122              if (current_desc == current_part->default_desc)
15123                {
15124                   ob_collections_group_parts_part_description();
15125                   current_desc->state.name = strdup("default");
15126                }
15127              else
15128                {
15129                   unsigned int j;
15130 
15131                   for (j = 0; j < current_part->other.desc_count; j++)
15132                     {
15133                        /* check for inherited descriptions */
15134                        Edje_Part_Description_Common *ed = current_part->other.desc[j];
15135 
15136                        if (((!!ed->state.name) != (!!current_desc->state.name)) ||
15137                            (ed->state.name && strcmp(ed->state.name, current_desc->state.name)) ||
15138                            (!EINA_DBL_EQ(ed->state.value, st))) continue;
15139                        current_desc = ed;
15140                        break;
15141                     }
15142                   /* not found */
15143                   if (j == current_part->other.desc_count)
15144                     {
15145                        void *name = NULL;
15146 
15147                        if (current_desc->state.name)
15148                          name = strdup(current_desc->state.name);
15149                        ob_collections_group_parts_part_description();
15150                        current_desc->state.name = name;
15151                     }
15152                }
15153              current_desc->state.value = st;
15154              stack_pop_quick(EINA_FALSE, EINA_TRUE);
15155              return EINA_TRUE;
15156           }
15157      }
15158    if (current_program && ((!strcmp(last, "program")) || (!strcmp(last, "sequence"))))
15159      {
15160         if (!had_quote) return EINA_FALSE;
15161         _program_sequence_check();
15162         _program_name(token);
15163         stack_pop_quick(EINA_FALSE, EINA_FALSE);
15164         return EINA_TRUE;
15165      }
15166    if (current_de && (!strcmp(last, "group")))
15167      {
15168         if (!had_quote) return EINA_FALSE;
15169         _group_name(token);
15170         stack_pop_quick(EINA_FALSE, EINA_FALSE);
15171         return EINA_TRUE;
15172      }
15173    if (edje_file->styles && (!strcmp(last, "style")))
15174      {
15175         if (!had_quote) return EINA_FALSE;
15176         _style_name(token);
15177         stack_pop_quick(EINA_FALSE, EINA_FALSE);
15178         return EINA_TRUE;
15179      }
15180    if (edje_file->color_classes && (!strcmp(last, "color_class")))
15181      {
15182         if (!had_quote) return EINA_FALSE;
15183         _color_class_name(token);
15184         stack_pop_quick(EINA_FALSE, EINA_FALSE);
15185         return EINA_TRUE;
15186      }
15187    if (edje_file->text_classes && (!strcmp(last, "text_class")))
15188      {
15189         if (!had_quote) return EINA_FALSE;
15190         _text_class_name(token);
15191         stack_pop_quick(EINA_FALSE, EINA_FALSE);
15192         return EINA_TRUE;
15193      }
15194    if (edje_file->size_classes && (!strcmp(last, "size_class")))
15195      {
15196         if (!had_quote) return EINA_FALSE;
15197         _size_class_name(token);
15198         stack_pop_quick(EINA_FALSE, EINA_FALSE);
15199         return EINA_TRUE;
15200      }
15201    return EINA_FALSE;
15202 }
15203 
15204