forked from enlightenment/efl
795 lines
26 KiB
C
795 lines
26 KiB
C
#include "edje_private.h"
|
|
|
|
/* States manipulations. */
|
|
|
|
typedef struct _Edje_State Edje_State;
|
|
struct _Edje_State
|
|
{
|
|
size_t idx;
|
|
size_t pos;
|
|
};
|
|
|
|
struct _Edje_States
|
|
{
|
|
size_t size;
|
|
Edje_State *states;
|
|
_Bool *has;
|
|
};
|
|
|
|
static void
|
|
_edje_match_states_free(Edje_States *states,
|
|
size_t states_size)
|
|
{
|
|
(void) states_size;
|
|
free(states);
|
|
}
|
|
|
|
#define ALIGN(Size) \
|
|
{ \
|
|
Size--; \
|
|
Size |= sizeof (void*) - 1; \
|
|
Size++; \
|
|
};
|
|
|
|
static int
|
|
_edje_match_states_alloc(Edje_Patterns *ppat, int n)
|
|
{
|
|
Edje_States *l;
|
|
|
|
const size_t patterns_size = ppat->patterns_size;
|
|
const size_t patterns_max_length = ppat->max_length;
|
|
|
|
const size_t array_len = (patterns_max_length + 1) * patterns_size;
|
|
|
|
size_t states_size;
|
|
size_t has_size;
|
|
size_t states_has_size;
|
|
size_t struct_size;
|
|
|
|
unsigned char *states;
|
|
unsigned char *has;
|
|
|
|
int i;
|
|
|
|
states_size = sizeof (*l->states) * array_len;
|
|
ALIGN(states_size);
|
|
|
|
has_size = sizeof (*l->has) * array_len;
|
|
ALIGN(has_size);
|
|
|
|
states_has_size = states_size + has_size;
|
|
|
|
struct_size = sizeof (*l);
|
|
ALIGN(struct_size);
|
|
struct_size += states_has_size;
|
|
|
|
l = malloc(n * struct_size);
|
|
if (!l) return 0;
|
|
|
|
ppat->states = l;
|
|
ppat->states->size = 0;
|
|
|
|
states = (unsigned char *) (l + n);
|
|
has = states + states_size;
|
|
|
|
for (i = 0; i < n; ++i)
|
|
{
|
|
l[i].states = (Edje_State *) states;
|
|
l[i].has = (_Bool *) has;
|
|
|
|
memset(l[i].has, 0, has_size);
|
|
|
|
states += states_has_size;
|
|
has += states_has_size;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
_edje_match_states_insert(Edje_States *list,
|
|
size_t patterns_max_length,
|
|
size_t idx,
|
|
size_t pos)
|
|
{
|
|
size_t i;
|
|
|
|
i = (idx * (patterns_max_length + 1)) + pos;
|
|
|
|
if (i < list->size)
|
|
{
|
|
if (list->has[i]) return;
|
|
}
|
|
list->has[i] = 1;
|
|
|
|
i = list->size;
|
|
list->states[i].idx = idx;
|
|
list->states[i].pos = pos;
|
|
list->has[i] = 0;
|
|
list->size++;
|
|
}
|
|
|
|
static void
|
|
_edje_match_states_clear(Edje_States *list,
|
|
__UNUSED__ size_t patterns_size,
|
|
__UNUSED__ size_t patterns_max_length)
|
|
{
|
|
list->size = 0;
|
|
}
|
|
|
|
/* Token manipulation. */
|
|
|
|
enum status
|
|
{
|
|
patterns_not_found = 0,
|
|
patterns_found = 1,
|
|
patterns_syntax_error = 2
|
|
};
|
|
|
|
static size_t
|
|
_edje_match_patterns_exec_class_token(enum status *status,
|
|
const char *cl_tok,
|
|
char c)
|
|
{
|
|
if (! *cl_tok)
|
|
{
|
|
*status = patterns_syntax_error;
|
|
return 0;
|
|
}
|
|
else if (cl_tok[1] == '-' && cl_tok[2] != ']')
|
|
{
|
|
if (*cl_tok <= c && c <= cl_tok[2])
|
|
*status = patterns_found;
|
|
return 3;
|
|
}
|
|
else
|
|
{
|
|
if (c == *cl_tok)
|
|
*status = patterns_found;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static Edje_Match_Error
|
|
_edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret)
|
|
{
|
|
switch (*cl_tok)
|
|
{
|
|
case 0:
|
|
return EDJE_MATCH_SYNTAX_ERROR;
|
|
|
|
case '!':
|
|
*ret = 1;
|
|
return EDJE_MATCH_OK;
|
|
|
|
default:
|
|
*ret = 0;
|
|
return EDJE_MATCH_OK;
|
|
}
|
|
}
|
|
|
|
static Edje_Match_Error
|
|
_edje_match_patterns_exec_class(const char *cl,
|
|
char c,
|
|
size_t *ret)
|
|
{
|
|
enum status status = patterns_not_found;
|
|
int pos = 1;
|
|
size_t neg;
|
|
|
|
if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK)
|
|
return EDJE_MATCH_SYNTAX_ERROR;
|
|
|
|
pos += neg;
|
|
|
|
do
|
|
{
|
|
pos += _edje_match_patterns_exec_class_token(&status, cl + pos, c);
|
|
}
|
|
while (cl[pos] && cl[pos] != ']');
|
|
|
|
if (status == patterns_syntax_error || ! cl[pos])
|
|
return EDJE_MATCH_SYNTAX_ERROR;
|
|
|
|
if (status == patterns_found)
|
|
*ret = neg ? 0 : pos + 1;
|
|
else
|
|
*ret = neg ? pos + 1 : 0;
|
|
|
|
return EDJE_MATCH_OK;
|
|
}
|
|
|
|
static Edje_Match_Error
|
|
_edje_match_patterns_exec_token(const char *tok,
|
|
char c,
|
|
size_t *ret)
|
|
{
|
|
switch (*tok)
|
|
{
|
|
case '\\':
|
|
if (tok[1])
|
|
{
|
|
*ret = tok[1] == c ? 2 : 0;
|
|
return EDJE_MATCH_OK;
|
|
}
|
|
return EDJE_MATCH_SYNTAX_ERROR;
|
|
|
|
case '?':
|
|
*ret = 1;
|
|
return EDJE_MATCH_OK;
|
|
|
|
case '[':
|
|
return _edje_match_patterns_exec_class(tok, c, ret);
|
|
|
|
default:
|
|
*ret = *tok == c ? 1 : 0;
|
|
return EDJE_MATCH_OK;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_edje_match_patterns_exec_init_states(Edje_States *states,
|
|
size_t patterns_size,
|
|
size_t patterns_max_length)
|
|
{
|
|
size_t i;
|
|
|
|
states->size = patterns_size;
|
|
|
|
for (i = 0; i < patterns_size; ++i)
|
|
{
|
|
states->states[i].idx = i;
|
|
states->states[i].pos = 0;
|
|
states->has[i * (patterns_max_length + 1)] = 1;
|
|
}
|
|
}
|
|
|
|
/* Exported function. */
|
|
|
|
#define EDJE_MATCH_INIT_LIST(Func, Type, Source, Show) \
|
|
Edje_Patterns* \
|
|
Func(const Eina_List *lst) \
|
|
{ \
|
|
Edje_Patterns *r; \
|
|
size_t i; \
|
|
\
|
|
if (!lst || eina_list_count(lst) <= 0) \
|
|
return NULL; \
|
|
\
|
|
r = malloc(sizeof (Edje_Patterns) + \
|
|
eina_list_count(lst) \
|
|
* sizeof(*r->finals) \
|
|
* sizeof(*r->patterns)); \
|
|
if (!r) return NULL; \
|
|
\
|
|
r->ref = 1; \
|
|
r->delete_me = 0; \
|
|
r->patterns_size = eina_list_count(lst); \
|
|
r->max_length = 0; \
|
|
r->patterns = (const char **) r->finals + r->patterns_size + 1; \
|
|
\
|
|
for (i = 0; lst; ++i) \
|
|
{ \
|
|
const char *str; \
|
|
Type *data; \
|
|
size_t j; \
|
|
\
|
|
data = eina_list_data_get(lst); \
|
|
if (!data) \
|
|
{ \
|
|
free(r); \
|
|
return NULL; \
|
|
} \
|
|
\
|
|
str = data->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; \
|
|
\
|
|
if (j > r->max_length) \
|
|
r->max_length = j; \
|
|
\
|
|
lst = eina_list_next(lst); \
|
|
} \
|
|
\
|
|
if (!_edje_match_states_alloc(r, 2)) \
|
|
{ \
|
|
free(r); \
|
|
return NULL; \
|
|
} \
|
|
\
|
|
return r; \
|
|
}
|
|
|
|
#define EDJE_MATCH_INIT_ARRAY(Func, Type, Source, Show) \
|
|
Edje_Patterns* \
|
|
Func(Type * const *lst, unsigned int count) \
|
|
{ \
|
|
Edje_Patterns *r; \
|
|
size_t i; \
|
|
\
|
|
if (!lst || count == 0) \
|
|
return NULL; \
|
|
\
|
|
r = malloc(sizeof (Edje_Patterns) + \
|
|
count \
|
|
* sizeof(*r->finals) \
|
|
* sizeof(*r->patterns)); \
|
|
if (!r) return NULL; \
|
|
\
|
|
r->ref = 1; \
|
|
r->delete_me = 0; \
|
|
r->patterns_size = count; \
|
|
r->max_length = 0; \
|
|
r->patterns = (const char **) r->finals + r->patterns_size + 1; \
|
|
\
|
|
for (i = 0; i < count; ++i) \
|
|
{ \
|
|
const char *str; \
|
|
size_t j; \
|
|
\
|
|
if (!lst[i]) \
|
|
{ \
|
|
free(r); \
|
|
return NULL; \
|
|
} \
|
|
\
|
|
str = lst[i]->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; \
|
|
\
|
|
if (j > r->max_length) \
|
|
r->max_length = j; \
|
|
} \
|
|
\
|
|
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);
|
|
EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init,
|
|
Edje_Program,
|
|
signal, 0);
|
|
EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init,
|
|
Edje_Program,
|
|
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,
|
|
const Edje_States *states)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < states->size; ++i)
|
|
{
|
|
if (states->states[i].pos >= finals[states->states[i].idx])
|
|
return EINA_TRUE;
|
|
}
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
edje_match_programs_exec_check_finals(const size_t *signal_finals,
|
|
const size_t *source_finals,
|
|
const Edje_States *signal_states,
|
|
const Edje_States *source_states,
|
|
Edje_Program **programs,
|
|
Eina_Bool (*func)(Edje_Program *pr, void *data),
|
|
void *data)
|
|
{
|
|
size_t i;
|
|
size_t j;
|
|
|
|
/* when not enought memory, they could be NULL */
|
|
if (!signal_finals || !source_finals) return EINA_TRUE;
|
|
|
|
for (i = 0; i < signal_states->size; ++i)
|
|
{
|
|
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])
|
|
{
|
|
Edje_Program *pr;
|
|
|
|
pr = programs[signal_states->states[i].idx];
|
|
if (pr)
|
|
{
|
|
if (func(pr, data))
|
|
return EINA_FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
edje_match_callback_exec_check_finals(const Edje_Patterns *singal_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 *signal,
|
|
const char *source,
|
|
Eina_List *callbacks,
|
|
Edje *ed)
|
|
{
|
|
size_t i;
|
|
size_t j;
|
|
int r = 1;
|
|
|
|
for (i = 0; i < signal_states->size; ++i)
|
|
{
|
|
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])
|
|
{
|
|
Edje_Signal_Callback *escb;
|
|
|
|
escb = eina_list_nth(callbacks, signal_states->states[i].idx);
|
|
if (escb)
|
|
{
|
|
if ((!escb->just_added)
|
|
&& (!escb->delete_me))
|
|
{
|
|
escb->func(escb->data, ed->obj, signal, source);
|
|
r = 2;
|
|
}
|
|
if (_edje_block_break(ed))
|
|
return 0;
|
|
if ((singal_ppat->delete_me) || (source_ppat->delete_me))
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
static Edje_States*
|
|
_edje_match_fn(const Edje_Patterns *ppat,
|
|
const char *string,
|
|
Edje_States *states)
|
|
{
|
|
Edje_States *new_states = states + 1;
|
|
const char *c;
|
|
|
|
for (c = string; *c && states->size; ++c)
|
|
{
|
|
size_t i;
|
|
|
|
_edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length);
|
|
|
|
for (i = 0; i < states->size; ++i)
|
|
{
|
|
const size_t idx = states->states[i].idx;
|
|
const size_t pos = states->states[i].pos;
|
|
|
|
if (!ppat->patterns[idx][pos])
|
|
continue;
|
|
else if (ppat->patterns[idx][pos] == '*')
|
|
{
|
|
_edje_match_states_insert(states, ppat->max_length, idx, pos + 1);
|
|
_edje_match_states_insert(new_states, ppat->max_length, idx, pos);
|
|
}
|
|
else
|
|
{
|
|
size_t m;
|
|
|
|
if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos,
|
|
*c,
|
|
&m) != EDJE_MATCH_OK)
|
|
return NULL;
|
|
|
|
if (m)
|
|
_edje_match_states_insert(new_states, ppat->max_length, idx, pos + m);
|
|
}
|
|
}
|
|
{
|
|
Edje_States *tmp = states;
|
|
|
|
states = new_states;
|
|
new_states = tmp;
|
|
}
|
|
}
|
|
|
|
return states;
|
|
}
|
|
|
|
Eina_Bool
|
|
edje_match_collection_dir_exec(const Edje_Patterns *ppat,
|
|
const char *string)
|
|
{
|
|
Edje_States *result;
|
|
Eina_Bool r = EINA_FALSE;
|
|
|
|
/* under high memory presure, it could be NULL */
|
|
if (!ppat) return EINA_FALSE;
|
|
|
|
_edje_match_patterns_exec_init_states(ppat->states, ppat->patterns_size, ppat->max_length);
|
|
|
|
result = _edje_match_fn(ppat, string, ppat->states);
|
|
|
|
if (result)
|
|
r = _edje_match_collection_dir_exec_finals(ppat->finals, result);
|
|
|
|
return r;
|
|
}
|
|
|
|
Eina_Bool
|
|
edje_match_programs_exec(const Edje_Patterns *ppat_signal,
|
|
const Edje_Patterns *ppat_source,
|
|
const char *signal,
|
|
const char *source,
|
|
Edje_Program **programs,
|
|
Eina_Bool (*func)(Edje_Program *pr, void *data),
|
|
void *data)
|
|
{
|
|
Edje_States *signal_result;
|
|
Edje_States *source_result;
|
|
Eina_Bool r = EINA_FALSE;
|
|
|
|
/* under high memory presure, they could be NULL */
|
|
if (!ppat_source || !ppat_signal) return EINA_FALSE;
|
|
|
|
_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(ppat_signal, signal, ppat_signal->states);
|
|
source_result = _edje_match_fn(ppat_source, source, ppat_source->states);
|
|
|
|
if (signal_result && source_result)
|
|
r = edje_match_programs_exec_check_finals(ppat_signal->finals,
|
|
ppat_source->finals,
|
|
signal_result,
|
|
source_result,
|
|
programs,
|
|
func,
|
|
data);
|
|
return r;
|
|
}
|
|
|
|
int
|
|
edje_match_callback_exec(Edje_Patterns *ppat_signal,
|
|
Edje_Patterns *ppat_source,
|
|
const char *signal,
|
|
const char *source,
|
|
Eina_List *callbacks,
|
|
Edje *ed)
|
|
{
|
|
Edje_States *signal_result;
|
|
Edje_States *source_result;
|
|
int r = 0;
|
|
|
|
/* under high memory presure, they could be NULL */
|
|
if (!ppat_source || !ppat_signal) return 0;
|
|
|
|
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(ppat_signal, signal, 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(ppat_signal,
|
|
ppat_source,
|
|
ppat_signal->finals,
|
|
ppat_source->finals,
|
|
signal_result,
|
|
source_result,
|
|
signal,
|
|
source,
|
|
callbacks,
|
|
ed);
|
|
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;
|
|
}
|
|
|
|
void
|
|
edje_match_patterns_free(Edje_Patterns *ppat)
|
|
{
|
|
if (!ppat) return ;
|
|
|
|
ppat->delete_me = 1;
|
|
ppat->ref--;
|
|
if (ppat->ref > 0) return;
|
|
_edje_match_states_free(ppat->states, 2);
|
|
free(ppat);
|
|
}
|
|
|
|
void
|
|
_edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp)
|
|
{
|
|
if (!ssp->signals_patterns)
|
|
return;
|
|
|
|
edje_match_patterns_free(ssp->signals_patterns);
|
|
edje_match_patterns_free(ssp->sources_patterns);
|
|
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(Edje_Program * const *programs,
|
|
unsigned int count,
|
|
Eina_Rbtree **tree)
|
|
{
|
|
Eina_List *result = NULL;
|
|
Eina_Rbtree *new = NULL;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
if (programs[i]->signal && !strpbrk(programs[i]->signal, "*?[\\")
|
|
&& programs[i]->source && !strpbrk(programs[i]->source, "*?[\\"))
|
|
{
|
|
Edje_Signal_Source_Char *item;
|
|
|
|
item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, programs[i]->signal, 0,
|
|
EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), programs[i]->source);
|
|
if (!item)
|
|
{
|
|
item = malloc(sizeof (Edje_Signal_Source_Char));
|
|
if (!item) continue;
|
|
|
|
item->signal = programs[i]->signal;
|
|
item->source = programs[i]->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, programs[i]);
|
|
}
|
|
else
|
|
result = eina_list_prepend(result, programs[i]);
|
|
}
|
|
|
|
*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, "*?[\\")
|
|
&& callback->source && !strpbrk(callback->source, "*?[\\"))
|
|
{
|
|
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);
|
|
}
|