diff --git a/legacy/edje/src/lib/edje_load.c b/legacy/edje/src/lib/edje_load.c index 1b07e6be9a..6dda317580 100644 --- a/legacy/edje/src/lib/edje_load.c +++ b/legacy/edje/src/lib/edje_load.c @@ -214,19 +214,28 @@ static void _edje_programs_patterns_clean(Edje *ed) { _edje_signals_sources_patterns_clean(&ed->patterns.programs); + + eina_rbtree_delete(ed->patterns.programs.exact_match, + EINA_RBTREE_FREE_CB(edje_match_signal_source_free), + NULL); + ed->patterns.programs.exact_match = NULL; + + ed->patterns.programs.globing = eina_list_free(ed->patterns.programs.globing); } static void _edje_programs_patterns_init(Edje *ed) { Edje_Signals_Sources_Patterns *ssp = &ed->patterns.programs; - Eina_List *programs = ed->collection->programs; if (ssp->signals_patterns) return; - ssp->signals_patterns = edje_match_programs_signal_init(programs); - ssp->sources_patterns = edje_match_programs_source_init(programs); + ssp->globing = edje_match_program_hash_build(ed->collection->programs, + &ssp->exact_match); + + ssp->signals_patterns = edje_match_programs_signal_init(ssp->globing); + ssp->sources_patterns = edje_match_programs_source_init(ssp->globing); } static int diff --git a/legacy/edje/src/lib/edje_match.c b/legacy/edje/src/lib/edje_match.c index 550f7b2d28..ffe6541f59 100644 --- a/legacy/edje/src/lib/edje_match.c +++ b/legacy/edje/src/lib/edje_match.c @@ -55,7 +55,7 @@ _edje_match_states_alloc(Edje_Patterns *ppat, int n) unsigned char *states; unsigned char *has; - size_t i; + int i; states_size = sizeof (*l->states) * array_len; ALIGN(states_size); @@ -116,9 +116,9 @@ _edje_match_states_insert(Edje_States *list, } static void -_edje_match_states_clear(Edje_States *list, - size_t patterns_size, - size_t patterns_max_length) +_edje_match_states_clear(Edje_States *list, + __UNUSED__ size_t patterns_size, + __UNUSED__ size_t patterns_max_length) { list->size = 0; } @@ -276,7 +276,7 @@ _edje_match_patterns_exec_init_states(Edje_States *states, Type *data; \ size_t j; \ \ - data = eina_list_data_get(lst); \ + data = eina_list_data_get(lst); \ if (!data) \ { \ free(r); \ @@ -562,3 +562,134 @@ _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp) ssp->signals_patterns = NULL; ssp->sources_patterns = NULL; } + +static Eina_Rbtree_Direction +_edje_signal_source_node_cmp(const Edje_Signal_Source_Char *n1, + const Edje_Signal_Source_Char *n2, + __UNUSED__ void *data) +{ + int cmp; + + cmp = strcmp(n1->signal, n2->signal); + if (cmp) return cmp < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT; + + return strcmp(n1->source, n2->source) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT; +} + +static int +_edje_signal_source_key_cmp(const Edje_Signal_Source_Char *node, + const char *signal, + __UNUSED__ int length, + const char *source) +{ + int cmp; + + cmp = strcmp(node->signal, signal); + if (cmp) return cmp; + + return strcmp(node->source, source); +} + + +Eina_List * +edje_match_program_hash_build(const Eina_List *callbacks, + Eina_Rbtree **tree) +{ + Eina_List *result = NULL; + Eina_Rbtree *new = NULL; + Edje_Program *program; + const Eina_List *l; + + EINA_LIST_FOREACH(callbacks, l, program) + { + if (program->signal && strpbrk(program->signal, "*?[\\") == NULL + && program->source && strpbrk(program->source, "*?[\\") == NULL) + { + Edje_Signal_Source_Char *item; + + item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, program->signal, 0, + EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), program->source); + if (!item) + { + item = malloc(sizeof (Edje_Signal_Source_Char)); + if (!item) continue ; + + item->signal = program->signal; + item->source = program->source; + item->list = NULL; + + new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), + EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); + } + + item->list = eina_list_prepend(item->list, program); + } + else + result = eina_list_prepend(result, program); + } + + *tree = new; + return result; +} + +Eina_List * +edje_match_callback_hash_build(const Eina_List *callbacks, + Eina_Rbtree **tree) +{ + Eina_List *result = NULL; + Eina_Rbtree *new = NULL; + Edje_Signal_Callback *callback; + const Eina_List *l; + + EINA_LIST_FOREACH(callbacks, l, callback) + { + if (callback->signal && strpbrk(callback->signal, "*?[\\") == NULL + && callback->source && strpbrk(callback->source, "*?[\\") == NULL) + { + Edje_Signal_Source_Char *item; + + 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 = callback->signal; + item->source = callback->source; + item->list = NULL; + + new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), + EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); + } + + item->list = eina_list_prepend(item->list, callback); + } + else + result = eina_list_prepend(result, callback); + } + + *tree = new; + return result; +} + +const Eina_List * +edje_match_signal_source_hash_get(const char *signal, + const char *source, + const Eina_Rbtree *tree) +{ + Edje_Signal_Source_Char *lookup; + + lookup = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(tree, signal, 0, + EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), source); + + if (lookup) return lookup->list; + return NULL; +} + +void +edje_match_signal_source_free(Edje_Signal_Source_Char *key, __UNUSED__ void *data) +{ + eina_list_free(key->list); + free(key); +} diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 1bed06bda9..a203fde7a1 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -581,11 +581,25 @@ typedef struct _Edje_Var_Hash Edje_Var_Hash; typedef struct _Edje_Var_Animator Edje_Var_Animator; typedef struct _Edje_Var_Timer Edje_Var_Timer; typedef struct _Edje_Var_Pool Edje_Var_Pool; +typedef struct _Edje_Signal_Source_Char Edje_Signal_Source_Char; + +struct _Edje_Signal_Source_Char +{ + EINA_RBTREE; + + const char *signal; + const char *source; + + Eina_List *list; +}; struct _Edje_Signals_Sources_Patterns { Edje_Patterns *signals_patterns; Edje_Patterns *sources_patterns; + + Eina_Rbtree *exact_match; + Eina_List *globing; }; typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns; @@ -952,6 +966,15 @@ int edje_match_callback_exec(const Edje_Patterns *ppat_signal, void edje_match_patterns_free(Edje_Patterns *ppat); +Eina_List *edje_match_program_hash_build(const Eina_List *callbacks, + Eina_Rbtree **tree); +Eina_List *edje_match_callback_hash_build(const Eina_List *callbacks, + Eina_Rbtree **tree); +const Eina_List *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); + EAPI extern Eet_Data_Descriptor *_edje_edd_edje_file; EAPI extern Eet_Data_Descriptor *_edje_edd_edje_style; EAPI extern Eet_Data_Descriptor *_edje_edd_edje_style_tag; diff --git a/legacy/edje/src/lib/edje_program.c b/legacy/edje/src/lib/edje_program.c index eb989e2607..3e778f2f42 100644 --- a/legacy/edje/src/lib/edje_program.c +++ b/legacy/edje/src/lib/edje_program.c @@ -860,6 +860,13 @@ void _edje_callbacks_patterns_clean(Edje *ed) { _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.globing = eina_list_free(ed->patterns.callbacks.globing); } static void @@ -870,8 +877,11 @@ _edje_callbacks_patterns_init(Edje *ed) if (ssp->signals_patterns) return; - ssp->signals_patterns = edje_match_callback_signal_init(ed->callbacks); - ssp->sources_patterns = edje_match_callback_source_init(ed->callbacks); + ssp->globing = edje_match_callback_hash_build(ed->callbacks, + &ssp->exact_match); + + ssp->signals_patterns = edje_match_callback_signal_init(ssp->globing); + ssp->sources_patterns = edje_match_callback_source_init(ssp->globing); } /* FIXME: what if we delete the evas object??? */ @@ -942,14 +952,24 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src) #endif if (ed->collection->programs) { - if (edje_match_programs_exec(ed->patterns.programs.signals_patterns, - ed->patterns.programs.sources_patterns, - sig, - src, - ed->collection->programs, - _edje_glob_callback, - &data) == 0) - goto break_prog; + const Eina_List *match; + const Eina_List *l; + Edje_Program *pr; + + if (ed->patterns.programs.globing) + if (edje_match_programs_exec(ed->patterns.programs.signals_patterns, + ed->patterns.programs.sources_patterns, + sig, + src, + ed->patterns.programs.globing, + _edje_glob_callback, + &data) == 0) + goto break_prog; + + match = edje_match_signal_source_hash_get(sig, src, + ed->patterns.programs.exact_match); + EINA_LIST_FOREACH(match, l, pr) + _edje_glob_callback(pr, &data); } #ifdef EDJE_PROGRAM_CACHE @@ -994,18 +1014,32 @@ _edje_emit_cb(Edje *ed, const char *sig, const char *src) if (ed->callbacks) { - int r; + Edje_Signal_Callback *escb; + const Eina_List *match; + const Eina_List *l; + int r = 1; _edje_callbacks_patterns_init(ed); - r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns, - ed->patterns.callbacks.sources_patterns, - sig, - src, - ed->callbacks, - ed); + if (ed->patterns.callbacks.globing) + r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns, + ed->patterns.callbacks.sources_patterns, + sig, + src, + ed->patterns.callbacks.globing, + ed); if (!r) goto break_prog; + + match = edje_match_signal_source_hash_get(sig, src, + ed->patterns.callbacks.exact_match); + EINA_LIST_FOREACH(match, l, escb) + if ((!escb->just_added) && (!escb->delete_me)) + { + escb->func(escb->data, ed->obj, sig, src); + if (_edje_block_break(ed)) + goto break_prog; + } } ed->walking_callbacks = 0;