Imported Upstream version 1.7.2
[platform/upstream/edje.git] / src / lib / edje_message_queue.c
1 #include "edje_private.h"
2
3 static void _edje_object_message_popornot_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg, Eina_Bool prop);
4
5 static int _injob = 0;
6 static Ecore_Job *_job = NULL;
7 static Ecore_Timer *_job_loss_timer = NULL;
8
9 static Eina_List *msgq = NULL;
10 static Eina_List *tmp_msgq = NULL;
11 static int tmp_msgq_processing = 0;
12 static int tmp_msgq_restart = 0;
13
14 /*============================================================================*
15  *                                   API                                      *
16  *============================================================================*/
17
18 static void
19 _edje_object_message_popornot_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg, Eina_Bool prop)
20 {
21    Edje *ed;
22    Eina_List *l;
23    Evas_Object *o;
24
25    ed = _edje_fetch(obj);
26    if (!ed) return;
27    _edje_message_propornot_send(ed, EDJE_QUEUE_SCRIPT, type, id, msg, prop);
28    EINA_LIST_FOREACH(ed->subobjs, l, o)
29      {
30         _edje_object_message_popornot_send(o, type, id, msg, EINA_TRUE);
31      }
32 }
33
34 EAPI void
35 edje_object_message_send(Evas_Object *obj, Edje_Message_Type type, int id, void *msg)
36 {
37    _edje_object_message_popornot_send(obj, type, id, msg, EINA_FALSE);
38 }
39
40
41 EAPI void
42 edje_object_message_handler_set(Evas_Object *obj, Edje_Message_Handler_Cb func, void *data)
43 {
44    Edje *ed;
45
46    ed = _edje_fetch(obj);
47    if (!ed) return;
48    _edje_message_cb_set(ed, func, data);
49 }
50
51 EAPI void
52 edje_object_message_signal_process(Evas_Object *obj)
53 {
54    Eina_List *l, *ln, *tmpq = NULL;
55    Edje *ed;
56    Edje *lookup_ed;
57    Eina_List *lg;
58    Edje_Message *em;
59    Eina_List *groups = NULL;
60    int gotos = 0;
61
62    ed = _edje_fetch(obj);
63    if (!ed) return;
64
65    groups = ed->groups;
66
67    EINA_LIST_FOREACH_SAFE(msgq, l, ln, em)
68      {
69         EINA_LIST_FOREACH(groups, lg, lookup_ed)
70           if (em->edje == lookup_ed)
71             {
72                tmpq = eina_list_append(tmpq, em);
73                msgq = eina_list_remove_list(msgq, l);
74                break;
75             }
76      }
77    /* a temporary message queue */
78    if (tmp_msgq)
79      {
80         EINA_LIST_FREE(tmpq, em)
81           tmp_msgq = eina_list_append(tmp_msgq, em);
82      }
83    else
84      {
85         tmp_msgq = tmpq;
86         tmpq = NULL;
87      }
88
89    tmp_msgq_processing++;
90 again:
91    EINA_LIST_FOREACH_SAFE(tmp_msgq, l, ln, em)
92      {
93         EINA_LIST_FOREACH(groups, lg, lookup_ed)
94           if (em->edje == lookup_ed)
95             break;
96         if (em->edje != lookup_ed) continue;
97         tmp_msgq = eina_list_remove_list(tmp_msgq, l);
98         if (!lookup_ed->delete_me)
99           {
100              lookup_ed->processing_messages++;
101              _edje_message_process(em);
102              _edje_message_free(em);
103              lookup_ed->processing_messages--;
104           }
105         else
106            _edje_message_free(em);
107         if (lookup_ed->processing_messages == 0)
108           {
109              if (lookup_ed->delete_me) _edje_del(lookup_ed);
110           }
111         // if some child callback in _edje_message_process called
112         // edje_object_message_signal_process() or
113         // edje_message_signal_process() then those will mark the restart
114         // flag when they finish - it mabsicammyt means tmp_msgq and
115         // any item in it has potentially become invalid - so that means l
116         // and ln could be rogue pointers, so start again from the beginning
117         // and skip anything that is not this object and process only what is.
118         // to avoid self-feeding loops allow a max of 1024 loops.
119         if (tmp_msgq_restart)
120           {
121              tmp_msgq_restart = 0;
122              gotos++;
123              if (gotos < 1024) goto again;
124              else
125                {
126                   WRN("Edje is in a self-feeding message loop (> 1024 gotos needed in a row)");
127                   goto end;
128                }
129           }
130      }
131 end:
132    tmp_msgq_processing--;
133    if (tmp_msgq_processing == 0)
134       tmp_msgq_restart = 0;
135    else
136       tmp_msgq_restart = 1;
137 }
138
139 EAPI void
140 edje_message_signal_process(void)
141 {
142    _edje_message_queue_process();
143 }
144
145
146 static Eina_Bool
147 _edje_dummy_timer(void *data __UNUSED__)
148 {
149    return ECORE_CALLBACK_CANCEL;
150 }
151
152 static void
153 _edje_job(void *data __UNUSED__)
154 {
155    if (_job_loss_timer)
156      {
157         ecore_timer_del(_job_loss_timer);
158         _job_loss_timer = NULL;
159      }
160    _job = NULL;
161    _injob++;
162    _edje_message_queue_process();
163    _injob--;
164 }
165
166 static Eina_Bool
167 _edje_job_loss_timer(void *data __UNUSED__)
168 {
169    _job_loss_timer = NULL;
170    if (!_job)
171      {
172         _job = ecore_job_add(_edje_job, NULL);
173      }
174    return ECORE_CALLBACK_CANCEL;
175 }
176
177 void
178 _edje_message_init(void)
179 {
180 }
181
182 void
183 _edje_message_shutdown(void)
184 {
185    _edje_message_queue_clear();
186    if (_job_loss_timer)
187      {
188         ecore_timer_del(_job_loss_timer);
189         _job_loss_timer = NULL;
190      }
191    if (_job)
192      {
193         ecore_job_del(_job);
194         _job = NULL;
195      }
196 }
197
198 void
199 _edje_message_cb_set(Edje *ed, void (*func) (void *data, Evas_Object *obj, Edje_Message_Type type, int id, void *msg), void *data)
200 {
201    Eina_List *l;
202    Evas_Object *o;
203
204    ed->message.func = func;
205    ed->message.data = data;
206    EINA_LIST_FOREACH(ed->subobjs, l, o)
207      {
208         Edje *edj2 = _edje_fetch(o);
209         if (!edj2) continue;
210         _edje_message_cb_set(edj2, func, data);
211      }
212 }
213
214 Edje_Message *
215 _edje_message_new(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id)
216 {
217    Edje_Message *em;
218
219    em = calloc(1, sizeof(Edje_Message));
220    if (!em) return NULL;
221    em->edje = ed;
222    em->queue = queue;
223    em->type = type;
224    em->id = id;
225    em->edje->message.num++;
226    return em;
227 }
228
229 void
230 _edje_message_free(Edje_Message *em)
231 {
232    if (em->msg)
233      {
234         int i;
235
236         switch (em->type)
237           {
238            case EDJE_MESSAGE_STRING:
239                {
240                   Edje_Message_String *emsg;
241
242                   emsg = (Edje_Message_String *)em->msg;
243                   free(emsg->str);
244                   free(emsg);
245                }
246              break;
247            case EDJE_MESSAGE_INT:
248                {
249                   Edje_Message_Int *emsg;
250
251                   emsg = (Edje_Message_Int *)em->msg;
252                   free(emsg);
253                }
254              break;
255            case EDJE_MESSAGE_FLOAT:
256                {
257                   Edje_Message_Float *emsg;
258
259                   emsg = (Edje_Message_Float *)em->msg;
260                   free(emsg);
261                }
262              break;
263            case EDJE_MESSAGE_INT_SET:
264                {
265                   Edje_Message_Int_Set *emsg;
266
267                   emsg = (Edje_Message_Int_Set *)em->msg;
268                   free(emsg);
269                }
270              break;
271            case EDJE_MESSAGE_FLOAT_SET:
272                {
273                   Edje_Message_Float_Set *emsg;
274
275                   emsg = (Edje_Message_Float_Set *)em->msg;
276                   free(emsg);
277                }
278              break;
279            case EDJE_MESSAGE_STRING_FLOAT:
280                {
281                   Edje_Message_String_Float *emsg;
282
283                   emsg = (Edje_Message_String_Float *)em->msg;
284                   free(emsg->str);
285                   free(emsg);
286                }
287              break;
288            case EDJE_MESSAGE_STRING_INT:
289                {
290                   Edje_Message_String_Int *emsg;
291
292                   emsg = (Edje_Message_String_Int *)em->msg;
293                   free(emsg->str);
294                   free(emsg);
295                }
296              break;
297            case EDJE_MESSAGE_STRING_FLOAT_SET:
298                {
299                   Edje_Message_String_Float_Set *emsg;
300
301                   emsg = (Edje_Message_String_Float_Set *)em->msg;
302                   free(emsg->str);
303                   free(emsg);
304                }
305              break;
306            case EDJE_MESSAGE_STRING_INT_SET:
307                {
308                   Edje_Message_String_Int_Set *emsg;
309
310                   emsg = (Edje_Message_String_Int_Set *)em->msg;
311                   free(emsg->str);
312                   free(emsg);
313                }
314              break;
315            case EDJE_MESSAGE_SIGNAL:
316                {
317                   Edje_Message_Signal *emsg;
318
319                   emsg = (Edje_Message_Signal *)em->msg;
320                   if (emsg->sig) eina_stringshare_del(emsg->sig);
321                   if (emsg->src) eina_stringshare_del(emsg->src);
322                   if (emsg->data && (--(emsg->data->ref) == 0))
323                     {
324                        if (emsg->data->free_func)
325                          {
326                             emsg->data->free_func(emsg->data->data);
327                          }
328                        free(emsg->data);
329                     }
330                   free(emsg);
331                }
332              break;
333            case EDJE_MESSAGE_STRING_SET:
334                {
335                   Edje_Message_String_Set *emsg;
336
337                   emsg = (Edje_Message_String_Set *)em->msg;
338                   for (i = 0; i < emsg->count; i++)
339                     free(emsg->str[i]);
340                   free(emsg);
341                }
342              break;
343            case EDJE_MESSAGE_NONE:
344            default:
345              break;
346           }
347      }
348    free(em);
349 }
350
351 void
352 _edje_message_propornot_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg, Eina_Bool prop)
353 {
354    /* FIXME: check all malloc & strdup fails and gracefully unroll and exit */
355    Edje_Message *em;
356    int i;
357    unsigned char *msg = NULL;
358
359    em = _edje_message_new(ed, queue, type, id);
360    if (!em) return;
361    em->propagated = prop;
362    if (_job)
363      {
364         ecore_job_del(_job);
365         _job = NULL;
366      }
367    if (_injob > 0)
368      {
369         if (!_job_loss_timer)
370           _job_loss_timer = ecore_timer_add(0.001, _edje_job_loss_timer, NULL);
371      }
372    else
373      {
374         if (!_job)
375           {
376              _job = ecore_job_add(_edje_job, NULL);
377           }
378         if (_job_loss_timer)
379           {
380              ecore_timer_del(_job_loss_timer);
381              _job_loss_timer = NULL;
382           }
383      }
384    switch (em->type)
385      {
386       case EDJE_MESSAGE_NONE:
387         break;
388       case EDJE_MESSAGE_SIGNAL:
389           {
390              Edje_Message_Signal *emsg2, *emsg3;
391
392              emsg2 = (Edje_Message_Signal *)emsg;
393              emsg3 = calloc(1, sizeof(Edje_Message_Signal));
394              if (emsg2->sig) emsg3->sig = eina_stringshare_add(emsg2->sig);
395              if (emsg2->src) emsg3->src = eina_stringshare_add(emsg2->src);
396              if (emsg2->data)
397                {
398                   emsg3->data = emsg2->data;
399                   emsg3->data->ref++;
400                }
401              msg = (unsigned char *)emsg3;
402           }
403         break;
404       case EDJE_MESSAGE_STRING:
405           {
406              Edje_Message_String *emsg2, *emsg3;
407
408              emsg2 = (Edje_Message_String *)emsg;
409
410              emsg3 = malloc(sizeof(Edje_Message_String));
411              emsg3->str = strdup(emsg2->str);
412              msg = (unsigned char *)emsg3;
413           }
414         break;
415       case EDJE_MESSAGE_INT:
416           {
417              Edje_Message_Int *emsg2, *emsg3;
418
419              emsg2 = (Edje_Message_Int *)emsg;
420              emsg3 = malloc(sizeof(Edje_Message_Int));
421              emsg3->val = emsg2->val;
422              msg = (unsigned char *)emsg3;
423           }
424         break;
425       case EDJE_MESSAGE_FLOAT:
426           {
427              Edje_Message_Float *emsg2, *emsg3;
428
429              emsg2 = (Edje_Message_Float *)emsg;
430              emsg3 = malloc(sizeof(Edje_Message_Float));
431              emsg3->val = emsg2->val;
432              msg = (unsigned char *)emsg3;
433           }
434         break;
435       case EDJE_MESSAGE_STRING_SET:
436           {
437              Edje_Message_String_Set *emsg2, *emsg3;
438
439              emsg2 = (Edje_Message_String_Set *)emsg;
440              emsg3 = malloc(sizeof(Edje_Message_String_Set) + ((emsg2->count - 1) * sizeof(char *)));
441              emsg3->count = emsg2->count;
442              for (i = 0; i < emsg3->count; i++)
443                emsg3->str[i] = strdup(emsg2->str[i]);
444              msg = (unsigned char *)emsg3;
445           }
446         break;
447       case EDJE_MESSAGE_INT_SET:
448           {
449              Edje_Message_Int_Set *emsg2, *emsg3;
450
451              emsg2 = (Edje_Message_Int_Set *)emsg;
452              emsg3 = malloc(sizeof(Edje_Message_Int_Set) + ((emsg2->count - 1) * sizeof(int)));
453              emsg3->count = emsg2->count;
454              for (i = 0; i < emsg3->count; i++)
455                emsg3->val[i] = emsg2->val[i];
456              msg = (unsigned char *)emsg3;
457           }
458         break;
459       case EDJE_MESSAGE_FLOAT_SET:
460           {
461              Edje_Message_Float_Set *emsg2, *emsg3;
462
463              emsg2 = (Edje_Message_Float_Set *)emsg;
464              emsg3 = malloc(sizeof(Edje_Message_Float_Set) + ((emsg2->count - 1) * sizeof(double)));
465              emsg3->count = emsg2->count;
466              for (i = 0; i < emsg3->count; i++)
467                emsg3->val[i] = emsg2->val[i];
468              msg = (unsigned char *)emsg3;
469           }
470         break;
471       case EDJE_MESSAGE_STRING_INT:
472           {
473              Edje_Message_String_Int *emsg2, *emsg3;
474
475              emsg2 = (Edje_Message_String_Int *)emsg;
476              emsg3 = malloc(sizeof(Edje_Message_String_Int));
477              emsg3->str = strdup(emsg2->str);
478              emsg3->val = emsg2->val;
479              msg = (unsigned char *)emsg3;
480           }
481         break;
482       case EDJE_MESSAGE_STRING_FLOAT:
483           {
484              Edje_Message_String_Float *emsg2, *emsg3;
485
486              emsg2 = (Edje_Message_String_Float *)emsg;
487              emsg3 = malloc(sizeof(Edje_Message_String_Float));
488              emsg3->str = strdup(emsg2->str);
489              emsg3->val = emsg2->val;
490              msg = (unsigned char *)emsg3;
491           }
492         break;
493       case EDJE_MESSAGE_STRING_INT_SET:
494           {
495              Edje_Message_String_Int_Set *emsg2, *emsg3;
496
497              emsg2 = (Edje_Message_String_Int_Set *)emsg;
498              emsg3 = malloc(sizeof(Edje_Message_String_Int_Set) + ((emsg2->count - 1) * sizeof(int)));
499              emsg3->str = strdup(emsg2->str);
500              emsg3->count = emsg2->count;
501              for (i = 0; i < emsg3->count; i++)
502                emsg3->val[i] = emsg2->val[i];
503              msg = (unsigned char *)emsg3;
504           }
505         break;
506       case EDJE_MESSAGE_STRING_FLOAT_SET:
507           {
508              Edje_Message_String_Float_Set *emsg2, *emsg3;
509
510              emsg2 = (Edje_Message_String_Float_Set *)emsg;
511              emsg3 = malloc(sizeof(Edje_Message_String_Float_Set) + ((emsg2->count - 1) * sizeof(double)));
512              emsg3->str = strdup(emsg2->str);
513              emsg3->count = emsg2->count;
514              for (i = 0; i < emsg3->count; i++)
515                emsg3->val[i] = emsg2->val[i];
516              msg = (unsigned char *)emsg3;
517           }
518         break;
519       default:
520         break;
521      }
522
523    em->msg = msg;
524    msgq = eina_list_append(msgq, em);
525 }
526
527 void
528 _edje_message_send(Edje *ed, Edje_Queue queue, Edje_Message_Type type, int id, void *emsg)
529 {
530    _edje_message_propornot_send(ed, queue, type, id, emsg, EINA_FALSE);
531 }
532
533 void
534 _edje_message_parameters_push(Edje_Message *em)
535 {
536    int i;
537    
538    /* these params ALWAYS go on */
539    /* first param is the message type - always */
540    embryo_parameter_cell_push(em->edje->collection->script,
541                               (Embryo_Cell)em->type);
542    /* 2nd param is the integer of the event id - always there */
543    embryo_parameter_cell_push(em->edje->collection->script,
544                               (Embryo_Cell)em->id);
545    /* the rest is varags of whatever is in the msg */
546    switch (em->type)
547      {
548       case EDJE_MESSAGE_NONE:
549         break;
550       case EDJE_MESSAGE_STRING:
551         embryo_parameter_string_push(em->edje->collection->script,
552                                      ((Edje_Message_String *)em->msg)->str);
553         break;
554       case EDJE_MESSAGE_INT:
555           {
556              Embryo_Cell v;
557
558              v = (Embryo_Cell)((Edje_Message_Int *)em->msg)->val;
559              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
560           }
561         break;
562       case EDJE_MESSAGE_FLOAT:
563           {
564              Embryo_Cell v;
565              float fv;
566
567              fv = ((Edje_Message_Float *)em->msg)->val;
568              v = EMBRYO_FLOAT_TO_CELL(fv);
569              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
570           }
571         break;
572       case EDJE_MESSAGE_STRING_SET:
573         for (i = 0; i < ((Edje_Message_String_Set *)em->msg)->count; i++)
574           embryo_parameter_string_push(em->edje->collection->script,
575                                        ((Edje_Message_String_Set *)em->msg)->str[i]);
576         break;
577       case EDJE_MESSAGE_INT_SET:
578         for (i = 0; i < ((Edje_Message_Int_Set *)em->msg)->count; i++)
579           {
580              Embryo_Cell v;
581
582              v = (Embryo_Cell)((Edje_Message_Int_Set *)em->msg)->val[i];
583              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
584           }
585         break;
586       case EDJE_MESSAGE_FLOAT_SET:
587         for (i = 0; i < ((Edje_Message_Float_Set *)em->msg)->count; i++)
588           {
589              Embryo_Cell v;
590              float fv;
591
592              fv = ((Edje_Message_Float_Set *)em->msg)->val[i];
593              v = EMBRYO_FLOAT_TO_CELL(fv);
594              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
595           }
596         break;
597       case EDJE_MESSAGE_STRING_INT:
598         embryo_parameter_string_push(em->edje->collection->script,
599                                      ((Edje_Message_String_Int *)em->msg)->str);
600           {
601              Embryo_Cell v;
602
603              v = (Embryo_Cell)((Edje_Message_String_Int *)em->msg)->val;
604              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
605           }
606         break;
607       case EDJE_MESSAGE_STRING_FLOAT:
608         embryo_parameter_string_push(em->edje->collection->script,
609                                      ((Edje_Message_String_Float *)em->msg)->str);
610           {
611              Embryo_Cell v;
612              float fv;
613
614              fv = ((Edje_Message_String_Float *)em->msg)->val;
615              v = EMBRYO_FLOAT_TO_CELL(fv);
616              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
617           }
618         break;
619       case EDJE_MESSAGE_STRING_INT_SET:
620         embryo_parameter_string_push(em->edje->collection->script,
621                                      ((Edje_Message_String_Int_Set *)em->msg)->str);
622         for (i = 0; i < ((Edje_Message_String_Int_Set *)em->msg)->count; i++)
623           {
624              Embryo_Cell v;
625
626              v = (Embryo_Cell)((Edje_Message_String_Int_Set *)em->msg)->val[i];
627              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
628           }
629         break;
630       case EDJE_MESSAGE_STRING_FLOAT_SET:
631         embryo_parameter_string_push(em->edje->collection->script,
632                                      ((Edje_Message_String_Float_Set *)em->msg)->str);
633         for (i = 0; i < ((Edje_Message_String_Float_Set *)em->msg)->count; i++)
634           {
635              Embryo_Cell v;
636              float fv;
637
638              fv = ((Edje_Message_String_Float_Set *)em->msg)->val[i];
639              v = EMBRYO_FLOAT_TO_CELL(fv);
640              embryo_parameter_cell_array_push(em->edje->collection->script, &v, 1);
641           }
642         break;
643       default:
644         break;
645      }
646 }
647
648 void
649 _edje_message_process(Edje_Message *em)
650 {
651    Embryo_Function fn;
652    void *pdata;
653    int ret;
654    
655    /* signals are only handled one way */
656    if (em->type == EDJE_MESSAGE_SIGNAL)
657      {
658         _edje_emit_handle(em->edje,
659                           ((Edje_Message_Signal *)em->msg)->sig,
660                           ((Edje_Message_Signal *)em->msg)->src,
661                           ((Edje_Message_Signal *)em->msg)->data,
662                           em->propagated);
663         return;
664      }
665    /* if this has been queued up for the app then just call the callback */
666    if (em->queue == EDJE_QUEUE_APP)
667      {
668         if (em->edje->message.func)
669           em->edje->message.func(em->edje->message.data, em->edje->obj,
670                                  em->type, em->id, em->msg);
671         return;
672      }
673    /* now this message is destined for the script message handler fn */
674    if (!(em->edje->collection)) return;
675    if ((em->edje->collection->script) && _edje_script_only (em->edje))
676      {
677         _edje_script_only_message(em->edje, em);
678         return;
679      }
680    if (em->edje->L)
681      {
682         _edje_lua_script_only_message(em->edje, em);
683         return;
684      }
685    fn = embryo_program_function_find(em->edje->collection->script, "message");
686    if (fn == EMBRYO_FUNCTION_NONE) return;
687    /* reset the engine */
688    _edje_embryo_script_reset(em->edje);
689    
690    _edje_message_parameters_push(em);
691    
692    embryo_program_vm_push(em->edje->collection->script);
693    _edje_embryo_globals_init(em->edje);
694    pdata = embryo_program_data_get(em->edje->collection->script);
695    embryo_program_data_set(em->edje->collection->script, em->edje);
696    embryo_program_max_cycle_run_set(em->edje->collection->script, 5000000);
697    ret = embryo_program_run(em->edje->collection->script, fn);
698    if (ret == EMBRYO_PROGRAM_FAIL)
699      {
700         ERR("ERROR with embryo script. "
701             "OBJECT NAME: '%s', "
702             "OBJECT FILE: '%s', "
703             "ENTRY POINT: '%s', "
704             "ERROR: '%s'",
705             em->edje->collection->part,
706             em->edje->file->path,
707             "message",
708             embryo_error_string_get(embryo_program_error_get(em->edje->collection->script)));
709      }
710    else if (ret == EMBRYO_PROGRAM_TOOLONG)
711      {
712         ERR("ERROR with embryo script. "
713             "OBJECT NAME: '%s', "
714             "OBJECT FILE: '%s', "
715             "ENTRY POINT: '%s', "
716             "ERROR: 'Script exceeded maximum allowed cycle count of %i'",
717             em->edje->collection->part,
718             em->edje->file->path,
719             "message",
720             embryo_program_max_cycle_run_get(em->edje->collection->script));
721      }
722    
723    embryo_program_data_set(em->edje->collection->script, pdata);
724    embryo_program_vm_pop(em->edje->collection->script);
725 }
726
727 void
728 _edje_message_queue_process(void)
729 {
730    int i;
731
732    if (!msgq) return;
733
734    /* allow the message queue to feed itself up to 8 times before forcing */
735    /* us to go back to normal processing and let a 0 timeout deal with it */
736    for (i = 0; (i < 8) && (msgq); i++)
737      {
738         /* a temporary message queue */
739         if (tmp_msgq)
740           {
741              while (msgq)
742                {
743                   tmp_msgq = eina_list_append(tmp_msgq, msgq->data);
744                   msgq = eina_list_remove_list(msgq, msgq);
745                }
746           }
747         else
748           {
749              tmp_msgq = msgq;
750              msgq = NULL;
751           }
752
753         tmp_msgq_processing++;
754         while (tmp_msgq)
755           {
756              Edje_Message *em;
757              Edje *ed;
758
759              em = tmp_msgq->data;
760              ed = em->edje;
761              tmp_msgq = eina_list_remove_list(tmp_msgq, tmp_msgq);
762              em->edje->message.num--;
763              if (!ed->delete_me)
764                {
765                   ed->processing_messages++;
766                   _edje_message_process(em);
767                   _edje_message_free(em);
768                   ed->processing_messages--;
769                }
770              else
771                _edje_message_free(em);
772              if (ed->processing_messages == 0)
773                {
774                   if (ed->delete_me) _edje_del(ed);
775                }
776           }
777         tmp_msgq_processing--;
778         if (tmp_msgq_processing == 0)
779            tmp_msgq_restart = 0;
780         else
781            tmp_msgq_restart = 1;
782      }
783
784    /* if the message queue filled again set a timer to expire in 0.0 sec */
785    /* to get the idle enterer to be run again */
786    if (msgq)
787      {
788         static int self_feed_debug = -1;
789         
790         if (self_feed_debug == -1)
791           {
792              const char *s = getenv("EDJE_SELF_FEED_DEBUG");
793              if (s) self_feed_debug = atoi(s);
794              else self_feed_debug = 0;
795           }
796         if (self_feed_debug)
797           {
798              WRN("Edje is in a self-feeding message loop (> 8 loops needed)");
799           }
800         ecore_timer_add(0.0, _edje_dummy_timer, NULL);
801      }
802 }
803
804 void
805 _edje_message_queue_clear(void)
806 {
807    while (msgq)
808      {
809         Edje_Message *em;
810
811         em = msgq->data;
812         msgq = eina_list_remove_list(msgq, msgq);
813         em->edje->message.num--;
814         _edje_message_free(em);
815      }
816    while (tmp_msgq)
817      {
818         Edje_Message *em;
819
820         em = tmp_msgq->data;
821         tmp_msgq = eina_list_remove_list(tmp_msgq, tmp_msgq);
822         em->edje->message.num--;
823         _edje_message_free(em);
824      }
825 }
826
827 void
828 _edje_message_del(Edje *ed)
829 {
830    Eina_List *l;
831
832    if (ed->message.num <= 0) return;
833    /* delete any messages on the main queue for this edje object */
834    for (l = msgq; l; )
835      {
836         Edje_Message *em;
837         Eina_List *lp;
838
839         em = eina_list_data_get(l);
840         lp = l;
841         l = eina_list_next(l);
842         if (em->edje == ed)
843           {
844              msgq = eina_list_remove_list(msgq, lp);
845              em->edje->message.num--;
846              _edje_message_free(em);
847           }
848         if (ed->message.num <= 0) return;
849      }
850    /* delete any on the processing queue */
851    for (l = tmp_msgq; l; )
852      {
853         Edje_Message *em;
854         Eina_List *lp;
855
856         em = eina_list_data_get(l);
857         lp = l;
858         l = eina_list_next(l);
859         if (em->edje == ed)
860           {
861              tmp_msgq = eina_list_remove_list(tmp_msgq, lp);
862              em->edje->message.num--;
863              _edje_message_free(em);
864           }
865         if (ed->message.num <= 0) return;
866      }
867 }