enlightenment/src/bin/e_msg.c

151 lines
3.5 KiB
C

#include "e.h"
typedef struct _E_Msg_Event E_Msg_Event;
struct _E_Msg_Handler
{
void (*func)(void *data, const char *name, const char *info, int val, E_Object *obj, void *msgdata);
void *data;
unsigned char delete_me E_BITFIELD;
};
struct _E_Msg_Event
{
char *name;
char *info;
int val;
E_Object *obj;
void *msgdata;
void (*afterfunc)(void *data, E_Object *obj, void *msgdata);
void *afterdata;
};
/* local subsystem functions */
static Eina_Bool _e_msg_event_cb(void *data, int ev_type, void *ev);
static void _e_msg_event_free(void *data, void *ev);
/* local subsystem globals */
static Eina_List *handlers = NULL;
static Eina_List *del_handlers = NULL;
static int processing_handlers = 0;
static int E_EVENT_MSG = 0;
static Ecore_Event_Handler *hand = NULL;
/* externally accessible functions */
EINTERN int
e_msg_init(void)
{
E_EVENT_MSG = ecore_event_type_new();
hand = ecore_event_handler_add(E_EVENT_MSG, _e_msg_event_cb, NULL);
return 1;
}
EINTERN int
e_msg_shutdown(void)
{
while (handlers)
e_msg_handler_del(eina_list_data_get(handlers));
E_EVENT_MSG = 0;
if (hand) ecore_event_handler_del(hand);
hand = NULL;
return 1;
}
E_API void
e_msg_send(const char *name, const char *info, int val, E_Object *obj, void *msgdata, void (*afterfunc)(void *data, E_Object *obj, void *msgdata), void *afterdata)
{
unsigned int size, pos, name_len, info_len;
E_Msg_Event *ev;
name_len = info_len = 0;
size = sizeof(E_Msg_Event);
if (name) name_len = strlen(name) + 1;
if (info) info_len = strlen(info) + 1;
ev = malloc(size + name_len + info_len);
if (!ev) return;
pos = size;
if (name)
{
ev->name = ((char *)ev) + pos;
pos += name_len;
strcpy(ev->name, name);
}
if (info)
{
ev->info = ((char *)ev) + pos;
strcpy(ev->info, info);
}
ev->val = val;
ev->obj = obj;
ev->msgdata = msgdata;
ev->afterfunc = afterfunc;
ev->afterdata = afterdata;
if (ev->obj) e_object_ref(ev->obj);
ecore_event_add(E_EVENT_MSG, ev, _e_msg_event_free, NULL);
}
E_API E_Msg_Handler *
e_msg_handler_add(void (*func)(void *data, const char *name, const char *info, int val, E_Object *obj, void *msgdata), void *data)
{
E_Msg_Handler *emsgh;
emsgh = calloc(1, sizeof(E_Msg_Handler));
if (!emsgh) return NULL;
emsgh->func = func;
emsgh->data = data;
handlers = eina_list_append(handlers, emsgh);
return emsgh;
}
E_API void
e_msg_handler_del(E_Msg_Handler *emsgh)
{
if (processing_handlers > 0)
{
emsgh->delete_me = 1;
del_handlers = eina_list_append(del_handlers, emsgh);
}
else
{
handlers = eina_list_remove(handlers, emsgh);
free(emsgh);
}
}
/* local subsystem functions */
static Eina_Bool
_e_msg_event_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev)
{
E_Msg_Event *e;
Eina_List *l;
E_Msg_Handler *emsgh;
processing_handlers++;
e = ev;
EINA_LIST_FOREACH(handlers, l, emsgh)
{
if (!emsgh->delete_me)
emsgh->func(emsgh->data, e->name, e->info, e->val, e->obj, e->msgdata);
}
if (e->afterfunc) e->afterfunc(e->afterdata, e->obj, e->msgdata);
processing_handlers--;
if ((processing_handlers == 0) && (del_handlers))
{
E_FREE_LIST(del_handlers, e_msg_handler_del);
}
return 1;
}
static void
_e_msg_event_free(void *data EINA_UNUSED, void *ev)
{
E_Msg_Event *e;
e = ev;
if (e->obj) e_object_unref(e->obj);
E_FREE(ev);
}