More implementation of uiEvent. Now we'll need to deal with memory allocation.

This commit is contained in:
Pietro Gagliardi 2019-05-16 12:27:04 -04:00
parent caa926feeb
commit bd84da7179
5 changed files with 63 additions and 18 deletions

View File

@ -29,6 +29,7 @@ static const char *messages[uiprivNumProgrammerErrors] = {
[uiprivProgrammerErrorIndexOutOfRange] = "index %d out of range in %s()", [uiprivProgrammerErrorIndexOutOfRange] = "index %d out of range in %s()",
[uiprivProgrammerErrorNullPointer] = "invalid null pointer for %s passed into %s()", [uiprivProgrammerErrorNullPointer] = "invalid null pointer for %s passed into %s()",
[uiprivProgrammerErrorIntIDNotFound] = "%s identifier %d not found in %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", [uiprivProgrammerErrorChangingEventDuringFire] = "attempt to change a uiEvent with %s() while it is firing",
[uiprivProgrammerErrorRecursiveEventFire] = "attempt to fire a uiEvent while it is already being fired", [uiprivProgrammerErrorRecursiveEventFire] = "attempt to fire a uiEvent while it is already being fired",
}; };

View File

@ -24,15 +24,6 @@ static int handlerCmp(const void *a, const void *b)
return 0; 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) static void handlerSort(struct handler *handlers, size_t len)
{ {
qsort(handlers, len, sizeof (struct handler), handlerCmp); qsort(handlers, len, sizeof (struct handler), handlerCmp);
@ -46,8 +37,12 @@ struct uiEvent {
bool firing; 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) { \ #define checkEventNonnull(e, ...) if ((e) == NULL) { \
@ -59,10 +54,47 @@ uiEvent *uiNewEvent(uiEventOptions *options)
return __VA_ARGS__; \ 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) int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data)
{ {
checkEventNonnull(e, 0); checkEventNonnull(e, 0);
checkEventNotFiring(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) void uiEventDeleteHandler(uiEvent *e, int id)
@ -71,11 +103,9 @@ void uiEventDeleteHandler(uiEvent *e, int id)
checkEventNonnull(e); checkEventNonnull(e);
checkEventNotFiring(e); checkEventNotFiring(e);
if (e->len == 0) h = findHandler(e, id, __func__);
TODO
h = handlerFind(e->handlers, e->len, id);
if (h == NULL) if (h == NULL)
TODO return;
e->len--; e->len--;
memmove(h + 1, h, (e->len - (h - e->handlers)) * sizeof (struct handler)); 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); uiprivProgrammerError(uiprivProgrammerErrorRecursiveEventFire);
return; return;
} }
if (e->opts.Global && sender != NULL) if (!checkEventSender(e, sender, __func__))
TODO return;
e->firing = true; e->firing = true;
h = e->handlers; h = e->handlers;
for (i = 0; i < e->len; i++) { 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) bool uiEventHandlerBlocked(const uiEvent *e, int id)
{ {
struct handler *h;
checkEventNonnull(e, false); checkEventNonnull(e, false);
h = findHandler(e, id, __func__);
if (h == NULL)
return false;
return h->blocked;
} }
void uiEventSetHandlerBlocked(uiEvent *e, int id, bool blocked) void uiEventSetHandlerBlocked(uiEvent *e, int id, bool blocked)
{ {
struct handler *h;
checkEventNonnull(e); checkEventNonnull(e);
checkEventNotFiring(e); checkEventNotFiring(e);
h = findHandler(e, id, __func__);
if (h == NULL)
return;
h->blocked = blocked;
} }

View File

@ -18,6 +18,7 @@ enum {
uiprivProgrammerErrorNullPointer, // arguments: const char *paramDesc, __func__ uiprivProgrammerErrorNullPointer, // arguments: const char *paramDesc, __func__
uiprivProgrammerErrorIntIDNotFound, // arguments: const char *idDesc, int badID, __func__ uiprivProgrammerErrorIntIDNotFound, // arguments: const char *idDesc, int badID, __func__
// TODO type mismatch // TODO type mismatch
uiprivProgrammerErrorBadSenderForEvent, // arguments: const char *senderDesc, const char *eventDesc, __func__
uiprivProgrammerErrorChangingEventDuringFire, // arguments: __func__ uiprivProgrammerErrorChangingEventDuringFire, // arguments: __func__
uiprivProgrammerErrorRecursiveEventFire, // no arguments uiprivProgrammerErrorRecursiveEventFire, // no arguments
uiprivNumProgrammerErrors, uiprivNumProgrammerErrors,

View File

@ -43,7 +43,7 @@ If `Global` is true, the event is "global" — there are no specific senders, an
### `uiNewEvent()` ### `uiNewEvent()`
```c ```c
uiEvent *uiNewEvent(uiEventOptions *options); uiEvent *uiNewEvent(const uiEventOptions *options);
``` ```
`uiNewEvent()` creates a new `uiEvent` with the given options. `uiNewEvent()` creates a new `uiEvent` with the given options.

2
ui.h
View File

@ -53,7 +53,7 @@ struct uiEventOptions {
bool Global; bool Global;
}; };
uiprivExtern uiEvent *uiNewEvent(uiEventOptions *options); uiprivExtern uiEvent *uiNewEvent(const uiEventOptions *options);
// TODO uiFreeEvent() // TODO uiFreeEvent()
uiprivExtern int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data); uiprivExtern int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data);
uiprivExtern void uiEventDeleteHandler(uiEvent *e, int id); uiprivExtern void uiEventDeleteHandler(uiEvent *e, int id);