#include "gui.h" #include "gui_defs.h" #include #include #include 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; }