From f1b08663ddff6432289ca4780bc823c96d471657 Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Sat, 18 Apr 1998 04:02:46 +0000 Subject: Yes. Yes. It works. It loads, it saves, it does all that stuff. It works, even if federico complains that we did not test close. Repetition, alarms, all that stuff you all guys love. It it is there. We did minimal testing, but we know you will happilly commit a fix if you find a problem, right? Ok, we are off to a party now. Miguel svn path=/trunk/; revision=155 --- calendar/gui/alarm.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 calendar/gui/alarm.c (limited to 'calendar/gui/alarm.c') diff --git a/calendar/gui/alarm.c b/calendar/gui/alarm.c new file mode 100644 index 0000000000..bb5c4c1b8d --- /dev/null +++ b/calendar/gui/alarm.c @@ -0,0 +1,145 @@ +/* + * Alarm handling for the GNOME Calendar. + * + * (C) 1998 the Free Software Foundation + * + * Author: Miguel de Icaza (miguel@kernel.org) + */ +#include +#include +#include +#include +#include +#include +#include "alarm.h" + +/* The pipes used to notify about an alarm */ +int alarm_pipes [2]; + +/* The list of pending alarms */ +static GList *alarms; + +static void *head_alarm; + +typedef struct { + time_t activation_time; + AlarmFunction fn; + void *closure; +} AlarmRecord; + +/* + * SIGALRM handler. Notifies the callback about the alarm + */ +static void +alarm_activate () +{ + char c = 0; + + printf ("ALARMA!\n"); + write (alarm_pipes [1], &c, 1); +} + +static void +alarm_ready (void *closure, int fd, GdkInputCondition cond) +{ + AlarmRecord *ar = head_alarm; + char c; + + if (read (alarm_pipes [0], &c, 1) != 1) + return; + + if (ar == NULL){ + g_warning ("Empty events. This should not happen\n"); + return; + } + (*ar->fn)(ar->activation_time, ar->closure); + alarms = g_list_remove (alarms, head_alarm); + if (alarms) + head_alarm = alarms->data; + else + head_alarm = NULL; + g_free (ar); +} + +static int +alarm_compare_by_time (gpointer a, gpointer b) +{ + AlarmRecord *ara = a; + AlarmRecord *arb = b; + time_t diff; + + diff = ara->activation_time - arb->activation_time; + return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; +} + +void +alarm_add (time_t alarm_time, AlarmFunction fn, void *closure) +{ + time_t now = time (NULL); + AlarmRecord *ar; + + /* If it already expired, do not add it */ + if (alarm_time < now) + return; + + ar = g_new0 (AlarmRecord, 1); + ar->activation_time = alarm_time; + ar->fn = fn; + ar->closure = closure; + + alarms = g_list_insert_sorted (alarms, ar, alarm_compare_by_time); + + /* If first alarm is not the previous first alarm, reschedule SIGALRM */ + if (head_alarm != alarms->data){ + struct itimerval itimer; + int v; + + /* Set the timer to disable upon activation */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = 0; + itimer.it_value.tv_sec = alarm_time - now; + itimer.it_value.tv_usec = 0; + v = setitimer (ITIMER_REAL, &itimer, NULL); + head_alarm = alarms->data; + } +} + +void +alarm_kill (void *closure_key) +{ + GList *p; + + for (p = alarms; p; p = p->next){ + AlarmRecord *ar = p->data; + + if (ar->closure == closure_key){ + alarms = g_list_remove (alarms, p->data); + if (alarms) + head_alarm = alarms->data; + else + head_alarm = NULL; + return; + } + } +} + +void +alarm_init (void) +{ + struct sigaction sa; + int flags; + + pipe (alarm_pipes); + + /* set non blocking mode */ + fcntl (alarm_pipes [0], F_GETFL, &flags); + fcntl (alarm_pipes [0], F_SETFL, flags | O_NONBLOCK); + gdk_input_add (alarm_pipes [0], GDK_INPUT_READ, alarm_ready, 0); + + /* Setup the signal handler */ + sa.sa_handler = alarm_activate; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction (SIGALRM, &sa, NULL); +} + -- cgit v1.2.3