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