Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / lib / edje_program.c
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_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param);
5 static void _edje_param_set(Edje_Real_Part *part, const char *param, const char *value);
6
7 int             _edje_anim_count = 0;
8 Ecore_Animator *_edje_timer = NULL;
9 Eina_List      *_edje_animators = NULL;
10
11
12 /*============================================================================*
13  *                                   API                                      *
14  *============================================================================*/
15
16 EAPI void
17 edje_frametime_set(double t)
18 {
19    ecore_animator_frametime_set(t);
20 }
21
22 EAPI double
23 edje_frametime_get(void)
24 {
25    return ecore_animator_frametime_get();
26 }
27
28 void
29 edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
30 {
31    Edje *ed;
32    Edje_Signal_Callback *escb;
33
34    ed = _edje_fetch(obj);
35    if (!ed) return;
36    if (ed->delete_me) return;
37    escb = calloc(1, sizeof(Edje_Signal_Callback));
38    escb->propagate = EINA_TRUE;
39    escb->signal = eina_stringshare_add("*");
40    escb->source = eina_stringshare_add("*");
41    escb->func = func;
42    escb->data = data;
43    ed->callbacks = eina_list_append(ed->callbacks, escb);
44    if (ed->walking_callbacks)
45      {
46         escb->just_added = 1;
47         ed->just_added_callbacks = 1;
48      }
49    else
50      _edje_callbacks_patterns_clean(ed);
51 }
52
53 EAPI void
54 edje_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
55 {
56    Edje *ed;
57    Edje_Signal_Callback *escb;
58
59    if ((!emission) || (!source) || (!func)) return;
60    ed = _edje_fetch(obj);
61    if (!ed) return;
62    if (ed->delete_me) return;
63    escb = calloc(1, sizeof(Edje_Signal_Callback));
64    if (emission[0])
65      escb->signal = eina_stringshare_add(emission);
66    if (source[0])
67      escb->source = eina_stringshare_add(source);
68    escb->func = func;
69    escb->data = data;
70    ed->callbacks = eina_list_append(ed->callbacks, escb);
71    if (ed->walking_callbacks)
72      {
73         escb->just_added = 1;
74         ed->just_added_callbacks = 1;
75      }
76    else
77      _edje_callbacks_patterns_clean(ed);
78 }
79
80 EAPI void *
81 edje_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source))
82 {
83    Edje *ed;
84    Eina_List *l;
85    Edje_Signal_Callback *escb;
86
87    if ((!emission) || (!source) || (!func)) return NULL;
88    ed = _edje_fetch(obj);
89    if (!ed) return NULL;
90    if (ed->delete_me) return NULL;
91    EINA_LIST_FOREACH(ed->callbacks, l, escb)
92      {
93         if ((escb->func == func) &&
94             ((!escb->signal && !emission[0]) ||
95              (escb->signal && !strcmp(escb->signal, emission))) &&
96             ((!escb->source && !source[0]) ||
97              (escb->source && !strcmp(escb->source, source))))
98           {
99              void *data;
100
101              data = escb->data;
102              if (ed->walking_callbacks)
103                {
104                   escb->delete_me = 1;
105                   ed->delete_callbacks = 1;
106                }
107              else
108                {
109                   _edje_callbacks_patterns_clean(ed);
110
111                   ed->callbacks = eina_list_remove_list(ed->callbacks, l);
112                   if (escb->signal) eina_stringshare_del(escb->signal);
113                   if (escb->source) eina_stringshare_del(escb->source);
114                   free(escb);
115                }
116              return data;
117           }
118      }
119    return NULL;
120 }
121
122 EAPI void *
123 edje_object_signal_callback_del_full(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
124 {
125    Edje *ed;
126    Eina_List *l;
127    Edje_Signal_Callback *escb;
128
129    if ((!emission) || (!source) || (!func)) return NULL;
130    ed = _edje_fetch(obj);
131    if (!ed) return NULL;
132    if (ed->delete_me) return NULL;
133    EINA_LIST_FOREACH(ed->callbacks, l, escb)
134      {
135         if ((escb->func == func) && (escb->data == data) &&
136             ((!escb->signal && !emission[0]) ||
137              (escb->signal && !strcmp(escb->signal, emission))) &&
138             ((!escb->source && !source[0]) ||
139              (escb->source && !strcmp(escb->source, source))))
140           {
141              void *data2;
142
143              data2 = escb->data;
144              if (ed->walking_callbacks)
145                {
146                   escb->delete_me = 1;
147                   ed->delete_callbacks = 1;
148                }
149              else
150                {
151                   _edje_callbacks_patterns_clean(ed);
152
153                   ed->callbacks = eina_list_remove_list(ed->callbacks, l);
154                   if (escb->signal) eina_stringshare_del(escb->signal);
155                   if (escb->source) eina_stringshare_del(escb->source);
156                   free(escb);
157                }
158              return data2;
159           }
160      }
161    return NULL;
162 }
163
164 EAPI void
165 edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source)
166 {
167    Edje *ed;
168
169    if ((!emission) || (!source)) return;
170    ed = _edje_fetch(obj);
171    if (!ed) return;
172    if (ed->delete_me) return;
173    _edje_emit(ed, (char *)emission, (char *)source);
174 }
175
176 /* FIXDOC: Verify/Expand */
177 EAPI void
178 edje_object_play_set(Evas_Object *obj, Eina_Bool play)
179 {
180    Edje *ed;
181    double t;
182    Eina_List *l;
183    Edje_Running_Program *runp;
184    unsigned int i;
185
186    ed = _edje_fetch(obj);
187    if (!ed) return;
188    if (ed->delete_me) return;
189    if (play)
190      {
191         if (!ed->paused) return;
192         ed->paused = 0;
193         t = ecore_time_get() - ed->paused_at;
194         EINA_LIST_FOREACH(ed->actions, l, runp)
195           runp->start_time += t;
196      }
197    else
198      {
199         if (ed->paused) return;
200         ed->paused = EINA_TRUE;
201         ed->paused_at = ecore_time_get();
202      }
203
204    for (i = 0; i < ed->table_parts_size; i++)
205      {
206         Edje_Real_Part *rp;
207         rp = ed->table_parts[i];
208         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
209           edje_object_play_set(rp->swallowed_object, play);
210      }
211 }
212
213 EAPI Eina_Bool
214 edje_object_play_get(const Evas_Object *obj)
215 {
216    Edje *ed;
217
218    ed = _edje_fetch(obj);
219    if (!ed) return EINA_FALSE;
220    if (ed->delete_me) return EINA_FALSE;
221    if (ed->paused) return EINA_FALSE;
222    return EINA_TRUE;
223 }
224
225 /* FIXDOC: Verify/Expand */
226 EAPI void
227 edje_object_animation_set(Evas_Object *obj, Eina_Bool on)
228 {
229    Edje *ed;
230    Eina_List *l;
231    unsigned int i;
232
233    ed = _edje_fetch(obj);
234    if (!ed) return;
235    if (ed->delete_me) return;
236    _edje_block(ed);
237    ed->no_anim = !on;
238    _edje_freeze(ed);
239    if (!on)
240      {
241         Eina_List *newl = NULL;
242         const void *data;
243
244         EINA_LIST_FOREACH(ed->actions, l, data)
245           newl = eina_list_append(newl, data);
246         while (newl)
247           {
248              Edje_Running_Program *runp;
249
250              runp = eina_list_data_get(newl);
251              newl = eina_list_remove(newl, eina_list_data_get(newl));
252              _edje_program_run_iterate(runp, runp->start_time + TO_DOUBLE(runp->program->tween.time));
253              if (_edje_block_break(ed))
254                {
255                   eina_list_free(newl);
256                   goto break_prog;
257                }
258           }
259      }
260    else
261      {
262         _edje_emit(ed, "load", NULL);
263         if (evas_object_visible_get(obj))
264           {
265              evas_object_hide(obj);
266              evas_object_show(obj);
267           }
268      }
269    break_prog:
270
271    for (i = 0; i < ed->table_parts_size; i++)
272      {
273         Edje_Real_Part *rp;
274         rp = ed->table_parts[i];
275         if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
276           edje_object_animation_set(rp->swallowed_object, on);
277      }
278
279    _edje_thaw(ed);
280    _edje_unblock(ed);
281 }
282
283
284 EAPI Eina_Bool
285 edje_object_animation_get(const Evas_Object *obj)
286 {
287    Edje *ed;
288
289    ed = _edje_fetch(obj);
290    if (!ed) return EINA_FALSE;
291    if (ed->delete_me) return EINA_FALSE;
292    if (ed->no_anim) return EINA_FALSE;
293    return EINA_TRUE;
294 }
295
296 /* Private Routines */
297
298 Eina_Bool
299 _edje_program_run_iterate(Edje_Running_Program *runp, double tim)
300 {
301    FLOAT_T t, total;
302    Eina_List *l;
303    Edje *ed;
304    Edje_Program_Target *pt;
305    Edje_Real_Part *rp;
306
307    ed = runp->edje;
308    if (ed->delete_me) return EINA_FALSE;
309    _edje_block(ed);
310    _edje_ref(ed);
311    _edje_freeze(ed);
312    t = FROM_DOUBLE(tim - runp->start_time);
313    total = runp->program->tween.time;
314    t = DIV(t, total);
315    if (t > FROM_INT(1)) t = FROM_INT(1);
316    EINA_LIST_FOREACH(runp->program->targets, l, pt)
317      {
318         if (pt->id >= 0)
319           {
320              rp = ed->table_parts[pt->id % ed->table_parts_size];
321              if (rp) _edje_part_pos_set(ed, rp,
322                                         runp->program->tween.mode, t,
323                                         runp->program->tween.v1,
324                                         runp->program->tween.v2);
325           }
326      }
327    if (t >= FROM_INT(1))
328      {
329         Edje_Program_After *pa;
330
331         EINA_LIST_FOREACH(runp->program->targets, l, pt)
332           {
333              if (pt->id >= 0)
334                {
335                   rp = ed->table_parts[pt->id % ed->table_parts_size];
336                   if (rp)
337                     {
338                        _edje_part_description_apply(ed, rp,
339                                                     runp->program->state,
340                                                     runp->program->value,
341                                                     NULL,
342                                                     0.0);
343                        _edje_part_pos_set(ed, rp,
344                                           runp->program->tween.mode, ZERO,
345                                           runp->program->tween.v1,
346                                           runp->program->tween.v2);
347                        rp->program = NULL;
348                     }
349                }
350           }
351         _edje_recalc(ed);
352         runp->delete_me = 1;
353         if (!ed->walking_actions)
354           {
355              _edje_anim_count--;
356              ed->actions = eina_list_remove(ed->actions, runp);
357              if (!ed->actions)
358                _edje_animators = eina_list_remove(_edje_animators, ed);
359           }
360 //      _edje_emit(ed, "program,stop", runp->program->name);
361         if (_edje_block_break(ed))
362           {
363              if (!ed->walking_actions) free(runp);
364              goto break_prog;
365           }
366         EINA_LIST_FOREACH(runp->program->after, l, pa)
367           {
368              Edje_Program *pr;
369
370              if (pa->id >= 0)
371                {
372                   pr = ed->table_programs[pa->id % ed->table_programs_size];
373                   if (pr) _edje_program_run(ed, pr, 0, "", "");
374                   if (_edje_block_break(ed))
375                     {
376                        if (!ed->walking_actions) free(runp);
377                        goto break_prog;
378                     }
379                }
380           }
381         _edje_thaw(ed);
382         _edje_unref(ed);
383         if (!ed->walking_actions) free(runp);
384         _edje_unblock(ed);
385         return  EINA_FALSE;
386      }
387    break_prog:
388    _edje_recalc(ed);
389    _edje_thaw(ed);
390    _edje_unref(ed);
391    _edje_unblock(ed);
392    return EINA_TRUE;
393 }
394
395 void
396 _edje_program_end(Edje *ed, Edje_Running_Program *runp)
397 {
398    Eina_List *l;
399    Edje_Program_Target *pt;
400 //   const char *pname = NULL;
401    int free_runp = 0;
402
403    if (ed->delete_me) return;
404    _edje_ref(ed);
405    _edje_freeze(ed);
406    EINA_LIST_FOREACH(runp->program->targets, l, pt)
407      {
408         Edje_Real_Part *rp;
409
410         if (pt->id >= 0)
411           {
412              rp = ed->table_parts[pt->id % ed->table_parts_size];
413              if (rp)
414                {
415                   _edje_part_description_apply(ed, rp,
416                                                runp->program->state,
417                                                runp->program->value,
418                                                NULL,
419                                                0.0);
420                   _edje_part_pos_set(ed, rp,
421                                      runp->program->tween.mode, ZERO,
422                                      runp->program->tween.v1,
423                                      runp->program->tween.v2);
424                   rp->program = NULL;
425                }
426           }
427      }
428    _edje_recalc(ed);
429    runp->delete_me = 1;
430 //   pname = runp->program->name;
431    if (!ed->walking_actions)
432      {
433         _edje_anim_count--;
434         ed->actions = eina_list_remove(ed->actions, runp);
435         free_runp = 1;
436         if (!ed->actions)
437           {
438              _edje_animators = eina_list_remove(_edje_animators, ed);
439           }
440      }
441 //   _edje_emit(ed, "program,stop", pname);
442    _edje_thaw(ed);
443    _edje_unref(ed);
444    if (free_runp) free(runp);
445 }
446
447 void
448 _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc)
449 {
450    Eina_List *l;
451    Edje_Real_Part *rp;
452    Edje_Program_Target *pt;
453    Edje_Program *pr2;
454    Edje_Program_After *pa;
455    /* limit self-feeding loops in programs to 64 levels */
456    static int recursions = 0;
457    static int recursion_limit = 0;
458
459    if (ed->delete_me) return;
460    if ((pr->in.from > 0.0) && (pr->in.range >= 0.0) && (!force))
461      {
462         Edje_Pending_Program *pp;
463         double r = 0.0;
464
465         pp = calloc(1, sizeof(Edje_Pending_Program));
466         if (!pp) return;
467         if (pr->in.range > 0.0) r = ((double)rand() / RAND_MAX);
468         pp->timer = ecore_timer_add(pr->in.from + (pr->in.range * r),
469                                     _edje_pending_timer_cb, pp);
470         if (!pp->timer)
471           {
472              free(pp);
473              return;
474           }
475         pp->edje = ed;
476         pp->program = pr;
477         ed->pending_actions = eina_list_append(ed->pending_actions, pp);
478         return;
479      }
480    if ((recursions >= 64) || (recursion_limit))
481      {
482         ERR("Programs recursing up to recursion limit of %i in '%s' with '%s', '%s' from '%s', '%s'. Disabled.",
483             64, pr->name, ssig, ssrc, ed->path, ed->group);
484         recursion_limit = 1;
485         return;
486      }
487    recursions++;
488    _edje_block(ed);
489    _edje_ref(ed);
490    _edje_freeze(ed);
491    switch (pr->action)
492      {
493      case EDJE_ACTION_TYPE_STATE_SET:
494         if ((pr->tween.time > ZERO) && (!ed->no_anim))
495           {
496              Edje_Running_Program *runp;
497
498              runp = calloc(1, sizeof(Edje_Running_Program));
499              EINA_LIST_FOREACH(pr->targets, l, pt)
500                {
501                   if (pt->id >= 0)
502                     {
503                        rp = ed->table_parts[pt->id % ed->table_parts_size];
504                        if (rp)
505                          {
506                             if ((rp->object) && (pr->tween.mode & EDJE_TWEEN_MODE_OPT_FROM_CURRENT))
507                               {
508                                  Edje_Calc_Params *tmp;
509
510                                  tmp = calloc(1, sizeof(Edje_Calc_Params));
511                                  if (!tmp) goto low_mem_current;
512                                  _edje_part_recalc(ed, rp, FLAG_XY, tmp);
513
514                                  if (rp->current) free(rp->current);
515                                  rp->current = tmp;
516
517                                  rp->current->x -= ed->x;
518                                  rp->current->y -= ed->y;
519                                  rp->current->map.center.x -= ed->x;
520                                  rp->current->map.center.y -= ed->y;
521                                  rp->current->map.light.x -= ed->x;
522                                  rp->current->map.light.y -= ed->y;
523                                  rp->current->map.persp.x -= ed->x;
524                                  rp->current->map.persp.y -= ed->y;
525                               }
526                             else
527                               {
528                               low_mem_current:
529                                  if (rp->current) free(rp->current);
530                                  rp->current = NULL;
531                               }
532
533                             if (rp->program)
534                               _edje_program_end(ed, rp->program);
535                             _edje_part_description_apply(ed, rp,
536                                                          rp->param1.description->state.name,
537                                                          rp->param1.description->state.value,
538                                                          pr->state,
539                                                          pr->value);
540                             _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
541                                                pr->tween.v1,
542                                                pr->tween.v2);
543                             rp->program = runp;
544                          }
545                     }
546                }
547              // _edje_emit(ed, "program,start", pr->name);
548              if (_edje_block_break(ed))
549                {
550                   ed->actions = eina_list_append(ed->actions, runp);
551                   goto break_prog;
552                }
553              if (!ed->actions)
554                _edje_animators = eina_list_append(_edje_animators, ed);
555              ed->actions = eina_list_append(ed->actions, runp);
556              runp->start_time = ecore_loop_time_get();
557              runp->edje = ed;
558              runp->program = pr;
559              if (!_edje_timer)
560                _edje_timer = ecore_animator_add(_edje_timer_cb, NULL);
561              _edje_anim_count++;
562           }
563         else
564           {
565              EINA_LIST_FOREACH(pr->targets, l, pt)
566                {
567                   if (pt->id >= 0)
568                     {
569                        rp = ed->table_parts[pt->id % ed->table_parts_size];
570                        if (rp)
571                          {
572                             if (rp->program)
573                               _edje_program_end(ed, rp->program);
574                             _edje_part_description_apply(ed, rp,
575                                                          pr->state,
576                                                          pr->value,
577                                                          NULL,
578                                                          0.0);
579                             _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
580                                                pr->tween.v1,
581                                                pr->tween.v2);
582                          }
583                     }
584                }
585              // _edje_emit(ed, "program,start", pr->name);
586              if (_edje_block_break(ed)) goto break_prog;
587              // _edje_emit(ed, "program,stop", pr->name);
588              if (_edje_block_break(ed)) goto break_prog;
589
590              EINA_LIST_FOREACH(pr->after, l, pa)
591                {
592                   if (pa->id >= 0)
593                     {
594                        pr2 = ed->table_programs[pa->id % ed->table_programs_size];
595                        if (pr2) _edje_program_run(ed, pr2, 0, "", "");
596                        if (_edje_block_break(ed)) goto break_prog;
597                     }
598                }
599              _edje_recalc(ed);
600           }
601         break;
602      case EDJE_ACTION_TYPE_ACTION_STOP:
603         // _edje_emit(ed, "program,start", pr->name);
604         EINA_LIST_FOREACH(pr->targets, l, pt)
605           {
606              Eina_List *ll;
607              Edje_Running_Program *runp;
608              Edje_Pending_Program *pp;
609
610              for (ll = ed->actions; ll; )
611                {
612                   runp = ll->data;
613                   ll = ll->next;
614                   if (pt->id == runp->program->id)
615                     {
616                        _edje_program_end(ed, runp);
617 //                     goto done;
618                     }
619                }
620              for (ll = ed->pending_actions; ll; )
621               {
622                   pp = ll->data;
623                   ll = ll->next;
624                   if (pt->id == pp->program->id)
625                     {
626                        ed->pending_actions = eina_list_remove(ed->pending_actions, pp);
627                        ecore_timer_del(pp->timer);
628                        free(pp);
629 //                     goto done;
630                     }
631                }
632 //           done:
633 //              continue;
634           }
635         // _edje_emit(ed, "program,stop", pr->name);
636         if (_edje_block_break(ed)) goto break_prog;
637         break;
638      case EDJE_ACTION_TYPE_SIGNAL_EMIT:
639         // _edje_emit(ed, "program,start", pr->name);
640         if (_edje_block_break(ed)) goto break_prog;
641         _edje_emit(ed, pr->state, pr->state2);
642         if (_edje_block_break(ed)) goto break_prog;
643         // _edje_emit(ed, "program,stop", pr->name);
644         if (_edje_block_break(ed)) goto break_prog;
645         break;
646      case EDJE_ACTION_TYPE_DRAG_VAL_SET:
647         // _edje_emit(ed, "program,start", pr->name);
648         if (_edje_block_break(ed)) goto break_prog;
649         EINA_LIST_FOREACH(pr->targets, l, pt)
650           {
651              if (pt->id >= 0)
652                {
653                   rp = ed->table_parts[pt->id % ed->table_parts_size];
654                   if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
655                     {
656                        rp->drag->val.x = pr->value;
657                        rp->drag->val.y = pr->value2;
658                        if      (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
659                        else if (rp->drag->val.x > 1.0) rp->drag->val.x = 1.0;
660                        if      (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
661                        else if (rp->drag->val.y > 1.0) rp->drag->val.y = 1.0;
662                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
663                        _edje_emit(ed, "drag,set", rp->part->name);
664                        if (_edje_block_break(ed)) goto break_prog;
665                     }
666                }
667           }
668         // _edje_emit(ed, "program,stop", pr->name);
669         if (_edje_block_break(ed)) goto break_prog;
670         break;
671      case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
672         // _edje_emit(ed, "program,start", pr->name);
673         if (_edje_block_break(ed)) goto break_prog;
674         EINA_LIST_FOREACH(pr->targets, l, pt)
675           {
676              if (pt->id >= 0)
677                {
678                   rp = ed->table_parts[pt->id % ed->table_parts_size];
679                   if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
680                     {
681                        rp->drag->val.x += pr->value * rp->drag->step.x * rp->part->dragable.x;
682                        rp->drag->val.y += pr->value2 * rp->drag->step.y * rp->part->dragable.y;
683                        if      (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
684                        else if (rp->drag->val.x > 1.0) rp->drag->val.x = 1.0;
685                        if      (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
686                        else if (rp->drag->val.y > 1.0) rp->drag->val.y = 1.0;
687                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
688                        _edje_emit(ed, "drag,step", rp->part->name);
689                        if (_edje_block_break(ed)) goto break_prog;
690                     }
691                }
692           }
693         // _edje_emit(ed, "program,stop", pr->name);
694         if (_edje_block_break(ed)) goto break_prog;
695         break;
696      case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
697         // _edje_emit(ed, "program,start", pr->name);
698         if (_edje_block_break(ed)) goto break_prog;
699         EINA_LIST_FOREACH(pr->targets, l, pt)
700           {
701              if (pt->id >= 0)
702                {
703                   rp = ed->table_parts[pt->id % ed->table_parts_size];
704                   if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
705                     {
706                        rp->drag->val.x += pr->value * rp->drag->page.x * rp->part->dragable.x;
707                        rp->drag->val.y += pr->value2 * rp->drag->page.y * rp->part->dragable.y;
708                        if      (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
709                        else if (rp->drag->val.x > 1.0) rp->drag->val.x = 1.0;
710                        if      (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
711                        else if (rp->drag->val.y > 1.0) rp->drag->val.y = 1.0;
712                        _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
713                        _edje_emit(ed, "drag,page", rp->part->name);
714                        if (_edje_block_break(ed)) goto break_prog;
715                     }
716                }
717           }
718         // _edje_emit(ed, "program,stop", pr->name);
719         if (_edje_block_break(ed)) goto break_prog;
720         break;
721      case EDJE_ACTION_TYPE_SCRIPT:
722           {
723              char fname[128];
724
725              // _edje_emit(ed, "program,start", pr->name);
726              if (_edje_block_break(ed)) goto break_prog;
727              snprintf(fname, sizeof(fname), "_p%i", pr->id);
728              _edje_embryo_test_run(ed, fname, ssig, ssrc);
729              // _edje_emit(ed, "program,stop", pr->name);
730              if (_edje_block_break(ed)) goto break_prog;
731              _edje_recalc_do(ed);
732           }
733         break;
734      case EDJE_ACTION_TYPE_FOCUS_SET:
735         if (!pr->targets)
736            ed->focused_part = NULL;
737         else
738           {
739              EINA_LIST_FOREACH(pr->targets, l, pt)
740                {
741                   if (pt->id >= 0)
742                     {
743                        rp = ed->table_parts[pt->id % ed->table_parts_size];
744                        if (rp)
745                          {
746                             if (ed->focused_part != rp)
747                               {
748                                  if (ed->focused_part)
749                                    _edje_emit(ed, "focus,part,out", 
750                                               ed->focused_part->part->name);
751                                  ed->focused_part = rp;
752                                  _edje_emit(ed, "focus,part,in",
753                                             ed->focused_part->part->name);
754                               }
755                          }
756                     }
757                }
758           }
759         break;
760      case EDJE_ACTION_TYPE_FOCUS_OBJECT:
761         if (!pr->targets)
762           {
763              Evas_Object *focused;
764
765              focused = evas_focus_get(evas_object_evas_get(ed->obj));
766              if (focused)
767                {
768                   unsigned int i;
769
770                   /* Check if the current swallowed object is one of my child. */
771                   for (i = 0; i < ed->table_parts_size; ++i)
772                     {
773                        rp = ed->table_parts[i];
774                        if (rp && rp->swallowed_object == focused)
775                          {
776                             evas_object_focus_set(focused, EINA_FALSE);
777                             break;
778                          }
779                     }
780                }
781           }
782         else
783           {
784              EINA_LIST_FOREACH(pr->targets, l, pt)
785                {
786                   if (pt->id >= 0)
787                     {
788                        rp = ed->table_parts[pt->id % ed->table_parts_size];
789                        if (rp && rp->swallowed_object)
790                           evas_object_focus_set(rp->swallowed_object, EINA_TRUE);
791                     }
792                }
793           }
794         break;
795      case EDJE_ACTION_TYPE_SOUND_SAMPLE:
796         if (_edje_block_break(ed))
797           goto break_prog;
798         _edje_multisense_internal_sound_sample_play(ed, pr->sample_name, pr->speed);
799         break;
800      case EDJE_ACTION_TYPE_SOUND_TONE:
801         if (_edje_block_break(ed))
802           goto break_prog;
803         _edje_multisense_internal_sound_tone_play(ed, pr->tone_name, pr->duration);
804         break;
805      case EDJE_ACTION_TYPE_PARAM_COPY:
806           {
807              Edje_Real_Part *src_part, *dst_part;
808
809              // _edje_emit(ed, "program,start", pr->name);
810              if (_edje_block_break(ed)) goto break_prog;
811              
812              src_part = ed->table_parts[pr->param.src % ed->table_parts_size];
813              dst_part = ed->table_parts[pr->param.dst % ed->table_parts_size];
814              _edje_param_copy(src_part, pr->state, dst_part, pr->state2);
815              
816              if (_edje_block_break(ed)) goto break_prog;
817              // _edje_emit(ed, "program,stop", pr->name);
818              if (_edje_block_break(ed)) goto break_prog;
819           }
820         break;
821      case EDJE_ACTION_TYPE_PARAM_SET:
822           {
823              Edje_Real_Part *part;
824
825              // _edje_emit(ed, "program,start", pr->name);
826              if (_edje_block_break(ed)) goto break_prog;
827              
828              part = ed->table_parts[pr->param.dst % ed->table_parts_size];
829              _edje_param_set(part, pr->state, pr->state2);
830              
831              if (_edje_block_break(ed)) goto break_prog;
832              // _edje_emit(ed, "program,stop", pr->name);
833              if (_edje_block_break(ed)) goto break_prog;
834           }
835         break;
836      default:
837         // _edje_emit(ed, "program,start", pr->name);
838         // _edje_emit(ed, "program,stop", pr->name);
839         break;
840      }
841    if (!((pr->action == EDJE_ACTION_TYPE_STATE_SET)
842          /* hmm this fucks somethgin up. must look into it later */
843          /* && (pr->tween.time > ZERO) && (!ed->no_anim))) */
844          ))
845      {
846         EINA_LIST_FOREACH(pr->after, l, pa)
847           {
848              if (pa->id >= 0)
849                {
850                   pr2 = ed->table_programs[pa->id % ed->table_programs_size];
851                   if (pr2) _edje_program_run(ed, pr2, 0, "", "");
852                   if (_edje_block_break(ed)) goto break_prog;
853                }
854           }
855      }
856    break_prog:
857    _edje_thaw(ed);
858    _edje_unref(ed);
859    recursions--;
860    if (recursions == 0) recursion_limit = 0;
861    _edje_unblock(ed);
862 }
863
864 void
865 _edje_emit(Edje *ed, const char *sig, const char *src)
866 {
867    _edje_emit_full(ed, sig, src, NULL, NULL);
868 }
869
870 /* data should either be NULL or a malloc allocated data */
871 void
872 _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *))
873 {
874    Edje_Message_Signal emsg;
875    const char *sep;
876    Eina_Bool broadcast;
877
878    if (!ed->collection) return;
879    if (ed->delete_me) return;
880    broadcast = ed->collection->broadcast_signal;
881
882    sep = strchr(sig, EDJE_PART_PATH_SEPARATOR);
883
884    /* If we are not sending the signal to a part of the child, the
885     * signal if for ourself
886     */
887    if (sep)
888      {
889         Edje_Real_Part *rp = NULL;
890         const char *newsig;
891         Edje *ed2;
892         char *part;
893         char *idx;
894         size_t length;
895
896         /* the signal contains a colon, split the signal into "parts:signal" */
897         length = sep - sig + 1;
898         part = alloca(length);
899         memcpy(part, sig, length - 1);
900         part[length - 1] = '\0';
901
902         newsig = sep + 1;
903
904         /* lookup for alias */
905         if (ed->collection && ed->collection->alias)
906           {
907              char *alias;
908
909              alias = eina_hash_find(ed->collection->alias, part);
910              if (alias) {
911                 char *aliased;
912                 int alien;
913                 int nslen;
914
915                 alien = strlen(alias);
916                 nslen = strlen(newsig);
917                 length = alien + nslen + 2;
918
919                 aliased = alloca(length);
920                 memcpy(aliased, alias, alien);
921                 aliased[alien] = EDJE_PART_PATH_SEPARATOR;
922                 memcpy(aliased + alien + 1, newsig, nslen + 1);
923
924                 _edje_emit(ed, aliased, src);
925                 return;
926              }
927           }
928
929         /* search for the index if present and remove it from the part */
930         idx = strchr(part, EDJE_PART_PATH_SEPARATOR_INDEXL);
931         if (idx)
932           {
933              char *end;
934
935              end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
936              if (end && end != idx + 1)
937                {
938                   char *tmp;
939
940                   tmp = alloca(end - idx - 1);
941                   memcpy(tmp, idx + 1, end - idx - 1);
942                   tmp[end - idx - 1] = '\0';
943                   *idx = '\0';
944                   idx = tmp;
945                }
946              else
947                {
948                   idx = NULL;
949                }
950           }
951
952         /* search for the right part now */
953         rp = _edje_real_part_get(ed, part);
954         if (!rp) goto end;
955
956         switch (rp->part->type)
957           {
958            case EDJE_PART_TYPE_GROUP:
959               if (!rp->swallowed_object) goto end;
960               ed2 = _edje_fetch(rp->swallowed_object);
961               if (!ed2) goto end;
962
963               _edje_emit(ed2, newsig, src);
964               broadcast = EINA_FALSE;
965               break;
966
967            case EDJE_PART_TYPE_EXTERNAL:
968               if (!rp->swallowed_object) break ;
969
970               if (!idx)
971                 {
972                    _edje_external_signal_emit(rp->swallowed_object, newsig, src);
973                 }
974               else
975                 {
976                    Evas_Object *child;
977
978                    child = _edje_children_get(rp, idx);
979                    ed2 = _edje_fetch(child);
980                    if (!ed2) goto end;
981                    _edje_emit(ed2, newsig, src);
982                 }
983               broadcast = EINA_FALSE;
984               break ;
985
986            case EDJE_PART_TYPE_BOX:
987            case EDJE_PART_TYPE_TABLE:
988               if (idx)
989                 {
990                    Evas_Object *child;
991
992                    child = _edje_children_get(rp, idx);
993                    ed2 = _edje_fetch(child);
994                    if (!ed2) goto end;
995                    _edje_emit(ed2, newsig, src);
996                    broadcast = EINA_FALSE;
997                 }
998               break ;
999
1000            default:
1001 //              ERR("SPANK SPANK SPANK !!!\nYou should never be here !");
1002               break;
1003           }
1004      }
1005
1006  end:
1007    emsg.sig = sig;
1008    emsg.src = src;
1009    if (data)
1010      {
1011         emsg.data = calloc(1, sizeof(*(emsg.data)));
1012         emsg.data->ref = 1;
1013         emsg.data->data = data;
1014         emsg.data->free_func = free_func;
1015      }
1016    else
1017      {
1018         emsg.data = NULL;
1019      }
1020 /* new sends code */
1021    if (broadcast)
1022      edje_object_message_send(ed->obj, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1023    else
1024      _edje_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1025 /* old send code - use api now
1026    _edje_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1027    EINA_LIST_FOREACH(ed->subobjs, l, obj)
1028      {
1029         Edje *ed2;
1030
1031         ed2 = _edje_fetch(obj);
1032         if (!ed2) continue;
1033         if (ed2->delete_me) continue;
1034         _edje_message_send(ed2, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1035      }
1036  */
1037    if (emsg.data && (--(emsg.data->ref) == 0))
1038      {
1039         if (emsg.data->free_func)
1040           {
1041              emsg.data->free_func(emsg.data->data);
1042           }
1043         free(emsg.data);
1044      }
1045 }
1046
1047 struct _Edje_Program_Data
1048 {
1049   Eina_List     *matches;
1050   Edje          *ed;
1051   const char    *source;
1052 };
1053
1054 static Eina_Bool _edje_glob_callback(Edje_Program *pr, void *dt)
1055 {
1056    struct _Edje_Program_Data *data = dt;
1057    Edje_Real_Part *rp = NULL;
1058    Eina_Bool exec = EINA_TRUE;
1059
1060    if (pr->filter.state)
1061      {
1062         rp = _edje_real_part_get(data->ed, pr->filter.part ? pr->filter.part : data->source);
1063         if (rp)
1064           exec = (rp->chosen_description->state.name == pr->filter.state);
1065      }
1066
1067    pr->exec = exec;
1068
1069    data->matches = eina_list_append(data->matches, pr);
1070
1071    return EINA_FALSE;
1072 }
1073
1074 void
1075 _edje_callbacks_patterns_clean(Edje *ed)
1076 {
1077    _edje_signals_sources_patterns_clean(&ed->patterns.callbacks);
1078
1079    eina_rbtree_delete(ed->patterns.callbacks.exact_match,
1080                       EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
1081                       NULL);
1082    ed->patterns.callbacks.exact_match = NULL;
1083
1084    ed->patterns.callbacks.u.callbacks.globing = eina_list_free(ed->patterns.callbacks.u.callbacks.globing);
1085 }
1086
1087 static void
1088 _edje_callbacks_patterns_init(Edje *ed)
1089 {
1090    Edje_Signals_Sources_Patterns *ssp = &ed->patterns.callbacks;
1091
1092    if ((ssp->signals_patterns) || (ssp->sources_patterns) ||
1093        (ssp->u.callbacks.globing) || (ssp->exact_match))
1094      return;
1095
1096    ssp->u.callbacks.globing = edje_match_callback_hash_build(ed->callbacks,
1097                                                              &ssp->exact_match);
1098
1099    ssp->signals_patterns = edje_match_callback_signal_init(ssp->u.callbacks.globing);
1100    ssp->sources_patterns = edje_match_callback_source_init(ssp->u.callbacks.globing);
1101 }
1102
1103 /* FIXME: what if we delete the evas object??? */
1104 void
1105 _edje_emit_handle(Edje *ed, const char *sig, const char *src,
1106                   Edje_Message_Signal_Data *sdata, Eina_Bool prop)
1107 {
1108    if (ed->delete_me) return;
1109    if (!sig) sig = "";
1110    if (!src) src = "";
1111 //   printf("EDJE EMIT: (%p) signal: \"%s\" source: \"%s\"\n", ed, sig, src);
1112    _edje_block(ed);
1113    _edje_ref(ed);
1114    _edje_freeze(ed);
1115    
1116    if (ed->collection && ed->L)
1117      _edje_lua2_script_func_signal(ed, sig, src);
1118
1119    if (ed->collection)
1120      {
1121 #ifdef EDJE_PROGRAM_CACHE
1122         Edje_Part_Collection *ec;
1123         char *tmps;
1124         int l1, l2;
1125 #endif
1126         int done;
1127
1128 #ifdef EDJE_PROGRAM_CACHE
1129         ec = ed->collection;
1130         l1 = strlen(sig);
1131         l2 = strlen(src);
1132         tmps = alloca(l1 + l2 + 3); /* \0, \337, \0 */
1133         strcpy(tmps, sig);
1134         tmps[l1] = '\377';
1135         strcpy(&(tmps[l1 + 1]), src);
1136 #endif
1137         done = 0;
1138
1139 #ifdef EDJE_PROGRAM_CACHE
1140           {
1141              Eina_List *matches;
1142              Eina_List *l;
1143              Edje_Program *pr;
1144
1145              if (eina_hash_find(ec->prog_cache.no_matches, tmps))
1146                {
1147                   done = 1;
1148                }
1149              else if ((matches = eina_hash_find(ec->prog_cache.matches, tmps)))
1150                {
1151                   EINA_LIST_FOREACH(matches, l, pr)
1152                     {
1153                        Eina_Bool exec = EINA_TRUE;
1154
1155                        if (pr->filter.state)
1156                          {
1157                             Edje_Real_Part *rp;
1158
1159                             rp = _edje_real_part_get(ed, pr->filter.part ? pr->filter.part : src);
1160                             if (rp)
1161                               {
1162                                  if (rp->program)
1163                                    exec = EINA_FALSE;
1164                                  else
1165                                    exec = (rp->chosen_description->state.name == pr->filter.state);
1166                               }
1167                          }
1168
1169                        pr->exec = exec;
1170                     }
1171
1172                   EINA_LIST_FOREACH(matches, l, pr)
1173                     if (pr->exec)
1174                       {
1175                          _edje_program_run(ed, pr, 0, sig, src);
1176                          if (_edje_block_break(ed))
1177                            {
1178                               goto break_prog;
1179                            }
1180                       }
1181
1182                   done = 1;
1183                }
1184           }
1185 #endif
1186         if (!done)
1187           {
1188              struct _Edje_Program_Data  data;
1189
1190              data.ed = ed;
1191              data.source = src;
1192              data.matches = NULL;
1193
1194              if (ed->table_programs_size > 0)
1195                {
1196                   const Eina_List *match;
1197                   const Eina_List *l;
1198                   Edje_Program *pr;
1199
1200                   if (ed->patterns.programs.u.programs.globing)
1201                     if (edje_match_programs_exec(ed->patterns.programs.signals_patterns,
1202                                                  ed->patterns.programs.sources_patterns,
1203                                                  sig,
1204                                                  src,
1205                                                  ed->patterns.programs.u.programs.globing,
1206                                                  _edje_glob_callback,
1207                                                  &data,
1208                                                  prop) == 0)
1209                       goto break_prog;
1210
1211                   match = edje_match_signal_source_hash_get(sig, src,
1212                                                             ed->patterns.programs.exact_match);
1213                   EINA_LIST_FOREACH(match, l, pr)
1214                     _edje_glob_callback(pr, &data);
1215
1216 #ifdef EDJE_PROGRAM_CACHE
1217                   EINA_LIST_FOREACH(data.matches, l, pr)
1218 #else
1219                   EINA_LIST_FREE(data.matches, pr)
1220 #endif
1221                     {
1222                        if (pr->exec)
1223                          _edje_program_run(ed, pr, 0, sig, src);
1224
1225                        if (_edje_block_break(ed))
1226                          {
1227                             eina_list_free(data.matches);
1228                             data.matches = NULL;
1229                             goto break_prog;
1230                          }
1231                     }
1232                }
1233
1234 #ifdef EDJE_PROGRAM_CACHE
1235              if (tmps)
1236                {
1237                   if (data.matches == NULL)
1238                     {
1239                       if (!ec->prog_cache.no_matches)
1240                         ec->prog_cache.no_matches = eina_hash_string_superfast_new(NULL);
1241                       eina_hash_add(ec->prog_cache.no_matches, tmps, ed);
1242                     }
1243                   else
1244                     {
1245                       if (!ec->prog_cache.matches)
1246                         ec->prog_cache.matches = eina_hash_string_superfast_new(NULL);
1247                       eina_hash_add(ec->prog_cache.matches, tmps, data.matches);
1248                     }
1249                }
1250 #endif
1251           }
1252         _edje_emit_cb(ed, sig, src, sdata, prop);
1253         if (_edje_block_break(ed))
1254           {
1255              goto break_prog;
1256           }
1257      }
1258    break_prog:
1259    _edje_thaw(ed);
1260    _edje_unref(ed);
1261    _edje_unblock(ed);
1262 }
1263
1264 /* Extra data for callbacks */
1265 static void *callback_extra_data = NULL;
1266
1267 EAPI void *
1268 edje_object_signal_callback_extra_data_get(void)
1269 {
1270    return callback_extra_data;
1271 }
1272
1273 /* FIXME: what if we delete the evas object??? */
1274 static void
1275 _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop)
1276 {
1277    Eina_List            *l;
1278
1279    if (ed->delete_me) return;
1280    _edje_ref(ed);
1281    _edje_freeze(ed);
1282    _edje_block(ed);
1283
1284    if (ed->just_added_callbacks)
1285      _edje_callbacks_patterns_clean(ed);
1286
1287    ed->walking_callbacks++;
1288
1289    if (ed->callbacks)
1290      {
1291         Edje_Signal_Callback *escb;
1292         const Eina_List *match;
1293         const Eina_List *l2;
1294         int r = 1;
1295         callback_extra_data = (data) ? data->data : NULL;
1296
1297         _edje_callbacks_patterns_init(ed);
1298         if (ed->patterns.callbacks.u.callbacks.globing)
1299           r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
1300                                        ed->patterns.callbacks.sources_patterns,
1301                                        sig,
1302                                        src,
1303                                        ed->patterns.callbacks.u.callbacks.globing,
1304                                        ed,
1305                                        prop);
1306
1307         if (!r)
1308           goto break_prog;
1309
1310         match = edje_match_signal_source_hash_get(sig, src,
1311                                                   ed->patterns.callbacks.exact_match);
1312         EINA_LIST_FOREACH(match, l2, escb)
1313           {
1314              if ((prop) && (escb->propagate)) continue;
1315              if ((!escb->just_added) && (!escb->delete_me))
1316                {
1317                   escb->func(escb->data, ed->obj, sig, src);
1318                   if (_edje_block_break(ed))
1319                     break;
1320                }
1321           }
1322      }
1323    break_prog:
1324
1325    ed->walking_callbacks--;
1326    if (!ed->walking_callbacks &&
1327        ((ed->delete_callbacks) || (ed->just_added_callbacks)))
1328      {
1329         ed->delete_callbacks = 0;
1330         ed->just_added_callbacks = 0;
1331         l = ed->callbacks;
1332         while (l)
1333           {
1334              Edje_Signal_Callback *escb = l->data;
1335              Eina_List *next_l = l->next;
1336
1337              if (escb->just_added)
1338                escb->just_added = 0;
1339              if (escb->delete_me)
1340                {
1341                   ed->callbacks = eina_list_remove_list(ed->callbacks, l);
1342                   if (escb->signal) eina_stringshare_del(escb->signal);
1343                   if (escb->source) eina_stringshare_del(escb->source);
1344                   free(escb);
1345                }
1346              l = next_l;
1347           }
1348
1349         _edje_callbacks_patterns_clean(ed);
1350      }
1351    _edje_unblock(ed);
1352    _edje_thaw(ed);
1353    _edje_unref(ed);
1354 }
1355
1356 static const Edje_External_Param_Info *
1357 _edje_external_param_info_get(const Evas_Object *obj, const char *name)
1358 {
1359    const Edje_External_Type *type;
1360    const Edje_External_Param_Info *info;
1361
1362    type = evas_object_data_get(obj, "Edje_External_Type");
1363    if (!type) return NULL;
1364    for (info = type->parameters_info; info->name; info++)
1365      if (!strcmp(info->name, name)) return info;
1366
1367    return NULL;
1368 }
1369
1370 static Edje_External_Param *
1371 _edje_param_external_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param)
1372 {
1373    Evas_Object *swallowed_object = rp->swallowed_object;
1374    const Edje_External_Param_Info *info;
1375
1376    info = _edje_external_param_info_get(swallowed_object, name);
1377    if (!info) return NULL;
1378
1379    memset(param, 0, sizeof(*param));
1380    param->name = info->name;
1381    param->type = info->type;
1382    if (!_edje_external_param_get(NULL, rp, param)) return NULL;
1383    return param;
1384 }
1385
1386 /* simulate external properties for native objects */
1387 static Edje_External_Param *
1388 _edje_param_native_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param, void **free_ptr)
1389 {
1390    *free_ptr = NULL;
1391    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1392        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1393      {
1394         if (!strcmp(name, "text"))
1395           {
1396              param->name = name;
1397              param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1398
1399              _edje_recalc_do(rp->edje);
1400              if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1401                param->s = _edje_entry_text_get(rp);
1402              else if (rp->part->type == EDJE_PART_TYPE_TEXT)
1403                     param->s = rp->text.text;
1404              else
1405                param->s = evas_object_textblock_text_markup_get(rp->object);
1406              return param;
1407           }
1408         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1409           {
1410              if (!strcmp(name, "text_unescaped"))
1411                {
1412                   param->name = name;
1413                   param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1414
1415                   _edje_recalc_do(rp->edje);
1416                   if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1417                     {
1418                        const char *tmp = _edje_entry_text_get(rp);
1419                        char *unescaped = _edje_text_unescape(tmp);
1420                        *free_ptr = unescaped;
1421                        param->s = unescaped;
1422                     }
1423                   else if (rp->part->type == EDJE_PART_TYPE_TEXT)
1424                     param->s = rp->text.text;
1425                   else
1426                     {
1427                        const char *tmp;
1428                        char *unescaped;
1429
1430                        tmp = evas_object_textblock_text_markup_get(rp->object);
1431                        unescaped = _edje_text_unescape(tmp);
1432                        *free_ptr = unescaped;
1433                        param->s = unescaped;
1434                     }
1435
1436                   return param;
1437                }
1438
1439              if ((rp->entry_data) &&
1440                  (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
1441                  (!strcmp(name, "select_allow")))
1442                {
1443                   param->name = name;
1444                   param->type = EDJE_EXTERNAL_PARAM_TYPE_BOOL;
1445                   param->i = _edje_entry_select_allow_get(rp);
1446                   return param;
1447                }
1448           }
1449      }
1450
1451    if ((rp->drag) && (rp->drag->down.count == 0))
1452      {
1453         if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1454           {
1455              const char *sub_name = name + sizeof("drag_") - 1;
1456              if (!strcmp(sub_name, "value_x"))
1457                {
1458                   double d;
1459
1460                   _edje_recalc_do(rp->edje);
1461                   d = TO_DOUBLE(rp->drag->val.x);
1462                   if (rp->part->dragable.x < 0) d = 1.0 - d;
1463                   param->name = name;
1464                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1465                   param->d = d;
1466                   return param;
1467                }
1468              if (!strcmp(sub_name, "value_y"))
1469                {
1470                   double d;
1471
1472                   _edje_recalc_do(rp->edje);
1473                   d = TO_DOUBLE(rp->drag->val.y);
1474                   if (rp->part->dragable.y < 0) d = 1.0 - d;
1475                   param->name = name;
1476                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1477                   param->d = d;
1478                   return param;
1479                }
1480
1481              if (!strcmp(sub_name, "size_w"))
1482                {
1483                   _edje_recalc_do(rp->edje);
1484                   param->name = name;
1485                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1486                   param->d = TO_DOUBLE(rp->drag->size.x);
1487                   return param;
1488                }
1489              if (!strcmp(sub_name, "size_h"))
1490                {
1491                   _edje_recalc_do(rp->edje);
1492                   param->name = name;
1493                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1494                   param->d = TO_DOUBLE(rp->drag->size.y);
1495                   return param;
1496                }
1497
1498              if (!strcmp(sub_name, "step_x"))
1499                {
1500                   _edje_recalc_do(rp->edje);
1501                   param->name = name;
1502                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1503                   param->d = TO_DOUBLE(rp->drag->step.x);
1504                   return param;
1505                }
1506              if (!strcmp(sub_name, "step_y"))
1507                {
1508                   _edje_recalc_do(rp->edje);
1509                   param->name = name;
1510                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1511                   param->d = TO_DOUBLE(rp->drag->step.y);
1512                   return param;
1513                }
1514
1515              if (!strcmp(sub_name, "page_x"))
1516                {
1517                   _edje_recalc_do(rp->edje);
1518                   param->name = name;
1519                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1520                   param->d = TO_DOUBLE(rp->drag->page.x);
1521                   return param;
1522                }
1523              if (!strcmp(sub_name, "page_y"))
1524                {
1525                   _edje_recalc_do(rp->edje);
1526                   param->name = name;
1527                   param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1528                   param->d = TO_DOUBLE(rp->drag->page.y);
1529                   return param;
1530                }
1531
1532              return NULL;
1533           }
1534      }
1535
1536    return NULL;
1537 }
1538
1539 static Eina_Bool
1540 _edje_param_native_set(Edje_Real_Part *rp, const char *name, const Edje_External_Param *param)
1541 {
1542    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1543        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1544      {
1545         if (!strcmp(name, "text"))
1546           {
1547              if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
1548                return EINA_FALSE;
1549
1550              _edje_object_part_text_raw_set
1551                (rp->edje->obj, rp, rp->part->name, param->s);
1552              return EINA_TRUE;
1553           }
1554         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1555           {
1556              if (!strcmp(name, "text_unescaped"))
1557                {
1558                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
1559                     return EINA_FALSE;
1560
1561                   if (rp->part->type == EDJE_PART_TYPE_TEXT)
1562                     _edje_object_part_text_raw_set
1563                       (rp->edje->obj, rp, rp->part->name, param->s);
1564                   else
1565                     {
1566                        char *escaped = _edje_text_escape(param->s);
1567                       _edje_object_part_text_raw_set
1568                          (rp->edje->obj, rp, rp->part->name, escaped);
1569                        free(escaped);
1570                     }
1571
1572                   return EINA_TRUE;
1573                }
1574
1575              if ((rp->entry_data) &&
1576                  (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
1577                  (!strcmp(name, "select_allow")))
1578                {
1579                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_BOOL)
1580                     return EINA_FALSE;
1581                   _edje_entry_select_allow_set(rp, param->i);
1582                   return EINA_TRUE;
1583                }
1584           }
1585      }
1586
1587    if ((rp->drag) && (rp->drag->down.count == 0))
1588      {
1589         if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1590           {
1591              const char *sub_name = name + sizeof("drag_") - 1;
1592              if (!strcmp(sub_name, "value_x"))
1593                {
1594                   double d;
1595                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1596                     return EINA_FALSE;
1597                   d = param->d;
1598                   if (rp->part->dragable.confine_id != -1)
1599                     d = CLAMP(d, 0.0, 1.0);
1600                   if (rp->part->dragable.x < 0) d = 1.0 - d;
1601                   if (rp->drag->val.x == FROM_DOUBLE(d)) return EINA_TRUE;
1602                   rp->drag->val.x = FROM_DOUBLE(d);
1603 #ifdef EDJE_CALC_CACHE
1604                   rp->invalidate = 1;
1605 #endif
1606                   _edje_dragable_pos_set
1607                     (rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
1608                   _edje_emit(rp->edje, "drag,set", rp->part->name);
1609                   return EINA_TRUE;
1610                }
1611              if (!strcmp(sub_name, "value_y"))
1612                {
1613                   double d;
1614                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1615                     return EINA_FALSE;
1616                   d = param->d;
1617                   if (rp->part->dragable.confine_id != -1)
1618                     d = CLAMP(d, 0.0, 1.0);
1619                   if (rp->part->dragable.y < 0) d = 1.0 - d;
1620                   if (rp->drag->val.y == FROM_DOUBLE(d)) return EINA_TRUE;
1621                   rp->drag->val.y = FROM_DOUBLE(d);
1622 #ifdef EDJE_CALC_CACHE
1623                   rp->invalidate = 1;
1624 #endif
1625                   _edje_dragable_pos_set
1626                     (rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
1627                   _edje_emit(rp->edje, "drag,set", rp->part->name);
1628                   return EINA_TRUE;
1629                }
1630
1631              if (!strcmp(sub_name, "size_w"))
1632                {
1633                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1634                     return EINA_FALSE;
1635                   rp->drag->size.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1636                   rp->edje->recalc_call = 1;
1637                   rp->edje->dirty = 1;
1638 #ifdef EDJE_CALC_CACHE
1639                   rp->invalidate = 1;
1640 #endif
1641                   _edje_recalc(rp->edje);
1642                   return EINA_TRUE;
1643                }
1644              if (!strcmp(sub_name, "size_h"))
1645                {
1646                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1647                     return EINA_FALSE;
1648                   rp->drag->size.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1649                   rp->edje->recalc_call = 1;
1650                   rp->edje->dirty = 1;
1651 #ifdef EDJE_CALC_CACHE
1652                   rp->invalidate = 1;
1653 #endif
1654                   _edje_recalc(rp->edje);
1655                   return EINA_TRUE;
1656                }
1657
1658              if (!strcmp(sub_name, "step_x"))
1659                {
1660                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1661                     return EINA_FALSE;
1662                   rp->drag->step.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1663 #ifdef EDJE_CALC_CACHE
1664                   rp->invalidate = 1;
1665 #endif
1666                   return EINA_TRUE;
1667                }
1668              if (!strcmp(sub_name, "step_y"))
1669                {
1670                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1671                     return EINA_FALSE;
1672                   rp->drag->step.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1673 #ifdef EDJE_CALC_CACHE
1674                   rp->invalidate = 1;
1675 #endif
1676                   return EINA_TRUE;
1677                }
1678
1679              if (!strcmp(sub_name, "page_x"))
1680                {
1681                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1682                     return EINA_FALSE;
1683                   rp->drag->page.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1684 #ifdef EDJE_CALC_CACHE
1685                   rp->invalidate = 1;
1686 #endif
1687                   return EINA_TRUE;
1688                }
1689              if (!strcmp(sub_name, "page_y"))
1690                {
1691                   if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1692                     return EINA_FALSE;
1693                   rp->drag->page.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1694 #ifdef EDJE_CALC_CACHE
1695                   rp->invalidate = 1;
1696 #endif
1697                   return EINA_TRUE;
1698                }
1699
1700              return EINA_FALSE;
1701           }
1702      }
1703
1704    return EINA_FALSE;
1705 }
1706
1707 static const Edje_External_Param_Info *
1708 _edje_native_param_info_get(const Edje_Real_Part *rp, const char *name)
1709 {
1710    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1711        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1712      {
1713         if (!strcmp(name, "text"))
1714           {
1715              static const Edje_External_Param_Info pi =
1716                EDJE_EXTERNAL_PARAM_INFO_STRING("text");
1717              return &pi;
1718           }
1719         if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1720           {
1721              if (!strcmp(name, "text_unescaped"))
1722                {
1723                   static const Edje_External_Param_Info pi =
1724                     EDJE_EXTERNAL_PARAM_INFO_STRING("text_unescaped");
1725                   return &pi;
1726                }
1727              if (!strcmp(name, "select_allow"))
1728                {
1729                   static const Edje_External_Param_Info pi =
1730                     EDJE_EXTERNAL_PARAM_INFO_BOOL("text_unescaped");
1731                   return &pi;
1732                }
1733           }
1734      }
1735
1736    if ((rp->drag) && (rp->drag->down.count == 0))
1737      {
1738         if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1739           {
1740              name += sizeof("drag_") - 1;
1741              if (!strcmp(name, "value_x"))
1742                {
1743                   static const Edje_External_Param_Info pi =
1744                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_x");
1745                   return &pi;
1746                }
1747              if (!strcmp(name, "value_y"))
1748                {
1749                   static const Edje_External_Param_Info pi =
1750                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_y");
1751                   return &pi;
1752                }
1753              if (!strcmp(name, "size_w"))
1754                {
1755                   static const Edje_External_Param_Info pi =
1756                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_w");
1757                   return &pi;
1758                }
1759              if (!strcmp(name, "size_h"))
1760                {
1761                   static const Edje_External_Param_Info pi =
1762                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_h");
1763                   return &pi;
1764                }
1765              if (!strcmp(name, "step_x"))
1766                {
1767                   static const Edje_External_Param_Info pi =
1768                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_x");
1769                   return &pi;
1770                }
1771              if (!strcmp(name, "step_y"))
1772                {
1773                   static const Edje_External_Param_Info pi =
1774                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_y");
1775                   return &pi;
1776                }
1777              if (!strcmp(name, "page_x"))
1778                {
1779                   static const Edje_External_Param_Info pi =
1780                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_x");
1781                   return &pi;
1782                }
1783              if (!strcmp(name, "page_y"))
1784                {
1785                   static const Edje_External_Param_Info pi =
1786                     EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_y");
1787                   return &pi;
1788                }
1789
1790              return NULL;
1791           }
1792      }
1793
1794    return NULL;
1795 }
1796
1797 static Edje_External_Param *
1798 _edje_param_convert(Edje_External_Param *param, const Edje_External_Param_Info *dst_info)
1799 {
1800    if (param->type == dst_info->type) return param;
1801
1802    switch (dst_info->type)
1803      {
1804       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1805       case EDJE_EXTERNAL_PARAM_TYPE_INT:
1806         {
1807            int i;
1808            switch (param->type)
1809              {
1810               case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1811                  i = (int)param->d;
1812                  break;
1813               case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1814               case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1815                  i = (param->s) ? atoi(param->s) : 0;
1816                  break;
1817               case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1818               case EDJE_EXTERNAL_PARAM_TYPE_INT:
1819                  i = param->i;
1820                  break;
1821               default:
1822                  return NULL;
1823              }
1824            if (dst_info->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
1825              i = !!i;
1826            param->type = dst_info->type;
1827            param->i = i;
1828            return param;
1829         }
1830
1831       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1832         {
1833            double d;
1834            switch (param->type)
1835              {
1836               case EDJE_EXTERNAL_PARAM_TYPE_INT:
1837                  d = (double)param->i;
1838                  break;
1839               case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1840               case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1841                  d = (param->s) ? atof(param->s) : 0.0;
1842                  break;
1843               case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1844                  d = (double)param->i;
1845                  break;
1846               default:
1847                  return NULL;
1848              }
1849            param->type = dst_info->type;
1850            param->d = d;
1851            return param;
1852         }
1853
1854       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1855         {
1856            static char s[64];
1857            switch (param->type)
1858              {
1859               case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1860               case EDJE_EXTERNAL_PARAM_TYPE_INT:
1861                  if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
1862                  break;
1863               case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1864                  if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
1865                  break;
1866               case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1867                  param->type = dst_info->type;
1868                  return param;
1869               default:
1870                  return NULL;
1871              }
1872            param->type = dst_info->type;
1873            param->s = s;
1874            return param;
1875         }
1876
1877       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1878         {
1879            static char s[64];
1880            const char *val;
1881            switch (param->type)
1882              {
1883               case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1884               case EDJE_EXTERNAL_PARAM_TYPE_INT:
1885                  if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
1886                  val = s;
1887                  break;
1888               case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1889                  if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
1890                  val = s;
1891                  break;
1892               case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1893                  val = param->s;
1894                  break;
1895               default:
1896                  return NULL;
1897              }
1898
1899            param->type = dst_info->type;
1900            if (param->s != val) param->s = val;
1901            return param;
1902         }
1903
1904       default: return NULL;
1905      }
1906 }
1907
1908 static Eina_Bool
1909 _edje_param_validate(const Edje_External_Param *param, const Edje_External_Param_Info *info)
1910 {
1911    switch (info->type)
1912      {
1913       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1914          return ((param->i == 0) || (param->i == 1));
1915
1916       case EDJE_EXTERNAL_PARAM_TYPE_INT:
1917          if ((info->info.i.min != EDJE_EXTERNAL_INT_UNSET) &&
1918              (info->info.i.min > param->i))
1919            return EINA_FALSE;
1920
1921          if ((info->info.i.max != EDJE_EXTERNAL_INT_UNSET) &&
1922              (info->info.i.max < param->i))
1923            return EINA_FALSE;
1924
1925          return EINA_TRUE;
1926
1927       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1928          if ((info->info.d.min != EDJE_EXTERNAL_DOUBLE_UNSET) &&
1929              (info->info.d.min > param->d))
1930            return EINA_FALSE;
1931
1932          if ((info->info.d.max != EDJE_EXTERNAL_DOUBLE_UNSET) &&
1933              (info->info.d.max < param->d))
1934            return EINA_FALSE;
1935
1936          return EINA_TRUE;
1937
1938       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1939          if (!param->s) return EINA_FALSE;
1940          if (info->info.s.accept_fmt)
1941            INF("string 'accept_fmt' validation not implemented.");
1942          if (info->info.s.deny_fmt)
1943            INF("string 'deny_fmt' validation not implemented.");
1944          return EINA_TRUE;
1945
1946       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1947         {
1948            const char **itr = info->info.c.choices;
1949            if (!itr) return EINA_FALSE;
1950            for (; *itr; itr++)
1951              if (!strcmp(*itr, param->s))
1952                return EINA_TRUE;
1953            return EINA_FALSE;
1954         }
1955
1956       default: return EINA_FALSE;
1957      }
1958 }
1959
1960 static void
1961 _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param)
1962 {
1963    Edje_External_Param val;
1964    const Edje_External_Param_Info *dst_info;
1965    void *free_ptr = NULL;
1966
1967    if ((!src_part) || (!src_param) || (!dst_part) || (!dst_param))
1968      return;
1969
1970    if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
1971      dst_info = _edje_external_param_info_get
1972        (dst_part->swallowed_object, dst_param);
1973    else
1974      dst_info = _edje_native_param_info_get(dst_part, dst_param);
1975
1976    if (!dst_info)
1977      {
1978         ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
1979             dst_param, dst_part->part->name);
1980         return;
1981      }
1982
1983    if (src_part->part->type == EDJE_PART_TYPE_EXTERNAL)
1984      {
1985         if (!_edje_param_external_get
1986             (src_part, src_param, &val))
1987           {
1988              ERR("cannot get parameter '%s' of part '%s'",
1989                  src_param, src_part->part->name);
1990              return;
1991           }
1992      }
1993    else
1994      {
1995         if (!_edje_param_native_get(src_part, src_param, &val, &free_ptr))
1996           {
1997              ERR("cannot get parameter '%s' of part '%s'",
1998                  src_param, src_part->part->name);
1999              return;
2000           }
2001      }
2002
2003    if (!_edje_param_convert(&val, dst_info))
2004      {
2005         ERR("cannot convert parameter type %s to requested type %s",
2006             edje_external_param_type_str(val.type),
2007             edje_external_param_type_str(dst_info->type));
2008         goto end;
2009      }
2010
2011    if (!_edje_param_validate(&val, dst_info))
2012      {
2013         ERR("incorrect parameter value failed validation for type %s",
2014             edje_external_param_type_str(dst_info->type));
2015         goto end;
2016      }
2017
2018    if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
2019      {
2020         val.name = dst_param;
2021         if (!_edje_external_param_set(NULL, dst_part, &val))
2022           {
2023              ERR("failed to set parameter '%s' (%s) of part '%s'",
2024                  dst_param, edje_external_param_type_str(dst_info->type),
2025                  dst_part->part->name);
2026              goto end;
2027           }
2028      }
2029    else
2030      {
2031         if (!_edje_param_native_set(dst_part, dst_param, &val))
2032           {
2033              ERR("failed to set parameter '%s' (%s) of part '%s'",
2034                  dst_param, edje_external_param_type_str(dst_info->type),
2035                  dst_part->part->name);
2036              goto end;
2037           }
2038      }
2039
2040  end:
2041    free(free_ptr);
2042 }
2043
2044 static void
2045 _edje_param_set(Edje_Real_Part *part, const char *param, const char *value)
2046 {
2047    Edje_External_Param val;
2048    const Edje_External_Param_Info *info;
2049
2050    if ((!part) || (!param) || (!value))
2051      return;
2052
2053    if (part->part->type == EDJE_PART_TYPE_EXTERNAL)
2054      info = _edje_external_param_info_get(part->swallowed_object, param);
2055    else
2056      info = _edje_native_param_info_get(part, param);
2057
2058    if (!info)
2059      {
2060         ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
2061             param, part->part->name);
2062         return;
2063      }
2064
2065    val.name = "(temp)";
2066    val.type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
2067    val.s = value;
2068
2069    if (!_edje_param_convert(&val, info))
2070      {
2071         ERR("cannot convert parameter type STRING to requested type %s",
2072             edje_external_param_type_str(info->type));
2073         return;
2074      }
2075
2076    if (!_edje_param_validate(&val, info))
2077      {
2078         ERR("incorrect parameter value failed validation for type %s",
2079             edje_external_param_type_str(info->type));
2080         return;
2081      }
2082
2083    if (part->part->type == EDJE_PART_TYPE_EXTERNAL)
2084      {
2085         val.name = param;
2086         if (!_edje_external_param_set(NULL, part, &val))
2087           {
2088              ERR("failed to set parameter '%s' (%s) of part '%s'",
2089                  param, edje_external_param_type_str(info->type),
2090                  part->part->name);
2091              return;
2092           }
2093      }
2094    else
2095      {
2096         if (!_edje_param_native_set(part, param, &val))
2097           {
2098              ERR("failed to set parameter '%s' (%s) of part '%s'",
2099                  param, edje_external_param_type_str(info->type),
2100                  part->part->name);
2101              return;
2102           }
2103      }
2104 }