summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile_Edje.am3
-rw-r--r--src/lib/edje/Edje.h19
-rw-r--r--src/lib/edje/edje_main.c11
-rw-r--r--src/lib/edje/edje_match.c364
-rw-r--r--src/lib/edje/edje_private.h96
-rw-r--r--src/lib/edje/edje_program.c337
-rw-r--r--src/lib/edje/edje_signal.c477
-rw-r--r--src/lib/edje/edje_smart.c2
8 files changed, 889 insertions, 420 deletions
diff --git a/src/Makefile_Edje.am b/src/Makefile_Edje.am
index db4534ac2a..20ec55288b 100644
--- a/src/Makefile_Edje.am
+++ b/src/Makefile_Edje.am
@@ -46,7 +46,8 @@ lib/edje/edje_smart.c \
46lib/edje/edje_text.c \ 46lib/edje/edje_text.c \
47lib/edje/edje_textblock_styles.c \ 47lib/edje/edje_textblock_styles.c \
48lib/edje/edje_util.c \ 48lib/edje/edje_util.c \
49lib/edje/edje_var.c 49lib/edje/edje_var.c \
50lib/edje/edje_signal.c
50 51
51lib_edje_libedje_la_CPPFLAGS = $(EDJE_COMMON_CPPFLAGS) 52lib_edje_libedje_la_CPPFLAGS = $(EDJE_COMMON_CPPFLAGS)
52lib_edje_libedje_la_LIBADD = @EDJE_LIBS@ 53lib_edje_libedje_la_LIBADD = @EDJE_LIBS@
diff --git a/src/lib/edje/Edje.h b/src/lib/edje/Edje.h
index c678ee7872..5a5afe5460 100644
--- a/src/lib/edje/Edje.h
+++ b/src/lib/edje/Edje.h
@@ -893,7 +893,6 @@ enum
893 893
894 EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD, 894 EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD,
895 EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL, 895 EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL,
896 EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL,
897 EDJE_OBJ_SUB_ID_SIGNAL_EMIT, 896 EDJE_OBJ_SUB_ID_SIGNAL_EMIT,
898 EDJE_OBJ_SUB_ID_PLAY_SET, 897 EDJE_OBJ_SUB_ID_PLAY_SET,
899 EDJE_OBJ_SUB_ID_PLAY_GET, 898 EDJE_OBJ_SUB_ID_PLAY_GET,
@@ -2709,23 +2708,7 @@ enum
2709 * 2708 *
2710 * @see edje_object_signal_callback_del 2709 * @see edje_object_signal_callback_del
2711 */ 2710 */
2712#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) 2711#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)
2713
2714/**
2715 * @def edje_obj_signal_callback_del_full
2716 * @since 1.8
2717 *
2718 * @brief Unregister/delete a callback set for an arriving Edje
2719 *
2720 * @param[in] emission
2721 * @param[in] source
2722 * @param[in] func
2723 * @param[in] data
2724 * @param[out] ret
2725 *
2726 * @see edje_object_signal_callback_del_full
2727 */
2728#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)
2729 2712
2730/** 2713/**
2731 * @def edje_obj_signal_emit 2714 * @def edje_obj_signal_emit
diff --git a/src/lib/edje/edje_main.c b/src/lib/edje/edje_main.c
index 42ff7f4c2f..b16836a643 100644
--- a/src/lib/edje/edje_main.c
+++ b/src/lib/edje/edje_main.c
@@ -78,6 +78,7 @@ edje_init(void)
78 _edje_module_init(); 78 _edje_module_init();
79 _edje_message_init(); 79 _edje_message_init();
80 _edje_multisense_init(); 80 _edje_multisense_init();
81 edje_signal_init();
81 82
82 _edje_real_part_mp = eina_mempool_add("chained_mempool", 83 _edje_real_part_mp = eina_mempool_add("chained_mempool",
83 "Edje_Real_Part", NULL, 84 "Edje_Real_Part", NULL,
@@ -147,6 +148,7 @@ _edje_shutdown_core(void)
147 _edje_real_part_state_mp = NULL; 148 _edje_real_part_state_mp = NULL;
148 _edje_real_part_mp = NULL; 149 _edje_real_part_mp = NULL;
149 150
151 edje_signal_shutdown();
150 _edje_multisense_shutdown(); 152 _edje_multisense_shutdown();
151 _edje_message_shutdown(); 153 _edje_message_shutdown();
152 _edje_module_shutdown(); 154 _edje_module_shutdown();
@@ -242,7 +244,6 @@ _edje_del(Edje *ed)
242{ 244{
243 Edje_Running_Program *runp; 245 Edje_Running_Program *runp;
244 Edje_Pending_Program *pp; 246 Edje_Pending_Program *pp;
245 Edje_Signal_Callback *escb;
246 Edje_Text_Class *tc; 247 Edje_Text_Class *tc;
247 Edje_Text_Insert_Filter_Callback *cb; 248 Edje_Text_Insert_Filter_Callback *cb;
248 249
@@ -252,7 +253,7 @@ _edje_del(Edje *ed)
252 return; 253 return;
253 } 254 }
254 _edje_message_del(ed); 255 _edje_message_del(ed);
255 _edje_callbacks_patterns_clean(ed); 256 _edje_signal_callback_free(ed->callbacks);
256 _edje_file_del(ed); 257 _edje_file_del(ed);
257 if (ed->path) eina_stringshare_del(ed->path); 258 if (ed->path) eina_stringshare_del(ed->path);
258 if (ed->group) eina_stringshare_del(ed->group); 259 if (ed->group) eina_stringshare_del(ed->group);
@@ -267,12 +268,6 @@ _edje_del(Edje *ed)
267 free(runp); 268 free(runp);
268 EINA_LIST_FREE(ed->pending_actions, pp) 269 EINA_LIST_FREE(ed->pending_actions, pp)
269 free(pp); 270 free(pp);
270 EINA_LIST_FREE(ed->callbacks, escb)
271 {
272 if (escb->signal) eina_stringshare_del(escb->signal);
273 if (escb->source) eina_stringshare_del(escb->source);
274 free(escb);
275 }
276 eina_hash_free(ed->color_classes); 271 eina_hash_free(ed->color_classes);
277 EINA_LIST_FREE(ed->text_classes, tc) 272 EINA_LIST_FREE(ed->text_classes, tc)
278 { 273 {
diff --git a/src/lib/edje/edje_match.c b/src/lib/edje/edje_match.c
index 558d982ff4..f80af37e98 100644
--- a/src/lib/edje/edje_match.c
+++ b/src/lib/edje/edje_match.c
@@ -5,20 +5,20 @@
5typedef struct _Edje_State Edje_State; 5typedef struct _Edje_State Edje_State;
6struct _Edje_State 6struct _Edje_State
7{ 7{
8 size_t idx; 8 unsigned int idx;
9 size_t pos; 9 unsigned int pos;
10}; 10};
11 11
12struct _Edje_States 12struct _Edje_States
13{ 13{
14 size_t size; 14 unsigned int size;
15 Edje_State *states; 15 Edje_State *states;
16 Eina_Bool *has; 16 Eina_Bool *has;
17}; 17};
18 18
19static void 19static void
20_edje_match_states_free(Edje_States *states, 20_edje_match_states_free(Edje_States *states,
21 size_t states_size) 21 unsigned int states_size)
22{ 22{
23 (void) states_size; 23 (void) states_size;
24 free(states); 24 free(states);
@@ -36,15 +36,15 @@ _edje_match_states_alloc(Edje_Patterns *ppat, int n)
36{ 36{
37 Edje_States *l; 37 Edje_States *l;
38 38
39 const size_t patterns_size = ppat->patterns_size; 39 const unsigned int patterns_size = ppat->patterns_size;
40 const size_t patterns_max_length = ppat->max_length; 40 const unsigned int patterns_max_length = ppat->max_length;
41 41
42 const size_t array_len = (patterns_max_length + 1) * patterns_size; 42 const unsigned int array_len = (patterns_max_length + 1) * patterns_size;
43 43
44 size_t states_size; 44 unsigned int states_size;
45 size_t has_size; 45 unsigned int has_size;
46 size_t states_has_size; 46 unsigned int states_has_size;
47 size_t struct_size; 47 unsigned int struct_size;
48 48
49 unsigned char *states; 49 unsigned char *states;
50 unsigned char *has; 50 unsigned char *has;
@@ -88,12 +88,12 @@ _edje_match_states_alloc(Edje_Patterns *ppat, int n)
88} 88}
89 89
90static void 90static void
91_edje_match_states_insert(Edje_States *list, 91_edje_match_states_insert(Edje_States *list,
92 size_t patterns_max_length, 92 unsigned int patterns_max_length,
93 size_t idx, 93 unsigned int idx,
94 size_t pos) 94 unsigned int pos)
95{ 95{
96 size_t i; 96 unsigned int i;
97 97
98 i = (idx * (patterns_max_length + 1)) + pos; 98 i = (idx * (patterns_max_length + 1)) + pos;
99 99
@@ -112,8 +112,8 @@ _edje_match_states_insert(Edje_States *list,
112 112
113static void 113static void
114_edje_match_states_clear(Edje_States *list, 114_edje_match_states_clear(Edje_States *list,
115 EINA_UNUSED size_t patterns_size, 115 EINA_UNUSED unsigned int patterns_size,
116 EINA_UNUSED size_t patterns_max_length) 116 EINA_UNUSED unsigned int patterns_max_length)
117{ 117{
118 list->size = 0; 118 list->size = 0;
119} 119}
@@ -127,7 +127,7 @@ enum status
127 patterns_syntax_error = 2 127 patterns_syntax_error = 2
128}; 128};
129 129
130static size_t 130static unsigned int
131_edje_match_patterns_exec_class_token(enum status *status, 131_edje_match_patterns_exec_class_token(enum status *status,
132 const char *cl_tok, 132 const char *cl_tok,
133 char c) 133 char c)
@@ -152,7 +152,7 @@ _edje_match_patterns_exec_class_token(enum status *status,
152} 152}
153 153
154static Edje_Match_Error 154static Edje_Match_Error
155_edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret) 155_edje_match_patterns_exec_class_complement(const char *cl_tok, unsigned int *ret)
156{ 156{
157 switch (*cl_tok) 157 switch (*cl_tok)
158 { 158 {
@@ -170,13 +170,13 @@ _edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret)
170} 170}
171 171
172static Edje_Match_Error 172static Edje_Match_Error
173_edje_match_patterns_exec_class(const char *cl, 173_edje_match_patterns_exec_class(const char *cl,
174 char c, 174 char c,
175 size_t *ret) 175 unsigned int *ret)
176{ 176{
177 enum status status = patterns_not_found; 177 enum status status = patterns_not_found;
178 int pos = 1; 178 int pos = 1;
179 size_t neg; 179 size_t neg;
180 180
181 if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK) 181 if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK)
182 return EDJE_MATCH_SYNTAX_ERROR; 182 return EDJE_MATCH_SYNTAX_ERROR;
@@ -201,9 +201,9 @@ _edje_match_patterns_exec_class(const char *cl,
201} 201}
202 202
203static Edje_Match_Error 203static Edje_Match_Error
204_edje_match_patterns_exec_token(const char *tok, 204_edje_match_patterns_exec_token(const char *tok,
205 char c, 205 char c,
206 size_t *ret) 206 unsigned int *ret)
207{ 207{
208 switch (*tok) 208 switch (*tok)
209 { 209 {
@@ -229,11 +229,11 @@ _edje_match_patterns_exec_token(const char *tok,
229} 229}
230 230
231static void 231static void
232_edje_match_patterns_exec_init_states(Edje_States *states, 232_edje_match_patterns_exec_init_states(Edje_States *states,
233 size_t patterns_size, 233 unsigned int patterns_size,
234 size_t patterns_max_length) 234 unsigned int patterns_max_length)
235{ 235{
236 size_t i; 236 unsigned int i;
237 237
238 states->size = patterns_size; 238 states->size = patterns_size;
239 239
@@ -251,8 +251,8 @@ _edje_match_patterns_exec_init_states(Edje_States *states,
251 Edje_Patterns* \ 251 Edje_Patterns* \
252 Func(const Eina_List *lst) \ 252 Func(const Eina_List *lst) \
253 { \ 253 { \
254 Edje_Patterns *r; \ 254 Edje_Patterns *r; \
255 size_t i; \ 255 unsigned int i; \
256 \ 256 \
257 if (!lst || eina_list_count(lst) <= 0) \ 257 if (!lst || eina_list_count(lst) <= 0) \
258 return NULL; \ 258 return NULL; \
@@ -273,7 +273,7 @@ _edje_match_patterns_exec_init_states(Edje_States *states,
273 { \ 273 { \
274 const char *str; \ 274 const char *str; \
275 Type *data; \ 275 Type *data; \
276 size_t j; \ 276 unsigned int j; \
277 int special = 0; \ 277 int special = 0; \
278 \ 278 \
279 data = eina_list_data_get(lst); \ 279 data = eina_list_data_get(lst); \
@@ -318,8 +318,8 @@ _edje_match_patterns_exec_init_states(Edje_States *states,
318 Edje_Patterns* \ 318 Edje_Patterns* \
319 Func(Type * const *lst, unsigned int count) \ 319 Func(Type * const *lst, unsigned int count) \
320 { \ 320 { \
321 Edje_Patterns *r; \ 321 Edje_Patterns *r; \
322 size_t i; \ 322 unsigned int i; \
323 \ 323 \
324 if (!lst || count == 0) \ 324 if (!lst || count == 0) \
325 return NULL; \ 325 return NULL; \
@@ -339,7 +339,7 @@ _edje_match_patterns_exec_init_states(Edje_States *states,
339 for (i = 0; i < count; ++i) \ 339 for (i = 0; i < count; ++i) \
340 { \ 340 { \
341 const char *str; \ 341 const char *str; \
342 size_t j; \ 342 unsigned int j; \
343 int special = 0; \ 343 int special = 0; \
344 \ 344 \
345 if (!lst[i]) \ 345 if (!lst[i]) \
@@ -377,6 +377,66 @@ _edje_match_patterns_exec_init_states(Edje_States *states,
377 return r; \ 377 return r; \
378 } 378 }
379 379
380#define EDJE_MATCH_INIT_INARRAY(Func, Source, Show) \
381 Edje_Patterns* \
382 Func(const Eina_Inarray *array, const Edje_Signal_Callback_Match *matches) \
383 { \
384 Edje_Patterns *r; \
385 int *it; \
386 unsigned int i = 0; \
387 \
388 if (!matches) \
389 return NULL; \
390 \
391 r = malloc(sizeof (Edje_Patterns) + \
392 eina_inarray_count(array) \
393 * sizeof(*r->finals) \
394 * sizeof(*r->patterns)); \
395 if (!r) return NULL; \
396 \
397 r->ref = 1; \
398 r->delete_me = EINA_FALSE; \
399 r->patterns_size = eina_inarray_count(array); \
400 r->max_length = 0; \
401 r->patterns = (const char **) r->finals + r->patterns_size + 1; \
402 \
403 EINA_INARRAY_FOREACH(array, it) \
404 { \
405 const char *str; \
406 unsigned int j; \
407 int special = 0; \
408 \
409 str = (matches + *it)->Source; \
410 if (!str) str = ""; \
411 r->patterns[i] = str; \
412 \
413 if (Show) \
414 INF("%lu [%s]", (unsigned long)i, str); \
415 \
416 r->finals[i] = 0; \
417 for (j = 0; str[j]; ++j) \
418 if (str[j] != '*') \
419 { \
420 r->finals[i] = j + 1; \
421 special++; \
422 } \
423 j += special ? special + 1 : 0; \
424 \
425 if (j > r->max_length) \
426 r->max_length = j; \
427 \
428 i++; \
429 } \
430 \
431 if (!_edje_match_states_alloc(r, 2)) \
432 { \
433 free(r); \
434 return NULL; \
435 } \
436 \
437 return r; \
438 }
439
380EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init, 440EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init,
381 Edje_Part_Collection_Directory_Entry, 441 Edje_Part_Collection_Directory_Entry,
382 entry, 0); 442 entry, 0);
@@ -386,18 +446,16 @@ EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init,
386EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init, 446EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init,
387 Edje_Program, 447 Edje_Program,
388 source, 0); 448 source, 0);
389EDJE_MATCH_INIT_LIST(edje_match_callback_signal_init, 449EDJE_MATCH_INIT_INARRAY(edje_match_callback_signal_init,
390 Edje_Signal_Callback, 450 signal, 0);
391 signal, 0); 451EDJE_MATCH_INIT_INARRAY(edje_match_callback_source_init,
392EDJE_MATCH_INIT_LIST(edje_match_callback_source_init, 452 source, 0);
393 Edje_Signal_Callback,
394 source, 0);
395 453
396static Eina_Bool 454static Eina_Bool
397_edje_match_collection_dir_exec_finals(const size_t *finals, 455_edje_match_collection_dir_exec_finals(const unsigned int *finals,
398 const Edje_States *states) 456 const Edje_States *states)
399{ 457{
400 size_t i; 458 unsigned int i;
401 459
402 for (i = 0; i < states->size; ++i) 460 for (i = 0; i < states->size; ++i)
403 { 461 {
@@ -408,17 +466,17 @@ _edje_match_collection_dir_exec_finals(const size_t *finals,
408} 466}
409 467
410static Eina_Bool 468static Eina_Bool
411edje_match_programs_exec_check_finals(const size_t *signal_finals, 469edje_match_programs_exec_check_finals(const unsigned int *signal_finals,
412 const size_t *source_finals, 470 const unsigned int *source_finals,
413 const Edje_States *signal_states, 471 const Edje_States *signal_states,
414 const Edje_States *source_states, 472 const Edje_States *source_states,
415 Edje_Program **programs, 473 Edje_Program **programs,
416 Eina_Bool (*func)(Edje_Program *pr, void *data), 474 Eina_Bool (*func)(Edje_Program *pr, void *data),
417 void *data, 475 void *data,
418 Eina_Bool prop EINA_UNUSED) 476 Eina_Bool prop EINA_UNUSED)
419{ 477{
420 size_t i; 478 unsigned int i;
421 size_t j; 479 unsigned int j;
422 480
423 /* when not enought memory, they could be NULL */ 481 /* when not enought memory, they could be NULL */
424 if (!signal_finals || !source_finals) return EINA_TRUE; 482 if (!signal_finals || !source_finals) return EINA_TRUE;
@@ -449,61 +507,59 @@ edje_match_programs_exec_check_finals(const size_t *signal_finals,
449} 507}
450 508
451static int 509static int
452edje_match_callback_exec_check_finals(const Edje_Patterns *signal_ppat, 510edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns *ssp,
453 const Edje_Patterns *source_ppat, 511 const Edje_Signal_Callback_Match *matches,
454 const size_t *signal_finals, 512 const void **custom_data,
455 const size_t *source_finals, 513 const Eina_Bool *flags,
456 const Edje_States *signal_states, 514 const Edje_States *signal_states,
457 const Edje_States *source_states, 515 const Edje_States *source_states,
458 const char *sig, 516 const char *sig,
459 const char *source, 517 const char *source,
460 Eina_List *callbacks,
461 Edje *ed, 518 Edje *ed,
462 Eina_Bool prop 519 Eina_Bool prop)
463 )
464{ 520{
465 Edje_Signal_Callback *escb; 521 const Edje_Signal_Callback_Match *cb;
466 Eina_Array run; 522 Eina_Array run;
467 size_t i; 523 unsigned int i;
468 size_t j; 524 unsigned int j;
469 int r = 1; 525 int r = 1;
470 526
471 eina_array_step_set(&run, sizeof (Eina_Array), 4); 527 eina_array_step_set(&run, sizeof (Eina_Array), 4);
472 528
473 for (i = 0; i < signal_states->size; ++i) 529 for (i = 0; i < signal_states->size; ++i)
530 if (signal_states->states[i].pos >= ssp->signals_patterns->finals[signal_states->states[i].idx])
531 {
532 for (j = 0; j < source_states->size; ++j)
533 {
534 if (signal_states->states[i].idx == source_states->states[j].idx
535 && source_states->states[j].pos >= ssp->sources_patterns->finals[source_states->states[j].idx])
536 {
537 int *e;
538
539 e = eina_inarray_nth(&ssp->u.callbacks.globing, signal_states->states[i].idx);
540
541 cb = &matches[*e];
542 if (cb)
543 {
544 if ((prop) && _edje_signal_callback_prop(flags, *e)) continue;
545 eina_array_push(&run, cb);
546 r = 2;
547 }
548 }
549 }
550 }
551
552 while ((cb = eina_array_pop(&run)))
474 { 553 {
475 if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx]) 554 int idx = cb - matches;
476 {
477 for (j = 0; j < source_states->size; ++j)
478 {
479 if (signal_states->states[i].idx == source_states->states[j].idx
480 && source_states->states[j].pos >= source_finals[source_states->states[j].idx])
481 {
482 escb = eina_list_nth(callbacks, signal_states->states[i].idx);
483 if (escb)
484 {
485 if ((prop) && (escb->propagate)) continue;
486 if ((!escb->just_added)
487 && (!escb->delete_me))
488 {
489 eina_array_push(&run, escb);
490 r = 2;
491 }
492 }
493 }
494 }
495 }
496 }
497 555
498 while ((escb = eina_array_pop(&run))) 556 cb->func((void*) custom_data[idx], ed->obj, sig, source);
499 {
500 escb->func(escb->data, ed->obj, sig, source);
501 if (_edje_block_break(ed)) 557 if (_edje_block_break(ed))
502 { 558 {
503 r = 0; 559 r = 0;
504 break; 560 break;
505 } 561 }
506 if ((signal_ppat->delete_me) || (source_ppat->delete_me)) 562 if ((ssp->signals_patterns->delete_me) || (ssp->sources_patterns->delete_me))
507 { 563 {
508 r = 0; 564 r = 0;
509 break; 565 break;
@@ -526,14 +582,14 @@ _edje_match_fn(const Edje_Patterns *ppat,
526 582
527 for (c = string; *c && states->size; ++c) 583 for (c = string; *c && states->size; ++c)
528 { 584 {
529 size_t i; 585 unsigned int i;
530 586
531 _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length); 587 _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
532 588
533 for (i = 0; i < states->size; ++i) 589 for (i = 0; i < states->size; ++i)
534 { 590 {
535 const size_t idx = states->states[i].idx; 591 const unsigned int idx = states->states[i].idx;
536 const size_t pos = states->states[i].pos; 592 const unsigned int pos = states->states[i].pos;
537 593
538 if (!ppat->patterns[idx][pos]) 594 if (!ppat->patterns[idx][pos])
539 continue; 595 continue;
@@ -544,7 +600,7 @@ _edje_match_fn(const Edje_Patterns *ppat,
544 } 600 }
545 else 601 else
546 { 602 {
547 size_t m; 603 unsigned int m;
548 604
549 if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos, 605 if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
550 *c, 606 *c,
@@ -626,50 +682,49 @@ edje_match_programs_exec(const Edje_Patterns *ppat_signal,
626} 682}
627 683
628int 684int
629edje_match_callback_exec(Edje_Patterns *ppat_signal, 685edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp,
630 Edje_Patterns *ppat_source, 686 const Edje_Signal_Callback_Match *matches,
631 const char *sig, 687 const void **custom_data,
632 const char *source, 688 const Eina_Bool *flags,
633 Eina_List *callbacks, 689 const char *sig,
634 Edje *ed, 690 const char *source,
635 Eina_Bool prop 691 Edje *ed,
636 ) 692 Eina_Bool prop)
637{ 693{
638 Edje_States *signal_result; 694 Edje_States *signal_result;
639 Edje_States *source_result; 695 Edje_States *source_result;
640 int r = 0; 696 int r = 0;
641 697
642 /* under high memory presure, they could be NULL */ 698 /* under high memory presure, they could be NULL */
643 if (!ppat_source || !ppat_signal) return 0; 699 if (!ssp->sources_patterns || !ssp->signals_patterns) return 0;
644 700
645 ppat_signal->ref++; 701 ssp->signals_patterns->ref++;
646 ppat_source->ref++; 702 ssp->sources_patterns->ref++;
647 _edje_match_patterns_exec_init_states(ppat_signal->states, 703 _edje_match_patterns_exec_init_states(ssp->signals_patterns->states,
648 ppat_signal->patterns_size, 704 ssp->signals_patterns->patterns_size,
649 ppat_signal->max_length); 705 ssp->signals_patterns->max_length);
650 _edje_match_patterns_exec_init_states(ppat_source->states, 706 _edje_match_patterns_exec_init_states(ssp->sources_patterns->states,
651 ppat_source->patterns_size, 707 ssp->sources_patterns->patterns_size,
652 ppat_source->max_length); 708 ssp->sources_patterns->max_length);
653 709
654 signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states); 710 signal_result = _edje_match_fn(ssp->signals_patterns, sig, ssp->signals_patterns->states);
655 source_result = _edje_match_fn(ppat_source, source, ppat_source->states); 711 source_result = _edje_match_fn(ssp->sources_patterns, source, ssp->sources_patterns->states);
656 712
657 if (signal_result && source_result) 713 if (signal_result && source_result)
658 r = edje_match_callback_exec_check_finals(ppat_signal, 714 r = edje_match_callback_exec_check_finals(ssp,
659 ppat_source, 715 matches,
660 ppat_signal->finals, 716 custom_data,
661 ppat_source->finals, 717 flags,
662 signal_result, 718 signal_result,
663 source_result, 719 source_result,
664 sig, 720 sig,
665 source, 721 source,
666 callbacks, 722 ed,
667 ed, 723 prop);
668 prop); 724 ssp->signals_patterns->ref--;
669 ppat_signal->ref--; 725 ssp->sources_patterns->ref--;
670 ppat_source->ref--; 726 if (ssp->signals_patterns->ref <= 0) edje_match_patterns_free(ssp->signals_patterns);
671 if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal); 727 if (ssp->sources_patterns->ref <= 0) edje_match_patterns_free(ssp->sources_patterns);
672 if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source);
673 return r; 728 return r;
674} 729}
675 730
@@ -750,13 +805,13 @@ edje_match_program_hash_build(Edje_Program * const *programs,
750 805
751 item->signal = programs[i]->signal; 806 item->signal = programs[i]->signal;
752 item->source = programs[i]->source; 807 item->source = programs[i]->source;
753 eina_array_step_set(&item->list, sizeof (Eina_Array), 8); 808 eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (void*), 8);
754 809
755 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), 810 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
756 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); 811 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
757 } 812 }
758 813
759 eina_array_push(&item->list, programs[i]); 814 eina_inarray_push(&item->list, &programs[i]);
760 } 815 }
761 else 816 else
762 result = eina_list_prepend(result, programs[i]); 817 result = eina_list_prepend(result, programs[i]);
@@ -766,48 +821,51 @@ edje_match_program_hash_build(Edje_Program * const *programs,
766 return result; 821 return result;
767} 822}
768 823
769Eina_List * 824void
770edje_match_callback_hash_build(const Eina_List *callbacks, 825edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callbacks,
771 Eina_Rbtree **tree) 826 int callbacks_count,
827 Eina_Rbtree **tree,
828 Eina_Inarray *result)
772{ 829{
773 Eina_List *result = NULL;
774 Eina_Rbtree *new = NULL; 830 Eina_Rbtree *new = NULL;
775 Edje_Signal_Callback *callback; 831 int i;
776 const Eina_List *l; 832
833 eina_inarray_step_set(result, sizeof (Eina_Inarray), sizeof (int), 8);
777 834
778 EINA_LIST_FOREACH(callbacks, l, callback) 835 for (i = 0; i < callbacks_count; ++i, ++callbacks)
779 { 836 {
780 if (callback->signal && !strpbrk(callback->signal, "*?[\\") 837 if (callbacks->signal && !strpbrk(callbacks->signal, "*?[\\")
781 && callback->source && !strpbrk(callback->source, "*?[\\")) 838 && callbacks->source && !strpbrk(callbacks->source, "*?[\\"))
782 { 839 {
783 Edje_Signal_Source_Char *item; 840 Edje_Signal_Source_Char *item;
784 841
785 item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callback->signal, 0, 842 item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callbacks->signal, 0,
786 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source); 843 EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callbacks->source);
787 if (!item) 844 if (!item)
788 { 845 {
789 item = malloc(sizeof (Edje_Signal_Source_Char)); 846 item = malloc(sizeof (Edje_Signal_Source_Char));
790 if (!item) continue; 847 if (!item) continue;
791 848
792 item->signal = callback->signal; 849 item->signal = callbacks->signal;
793 item->source = callback->source; 850 item->source = callbacks->source;
794 eina_array_step_set(&item->list, sizeof (Eina_Array), 8); 851 eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (int), 8);
795 852
796 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), 853 new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item),
797 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); 854 EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL);
798 } 855 }
799 856
800 eina_array_push(&item->list, callback); 857 eina_inarray_push(&item->list, &i);
801 } 858 }
802 else 859 else
803 result = eina_list_prepend(result, callback); 860 {
861 eina_inarray_push(result, &i);
862 }
804 } 863 }
805 864
806 *tree = new; 865 *tree = new;
807 return result;
808} 866}
809 867
810const Eina_Array * 868const Eina_Inarray *
811edje_match_signal_source_hash_get(const char *sig, 869edje_match_signal_source_hash_get(const char *sig,
812 const char *source, 870 const char *source,
813 const Eina_Rbtree *tree) 871 const Eina_Rbtree *tree)
@@ -824,6 +882,6 @@ edje_match_signal_source_hash_get(const char *sig,
824void 882void
825edje_match_signal_source_free(Edje_Signal_Source_Char *key, EINA_UNUSED void *data) 883edje_match_signal_source_free(Edje_Signal_Source_Char *key, EINA_UNUSED void *data)
826{ 884{
827 eina_array_flush(&key->list); 885 eina_inarray_flush(&key->list);
828 free(key); 886 free(key);
829} 887}
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index 42dc6ba69d..0bfbdfe69b 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -323,6 +323,10 @@ typedef struct _Edje_Signal_Source_Char Edje_Signal_Source_Char;
323typedef struct _Edje_Text_Insert_Filter_Callback Edje_Text_Insert_Filter_Callback; 323typedef struct _Edje_Text_Insert_Filter_Callback Edje_Text_Insert_Filter_Callback;
324typedef struct _Edje_Markup_Filter_Callback Edje_Markup_Filter_Callback; 324typedef struct _Edje_Markup_Filter_Callback Edje_Markup_Filter_Callback;
325typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns; 325typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns;
326typedef struct _Edje_Signal_Callback_Group Edje_Signal_Callback_Group;
327typedef struct _Edje_Signal_Callback_Match Edje_Signal_Callback_Match;
328typedef struct _Edje_Signal_Callback_Matches Edje_Signal_Callback_Matches;
329typedef struct _Edje_Signal_Callback_Custom Edje_Signal_Callback_Custom;
326 330
327#define EDJE_INF_MAX_W 100000 331#define EDJE_INF_MAX_W 100000
328#define EDJE_INF_MAX_H 100000 332#define EDJE_INF_MAX_H 100000
@@ -772,6 +776,7 @@ struct _Edje_Part_Limit
772 776
773struct _Edje_Signals_Sources_Patterns 777struct _Edje_Signals_Sources_Patterns
774{ 778{
779 EINA_REFCOUNT;
775 Edje_Patterns *signals_patterns; 780 Edje_Patterns *signals_patterns;
776 Edje_Patterns *sources_patterns; 781 Edje_Patterns *sources_patterns;
777 782
@@ -783,11 +788,39 @@ struct _Edje_Signals_Sources_Patterns
783 unsigned int count; 788 unsigned int count;
784 } programs; 789 } programs;
785 struct { 790 struct {
786 Eina_List *globing; 791 Eina_Inarray globing;
787 } callbacks; 792 } callbacks;
788 } u; 793 } u;
789}; 794};
790 795
796struct _Edje_Signal_Callback_Match
797{
798 const char *signal;
799 const char *source;
800 Edje_Signal_Cb func;
801};
802
803struct _Edje_Signal_Callback_Matches
804{
805 Edje_Signal_Callback_Match *matches;
806
807 Edje_Signals_Sources_Patterns *patterns;
808
809 unsigned int matches_count;
810 EINA_REFCOUNT;
811
812 Eina_Bool hashed : 1;
813};
814
815struct _Edje_Signal_Callback_Group
816{
817 const Edje_Signal_Callback_Matches *matches;
818
819 void **custom_data;
820
821 Eina_Bool *flags; /* 4 bits per custom data (delete_me, just_added, propagate) */
822};
823
791/*----------*/ 824/*----------*/
792 825
793struct _Edje_Part_Collection 826struct _Edje_Part_Collection
@@ -1189,7 +1222,7 @@ struct _Edje_Signal_Source_Char
1189 const char *signal; 1222 const char *signal;
1190 const char *source; 1223 const char *source;
1191 1224
1192 Eina_Array list; 1225 Eina_Inarray list;
1193}; 1226};
1194 1227
1195struct _Edje 1228struct _Edje
@@ -1207,7 +1240,6 @@ struct _Edje
1207 Edje_File *file; /* the file the data comes form */ 1240 Edje_File *file; /* the file the data comes form */
1208 Edje_Part_Collection *collection; /* the description being used */ 1241 Edje_Part_Collection *collection; /* the description being used */
1209 Eina_List *actions; /* currently running actions */ 1242 Eina_List *actions; /* currently running actions */
1210 Eina_List *callbacks;
1211 Eina_List *pending_actions; 1243 Eina_List *pending_actions;
1212 Eina_Hash *color_classes; 1244 Eina_Hash *color_classes;
1213 Eina_List *text_classes; 1245 Eina_List *text_classes;
@@ -1230,9 +1262,7 @@ struct _Edje
1230 1262
1231 Edje_Perspective *persp; 1263 Edje_Perspective *persp;
1232 1264
1233 struct { 1265 const Edje_Signal_Callback_Group *callbacks;
1234 Edje_Signals_Sources_Patterns callbacks;
1235 } patterns;
1236 1266
1237 struct { 1267 struct {
1238 Edje_Text_Change_Cb func; 1268 Edje_Text_Change_Cb func;
@@ -1789,8 +1819,10 @@ Edje_Patterns *edje_match_programs_signal_init(Edje_Program * const *array,
1789 unsigned int count); 1819 unsigned int count);
1790Edje_Patterns *edje_match_programs_source_init(Edje_Program * const *array, 1820Edje_Patterns *edje_match_programs_source_init(Edje_Program * const *array,
1791 unsigned int count); 1821 unsigned int count);
1792Edje_Patterns *edje_match_callback_signal_init(const Eina_List *lst); 1822Edje_Patterns *edje_match_callback_signal_init(const Eina_Inarray *lst,
1793Edje_Patterns *edje_match_callback_source_init(const Eina_List *lst); 1823 const Edje_Signal_Callback_Match *matches);
1824Edje_Patterns *edje_match_callback_source_init(const Eina_Inarray *lst,
1825 const Edje_Signal_Callback_Match *matches);
1794 1826
1795Eina_Bool edje_match_collection_dir_exec(const Edje_Patterns *ppat, 1827Eina_Bool edje_match_collection_dir_exec(const Edje_Patterns *ppat,
1796 const char *string); 1828 const char *string);
@@ -1802,25 +1834,29 @@ Eina_Bool edje_match_programs_exec(const Edje_Patterns *ppat_signal,
1802 Eina_Bool (*func)(Edje_Program *pr, void *data), 1834 Eina_Bool (*func)(Edje_Program *pr, void *data),
1803 void *data, 1835 void *data,
1804 Eina_Bool prop); 1836 Eina_Bool prop);
1805int edje_match_callback_exec(Edje_Patterns *ppat_signal, 1837int edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp,
1806 Edje_Patterns *ppat_source, 1838 const Edje_Signal_Callback_Match *matches,
1807 const char *signal, 1839 const void **custom_data,
1808 const char *source, 1840 const Eina_Bool *flags,
1809 Eina_List *callbacks, 1841 const char *sig,
1810 Edje *ed, 1842 const char *source,
1811 Eina_Bool prop); 1843 Edje *ed,
1844 Eina_Bool prop);
1812 1845
1813void edje_match_patterns_free(Edje_Patterns *ppat); 1846void edje_match_patterns_free(Edje_Patterns *ppat);
1814 1847
1815Eina_List *edje_match_program_hash_build(Edje_Program * const * programs, 1848Eina_List *edje_match_program_hash_build(Edje_Program * const * programs,
1816 unsigned int count, 1849 unsigned int count,
1817 Eina_Rbtree **tree); 1850 Eina_Rbtree **tree);
1818Eina_List *edje_match_callback_hash_build(const Eina_List *callbacks, 1851void edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callback,
1819 Eina_Rbtree **tree); 1852 int callbacks_count,
1820const Eina_Array *edje_match_signal_source_hash_get(const char *signal, 1853 Eina_Rbtree **tree,
1821 const char *source, 1854 Eina_Inarray *result);
1822 const Eina_Rbtree *tree); 1855const Eina_Inarray *edje_match_signal_source_hash_get(const char *signal,
1856 const char *source,
1857 const Eina_Rbtree *tree);
1823void edje_match_signal_source_free(Edje_Signal_Source_Char *key, void *data); 1858void edje_match_signal_source_free(Edje_Signal_Source_Char *key, void *data);
1859void _edje_signal_callback_matches_unref(Edje_Signal_Callback_Matches *m);
1824 1860
1825// FIXME remove below 3 eapi decls when edje_convert goes 1861// FIXME remove below 3 eapi decls when edje_convert goes
1826EAPI void _edje_edd_init(void); 1862EAPI void _edje_edd_init(void);
@@ -1881,6 +1917,16 @@ void _edje_callbacks_focus_add(Evas_Object *obj, Edje *ed, Edje_Real_Part *rp);
1881void _edje_callbacks_del(Evas_Object *obj, Edje *ed); 1917void _edje_callbacks_del(Evas_Object *obj, Edje *ed);
1882void _edje_callbacks_focus_del(Evas_Object *obj, Edje *ed); 1918void _edje_callbacks_focus_del(Evas_Object *obj, Edje *ed);
1883 1919
1920const Edje_Signal_Callback_Group *_edje_signal_callback_alloc(void);
1921void _edje_signal_callback_free(const Edje_Signal_Callback_Group *cgp);
1922void _edje_signal_callback_push(const Edje_Signal_Callback_Group *cgp,
1923 const char *signal, const char *source,
1924 Edje_Signal_Cb func, void *data,
1925 Eina_Bool propagate);
1926void *_edje_signal_callback_disable(const Edje_Signal_Callback_Group *cgp,
1927 const char *signal, const char *source,
1928 Edje_Signal_Cb func, void *data);
1929
1884EAPI void _edje_edd_init(void); 1930EAPI void _edje_edd_init(void);
1885EAPI void _edje_edd_shutdown(void); 1931EAPI void _edje_edd_shutdown(void);
1886 1932
@@ -1917,7 +1963,12 @@ void _edje_emit(Edje *ed, const char *sig, const char *src);
1917void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *)); 1963void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *));
1918void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop); 1964void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop);
1919void _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp); 1965void _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp);
1920void _edje_callbacks_patterns_clean(Edje *ed); 1966
1967const Edje_Signals_Sources_Patterns *_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp);
1968void _edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp);
1969Eina_Bool _edje_signal_callback_prop(const Eina_Bool *flags, int i);
1970
1971void _edje_signal_callback_free(const Edje_Signal_Callback_Group *gp);
1921 1972
1922void _edje_text_init(void); 1973void _edje_text_init(void);
1923void _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep); 1974void _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep);
@@ -2462,6 +2513,9 @@ void _play_get(Eo *obj, void *_pd, va_list *list);
2462void _animation_set(Eo *obj, void *_pd, va_list *list); 2513void _animation_set(Eo *obj, void *_pd, va_list *list);
2463void _animation_get(Eo *obj, void *_pd, va_list *list); 2514void _animation_get(Eo *obj, void *_pd, va_list *list);
2464 2515
2516void edje_signal_init(void);
2517void edje_signal_shutdown(void);
2518
2465#ifdef HAVE_LIBREMIX 2519#ifdef HAVE_LIBREMIX
2466#include <remix/remix.h> 2520#include <remix/remix.h>
2467#endif 2521#endif
diff --git a/src/lib/edje/edje_program.c b/src/lib/edje/edje_program.c
index fbcc136f2c..2eb36306d0 100644
--- a/src/lib/edje/edje_program.c
+++ b/src/lib/edje/edje_program.c
@@ -28,26 +28,27 @@ edje_frametime_get(void)
28void 28void
29edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) 29edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
30{ 30{
31 const char *sig;
32 const char *src;
31 Edje *ed; 33 Edje *ed;
32 Edje_Signal_Callback *escb;
33 34
34 ed = _edje_fetch(obj); 35 ed = _edje_fetch(obj);
35 if (!ed) return; 36 if (!ed) return;
36 if (ed->delete_me) return; 37 if (ed->delete_me) return;
37 escb = calloc(1, sizeof(Edje_Signal_Callback)); 38
38 escb->propagate = EINA_TRUE; 39 if (!ed->callbacks)
39 escb->signal = eina_stringshare_add("*"); 40 ed->callbacks = _edje_signal_callback_alloc();
40 escb->source = eina_stringshare_add("*"); 41
41 escb->func = func; 42 sig = eina_stringshare_add("*");
42 escb->data = data; 43 src = eina_stringshare_add("*");
43 ed->callbacks = eina_list_append(ed->callbacks, escb); 44
44 if (ed->walking_callbacks) 45 _edje_signal_callback_push(ed->callbacks,
45 { 46 sig, src,
46 escb->just_added = 1; 47 func, data,
47 ed->just_added_callbacks = EINA_TRUE; 48 EINA_TRUE);
48 } 49
49 else 50 eina_stringshare_del(sig);
50 _edje_callbacks_patterns_clean(ed); 51 eina_stringshare_del(src);
51} 52}
52 53
53EAPI void 54EAPI void
@@ -66,27 +67,24 @@ _signal_callback_add(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
66 void *data = va_arg(*list, void *); 67 void *data = va_arg(*list, void *);
67 68
68 Edje *ed = _pd; 69 Edje *ed = _pd;
69 Edje_Signal_Callback *escb;
70 70
71 if ((!emission) || (!source) || (!func)) return; 71 if ((!emission) || (!source) || (!func)) return;
72 ed = _pd; 72 ed = _pd;
73 if (!ed) return; 73 if (!ed) return;
74 if (ed->delete_me) return; 74 if (ed->delete_me) return;
75 escb = calloc(1, sizeof(Edje_Signal_Callback)); 75
76 if (emission[0]) 76 emission = eina_stringshare_add(emission);
77 escb->signal = eina_stringshare_add(emission); 77 source = eina_stringshare_add(source);
78 if (source[0]) 78
79 escb->source = eina_stringshare_add(source); 79 if (!ed->callbacks)
80 escb->func = func; 80 ed->callbacks = _edje_signal_callback_alloc();
81 escb->data = data; 81
82 ed->callbacks = eina_list_append(ed->callbacks, escb); 82 _edje_signal_callback_push(ed->callbacks,
83 if (ed->walking_callbacks) 83 emission, source,
84 { 84 func, data, EINA_FALSE);
85 escb->just_added = 1; 85
86 ed->just_added_callbacks = EINA_TRUE; 86 eina_stringshare_del(emission);
87 } 87 eina_stringshare_del(source);
88 else
89 _edje_callbacks_patterns_clean(ed);
90} 88}
91 89
92EAPI void * 90EAPI void *
@@ -94,7 +92,7 @@ edje_object_signal_callback_del(Evas_Object *obj, const char *emission, const ch
94{ 92{
95 if (!obj) return NULL; 93 if (!obj) return NULL;
96 void *ret = NULL; 94 void *ret = NULL;
97 eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, &ret)); 95 eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, NULL, &ret));
98 return ret; 96 return ret;
99} 97}
100 98
@@ -104,46 +102,25 @@ _signal_callback_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
104 const char *emission = va_arg(*list, const char *); 102 const char *emission = va_arg(*list, const char *);
105 const char *source = va_arg(*list, const char *); 103 const char *source = va_arg(*list, const char *);
106 Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb); 104 Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb);
105 void *data = va_arg(*list, void *);
107 void **ret = va_arg(*list, void **); 106 void **ret = va_arg(*list, void **);
108 if (ret) *ret = NULL;
109
110 Edje *ed = _pd; 107 Edje *ed = _pd;
111 Eina_List *l; 108
112 Edje_Signal_Callback *escb; 109 if (ret) *ret = NULL;
113 110
114 if ((!emission) || (!source) || (!func)) return; 111 if ((!emission) || (!source) || (!func)) return;
115 if (!ed) return; 112 if (!ed) return;
116 if (ed->delete_me) return; 113 if (ed->delete_me) return;
117 EINA_LIST_FOREACH(ed->callbacks, l, escb)
118 {
119 if ((escb->func == func) &&
120 ((!escb->signal && !emission[0]) ||
121 (escb->signal && !strcmp(escb->signal, emission))) &&
122 ((!escb->source && !source[0]) ||
123 (escb->source && !strcmp(escb->source, source))))
124 {
125 void *data;
126 114
127 data = escb->data; 115 emission = eina_stringshare_add(emission);
128 if (ed->walking_callbacks) 116 source = eina_stringshare_add(source);
129 {
130 escb->delete_me = EINA_TRUE;
131 ed->delete_callbacks = EINA_TRUE;
132 }
133 else
134 {
135 _edje_callbacks_patterns_clean(ed);
136 117
137 ed->callbacks = eina_list_remove_list(ed->callbacks, l); 118 _edje_signal_callback_disable(ed->callbacks,
138 if (escb->signal) eina_stringshare_del(escb->signal); 119 emission, source,
139 if (escb->source) eina_stringshare_del(escb->source); 120 func, data);
140 free(escb); 121
141 } 122 eina_stringshare_del(emission);
142 if (ret) *ret = data; 123 eina_stringshare_del(source);
143 return;
144 }
145 }
146 return;
147} 124}
148 125
149EAPI void * 126EAPI void *
@@ -151,59 +128,10 @@ edje_object_signal_callback_del_full(Evas_Object *obj, const char *emission, con
151{ 128{
152 if (!obj) return NULL; 129 if (!obj) return NULL;
153 void *ret = NULL; 130 void *ret = NULL;
154 eo_do(obj, edje_obj_signal_callback_del_full(emission, source, func, data, &ret)); 131 eo_do(obj, edje_obj_signal_callback_del(emission, source, func, data, &ret));
155 return ret; 132 return ret;
156} 133}
157 134
158void
159_signal_callback_del_full(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
160{
161 const char *emission = va_arg(*list, const char *);
162 const char *source = va_arg(*list, const char *);
163 Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb);
164 void *data = va_arg(*list, void *);
165 void **ret = va_arg(*list, void **);
166 if (ret) *ret = NULL;
167
168 Edje *ed = _pd;
169 Eina_List *l;
170 Edje_Signal_Callback *escb;
171
172 if ((!emission) || (!source) || (!func)) return;
173 if (!ed) return;
174 if (ed->delete_me) return;
175 EINA_LIST_FOREACH(ed->callbacks, l, escb)
176 {
177 if ((escb->func == func) && (escb->data == data) &&
178 ((!escb->signal && !emission[0]) ||
179 (escb->signal && !strcmp(escb->signal, emission))) &&
180 ((!escb->source && !source[0]) ||
181 (escb->source && !strcmp(escb->source, source))))
182 {
183 void *data2;
184
185 data2 = escb->data;
186 if (ed->walking_callbacks)
187 {
188 escb->delete_me = EINA_TRUE;
189 ed->delete_callbacks = EINA_TRUE;
190 }
191 else
192 {
193 _edje_callbacks_patterns_clean(ed);
194
195 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
196 if (escb->signal) eina_stringshare_del(escb->signal);
197 if (escb->source) eina_stringshare_del(escb->source);
198 free(escb);
199 }
200 if (ret) *ret = data2;
201 return;
202 }
203 }
204 return;
205}
206
207EAPI void 135EAPI void
208edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source) 136edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source)
209{ 137{
@@ -627,9 +555,20 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig,
627 555
628 tmp = calloc(1, sizeof(Edje_Calc_Params)); 556 tmp = calloc(1, sizeof(Edje_Calc_Params));
629 if (!tmp) goto low_mem_current; 557 if (!tmp) goto low_mem_current;
558 tmp->map = eina_cow_alloc(_edje_calc_params_map_cow);
559#ifdef HAVE_EPHYSICS
560 tmp->physics = eina_cow_alloc(_edje_calc_params_physics_cow);
561#endif
630 _edje_part_recalc(ed, rp, FLAG_XY, tmp); 562 _edje_part_recalc(ed, rp, FLAG_XY, tmp);
631 563
632 if (rp->current) free(rp->current); 564 if (rp->current)
565 {
566 eina_cow_free(_edje_calc_params_map_cow, rp->current->map);
567#ifdef HAVE_EPHYSICS
568 eina_cow_free(_edje_calc_params_physics_cow, rp->current->physics);
569#endif
570 free(rp->current);
571 }
633 rp->current = tmp; 572 rp->current = tmp;
634 573
635 rp->current->x -= ed->x; 574 rp->current->x -= ed->x;
@@ -650,7 +589,14 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig,
650 else 589 else
651 { 590 {
652 low_mem_current: 591 low_mem_current:
653 if (rp->current) free(rp->current); 592 if (rp->current)
593 {
594 eina_cow_free(_edje_calc_params_map_cow, rp->current->map);
595#ifdef HAVE_EPHYSICS
596 eina_cow_free(_edje_calc_params_physics_cow, rp->current->physics);
597#endif
598 free(rp->current);
599 }
654 rp->current = NULL; 600 rp->current = NULL;
655 } 601 }
656 602
@@ -1093,7 +1039,7 @@ _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*f
1093 Edje *ed2; 1039 Edje *ed2;
1094 char *part; 1040 char *part;
1095 char *idx; 1041 char *idx;
1096 size_t length; 1042 unsigned int length;
1097 1043
1098 /* the signal contains a colon, split the signal into "parts:signal" */ 1044 /* the signal contains a colon, split the signal into "parts:signal" */
1099 length = sep - sig + 1; 1045 length = sep - sig + 1;
@@ -1279,37 +1225,6 @@ static Eina_Bool _edje_glob_callback(Edje_Program *pr, void *dt)
1279 return EINA_FALSE; 1225 return EINA_FALSE;
1280} 1226}
1281 1227
1282void
1283_edje_callbacks_patterns_clean(Edje *ed)
1284{
1285 if (ed->walking_callbacks > 0) return;
1286
1287 _edje_signals_sources_patterns_clean(&ed->patterns.callbacks);
1288
1289 eina_rbtree_delete(ed->patterns.callbacks.exact_match,
1290 EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
1291 NULL);
1292 ed->patterns.callbacks.exact_match = NULL;
1293
1294 ed->patterns.callbacks.u.callbacks.globing = eina_list_free(ed->patterns.callbacks.u.callbacks.globing);
1295}
1296
1297static void
1298_edje_callbacks_patterns_init(Edje *ed)
1299{
1300 Edje_Signals_Sources_Patterns *ssp = &ed->patterns.callbacks;
1301
1302 if ((ssp->signals_patterns) || (ssp->sources_patterns) ||
1303 (ssp->u.callbacks.globing) || (ssp->exact_match))
1304 return;
1305
1306 ssp->u.callbacks.globing = edje_match_callback_hash_build(ed->callbacks,
1307 &ssp->exact_match);
1308
1309 ssp->signals_patterns = edje_match_callback_signal_init(ssp->u.callbacks.globing);
1310 ssp->sources_patterns = edje_match_callback_source_init(ssp->u.callbacks.globing);
1311}
1312
1313/* FIXME: what if we delete the evas object??? */ 1228/* FIXME: what if we delete the evas object??? */
1314void 1229void
1315_edje_emit_handle(Edje *ed, const char *sig, const char *src, 1230_edje_emit_handle(Edje *ed, const char *sig, const char *src,
@@ -1403,13 +1318,11 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src,
1403 1318
1404 if (ed->collection->patterns.table_programs_size > 0) 1319 if (ed->collection->patterns.table_programs_size > 0)
1405 { 1320 {
1406 const Eina_Array *match; 1321 const Eina_Inarray *match;
1407#ifdef EDJE_PROGRAM_CACHE 1322#ifdef EDJE_PROGRAM_CACHE
1408 const Eina_List *l; 1323 const Eina_List *l;
1409#endif 1324#endif
1410 Edje_Program *pr; 1325 Edje_Program *pr;
1411 Eina_Array_Iterator iterator;
1412 unsigned int i;
1413 1326
1414 if (ed->collection->patterns.programs.u.programs.globing) 1327 if (ed->collection->patterns.programs.u.programs.globing)
1415 if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns, 1328 if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns,
@@ -1420,13 +1333,17 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src,
1420 _edje_glob_callback, 1333 _edje_glob_callback,
1421 &data, 1334 &data,
1422 prop) == 0) 1335 prop) == 0)
1423 goto break_prog; 1336 goto break_prog;
1424 1337
1425 match = edje_match_signal_source_hash_get(sig, src, 1338 match = edje_match_signal_source_hash_get(sig, src,
1426 ed->collection->patterns.programs.exact_match); 1339 ed->collection->patterns.programs.exact_match);
1427 if (match) 1340 if (match)
1428 EINA_ARRAY_ITER_NEXT(match, i, pr, iterator) 1341 {
1429 _edje_glob_callback(pr, &data); 1342 Edje_Program **tpr;
1343
1344 EINA_INARRAY_FOREACH(match, tpr)
1345 _edje_glob_callback(*tpr, &data);
1346 }
1430 1347
1431#ifdef EDJE_PROGRAM_CACHE 1348#ifdef EDJE_PROGRAM_CACHE
1432 EINA_LIST_FOREACH(data.matches, l, pr) 1349 EINA_LIST_FOREACH(data.matches, l, pr)
@@ -1489,82 +1406,68 @@ edje_object_signal_callback_extra_data_get(void)
1489static void 1406static void
1490_edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop) 1407_edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop)
1491{ 1408{
1492 Eina_List *l; 1409 const Edje_Signals_Sources_Patterns *ssp;
1410 Edje_Signal_Callback_Matches *m;
1411 const void **custom_data;
1412 Eina_Bool *flags;
1413 const Eina_Inarray *match;
1414 int r = 1;
1493 1415
1494 if (ed->delete_me) return; 1416 if (ed->delete_me) return;
1417 if (!ed->callbacks || !ed->callbacks->matches) return;
1418
1495 _edje_ref(ed); 1419 _edje_ref(ed);
1496 _edje_freeze(ed); 1420 _edje_freeze(ed);
1497 _edje_block(ed); 1421 _edje_block(ed);
1498 1422
1499 if (ed->just_added_callbacks) 1423 ssp = _edje_signal_callback_patterns_ref(ed->callbacks);
1500 _edje_callbacks_patterns_clean(ed); 1424
1425 m = (Edje_Signal_Callback_Matches*) ed->callbacks->matches;
1426 EINA_REFCOUNT_REF(m);
1427
1428 callback_extra_data = (data) ? data->data : NULL;
1429 custom_data = alloca(sizeof (void*) * m->matches_count);
1430 memcpy(custom_data, ed->callbacks->custom_data, sizeof (void*) * m->matches_count);
1431 flags = alloca(sizeof (Eina_Bool) * m->matches_count);
1432 memcpy(flags, ed->callbacks->flags, sizeof (Eina_Bool) * (m->matches_count >> 1));
1433
1434 if (eina_inarray_count(&ssp->u.callbacks.globing))
1435 r = edje_match_callback_exec(ssp,
1436 m->matches,
1437 custom_data,
1438 flags,
1439 sig,
1440 src,
1441 ed,
1442 prop);
1443
1444 if (!r)
1445 goto break_prog;
1446
1447 match = edje_match_signal_source_hash_get(sig, src,
1448 ssp->exact_match);
1449 if (match)
1450 {
1451 const Edje_Signal_Callback_Match *cb;
1452 unsigned int *i;
1501 1453
1502 ed->walking_callbacks++; 1454 EINA_INARRAY_FOREACH(match, i)
1455 {
1456 cb = &m->matches[*i];
1503 1457
1504 if (ed->callbacks) 1458 if ((prop) && (_edje_signal_callback_prop(flags, *i))) continue;
1505 {
1506 Edje_Signal_Callback *escb;
1507 const Eina_Array *match;
1508 Eina_Array_Iterator iterator;
1509 unsigned int i;
1510 int r = 1;
1511 callback_extra_data = (data) ? data->data : NULL;
1512
1513 _edje_callbacks_patterns_init(ed);
1514 if (ed->patterns.callbacks.u.callbacks.globing)
1515 r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
1516 ed->patterns.callbacks.sources_patterns,
1517 sig,
1518 src,
1519 ed->patterns.callbacks.u.callbacks.globing,
1520 ed,
1521 prop);
1522
1523 if (!r)
1524 goto break_prog;
1525 1459
1526 match = edje_match_signal_source_hash_get(sig, src, 1460 cb->func((void*) custom_data[*i], ed->obj, sig, src);
1527 ed->patterns.callbacks.exact_match); 1461 if (_edje_block_break(ed))
1528 if (match) 1462 break;
1529 EINA_ARRAY_ITER_NEXT(match, i, escb, iterator) 1463 }
1530 {
1531 if ((prop) && (escb->propagate)) continue;
1532 if ((!escb->just_added) && (!escb->delete_me))
1533 {
1534 escb->func(escb->data, ed->obj, sig, src);
1535 if (_edje_block_break(ed))
1536 break;
1537 }
1538 }
1539 } 1464 }
1540 break_prog:
1541 1465
1542 ed->walking_callbacks--; 1466 break_prog:
1543 if (!ed->walking_callbacks && 1467 _edje_signal_callback_matches_unref(m);
1544 ((ed->delete_callbacks) || (ed->just_added_callbacks)))
1545 {
1546 ed->delete_callbacks = EINA_FALSE;
1547 ed->just_added_callbacks = EINA_FALSE;
1548 l = ed->callbacks;
1549 while (l)
1550 {
1551 Edje_Signal_Callback *escb = l->data;
1552 Eina_List *next_l = l->next;
1553 1468
1554 if (escb->just_added) 1469 _edje_signal_callback_patterns_unref(ssp);
1555 escb->just_added = 0;
1556 if (escb->delete_me)
1557 {
1558 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
1559 if (escb->signal) eina_stringshare_del(escb->signal);
1560 if (escb->source) eina_stringshare_del(escb->source);
1561 free(escb);
1562 }
1563 l = next_l;
1564 }
1565 1470
1566 _edje_callbacks_patterns_clean(ed);
1567 }
1568 _edje_unblock(ed); 1471 _edje_unblock(ed);
1569 _edje_thaw(ed); 1472 _edje_thaw(ed);
1570 _edje_unref(ed); 1473 _edje_unref(ed);
diff --git a/src/lib/edje/edje_signal.c b/src/lib/edje/edje_signal.c
new file mode 100644
index 0000000000..3dfdae1230
--- /dev/null
+++ b/src/lib/edje/edje_signal.c
@@ -0,0 +1,477 @@
1#include <assert.h>
2
3#include "edje_private.h"
4
5#define _DELETE_ME 0x4
6#define _JUST_ADDED 0x2
7#define _PROPAGATE 0x1
8
9static Eina_Hash *signal_match = NULL;
10
11static unsigned int
12_edje_signal_match_key_length(const void *key EINA_UNUSED)
13{
14 return sizeof (Edje_Signal_Callback_Matches);
15}
16
17static int
18_edje_signal_match_key_cmp(const void *key1, int key1_length EINA_UNUSED, const void *key2, int key2_length EINA_UNUSED)
19{
20 const Edje_Signal_Callback_Matches *a = key1;
21 const Edje_Signal_Callback_Matches *b = key2;
22 unsigned int i;
23
24 if (a->matches_count != b->matches_count) return a->matches_count - b->matches_count;
25 for (i = 0; i < a->matches_count; ++i)
26 {
27 if (a->matches[i].signal != b->matches[i].signal) return a->matches[i].signal - b->matches[i].signal;
28 if (a->matches[i].source != b->matches[i].source) return a->matches[i].source - b->matches[i].source;
29 if (a->matches[i].func != b->matches[i].func) return (unsigned char*) a->matches[i].func - (unsigned char*) b->matches[i].func;
30 }
31 return 0;
32}
33
34static int
35_edje_signal_match_key_hash(const void *key, int key_length EINA_UNUSED)
36{
37 const Edje_Signal_Callback_Matches *a = key;
38 unsigned int hash, i;
39
40 hash = eina_hash_int32(&a->matches_count, sizeof (int));
41 for (i = 0; i < a->matches_count; ++i)
42 {
43#ifdef __LP64__
44 hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].signal, sizeof (char *));
45 hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].source, sizeof (char *));
46 hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].func, sizeof (Edje_Signal_Cb));
47#else
48 hash ^= eina_hash_int32((const unsigned int*) a->matches[i].signal, sizeof (char *));
49 hash ^= eina_hash_int32((const unsigned int*) a->matches[i].source, sizeof (char *));
50 hash ^= eina_hash_int32((const unsigned int*) a->matches[i].func, sizeof (Edje_Signal_Cb));
51#endif
52 }
53 return hash;
54}
55
56static const Edje_Signal_Callback_Matches *
57_edje_signal_callback_matches_dup(const Edje_Signal_Callback_Matches *src)
58{
59 Edje_Signal_Callback_Matches *result;
60 unsigned int i;
61
62 result = calloc(1, sizeof (Edje_Signal_Callback_Matches));
63 if (!result) return NULL;
64
65 result->hashed = EINA_FALSE;
66 result->matches = malloc(sizeof (Edje_Signal_Callback_Match) * src->matches_count);
67 result->matches_count = src->matches_count;
68 result->patterns = NULL;
69 EINA_REFCOUNT_REF(result);
70
71 for (i = 0; i < src->matches_count; i++)
72 {
73 result->matches[i].signal = eina_stringshare_ref(src->matches[i].signal);
74 result->matches[i].source = eina_stringshare_ref(src->matches[i].source);
75 result->matches[i].func = src->matches[i].func;
76 }
77
78 return result;
79}
80
81void
82_edje_callbacks_patterns_clean(Edje_Signal_Callback_Group *gp)
83{
84 Edje_Signal_Callback_Matches *tmp;
85
86 assert(EINA_REFCOUNT_GET(gp->matches) == 1);
87 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
88
89 _edje_signal_callback_patterns_unref(tmp->patterns);
90 tmp->patterns = NULL;
91}
92
93static void
94_edje_callbacks_patterns_init(Edje_Signal_Callback_Group *gp)
95{
96 Edje_Signals_Sources_Patterns *ssp;
97 Edje_Signal_Callback_Matches *tmp;
98
99 if (gp->matches->patterns) return ;
100
101 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
102 tmp->patterns = calloc(1, sizeof (Edje_Signals_Sources_Patterns));
103 if (!gp->matches->patterns) return ;
104
105 ssp = gp->matches->patterns;
106 edje_match_callback_hash_build(gp->matches->matches,
107 gp->matches->matches_count,
108 &ssp->exact_match,
109 &ssp->u.callbacks.globing);
110
111 ssp->signals_patterns = edje_match_callback_signal_init(&ssp->u.callbacks.globing, tmp->matches);
112 ssp->sources_patterns = edje_match_callback_source_init(&ssp->u.callbacks.globing, tmp->matches);
113 EINA_REFCOUNT_REF(ssp);
114}
115
116void
117edje_signal_init(void)
118{
119 signal_match = eina_hash_new(_edje_signal_match_key_length,
120 _edje_signal_match_key_cmp,
121 _edje_signal_match_key_hash,
122 NULL,
123 3);
124}
125
126void
127edje_signal_shutdown(void)
128{
129 // FIXME: iterate and destroy leftover signal matcher
130 eina_hash_free(signal_match);
131}
132
133static void
134_edje_signal_callback_unset(Edje_Signal_Callback_Group *gp, int idx)
135{
136 Edje_Signal_Callback_Match *m;
137
138 m = gp->matches->matches + idx;
139 eina_stringshare_del(m->signal);
140 m->signal = NULL;
141 eina_stringshare_del(m->source);
142 m->source = NULL;
143}
144
145static void
146_edje_signal_callback_set(Edje_Signal_Callback_Group *gp, int idx,
147 const char *sig, const char *src,
148 Edje_Signal_Cb func, void *data, Eina_Bool flags)
149{
150 Edje_Signal_Callback_Match *m;
151
152 m = gp->matches->matches + idx;
153 m->signal = eina_stringshare_ref(sig);
154 m->source = eina_stringshare_ref(src);
155 m->func = func;
156
157 gp->custom_data[idx] = data;
158
159 gp->flags[idx >> 1] = (gp->flags[idx >> 1] & (0xF << (((idx & 1) ^ 1) * 4))) |
160 ((flags & 0xF) << ((idx & 1) * 4));
161}
162
163Eina_Bool
164_edje_signal_callback_prop(const Eina_Bool *flags, int i)
165{
166 Eina_Bool b;
167
168 b = flags[i >> 1];
169 return b & (_PROPAGATE << ((i & 1) * 4));
170}
171
172static Edje_Signal_Callback_Group *
173_edje_signal_callback_grow(Edje_Signal_Callback_Group *gp)
174{
175 Edje_Signal_Callback_Matches *tmp;
176 unsigned int c;
177
178 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
179 tmp->matches_count++;
180 tmp->matches = realloc(tmp->matches, sizeof (Edje_Signal_Callback_Match) * tmp->matches_count);
181 gp->custom_data = realloc(gp->custom_data, sizeof (void*) * tmp->matches_count);
182
183 c = ((tmp->matches_count >> 1) | (tmp->matches_count & 1));
184 gp->flags = realloc(gp->flags, sizeof (Edje_Signal_Callback_Group) + c);
185 // We have just expanded by one char, set it to 0
186 if (tmp->matches_count & 1) gp->flags[tmp->matches_count >> 1] = 0;
187
188 return gp;
189}
190
191void
192_edje_signal_callback_push(const Edje_Signal_Callback_Group *cgp,
193 const char *sig, const char *src,
194 Edje_Signal_Cb func, void *data, Eina_Bool propagate)
195{
196 Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp;
197 unsigned int i;
198
199 // let's first try to see if we do find an empty matching stop
200 for (i = 0; i < gp->matches->matches_count; i++)
201 if (sig == gp->matches->matches[i].signal &&
202 src == gp->matches->matches[i].source &&
203 func == gp->matches->matches[i].func)
204 {
205 Eina_Bool flags;
206
207 flags = gp->flags[i >> 1] & (0xF << ((i & 1) * 4));
208 if (flags & _DELETE_ME)
209 {
210 _edje_signal_callback_unset(gp, i);
211 _edje_signal_callback_set(gp, i,
212 sig, src, func, data,
213 (((!!propagate) & 1) | _JUST_ADDED));
214 return ;
215 }
216 }
217
218 if (gp->matches->hashed)
219 {
220 Edje_Signal_Callback_Matches *tmp;
221
222 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
223 if (EINA_REFCOUNT_GET(tmp) == 1)
224 {
225 eina_hash_del(signal_match, tmp, tmp);
226 tmp->hashed = 0;
227 }
228 else
229 {
230 Edje_Signal_Callback_Matches *tmp_dup;
231 tmp_dup = (Edje_Signal_Callback_Matches*) _edje_signal_callback_matches_dup(tmp);
232 if (!tmp_dup) return ;
233 EINA_REFCOUNT_UNREF(tmp)
234 (void) 0; // Nothing to do because the case where refcount == 1 was already handle above.
235 gp->matches = tmp_dup;
236 }
237 }
238
239 // search an empty spot now
240 for (i = 0; i < gp->matches->matches_count; i += 2)
241 if (gp->flags[i >> 1] & (_DELETE_ME | (_DELETE_ME << 4)))
242 {
243 if (gp->flags[i >> 1] & _DELETE_ME)
244 {
245 _edje_signal_callback_unset(gp, i);
246 _edje_signal_callback_set(gp, i,
247 sig, src, func, data,
248 (((!!propagate) & 1) | _JUST_ADDED));
249 return ;
250 }
251 if (gp->flags[i >> 1] & (_DELETE_ME << 4))
252 {
253 _edje_signal_callback_unset(gp, i + 1);
254 _edje_signal_callback_set(gp, i + 1,
255 sig, src, func, data,
256 (((!!propagate) & 1) | _JUST_ADDED));
257 return ;
258 }
259 }
260
261 _edje_signal_callback_grow(gp);
262
263 // Set propagate and just_added flags
264 _edje_signal_callback_set(gp, gp->matches->matches_count - 1,
265 sig, src, func, data, (((!!propagate) & 1) | _JUST_ADDED));
266
267 return ;
268}
269
270const Edje_Signal_Callback_Group *
271_edje_signal_callback_alloc(void)
272{
273 Edje_Signal_Callback_Group *escg;
274 Edje_Signal_Callback_Matches *m;
275
276 escg = calloc(1, sizeof (Edje_Signal_Callback_Group));
277 if (!escg) return NULL;
278
279 m = calloc(1, sizeof (Edje_Signal_Callback_Matches));
280 if (!m)
281 {
282 free(escg);
283 return NULL;
284 }
285
286 EINA_REFCOUNT_REF(m);
287 escg->matches = m;
288
289 return escg;
290}
291
292void
293_edje_signal_callback_matches_unref(Edje_Signal_Callback_Matches *m)
294{
295 EINA_REFCOUNT_UNREF(m)
296 {
297 unsigned int i;
298
299 _edje_signal_callback_patterns_unref(m->patterns);
300
301 if (m->hashed)
302 eina_hash_del(signal_match, m, m);
303
304 for (i = 0; i < m->matches_count; ++i)
305 {
306 eina_stringshare_del(m->matches[i].signal);
307 eina_stringshare_del(m->matches[i].source);
308 }
309 free(m->matches);
310 free(m);
311 }
312}
313
314void
315_edje_signal_callback_free(const Edje_Signal_Callback_Group *cgp)
316{
317 Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp;
318
319 if (!gp) return ;
320
321 _edje_signal_callback_matches_unref((Edje_Signal_Callback_Matches*) gp->matches);
322 gp->matches = NULL;
323 free(gp->custom_data);
324 free(gp);
325}
326
327void *
328_edje_signal_callback_disable(const Edje_Signal_Callback_Group *cgp,
329 const char *sig, const char *src,
330 Edje_Signal_Cb func, void *data)
331{
332 Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp;
333 unsigned int i;
334
335 // FIXME: Shall we check DELETE_ME flags ?
336 for (i = 0; i < gp->matches->matches_count; ++i)
337 {
338 if (sig == gp->matches->matches[i].signal &&
339 src == gp->matches->matches[i].source &&
340 func == gp->matches->matches[i].func &&
341 gp->custom_data[i] == data)
342 {
343 Eina_Bool flags;
344
345 flags = gp->flags[i >> 1] | (_DELETE_ME << ((i & 1) * 4));
346 gp->flags[i >> 1] = flags;
347 return gp->custom_data[i];
348 }
349 }
350
351 if (data == NULL)
352 {
353 for (i = 0; i < gp->matches->matches_count; ++i)
354 {
355 if (sig == gp->matches->matches[i].signal &&
356 src == gp->matches->matches[i].source &&
357 func == gp->matches->matches[i].func)
358 {
359 Eina_Bool flags;
360
361 flags = gp->flags[i >> 1] | (_DELETE_ME << ((i & 1) * 4));
362 gp->flags[i >> 1] = flags;
363 return gp->custom_data[i];
364 }
365 }
366 }
367
368 return NULL;
369}
370
371static void
372_edje_signal_callback_move_last(Edje_Signal_Callback_Group *gp,
373 int i)
374{
375 Edje_Signal_Callback_Matches *m;
376 int j;
377
378 m = (Edje_Signal_Callback_Matches*) gp->matches;
379
380 for (j = (int) --m->matches_count; j > i; --j)
381 {
382 if (!(gp->flags[j >> 1] & (_DELETE_ME << ((j & 1) * 4))))
383 {
384 m->matches[i].signal = m->matches[j].signal;
385 m->matches[i].source = m->matches[j].source;
386 m->matches[i].func = m->matches[j].func;
387 gp->flags[i] = (gp->flags[i >> 1] & (0xF << (((i & 1) ^ 1) * 4))) |
388 (gp->flags[j >> 1] & (0xF << (((j & 1) * 4))));
389 return ;
390 }
391 --m->matches_count;
392 }
393}
394
395const Edje_Signals_Sources_Patterns *
396_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp)
397{
398 const Edje_Signal_Callback_Matches *m;
399 Edje_Signal_Callback_Matches *tmp;
400
401 if (gp->matches->hashed)
402 goto got_it;
403
404 m = eina_hash_find(signal_match, gp->matches);
405 if (!m)
406 {
407 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
408 if (!(tmp->patterns && (EINA_REFCOUNT_GET(tmp->patterns) > 1)))
409 {
410 // Let compact it and remove uneeded pattern before building it
411 // We can do that because the custom data are kept local into the matching code.
412 Eina_Bool delete_me = _DELETE_ME | (_DELETE_ME << 4);
413 unsigned int i;
414
415 for (i = 0; i < tmp->matches_count; i += 2)
416 {
417 if (gp->flags[i >> 1] & delete_me)
418 {
419 if (gp->flags[i >> 1] & _DELETE_ME)
420 {
421 _edje_signal_callback_move_last((Edje_Signal_Callback_Group*) gp, i);
422 }
423 if (i + 1 < gp->matches->matches_count &&
424 (gp->flags[i >> 1] & (_DELETE_ME << 4)))
425 {
426 _edje_signal_callback_move_last((Edje_Signal_Callback_Group*) gp, i + 1);
427 }
428 }
429 }
430
431 }
432
433 _edje_signal_callback_patterns_unref(tmp->patterns);
434 tmp->patterns = NULL;
435
436 _edje_callbacks_patterns_init((Edje_Signal_Callback_Group*) gp);
437 eina_hash_add(signal_match, tmp, tmp);
438 tmp->hashed = EINA_TRUE;
439 }
440 else
441 {
442 _edje_signal_callback_matches_unref((Edje_Signal_Callback_Matches*) gp->matches);
443 ((Edje_Signal_Callback_Group*)gp)->matches = m;
444 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
445 EINA_REFCOUNT_REF(tmp);
446 }
447
448 got_it:
449 tmp = (Edje_Signal_Callback_Matches*) gp->matches;
450
451 EINA_REFCOUNT_REF(tmp->patterns);
452 return gp->matches->patterns;
453}
454
455void
456_edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp)
457{
458 Edje_Signals_Sources_Patterns *ssp;
459
460 if (!essp) return ;
461
462 ssp = (Edje_Signals_Sources_Patterns*) essp;
463
464 EINA_REFCOUNT_UNREF(ssp)
465 {
466 _edje_signals_sources_patterns_clean(ssp);
467
468 eina_rbtree_delete(ssp->exact_match,
469 EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
470 NULL);
471 ssp->exact_match = NULL;
472
473 eina_inarray_flush(&ssp->u.callbacks.globing);
474
475 free(ssp);
476 }
477}
diff --git a/src/lib/edje/edje_smart.c b/src/lib/edje/edje_smart.c
index 80951d95bd..d31203471f 100644
--- a/src/lib/edje/edje_smart.c
+++ b/src/lib/edje/edje_smart.c
@@ -480,7 +480,6 @@ _edje_smart_class_constructor(Eo_Class *klass)
480 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS), _message_signal_process), 480 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS), _message_signal_process),
481 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD), _signal_callback_add), 481 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD), _signal_callback_add),
482 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), _signal_callback_del), 482 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), _signal_callback_del),
483 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL), _signal_callback_del_full),
484 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_EMIT), _signal_emit), 483 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_EMIT), _signal_emit),
485 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_SET), _play_set), 484 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_SET), _play_set),
486 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_GET), _play_get), 485 EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_GET), _play_get),
@@ -626,7 +625,6 @@ static const Eo_Op_Description op_desc[] = {
626 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS, "Process an object's message queue."), 625 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS, "Process an object's message queue."),
627 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD, "Add a callback for an arriving Edje signal, emitted by"), 626 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD, "Add a callback for an arriving Edje signal, emitted by"),
628 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL, "Remove a signal-triggered callback from an object."), 627 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL, "Remove a signal-triggered callback from an object."),
629 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL, "Unregister/delete a callback set for an arriving Edje"),
630 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_EMIT, "Send/emit an Edje signal to a given Edje object"), 628 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_EMIT, "Send/emit an Edje signal to a given Edje object"),
631 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_SET, "Set the Edje object to playing or paused states."), 629 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_SET, "Set the Edje object to playing or paused states."),
632 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_GET, "Get the Edje object's state."), 630 EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_GET, "Get the Edje object's state."),