From bd84da7179534ac03a094e423623d68f321425cf Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Thu, 16 May 2019 12:27:04 -0400 Subject: [PATCH] More implementation of uiEvent. Now we'll need to deal with memory allocation. --- common/errors.c | 1 + common/events.c | 75 ++++++++++++++++++++++++++++++++++++++----------- common/uipriv.h | 1 + doc/events.md | 2 +- ui.h | 2 +- 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/common/errors.c b/common/errors.c index f3fe1da1..8f111841 100644 --- a/common/errors.c +++ b/common/errors.c @@ -29,6 +29,7 @@ static const char *messages[uiprivNumProgrammerErrors] = { [uiprivProgrammerErrorIndexOutOfRange] = "index %d out of range in %s()", [uiprivProgrammerErrorNullPointer] = "invalid null pointer for %s passed into %s()", [uiprivProgrammerErrorIntIDNotFound] = "%s identifier %d not found in %s()", + [uiprivProgrammerErrorBadSenderForEvent] = "attempt to use a %s sender with a %s event in %s()", [uiprivProgrammerErrorChangingEventDuringFire] = "attempt to change a uiEvent with %s() while it is firing", [uiprivProgrammerErrorRecursiveEventFire] = "attempt to fire a uiEvent while it is already being fired", }; diff --git a/common/events.c b/common/events.c index 6ba5548f..eafd668c 100644 --- a/common/events.c +++ b/common/events.c @@ -24,15 +24,6 @@ static int handlerCmp(const void *a, const void *b) return 0; } -static struct handler *handlerFind(struct handler *handlers, size_t len, int id) -{ - struct handler key; - - memset(&key, 0, sizeof (struct handler)); - key.id = id; - return (struct handler *) bsearch(&key, handlers, len, sizeof (struct handler), handlerCmp); -} - static void handlerSort(struct handler *handlers, size_t len) { qsort(handlers, len, sizeof (struct handler), handlerCmp); @@ -46,8 +37,12 @@ struct uiEvent { bool firing; }; -uiEvent *uiNewEvent(uiEventOptions *options) +uiEvent *uiNewEvent(const uiEventOptions *options) { + if (options == NULL) { + uiprivProgrammerError(uiprivProgrammerErrorNullPointer, "uiEventOptions", __func__); + return NULL; + } } #define checkEventNonnull(e, ...) if ((e) == NULL) { \ @@ -59,10 +54,47 @@ uiEvent *uiNewEvent(uiEventOptions *options) return __VA_ARGS__; \ } +static bool checkEventSender(const uiEvent *e, void *sender, const char *func) +{ + if (e->opts.Global && sender != NULL) { + uiprivProgrammerError(uiprivProgrammerErrorBadSenderForEvent, "non-NULL", "global", func); + return false; + } + if (!e->opts.Global && sender == NULL) { + uiprivProgrammerError(uiprivProgrammerErrorBadSenderForEvent, "NULL", "non-global", func); + return false; + } + return true; +} + int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data) { checkEventNonnull(e, 0); checkEventNotFiring(e, 0); + if (handler == NULL) { + uiprivProgrammerError(uiprivProgrammerErrorNullPointer, "uiEventHandler", __func__); + return 0; + } + if (!checkEventSender(e, sender, __func__)) + return 0; +} + +static struct handler *findHandler(const uiEvent *e, int id, const char *func) +{ + struct handler key; + struct handler *ret; + + if (e->len == 0) + goto notFound; + memset(&key, 0, sizeof (struct handler)); + key.id = id; + ret = (struct handler *) bsearch(&key, e->handlers, e->len, sizeof (struct handler), handlerCmp); + if (ret != NULL) + return ret; + // otherwise fall through +notFound: + uiprivProgrammerError(uiprivProgrammerErrorIntIDNotFound, "uiEvent handler", id, func); + return NULL; } void uiEventDeleteHandler(uiEvent *e, int id) @@ -71,11 +103,9 @@ void uiEventDeleteHandler(uiEvent *e, int id) checkEventNonnull(e); checkEventNotFiring(e); - if (e->len == 0) - TODO - h = handlerFind(e->handlers, e->len, id); + h = findHandler(e, id, __func__); if (h == NULL) - TODO + return; e->len--; memmove(h + 1, h, (e->len - (h - e->handlers)) * sizeof (struct handler)); } @@ -90,8 +120,9 @@ void uiEventFire(uiEvent *e, void *sender, void *args) uiprivProgrammerError(uiprivProgrammerErrorRecursiveEventFire); return; } - if (e->opts.Global && sender != NULL) - TODO + if (!checkEventSender(e, sender, __func__)) + return; + e->firing = true; h = e->handlers; for (i = 0; i < e->len; i++) { @@ -104,11 +135,23 @@ void uiEventFire(uiEvent *e, void *sender, void *args) bool uiEventHandlerBlocked(const uiEvent *e, int id) { + struct handler *h; + checkEventNonnull(e, false); + h = findHandler(e, id, __func__); + if (h == NULL) + return false; + return h->blocked; } void uiEventSetHandlerBlocked(uiEvent *e, int id, bool blocked) { + struct handler *h; + checkEventNonnull(e); checkEventNotFiring(e); + h = findHandler(e, id, __func__); + if (h == NULL) + return; + h->blocked = blocked; } diff --git a/common/uipriv.h b/common/uipriv.h index 839a9b9e..d54b5708 100644 --- a/common/uipriv.h +++ b/common/uipriv.h @@ -18,6 +18,7 @@ enum { uiprivProgrammerErrorNullPointer, // arguments: const char *paramDesc, __func__ uiprivProgrammerErrorIntIDNotFound, // arguments: const char *idDesc, int badID, __func__ // TODO type mismatch + uiprivProgrammerErrorBadSenderForEvent, // arguments: const char *senderDesc, const char *eventDesc, __func__ uiprivProgrammerErrorChangingEventDuringFire, // arguments: __func__ uiprivProgrammerErrorRecursiveEventFire, // no arguments uiprivNumProgrammerErrors, diff --git a/doc/events.md b/doc/events.md index 168a6a8f..d0647ec6 100644 --- a/doc/events.md +++ b/doc/events.md @@ -43,7 +43,7 @@ If `Global` is true, the event is "global" — there are no specific senders, an ### `uiNewEvent()` ```c -uiEvent *uiNewEvent(uiEventOptions *options); +uiEvent *uiNewEvent(const uiEventOptions *options); ``` `uiNewEvent()` creates a new `uiEvent` with the given options. diff --git a/ui.h b/ui.h index 5e234ce8..82a1570b 100644 --- a/ui.h +++ b/ui.h @@ -53,7 +53,7 @@ struct uiEventOptions { bool Global; }; -uiprivExtern uiEvent *uiNewEvent(uiEventOptions *options); +uiprivExtern uiEvent *uiNewEvent(const uiEventOptions *options); // TODO uiFreeEvent() uiprivExtern int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data); uiprivExtern void uiEventDeleteHandler(uiEvent *e, int id);