Commit f2195ba4 authored by Cedric Roux's avatar Cedric Roux

notification system (from user input to application basically)

parent e742718c
...@@ -2,7 +2,7 @@ CC=gcc ...@@ -2,7 +2,7 @@ CC=gcc
CFLAGS=-Wall -g -pthread CFLAGS=-Wall -g -pthread
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \ OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
gui.o label.o event.o xy_plot.o text_list.o gui.o label.o event.o xy_plot.o text_list.o notify.o
gui.a: $(OBJS) gui.a: $(OBJS)
ar cr gui.a $(OBJS) ar cr gui.a $(OBJS)
......
...@@ -36,4 +36,19 @@ void gunlock(gui *gui); ...@@ -36,4 +36,19 @@ void gunlock(gui *gui);
int new_color(gui *gui, char *color); int new_color(gui *gui, char *color);
/* notifications */
/* known notifications:
* - text_list:
* - scrollup { }
* - scrolldown { }
* //- click { int line, int button }
*/
/* same type as in gui_defs.h */
typedef void (*notifier)(void *private, gui *g,
char *notification, widget *w, void *notification_data);
unsigned long register_notifier(gui *g, char *notification, widget *w,
notifier handler, void *private);
void unregister_notifier(gui *g, unsigned long notifier_id);
#endif /* _GUI_H_ */ #endif /* _GUI_H_ */
...@@ -143,6 +143,24 @@ struct repack_event { ...@@ -143,6 +143,24 @@ struct repack_event {
int id; int id;
}; };
/*************************************************************************/
/* notifications */
/*************************************************************************/
/* same type as in gui.h */
typedef void (*notifier)(void *private, gui *g,
char *notification, widget *w, void *notification_data);
struct notifier {
notifier handler;
unsigned long id;
char *notification;
widget *w;
void *private;
/* done is used bu gui_notify */
int done;
};
/*************************************************************************/ /*************************************************************************/
/* main structure */ /* main structure */
/*************************************************************************/ /*************************************************************************/
...@@ -161,6 +179,9 @@ struct gui { ...@@ -161,6 +179,9 @@ struct gui {
void *xwin; /* set by a toplevel_window when void *xwin; /* set by a toplevel_window when
* it paints itself, to be used * it paints itself, to be used
* by its children */ * by its children */
struct notifier *notifiers;
int notifiers_count;
unsigned long next_notifier_id;
}; };
/*************************************************************************/ /*************************************************************************/
...@@ -178,4 +199,7 @@ void gui_events(gui *gui); ...@@ -178,4 +199,7 @@ void gui_events(gui *gui);
struct widget *find_widget(struct gui *g, int id); struct widget *find_widget(struct gui *g, int id);
void gui_notify(struct gui *g, char *notification, widget *w,
void *notification_data);
#endif /* _GUI_DEFS_H_ */ #endif /* _GUI_DEFS_H_ */
#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)
{ printf("%s:%d: report a bug\n", __FILE__, __LINE__); abort(); }
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) {
printf("%s:%d: notifier_id %ld not found\n", __FILE__, __LINE__,
notifier_id);
abort();
}
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)
{printf("%s:%d: BUG! contact the authors\n", __FILE__, __LINE__);abort();}
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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment