aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog6
-rw-r--r--calendar/Makefile.am2
-rw-r--r--calendar/alarm.c145
-rw-r--r--calendar/alarm.h10
-rw-r--r--calendar/cal-util/calobj.c18
-rw-r--r--calendar/cal-util/calobj.h7
-rw-r--r--calendar/calendar.c69
-rw-r--r--calendar/calendar.h1
-rw-r--r--calendar/calobj.c18
-rw-r--r--calendar/calobj.h7
-rw-r--r--calendar/eventedit.c4
-rw-r--r--calendar/gnome-cal.c157
-rw-r--r--calendar/gnome-cal.h1
-rw-r--r--calendar/gui/Makefile.am2
-rw-r--r--calendar/gui/alarm-notify/alarm.c145
-rw-r--r--calendar/gui/alarm-notify/alarm.h10
-rw-r--r--calendar/gui/alarm.c145
-rw-r--r--calendar/gui/alarm.h10
-rw-r--r--calendar/gui/calendar.c69
-rw-r--r--calendar/gui/calendar.h1
-rw-r--r--calendar/gui/eventedit.c4
-rw-r--r--calendar/gui/gnome-cal.c157
-rw-r--r--calendar/gui/gnome-cal.h1
-rw-r--r--calendar/gui/main.c36
-rw-r--r--calendar/main.c36
-rw-r--r--calendar/pcs/calobj.c18
-rw-r--r--calendar/pcs/calobj.h7
-rw-r--r--calendar/timeutil.c2
28 files changed, 1033 insertions, 55 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 1bd14e83a0..a38f7e90d9 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,9 @@
+
+1998-04-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * alarm.c (alarm_kill, alarm_init, alarm_add): Implement the alarm
+ management framework.
+
1998-04-17 Federico Mena Quintero <federico@nuclecu.unam.mx>
* calobj.c (ical_new): Added mandatory status property.
diff --git a/calendar/Makefile.am b/calendar/Makefile.am
index b762dae475..9728a02d4b 100644
--- a/calendar/Makefile.am
+++ b/calendar/Makefile.am
@@ -9,6 +9,8 @@ INCLUDES = \
bin_PROGRAMS = gnomecal
gnomecal_SOURCES = \
+ alarm.c \
+ alarm.h \
calendar.c \
calendar.h \
calobj.c \
diff --git a/calendar/alarm.c b/calendar/alarm.c
new file mode 100644
index 0000000000..bb5c4c1b8d
--- /dev/null
+++ b/calendar/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 <config.h>
+#include <time.h>
+#include <gnome.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/time.h>
+#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);
+}
+
diff --git a/calendar/alarm.h b/calendar/alarm.h
new file mode 100644
index 0000000000..39f7281ce7
--- /dev/null
+++ b/calendar/alarm.h
@@ -0,0 +1,10 @@
+#ifndef ALARM_H
+#define ALARM_H
+
+typedef void (*AlarmFunction)(time_t time, void *closuse);
+
+void alarm_init (void);
+void alarm_add (time_t alarm_time, AlarmFunction fn, void *closure);
+void alarm_kill (void *closure);
+
+#endif
diff --git a/calendar/cal-util/calobj.c b/calendar/cal-util/calobj.c
index 47d8c8a97e..624a179b05 100644
--- a/calendar/cal-util/calobj.c
+++ b/calendar/cal-util/calobj.c
@@ -1102,3 +1102,21 @@ ical_object_compute_end (iCalObject *ico)
ico->recur->_enddate = 0;
ical_object_generate_events (ico, ico->dtstart, 0, duration_callback, &count);
}
+
+int
+alarm_compute_offset (CalendarAlarm *a)
+{
+ if (!a->enabled)
+ return -1;
+ switch (a->units){
+ case ALARM_MINUTES:
+ a->offset = a->count * 60;
+ break;
+ case ALARM_HOURS:
+ a->offset = a->count * 3600;
+ break;
+ case ALARM_DAYS:
+ a->offset = a->count * 24 * 3600;
+ }
+ return a->offset;
+}
diff --git a/calendar/cal-util/calobj.h b/calendar/cal-util/calobj.h
index 26b0acf35b..60483c68ad 100644
--- a/calendar/cal-util/calobj.h
+++ b/calendar/cal-util/calobj.h
@@ -32,6 +32,10 @@ typedef struct {
int count;
enum AlarmUnit units;
char *data;
+
+ /* Does not get saved, internally used */
+ time_t offset;
+ time_t trigger;
/* Widgets */
void *w_count; /* A GtkEntry */
@@ -180,6 +184,9 @@ void ical_object_generate_events (iCalObject *ico, time_t start, time
/* Computes the enddate field of the recurrence based on the duration */
void ical_object_compute_end (iCalObject *ico);
+/* Returns the number of seconds configured to trigger the alarm in advance to an event */
+int alarm_compute_offset (CalendarAlarm *a);
+
END_GNOME_DECLS
#endif
diff --git a/calendar/calendar.c b/calendar/calendar.c
index be45bb04bb..28f37f78eb 100644
--- a/calendar/calendar.c
+++ b/calendar/calendar.c
@@ -18,6 +18,9 @@
#include "timeutil.h"
#include "versit/vcc.h"
+/* Our day range */
+time_t calendar_day_begin, calendar_day_end;
+
Calendar *
calendar_new (char *title)
{
@@ -29,12 +32,71 @@ calendar_new (char *title)
return cal;
}
+static void
+try_add (iCalObject *ico, CalendarAlarm *alarm, time_t start, time_t end)
+{
+ alarm->trigger = start-alarm->offset;
+
+ if (alarm->trigger < calendar_day_begin)
+ return;
+ if (alarm->trigger > calendar_day_end)
+ return;
+ alarm_add (alarm->trigger, calendar_notify, ico);
+}
+
+static int
+add_alarm (iCalObject *obj, time_t start, time_t end, void *closure)
+{
+ if (obj->aalarm.enabled)
+ try_add (obj, &obj->aalarm, start, end);
+ if (obj->dalarm.enabled)
+ try_add (obj, &obj->dalarm, start, end);
+ if (obj->palarm.enabled)
+ try_add (obj,&obj->palarm, start, end);
+ if (obj->malarm.enabled)
+ try_add (obj, &obj->malarm, start, end);
+
+ return TRUE;
+}
+
+#define max(a,b) ((a > b) ? a : b)
+
+void
+ical_object_try_alarms (iCalObject *obj)
+{
+ GList *alarms, *p;
+ int ao, po, od, mo;
+ int max_o;
+
+ ao = alarm_compute_offset (&obj->aalarm);
+ po = alarm_compute_offset (&obj->palarm);
+ od = alarm_compute_offset (&obj->dalarm);
+ mo = alarm_compute_offset (&obj->malarm);
+
+ max_o = max (ao, max (po, max (od, mo)));
+ if (max_o == -1)
+ return;
+
+ ical_object_generate_events (obj, calendar_day_begin, calendar_day_end + max_o, add_alarm, obj);
+}
+
+void
+calendar_add_alarms (Calendar *cal)
+{
+ time_t now = time (NULL);
+ GList *events = cal->events;
+
+ for (; events; events=events->next)
+ ical_object_try_alarms (events->data);
+}
+
void
calendar_add_object (Calendar *cal, iCalObject *obj)
{
switch (obj->type){
case ICAL_EVENT:
cal->events = g_list_prepend (cal->events, obj);
+ ical_object_try_alarms (obj);
break;
case ICAL_TODO:
@@ -207,6 +269,7 @@ char *
calendar_load (Calendar *cal, char *fname)
{
VObject *vcal;
+ time_t calendar_today;
if (cal->filename){
g_warning ("Calendar load called again\n");
@@ -217,7 +280,11 @@ calendar_load (Calendar *cal, char *fname)
vcal = Parse_MIME_FromFileName (fname);
if (!vcal)
return "Could not load the calendar";
-
+
+ calendar_today = time (NULL);
+ calendar_day_begin = time_start_of_day (calendar_today);
+ calendar_day_end = time_end_of_day (calendar_today);
+
calendar_load_from_vobject (cal, vcal);
cleanVObject (vcal);
cleanStrTbl ();
diff --git a/calendar/calendar.h b/calendar/calendar.h
index 52cd2c90f6..91d0f3338c 100644
--- a/calendar/calendar.h
+++ b/calendar/calendar.h
@@ -54,6 +54,7 @@ GList *calendar_get_events_in_range (Calendar *cal, time_t start, time_t end
/* Destroy the above list with this method */
void calendar_destroy_event_list (GList *l);
+void calendar_notify (time_t, void *data);
END_GNOME_DECLS
#endif
diff --git a/calendar/calobj.c b/calendar/calobj.c
index 47d8c8a97e..624a179b05 100644
--- a/calendar/calobj.c
+++ b/calendar/calobj.c
@@ -1102,3 +1102,21 @@ ical_object_compute_end (iCalObject *ico)
ico->recur->_enddate = 0;
ical_object_generate_events (ico, ico->dtstart, 0, duration_callback, &count);
}
+
+int
+alarm_compute_offset (CalendarAlarm *a)
+{
+ if (!a->enabled)
+ return -1;
+ switch (a->units){
+ case ALARM_MINUTES:
+ a->offset = a->count * 60;
+ break;
+ case ALARM_HOURS:
+ a->offset = a->count * 3600;
+ break;
+ case ALARM_DAYS:
+ a->offset = a->count * 24 * 3600;
+ }
+ return a->offset;
+}
diff --git a/calendar/calobj.h b/calendar/calobj.h
index 26b0acf35b..60483c68ad 100644
--- a/calendar/calobj.h
+++ b/calendar/calobj.h
@@ -32,6 +32,10 @@ typedef struct {
int count;
enum AlarmUnit units;
char *data;
+
+ /* Does not get saved, internally used */
+ time_t offset;
+ time_t trigger;
/* Widgets */
void *w_count; /* A GtkEntry */
@@ -180,6 +184,9 @@ void ical_object_generate_events (iCalObject *ico, time_t start, time
/* Computes the enddate field of the recurrence based on the duration */
void ical_object_compute_end (iCalObject *ico);
+/* Returns the number of seconds configured to trigger the alarm in advance to an event */
+int alarm_compute_offset (CalendarAlarm *a);
+
END_GNOME_DECLS
#endif
diff --git a/calendar/eventedit.c b/calendar/eventedit.c
index 3ea0f674ec..39a92c5480 100644
--- a/calendar/eventedit.c
+++ b/calendar/eventedit.c
@@ -1265,7 +1265,7 @@ get_exception_string (time_t t)
{
static char buf[256];
- strftime (buf, 256, "%a %b %d %Y", localtime (&t)); /* FIXME: how to i18n this? */
+ strftime (buf, sizeof(buf), "%a %b %d %Y", localtime (&t)); /* FIXME: how to i18n this? */
return buf;
}
@@ -1483,7 +1483,7 @@ event_editor_new (GnomeCalendar *gcal, iCalObject *ical)
ee = EVENT_EDITOR (retval);
if (ical == 0){
- ical = ical_new ("Test Comment", user_name, "Test Summary");
+ ical = ical_new ("", user_name, "");
ical->new = 1;
}
diff --git a/calendar/gnome-cal.c b/calendar/gnome-cal.c
index 862c659d83..b851b65d44 100644
--- a/calendar/gnome-cal.c
+++ b/calendar/gnome-cal.c
@@ -6,6 +6,8 @@
*/
#include <gnome.h>
+#include <unistd.h>
+#include <signal.h>
#include "calendar.h"
#include "gnome-cal.h"
#include "gncal-full-day.h"
@@ -54,11 +56,22 @@ day_view_range_activated (GncalFullDay *fullday, GnomeCalendar *gcal)
}
static void
-setup_day_view (GnomeCalendar *gcal)
+set_day_view_label (GnomeCalendar *gcal, time_t t)
{
- time_t a, b, now;
+ static char buf[256];
+
+ strftime (buf, sizeof (buf), "%a %b %d %Y", localtime (&t));
+ gtk_label_set (GTK_LABEL (gcal->day_view_label), buf);
+}
+
+static void
+setup_day_view (GnomeCalendar *gcal, time_t now)
+{
+ GtkTable *t;
+ GtkWidget *sw;
+
+ time_t a, b;
- now = time (NULL);
a = time_start_of_day (now);
b = time_end_of_day (now);
@@ -66,12 +79,29 @@ setup_day_view (GnomeCalendar *gcal)
gtk_signal_connect (GTK_OBJECT (gcal->day_view), "range_activated",
(GtkSignalFunc) day_view_range_activated,
gcal);
- gcal->day_view_container = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (gcal->day_view_container),
+
+ t = (GtkTable *) gcal->day_view_container = gtk_table_new (0, 0, 0);
+ gtk_container_border_width (GTK_CONTAINER (t), 4);
+ gtk_table_set_row_spacings (t, 4);
+ gtk_table_set_col_spacings (t, 4);
+
+ gcal->day_view_label = gtk_label_new ("");
+ set_day_view_label (gcal, now);
+ gtk_table_attach (t, gcal->day_view_label, 0, 1, 0, 1,
+ GTK_FILL | GTK_SHRINK,
+ GTK_FILL | GTK_SHRINK,
+ 0, 0);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- gtk_container_add (GTK_CONTAINER (gcal->day_view_container), gcal->day_view);
- gtk_widget_show (gcal->day_view);
+ gtk_table_attach (t, sw, 0, 1, 1, 2,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+ 0, 0);
+ gtk_container_add (GTK_CONTAINER (sw), gcal->day_view);
+ gtk_widget_show_all (GTK_WIDGET (t));
}
static void
@@ -86,7 +116,7 @@ setup_widgets (GnomeCalendar *gcal)
gcal->year_view = gncal_year_view_new (gcal, now);
gcal->task_view = tasks_create (gcal);
- setup_day_view (gcal);
+ setup_day_view (gcal, now);
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->day_view_container, gtk_label_new (_("Day View")));
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->week_view, gtk_label_new (_("Week View")));
@@ -129,6 +159,7 @@ gnome_calendar_goto (GnomeCalendar *gcal, time_t new_time)
gncal_full_day_set_bounds (GNCAL_FULL_DAY (gcal->day_view),
time_start_of_day (new_time),
time_end_of_day (new_time));
+ set_day_view_label (gcal, new_time);
} else if (current == gcal->year_view)
gncal_year_view_set (GNCAL_YEAR_VIEW (gcal->year_view), new_time);
else
@@ -157,7 +188,7 @@ gnome_calendar_direction (GnomeCalendar *gcal, int direction)
void
gnome_calendar_next (GnomeCalendar *gcal)
{
- gnome_calendar_direction (gcal, 1);
+gnome_calendar_direction (gcal, 1);
}
void
@@ -244,3 +275,111 @@ gnome_calendar_object_changed (GnomeCalendar *gcal, iCalObject *obj, int flags)
gnome_calendar_update_all (gcal, obj, flags);
}
+
+static int
+max_open_files (void)
+{
+ static int files;
+
+ if (files)
+ return files;
+
+ files = sysconf (_SC_OPEN_MAX);
+ if (files != -1)
+ return files;
+#ifdef OPEN_MAX
+ return files = OPEN_MAX;
+#else
+ return files = 256;
+#endif
+}
+
+static void
+execute (char *command, int close_standard)
+{
+ struct sigaction ignore, save_intr, save_quit;
+ int status = 0, i;
+ pid_t pid;
+
+ ignore.sa_handler = SIG_IGN;
+ sigemptyset (&ignore.sa_mask);
+ ignore.sa_flags = 0;
+
+ sigaction (SIGINT, &ignore, &save_intr);
+ sigaction (SIGQUIT, &ignore, &save_quit);
+
+ if ((pid = fork ()) < 0){
+ fprintf (stderr, "\n\nfork () = -1\n");
+ return;
+ }
+ if (pid == 0){
+ pid = fork ();
+ if (pid == 0){
+ const int top = max_open_files ();
+ sigaction (SIGINT, &save_intr, NULL);
+ sigaction (SIGQUIT, &save_quit, NULL);
+
+ for (i = (close_standard ? 0 : 3); i < 4096; i++)
+ close (i);
+
+ /* FIXME: As an excercise to the reader, copy the
+ * code from mc to setup shell properly instead of
+ * /bin/sh. Yes, this comment is larger than a cut and paste.
+ */
+ execl ("/bin/sh", "/bin/sh", "-c", command, (char *) 0);
+
+ exit (127);
+ } else {
+ exit (127);
+ }
+ }
+ wait (&status);
+ sigaction (SIGINT, &save_intr, NULL);
+ sigaction (SIGQUIT, &save_quit, NULL);
+}
+
+void
+calendar_notify (time_t time, void *data)
+{
+ iCalObject *ico = data;
+
+ if (ico->aalarm.enabled && ico->aalarm.trigger == time){
+ printf ("bip\n");
+ return;
+ }
+
+ if (ico->palarm.enabled && ico->palarm.trigger == time){
+ execute (ico->palarm.data, 0);
+ return;
+ }
+
+ if (ico->malarm.enabled && ico->malarm.trigger == time){
+ char *command;
+ time_t app = ico->malarm.trigger + ico->malarm.offset;
+
+ command = g_copy_strings ("mail -s '",
+ _("Reminder of your appointment at "),
+ ctime (&app), "' '",
+ ico->malarm.data, "' ",
+ NULL);
+ execute (command, 1);
+
+ g_free (command);
+ return;
+ }
+
+ if (ico->dalarm.enabled && ico->dalarm.trigger == time){
+ time_t app = ico->dalarm.trigger + ico->dalarm.offset;
+ GtkWidget *w;
+ char *msg;
+
+ msg = g_copy_strings (_("Reminder of your appointment at "),
+ ctime (&app), "`",
+ ico->summary, "'", NULL);
+ w = gnome_message_box_new (msg, GNOME_MESSAGE_BOX_INFO, "Ok", NULL);
+ gtk_widget_show (w);
+ return;
+ }
+}
+
+
diff --git a/calendar/gnome-cal.h b/calendar/gnome-cal.h
index e526d219d7..002aed07ae 100644
--- a/calendar/gnome-cal.h
+++ b/calendar/gnome-cal.h
@@ -28,6 +28,7 @@ typedef struct {
GtkWidget *week_view;
GtkWidget *day_view;
GtkWidget *day_view_container;
+ GtkWidget *day_view_label;
GtkWidget *year_view;
GtkWidget *task_view;
void *event_editor;
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index b762dae475..9728a02d4b 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -9,6 +9,8 @@ INCLUDES = \
bin_PROGRAMS = gnomecal
gnomecal_SOURCES = \
+ alarm.c \
+ alarm.h \
calendar.c \
calendar.h \
calobj.c \
diff --git a/calendar/gui/alarm-notify/alarm.c b/calendar/gui/alarm-notify/alarm.c
new file mode 100644
index 0000000000..bb5c4c1b8d
--- /dev/null
+++ b/calendar/gui/alarm-notify/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 <config.h>
+#include <time.h>
+#include <gnome.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/time.h>
+#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);
+}
+
diff --git a/calendar/gui/alarm-notify/alarm.h b/calendar/gui/alarm-notify/alarm.h
new file mode 100644
index 0000000000..39f7281ce7
--- /dev/null
+++ b/calendar/gui/alarm-notify/alarm.h
@@ -0,0 +1,10 @@
+#ifndef ALARM_H
+#define ALARM_H
+
+typedef void (*AlarmFunction)(time_t time, void *closuse);
+
+void alarm_init (void);
+void alarm_add (time_t alarm_time, AlarmFunction fn, void *closure);
+void alarm_kill (void *closure);
+
+#endif
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 <config.h>
+#include <time.h>
+#include <gnome.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/time.h>
+#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);
+}
+
diff --git a/calendar/gui/alarm.h b/calendar/gui/alarm.h
new file mode 100644
index 0000000000..39f7281ce7
--- /dev/null
+++ b/calendar/gui/alarm.h
@@ -0,0 +1,10 @@
+#ifndef ALARM_H
+#define ALARM_H
+
+typedef void (*AlarmFunction)(time_t time, void *closuse);
+
+void alarm_init (void);
+void alarm_add (time_t alarm_time, AlarmFunction fn, void *closure);
+void alarm_kill (void *closure);
+
+#endif
diff --git a/calendar/gui/calendar.c b/calendar/gui/calendar.c
index be45bb04bb..28f37f78eb 100644
--- a/calendar/gui/calendar.c
+++ b/calendar/gui/calendar.c
@@ -18,6 +18,9 @@
#include "timeutil.h"
#include "versit/vcc.h"
+/* Our day range */
+time_t calendar_day_begin, calendar_day_end;
+
Calendar *
calendar_new (char *title)
{
@@ -29,12 +32,71 @@ calendar_new (char *title)
return cal;
}
+static void
+try_add (iCalObject *ico, CalendarAlarm *alarm, time_t start, time_t end)
+{
+ alarm->trigger = start-alarm->offset;
+
+ if (alarm->trigger < calendar_day_begin)
+ return;
+ if (alarm->trigger > calendar_day_end)
+ return;
+ alarm_add (alarm->trigger, calendar_notify, ico);
+}
+
+static int
+add_alarm (iCalObject *obj, time_t start, time_t end, void *closure)
+{
+ if (obj->aalarm.enabled)
+ try_add (obj, &obj->aalarm, start, end);
+ if (obj->dalarm.enabled)
+ try_add (obj, &obj->dalarm, start, end);
+ if (obj->palarm.enabled)
+ try_add (obj,&obj->palarm, start, end);
+ if (obj->malarm.enabled)
+ try_add (obj, &obj->malarm, start, end);
+
+ return TRUE;
+}
+
+#define max(a,b) ((a > b) ? a : b)
+
+void
+ical_object_try_alarms (iCalObject *obj)
+{
+ GList *alarms, *p;
+ int ao, po, od, mo;
+ int max_o;
+
+ ao = alarm_compute_offset (&obj->aalarm);
+ po = alarm_compute_offset (&obj->palarm);
+ od = alarm_compute_offset (&obj->dalarm);
+ mo = alarm_compute_offset (&obj->malarm);
+
+ max_o = max (ao, max (po, max (od, mo)));
+ if (max_o == -1)
+ return;
+
+ ical_object_generate_events (obj, calendar_day_begin, calendar_day_end + max_o, add_alarm, obj);
+}
+
+void
+calendar_add_alarms (Calendar *cal)
+{
+ time_t now = time (NULL);
+ GList *events = cal->events;
+
+ for (; events; events=events->next)
+ ical_object_try_alarms (events->data);
+}
+
void
calendar_add_object (Calendar *cal, iCalObject *obj)
{
switch (obj->type){
case ICAL_EVENT:
cal->events = g_list_prepend (cal->events, obj);
+ ical_object_try_alarms (obj);
break;
case ICAL_TODO:
@@ -207,6 +269,7 @@ char *
calendar_load (Calendar *cal, char *fname)
{
VObject *vcal;
+ time_t calendar_today;
if (cal->filename){
g_warning ("Calendar load called again\n");
@@ -217,7 +280,11 @@ calendar_load (Calendar *cal, char *fname)
vcal = Parse_MIME_FromFileName (fname);
if (!vcal)
return "Could not load the calendar";
-
+
+ calendar_today = time (NULL);
+ calendar_day_begin = time_start_of_day (calendar_today);
+ calendar_day_end = time_end_of_day (calendar_today);
+
calendar_load_from_vobject (cal, vcal);
cleanVObject (vcal);
cleanStrTbl ();
diff --git a/calendar/gui/calendar.h b/calendar/gui/calendar.h
index 52cd2c90f6..91d0f3338c 100644
--- a/calendar/gui/calendar.h
+++ b/calendar/gui/calendar.h
@@ -54,6 +54,7 @@ GList *calendar_get_events_in_range (Calendar *cal, time_t start, time_t end
/* Destroy the above list with this method */
void calendar_destroy_event_list (GList *l);
+void calendar_notify (time_t, void *data);
END_GNOME_DECLS
#endif
diff --git a/calendar/gui/eventedit.c b/calendar/gui/eventedit.c
index 3ea0f674ec..39a92c5480 100644
--- a/calendar/gui/eventedit.c
+++ b/calendar/gui/eventedit.c
@@ -1265,7 +1265,7 @@ get_exception_string (time_t t)
{
static char buf[256];
- strftime (buf, 256, "%a %b %d %Y", localtime (&t)); /* FIXME: how to i18n this? */
+ strftime (buf, sizeof(buf), "%a %b %d %Y", localtime (&t)); /* FIXME: how to i18n this? */
return buf;
}
@@ -1483,7 +1483,7 @@ event_editor_new (GnomeCalendar *gcal, iCalObject *ical)
ee = EVENT_EDITOR (retval);
if (ical == 0){
- ical = ical_new ("Test Comment", user_name, "Test Summary");
+ ical = ical_new ("", user_name, "");
ical->new = 1;
}
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 862c659d83..b851b65d44 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -6,6 +6,8 @@
*/
#include <gnome.h>
+#include <unistd.h>
+#include <signal.h>
#include "calendar.h"
#include "gnome-cal.h"
#include "gncal-full-day.h"
@@ -54,11 +56,22 @@ day_view_range_activated (GncalFullDay *fullday, GnomeCalendar *gcal)
}
static void
-setup_day_view (GnomeCalendar *gcal)
+set_day_view_label (GnomeCalendar *gcal, time_t t)
{
- time_t a, b, now;
+ static char buf[256];
+
+ strftime (buf, sizeof (buf), "%a %b %d %Y", localtime (&t));
+ gtk_label_set (GTK_LABEL (gcal->day_view_label), buf);
+}
+
+static void
+setup_day_view (GnomeCalendar *gcal, time_t now)
+{
+ GtkTable *t;
+ GtkWidget *sw;
+
+ time_t a, b;
- now = time (NULL);
a = time_start_of_day (now);
b = time_end_of_day (now);
@@ -66,12 +79,29 @@ setup_day_view (GnomeCalendar *gcal)
gtk_signal_connect (GTK_OBJECT (gcal->day_view), "range_activated",
(GtkSignalFunc) day_view_range_activated,
gcal);
- gcal->day_view_container = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (gcal->day_view_container),
+
+ t = (GtkTable *) gcal->day_view_container = gtk_table_new (0, 0, 0);
+ gtk_container_border_width (GTK_CONTAINER (t), 4);
+ gtk_table_set_row_spacings (t, 4);
+ gtk_table_set_col_spacings (t, 4);
+
+ gcal->day_view_label = gtk_label_new ("");
+ set_day_view_label (gcal, now);
+ gtk_table_attach (t, gcal->day_view_label, 0, 1, 0, 1,
+ GTK_FILL | GTK_SHRINK,
+ GTK_FILL | GTK_SHRINK,
+ 0, 0);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- gtk_container_add (GTK_CONTAINER (gcal->day_view_container), gcal->day_view);
- gtk_widget_show (gcal->day_view);
+ gtk_table_attach (t, sw, 0, 1, 1, 2,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+ 0, 0);
+ gtk_container_add (GTK_CONTAINER (sw), gcal->day_view);
+ gtk_widget_show_all (GTK_WIDGET (t));
}
static void
@@ -86,7 +116,7 @@ setup_widgets (GnomeCalendar *gcal)
gcal->year_view = gncal_year_view_new (gcal, now);
gcal->task_view = tasks_create (gcal);
- setup_day_view (gcal);
+ setup_day_view (gcal, now);
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->day_view_container, gtk_label_new (_("Day View")));
gtk_notebook_append_page (GTK_NOTEBOOK (gcal->notebook), gcal->week_view, gtk_label_new (_("Week View")));
@@ -129,6 +159,7 @@ gnome_calendar_goto (GnomeCalendar *gcal, time_t new_time)
gncal_full_day_set_bounds (GNCAL_FULL_DAY (gcal->day_view),
time_start_of_day (new_time),
time_end_of_day (new_time));
+ set_day_view_label (gcal, new_time);
} else if (current == gcal->year_view)
gncal_year_view_set (GNCAL_YEAR_VIEW (gcal->year_view), new_time);
else
@@ -157,7 +188,7 @@ gnome_calendar_direction (GnomeCalendar *gcal, int direction)
void
gnome_calendar_next (GnomeCalendar *gcal)
{
- gnome_calendar_direction (gcal, 1);
+gnome_calendar_direction (gcal, 1);
}
void
@@ -244,3 +275,111 @@ gnome_calendar_object_changed (GnomeCalendar *gcal, iCalObject *obj, int flags)
gnome_calendar_update_all (gcal, obj, flags);
}
+
+static int
+max_open_files (void)
+{
+ static int files;
+
+ if (files)
+ return files;
+
+ files = sysconf (_SC_OPEN_MAX);
+ if (files != -1)
+ return files;
+#ifdef OPEN_MAX
+ return files = OPEN_MAX;
+#else
+ return files = 256;
+#endif
+}
+
+static void
+execute (char *command, int close_standard)
+{
+ struct sigaction ignore, save_intr, save_quit;
+ int status = 0, i;
+ pid_t pid;
+
+ ignore.sa_handler = SIG_IGN;
+ sigemptyset (&ignore.sa_mask);
+ ignore.sa_flags = 0;
+
+ sigaction (SIGINT, &ignore, &save_intr);
+ sigaction (SIGQUIT, &ignore, &save_quit);
+
+ if ((pid = fork ()) < 0){
+ fprintf (stderr, "\n\nfork () = -1\n");
+ return;
+ }
+ if (pid == 0){
+ pid = fork ();
+ if (pid == 0){
+ const int top = max_open_files ();
+ sigaction (SIGINT, &save_intr, NULL);
+ sigaction (SIGQUIT, &save_quit, NULL);
+
+ for (i = (close_standard ? 0 : 3); i < 4096; i++)
+ close (i);
+
+ /* FIXME: As an excercise to the reader, copy the
+ * code from mc to setup shell properly instead of
+ * /bin/sh. Yes, this comment is larger than a cut and paste.
+ */
+ execl ("/bin/sh", "/bin/sh", "-c", command, (char *) 0);
+
+ exit (127);
+ } else {
+ exit (127);
+ }
+ }
+ wait (&status);
+ sigaction (SIGINT, &save_intr, NULL);
+ sigaction (SIGQUIT, &save_quit, NULL);
+}
+
+void
+calendar_notify (time_t time, void *data)
+{
+ iCalObject *ico = data;
+
+ if (ico->aalarm.enabled && ico->aalarm.trigger == time){
+ printf ("bip\n");
+ return;
+ }
+
+ if (ico->palarm.enabled && ico->palarm.trigger == time){
+ execute (ico->palarm.data, 0);
+ return;
+ }
+
+ if (ico->malarm.enabled && ico->malarm.trigger == time){
+ char *command;
+ time_t app = ico->malarm.trigger + ico->malarm.offset;
+
+ command = g_copy_strings ("mail -s '",
+ _("Reminder of your appointment at "),
+ ctime (&app), "' '",
+ ico->malarm.data, "' ",
+ NULL);
+ execute (command, 1);
+
+ g_free (command);
+ return;
+ }
+
+ if (ico->dalarm.enabled && ico->dalarm.trigger == time){
+ time_t app = ico->dalarm.trigger + ico->dalarm.offset;
+ GtkWidget *w;
+ char *msg;
+
+ msg = g_copy_strings (_("Reminder of your appointment at "),
+ ctime (&app), "`",
+ ico->summary, "'", NULL);
+ w = gnome_message_box_new (msg, GNOME_MESSAGE_BOX_INFO, "Ok", NULL);
+ gtk_widget_show (w);
+ return;
+ }
+}
+
+
diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h
index e526d219d7..002aed07ae 100644
--- a/calendar/gui/gnome-cal.h
+++ b/calendar/gui/gnome-cal.h
@@ -28,6 +28,7 @@ typedef struct {
GtkWidget *week_view;
GtkWidget *day_view;
GtkWidget *day_view_container;
+ GtkWidget *day_view_label;
GtkWidget *year_view;
GtkWidget *task_view;
void *event_editor;
diff --git a/calendar/gui/main.c b/calendar/gui/main.c
index 8249763ff0..ff4fc370a9 100644
--- a/calendar/gui/main.c
+++ b/calendar/gui/main.c
@@ -11,6 +11,7 @@
#include <gnome.h>
#include <pwd.h>
#include <sys/types.h>
+
#include "calendar.h"
#include "eventedit.h"
#include "gnome-cal.h"
@@ -96,6 +97,8 @@ init_calendar (void)
gnome_config_pop_prefix ();
}
+void save_calendar_cmd (GtkWidget *widget, void *data);
+
void
about_calendar_cmd (GtkWidget *widget, void *data)
{
@@ -125,30 +128,34 @@ display_objedit (GtkWidget *widget, GnomeCalendar *gcal)
}
void
-quit_cmd (GtkWidget *widget, GnomeCalendar *gcal)
-{
- /* FIXME: check all of the calendars for their state (modified) */
-
- gtk_main_quit ();
-}
-
-void
close_cmd (GtkWidget *widget, GnomeCalendar *gcal)
{
if (gcal->cal->modified){
- gnome_message_box_new (_("The calendar has unsaved changes, Save them?"),
- GNOME_MESSAGE_BOX_WARNING,
- "Yes", "No");
+ if (!gcal->cal->filename)
+ save_calendar_cmd (widget, gcal);
+ else
+ calendar_save (gcal->cal, gcal->cal->filename);
}
- gtk_widget_destroy (widget);
+ gtk_widget_destroy (GTK_WIDGET (gcal));
active_calendars--;
-
+ all_calendars = g_list_remove (all_calendars, gcal);
+
if (active_calendars == 0)
gtk_main_quit ();
}
void
+quit_cmd (GtkWidget *widget, GnomeCalendar *gcal)
+{
+ while (all_calendars){
+ GnomeCalendar *cal = GNOME_CALENDAR (all_calendars->data);
+
+ close_cmd (GTK_WIDGET (cal), cal);
+ }
+}
+
+void
previous_clicked (GtkWidget *widget, GnomeCalendar *gcal)
{
gnome_calendar_previous (gcal);
@@ -307,7 +314,6 @@ new_calendar (char *full_name, char *calendar_file)
printf ("Trying to load %s\n", calendar_file);
gnome_calendar_load (GNOME_CALENDAR (toplevel), calendar_file);
}
-
active_calendars++;
all_calendars = g_list_prepend (all_calendars, toplevel);
gtk_widget_show (toplevel);
@@ -320,12 +326,12 @@ main(int argc, char *argv[])
argp_program_version = VERSION;
- /* Initialise the i18n stuff */
bindtextdomain(PACKAGE, GNOMELOCALEDIR);
textdomain(PACKAGE);
gnome_init ("gncal", NULL, argc, argv, 0, NULL);
+ alarm_init ();
init_calendar ();
new_calendar (full_name, user_calendar_file);
diff --git a/calendar/main.c b/calendar/main.c
index 8249763ff0..ff4fc370a9 100644
--- a/calendar/main.c
+++ b/calendar/main.c
@@ -11,6 +11,7 @@
#include <gnome.h>
#include <pwd.h>
#include <sys/types.h>
+
#include "calendar.h"
#include "eventedit.h"
#include "gnome-cal.h"
@@ -96,6 +97,8 @@ init_calendar (void)
gnome_config_pop_prefix ();
}
+void save_calendar_cmd (GtkWidget *widget, void *data);
+
void
about_calendar_cmd (GtkWidget *widget, void *data)
{
@@ -125,30 +128,34 @@ display_objedit (GtkWidget *widget, GnomeCalendar *gcal)
}
void
-quit_cmd (GtkWidget *widget, GnomeCalendar *gcal)
-{
- /* FIXME: check all of the calendars for their state (modified) */
-
- gtk_main_quit ();
-}
-
-void
close_cmd (GtkWidget *widget, GnomeCalendar *gcal)
{
if (gcal->cal->modified){
- gnome_message_box_new (_("The calendar has unsaved changes, Save them?"),
- GNOME_MESSAGE_BOX_WARNING,
- "Yes", "No");
+ if (!gcal->cal->filename)
+ save_calendar_cmd (widget, gcal);
+ else
+ calendar_save (gcal->cal, gcal->cal->filename);
}
- gtk_widget_destroy (widget);
+ gtk_widget_destroy (GTK_WIDGET (gcal));
active_calendars--;
-
+ all_calendars = g_list_remove (all_calendars, gcal);
+
if (active_calendars == 0)
gtk_main_quit ();
}
void
+quit_cmd (GtkWidget *widget, GnomeCalendar *gcal)
+{
+ while (all_calendars){
+ GnomeCalendar *cal = GNOME_CALENDAR (all_calendars->data);
+
+ close_cmd (GTK_WIDGET (cal), cal);
+ }
+}
+
+void
previous_clicked (GtkWidget *widget, GnomeCalendar *gcal)
{
gnome_calendar_previous (gcal);
@@ -307,7 +314,6 @@ new_calendar (char *full_name, char *calendar_file)
printf ("Trying to load %s\n", calendar_file);
gnome_calendar_load (GNOME_CALENDAR (toplevel), calendar_file);
}
-
active_calendars++;
all_calendars = g_list_prepend (all_calendars, toplevel);
gtk_widget_show (toplevel);
@@ -320,12 +326,12 @@ main(int argc, char *argv[])
argp_program_version = VERSION;
- /* Initialise the i18n stuff */
bindtextdomain(PACKAGE, GNOMELOCALEDIR);
textdomain(PACKAGE);
gnome_init ("gncal", NULL, argc, argv, 0, NULL);
+ alarm_init ();
init_calendar ();
new_calendar (full_name, user_calendar_file);
diff --git a/calendar/pcs/calobj.c b/calendar/pcs/calobj.c
index 47d8c8a97e..624a179b05 100644
--- a/calendar/pcs/calobj.c
+++ b/calendar/pcs/calobj.c
@@ -1102,3 +1102,21 @@ ical_object_compute_end (iCalObject *ico)
ico->recur->_enddate = 0;
ical_object_generate_events (ico, ico->dtstart, 0, duration_callback, &count);
}
+
+int
+alarm_compute_offset (CalendarAlarm *a)
+{
+ if (!a->enabled)
+ return -1;
+ switch (a->units){
+ case ALARM_MINUTES:
+ a->offset = a->count * 60;
+ break;
+ case ALARM_HOURS:
+ a->offset = a->count * 3600;
+ break;
+ case ALARM_DAYS:
+ a->offset = a->count * 24 * 3600;
+ }
+ return a->offset;
+}
diff --git a/calendar/pcs/calobj.h b/calendar/pcs/calobj.h
index 26b0acf35b..60483c68ad 100644
--- a/calendar/pcs/calobj.h
+++ b/calendar/pcs/calobj.h
@@ -32,6 +32,10 @@ typedef struct {
int count;
enum AlarmUnit units;
char *data;
+
+ /* Does not get saved, internally used */
+ time_t offset;
+ time_t trigger;
/* Widgets */
void *w_count; /* A GtkEntry */
@@ -180,6 +184,9 @@ void ical_object_generate_events (iCalObject *ico, time_t start, time
/* Computes the enddate field of the recurrence based on the duration */
void ical_object_compute_end (iCalObject *ico);
+/* Returns the number of seconds configured to trigger the alarm in advance to an event */
+int alarm_compute_offset (CalendarAlarm *a);
+
END_GNOME_DECLS
#endif
diff --git a/calendar/timeutil.c b/calendar/timeutil.c
index 3e912a0fa3..09123b3202 100644
--- a/calendar/timeutil.c
+++ b/calendar/timeutil.c
@@ -57,7 +57,7 @@ isodate_from_time_t (time_t t)
static char isotime [40];
tm = localtime (&t);
- strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%sZ", tm);
+ strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%SZ", tm);
return isotime;
}