My first icalendar patch



Fellow gnomecal hackers:

This is the first of what I hope will be a series of patches to 
gnomecal to add iCalendar support.  Since this is a fairly major 
architectural change, I'm going to post significant patches to 
existing code to the list for review before committing, although I'll 
still probably make the usual tweaks directly to CVS.  (In 
particular, I've tried to isolate as much of the new code as possible 
to new files to try to minimize disruptions to existing code):

Anyway, this is more of a "preliminary" patch: it doesn't actually 
add much (if any) iCalendar support, and should not change the 
operation of gnomecal in any way. It does, however, change the format 
of several key internal structures, most importantly iCalObject.

The following changes were made to iCalObject.  The patch also
attempts to fix all existing references to these fields to make them
conform to the new semantics:

* The attendee field in has been changed from a list of strings to a
  list of iCalPerson's (a new structure).  (The field does not yet
  appear to be in use.)

* The organizer field was changed from a char* to an iCalPerson*.

* The related field was changed from a list of strings to a list of
  iCalRelated's (a new structure).

* New fields alarms (a list of CalendarAlarm), desc (a string), and
  date_only (a boolean) were added.  These are for iCal-use, and
  existing code should not be affected.  (The alarms list will replace
  the current dalarm, palarm, malarm, and aalarm fields, but I have
  not yet made those changes.)

The following is a brief summary of other changes:

* A format field was added to Calendar, and supporting code was added
  to call the appropriate vCal/iCal loader in calendar_load.  (Note
  that a #ifdef HAVE_LIBICAL surrounds a reference to the icalendar
  loader, which is not yet complete and is not included.)

* A new flag CALENDAR_USE_ICAL was added to Eskil's CalendarNewOptions
  enum to tell a Calendar to use iCalendar.

* Some new pointers were added to CalendarAlarm to support the richer
  semantics of iCalendar-alarms.  Eventually, I want to delete the
  redundant old fields, but not until the rest of the code is ready.

A formal ChangeLog entry is not included in the patch, but I will add
something appropriate before committing.

If there are objections to any of these changes, please let me know.
Otherwise, I will commit them to HEAD in the next few days.  More
substantial changes are in the works...

-Russell

Index: calendar.c
===================================================================
RCS file: /cvs/gnome/gnome-pim/gncal/calendar.c,v
retrieving revision 1.51
diff -u -r1.51 calendar.c
--- calendar.c	1999/12/31 15:58:08	1.51
+++ calendar.c	2000/01/17 07:52:31
@@ -40,6 +40,10 @@
 	cal = g_new0 (Calendar, 1);
 
 	cal->title = g_strdup (title);
+	if (options & CALENDAR_USE_ICAL)
+	  cal->format = CAL_ICAL;
+	else
+	  cal->format = CAL_VCAL;
 
 	if ((calendar_day_begin == 0) || (calendar_day_end == 0))
 		calendar_set_day ();
@@ -315,18 +319,30 @@
 	}
 
 	cal->filename = g_strdup (fname);
-	vcal = Parse_MIME_FromFileName (fname);
-	if (!vcal)
-		return "Could not load the calendar";
 
 	stat (fname, &s);
 	cal->file_time = s.st_mtime;
-
+	
 	calendar_set_day ();
-		
-	calendar_load_from_vobject (cal, vcal);
-	cleanVObject (vcal);
-	cleanStrTbl ();
+
+	switch (cal->format) {
+	case CAL_VCAL:
+		vcal = Parse_MIME_FromFileName (fname);
+		if (!vcal)
+			return "Could not load the calendar";
+		calendar_load_from_vobject (cal, vcal);
+		cleanVObject (vcal);
+		cleanStrTbl ();
+		break;
+#ifdef HAVE_LIBICAL
+	case CAL_ICAL:
+		icalendar_calendar_load (cal, fname);
+		break;
+#endif
+	default:
+		return "Unknown calendar format";
+	}
+
 	return NULL;
 }
 
Index: calendar.h
===================================================================
RCS file: /cvs/gnome/gnome-pim/gncal/calendar.h,v
retrieving revision 1.24
diff -u -r1.24 calendar.h
--- calendar.h	1999/12/31 15:58:08	1.24
+++ calendar.h	2000/01/17 07:52:31
@@ -5,17 +5,24 @@
 
 BEGIN_GNOME_DECLS
 
+typedef enum {
+	CAL_VCAL,
+	CAL_ICAL
+} CalendarFormat;
+
 typedef struct {
 	/* This calendar's title */
 	char    *title;
 
 	/* backing store for this calendar object */
 	char    *filename;
+	CalendarFormat format;
 
 	/* The list of events;  todo's and journal entries */
 	GList  	*events;
 	GList  	*todo;
 	GList  	*journal;
+	GList   *timezones;	/* required for iCalendar */
 
 	GHashTable *event_hash;
 	
@@ -43,7 +50,8 @@
 
 typedef enum {
 	CALENDAR_INIT_NIL    = 0,
-	CALENDAR_INIT_ALARMS = 1 << 0
+	CALENDAR_INIT_ALARMS = 1 << 0,
+	CALENDAR_USE_ICAL    = 1 << 1
 } CalendarNewOptions;
 
 Calendar *calendar_new                  (char *title,CalendarNewOptio
ns options);
Index: calobj.c
===================================================================
RCS file: /cvs/gnome/gnome-pim/gncal/calobj.c,v
retrieving revision 1.57
diff -u -r1.57 calobj.c
--- calobj.c	1999/11/03 02:36:31	1.57
+++ calobj.c	2000/01/17 07:52:31
@@ -82,7 +82,8 @@
 	ico = ical_object_new ();
 
 	ico->comment   = g_strdup (comment);
-	ico->organizer = g_strdup (organizer);
+	ico->organizer = g_new0 (iCalPerson, 1);
+	ico->organizer->addr = g_strdup (organizer);
 	ico->summary   = g_strdup (summary);
 	ico->class     = g_strdup ("PUBLIC");
 	ico->status    = g_strdup ("NEEDS ACTION");
@@ -699,13 +700,23 @@
 
 	/* Organizer */
 	if (has (o, VCOrgNameProp)){
-		ical->organizer = g_strdup (str_val (vo));
+		ical->organizer = g_new0 (iCalPerson, 1);
+		ical->organizer->addr = g_strdup (str_val (vo));
 		free (the_str);
 	}
 					   
 	/* related */
 	if (has (o, VCRelatedToProp)){
-		ical->related = set_list (str_val (vo));
+		char *str;
+		char *s;
+		iCalRelation *rel;
+		str = str_val (vo);
+		for (s = strtok (str, ";"); s; s = strtok (NULL, ";")) {
+			rel = g_new0 (iCalRelation, 1);
+			rel->uid = g_strdup (s);
+			rel->reltype = g_strdup ("PARENT");
+			ical->related = g_list_prepend (ical->related, rel);
+		}
 		free (the_str);
 	}
 	
@@ -849,6 +860,36 @@
 }
 
 static void
+store_rel_list (VObject *o, char *prop, GList *values)
+{
+	GList *l;
+	int len;
+	char *result, *p;
+	
+	for (len = 0, l = values; l; l = l->next)
+		len += strlen (((iCalRelation*)(l->data))->uid) + 1;
+
+	result = g_malloc (len);
+
+	for (p = result, l = values; l; l = l->next) {
+		int len = strlen (((iCalRelation*)(l->data))->uid);
+		
+		strcpy (p, ((iCalRelation*)(l->data))->uid);
+
+		if (l->next) {
+			p [len] = ';';
+			p += len+1;
+		} else
+			p += len;
+	}
+
+	*p = 0;
+
+	addPropValue (o, prop, result);
+	g_free (result);
+}
+
+static void
 store_date_list (VObject *o, char *prop, GList *values)
 {
 	GList *l;
@@ -996,12 +1037,12 @@
 	addPropValue (o, VCTranspProp, to_str (ical->transp));
 
 	/* Owenr/organizer */
-	if (ical->organizer)
-		addPropValue (o, VCOrgNameProp, ical->organizer);
+	if (ical->organizer && ical->organizer->addr)
+		addPropValue (o, VCOrgNameProp, ical->organizer->addr);
 	
 	/* related */
 	if (ical->related)
-		store_list (o, VCRelatedToProp, ical->related);
+		store_rel_list (o, VCRelatedToProp, ical->related);
 
 	/* attach */
 	for (l = ical->attach; l; l = l->next)
Index: calobj.h
===================================================================
RCS file: /cvs/gnome/gnome-pim/gncal/calobj.h,v
retrieving revision 1.26
diff -u -r1.26 calobj.h
--- calobj.h	1999/09/19 09:35:41	1.26
+++ calobj.h	2000/01/17 07:52:31
@@ -31,8 +31,15 @@
 	int            enabled;
 	int            count;
 	enum AlarmUnit units;
-	char           *data;
+	char           *data;	/* not used for iCalendar alarms */
 
+	/* the following pointers are used for iCalendar alarms */
+
+	char           *attach;	           /* AUDIO, EMAIL, PROC */
+	char           *desc;	           /* DISPLAY, EMAIL, PROC */
+	char           *summary;           /* EMAIL */
+	char           *attendee;          /* EMAIL */
+
 	/* Does not get saved, internally used */
 	time_t         offset;
 	time_t         trigger;
@@ -82,6 +89,11 @@
 	ICAL_TRANSPARENT
 } iCalTransp;
 
+typedef struct {
+	char   *uid;
+	char   *reltype;
+} iCalRelation;
+
 typedef char NotYet;
 
 enum RecurType {
@@ -119,6 +131,28 @@
 	int            __count;
 } Recurrence;
 
+/* 
+   NOTE: iCalPerson is used for various property values which specify
+   people (e.g. ATTENDEE, ORGANIZER, etc.  Not all fields are valid
+   under RFC 2445 for all property values, but iCalPerson can store
+   them anyway.  Enforcing the RFC is a job for the parser.
+*/
+
+typedef struct {
+	char          *addr;
+	char          *name;
+	char          *role;
+	char          *partstat;
+	gboolean      rsvp;
+	char          *cutype;	/* calendar user type */
+	GList         *member;	/* group memberships */
+	GList         *deleg_to;
+	GList         *deleg_from;
+	char          *sent_by;
+	char          *directory;
+	GList         *altrep;	/* list of char* URI's */
+} iCalPerson;
+
 #define IS_INFINITE(r) (r->duration == 0)
 
 /* Flags to indicate what has changed in an object */
@@ -137,7 +171,7 @@
 	iCalType      type;
 
 	GList         *attach;		/* type: one or more URIs or binary data */
-	GList         *attendee; 	/* type: CAL-ADDRESS */
+	GList         *attendee; 	/* type: CAL-ADDRESS (list of iCalPerson) 
*/
 	GList         *categories; 	/* type: one or more TEXT */
 	char          *class;
 
@@ -145,15 +179,17 @@
 	time_t        completed;
 	time_t        created;
 	GList         *contact;		/* type: one or more TEXT */
+	char          *desc;
 	time_t        dtstamp;
 	time_t        dtstart;
-	time_t        dtend;
+	time_t        dtend;            /* also duedate for todo's */
+	gboolean      date_only;        /* set if the start/end times were 
specified using dates, not times (internal use, not stored to disk) */
 	GList         *exdate;		/* type: one or more time_t's */
 	GList         *exrule;		/* type: one or more RECUR */
 	iCalGeo       geo;
 	time_t        last_mod;
 	char          *location;
-	char          *organizer;
+	iCalPerson    *organizer;
 	int           percent;
 	int           priority;
 	char          *rstatus;	        /* request status for freebusy */
@@ -173,6 +209,8 @@
 	CalendarAlarm aalarm;
 	CalendarAlarm palarm;
 	CalendarAlarm malarm;
+	
+	GList         *alarms;
 
 	Recurrence    *recur;
 	
Index: eventedit.c
===================================================================
RCS file: /cvs/gnome/gnome-pim/gncal/eventedit.c,v
retrieving revision 1.61
diff -u -r1.61 eventedit.c
--- eventedit.c	1999/12/31 15:58:08	1.61
+++ eventedit.c	2000/01/17 07:52:31
@@ -826,7 +826,8 @@
 	l = gtk_label_new (_("Owner:"));
 	gtk_box_pack_start (GTK_BOX (hbox), l, FALSE, FALSE, 0);
 
-	ee->general_owner = gtk_label_new (ee->ical->organizer ? ee->ical->
organizer: _("?"));
+	ee->general_owner = gtk_label_new (ee->ical->organizer->addr ? 
+					   ee->ical->organizer->addr : _("?"));
 	gtk_misc_set_alignment (GTK_MISC (ee->general_owner), 0.0, 0.5);
 	gtk_box_pack_start (GTK_BOX (hbox), ee->general_owner, TRUE, TRUE, 
4);
 
Index: main.c
===================================================================
RCS file: /cvs/gnome/gnome-pim/gncal/main.c,v
retrieving revision 1.92
diff -u -r1.92 main.c
--- main.c	1999/12/31 15:58:08	1.92
+++ main.c	2000/01/17 07:52:31
@@ -844,7 +844,7 @@
 		if (object->type != ICAL_TODO)
 			continue;
 
-		printf ("[%s]: %s\n", object->organizer, object->summary);
+		printf ("[%s]: %s\n", object->organizer->addr, object->summary);
 	}
 	calendar_destroy (cal);
 	exit (0);







[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]