1 #include "edje_private.h"
2 
3 static void _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop);
4 static void _edje_param_copy(Edje *ed, Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param);
5 static void _edje_param_set(Edje *ed, Edje_Real_Part *part, const char *param, const char *value);
6 
7 static double _edje_transition_duration_scale = 0;
8 
9 static Eina_Bool
_edje_animator_cb(void * data)10 _edje_animator_cb(void *data)
11 {
12    const Efl_Event event = { NULL, NULL, NULL };
13    _edje_timer_cb(data, &event);
14    return EINA_TRUE;
15 }
16 
17 static Eina_Bool
_edje_emit_aliased(Edje * ed,const char * part,const char * sig,const char * src)18 _edje_emit_aliased(Edje *ed, const char *part, const char *sig, const char *src)
19 {
20    char *alias, *aliased;
21    int alien, nslen, length;
22 
23    /* lookup for alias */
24    if ((!ed->collection) || (!ed->collection->alias)) return EINA_FALSE;
25    alias = eina_hash_find(ed->collection->alias, part);
26    if (!alias) return EINA_FALSE;
27 
28    alien = strlen(alias);
29    nslen = strlen(sig);
30    length = alien + nslen + 2;
31 
32    aliased = alloca(length);
33    memcpy(aliased, alias, alien);
34    aliased[alien] = EDJE_PART_PATH_SEPARATOR;
35    memcpy(aliased + alien + 1, sig, nslen + 1);
36 
37    _edje_emit(ed, aliased, src);
38    return EINA_TRUE;
39 }
40 
41 static Eina_Bool
_edje_emit_child(Edje * ed,Edje_Real_Part * rp,const char * part,const char * sig,const char * src)42 _edje_emit_child(Edje *ed, Edje_Real_Part *rp, const char *part, const char *sig, const char *src)
43 {
44    Edje *ed2;
45    char *idx;
46 
47    /* search for the index if present and remove it from the part */
48    idx = strchr(part, EDJE_PART_PATH_SEPARATOR_INDEXL);
49    if (idx)
50      {
51         char *end;
52 
53         end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
54         if (end && end != idx + 1)
55           {
56              char *tmp;
57 
58              tmp = alloca(end - idx);
59              memcpy(tmp, idx + 1, end - idx - 1);
60              tmp[end - idx - 1] = '\0';
61              *idx = '\0';
62              idx = tmp;
63           }
64         else
65           {
66              idx = NULL;
67           }
68      }
69 
70    /* search for the right part now */
71    if (!rp)
72      rp = _edje_real_part_get(ed, part);
73    if (!rp) return ed->collection->broadcast_signal;
74 
75    switch (rp->part->type)
76      {
77       case EDJE_PART_TYPE_GROUP:
78         if (((rp->type != EDJE_RP_TYPE_SWALLOW) ||
79              (!rp->typedata.swallow)) ||
80             (!rp->typedata.swallow->swallowed_object))
81           break;
82         ed2 = _edje_fetch(rp->typedata.swallow->swallowed_object);
83         if (!ed2) break;
84 
85         _edje_emit(ed2, sig, src);
86         return EINA_FALSE;
87 
88       case EDJE_PART_TYPE_EXTERNAL:
89         if (((rp->type != EDJE_RP_TYPE_SWALLOW) ||
90              (!rp->typedata.swallow)) ||
91             (!rp->typedata.swallow->swallowed_object))
92           break;
93 
94         if (!idx)
95           {
96              _edje_external_signal_emit(rp->typedata.swallow->swallowed_object, sig, src);
97           }
98         else
99           {
100              Evas_Object *child;
101 
102              child = _edje_children_get(rp, idx);
103              ed2 = _edje_fetch(child);
104              if (!ed2) break;
105              _edje_emit(ed2, sig, src);
106           }
107         return EINA_FALSE;
108 
109       case EDJE_PART_TYPE_BOX:
110       case EDJE_PART_TYPE_TABLE:
111         if (idx)
112           {
113              Evas_Object *child;
114 
115              child = _edje_children_get(rp, idx);
116              ed2 = _edje_fetch(child);
117              if (!ed2) break;
118              _edje_emit(ed2, sig, src);
119              return EINA_FALSE;
120           }
121         break;
122 
123       default:
124         //              ERR("Unknown part type. You should never be here!");
125         break;
126      }
127    return ed->collection->broadcast_signal;
128 }
129 
130 static Edje_Message_Signal_Data *
_edje_signal_data_setup(void * data,Ecore_Cb free_func,void * seat_data,Ecore_Cb seat_free_func)131 _edje_signal_data_setup(void *data, Ecore_Cb free_func, void *seat_data, Ecore_Cb seat_free_func)
132 {
133    Edje_Message_Signal_Data *out = NULL;
134 
135    if (data || seat_data)
136      {
137         out = calloc(1, sizeof(*out));
138         if (!out) return NULL;
139 
140         out->ref = 1;
141         out->data = data;
142         out->free_func = free_func;
143         out->seat_data = seat_data;
144         out->seat_free_func = seat_free_func;
145      }
146    return out;
147 }
148 
149 void
_edje_signal_data_free(Edje_Message_Signal_Data * mdata)150 _edje_signal_data_free(Edje_Message_Signal_Data *mdata)
151 {
152    if (!mdata) return;
153    if (--(mdata->ref)) return;
154 
155    if (mdata->free_func)
156      {
157         mdata->free_func(mdata->data);
158      }
159    if (mdata->seat_free_func)
160      {
161         mdata->seat_free_func(mdata->seat_data);
162      }
163    free(mdata);
164 }
165 
166 void
_edje_signal_data_ref(Edje_Message_Signal_Data * mdata)167 _edje_signal_data_ref(Edje_Message_Signal_Data *mdata)
168 {
169    if (mdata) mdata->ref++;
170 }
171 
172 static void
_edje_emit_send(Edje * ed,Eina_Bool broadcast,const char * sig,const char * src,Edje_Message_Signal_Data * mdata)173 _edje_emit_send(Edje *ed, Eina_Bool broadcast, const char *sig, const char *src, Edje_Message_Signal_Data *mdata)
174 {
175    Edje_Message_Signal emsg;
176 
177    emsg.sig = sig;
178    emsg.src = src;
179    emsg.data = mdata;
180    /* new sends code */
181    if (broadcast)
182      edje_object_message_send(ed->obj, EDJE_MESSAGE_SIGNAL, 0, &emsg);
183    else
184      _edje_util_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
185    /* old send code - use api now
186       _edje_util_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
187       EINA_LIST_FOREACH(ed->subobjs, l, obj)
188       {
189       Edje *ed2;
190 
191       ed2 = _edje_fetch(obj);
192       if (!ed2) continue;
193       if (ed2->delete_me) continue;
194       _edje_util_message_send(ed2, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
195       }
196     */
197 }
198 
199 /*============================================================================*
200 *                                   API                                      *
201 *============================================================================*/
202 
203 EOLIAN Eina_Stringshare*
_efl_canvas_layout_seat_name_get(const Eo * obj EINA_UNUSED,Edje * ed,Efl_Input_Device * device)204 _efl_canvas_layout_seat_name_get(const Eo *obj EINA_UNUSED, Edje *ed, Efl_Input_Device *device)
205 {
206    return _edje_seat_name_get(ed, device);
207 }
208 
209 EOLIAN Efl_Input_Device *
_efl_canvas_layout_seat_get(const Eo * obj EINA_UNUSED,Edje * ed,Eina_Stringshare * name)210 _efl_canvas_layout_seat_get(const Eo *obj EINA_UNUSED, Edje *ed, Eina_Stringshare *name)
211 {
212    return _edje_seat_get(ed, name);
213 }
214 
215 EAPI void
edje_frametime_set(double t)216 edje_frametime_set(double t)
217 {
218    ecore_animator_frametime_set(t);
219 }
220 
221 EAPI double
edje_frametime_get(void)222 edje_frametime_get(void)
223 {
224    return ecore_animator_frametime_get();
225 }
226 
227 EAPI double
edje_transition_duration_factor_get(void)228 edje_transition_duration_factor_get(void)
229 {
230    return _edje_transition_duration_scale;
231 }
232 
233 EAPI void
edje_transition_duration_factor_set(double scale)234 edje_transition_duration_factor_set(double scale)
235 {
236    _edje_transition_duration_scale = FROM_DOUBLE(scale);
237 }
238 
239 Eina_Bool
_edje_object_signal_callback_add(Evas_Object * obj,Edje * ed,const char * emission,const char * source,Edje_Signal_Cb func_legacy,Efl_Signal_Cb func_eo,Eina_Free_Cb func_free_cb,void * data)240 _edje_object_signal_callback_add(Evas_Object *obj, Edje *ed,
241                                  const char *emission, const char *source,
242                                  Edje_Signal_Cb func_legacy,
243                                  Efl_Signal_Cb func_eo, Eina_Free_Cb func_free_cb, void *data)
244 {
245    Edje_Signal_Callback_Group *gp;
246    const char *sig;
247    const char *src;
248    Eina_Bool ok;
249 
250    if (!ed->callbacks)
251      ed->callbacks = _edje_signal_callback_alloc();
252    if (!ed->callbacks) return EINA_FALSE;
253 
254    sig = eina_stringshare_add(emission);
255    src = eina_stringshare_add(source);
256 
257    // Only load seat callbacks and trigger events just before we might need them.
258    if (!ed->need_seat && sig && !strncmp(sig, "seat,", 5))
259      {
260         ed->need_seat = EINA_TRUE;
261         if (ed->collection)
262           _edje_devices_add(ed, evas_object_evas_get(obj));
263      }
264 
265    gp = (Edje_Signal_Callback_Group *) ed->callbacks;
266    ok = _edje_signal_callback_push(gp, sig, src, func_legacy, func_eo, func_free_cb, data, EINA_TRUE);
267 
268    eina_stringshare_del(sig);
269    eina_stringshare_del(src);
270 
271    return ok;
272 }
273 
274 void
edje_object_propagate_callback_add(Evas_Object * obj,Efl_Signal_Cb func,void * data)275 edje_object_propagate_callback_add(Evas_Object *obj, Efl_Signal_Cb func, void *data)
276 {
277    Edje *ed;
278 
279    ed = _edje_fetch(obj);
280    if (!ed || ed->delete_me) return;
281    _edje_object_signal_callback_add(obj, ed, "*", "*", func, NULL, NULL, data);
282 }
283 
284 Eina_Bool
_efl_canvas_layout_efl_layout_signal_signal_callback_add(Eo * obj EINA_UNUSED,Edje * ed,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)285 _efl_canvas_layout_efl_layout_signal_signal_callback_add(Eo *obj EINA_UNUSED, Edje *ed, const char *emission, const char *source, void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
286 {
287    return _edje_object_signal_callback_add(obj, ed, emission, source, NULL, func, func_free_cb, func_data);
288 }
289 
290 Eina_Bool
_efl_canvas_layout_efl_layout_signal_signal_callback_del(Eo * obj EINA_UNUSED,Edje * ed,const char * emission,const char * source,void * func_data,EflLayoutSignalCb func,Eina_Free_Cb func_free_cb)291 _efl_canvas_layout_efl_layout_signal_signal_callback_del(Eo *obj EINA_UNUSED, Edje *ed, const char *emission, const char *source, void *func_data, EflLayoutSignalCb func, Eina_Free_Cb func_free_cb)
292 {
293    Edje_Signal_Callback_Group *gp;
294    Eina_Bool ok;
295 
296    if (ed->delete_me) return EINA_FALSE;
297    if ((!emission) || (!source) || (!func)) return EINA_FALSE;
298 
299    gp = (Edje_Signal_Callback_Group *) ed->callbacks;
300    if (!gp) return EINA_FALSE;
301 
302    emission = eina_stringshare_add(emission);
303    source = eina_stringshare_add(source);
304 
305    ok = _edje_signal_callback_disable(gp, emission, source, NULL, func, func_free_cb, func_data);
306 
307    eina_stringshare_del(emission);
308    eina_stringshare_del(source);
309 
310    return ok;
311 }
312 
313 EOLIAN void
_efl_canvas_layout_efl_layout_signal_signal_emit(Eo * obj EINA_UNUSED,Edje * ed,const char * emission,const char * source)314 _efl_canvas_layout_efl_layout_signal_signal_emit(Eo *obj EINA_UNUSED, Edje *ed, const char *emission, const char *source)
315 {
316    if (ed->delete_me) return;
317    if ((!emission) || (!source)) return;
318    _edje_emit(ed, emission, source);
319 }
320 
321 /* FIXDOC: Verify/Expand */
322 EOLIAN void
_efl_canvas_layout_animated_set(Eo * obj,Edje * ed,Eina_Bool on)323 _efl_canvas_layout_animated_set(Eo *obj, Edje *ed, Eina_Bool on)
324 {
325    Eina_List *l;
326    unsigned short i;
327 
328    if (!ed) return;
329    if (ed->delete_me) return;
330    _edje_block(ed);
331    ed->no_anim = !on;
332    _edje_util_freeze(ed);
333    if (!on)
334      {
335         Eina_List *newl = NULL;
336         Edje_Running_Program *data;
337 
338         EINA_LIST_FOREACH(ed->actions, l, data)
339           {
340              data->ref++;
341              newl = eina_list_append(newl, data);
342           }
343         while (newl)
344           {
345              Edje_Running_Program *runp;
346 
347              runp = eina_list_data_get(newl);
348              newl = eina_list_remove(newl, eina_list_data_get(newl));
349              runp->ref--;
350              _edje_program_run_iterate(runp, runp->start_time + TO_DOUBLE(runp->program->tween.time));
351              if (_edje_block_break(ed))
352                {
353                  EINA_LIST_FREE(newl, data)
354                     {
355                        data->ref--;
356                        if ((data->delete_me) && (data->ref == 0))
357                          {
358                             _edje_program_run_cleanup(ed, data);
359                             free(data);
360                          }
361                     }
362                   goto break_prog;
363                }
364           }
365      }
366    else
367      {
368         _edje_emit(ed, "load", NULL);
369         if (evas_object_visible_get(obj))
370           {
371              evas_object_hide(obj);
372              evas_object_show(obj);
373           }
374      }
375 break_prog:
376 
377    for (i = 0; i < ed->table_parts_size; i++)
378      {
379         Edje_Real_Part *rp;
380         rp = ed->table_parts[i];
381         if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
382             ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
383              (rp->typedata.swallow)) &&
384             (rp->typedata.swallow->swallowed_object))
385           edje_object_animation_set(rp->typedata.swallow->swallowed_object, on);
386      }
387 
388    _edje_util_thaw(ed);
389    _edje_unblock(ed);
390 }
391 
392 EOLIAN Eina_Bool
_efl_canvas_layout_animated_get(const Eo * obj EINA_UNUSED,Edje * ed)393 _efl_canvas_layout_animated_get(const Eo *obj EINA_UNUSED, Edje *ed)
394 {
395    if (!ed) return EINA_FALSE;
396    if (ed->delete_me) return EINA_FALSE;
397    if (ed->no_anim) return EINA_FALSE;
398 
399    return EINA_TRUE;
400 }
401 
402 /* Private Routines */
403 void
_edje_program_run_cleanup(Edje * ed,Edje_Running_Program * runp)404 _edje_program_run_cleanup(Edje *ed, Edje_Running_Program *runp)
405 {
406    ed->actions = eina_list_remove(ed->actions, runp);
407    if (!ed->actions)
408      {
409         efl_event_callback_del(ed->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _edje_timer_cb, ed);
410         ecore_animator_del(ed->animator);
411         ed->animator = NULL;
412      }
413 }
414 
415 Eina_Bool
_edje_program_run_iterate(Edje_Running_Program * runp,double tim)416 _edje_program_run_iterate(Edje_Running_Program *runp, double tim)
417 {
418    FLOAT_T t, total, t_scale = runp->edje->duration_scale;
419    Eina_List *l;
420    Edje *ed;
421    Edje_Program_Target *pt;
422    Edje_Real_Part *rp;
423 
424    ed = runp->edje;
425    if (ed->delete_me) return EINA_FALSE;
426    _edje_block(ed);
427    _edje_ref(ed);
428    _edje_util_freeze(ed);
429 
430    if (runp->program->tween.use_duration_factor)
431      t_scale = _edje_transition_duration_scale;
432    t = FROM_DOUBLE(tim - runp->start_time);
433    total = runp->program->tween.time * t_scale;
434    t = DIV(t, total);
435    if (t > FROM_INT(1)) t = FROM_INT(1);
436    EINA_LIST_FOREACH(runp->program->targets, l, pt)
437      {
438         if (pt->id >= 0)
439           {
440              rp = ed->table_parts[pt->id % ed->table_parts_size];
441              if (rp)
442                _edje_part_pos_set(ed, rp,
443                                   runp->program->tween.mode, t,
444                                   runp->program->tween.v1,
445                                   runp->program->tween.v2,
446                                   runp->program->tween.v3,
447                                   runp->program->tween.v4);
448           }
449      }
450    if (t >= FROM_INT(1))
451      {
452         Edje_Program_After *pa;
453 
454         EINA_LIST_FOREACH(runp->program->targets, l, pt)
455           {
456              if (pt->id >= 0)
457                {
458                   rp = ed->table_parts[pt->id % ed->table_parts_size];
459                   if (rp)
460                     {
461                        _edje_part_description_apply(ed, rp,
462                                                     runp->program->state,
463                                                     runp->program->value,
464                                                     NULL,
465                                                     0.0);
466                        _edje_part_pos_set(ed, rp,
467                                           runp->program->tween.mode, ZERO,
468                                           runp->program->tween.v1,
469                                           runp->program->tween.v2,
470                                           runp->program->tween.v3,
471                                           runp->program->tween.v4);
472                        rp->program = NULL;
473                     }
474                }
475           }
476         _edje_recalc(ed);
477         runp->delete_me = EINA_TRUE;
478         if (!ed->walking_actions)
479           _edje_program_run_cleanup(ed, runp);
480         //	_edje_emit(ed, "program,stop", runp->program->name);
481         if (_edje_block_break(ed))
482           {
483              if (!ed->walking_actions)
484                {
485                   if (runp->ref == 0)
486                     {
487                        _edje_program_run_cleanup(ed, runp);
488                        free(runp);
489                     }
490                }
491              goto break_prog;
492           }
493         EINA_LIST_FOREACH(runp->program->after, l, pa)
494           {
495              Edje_Program *pr;
496 
497              if (pa->id >= 0)
498                {
499                   pr = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
500                   if (pr) _edje_program_run(ed, pr, 0, "", "", NULL);
501                   if (_edje_block_break(ed))
502                     {
503                        if ((!ed->walking_actions) && (runp->ref == 0))
504                          {
505                             _edje_program_run_cleanup(ed, runp);
506                             free(runp);
507                          }
508                        goto break_prog;
509                     }
510                }
511           }
512         _edje_util_thaw(ed);
513         _edje_unref(ed);
514         if ((!ed->walking_actions) && (runp->ref == 0))
515           {
516              _edje_program_run_cleanup(ed, runp);
517              free(runp);
518           }
519         _edje_unblock(ed);
520         return EINA_FALSE;
521      }
522 break_prog:
523    _edje_recalc(ed);
524    _edje_util_thaw(ed);
525    _edje_unref(ed);
526    _edje_unblock(ed);
527    return EINA_TRUE;
528 }
529 
530 void
_edje_program_end(Edje * ed,Edje_Running_Program * runp)531 _edje_program_end(Edje *ed, Edje_Running_Program *runp)
532 {
533    Eina_List *l;
534    Edje_Program_Target *pt;
535    //   const char *pname = NULL;
536    int free_runp = 0;
537 
538    if (ed->delete_me) return;
539    _edje_ref(ed);
540    _edje_util_freeze(ed);
541    EINA_LIST_FOREACH(runp->program->targets, l, pt)
542      {
543         Edje_Real_Part *rp;
544 
545         if (pt->id >= 0)
546           {
547              rp = ed->table_parts[pt->id % ed->table_parts_size];
548              if (rp)
549                {
550                   _edje_part_description_apply(ed, rp,
551                                                runp->program->state,
552                                                runp->program->value,
553                                                NULL,
554                                                0.0);
555                   _edje_part_pos_set(ed, rp,
556                                      runp->program->tween.mode, ZERO,
557                                      runp->program->tween.v1,
558                                      runp->program->tween.v2,
559                                      runp->program->tween.v3,
560                                      runp->program->tween.v4);
561 
562                   rp->program = NULL;
563                }
564           }
565      }
566    _edje_recalc(ed);
567    runp->delete_me = EINA_TRUE;
568    //   pname = runp->program->name;
569    if (!ed->walking_actions)
570      {
571         _edje_program_run_cleanup(ed, runp);
572         free_runp = 1;
573      }
574    //   _edje_emit(ed, "program,stop", pname);
575    _edje_util_thaw(ed);
576    _edje_unref(ed);
577    if ((free_runp) && (runp->ref == 0)) free(runp);
578 }
579 
580 #ifdef HAVE_EPHYSICS
581 static Eina_Bool
_edje_physics_action_set(Edje * ed,Edje_Program * pr,void (* func)(EPhysics_Body * body,double x,double y,double z))582 _edje_physics_action_set(Edje *ed, Edje_Program *pr, void (*func)(EPhysics_Body *body, double x, double y, double z))
583 {
584    Edje_Program_Target *pt;
585    Edje_Real_Part *rp;
586    Eina_List *l;
587 
588    if (_edje_block_break(ed)) return EINA_FALSE;
589 
590    EINA_LIST_FOREACH(pr->targets, l, pt)
591      {
592         if (pt->id >= 0)
593           {
594              rp = ed->table_parts[pt->id % ed->table_parts_size];
595              if ((rp) && (rp->body))
596                func(rp->body, pr->physics.x, pr->physics.y, pr->physics.z);
597           }
598      }
599 
600    return EINA_TRUE;
601 }
602 
603 #endif
604 
605 static void
_edje_seat_name_emit(Edje * ed,const char * name,const char * sig,const char * src)606 _edje_seat_name_emit(Edje *ed, const char *name, const char *sig, const char *src)
607 {
608    char buf[128];
609 
610    /* keep sending signals without seat information for legacy compatibility */
611    _edje_emit_full(ed, sig, src, NULL, NULL);
612 
613    if (!name) return;
614 
615    snprintf(buf, sizeof(buf), "seat,%s,%s", name, sig);
616    _edje_emit_full(ed, buf, src, NULL, NULL);
617 }
618 
619 void
_edje_part_focus_set(Edje * ed,const char * seat_name,Edje_Real_Part * rp)620 _edje_part_focus_set(Edje *ed, const char *seat_name, Edje_Real_Part *rp)
621 {
622    Edje_Real_Part *focused_part;
623    Eina_Stringshare *sname;
624    Efl_Input_Device *seat;
625    Evas *e;
626 
627    if (seat_name)
628      sname = eina_stringshare_add(seat_name);
629    else /* Use default seat name */
630      {
631         e = evas_object_evas_get(ed->obj);
632         seat = evas_default_device_get(e, EVAS_DEVICE_CLASS_SEAT);
633         sname = eina_stringshare_ref(_edje_seat_name_get(ed, seat));
634      }
635 
636    focused_part = _edje_focused_part_get(ed, sname);
637 
638    if (focused_part != rp)
639      {
640         if (rp && (rp->part->allowed_seats) &&
641             (!_edje_part_allowed_seat_find(rp, sname)))
642           goto not_allowed;
643 
644         if (focused_part)
645           _edje_seat_name_emit(ed, sname, "focus,part,out",
646                                focused_part->part->name);
647         _edje_focused_part_set(ed, sname, rp);
648         if (rp)
649           _edje_seat_name_emit(ed, sname, "focus,part,in", rp->part->name);
650      }
651 
652 not_allowed:
653    eina_stringshare_del(sname);
654 }
655 
656 void
_edje_program_run(Edje * ed,Edje_Program * pr,Eina_Bool force,const char * ssig,const char * ssrc,Edje_Message_Signal_Data * mdata)657 _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc, Edje_Message_Signal_Data *mdata)
658 {
659    Eina_List *l;
660    Edje_Real_Part *rp;
661    Edje_Program_Target *pt;
662    Edje_Program *pr2;
663    Edje_Program_After *pa;
664    /* limit self-feeding loops in programs to 64 levels */
665    static int recursions = 0;
666    static int recursion_limit = 0;
667 
668    if (ed->delete_me) return;
669    if ((pr->in.from > 0.0) && (pr->in.range >= 0.0) && (!force))
670      {
671         Edje_Pending_Program *pp;
672         double r = 0.0;
673 
674         pp = calloc(1, sizeof(Edje_Pending_Program));
675         if (!pp) return;
676         if (pr->in.range > 0.0) r = ((double)rand() / RAND_MAX);
677         pp->timer = ecore_timer_add(pr->in.from + (pr->in.range * r),
678                                     _edje_pending_timer_cb, pp);
679         if (!pp->timer)
680           {
681              free(pp);
682              return;
683           }
684         pp->edje = ed;
685         pp->program = pr;
686         ed->pending_actions = eina_list_append(ed->pending_actions, pp);
687         return;
688      }
689    if ((recursions >= 64) || (recursion_limit))
690      {
691         ERR("Programs recursing up to recursion limit of %i in '%s' with sig='%s', src='%s' from '%s', '%s'. Disabled.",
692             64, pr->name, ssig, ssrc, ed->path, ed->group);
693         if (pr->action == EDJE_ACTION_TYPE_STATE_SET && (EQ(pr->tween.time, ZERO) || (ed->no_anim)))
694           ERR("Possible solution: try adding transition time to prevent Schrödinger's part state");
695         recursion_limit = 1;
696         return;
697      }
698    recursions++;
699    _edje_block(ed);
700    _edje_ref(ed);
701    _edje_util_freeze(ed);
702    switch (pr->action)
703      {
704       case EDJE_ACTION_TYPE_STATE_SET:
705         if ((pr->tween.time > ZERO) && (!ed->no_anim))
706           {
707              Edje_Running_Program *runp;
708 
709              runp = calloc(1, sizeof(Edje_Running_Program));
710              EINA_LIST_FOREACH(pr->targets, l, pt)
711                {
712                   if (pt->id >= 0)
713                     {
714                        rp = ed->table_parts[pt->id % ed->table_parts_size];
715                        if (rp)
716                          {
717                             if ((rp->object) && (pr->tween.mode & EDJE_TWEEN_MODE_OPT_FROM_CURRENT))
718                               {
719                                  Edje_Calc_Params *tmp;
720 
721                                  tmp = calloc(1, sizeof(Edje_Calc_Params));
722                                  if (!tmp) goto low_mem_current;
723                                  _edje_part_recalc(ed, rp, FLAG_XY, tmp);
724 
725                                  if (rp->current)
726                                    {
727 #ifdef EDJE_CALC_CACHE
728                                       _edje_calc_params_clear(rp->current);
729 #endif
730                                       free(rp->current);
731                                    }
732                                  rp->current = tmp;
733                               }
734                             else
735                               {
736 low_mem_current:
737                                  if (rp->current)
738                                    {
739 #ifdef EDJE_CALC_CACHE
740                                       _edje_calc_params_clear(rp->current);
741 #endif
742                                       free(rp->current);
743                                    }
744                                  rp->current = NULL;
745                               }
746 
747                             if (rp->program)
748                               _edje_program_end(ed, rp->program);
749                             _edje_part_description_apply(ed, rp,
750                                                          rp->param1.description->state.name,
751                                                          rp->param1.description->state.value,
752                                                          pr->state,
753                                                          pr->value);
754                             _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
755                                                pr->tween.v1,
756                                                pr->tween.v2,
757                                                pr->tween.v3,
758                                                pr->tween.v4);
759                             rp->program = runp;
760                          }
761                     }
762                }
763              // _edje_emit(ed, "program,start", pr->name);
764              if (_edje_block_break(ed))
765                {
766                   ed->actions = eina_list_append(ed->actions, runp);
767                   goto break_prog;
768                }
769 
770              if (!ed->actions)
771                {
772                   if (ed->canvas_animator)
773                     efl_event_callback_add(ed->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _edje_timer_cb, ed);
774                   else
775                     ed->animator = ecore_animator_add(_edje_animator_cb, ed);
776                }
777              ed->actions = eina_list_append(ed->actions, runp);
778 
779              runp->start_time = ecore_loop_time_get();
780              runp->edje = ed;
781              runp->program = pr;
782           }
783         else
784           {
785              EINA_LIST_FOREACH(pr->targets, l, pt)
786                {
787                   if (pt->id >= 0)
788                     {
789                        rp = ed->table_parts[pt->id % ed->table_parts_size];
790                        if (rp)
791                          {
792                             if (rp->program)
793                               _edje_program_end(ed, rp->program);
794                             _edje_part_description_apply(ed, rp,
795                                                          pr->state,
796                                                          pr->value,
797                                                          NULL,
798                                                          0.0);
799                             _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
800                                                pr->tween.v1,
801                                                pr->tween.v2,
802                                                pr->tween.v3,
803                                                pr->tween.v4);
804                          }
805                     }
806                }
807              // _edje_emit(ed, "program,start", pr->name);
808              if (_edje_block_break(ed)) goto break_prog;
809              // _edje_emit(ed, "program,stop", pr->name);
810              if (_edje_block_break(ed)) goto break_prog;
811 
812              EINA_LIST_FOREACH(pr->after, l, pa)
813                {
814                   if (pa->id >= 0)
815                     {
816                        pr2 = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
817                        if (pr2) _edje_program_run(ed, pr2, 0, "", "", mdata);
818                        if (_edje_block_break(ed)) goto break_prog;
819                     }
820                }
821              _edje_recalc(ed);
822           }
823         break;
824 
825       case EDJE_ACTION_TYPE_ACTION_STOP:
826         // _edje_emit(ed, "program,start", pr->name);
827         EINA_LIST_FOREACH(pr->targets, l, pt)
828           {
829              Eina_List *ll;
830              Edje_Running_Program *runp;
831              Edje_Pending_Program *pp;
832 
833              for (ll = ed->actions; ll; )
834                {
835                   runp = ll->data;
836                   ll = ll->next;
837                   if (pt->id == runp->program->id)
838                     {
839                        _edje_program_end(ed, runp);
840                        //		       goto done;
841                     }
842                }
843              for (ll = ed->pending_actions; ll; )
844                {
845                   pp = ll->data;
846                   ll = ll->next;
847                   if (pt->id == pp->program->id)
848                     {
849                        ed->pending_actions = eina_list_remove(ed->pending_actions, pp);
850                        ecore_timer_del(pp->timer);
851                        pp->timer = NULL;
852                        free(pp);
853                        //		       goto done;
854                     }
855                }
856              //	     done:
857              //	        continue;
858           }
859         // _edje_emit(ed, "program,stop", pr->name);
860         if (_edje_block_break(ed)) goto break_prog;
861         break;
862 
863       case EDJE_ACTION_TYPE_SIGNAL_EMIT:
864         // _edje_emit(ed, "program,start", pr->name);
865         if (_edje_block_break(ed)) goto break_prog;
866         if (pr->targets)
867           {
868              EINA_LIST_FOREACH(pr->targets, l, pt)
869                {
870                   if (pt->id < 0) continue;
871                   rp = ed->table_parts[pt->id % ed->table_parts_size];
872                   if (!rp) continue;
873                   if (!_edje_emit_aliased(ed, rp->part->name, pr->state, pr->state2))
874                     {
875                        Eina_Bool broadcast;
876 
877                        broadcast = _edje_emit_child(ed, rp, rp->part->name, pr->state, pr->state2);
878                        _edje_emit_send(ed, broadcast, pr->state, pr->state2, mdata);
879                     }
880                }
881           }
882         else
883           _edje_emit_full_data(ed, pr->state, pr->state2, mdata);
884         if (_edje_block_break(ed)) goto break_prog;
885         // _edje_emit(ed, "program,stop", pr->name);
886         if (_edje_block_break(ed)) goto break_prog;
887         break;
888 
889       case EDJE_ACTION_TYPE_DRAG_VAL_SET:
890         // _edje_emit(ed, "program,start", pr->name);
891         if (_edje_block_break(ed)) goto break_prog;
892         EINA_LIST_FOREACH(pr->targets, l, pt)
893           {
894              if (pt->id >= 0)
895                {
896                   rp = ed->table_parts[pt->id % ed->table_parts_size];
897                   if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
898                     {
899                        rp->drag->val.x = pr->value;
900                        rp->drag->val.y = pr->value2;
901                        if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
902                        else if (rp->drag->val.x > 1.0)
903                          rp->drag->val.x = 1.0;
904                        if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
905                        else if (rp->drag->val.y > 1.0)
906                          rp->drag->val.y = 1.0;
907                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
908                        _edje_emit(ed, "drag,set", rp->part->name);
909                        if (_edje_block_break(ed)) goto break_prog;
910                     }
911                }
912           }
913         // _edje_emit(ed, "program,stop", pr->name);
914         if (_edje_block_break(ed)) goto break_prog;
915         break;
916 
917       case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
918         // _edje_emit(ed, "program,start", pr->name);
919         if (_edje_block_break(ed)) goto break_prog;
920         EINA_LIST_FOREACH(pr->targets, l, pt)
921           {
922              if (pt->id >= 0)
923                {
924                   rp = ed->table_parts[pt->id % ed->table_parts_size];
925                   if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
926                     {
927                        rp->drag->val.x += pr->value * rp->drag->step.x * rp->part->dragable.x;
928                        rp->drag->val.y += pr->value2 * rp->drag->step.y * rp->part->dragable.y;
929                        if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
930                        else if (rp->drag->val.x > 1.0)
931                          rp->drag->val.x = 1.0;
932                        if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
933                        else if (rp->drag->val.y > 1.0)
934                          rp->drag->val.y = 1.0;
935                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
936                        _edje_emit(ed, "drag,step", rp->part->name);
937                        if (_edje_block_break(ed)) goto break_prog;
938                     }
939                }
940           }
941         // _edje_emit(ed, "program,stop", pr->name);
942         if (_edje_block_break(ed)) goto break_prog;
943         break;
944 
945       case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
946         // _edje_emit(ed, "program,start", pr->name);
947         if (_edje_block_break(ed)) goto break_prog;
948         EINA_LIST_FOREACH(pr->targets, l, pt)
949           {
950              if (pt->id >= 0)
951                {
952                   rp = ed->table_parts[pt->id % ed->table_parts_size];
953                   if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
954                     {
955                        rp->drag->val.x += pr->value * rp->drag->page.x * rp->part->dragable.x;
956                        rp->drag->val.y += pr->value2 * rp->drag->page.y * rp->part->dragable.y;
957                        if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
958                        else if (rp->drag->val.x > 1.0)
959                          rp->drag->val.x = 1.0;
960                        if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
961                        else if (rp->drag->val.y > 1.0)
962                          rp->drag->val.y = 1.0;
963                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
964                        _edje_emit(ed, "drag,page", rp->part->name);
965                        if (_edje_block_break(ed)) goto break_prog;
966                     }
967                }
968           }
969         // _edje_emit(ed, "program,stop", pr->name);
970         if (_edje_block_break(ed)) goto break_prog;
971         break;
972 
973       case EDJE_ACTION_TYPE_SCRIPT:
974       {
975          // _edje_emit(ed, "program,start", pr->name);
976          if (_edje_block_break(ed)) goto break_prog;
977          _edje_embryo_test_run(ed, pr, ssig, ssrc);
978          // _edje_emit(ed, "program,stop", pr->name);
979          if (_edje_block_break(ed)) goto break_prog;
980          _edje_recalc_do(ed);
981       }
982       break;
983 
984       case EDJE_ACTION_TYPE_FOCUS_SET:
985       {
986         if (!pr->targets)
987           _edje_part_focus_set(ed, pr->seat, NULL);
988         else
989           {
990              EINA_LIST_FOREACH(pr->targets, l, pt)
991                {
992                   if (pt->id >= 0)
993                     {
994                        rp = ed->table_parts[pt->id % ed->table_parts_size];
995                        if (rp)
996                          _edje_part_focus_set(ed, pr->seat, rp);
997                     }
998                }
999           }
1000       }
1001       break;
1002 
1003       case EDJE_ACTION_TYPE_FOCUS_OBJECT:
1004       {
1005          Efl_Input_Device *seat = NULL;
1006 
1007          if (pr->seat)
1008            {
1009               Eina_Stringshare *seat_name;
1010 
1011               seat_name = eina_stringshare_add(pr->seat);
1012               seat = _edje_seat_get(ed, seat_name);
1013               eina_stringshare_del(seat_name);
1014            }
1015          if (!seat)
1016            {
1017               Evas *e;
1018 
1019               e = evas_object_evas_get(ed->obj);
1020               seat = evas_default_device_get(e, EVAS_DEVICE_CLASS_SEAT);
1021            }
1022         if (!pr->targets)
1023           {
1024              Evas_Object *focused;
1025 
1026              focused = evas_seat_focus_get(evas_object_evas_get(ed->obj), seat);
1027              if (focused)
1028                {
1029                   unsigned int i;
1030 
1031                   /* Check if the current swallowed object is one of my child. */
1032                   for (i = 0; i < ed->table_parts_size; ++i)
1033                     {
1034                        rp = ed->table_parts[i];
1035                        if ((rp) &&
1036                            ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1037                             (rp->typedata.swallow)) &&
1038                            (rp->typedata.swallow->swallowed_object == focused))
1039                          {
1040                             efl_canvas_object_seat_focus_del(focused, seat);
1041                             break;
1042                          }
1043                     }
1044                }
1045           }
1046         else
1047           {
1048              EINA_LIST_FOREACH(pr->targets, l, pt)
1049                {
1050                   if (pt->id >= 0)
1051                     {
1052                        rp = ed->table_parts[pt->id % ed->table_parts_size];
1053                        if (rp &&
1054                            ((rp->type == EDJE_RP_TYPE_SWALLOW) &&
1055                             (rp->typedata.swallow)) &&
1056                            (rp->typedata.swallow->swallowed_object))
1057                          efl_canvas_object_seat_focus_add(
1058                             rp->typedata.swallow->swallowed_object, seat);
1059                     }
1060                }
1061           }
1062       }
1063       break;
1064 
1065       case EDJE_ACTION_TYPE_SOUND_SAMPLE:
1066         if (_edje_block_break(ed))
1067           goto break_prog;
1068         _edje_multisense_internal_sound_sample_play(ed, pr->sample_name, pr->speed, pr->channel);
1069         break;
1070 
1071       case EDJE_ACTION_TYPE_SOUND_TONE:
1072         if (_edje_block_break(ed))
1073           goto break_prog;
1074         _edje_multisense_internal_sound_tone_play(ed, pr->tone_name, pr->duration, pr->channel);
1075         break;
1076 
1077       case EDJE_ACTION_TYPE_VIBRATION_SAMPLE:
1078         if (_edje_block_break(ed))
1079           goto break_prog;
1080         _edje_multisense_internal_vibration_sample_play(ed, pr->vibration_name, pr->vibration_repeat);
1081         break;
1082 
1083       case EDJE_ACTION_TYPE_PARAM_COPY:
1084       {
1085          Edje_Real_Part *src_part, *dst_part;
1086 
1087          // _edje_emit(ed, "program,start", pr->name);
1088          if (_edje_block_break(ed)) goto break_prog;
1089 
1090          src_part = ed->table_parts[pr->param.src % ed->table_parts_size];
1091          dst_part = ed->table_parts[pr->param.dst % ed->table_parts_size];
1092          _edje_param_copy(ed, src_part, pr->state, dst_part, pr->state2);
1093 
1094          if (_edje_block_break(ed)) goto break_prog;
1095          // _edje_emit(ed, "program,stop", pr->name);
1096          if (_edje_block_break(ed)) goto break_prog;
1097       }
1098       break;
1099 
1100       case EDJE_ACTION_TYPE_PARAM_SET:
1101       {
1102          Edje_Real_Part *part;
1103 
1104          // _edje_emit(ed, "program,start", pr->name);
1105          if (_edje_block_break(ed)) goto break_prog;
1106 
1107          part = ed->table_parts[pr->param.dst % ed->table_parts_size];
1108          _edje_param_set(ed, part, pr->state, pr->state2);
1109 
1110          if (_edje_block_break(ed)) goto break_prog;
1111          // _edje_emit(ed, "program,stop", pr->name);
1112          if (_edje_block_break(ed)) goto break_prog;
1113       }
1114       break;
1115 
1116 #ifdef HAVE_EPHYSICS
1117       case EDJE_ACTION_TYPE_PHYSICS_IMPULSE:
1118         if (EPH_LOAD())
1119           {
1120              if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_central_impulse_apply)))
1121                goto break_prog;
1122           }
1123         break;
1124 
1125       case EDJE_ACTION_TYPE_PHYSICS_TORQUE_IMPULSE:
1126         if (EPH_LOAD())
1127           {
1128              if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_torque_impulse_apply)))
1129                goto break_prog;
1130           }
1131         break;
1132 
1133       case EDJE_ACTION_TYPE_PHYSICS_FORCE:
1134         if (EPH_LOAD())
1135           {
1136              if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_central_force_apply)))
1137                goto break_prog;
1138           }
1139         break;
1140 
1141       case EDJE_ACTION_TYPE_PHYSICS_TORQUE:
1142         if (EPH_LOAD())
1143           {
1144              if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_torque_apply)))
1145                goto break_prog;
1146           }
1147         break;
1148 
1149       case EDJE_ACTION_TYPE_PHYSICS_FORCES_CLEAR:
1150         if (EPH_LOAD())
1151           {
1152              if (_edje_block_break(ed))
1153                goto break_prog;
1154              EINA_LIST_FOREACH(pr->targets, l, pt)
1155                {
1156                   if (pt->id >= 0)
1157                     {
1158                        rp = ed->table_parts[pt->id % ed->table_parts_size];
1159                        if ((rp) && (rp->body))
1160                          EPH_CALL(ephysics_body_forces_clear)(rp->body);
1161                     }
1162                }
1163           }
1164         break;
1165 
1166       case EDJE_ACTION_TYPE_PHYSICS_VEL_SET:
1167         if (EPH_LOAD())
1168           {
1169              if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_linear_velocity_set)))
1170                goto break_prog;
1171           }
1172         break;
1173 
1174       case EDJE_ACTION_TYPE_PHYSICS_ANG_VEL_SET:
1175         if (EPH_LOAD())
1176           {
1177              if (!_edje_physics_action_set(ed, pr, EPH_CALL(ephysics_body_angular_velocity_set)))
1178                goto break_prog;
1179           }
1180         break;
1181 
1182       case EDJE_ACTION_TYPE_PHYSICS_STOP:
1183         if (EPH_LOAD())
1184           {
1185              if (_edje_block_break(ed))
1186                goto break_prog;
1187              EINA_LIST_FOREACH(pr->targets, l, pt)
1188                {
1189                   if (pt->id >= 0)
1190                     {
1191                        rp = ed->table_parts[pt->id % ed->table_parts_size];
1192                        if ((rp) && (rp->body))
1193                          EPH_CALL(ephysics_body_stop)(rp->body);
1194                     }
1195                }
1196           }
1197         break;
1198 
1199       case EDJE_ACTION_TYPE_PHYSICS_ROT_SET:
1200         if (EPH_LOAD())
1201           {
1202              if (_edje_block_break(ed))
1203                goto break_prog;
1204              EINA_LIST_FOREACH(pr->targets, l, pt)
1205                {
1206                   if (pt->id >= 0)
1207                     {
1208                        rp = ed->table_parts[pt->id % ed->table_parts_size];
1209                        if ((rp) && (rp->body))
1210                          {
1211                             EPhysics_Quaternion quat;
1212                             EPH_CALL(ephysics_quaternion_set)(&quat, pr->physics.x,
1213                                                               pr->physics.y, pr->physics.z,
1214                                                               pr->physics.w);
1215                             EPH_CALL(ephysics_quaternion_normalize)(&quat);
1216                             EPH_CALL(ephysics_body_rotation_set)(rp->body, &quat);
1217                          }
1218                     }
1219                }
1220           }
1221         break;
1222 
1223 #endif
1224 
1225 #ifdef BUILD_VG_LOADER_JSON
1226       case EDJE_ACTION_TYPE_VG_ANIM_STOP:
1227         if (_edje_block_break(ed))
1228           goto break_prog;
1229         EINA_LIST_FOREACH(pr->targets, l, pt)
1230           {
1231              if (pt->id >= 0)
1232                {
1233                   rp = ed->table_parts[pt->id % ed->table_parts_size];
1234                   if (rp)
1235                     _edje_part_vector_anim_stop(ed, rp);
1236                }
1237           }
1238         break;
1239 
1240       case EDJE_ACTION_TYPE_VG_ANIM_PAUSE:
1241         if (_edje_block_break(ed))
1242           goto break_prog;
1243         EINA_LIST_FOREACH(pr->targets, l, pt)
1244           {
1245              if (pt->id >= 0)
1246                {
1247                   rp = ed->table_parts[pt->id % ed->table_parts_size];
1248                   if (rp)
1249                     _edje_part_vector_anim_pause(ed, rp);
1250                }
1251           }
1252         break;
1253 
1254       case EDJE_ACTION_TYPE_VG_ANIM_RESUME:
1255         if (_edje_block_break(ed))
1256           goto break_prog;
1257         EINA_LIST_FOREACH(pr->targets, l, pt)
1258           {
1259              if (pt->id >= 0)
1260                {
1261                   rp = ed->table_parts[pt->id % ed->table_parts_size];
1262                   if (rp)
1263                     _edje_part_vector_anim_resume(ed, rp);
1264                }
1265           }
1266         break;
1267 
1268       case EDJE_ACTION_TYPE_VG_ANIM_LOOP:
1269       case EDJE_ACTION_TYPE_VG_ANIM_REWIND:
1270       case EDJE_ACTION_TYPE_VG_ANIM_PLAY:
1271         if (_edje_block_break(ed))
1272           goto break_prog;
1273         EINA_LIST_FOREACH(pr->targets, l, pt)
1274           {
1275              if (pt->id >= 0)
1276                {
1277                   rp = ed->table_parts[pt->id % ed->table_parts_size];
1278                   if (rp)
1279                     {
1280                        Eina_Bool vector_anim_backward = EINA_FALSE;
1281                        Eina_Bool vector_anim_loop = EINA_FALSE;
1282 
1283                        if (pr->action == EDJE_ACTION_TYPE_VG_ANIM_REWIND)
1284                          vector_anim_backward = EINA_TRUE;
1285 
1286                        if (pr->action == EDJE_ACTION_TYPE_VG_ANIM_LOOP)
1287                          vector_anim_loop = EINA_TRUE;
1288 
1289                        _edje_part_vector_anim_play(ed, rp,
1290                                                    vector_anim_backward,
1291                                                    vector_anim_loop);
1292                     }
1293                }
1294           }
1295         break;
1296 #else
1297       case EDJE_ACTION_TYPE_VG_ANIM_STOP:
1298       case EDJE_ACTION_TYPE_VG_ANIM_PAUSE:
1299       case EDJE_ACTION_TYPE_VG_ANIM_RESUME:
1300       case EDJE_ACTION_TYPE_VG_ANIM_LOOP:
1301       case EDJE_ACTION_TYPE_VG_ANIM_REWIND:
1302       case EDJE_ACTION_TYPE_VG_ANIM_PLAY:
1303         ERR("Evas Vg Json (Lottie) Loader is not supported, Only Static Vector Image(SVG) is available!");
1304         break;
1305 #endif
1306 
1307       default:
1308         // _edje_emit(ed, "program,start", pr->name);
1309         // _edje_emit(ed, "program,stop", pr->name);
1310         break;
1311      }
1312    if (!((pr->action == EDJE_ACTION_TYPE_STATE_SET)
1313          /* hmm this fucks somethgin up. must look into it later */
1314          /* && (pr->tween.time > ZERO) && (!ed->no_anim))) */
1315          ))
1316      {
1317         EINA_LIST_FOREACH(pr->after, l, pa)
1318           {
1319              if (pa->id >= 0)
1320                {
1321                   pr2 = ed->collection->patterns.table_programs[pa->id % ed->collection->patterns.table_programs_size];
1322                   if (pr2) _edje_program_run(ed, pr2, 0, "", "", mdata);
1323                   if (_edje_block_break(ed)) goto break_prog;
1324                }
1325           }
1326      }
1327 break_prog:
1328    _edje_util_thaw(ed);
1329    _edje_unref(ed);
1330    recursions--;
1331    if (recursions == 0) recursion_limit = 0;
1332    _edje_unblock(ed);
1333 }
1334 
1335 void
_edje_emit(Edje * ed,const char * sig,const char * src)1336 _edje_emit(Edje *ed, const char *sig, const char *src)
1337 {
1338    _edje_emit_full(ed, sig, src, NULL, NULL);
1339 }
1340 
1341 void
_edje_seat_emit(Edje * ed,Efl_Input_Device * dev,const char * sig,const char * src)1342 _edje_seat_emit(Edje *ed, Efl_Input_Device *dev, const char *sig, const char *src)
1343 {
1344    Edje_Message_Signal_Data *mdata = NULL;
1345    Efl_Input_Device *seat = NULL;
1346    char buf[128];
1347    char *sname;
1348    const char *s;
1349 
1350    if (dev) seat = efl_input_device_seat_get(dev);
1351    if (seat)
1352      {
1353         sname = eina_strdup(efl_name_get(seat));
1354         mdata = _edje_signal_data_setup(NULL, NULL, sname, free);
1355      }
1356    /* keep sending old style signals for legacy compatibility, but provide */
1357    /* queryable seat data for callers that can make use of it.  */
1358    _edje_emit_full_data(ed, sig, src, mdata);
1359 
1360    /* send extra signal with ",$SEAT" suffix if the input device originating
1361     * the signal belongs to a seat */
1362    if (!seat) return;
1363 
1364    s = _edje_seat_name_get(ed, seat);
1365    if (!s) s = "";
1366    snprintf(buf, sizeof(buf), "seat,%s,%s", s, sig);
1367    _edje_emit_full_data(ed, buf, src, mdata);
1368    _edje_signal_data_free(mdata);
1369 }
1370 
1371 /* data should either be NULL or a malloc allocated data */
1372 void
_edje_emit_full(Edje * ed,const char * sig,const char * src,void * data,void (* free_func)(void *))1373 _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *))
1374 {
1375    Edje_Message_Signal_Data *mdata;
1376 
1377    mdata = _edje_signal_data_setup(data, free_func, NULL, NULL);
1378    _edje_emit_full_data(ed, sig, src, mdata);
1379    _edje_signal_data_free(mdata);
1380 }
1381 
1382 void
_edje_emit_full_data(Edje * ed,const char * sig,const char * src,Edje_Message_Signal_Data * mdata)1383 _edje_emit_full_data(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *mdata)
1384 {
1385    const char *sep;
1386    Eina_Bool broadcast;
1387 
1388    if (!ed->collection) return;
1389    if (ed->delete_me) return;
1390 
1391    _edje_signal_data_ref(mdata);
1392 
1393    sep = strchr(sig, EDJE_PART_PATH_SEPARATOR);
1394    /* If we are not sending the signal to a part of the child, the
1395     * signal if for ourself
1396     */
1397    if (sep)
1398      {
1399         const char *newsig;
1400         char *part;
1401         unsigned int length;
1402 
1403         /* the signal contains a colon, split the signal into "parts:signal" */
1404         length = sep - sig + 1;
1405         part = alloca(length);
1406         memcpy(part, sig, length - 1);
1407         part[length - 1] = '\0';
1408 
1409         newsig = sep + 1;
1410 
1411         if (_edje_emit_aliased(ed, part, newsig, src)) goto out;
1412 
1413         broadcast = _edje_emit_child(ed, NULL, part, newsig, src);
1414      }
1415    else
1416      broadcast = ed->collection->broadcast_signal;
1417 
1418    _edje_emit_send(ed, broadcast, sig, src, mdata);
1419 out:
1420    _edje_signal_data_free(mdata);
1421 }
1422 
1423 void
_edje_focused_part_set(Edje * ed,Eina_Stringshare * seat_name,Edje_Real_Part * rp)1424 _edje_focused_part_set(Edje *ed, Eina_Stringshare *seat_name, Edje_Real_Part *rp)
1425 {
1426    Edje_Seat *seat;
1427    Eina_List *l;
1428 
1429    //defaulting seat NULL to seat1
1430    if (!seat_name) seat_name = eina_stringshare_add("seat1");
1431 
1432    EINA_LIST_FOREACH(ed->seats, l, seat)
1433      {
1434         if (seat_name == seat->name)
1435           {
1436              seat->focused_part = rp;
1437              return;
1438           }
1439      }
1440 
1441    /* A part to be set for a seat not yet announced by Evas */
1442    seat = calloc(1, sizeof(Edje_Seat));
1443    EINA_SAFETY_ON_NULL_RETURN(seat);
1444 
1445    seat->name = eina_stringshare_ref(seat_name);
1446    seat->focused_part = rp;
1447    ed->seats = eina_list_append(ed->seats, seat);
1448 
1449    return;
1450 }
1451 
1452 Edje_Real_Part *
_edje_focused_part_get(Edje * ed,Eina_Stringshare * seat_name)1453 _edje_focused_part_get(Edje *ed, Eina_Stringshare *seat_name)
1454 {
1455    Edje_Seat *seat;
1456    Eina_List *l;
1457 
1458    //defaulting seat NULL to seat1
1459    if (!seat_name) seat_name = eina_stringshare_add("seat1");
1460 
1461    EINA_LIST_FOREACH(ed->seats, l, seat)
1462      {
1463         if (seat_name == seat->name)
1464           return seat->focused_part;
1465      }
1466 
1467    return NULL;
1468 }
1469 
1470 Eina_Stringshare*
_edje_seat_name_get(Edje * ed,Efl_Input_Device * device)1471 _edje_seat_name_get(Edje *ed, Efl_Input_Device *device)
1472 {
1473    Edje_Seat *seat;
1474    Eina_List *l;
1475 
1476    EINA_LIST_FOREACH(ed->seats, l, seat)
1477      {
1478         if (seat->device == device)
1479           return seat->name;
1480      }
1481 
1482    return NULL;
1483 }
1484 
1485 Efl_Input_Device *
_edje_seat_get(Edje * ed,Eina_Stringshare * name)1486 _edje_seat_get(Edje *ed, Eina_Stringshare *name)
1487 {
1488    Edje_Seat *seat;
1489    Eina_List *l;
1490 
1491    EINA_LIST_FOREACH(ed->seats, l, seat)
1492      {
1493         if (seat->name == name)
1494           return seat->device;
1495      }
1496 
1497    return NULL;
1498 }
1499 
1500 struct _Edje_Program_Data
1501 {
1502    Eina_List  *matches;
1503    Edje       *ed;
1504    const char *source;
1505 };
1506 
1507 static Eina_Bool
_edje_glob_callback(Edje_Program * pr,void * dt)1508 _edje_glob_callback(Edje_Program *pr, void *dt)
1509 {
1510    struct _Edje_Program_Data *data = dt;
1511    Edje_Real_Part *rp = NULL;
1512    Eina_Bool exec = EINA_TRUE;
1513 
1514    if (pr->filter.state)
1515      {
1516         rp = _edje_real_part_get(data->ed, pr->filter.part ? pr->filter.part : data->source);
1517         if (rp)
1518           exec = !strcmp(rp->chosen_description->state.name, pr->filter.state);
1519      }
1520 
1521    pr->exec = exec;
1522 
1523    data->matches = eina_list_append(data->matches, pr);
1524 
1525    return EINA_FALSE;
1526 }
1527 
1528 /* FIXME: what if we delete the evas object??? */
1529 void
_edje_emit_handle(Edje * ed,const char * sig,const char * src,Edje_Message_Signal_Data * sdata,Eina_Bool prop)1530 _edje_emit_handle(Edje *ed, const char *sig, const char *src,
1531                   Edje_Message_Signal_Data *sdata, Eina_Bool prop)
1532 {
1533    if (ed->delete_me) return;
1534    if (!sig) sig = "";
1535    if (!src) src = "";
1536    DBG("EDJE EMIT: (%p) signal: \"%s\" source: \"%s\"", ed, sig, src);
1537    _edje_block(ed);
1538    _edje_ref(ed);
1539    _edje_util_freeze(ed);
1540 
1541    if (ed->collection && ed->L)
1542      _edje_lua2_script_func_signal(ed, sig, src);
1543 
1544    if (ed->collection)
1545      {
1546 #ifdef EDJE_PROGRAM_CACHE
1547         Edje_Part_Collection *ec;
1548         char *tmps;
1549         int l1, l2;
1550 #endif
1551         int done;
1552 
1553 #ifdef EDJE_PROGRAM_CACHE
1554         ec = ed->collection;
1555         l1 = strlen(sig);
1556         l2 = strlen(src);
1557         tmps = alloca(l1 + l2 + 3); /* \0, \337, \0 */
1558         strcpy(tmps, sig);
1559         tmps[l1] = '\377';
1560         strcpy(&(tmps[l1 + 1]), src);
1561 #endif
1562         done = 0;
1563 
1564 #ifdef EDJE_PROGRAM_CACHE
1565         {
1566            Eina_List *matches;
1567            Eina_List *l;
1568            Edje_Program *pr;
1569 
1570            if (eina_hash_find(ec->prog_cache.no_matches, tmps))
1571              {
1572                 done = 1;
1573              }
1574            else if ((matches = eina_hash_find(ec->prog_cache.matches, tmps)))
1575              {
1576                 EINA_LIST_FOREACH(matches, l, pr)
1577                   {
1578                      Eina_Bool exec = EINA_TRUE;
1579 
1580                      if (pr->filter.state)
1581                        {
1582                           Edje_Real_Part *rp;
1583 
1584                           rp = _edje_real_part_get(ed, pr->filter.part ? pr->filter.part : src);
1585                           if (rp)
1586                             {
1587                                if (rp->program)
1588                                  exec = EINA_FALSE;
1589                                else
1590                                  exec = (rp->chosen_description->state.name != pr->filter.state) ?
1591                                    !strcmp(rp->chosen_description->state.name, pr->filter.state) : EINA_TRUE;
1592                             }
1593                        }
1594 
1595                      pr->exec = exec;
1596                   }
1597 
1598                 EINA_LIST_FOREACH(matches, l, pr)
1599                   if (pr->exec)
1600                     {
1601                        _edje_program_run(ed, pr, 0, sig, src, sdata);
1602                        if (_edje_block_break(ed))
1603                          {
1604                             goto break_prog;
1605                          }
1606                     }
1607 
1608                 done = 1;
1609              }
1610         }
1611 #endif
1612         if (!done)
1613           {
1614              struct _Edje_Program_Data data;
1615 
1616              data.ed = ed;
1617              data.source = src;
1618              data.matches = NULL;
1619 
1620              if (ed->collection->patterns.table_programs_size > 0)
1621                {
1622                   const Eina_Inarray *match;
1623 #ifdef EDJE_PROGRAM_CACHE
1624                   const Eina_List *l;
1625 #endif
1626                   Edje_Program *pr;
1627 
1628                   if (ed->collection->patterns.programs.u.programs.globing)
1629                     if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns,
1630                                                  ed->collection->patterns.programs.sources_patterns,
1631                                                  sig,
1632                                                  src,
1633                                                  ed->collection->patterns.programs.u.programs.globing,
1634                                                  _edje_glob_callback,
1635                                                  &data,
1636                                                  prop) == 0)
1637                       goto break_prog;
1638 
1639                   match = edje_match_signal_source_hash_get(sig, src,
1640                                                             ed->collection->patterns.programs.exact_match);
1641                   if (match)
1642                     {
1643                        Edje_Program **tpr;
1644 
1645                        EINA_INARRAY_FOREACH(match, tpr)
1646                        _edje_glob_callback(*tpr, &data);
1647                     }
1648 
1649 #ifdef EDJE_PROGRAM_CACHE
1650                   EINA_LIST_FOREACH(data.matches, l, pr)
1651 #else
1652                   EINA_LIST_FREE(data.matches, pr)
1653 #endif
1654                     {
1655                        if (pr->exec)
1656                          _edje_program_run(ed, pr, 0, sig, src, sdata);
1657 
1658                        if (_edje_block_break(ed))
1659                          {
1660                             eina_list_free(data.matches);
1661                             data.matches = NULL;
1662                             goto break_prog;
1663                          }
1664                     }
1665                }
1666 
1667 #ifdef EDJE_PROGRAM_CACHE
1668              if (tmps)
1669                {
1670                   if (data.matches == NULL)
1671                     {
1672                        if (!ec->prog_cache.no_matches)
1673                          ec->prog_cache.no_matches = eina_hash_string_superfast_new(NULL);
1674                        eina_hash_add(ec->prog_cache.no_matches, tmps, ed);
1675                     }
1676                   else
1677                     {
1678                        if (!ec->prog_cache.matches)
1679                          ec->prog_cache.matches = eina_hash_string_superfast_new(NULL);
1680                        eina_hash_add(ec->prog_cache.matches, tmps, data.matches);
1681                     }
1682                }
1683 #endif
1684           }
1685         _edje_emit_cb(ed, sig, src, sdata, prop);
1686         if (_edje_block_break(ed))
1687           {
1688              goto break_prog;
1689           }
1690      }
1691 break_prog:
1692    _edje_util_thaw(ed);
1693    _edje_unref(ed);
1694    _edje_unblock(ed);
1695 }
1696 
1697 /* Extra data for callbacks */
1698 static void *callback_extra_data = NULL;
1699 static void *callback_seat_data = NULL;
1700 
1701 EAPI void *
edje_object_signal_callback_extra_data_get(void)1702 edje_object_signal_callback_extra_data_get(void)
1703 {
1704    return callback_extra_data;
1705 }
1706 
1707 #ifdef EFL_BETA_API_SUPPORT
1708 EAPI void *
edje_object_signal_callback_seat_data_get(void)1709 edje_object_signal_callback_seat_data_get(void)
1710 {
1711    return callback_seat_data;
1712 }
1713 #endif
1714 
1715 /* FIXME: what if we delete the evas object??? */
1716 static void
_edje_emit_cb(Edje * ed,const char * sig,const char * src,Edje_Message_Signal_Data * data,Eina_Bool prop)1717 _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop)
1718 {
1719    const Edje_Signals_Sources_Patterns *ssp;
1720    Edje_Signal_Callback_Matches *m;
1721    const Eina_Inarray *match;
1722    int r = 1;
1723 
1724    if (ed->delete_me) return;
1725    if (!ed->callbacks || !ed->callbacks->matches) return;
1726 
1727    _edje_ref(ed);
1728    _edje_util_freeze(ed);
1729    _edje_block(ed);
1730 
1731    ed->walking_callbacks++;
1732 
1733    ssp = _edje_signal_callback_patterns_ref
1734      ((Edje_Signal_Callback_Group *)ed->callbacks);
1735    if (ssp)
1736      {
1737         m = (Edje_Signal_Callback_Matches *)ed->callbacks->matches;
1738         EINA_REFCOUNT_REF(m);
1739 
1740         callback_extra_data = (data) ? data->data : NULL;
1741         callback_seat_data = (data) ? data->seat_data : NULL;
1742 
1743         if (eina_inarray_count(&ssp->u.callbacks.globing))
1744           r = edje_match_callback_exec(ssp,
1745                                        m->matches,
1746                                        sig,
1747                                        src,
1748                                        ed,
1749                                        prop);
1750 
1751         if (!r) goto break_prog;
1752 
1753         match = edje_match_signal_source_hash_get(sig, src,
1754                                                   ssp->exact_match);
1755         if (match)
1756           {
1757              const Edje_Signal_Callback_Match *cb;
1758              unsigned int *i;
1759 
1760              EINA_INARRAY_FOREACH(match, i)
1761                {
1762                   if (ed->callbacks->flags[*i].delete_me) continue;
1763                   if ((prop) && (ed->callbacks->flags[*i].propagate)) continue;
1764 
1765                   cb = &m->matches[*i];
1766 
1767                   if (ed->callbacks->flags[*i].legacy)
1768                     cb->legacy((void *)ed->callbacks->custom_data[*i], ed->obj, sig, src);
1769                   else
1770                     cb->eo((void *)ed->callbacks->custom_data[*i], ed->obj, sig, src);
1771                   if (_edje_block_break(ed)) break;
1772                }
1773           }
1774 
1775 break_prog:
1776         _edje_signal_callback_matches_unref(m, ed->callbacks->flags, ed->callbacks->custom_data);
1777 
1778         _edje_signal_callback_patterns_unref(ssp);
1779      }
1780 
1781    ed->walking_callbacks--;
1782 
1783    if (ed->walking_callbacks == 0)
1784      _edje_signal_callback_reset(ed->callbacks->flags,
1785                                  ed->callbacks->matches->matches_count);
1786 
1787    _edje_unblock(ed);
1788    _edje_util_thaw(ed);
1789    _edje_unref(ed);
1790 }
1791 
1792 static const Edje_External_Param_Info *
_edje_external_param_info_get(const Evas_Object * obj,const char * name)1793 _edje_external_param_info_get(const Evas_Object *obj, const char *name)
1794 {
1795    const Edje_External_Type *type;
1796    const Edje_External_Param_Info *info;
1797 
1798    type = evas_object_data_get(obj, "Edje_External_Type");
1799    if (!type) return NULL;
1800    for (info = type->parameters_info; info->name; info++)
1801      if (!strcmp(info->name, name)) return info;
1802 
1803    return NULL;
1804 }
1805 
1806 static Edje_External_Param *
_edje_param_external_get(Edje_Real_Part * rp,const char * name,Edje_External_Param * param)1807 _edje_param_external_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param)
1808 {
1809    Evas_Object *swallowed_object;
1810    const Edje_External_Param_Info *info;
1811 
1812    if ((rp->type != EDJE_RP_TYPE_SWALLOW) ||
1813        (!rp->typedata.swallow)) return NULL;
1814    swallowed_object = rp->typedata.swallow->swallowed_object;
1815 
1816    info = _edje_external_param_info_get(swallowed_object, name);
1817    if (!info) return NULL;
1818 
1819    memset(param, 0, sizeof(*param));
1820    param->name = info->name;
1821    param->type = info->type;
1822    if (!_edje_external_param_get(NULL, rp, param)) return NULL;
1823    return param;
1824 }
1825 
1826 /* simulate external properties for native objects */
1827 static Edje_External_Param *
_edje_param_native_get(Edje * ed,Edje_Real_Part * rp,const char * name,Edje_External_Param * param,void ** free_ptr)1828 _edje_param_native_get(Edje *ed, Edje_Real_Part *rp, const char *name, Edje_External_Param *param, void **free_ptr)
1829 {
1830    *free_ptr = NULL;
1831    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1832        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1833      {
1834         if (!strcmp(name, "text"))
1835           {
1836              param->name = name;
1837              param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1838 
1839              _edje_recalc_do(ed);
1840              if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1841                param->s = _edje_entry_text_get(rp);
1842              else if ((rp->part->type == EDJE_PART_TYPE_TEXT) &&
1843                       ((rp->type == EDJE_RP_TYPE_TEXT) &&
1844                        (rp->typedata.text)))
1845                param->s = rp->typedata.text->text;
1846              else
1847                param->s = evas_object_textblock_text_markup_get(rp->object);
1848              return param;
1849           }
1850         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1851           {
1852              if (!strcmp(name, "text_unescaped"))
1853                {
1854                   param->name = name;
1855                   param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1856 
1857                   _edje_recalc_do(ed);
1858                   if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1859                     {
1860                        const char *tmp = _edje_entry_text_get(rp);
1861                        char *unescaped = _edje_text_unescape(tmp);
1862                        *free_ptr = unescaped;
1863                        param->s = unescaped;
1864                     }
1865                   else if ((rp->part->type == EDJE_PART_TYPE_TEXT) &&
1866                            ((rp->type == EDJE_RP_TYPE_TEXT) &&
1867                             (rp->typedata.text)))
1868                     param->s = rp->typedata.text->text;
1869                   else
1870                     {
1871                        const char *tmp;
1872                        char *unescaped;
1873 
1874                        tmp = evas_object_textblock_text_markup_get(rp->object);
1875                        unescaped = _edje_text_unescape(tmp);
1876                        *free_ptr = unescaped;
1877                        param->s = unescaped;
1878                     }
1879 
1880                   return param;
1881                }
1882 
1883              if (((rp->type == EDJE_RP_TYPE_TEXT) &&
1884                   (rp->typedata.text)) &&
1885                  ((rp->typedata.text->entry_data) &&
1886                   (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
1887                   (!strcmp(name, "select_allow"))))
1888                {
1889                   param->name = name;
1890                   param->type = EDJE_EXTERNAL_PARAM_TYPE_BOOL;
1891                   param->i = _edje_entry_select_allow_get(rp);
1892                   return param;
1893                }
1894           }
1895      }
1896 
1897    if ((rp->drag) && (rp->drag->down.count == 0))
1898      {
1899         if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1900           {
1901              const char *sub_name = name + sizeof("drag_") - 1;
1902              if (!strcmp(sub_name, "value_x"))
1903                {
1904                   double d;
1905 
1906                   _edje_recalc_do(ed);
1907                   d = TO_DOUBLE(rp->drag->val.x);
1908                   if (rp->part->dragable.x < 0) d = 1.0 - d;
1909                   param->name = name;
1910                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1911                   param->d = d;
1912                   return param;
1913                }
1914              if (!strcmp(sub_name, "value_y"))
1915                {
1916                   double d;
1917 
1918                   _edje_recalc_do(ed);
1919                   d = TO_DOUBLE(rp->drag->val.y);
1920                   if (rp->part->dragable.y < 0) d = 1.0 - d;
1921                   param->name = name;
1922                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1923                   param->d = d;
1924                   return param;
1925                }
1926 
1927              if (!strcmp(sub_name, "size_w"))
1928                {
1929                   _edje_recalc_do(ed);
1930                   param->name = name;
1931                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1932                   param->d = TO_DOUBLE(rp->drag->size.x);
1933                   return param;
1934                }
1935              if (!strcmp(sub_name, "size_h"))
1936                {
1937                   _edje_recalc_do(ed);
1938                   param->name = name;
1939                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1940                   param->d = TO_DOUBLE(rp->drag->size.y);
1941                   return param;
1942                }
1943 
1944              if (!strcmp(sub_name, "step_x"))
1945                {
1946                   _edje_recalc_do(ed);
1947                   param->name = name;
1948                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1949                   param->d = TO_DOUBLE(rp->drag->step.x);
1950                   return param;
1951                }
1952              if (!strcmp(sub_name, "step_y"))
1953                {
1954                   _edje_recalc_do(ed);
1955                   param->name = name;
1956                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1957                   param->d = TO_DOUBLE(rp->drag->step.y);
1958                   return param;
1959                }
1960 
1961              if (!strcmp(sub_name, "page_x"))
1962                {
1963                   _edje_recalc_do(ed);
1964                   param->name = name;
1965                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1966                   param->d = TO_DOUBLE(rp->drag->page.x);
1967                   return param;
1968                }
1969              if (!strcmp(sub_name, "page_y"))
1970                {
1971                   _edje_recalc_do(ed);
1972                   param->name = name;
1973                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1974                   param->d = TO_DOUBLE(rp->drag->page.y);
1975                   return param;
1976                }
1977 
1978              return NULL;
1979           }
1980      }
1981 
1982    return NULL;
1983 }
1984 
1985 static Eina_Bool
_edje_param_native_set(Edje * ed,Edje_Real_Part * rp,const char * name,const Edje_External_Param * param)1986 _edje_param_native_set(Edje *ed, Edje_Real_Part *rp, const char *name, const Edje_External_Param *param)
1987 {
1988    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1989        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1990      {
1991         if (!strcmp(name, "text"))
1992           {
1993              if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
1994                return EINA_FALSE;
1995 
1996              _edje_object_part_text_raw_set(ed, ed->obj, rp, rp->part->name, param->s);
1997              return EINA_TRUE;
1998           }
1999         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2000           {
2001              if (!strcmp(name, "text_unescaped"))
2002                {
2003                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
2004                     return EINA_FALSE;
2005 
2006                   if (rp->part->type == EDJE_PART_TYPE_TEXT)
2007                     _edje_object_part_text_raw_set(ed, ed->obj, rp, rp->part->name, param->s);
2008                   else
2009                     {
2010                        char *escaped = _edje_text_escape(param->s);
2011                        _edje_object_part_text_raw_set(ed, ed->obj, rp, rp->part->name, escaped);
2012                        free(escaped);
2013                     }
2014 
2015                   return EINA_TRUE;
2016                }
2017 
2018              if (((rp->type == EDJE_RP_TYPE_TEXT) &&
2019                   (rp->typedata.text)) &&
2020                  ((rp->typedata.text->entry_data) &&
2021                   (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
2022                   (!strcmp(name, "select_allow"))))
2023                {
2024                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_BOOL)
2025                     return EINA_FALSE;
2026                   _edje_entry_select_allow_set(rp, param->i);
2027                   return EINA_TRUE;
2028                }
2029           }
2030      }
2031 
2032    if ((rp->drag) && (rp->drag->down.count == 0))
2033      {
2034         if (!strncmp(name, "drag_", sizeof("drag_") - 1))
2035           {
2036              const char *sub_name = name + sizeof("drag_") - 1;
2037              if (!strcmp(sub_name, "value_x"))
2038                {
2039                   double d;
2040                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2041                     return EINA_FALSE;
2042                   d = param->d;
2043                   if (rp->part->dragable.confine_id != -1)
2044                     d = CLAMP(d, 0.0, 1.0);
2045                   if (rp->part->dragable.x < 0) d = 1.0 - d;
2046                   if (EQ(rp->drag->val.x, FROM_DOUBLE(d))) return EINA_TRUE;
2047                   rp->drag->val.x = FROM_DOUBLE(d);
2048 #ifdef EDJE_CALC_CACHE
2049                   rp->invalidate = EINA_TRUE;
2050 #endif
2051                   _edje_dragable_pos_set
2052                     (ed, rp, rp->drag->val.x, rp->drag->val.y);
2053                   _edje_emit(ed, "drag,set", rp->part->name);
2054                   return EINA_TRUE;
2055                }
2056              if (!strcmp(sub_name, "value_y"))
2057                {
2058                   double d;
2059                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2060                     return EINA_FALSE;
2061                   d = param->d;
2062                   if (rp->part->dragable.confine_id != -1)
2063                     d = CLAMP(d, 0.0, 1.0);
2064                   if (rp->part->dragable.y < 0) d = 1.0 - d;
2065                   if (EQ(rp->drag->val.y, FROM_DOUBLE(d))) return EINA_TRUE;
2066                   rp->drag->val.y = FROM_DOUBLE(d);
2067 #ifdef EDJE_CALC_CACHE
2068                   rp->invalidate = EINA_TRUE;
2069 #endif
2070                   _edje_dragable_pos_set
2071                     (ed, rp, rp->drag->val.x, rp->drag->val.y);
2072                   _edje_emit(ed, "drag,set", rp->part->name);
2073                   return EINA_TRUE;
2074                }
2075 
2076              if (!strcmp(sub_name, "size_w"))
2077                {
2078                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2079                     return EINA_FALSE;
2080                   rp->drag->size.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2081                   ed->recalc_call = EINA_TRUE;
2082                   ed->dirty = EINA_TRUE;
2083 #ifdef EDJE_CALC_CACHE
2084                   rp->invalidate = EINA_TRUE;
2085 #endif
2086                   _edje_recalc(ed);
2087                   return EINA_TRUE;
2088                }
2089              if (!strcmp(sub_name, "size_h"))
2090                {
2091                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2092                     return EINA_FALSE;
2093                   rp->drag->size.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2094                   ed->recalc_call = EINA_TRUE;
2095                   ed->dirty = EINA_TRUE;
2096 #ifdef EDJE_CALC_CACHE
2097                   rp->invalidate = EINA_TRUE;
2098 #endif
2099                   _edje_recalc(ed);
2100                   return EINA_TRUE;
2101                }
2102 
2103              if (!strcmp(sub_name, "step_x"))
2104                {
2105                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2106                     return EINA_FALSE;
2107                   rp->drag->step.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2108 #ifdef EDJE_CALC_CACHE
2109                   rp->invalidate = EINA_TRUE;
2110 #endif
2111                   return EINA_TRUE;
2112                }
2113              if (!strcmp(sub_name, "step_y"))
2114                {
2115                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2116                     return EINA_FALSE;
2117                   rp->drag->step.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2118 #ifdef EDJE_CALC_CACHE
2119                   rp->invalidate = EINA_TRUE;
2120 #endif
2121                   return EINA_TRUE;
2122                }
2123 
2124              if (!strcmp(sub_name, "page_x"))
2125                {
2126                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2127                     return EINA_FALSE;
2128                   rp->drag->page.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2129 #ifdef EDJE_CALC_CACHE
2130                   rp->invalidate = EINA_TRUE;
2131 #endif
2132                   return EINA_TRUE;
2133                }
2134              if (!strcmp(sub_name, "page_y"))
2135                {
2136                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
2137                     return EINA_FALSE;
2138                   rp->drag->page.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
2139 #ifdef EDJE_CALC_CACHE
2140                   rp->invalidate = EINA_TRUE;
2141 #endif
2142                   return EINA_TRUE;
2143                }
2144 
2145              return EINA_FALSE;
2146           }
2147      }
2148 
2149    return EINA_FALSE;
2150 }
2151 
2152 static const Edje_External_Param_Info *
_edje_native_param_info_get(const Edje_Real_Part * rp,const char * name)2153 _edje_native_param_info_get(const Edje_Real_Part *rp, const char *name)
2154 {
2155    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
2156        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
2157      {
2158         if (!strcmp(name, "text"))
2159           {
2160              static const Edje_External_Param_Info pi =
2161                EDJE_EXTERNAL_PARAM_INFO_STRING("text");
2162              return &pi;
2163           }
2164         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2165           {
2166              if (!strcmp(name, "text_unescaped"))
2167                {
2168                   static const Edje_External_Param_Info pi =
2169                     EDJE_EXTERNAL_PARAM_INFO_STRING("text_unescaped");
2170                   return &pi;
2171                }
2172              if (!strcmp(name, "select_allow"))
2173                {
2174                   static const Edje_External_Param_Info pi =
2175                     EDJE_EXTERNAL_PARAM_INFO_BOOL("text_unescaped");
2176                   return &pi;
2177                }
2178           }
2179      }
2180 
2181    if ((rp->drag) && (rp->drag->down.count == 0))
2182      {
2183         if (!strncmp(name, "drag_", sizeof("drag_") - 1))
2184           {
2185              name += sizeof("drag_") - 1;
2186              if (!strcmp(name, "value_x"))
2187                {
2188                   static const Edje_External_Param_Info pi =
2189                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_x");
2190                   return &pi;
2191                }
2192              if (!strcmp(name, "value_y"))
2193                {
2194                   static const Edje_External_Param_Info pi =
2195                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_y");
2196                   return &pi;
2197                }
2198              if (!strcmp(name, "size_w"))
2199                {
2200                   static const Edje_External_Param_Info pi =
2201                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_w");
2202                   return &pi;
2203                }
2204              if (!strcmp(name, "size_h"))
2205                {
2206                   static const Edje_External_Param_Info pi =
2207                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_h");
2208                   return &pi;
2209                }
2210              if (!strcmp(name, "step_x"))
2211                {
2212                   static const Edje_External_Param_Info pi =
2213                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_x");
2214                   return &pi;
2215                }
2216              if (!strcmp(name, "step_y"))
2217                {
2218                   static const Edje_External_Param_Info pi =
2219                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_y");
2220                   return &pi;
2221                }
2222              if (!strcmp(name, "page_x"))
2223                {
2224                   static const Edje_External_Param_Info pi =
2225                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_x");
2226                   return &pi;
2227                }
2228              if (!strcmp(name, "page_y"))
2229                {
2230                   static const Edje_External_Param_Info pi =
2231                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_y");
2232                   return &pi;
2233                }
2234 
2235              return NULL;
2236           }
2237      }
2238 
2239    return NULL;
2240 }
2241 
2242 static Edje_External_Param *
_edje_param_convert(Edje_External_Param * param,const Edje_External_Param_Info * dst_info)2243 _edje_param_convert(Edje_External_Param *param, const Edje_External_Param_Info *dst_info)
2244 {
2245    if (param->type == dst_info->type) return param;
2246 
2247    switch (dst_info->type)
2248      {
2249       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2250       case EDJE_EXTERNAL_PARAM_TYPE_INT:
2251       {
2252          int i;
2253          switch (param->type)
2254            {
2255             case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2256               i = (int)param->d;
2257               break;
2258 
2259             case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2260             case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2261               i = (param->s) ? atoi(param->s) : 0;
2262               break;
2263 
2264             case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2265             case EDJE_EXTERNAL_PARAM_TYPE_INT:
2266               i = param->i;
2267               break;
2268 
2269             default:
2270               return NULL;
2271            }
2272          if (dst_info->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
2273            i = !!i;
2274          param->type = dst_info->type;
2275          param->i = i;
2276          return param;
2277       }
2278 
2279       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2280       {
2281          double d;
2282          switch (param->type)
2283            {
2284             case EDJE_EXTERNAL_PARAM_TYPE_INT:
2285               d = (double)param->i;
2286               break;
2287 
2288             case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2289             case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2290               d = (param->s) ? atof(param->s) : 0.0;
2291               break;
2292 
2293             case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2294               d = (double)param->i;
2295               break;
2296 
2297             default:
2298               return NULL;
2299            }
2300          param->type = dst_info->type;
2301          param->d = d;
2302          return param;
2303       }
2304 
2305       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2306       {
2307          static char s[64];
2308          switch (param->type)
2309            {
2310             case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2311             case EDJE_EXTERNAL_PARAM_TYPE_INT:
2312               if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
2313               break;
2314 
2315             case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2316               if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
2317               break;
2318 
2319             case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2320               param->type = dst_info->type;
2321               return param;
2322 
2323             default:
2324               return NULL;
2325            }
2326          param->type = dst_info->type;
2327          param->s = s;
2328          return param;
2329       }
2330 
2331       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2332       {
2333          static char s[64];
2334          const char *val;
2335          switch (param->type)
2336            {
2337             case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2338             case EDJE_EXTERNAL_PARAM_TYPE_INT:
2339               if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
2340               val = s;
2341               break;
2342 
2343             case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2344               if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
2345               val = s;
2346               break;
2347 
2348             case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2349               val = param->s;
2350               break;
2351 
2352             default:
2353               return NULL;
2354            }
2355 
2356          param->type = dst_info->type;
2357          if (param->s != val) param->s = val;
2358          return param;
2359       }
2360 
2361       default: return NULL;
2362      }
2363 }
2364 
2365 static Eina_Bool
_edje_param_validate(const Edje_External_Param * param,const Edje_External_Param_Info * info)2366 _edje_param_validate(const Edje_External_Param *param, const Edje_External_Param_Info *info)
2367 {
2368    switch (info->type)
2369      {
2370       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
2371         return (param->i == 0) || (param->i == 1);
2372 
2373       case EDJE_EXTERNAL_PARAM_TYPE_INT:
2374         if ((info->info.i.min != EDJE_EXTERNAL_INT_UNSET) &&
2375             (info->info.i.min > param->i))
2376           return EINA_FALSE;
2377 
2378         if ((info->info.i.max != EDJE_EXTERNAL_INT_UNSET) &&
2379             (info->info.i.max < param->i))
2380           return EINA_FALSE;
2381 
2382         return EINA_TRUE;
2383 
2384       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
2385         if (!EINA_DBL_EQ(info->info.d.min, EDJE_EXTERNAL_DOUBLE_UNSET) &&
2386             (info->info.d.min > param->d))
2387           return EINA_FALSE;
2388 
2389         if (!EINA_DBL_EQ(info->info.d.max, EDJE_EXTERNAL_DOUBLE_UNSET) &&
2390             (info->info.d.max < param->d))
2391           return EINA_FALSE;
2392 
2393         return EINA_TRUE;
2394 
2395       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
2396         if (!param->s) return EINA_FALSE;
2397         if (info->info.s.accept_fmt)
2398           INF("string 'accept_fmt' validation not implemented.");
2399         if (info->info.s.deny_fmt)
2400           INF("string 'deny_fmt' validation not implemented.");
2401         return EINA_TRUE;
2402 
2403       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
2404       {
2405          const char **itr = info->info.c.choices;
2406          if (!itr) return EINA_FALSE;
2407          for (; *itr; itr++)
2408            if (!strcmp(*itr, param->s))
2409              return EINA_TRUE;
2410          return EINA_FALSE;
2411       }
2412 
2413       default: return EINA_FALSE;
2414      }
2415 }
2416 
2417 static void
_edje_param_copy(Edje * ed,Edje_Real_Part * src_part,const char * src_param,Edje_Real_Part * dst_part,const char * dst_param)2418 _edje_param_copy(Edje *ed, Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param)
2419 {
2420    Edje_External_Param val;
2421    const Edje_External_Param_Info *dst_info;
2422    void *free_ptr = NULL;
2423 
2424    if ((!src_part) || (!src_param) || (!dst_part) || (!dst_param))
2425      return;
2426 
2427    if ((dst_part->part->type == EDJE_PART_TYPE_EXTERNAL) &&
2428        (dst_part->type == EDJE_RP_TYPE_SWALLOW) &&
2429        (dst_part->typedata.swallow))
2430      dst_info = _edje_external_param_info_get
2431          (dst_part->typedata.swallow->swallowed_object, dst_param);
2432    else
2433      dst_info = _edje_native_param_info_get(dst_part, dst_param);
2434 
2435    if (!dst_info)
2436      {
2437         ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
2438             dst_param, dst_part->part->name);
2439         return;
2440      }
2441 
2442    if (src_part->part->type == EDJE_PART_TYPE_EXTERNAL)
2443      {
2444         if (!_edje_param_external_get
2445               (src_part, src_param, &val))
2446           {
2447              ERR("cannot get parameter '%s' of part '%s'",
2448                  src_param, src_part->part->name);
2449              return;
2450           }
2451      }
2452    else
2453      {
2454         if (!_edje_param_native_get(ed, src_part, src_param, &val, &free_ptr))
2455           {
2456              ERR("cannot get parameter '%s' of part '%s'",
2457                  src_param, src_part->part->name);
2458              return;
2459           }
2460      }
2461 
2462    if (!_edje_param_convert(&val, dst_info))
2463      {
2464         ERR("cannot convert parameter type %s to requested type %s",
2465             edje_external_param_type_str(val.type),
2466             edje_external_param_type_str(dst_info->type));
2467         goto end;
2468      }
2469 
2470    if (!_edje_param_validate(&val, dst_info))
2471      {
2472         ERR("incorrect parameter value failed validation for type %s",
2473             edje_external_param_type_str(dst_info->type));
2474         goto end;
2475      }
2476 
2477    if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
2478      {
2479         val.name = dst_param;
2480         if (!_edje_external_param_set(NULL, dst_part, &val))
2481           {
2482              ERR("failed to set parameter '%s' (%s) of part '%s'",
2483                  dst_param, edje_external_param_type_str(dst_info->type),
2484                  dst_part->part->name);
2485              goto end;
2486           }
2487      }
2488    else
2489      {
2490         if (!_edje_param_native_set(ed, dst_part, dst_param, &val))
2491           {
2492              ERR("failed to set parameter '%s' (%s) of part '%s'",
2493                  dst_param, edje_external_param_type_str(dst_info->type),
2494                  dst_part->part->name);
2495              goto end;
2496           }
2497      }
2498 
2499 end:
2500    free(free_ptr);
2501 }
2502 
2503 static void
_edje_param_set(Edje * ed,Edje_Real_Part * part,const char * param,const char * value)2504 _edje_param_set(Edje *ed, Edje_Real_Part *part, const char *param, const char *value)
2505 {
2506    Edje_External_Param val;
2507    const Edje_External_Param_Info *info;
2508 
2509    if ((!part) || (!param) || (!value))
2510      return;
2511 
2512    if ((part->part->type == EDJE_PART_TYPE_EXTERNAL) &&
2513        (part->type == EDJE_RP_TYPE_SWALLOW) &&
2514        (part->typedata.swallow))
2515      info = _edje_external_param_info_get(part->typedata.swallow->swallowed_object, param);
2516    else
2517      info = _edje_native_param_info_get(part, param);
2518 
2519    if (!info)
2520      {
2521         ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
2522             param, part->part->name);
2523         return;
2524      }
2525 
2526    val.name = "(temp)";
2527    val.type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
2528    val.s = value;
2529 
2530    if (!_edje_param_convert(&val, info))
2531      {
2532         ERR("cannot convert parameter type STRING to requested type %s",
2533             edje_external_param_type_str(info->type));
2534         return;
2535      }
2536 
2537    if (!_edje_param_validate(&val, info))
2538      {
2539         ERR("incorrect parameter value failed validation for type %s",
2540             edje_external_param_type_str(info->type));
2541         return;
2542      }
2543 
2544    if (part->part->type == EDJE_PART_TYPE_EXTERNAL)
2545      {
2546         val.name = param;
2547         if (!_edje_external_param_set(NULL, part, &val))
2548           {
2549              ERR("failed to set parameter '%s' (%s) of part '%s'",
2550                  param, edje_external_param_type_str(info->type),
2551                  part->part->name);
2552              return;
2553           }
2554      }
2555    else
2556      {
2557         if (!_edje_param_native_set(ed, part, param, &val))
2558           {
2559              ERR("failed to set parameter '%s' (%s) of part '%s'",
2560                  param, edje_external_param_type_str(info->type),
2561                  part->part->name);
2562              return;
2563           }
2564      }
2565 }
2566 
2567