110 lines
3.0 KiB
C
110 lines
3.0 KiB
C
#include "gui.h"
|
|
#include "gui_defs.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
unsigned long register_notifier(gui *_g, char *notification, widget *w,
|
|
notifier handler, void *private) {
|
|
struct gui *g = _g;
|
|
unsigned long ret;
|
|
glock(g);
|
|
|
|
if (g->next_notifier_id == 2UL * 1024 * 1024 * 1024)
|
|
ERR("%s:%d: report a bug\n", __FILE__, __LINE__);
|
|
|
|
g->notifiers = realloc(g->notifiers,
|
|
(g->notifiers_count+1) * sizeof(struct notifier));
|
|
|
|
if (g->notifiers == NULL) abort();
|
|
|
|
ret = g->next_notifier_id;
|
|
g->notifiers[g->notifiers_count].handler = handler;
|
|
g->notifiers[g->notifiers_count].id = g->next_notifier_id;
|
|
g->next_notifier_id++;
|
|
g->notifiers[g->notifiers_count].notification = strdup(notification);
|
|
|
|
if (g->notifiers[g->notifiers_count].notification == NULL) abort();
|
|
|
|
g->notifiers[g->notifiers_count].w = w;
|
|
g->notifiers[g->notifiers_count].private = private;
|
|
/* initialize done to 1 so as not to call the handler if it's created
|
|
* by the call of another one that is in progress
|
|
*/
|
|
g->notifiers[g->notifiers_count].done = 1;
|
|
g->notifiers_count++;
|
|
gunlock(g);
|
|
return ret;
|
|
}
|
|
|
|
void unregister_notifier(gui *_g, unsigned long notifier_id) {
|
|
struct gui *g = _g;
|
|
int i;
|
|
glock(g);
|
|
|
|
for (i = 0; i < g->notifiers_count; i++)
|
|
if (g->notifiers[i].id == notifier_id) break;
|
|
|
|
if (i == g->notifiers_count)
|
|
ERR("%s:%d: notifier_id %lu not found\n", __FILE__,__LINE__,notifier_id);
|
|
|
|
free(g->notifiers[i].notification);
|
|
memmove(g->notifiers + i, g->notifiers + i + 1,
|
|
(g->notifiers_count-1 - i) * sizeof(struct notifier));
|
|
g->notifiers_count--;
|
|
g->notifiers = realloc(g->notifiers,
|
|
g->notifiers_count * sizeof(struct notifier));
|
|
|
|
if (g->notifiers == NULL) abort();
|
|
|
|
gunlock(g);
|
|
}
|
|
|
|
/* called with lock ON */
|
|
void gui_notify(struct gui *g, char *notification, widget *w,
|
|
void *notification_data) {
|
|
void *private;
|
|
notifier handler;
|
|
int i;
|
|
/* this function is not re-entrant, for the moment keep as is
|
|
* and if the need is there, we'll make a new thread to handle
|
|
* notifications (or something)
|
|
* for now let's crash in case of recursive call
|
|
*/
|
|
static int inside = 0;
|
|
|
|
if (inside) ERR("%s:%d: BUG! contact the authors\n", __FILE__, __LINE__);
|
|
|
|
inside = 1;
|
|
|
|
/* clear all handlers */
|
|
/* TODO: speedup */
|
|
for (i = 0; i < g->notifiers_count; i++) g->notifiers[i].done = 0;
|
|
|
|
/* calling the handler may modify the list of notifiers, we
|
|
* need to be careful here
|
|
*/
|
|
loop:
|
|
|
|
for (i = 0; i < g->notifiers_count; i++) {
|
|
if (g->notifiers[i].done == 1 ||
|
|
g->notifiers[i].w != w ||
|
|
strcmp(g->notifiers[i].notification, notification) != 0)
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
|
|
if (i == g->notifiers_count) goto done;
|
|
|
|
g->notifiers[i].done = 1;
|
|
handler = g->notifiers[i].handler;
|
|
private = g->notifiers[i].private;
|
|
gunlock(g);
|
|
handler(private, g, notification, w, notification_data);
|
|
glock(g);
|
|
goto loop;
|
|
done:
|
|
inside = 0;
|
|
}
|