gambas-source-code/main/gbx/gbx_event.c
gambas 09a0573e61 Replace my old sourceforge mail address by the new one.
[CONFIGURATION]
Replace my old sourceforge mail address by the new one.
2018-02-12 02:53:46 +01:00

271 lines
5.9 KiB
C

/***************************************************************************
gbx_event.c
(c) 2000-2017 Benoît Minisini <g4mba5@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __GBX_EVENT_C
#include "gb_common.h"
#include "gb_common_buffer.h"
#include "gbx_exec.h"
#include "gbx_api.h"
#include "gbx_event.h"
//#define DEBUG_ME 1
void *EVENT_Last = NULL;
char *EVENT_PreviousName = NULL;
char *EVENT_Name = NULL;
static EVENT_POST *_post_list = NULL;
static void check_event_method(CLASS *class, const char *name, CLASS_DESC_METHOD *desc, CLASS_EVENT *event)
{
int n = event->n_param;
if (n < desc->npmin)
{
/*printf("event->n_param = %d desc->npmin = %d desc->npmax = %d\n", event->n_param, desc->npmin, desc->npmax);*/
THROW(E_EVENT, CLASS_get_name(class), name, "Too many arguments");
}
if (n > desc->npmax)
{
if (!desc->npvar)
THROW(E_EVENT, CLASS_get_name(class), name, "Not enough arguments");
n = desc->npmax;
}
if (TYPE_compare_signature(desc->signature, n, (TYPE *)event->param, n, FALSE))
THROW(E_EVENT, CLASS_get_name(class), name, "Type mismatch");
if (desc->type != T_VOID)
THROW(E_EVENT, CLASS_get_name(class), name, "Not a procedure");
}
void EVENT_search(CLASS *class, ushort *event, const char *name, OBJECT *parent)
{
//ushort *event;
//ushort *self;
CLASS *class_parent;
int i, index;
const char *event_name;
CLASS_DESC *desc;
int kind;
int len_name, len_event_name;
char *func_name = COMMON_buffer;
char *pevent_name;
#if DEBUG_ME
fprintf(stderr, "EVENT_search: class = %s name = %s parent = %p\n", class->name, name, parent);
#endif
//event = OBJECT_event(object)->event;
//self = OBJECT_event(object)->self;
if (class->n_event <= 0)
return;
len_name = name ? strlen(name) : 0;
if (len_name == 0 || len_name >= (COMMON_BUF_MAX - 4))
{
memset(event, 0, class->n_event * sizeof(ushort));
return;
}
kind = parent->class == CLASS_Class ? CD_STATIC_METHOD : CD_METHOD;
if (kind == CD_STATIC_METHOD)
class_parent = (CLASS *)parent;
else
class_parent = parent->class;
strcpy(func_name, name);
pevent_name = &func_name[len_name];
*pevent_name++ = '_';
for (i = 0; i < class->n_event; i++)
{
event[i] = 0;
event_name = class->event[i].name;
if (*event_name == ':')
event_name++;
len_event_name = strlen(event_name);
if ((len_name + len_event_name + 1) >= COMMON_BUF_MAX)
continue;
strcpy(pevent_name, event_name);
index = CLASS_find_symbol(class_parent, func_name);
if (index != NO_SYMBOL)
{
desc = class_parent->table[index].desc;
if (CLASS_DESC_get_type(desc) == kind)
{
#if DEBUG_ME
fprintf(stderr, "EVENT_search: FOUND [%d] %s.%s index = %d parent = %s.%p\n", i, class_parent->name, func_name, index, parent->class->name, parent);
#endif
check_event_method(class_parent, func_name, &desc->method, &class->event[i]);
event[i] = index + 1;
}
}
#if 0
snprintf(func_name, COMMON_BUF_MAX, "ME_%s", event_name);
index = CLASS_find_symbol(class, func_name);
if (index != NO_SYMBOL)
{
desc = class->table[index].desc;
if (CLASS_DESC_get_type(desc) == CD_METHOD)
{
#if DEBUG_ME
printf("EVENT_search: FOUND [%d] %s.%s index = %d parent = %s.%p\n", i, class->name, func_name, index, parent->class->name, parent);
#endif
check_event_method(class, func_name, &desc->method, &class->event[i]);
if (!self)
{
ALLOC_ZERO(&self, sizeof(ushort) * class->n_event, "EVENT_search");
OBJECT_event(object)->self = self;
}
self[i] = index + 1;
}
}
#endif
}
}
void EVENT_exit()
{
EVENT_POST *ep;
while (_post_list)
{
ep = _post_list;
_post_list = _post_list->list.next;
FREE(&ep);
}
STRING_free(&EVENT_Name);
}
static void post(void (*func)(), int nparam, intptr_t param, intptr_t param2)
{
EVENT_POST *ep;
/*printf("EVENT_post\n");
fflush(NULL);*/
ALLOC(&ep, sizeof(EVENT_POST));
ep->func = func;
ep->nparam = nparam;
ep->param = param;
ep->param2 = param2;
LIST_insert(&_post_list, ep, &ep->list);
HOOK(post)();
}
void EVENT_post(void (*func)(), intptr_t param)
{
post(func, 1, param, 0);
}
void EVENT_post2(void (*func)(), intptr_t param, intptr_t param2)
{
post(func, 2, param, param2);
}
static void post_event(void *object, int event)
{
GB_Raise(object, event, 0);
OBJECT_UNREF(object);
}
void EVENT_post_event(void *object, int event)
{
OBJECT_REF(object);
post((void (*)())post_event, 2, (intptr_t)object, (intptr_t)event);
}
bool EVENT_check_post(void)
{
EVENT_POST *ep;
EVENT_POST save;
bool ret = FALSE;
#ifdef DEBUG_POST
fprintf(stderr, "EVENT_check_post: START\n");
#endif
while (_post_list)
{
ret = TRUE;
ep = _post_list;
save = *ep;
LIST_remove(&_post_list, _post_list, &_post_list->list);
FREE(&ep);
if (save.nparam == 1)
(*save.func)(save.param);
else
(*save.func)(save.param, save.param2);
}
/*norec = FALSE;*/
#ifdef DEBUG_POST
fprintf(stderr, "EVENT_check_post: END\n");
#endif
return ret;
}
char *EVENT_enter_name(const char *name)
{
char *save = EVENT_PreviousName;
EVENT_PreviousName = EVENT_Name;
EVENT_Name = (char *)name;
return save;
}
void EVENT_leave_name(const char *save)
{
EVENT_Name = EVENT_PreviousName;
EVENT_PreviousName = (char *)save;
}