This causes segv's on 64bit!
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Tue, 12 Mar 2013 14:48:42 +0000 (23:48 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Tue, 12 Mar 2013 14:48:42 +0000 (23:48 +0900)
Program received signal SIGSEGV, Segmentation fault.
_edje_emit_cb (ed=ed@entry=0x8ebd68, sig=sig@entry=0x8fba4c
"focus,part,in", src=src@entry=0x8222fc "elm.text",
data=data@entry=0x0, prop=prop@entry=0 '\000') at
lib/edje/edje_program.c:1442
warning: Source file is more recent than executable.
1442                                eina_list_free(data.matches);
(gdb) bt
"focus,part,in", src=src@entry=0x8222fc "elm.text",
data=data@entry=0x0, prop=prop@entry=0 '\000') at
lib/edje/edje_program.c:1442
"focus,part,in", src=0x8222fc "elm.text", sdata=0x0, prop=0 '\000') at
lib/edje/edje_program.c:1366
_pd=0x8222f0, list=0x7fff00000001) at lib/edje/edje_message_queue.c:124
op_type=EO_OP_TYPE_REGULAR, op=564, p_list=0x7fffffffcf28) at
lib/eo/eo.c:364
op_type=EO_OP_TYPE_REGULAR, obj=0x8ebae0) at lib/eo/eo.c:404
op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:435
(obj=<optimized out>) at lib/edje/edje_message_queue.c:71
(sid=sid@entry=0x8eae88) at elm_interface_scrollable.c:788
(sid=0x8eae88) at elm_interface_scrollable.c:805
_pd=0x8eae88, list=<optimized out>) at elm_interface_scrollable.c:3370
op_type=EO_OP_TYPE_REGULAR, op=840, p_list=0x7fffffffd158) at
lib/eo/eo.c:364
op_type=EO_OP_TYPE_REGULAR, obj=0x8ea9e0) at lib/eo/eo.c:404
op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:435
_pd=0x8ead70, list=<optimized out>) at elm_entry.c:2804
op_type=EO_OP_TYPE_REGULAR, op=129, p_list=0x7fffffffd328) at
lib/eo/eo.c:364
op_type=EO_OP_TYPE_REGULAR, obj=0x8ea9e0) at lib/eo/eo.c:404
lib/eo/eo.c:435
op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd4a8) at
lib/eo/eo.c:364
(obj=obj@entry=0x8ea9e0, op_type=op_type@entry=EO_OP_TYPE_REGULAR,
op=1) at lib/eo/eo.c:463
class_data=<optimized out>, list=<optimized out>) at elm_widget.c:5526
op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd628) at
lib/eo/eo.c:364
(obj=obj@entry=0x8ea9e0, op_type=op_type@entry=EO_OP_TYPE_REGULAR,
op=1) at lib/eo/eo.c:463
out>, list=<optimized out>) at elm_layout.c:2157
op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd7b8) at
lib/eo/eo.c:364
op_type=<optimized out>, op=1) at lib/eo/eo.c:463
op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd928) at
lib/eo/eo.c:364
(obj=obj@entry=0x8ea9e0, op_type=op_type@entry=EO_OP_TYPE_REGULAR,
op=1) at lib/eo/eo.c:463
out>, list=<optimized out>) at elm_entry.c:3076
op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffdad8) at
lib/eo/eo.c:364
op_type=EO_OP_TYPE_REGULAR, obj=0x8ea9e0) at lib/eo/eo.c:404
lib/eo/eo.c:1162
elm_entry.c:3068
autorun=0x0) at test.c:441

Revert "edje: reduce memory usage of Edje signal callbacks and automates."

This reverts commit 15aae2c0a4b9f59199395884439626de39e80e62.

src/Makefile_Edje.am
src/lib/edje/Edje.h
src/lib/edje/edje_main.c
src/lib/edje/edje_match.c
src/lib/edje/edje_private.h
src/lib/edje/edje_program.c
src/lib/edje/edje_signal.c [deleted file]
src/lib/edje/edje_smart.c

index 20ec55288b5b36bb20bd20ee1d11419cb208ae5b..db4534ac2ac30530a8158c18dcbf90d7752d14b9 100644 (file)
@@ -46,8 +46,7 @@ lib/edje/edje_smart.c \
 lib/edje/edje_text.c \
 lib/edje/edje_textblock_styles.c \
 lib/edje/edje_util.c \
-lib/edje/edje_var.c \
-lib/edje/edje_signal.c
+lib/edje/edje_var.c
 
 lib_edje_libedje_la_CPPFLAGS = $(EDJE_COMMON_CPPFLAGS)
 lib_edje_libedje_la_LIBADD = @EDJE_LIBS@
index 5a5afe5460d3ab3487f9a0d82c50e47e6d4e9a0e..c678ee78723f28b44d2ba42a71f9c5bfb58e6b79 100644 (file)
@@ -893,6 +893,7 @@ enum
 
    EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD,
    EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL,
+   EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL,
    EDJE_OBJ_SUB_ID_SIGNAL_EMIT,
    EDJE_OBJ_SUB_ID_PLAY_SET,
    EDJE_OBJ_SUB_ID_PLAY_GET,
@@ -2708,7 +2709,23 @@ enum
  *
  * @see edje_object_signal_callback_del
  */
-#define edje_obj_signal_callback_del(emission, source, func, data, ret) EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), EO_TYPECHECK(const char *, emission), EO_TYPECHECK(const char *, source), EO_TYPECHECK(Edje_Signal_Cb, func), EO_TYPECHECK(void *, data), EO_TYPECHECK(void **, ret)
+#define edje_obj_signal_callback_del(emission, source, func, ret) EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), EO_TYPECHECK(const char *, emission), EO_TYPECHECK(const char *, source), EO_TYPECHECK(Edje_Signal_Cb, func), EO_TYPECHECK(void **, ret)
+
+/**
+ * @def edje_obj_signal_callback_del_full
+ * @since 1.8
+ *
+ * @brief Unregister/delete a callback set for an arriving Edje
+ *
+ * @param[in] emission
+ * @param[in] source
+ * @param[in] func
+ * @param[in] data
+ * @param[out] ret
+ *
+ * @see edje_object_signal_callback_del_full
+ */
+#define edje_obj_signal_callback_del_full(emission, source, func, data, ret) EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL), EO_TYPECHECK(const char *, emission), EO_TYPECHECK(const char *, source), EO_TYPECHECK(Edje_Signal_Cb, func), EO_TYPECHECK(void *, data), EO_TYPECHECK(void **, ret)
 
 /**
  * @def edje_obj_signal_emit
index 2d0dc8b4972517bbe7636c4f89cefc605e10ccc5..74b1349ee87b29d7e4f1cb4ddb26d9a882e71bcd 100644 (file)
@@ -68,7 +68,6 @@ edje_init(void)
    _edje_module_init();
    _edje_message_init();
    _edje_multisense_init();
-   edje_signal_init();
 
    _edje_real_part_mp = eina_mempool_add("chained_mempool",
                                         "Edje_Real_Part", NULL,
@@ -135,7 +134,6 @@ _edje_shutdown_core(void)
    _edje_real_part_state_mp = NULL;
    _edje_real_part_mp = NULL;
 
-   edje_signal_shutdown();
    _edje_multisense_shutdown();
    _edje_message_shutdown();
    _edje_module_shutdown();
@@ -226,6 +224,7 @@ _edje_del(Edje *ed)
 {
    Edje_Running_Program *runp;
    Edje_Pending_Program *pp;
+   Edje_Signal_Callback *escb;
    Edje_Text_Class *tc;
    Edje_Text_Insert_Filter_Callback *cb;
 
@@ -235,7 +234,7 @@ _edje_del(Edje *ed)
        return;
      }
    _edje_message_del(ed);
-   _edje_signal_callback_free(ed->callbacks);
+   _edje_callbacks_patterns_clean(ed);
    _edje_file_del(ed);
    if (ed->path) eina_stringshare_del(ed->path);
    if (ed->group) eina_stringshare_del(ed->group);
@@ -250,6 +249,12 @@ _edje_del(Edje *ed)
      free(runp);
    EINA_LIST_FREE(ed->pending_actions, pp)
      free(pp);
+   EINA_LIST_FREE(ed->callbacks, escb)
+     {
+       if (escb->signal) eina_stringshare_del(escb->signal);
+       if (escb->source) eina_stringshare_del(escb->source);
+       free(escb);
+     }
    eina_hash_free(ed->color_classes);
    EINA_LIST_FREE(ed->text_classes, tc)
      {
index 40e609d2bd6a6f01bfc832cf3092eb44afc80f8a..558d982ff452575ceb617380f67fb3cc6b7b88be 100644 (file)
@@ -377,66 +377,6 @@ _edje_match_patterns_exec_init_states(Edje_States       *states,
      return r;                                                  \
   }
 
-#define EDJE_MATCH_INIT_INARRAY(Func, Source, Show)                     \
-  Edje_Patterns*                                                        \
-  Func(const Eina_Inarray *array, const Edje_Signal_Callback_Match *matches) \
-  {                                                                     \
-     Edje_Patterns *r;                                                  \
-     int *it;                                                           \
-     size_t i = 0;                                                      \
-                                                                        \
-     if (!matches)                                                      \
-       return NULL;                                                     \
-                                                                        \
-     r = malloc(sizeof (Edje_Patterns) +                                \
-                eina_inarray_count(array)                               \
-                * sizeof(*r->finals)                                    \
-                * sizeof(*r->patterns));                                \
-     if (!r) return NULL;                                               \
-                                                                        \
-     r->ref = 1;                                                        \
-     r->delete_me = EINA_FALSE;                                         \
-     r->patterns_size = eina_inarray_count(array);                      \
-     r->max_length = 0;                                                 \
-     r->patterns = (const char **) r->finals + r->patterns_size + 1;    \
-                                                                        \
-     EINA_INARRAY_FOREACH(array, it)                                    \
-       {                                                                \
-          const char    *str;                                           \
-          size_t         j;                                             \
-          int            special = 0;                                   \
-                                                                        \
-          str = (matches + *it)->Source;                                \
-          if (!str) str = "";                                           \
-          r->patterns[i] = str;                                         \
-                                                                        \
-          if (Show)                                                     \
-            INF("%lu [%s]", (unsigned long)i, str);                     \
-                                                                        \
-          r->finals[i] = 0;                                             \
-          for (j = 0; str[j]; ++j)                                      \
-            if (str[j] != '*')                                          \
-              {                                                         \
-                 r->finals[i] = j + 1;                                  \
-                 special++;                                             \
-              }                                                         \
-          j += special ? special + 1 : 0;                               \
-                                                                        \
-          if (j > r->max_length)                                        \
-            r->max_length = j;                                          \
-                                                                        \
-          i++;                                                          \
-       }                                                                \
-                                                                        \
-     if (!_edje_match_states_alloc(r, 2))                               \
-       {                                                                \
-          free(r);                                                      \
-          return NULL;                                                  \
-       }                                                                \
-                                                                        \
-     return r;                                                          \
-  }
-
 EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init,
                     Edje_Part_Collection_Directory_Entry,
                     entry, 0);
@@ -446,10 +386,12 @@ EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init,
 EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init,
                      Edje_Program,
                      source, 0);
-EDJE_MATCH_INIT_INARRAY(edje_match_callback_signal_init,
-                        signal, 0);
-EDJE_MATCH_INIT_INARRAY(edje_match_callback_source_init,
-                        source, 0);
+EDJE_MATCH_INIT_LIST(edje_match_callback_signal_init,
+                    Edje_Signal_Callback,
+                    signal, 0);
+EDJE_MATCH_INIT_LIST(edje_match_callback_source_init,
+                    Edje_Signal_Callback,
+                    source, 0);
 
 static Eina_Bool
 _edje_match_collection_dir_exec_finals(const size_t      *finals,
@@ -507,18 +449,20 @@ edje_match_programs_exec_check_finals(const size_t      *signal_finals,
 }
 
 static int
-edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns *ssp,
-                                      const Edje_Signal_Callback_Match    *matches,
-                                      const void       **custom_data,
-                                      const Eina_Bool   *flags,
+edje_match_callback_exec_check_finals(const Edje_Patterns *signal_ppat,
+                                      const Edje_Patterns *source_ppat,
+                                      const size_t      *signal_finals,
+                                      const size_t      *source_finals,
                                       const Edje_States *signal_states,
                                       const Edje_States *source_states,
                                       const char        *sig,
                                       const char        *source,
+                                      Eina_List         *callbacks,
                                       Edje              *ed,
-                                      Eina_Bool          prop)
+                                      Eina_Bool          prop
+                                     )
 {
-   const Edje_Signal_Callback_Match *cb;
+   Edje_Signal_Callback *escb;
    Eina_Array   run;
    size_t       i;
    size_t       j;
@@ -527,39 +471,39 @@ edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns *ssp,
    eina_array_step_set(&run, sizeof (Eina_Array), 4);
 
    for (i = 0; i < signal_states->size; ++i)
-     if (signal_states->states[i].pos >= ssp->signals_patterns->finals[signal_states->states[i].idx])
-       {
-          for (j = 0; j < source_states->size; ++j)
-            {
-               if (signal_states->states[i].idx == source_states->states[j].idx
-                   && source_states->states[j].pos >= ssp->sources_patterns->finals[source_states->states[j].idx])
-                 {
-                    int *e;
-
-                    e = eina_inarray_nth(&ssp->u.callbacks.globing, signal_states->states[i].idx);
-
-                    cb = &matches[*e];
-                    if (cb)
-                      {
-                         if ((prop) && _edje_signal_callback_prop(flags, *e)) continue;
-                        eina_array_push(&run, cb);
-                        r = 2;
-                      }
-                 }
-            }
-       }
-
-   while ((cb = eina_array_pop(&run)))
      {
-        int idx = cb - matches;
+        if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx])
+          {
+             for (j = 0; j < source_states->size; ++j)
+               {
+                  if (signal_states->states[i].idx == source_states->states[j].idx
+                      && source_states->states[j].pos >= source_finals[source_states->states[j].idx])
+                    {
+                       escb = eina_list_nth(callbacks, signal_states->states[i].idx);
+                       if (escb)
+                         {
+                            if ((prop) && (escb->propagate)) continue;
+                            if ((!escb->just_added)
+                                && (!escb->delete_me))
+                              {
+                                 eina_array_push(&run, escb);
+                                 r = 2;
+                              }
+                         }
+                    }
+               }
+          }
+     }
 
-        cb->func((void*) custom_data[idx], ed->obj, sig, source);
+   while ((escb = eina_array_pop(&run)))
+     {
+        escb->func(escb->data, ed->obj, sig, source);
         if (_edje_block_break(ed))
          {
              r = 0;
              break;
           }
-        if ((ssp->signals_patterns->delete_me) || (ssp->sources_patterns->delete_me))
+        if ((signal_ppat->delete_me) || (source_ppat->delete_me))
           {
              r = 0;
              break;
@@ -682,49 +626,50 @@ edje_match_programs_exec(const Edje_Patterns    *ppat_signal,
 }
 
 int
-edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp,
-                        const Edje_Signal_Callback_Match *matches,
-                        const void **custom_data,
-                        const Eina_Bool *flags,
-                         const char *sig,
-                         const char *source,
-                         Edje *ed,
-                         Eina_Bool prop)
+edje_match_callback_exec(Edje_Patterns          *ppat_signal,
+                         Edje_Patterns          *ppat_source,
+                         const char             *sig,
+                         const char             *source,
+                         Eina_List              *callbacks,
+                         Edje                   *ed,
+                         Eina_Bool               prop
+                        )
 {
    Edje_States  *signal_result;
    Edje_States  *source_result;
    int           r = 0;
 
    /* under high memory presure, they could be NULL */
-   if (!ssp->sources_patterns || !ssp->signals_patterns) return 0;
+   if (!ppat_source || !ppat_signal) return 0;
 
-   ssp->signals_patterns->ref++;
-   ssp->sources_patterns->ref++;
-   _edje_match_patterns_exec_init_states(ssp->signals_patterns->states,
-                                         ssp->signals_patterns->patterns_size,
-                                         ssp->signals_patterns->max_length);
-   _edje_match_patterns_exec_init_states(ssp->sources_patterns->states,
-                                         ssp->sources_patterns->patterns_size,
-                                         ssp->sources_patterns->max_length);
+   ppat_signal->ref++;
+   ppat_source->ref++;
+   _edje_match_patterns_exec_init_states(ppat_signal->states,
+                                         ppat_signal->patterns_size,
+                                         ppat_signal->max_length);
+   _edje_match_patterns_exec_init_states(ppat_source->states,
+                                         ppat_source->patterns_size,
+                                         ppat_source->max_length);
 
-   signal_result = _edje_match_fn(ssp->signals_patterns, sig, ssp->signals_patterns->states);
-   source_result = _edje_match_fn(ssp->sources_patterns, source, ssp->sources_patterns->states);
+   signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states);
+   source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
 
    if (signal_result && source_result)
-     r = edje_match_callback_exec_check_finals(ssp,
-                                              matches,
-                                              custom_data,
-                                              flags,
-                                               signal_result,
-                                               source_result,
-                                               sig,
-                                               source,
-                                               ed,
-                                               prop);
-   ssp->signals_patterns->ref--;
-   ssp->sources_patterns->ref--;
-   if (ssp->signals_patterns->ref <= 0) edje_match_patterns_free(ssp->signals_patterns);
-   if (ssp->sources_patterns->ref <= 0) edje_match_patterns_free(ssp->sources_patterns);
+      r = edje_match_callback_exec_check_finals(ppat_signal,
+                                                ppat_source,
+                                                ppat_signal->finals,
+                                                ppat_source->finals,
+                                                signal_result,
+                                                source_result,
+                                                sig,
+                                                source,
+                                                callbacks,
+                                                ed,
+                                                prop);
+   ppat_signal->ref--;
+   ppat_source->ref--;
+   if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal);
+   if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source);
    return r;
 }
 
@@ -805,13 +750,13 @@ edje_match_program_hash_build(Edje_Program * const *programs,
 
                  item->signal = programs[i]->signal;
                  item->source = programs[i]->source;
-                 eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (void*), 8);
+                 eina_array_step_set(&item->list, sizeof (Eina_Array), 8);
 
                  new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
                                                  EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
               }
 
-            eina_inarray_push(&item->list, &programs[i]);
+            eina_array_push(&item->list, programs[i]);
          }
        else
            result = eina_list_prepend(result, programs[i]);
@@ -821,51 +766,48 @@ edje_match_program_hash_build(Edje_Program * const *programs,
    return result;
 }
 
-void
-edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callbacks,
-                              int callbacks_count,
-                              Eina_Rbtree **tree,
-                               Eina_Inarray *result)
+Eina_List *
+edje_match_callback_hash_build(const Eina_List *callbacks,
+                              Eina_Rbtree **tree)
 {
+   Eina_List *result = NULL;
    Eina_Rbtree *new = NULL;
-   int i;
-
-   eina_inarray_step_set(result, sizeof (Eina_Inarray), sizeof (int), 8);
+   Edje_Signal_Callback *callback;
+   const Eina_List *l;
 
-   for (i = 0; i < callbacks_count; ++i, ++callbacks)
+   EINA_LIST_FOREACH(callbacks, l, callback)
      {
-        if (callbacks->signal && !strpbrk(callbacks->signal, "*?[\\")
-           && callbacks->source && !strpbrk(callbacks->source, "*?[\\"))
+       if (callback->signal && !strpbrk(callback->signal, "*?[\\")
+           && callback->source && !strpbrk(callback->source, "*?[\\"))
          {
             Edje_Signal_Source_Char *item;
 
-            item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callbacks->signal, 0,
-                                                                        EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callbacks->source);
+            item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callback->signal, 0,
+                                                                        EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source);
             if (!item)
               {
                  item = malloc(sizeof (Edje_Signal_Source_Char));
                  if (!item) continue;
 
-                 item->signal = callbacks->signal;
-                 item->source = callbacks->source;
-                  eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (int), 8);
+                 item->signal = callback->signal;
+                 item->source = callback->source;
+                 eina_array_step_set(&item->list, sizeof (Eina_Array), 8);
 
                  new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
                                                  EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
               }
 
-            eina_inarray_push(&item->list, &i);
+            eina_array_push(&item->list, callback);
          }
        else
-          {
-             eina_inarray_push(result, &i);
-          }
+           result = eina_list_prepend(result, callback);
      }
 
    *tree = new;
+   return result;
 }
 
-const Eina_Inarray *
+const Eina_Array *
 edje_match_signal_source_hash_get(const char *sig,
                                  const char *source,
                                  const Eina_Rbtree *tree)
@@ -882,6 +824,6 @@ edje_match_signal_source_hash_get(const char *sig,
 void
 edje_match_signal_source_free(Edje_Signal_Source_Char *key, EINA_UNUSED void *data)
 {
-   eina_inarray_flush(&key->list);
+   eina_array_flush(&key->list);
    free(key);
 }
index 6e849eca9a02095c6c8db35d955d449b699157fe..ac3b169e468b597475b7362aa922f76203d2d4b0 100644 (file)
@@ -321,10 +321,6 @@ typedef struct _Edje_Signal_Source_Char Edje_Signal_Source_Char;
 typedef struct _Edje_Text_Insert_Filter_Callback Edje_Text_Insert_Filter_Callback;
 typedef struct _Edje_Markup_Filter_Callback Edje_Markup_Filter_Callback;
 typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns;
-typedef struct _Edje_Signal_Callback_Group Edje_Signal_Callback_Group;
-typedef struct _Edje_Signal_Callback_Match Edje_Signal_Callback_Match;
-typedef struct _Edje_Signal_Callback_Matches Edje_Signal_Callback_Matches;
-typedef struct _Edje_Signal_Callback_Custom Edje_Signal_Callback_Custom;
 
 #define EDJE_INF_MAX_W 100000
 #define EDJE_INF_MAX_H 100000
@@ -774,7 +770,6 @@ struct _Edje_Part_Limit
 
 struct _Edje_Signals_Sources_Patterns
 {
-   EINA_REFCOUNT;
    Edje_Patterns *signals_patterns;
    Edje_Patterns *sources_patterns;
 
@@ -786,39 +781,11 @@ struct _Edje_Signals_Sources_Patterns
         unsigned int  count;
       } programs;
       struct {
-         Eina_Inarray   globing;
+        Eina_List     *globing;
       } callbacks;
    } u;
 };
 
-struct _Edje_Signal_Callback_Match
-{
-   const char     *signal;
-   const char     *source;
-   Edje_Signal_Cb  func;
-};
-
-struct _Edje_Signal_Callback_Matches
-{
-   Edje_Signal_Callback_Match *matches;
-
-   Edje_Signals_Sources_Patterns *patterns;
-
-   unsigned int matches_count;
-   EINA_REFCOUNT;
-
-   Eina_Bool hashed : 1;
-};
-
-struct _Edje_Signal_Callback_Group
-{
-   const Edje_Signal_Callback_Matches *matches;
-
-   void **custom_data;
-
-   Eina_Bool *flags; /* 4 bits per custom data (delete_me, just_added, propagate) */
-};
-
 /*----------*/
 
 struct _Edje_Part_Collection
@@ -1220,7 +1187,7 @@ struct _Edje_Signal_Source_Char
    const char *signal;
    const char *source;
 
-   Eina_Inarray  list;
+   Eina_Array  list;
 };
 
 struct _Edje
@@ -1238,6 +1205,7 @@ struct _Edje
    Edje_File            *file; /* the file the data comes form */
    Edje_Part_Collection *collection; /* the description being used */
    Eina_List            *actions; /* currently running actions */
+   Eina_List            *callbacks;
    Eina_List            *pending_actions;
    Eina_Hash            *color_classes;
    Eina_List            *text_classes;
@@ -1260,7 +1228,9 @@ struct _Edje
 
    Edje_Perspective     *persp;
 
-   const Edje_Signal_Callback_Group *callbacks;
+   struct {
+      Edje_Signals_Sources_Patterns callbacks;
+   } patterns;
 
    struct {
       Edje_Text_Change_Cb  func;
@@ -1811,10 +1781,8 @@ Edje_Patterns   *edje_match_programs_signal_init(Edje_Program * const *array,
                                                 unsigned int count);
 Edje_Patterns   *edje_match_programs_source_init(Edje_Program * const *array,
                                                 unsigned int count);
-Edje_Patterns   *edje_match_callback_signal_init(const Eina_Inarray *lst,
-                                                 const Edje_Signal_Callback_Match *matches);
-Edje_Patterns   *edje_match_callback_source_init(const Eina_Inarray *lst,
-                                                 const Edje_Signal_Callback_Match *matches);
+Edje_Patterns   *edje_match_callback_signal_init(const Eina_List *lst);
+Edje_Patterns   *edje_match_callback_source_init(const Eina_List *lst);
 
 Eina_Bool        edje_match_collection_dir_exec(const Edje_Patterns      *ppat,
                                                const char               *string);
@@ -1826,29 +1794,25 @@ Eina_Bool        edje_match_programs_exec(const Edje_Patterns    *ppat_signal,
                                          Eina_Bool (*func)(Edje_Program *pr, void *data),
                                          void                   *data,
                                           Eina_Bool               prop);
-int edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp,
-                            const Edje_Signal_Callback_Match *matches,
-                            const void **custom_data,
-                            const Eina_Bool *flags,
-                            const char *sig,
-                            const char *source,
-                            Edje *ed,
-                            Eina_Bool prop);
+int              edje_match_callback_exec(Edje_Patterns          *ppat_signal,
+                                         Edje_Patterns          *ppat_source,
+                                         const char             *signal,
+                                         const char             *source,
+                                         Eina_List              *callbacks,
+                                         Edje                   *ed,
+                                          Eina_Bool               prop);
 
 void             edje_match_patterns_free(Edje_Patterns *ppat);
 
 Eina_List *edje_match_program_hash_build(Edje_Program * const * programs,
                                         unsigned int count,
                                         Eina_Rbtree **tree);
-void edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callback,
-                                   int callbacks_count,
-                                   Eina_Rbtree **tree,
-                                   Eina_Inarray *result);
-const Eina_Inarray *edje_match_signal_source_hash_get(const char *signal,
-                                                     const char *source,
-                                                     const Eina_Rbtree *tree);
+Eina_List *edje_match_callback_hash_build(const Eina_List *callbacks,
+                                         Eina_Rbtree **tree);
+const Eina_Array *edje_match_signal_source_hash_get(const char *signal,
+                                                   const char *source,
+                                                   const Eina_Rbtree *tree);
 void edje_match_signal_source_free(Edje_Signal_Source_Char *key, void *data);
-void _edje_signal_callback_matches_unref(Edje_Signal_Callback_Matches *m);
 
 // FIXME remove below 3 eapi decls when edje_convert goes
 EAPI void _edje_edd_init(void);
@@ -1906,16 +1870,6 @@ void  _edje_callbacks_focus_add(Evas_Object *obj, Edje *ed, Edje_Real_Part *rp);
 void  _edje_callbacks_del(Evas_Object *obj, Edje *ed);
 void  _edje_callbacks_focus_del(Evas_Object *obj, Edje *ed);
 
-const Edje_Signal_Callback_Group *_edje_signal_callback_alloc(void);
-void _edje_signal_callback_free(const Edje_Signal_Callback_Group *cgp);
-void _edje_signal_callback_push(const Edje_Signal_Callback_Group *cgp,
-                                const char *signal, const char *source,
-                                Edje_Signal_Cb func, void *data,
-                                Eina_Bool propagate);
-void *_edje_signal_callback_disable(const Edje_Signal_Callback_Group *cgp,
-                                    const char *signal, const char *source,
-                                    Edje_Signal_Cb func, void *data);
-
 EAPI void _edje_edd_init(void);
 EAPI void _edje_edd_shutdown(void);
 
@@ -1952,12 +1906,7 @@ void  _edje_emit(Edje *ed, const char *sig, const char *src);
 void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *));
 void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop);
 void  _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp);
-
-const Edje_Signals_Sources_Patterns *_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp);
-void _edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp);
-Eina_Bool _edje_signal_callback_prop(const Eina_Bool *flags, int i);
-
-void _edje_signal_callback_free(const Edje_Signal_Callback_Group *gp);
+void  _edje_callbacks_patterns_clean(Edje *ed);
 
 void           _edje_text_init(void);
 void           _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep);
@@ -2502,9 +2451,6 @@ void _play_get(Eo *obj, void *_pd, va_list *list);
 void _animation_set(Eo *obj, void *_pd, va_list *list);
 void _animation_get(Eo *obj, void *_pd, va_list *list);
 
-void edje_signal_init(void);
-void edje_signal_shutdown(void);
-
 #ifdef HAVE_LIBREMIX
 #include <remix/remix.h>
 #endif
index 8c312837881c1a89723fa455a618eb20edb2b340..e66554d74783e6aa1c385fb448a6604da0833b0e 100644 (file)
@@ -28,27 +28,26 @@ edje_frametime_get(void)
 void
 edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
 {
-   const char *sig;
-   const char *src;
    Edje *ed;
+   Edje_Signal_Callback *escb;
 
    ed = _edje_fetch(obj);
    if (!ed) return;
    if (ed->delete_me) return;
-
-   if (!ed->callbacks)
-     ed->callbacks = _edje_signal_callback_alloc();
-
-   sig = eina_stringshare_add("*");
-   src = eina_stringshare_add("*");
-
-   _edje_signal_callback_push(ed->callbacks,
-                              sig, src,
-                              func, data,
-                              EINA_TRUE);
-
-   eina_stringshare_del(sig);
-   eina_stringshare_del(src);
+   escb = calloc(1, sizeof(Edje_Signal_Callback));
+   escb->propagate = EINA_TRUE;
+   escb->signal = eina_stringshare_add("*");
+   escb->source = eina_stringshare_add("*");
+   escb->func = func;
+   escb->data = data;
+   ed->callbacks = eina_list_append(ed->callbacks, escb);
+   if (ed->walking_callbacks)
+     {
+       escb->just_added = 1;
+       ed->just_added_callbacks = EINA_TRUE;
+     }
+   else
+     _edje_callbacks_patterns_clean(ed);
 }
 
 EAPI void
@@ -67,24 +66,27 @@ _signal_callback_add(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
    void *data = va_arg(*list, void *);
 
    Edje *ed = _pd;
+   Edje_Signal_Callback *escb;
 
    if ((!emission) || (!source) || (!func)) return;
    ed = _pd;
    if (!ed) return;
    if (ed->delete_me) return;
-
-   emission = eina_stringshare_add(emission);
-   source = eina_stringshare_add(source);
-
-   if (!ed->callbacks)
-     ed->callbacks = _edje_signal_callback_alloc();
-
-   _edje_signal_callback_push(ed->callbacks,
-                              emission, source,
-                              func, data, EINA_FALSE);
-
-   eina_stringshare_del(emission);
-   eina_stringshare_del(source);
+   escb = calloc(1, sizeof(Edje_Signal_Callback));
+   if (emission[0])
+     escb->signal = eina_stringshare_add(emission);
+   if (source[0])
+     escb->source = eina_stringshare_add(source);
+   escb->func = func;
+   escb->data = data;
+   ed->callbacks = eina_list_append(ed->callbacks, escb);
+   if (ed->walking_callbacks)
+     {
+       escb->just_added = 1;
+       ed->just_added_callbacks = EINA_TRUE;
+     }
+   else
+     _edje_callbacks_patterns_clean(ed);
 }
 
 EAPI void *
@@ -92,7 +94,7 @@ edje_object_signal_callback_del(Evas_Object *obj, const char *emission, const ch
 {
    if (!obj) return NULL;
    void *ret = NULL;
-   eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, NULL, &ret));
+   eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, &ret));
    return ret;
 }
 
@@ -102,25 +104,46 @@ _signal_callback_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
    const char *emission = va_arg(*list, const char *);
    const char *source = va_arg(*list, const char *);
    Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb);
-   void *data = va_arg(*list, void *);
    void **ret = va_arg(*list, void **);
-   Edje *ed = _pd;
-
    if (ret) *ret = NULL;
 
+   Edje *ed = _pd;
+   Eina_List *l;
+   Edje_Signal_Callback *escb;
+
    if ((!emission) || (!source) || (!func)) return;
    if (!ed) return;
    if (ed->delete_me) return;
+   EINA_LIST_FOREACH(ed->callbacks, l, escb)
+     {
+       if ((escb->func == func) &&
+           ((!escb->signal && !emission[0]) ||
+             (escb->signal && !strcmp(escb->signal, emission))) &&
+           ((!escb->source && !source[0]) ||
+             (escb->source && !strcmp(escb->source, source))))
+         {
+            void *data;
 
-   emission = eina_stringshare_add(emission);
-   source = eina_stringshare_add(source);
-
-   _edje_signal_callback_disable(ed->callbacks,
-                                 emission, source,
-                                 func, data);
+            data = escb->data;
+            if (ed->walking_callbacks)
+              {
+                 escb->delete_me = EINA_TRUE;
+                 ed->delete_callbacks = EINA_TRUE;
+              }
+            else
+              {
+                 _edje_callbacks_patterns_clean(ed);
 
-   eina_stringshare_del(emission);
-   eina_stringshare_del(source);
+                 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
+                 if (escb->signal) eina_stringshare_del(escb->signal);
+                 if (escb->source) eina_stringshare_del(escb->source);
+                 free(escb);
+              }
+            if (ret) *ret = data;
+             return;
+         }
+     }
+   return;
 }
 
 EAPI void *
@@ -128,10 +151,59 @@ edje_object_signal_callback_del_full(Evas_Object *obj, const char *emission, con
 {
    if (!obj) return NULL;
    void *ret = NULL;
-   eo_do(obj, edje_obj_signal_callback_del(emission, source, func, data, &ret));
+   eo_do(obj, edje_obj_signal_callback_del_full(emission, source, func, data, &ret));
    return ret;
 }
 
+void
+_signal_callback_del_full(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+   const char *emission = va_arg(*list, const char *);
+   const char *source = va_arg(*list, const char *);
+   Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb);
+   void *data = va_arg(*list, void *);
+   void **ret = va_arg(*list, void **);
+   if (ret) *ret = NULL;
+
+   Edje *ed = _pd;
+   Eina_List *l;
+   Edje_Signal_Callback *escb;
+
+   if ((!emission) || (!source) || (!func)) return;
+   if (!ed) return;
+   if (ed->delete_me) return;
+   EINA_LIST_FOREACH(ed->callbacks, l, escb)
+     {
+       if ((escb->func == func) && (escb->data == data) &&
+           ((!escb->signal && !emission[0]) ||
+             (escb->signal && !strcmp(escb->signal, emission))) &&
+           ((!escb->source && !source[0]) ||
+             (escb->source && !strcmp(escb->source, source))))
+         {
+            void *data2;
+
+            data2 = escb->data;
+            if (ed->walking_callbacks)
+              {
+                 escb->delete_me = EINA_TRUE;
+                 ed->delete_callbacks = EINA_TRUE;
+              }
+            else
+              {
+                 _edje_callbacks_patterns_clean(ed);
+
+                 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
+                 if (escb->signal) eina_stringshare_del(escb->signal);
+                 if (escb->source) eina_stringshare_del(escb->source);
+                 free(escb);
+              }
+            if (ret) *ret = data2;
+             return;
+         }
+     }
+   return;
+}
+
 EAPI void
 edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source)
 {
@@ -1207,6 +1279,37 @@ static Eina_Bool _edje_glob_callback(Edje_Program *pr, void *dt)
    return EINA_FALSE;
 }
 
+void
+_edje_callbacks_patterns_clean(Edje *ed)
+{
+   if (ed->walking_callbacks > 0) return;
+
+   _edje_signals_sources_patterns_clean(&ed->patterns.callbacks);
+
+   eina_rbtree_delete(ed->patterns.callbacks.exact_match,
+                     EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
+                     NULL);
+   ed->patterns.callbacks.exact_match = NULL;
+
+   ed->patterns.callbacks.u.callbacks.globing = eina_list_free(ed->patterns.callbacks.u.callbacks.globing);
+}
+
+static void
+_edje_callbacks_patterns_init(Edje *ed)
+{
+   Edje_Signals_Sources_Patterns *ssp = &ed->patterns.callbacks;
+
+   if ((ssp->signals_patterns) || (ssp->sources_patterns) ||
+       (ssp->u.callbacks.globing) || (ssp->exact_match))
+     return;
+
+   ssp->u.callbacks.globing = edje_match_callback_hash_build(ed->callbacks,
+                                                            &ssp->exact_match);
+
+   ssp->signals_patterns = edje_match_callback_signal_init(ssp->u.callbacks.globing);
+   ssp->sources_patterns = edje_match_callback_source_init(ssp->u.callbacks.globing);
+}
+
 /* FIXME: what if we delete the evas object??? */
 void
 _edje_emit_handle(Edje *ed, const char *sig, const char *src,
@@ -1300,11 +1403,13 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src,
 
              if (ed->collection->patterns.table_programs_size > 0)
                {
-                 const Eina_Inarray *match;
+                 const Eina_Array *match;
 #ifdef EDJE_PROGRAM_CACHE
                  const Eina_List *l;
 #endif
                  Edje_Program *pr;
+                 Eina_Array_Iterator iterator;
+                 unsigned int i;       
 
                  if (ed->collection->patterns.programs.u.programs.globing)
                    if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns,
@@ -1315,17 +1420,13 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src,
                                                 _edje_glob_callback,
                                                 &data,
                                                  prop) == 0)
-                      goto break_prog;
+                     goto break_prog;
 
                  match = edje_match_signal_source_hash_get(sig, src,
                                                            ed->collection->patterns.programs.exact_match);
                   if (match)
-                    {
-                       Edje_Program **tpr;
-
-                       EINA_INARRAY_FOREACH(match, tpr)
-                         _edje_glob_callback(*tpr, &data);
-                    }
+                    EINA_ARRAY_ITER_NEXT(match, i, pr, iterator)
+                      _edje_glob_callback(pr, &data);
 
 #ifdef EDJE_PROGRAM_CACHE
                   EINA_LIST_FOREACH(data.matches, l, pr)
@@ -1388,68 +1489,82 @@ edje_object_signal_callback_extra_data_get(void)
 static void
 _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop)
 {
-   const Edje_Signals_Sources_Patterns *ssp;
-   Edje_Signal_Callback_Matches *m;
-   const void **custom_data;
-   Eina_Bool *flags;
-   const Eina_Inarray *match;
-   int r = 1;
+   Eina_List            *l;
 
    if (ed->delete_me) return;
-   if (!ed->callbacks || !ed->callbacks->matches) return;
-
    _edje_ref(ed);
    _edje_freeze(ed);
    _edje_block(ed);
 
-   ssp = _edje_signal_callback_patterns_ref(ed->callbacks);
-
-   m = (Edje_Signal_Callback_Matches*) ed->callbacks->matches;
-   EINA_REFCOUNT_REF(m);
-
-   callback_extra_data = (data) ? data->data : NULL;
-   custom_data = alloca(sizeof (void*) * m->matches_count);
-   memcpy(custom_data, ed->callbacks->custom_data, sizeof (void*) * m->matches_count);
-   flags = alloca(sizeof (Eina_Bool) * m->matches_count);
-   memcpy(flags, ed->callbacks->flags, sizeof (Eina_Bool) * (m->matches_count >> 1));
-
-   if (eina_inarray_count(&ssp->u.callbacks.globing))
-     r = edje_match_callback_exec(ssp,
-                                 m->matches,
-                                 custom_data,
-                                 flags,
-                                  sig,
-                                  src,
-                                  ed,
-                                  prop);
-
-   if (!r)
-     goto break_prog;
-
-   match = edje_match_signal_source_hash_get(sig, src,
-                                             ssp->exact_match);
-   if (match)
-     {
-        const Edje_Signal_Callback_Match *cb;
-        size_t *i;
+   if (ed->just_added_callbacks)
+     _edje_callbacks_patterns_clean(ed);
 
-        EINA_INARRAY_FOREACH(match, i)
-          {
-             cb = &m->matches[*i];
+   ed->walking_callbacks++;
 
-             if ((prop) && (_edje_signal_callback_prop(flags, *i))) continue;
+   if (ed->callbacks)
+     {
+       Edje_Signal_Callback *escb;
+       const Eina_Array *match;
+        Eina_Array_Iterator iterator;
+        unsigned int i;
+        int r = 1;
+        callback_extra_data = (data) ? data->data : NULL;
+
+       _edje_callbacks_patterns_init(ed);
+       if (ed->patterns.callbacks.u.callbacks.globing)
+         r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
+                                      ed->patterns.callbacks.sources_patterns,
+                                      sig,
+                                      src,
+                                      ed->patterns.callbacks.u.callbacks.globing,
+                                      ed,
+                                       prop);
+
+        if (!r)
+          goto break_prog;
 
-             cb->func((void*) custom_data[*i], ed->obj, sig, src);
-             if (_edje_block_break(ed))
-               break;
-          }
+       match = edje_match_signal_source_hash_get(sig, src,
+                                                 ed->patterns.callbacks.exact_match);
+        if (match)
+          EINA_ARRAY_ITER_NEXT(match, i, escb, iterator)
+            {
+               if ((prop) && (escb->propagate)) continue;
+               if ((!escb->just_added) && (!escb->delete_me))
+                 {
+                    escb->func(escb->data, ed->obj, sig, src);
+                    if (_edje_block_break(ed))
+                      break;
+                 }
+            }
      }
+   break_prog:
 
- break_prog:
-   _edje_signal_callback_matches_unref(m);
+   ed->walking_callbacks--;
+   if (!ed->walking_callbacks &&
+       ((ed->delete_callbacks) || (ed->just_added_callbacks)))
+     {
+       ed->delete_callbacks = EINA_FALSE;
+       ed->just_added_callbacks = EINA_FALSE;
+       l = ed->callbacks;
+       while (l)
+         {
+            Edje_Signal_Callback *escb = l->data;
+            Eina_List *next_l = l->next;
 
-   _edje_signal_callback_patterns_unref(ssp);
+            if (escb->just_added)
+              escb->just_added = 0;
+            if (escb->delete_me)
+              {
+                 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
+                 if (escb->signal) eina_stringshare_del(escb->signal);
+                 if (escb->source) eina_stringshare_del(escb->source);
+                 free(escb);
+              }
+            l = next_l;
+         }
 
+        _edje_callbacks_patterns_clean(ed);
+     }
    _edje_unblock(ed);
    _edje_thaw(ed);
    _edje_unref(ed);
diff --git a/src/lib/edje/edje_signal.c b/src/lib/edje/edje_signal.c
deleted file mode 100644 (file)
index 3dfdae1..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-#include <assert.h>
-
-#include "edje_private.h"
-
-#define _DELETE_ME 0x4
-#define _JUST_ADDED 0x2
-#define _PROPAGATE 0x1
-
-static Eina_Hash *signal_match = NULL;
-
-static unsigned int
-_edje_signal_match_key_length(const void *key EINA_UNUSED)
-{
-   return sizeof (Edje_Signal_Callback_Matches);
-}
-
-static int
-_edje_signal_match_key_cmp(const void *key1, int key1_length EINA_UNUSED, const void *key2, int key2_length EINA_UNUSED)
-{
-   const Edje_Signal_Callback_Matches *a = key1;
-   const Edje_Signal_Callback_Matches *b = key2;
-   unsigned int i;
-
-   if (a->matches_count != b->matches_count) return a->matches_count - b->matches_count;
-   for (i = 0; i < a->matches_count; ++i)
-     {
-        if (a->matches[i].signal != b->matches[i].signal) return a->matches[i].signal - b->matches[i].signal;
-        if (a->matches[i].source != b->matches[i].source) return a->matches[i].source - b->matches[i].source;
-        if (a->matches[i].func != b->matches[i].func) return (unsigned char*) a->matches[i].func - (unsigned char*) b->matches[i].func;
-     }
-   return 0;
-}
-
-static int
-_edje_signal_match_key_hash(const void *key, int key_length EINA_UNUSED)
-{
-   const Edje_Signal_Callback_Matches *a = key;
-   unsigned int hash, i;
-
-   hash = eina_hash_int32(&a->matches_count, sizeof (int));
-   for (i = 0; i < a->matches_count; ++i)
-     {
-#ifdef __LP64__
-        hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].signal, sizeof (char *));
-        hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].source, sizeof (char *));
-        hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].func, sizeof (Edje_Signal_Cb));
-#else
-        hash ^= eina_hash_int32((const unsigned int*) a->matches[i].signal, sizeof (char *));
-        hash ^= eina_hash_int32((const unsigned int*) a->matches[i].source, sizeof (char *));
-        hash ^= eina_hash_int32((const unsigned int*) a->matches[i].func, sizeof (Edje_Signal_Cb));
-#endif
-     }
-   return hash;
-}
-
-static const Edje_Signal_Callback_Matches *
-_edje_signal_callback_matches_dup(const Edje_Signal_Callback_Matches *src)
-{
-   Edje_Signal_Callback_Matches *result;
-   unsigned int i;
-
-   result = calloc(1, sizeof (Edje_Signal_Callback_Matches));
-   if (!result) return NULL;
-
-   result->hashed = EINA_FALSE;
-   result->matches = malloc(sizeof (Edje_Signal_Callback_Match) * src->matches_count);
-   result->matches_count = src->matches_count;
-   result->patterns = NULL;
-   EINA_REFCOUNT_REF(result);
-
-   for (i = 0; i < src->matches_count; i++)
-     {
-       result->matches[i].signal = eina_stringshare_ref(src->matches[i].signal);
-       result->matches[i].source = eina_stringshare_ref(src->matches[i].source);
-       result->matches[i].func = src->matches[i].func;
-     }
-
-   return result;
-}
-
-void
-_edje_callbacks_patterns_clean(Edje_Signal_Callback_Group *gp)
-{
-   Edje_Signal_Callback_Matches *tmp;
-
-   assert(EINA_REFCOUNT_GET(gp->matches) == 1);
-   tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-
-   _edje_signal_callback_patterns_unref(tmp->patterns);
-   tmp->patterns = NULL;
-}
-
-static void
-_edje_callbacks_patterns_init(Edje_Signal_Callback_Group *gp)
-{
-   Edje_Signals_Sources_Patterns *ssp;
-   Edje_Signal_Callback_Matches *tmp;
-
-   if (gp->matches->patterns) return ;
-
-   tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-   tmp->patterns = calloc(1, sizeof (Edje_Signals_Sources_Patterns));
-   if (!gp->matches->patterns) return ;
-
-   ssp = gp->matches->patterns;
-   edje_match_callback_hash_build(gp->matches->matches,
-                                 gp->matches->matches_count,
-                                 &ssp->exact_match,
-                                 &ssp->u.callbacks.globing);
-
-   ssp->signals_patterns = edje_match_callback_signal_init(&ssp->u.callbacks.globing, tmp->matches);
-   ssp->sources_patterns = edje_match_callback_source_init(&ssp->u.callbacks.globing, tmp->matches);
-   EINA_REFCOUNT_REF(ssp);
-}
-
-void
-edje_signal_init(void)
-{
-   signal_match = eina_hash_new(_edje_signal_match_key_length,
-                                _edje_signal_match_key_cmp,
-                                _edje_signal_match_key_hash,
-                                NULL,
-                                3);
-}
-
-void
-edje_signal_shutdown(void)
-{
-   // FIXME: iterate and destroy leftover signal matcher
-   eina_hash_free(signal_match);
-}
-
-static void
-_edje_signal_callback_unset(Edje_Signal_Callback_Group *gp, int idx)
-{
-   Edje_Signal_Callback_Match *m;
-
-   m = gp->matches->matches + idx;
-   eina_stringshare_del(m->signal);
-   m->signal = NULL;
-   eina_stringshare_del(m->source);
-   m->source = NULL;
-}
-
-static void
-_edje_signal_callback_set(Edje_Signal_Callback_Group *gp, int idx,
-                          const char *sig, const char *src,
-                          Edje_Signal_Cb func, void *data, Eina_Bool flags)
-{
-   Edje_Signal_Callback_Match *m;
-
-   m = gp->matches->matches + idx;
-   m->signal = eina_stringshare_ref(sig);
-   m->source = eina_stringshare_ref(src);
-   m->func = func;
-
-   gp->custom_data[idx] = data;
-
-   gp->flags[idx >> 1] = (gp->flags[idx >> 1] & (0xF << (((idx & 1) ^ 1) * 4))) |
-     ((flags & 0xF) << ((idx & 1) * 4));
-}
-
-Eina_Bool
-_edje_signal_callback_prop(const Eina_Bool *flags, int i)
-{
-   Eina_Bool b;
-
-   b = flags[i >> 1];
-   return b & (_PROPAGATE << ((i & 1) * 4));
-}
-
-static Edje_Signal_Callback_Group *
-_edje_signal_callback_grow(Edje_Signal_Callback_Group *gp)
-{
-   Edje_Signal_Callback_Matches *tmp;
-   unsigned int c;
-
-   tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-   tmp->matches_count++;
-   tmp->matches = realloc(tmp->matches, sizeof (Edje_Signal_Callback_Match) * tmp->matches_count);
-   gp->custom_data = realloc(gp->custom_data, sizeof (void*) * tmp->matches_count);
-
-   c = ((tmp->matches_count >> 1) | (tmp->matches_count & 1));
-   gp->flags = realloc(gp->flags, sizeof (Edje_Signal_Callback_Group) + c);
-   // We have just expanded by one char, set it to 0
-   if (tmp->matches_count & 1) gp->flags[tmp->matches_count >> 1] = 0;
-
-   return gp;
-}
-
-void
-_edje_signal_callback_push(const Edje_Signal_Callback_Group *cgp,
-                           const char *sig, const char *src,
-                           Edje_Signal_Cb func, void *data, Eina_Bool propagate)
-{
-   Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp;
-   unsigned int i;
-
-   // let's first try to see if we do find an empty matching stop
-   for (i = 0; i < gp->matches->matches_count; i++)
-     if (sig == gp->matches->matches[i].signal &&
-         src == gp->matches->matches[i].source &&
-         func == gp->matches->matches[i].func)
-       {
-          Eina_Bool flags;
-
-          flags = gp->flags[i >> 1] & (0xF << ((i & 1) * 4));
-          if (flags & _DELETE_ME)
-            {
-               _edje_signal_callback_unset(gp, i);
-               _edje_signal_callback_set(gp, i,
-                                         sig, src, func, data,
-                                         (((!!propagate) & 1) | _JUST_ADDED));
-               return ;
-            }
-       }
-
-   if (gp->matches->hashed)
-     {
-        Edje_Signal_Callback_Matches *tmp;
-
-        tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-        if (EINA_REFCOUNT_GET(tmp) == 1)
-          {
-             eina_hash_del(signal_match, tmp, tmp);
-             tmp->hashed = 0;
-          }
-        else
-          {
-             Edje_Signal_Callback_Matches *tmp_dup;
-             tmp_dup = (Edje_Signal_Callback_Matches*) _edje_signal_callback_matches_dup(tmp);
-             if (!tmp_dup) return ;
-             EINA_REFCOUNT_UNREF(tmp)
-               (void) 0; // Nothing to do because the case where refcount == 1 was already handle above.
-             gp->matches = tmp_dup;
-          }
-     }
-
-   // search an empty spot now
-   for (i = 0; i < gp->matches->matches_count; i += 2)
-     if (gp->flags[i >> 1] & (_DELETE_ME | (_DELETE_ME << 4)))
-       {
-          if (gp->flags[i >> 1] & _DELETE_ME)
-            {
-               _edje_signal_callback_unset(gp, i);
-               _edje_signal_callback_set(gp, i,
-                                         sig, src, func, data,
-                                         (((!!propagate) & 1) | _JUST_ADDED));
-               return ;
-            }
-          if (gp->flags[i >> 1] & (_DELETE_ME << 4))
-            {
-               _edje_signal_callback_unset(gp, i + 1);
-               _edje_signal_callback_set(gp, i + 1,
-                                         sig, src, func, data,
-                                         (((!!propagate) & 1) | _JUST_ADDED));
-               return ;
-            }
-       }
-
-   _edje_signal_callback_grow(gp);
-
-   // Set propagate and just_added flags
-   _edje_signal_callback_set(gp, gp->matches->matches_count - 1,
-                             sig, src, func, data, (((!!propagate) & 1) | _JUST_ADDED));
-
-   return ;
-}
-
-const Edje_Signal_Callback_Group *
-_edje_signal_callback_alloc(void)
-{
-   Edje_Signal_Callback_Group *escg;
-   Edje_Signal_Callback_Matches *m;
-
-   escg = calloc(1, sizeof (Edje_Signal_Callback_Group));
-   if (!escg) return NULL;
-
-   m = calloc(1, sizeof (Edje_Signal_Callback_Matches));
-   if (!m)
-     {
-        free(escg);
-        return NULL;
-     }
-
-   EINA_REFCOUNT_REF(m);
-   escg->matches = m;
-
-   return escg;
-}
-
-void
-_edje_signal_callback_matches_unref(Edje_Signal_Callback_Matches *m)
-{
-   EINA_REFCOUNT_UNREF(m)
-     {
-        unsigned int i;
-
-        _edje_signal_callback_patterns_unref(m->patterns);
-
-        if (m->hashed)
-          eina_hash_del(signal_match, m, m);
-      
-        for (i = 0; i < m->matches_count; ++i)
-          {
-             eina_stringshare_del(m->matches[i].signal);
-             eina_stringshare_del(m->matches[i].source);
-          }
-        free(m->matches);
-        free(m);
-     }
-}
-
-void
-_edje_signal_callback_free(const Edje_Signal_Callback_Group *cgp)
-{
-   Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp;
-
-   if (!gp) return ;
-
-   _edje_signal_callback_matches_unref((Edje_Signal_Callback_Matches*) gp->matches);
-   gp->matches = NULL;
-   free(gp->custom_data);
-   free(gp);
-}
-
-void *
-_edje_signal_callback_disable(const Edje_Signal_Callback_Group *cgp,
-                              const char *sig, const char *src,
-                              Edje_Signal_Cb func, void *data)
-{
-   Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp;
-   unsigned int i;
-
-   // FIXME: Shall we check DELETE_ME flags ?
-   for (i = 0; i < gp->matches->matches_count; ++i)
-     {
-        if (sig == gp->matches->matches[i].signal &&
-            src == gp->matches->matches[i].source &&
-            func == gp->matches->matches[i].func &&
-            gp->custom_data[i] == data)
-          {
-             Eina_Bool flags;
-
-             flags = gp->flags[i >> 1] | (_DELETE_ME << ((i & 1) * 4));
-             gp->flags[i >> 1] = flags;
-             return gp->custom_data[i];
-          }
-     }
-
-   if (data == NULL)
-     {
-        for (i = 0; i < gp->matches->matches_count; ++i)
-          {
-             if (sig == gp->matches->matches[i].signal &&
-                 src == gp->matches->matches[i].source &&
-                 func == gp->matches->matches[i].func)
-               {
-                  Eina_Bool flags;
-
-                  flags = gp->flags[i >> 1] | (_DELETE_ME << ((i & 1) * 4));
-                  gp->flags[i >> 1] = flags;
-                  return gp->custom_data[i];
-               }
-          }
-     }
-
-   return NULL;
-}
-
-static void
-_edje_signal_callback_move_last(Edje_Signal_Callback_Group *gp,
-                                int i)
-{
-   Edje_Signal_Callback_Matches *m;
-   int j;
-
-   m = (Edje_Signal_Callback_Matches*) gp->matches;
-
-   for (j = (int) --m->matches_count; j > i; --j)
-     {
-        if (!(gp->flags[j >> 1] & (_DELETE_ME << ((j & 1) * 4))))
-          {
-             m->matches[i].signal = m->matches[j].signal;
-             m->matches[i].source = m->matches[j].source;
-             m->matches[i].func = m->matches[j].func;
-             gp->flags[i] = (gp->flags[i >> 1] & (0xF << (((i & 1) ^ 1) * 4))) |
-               (gp->flags[j >> 1] & (0xF << (((j & 1) * 4))));
-             return ;
-          }
-        --m->matches_count;
-     }
-}
-
-const Edje_Signals_Sources_Patterns *
-_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp)
-{
-   const Edje_Signal_Callback_Matches *m;
-   Edje_Signal_Callback_Matches *tmp;     
-
-   if (gp->matches->hashed)
-     goto got_it;
-
-   m = eina_hash_find(signal_match, gp->matches);
-   if (!m)
-     {
-        tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-        if (!(tmp->patterns && (EINA_REFCOUNT_GET(tmp->patterns) > 1)))
-          {
-             // Let compact it and remove uneeded pattern before building it
-             // We can do that because the custom data are kept local into the matching code.
-             Eina_Bool delete_me = _DELETE_ME | (_DELETE_ME << 4);
-             unsigned int i;
-
-             for (i = 0; i < tmp->matches_count; i += 2)
-               {
-                  if (gp->flags[i >> 1] & delete_me)
-                    {
-                       if (gp->flags[i >> 1] & _DELETE_ME)
-                         {
-                            _edje_signal_callback_move_last((Edje_Signal_Callback_Group*) gp, i);
-                         }
-                       if (i + 1 < gp->matches->matches_count &&
-                           (gp->flags[i >> 1] & (_DELETE_ME << 4)))
-                         {
-                            _edje_signal_callback_move_last((Edje_Signal_Callback_Group*) gp, i + 1);
-                         }
-                    }
-               }
-
-          }
-
-        _edje_signal_callback_patterns_unref(tmp->patterns);
-        tmp->patterns = NULL;
-
-        _edje_callbacks_patterns_init((Edje_Signal_Callback_Group*) gp);
-        eina_hash_add(signal_match, tmp, tmp);
-        tmp->hashed = EINA_TRUE;
-     }
-   else
-     {
-        _edje_signal_callback_matches_unref((Edje_Signal_Callback_Matches*) gp->matches);
-        ((Edje_Signal_Callback_Group*)gp)->matches = m;
-        tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-        EINA_REFCOUNT_REF(tmp);
-     }
-
- got_it:
-   tmp = (Edje_Signal_Callback_Matches*) gp->matches;
-
-   EINA_REFCOUNT_REF(tmp->patterns);
-   return gp->matches->patterns;
-}
-
-void
-_edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp)
-{
-   Edje_Signals_Sources_Patterns *ssp;
-
-   if (!essp) return ;
-
-   ssp = (Edje_Signals_Sources_Patterns*) essp;
-
-   EINA_REFCOUNT_UNREF(ssp)
-   {
-      _edje_signals_sources_patterns_clean(ssp);
-
-      eina_rbtree_delete(ssp->exact_match,
-                         EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
-                         NULL);
-      ssp->exact_match = NULL;
-
-      eina_inarray_flush(&ssp->u.callbacks.globing);
-
-      free(ssp);
-   }
-}
index d31203471fd478afdc9da6480257efcce8f12aed..80951d95bd8dc9edcf674d0e6bbdff106e0561e7 100644 (file)
@@ -480,6 +480,7 @@ _edje_smart_class_constructor(Eo_Class *klass)
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS), _message_signal_process),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD), _signal_callback_add),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), _signal_callback_del),
+        EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL), _signal_callback_del_full),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_EMIT), _signal_emit),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_SET), _play_set),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_GET), _play_get),
@@ -625,6 +626,7 @@ static const Eo_Op_Description op_desc[] = {
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS, "Process an object's message queue."),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD, "Add a callback for an arriving Edje signal, emitted by"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL, "Remove a signal-triggered callback from an object."),
+     EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL, "Unregister/delete a callback set for an arriving Edje"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_EMIT, "Send/emit an Edje signal to a given Edje object"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_SET, "Set the Edje object to playing or paused states."),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_GET, "Get the Edje object's state."),