aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArturo Espinosa <unammx@src.gnome.org>1998-04-18 12:02:46 +0800
committerArturo Espinosa <unammx@src.gnome.org>1998-04-18 12:02:46 +0800
commitf1b08663ddff6432289ca4780bc823c96d471657 (patch)
treefed1c651f292c4855550302ef94808338b9fd0dc
parentd79ee74dad39ee5210482aa90a7c6a7b2f0b7517 (diff)
downloadgsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.tar
gsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.tar.gz
gsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.tar.bz2
gsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.tar.lz
gsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.tar.xz
gsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.tar.zst
gsoc2013-evolution-f1b08663ddff6432289ca4780bc823c96d471657.zip
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
-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;
}