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()",
[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",
};

View File

@ -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;
}

View File

@ -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,

View File

@ -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.

2
ui.h
View File

@ -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);