Index: calendar/e-cal-backend-exchange-calendar.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange-calendar.c,v
retrieving revision 1.47
diff -u -p -u -p -r1.47 e-cal-backend-exchange-calendar.c
--- calendar/e-cal-backend-exchange-calendar.c	21 Sep 2005 05:55:06 -0000	1.47
+++ calendar/e-cal-backend-exchange-calendar.c	11 Nov 2005 15:17:30 -0000
@@ -51,7 +51,7 @@ enum {
 #define PARENT_TYPE E_TYPE_CAL_BACKEND_EXCHANGE
 static ECalBackendExchange *parent_class = NULL;
 
-#define d(x)
+#define d(x) (x)
 
 static ECalBackendSyncStatus modify_object_with_href (ECalBackendSync *backend, EDataCal *cal, const char *calobj, CalObjModType mod, char **old_object, const char *href);
 
@@ -176,7 +176,7 @@ add_ical (ECalBackendExchange *cbex, con
 	  const char *uid, const char *body, int len, int receipts)
 {
 	const char *start, *end;
-	char *ical_body;
+	char *ical_body, *summary;
 	icalcomponent *icalcomp, *subcomp, *new_comp;
 	icalcomponent_kind kind;
 	icalproperty *icalprop;
@@ -199,10 +199,14 @@ add_ical (ECalBackendExchange *cbex, con
 
 	ical_body = g_strndup (start, end - start);
 	icalcomp = icalparser_parse_string (ical_body);
+
+	/*if (uid && (!strcmp (uid, "040000008200E00074C5B7101A82E008000000004052A2D471E5C501000000000000000010000000250803A00E679E48B2E53F187B9638A9")))
+		printf ("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nical object is : \n%s\nYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\n", ical_body);*/
 	g_free (ical_body);
 	if (!icalcomp)
 		return FALSE;
 
+
 	kind = icalcomponent_isa (icalcomp);
 	if (kind == ICAL_VEVENT_COMPONENT) {
 		if (receipts) {
@@ -633,6 +637,8 @@ create_object (ECalBackendSync *backend,
 	struct _cb_data *cbdata;
 	gboolean send_options;
 	
+	d(printf ("ecbexc_create_object(%p, %p, %s, %s)", backend, cal, *calobj ? *calobj : NULL, *uid ? *uid : NULL));
+
 	cbexc =	E_CAL_BACKEND_EXCHANGE_CALENDAR (backend);
 	
 	g_return_val_if_fail (E_IS_CAL_BACKEND_EXCHANGE_CALENDAR (cbexc), GNOME_Evolution_Calendar_InvalidObject);
@@ -959,6 +965,8 @@ modify_object (ECalBackendSync *backend,
 	       const char *calobj, CalObjModType mod,
 	       char **old_object, char **new_object)
 {
+	d(printf ("ecbexc_modify_object(%p, %p, %d, %s)", backend, cal, mod, *old_object ? *old_object : NULL));
+
 	return modify_object_with_href (backend, cal, calobj, mod, old_object, NULL);
 }
 
@@ -977,7 +985,7 @@ modify_object_with_href (ECalBackendSync
 	char *attach_body = NULL;
 	char *attach_body_crlf = NULL;
 	char *boundary = NULL;
-	struct icaltimetype last_modified;
+	struct icaltimetype last_modified, key_rid;
 	icalcomponent_kind kind;
 	ECalComponentDateTime dt;
 	struct _cb_data *cbdata;
@@ -1010,6 +1018,8 @@ modify_object_with_href (ECalBackendSync
 		return GNOME_Evolution_Calendar_InvalidObject;
 	}
 	comp_uid = icalcomponent_get_uid (icalcomp);
+	if (mod == CALOBJ_MOD_THIS)
+		key_rid = icalcomponent_get_recurrenceid (icalcomp);
 	
 	ecomp = get_exchange_comp (E_CAL_BACKEND_EXCHANGE (cbexc), comp_uid);
 	
@@ -1037,6 +1047,7 @@ modify_object_with_href (ECalBackendSync
 		attach_body_crlf = e_cal_backend_exchange_lf_to_crlf (attach_body);	
 	}
 
+	e_cal_component_commit_sequence (updated_ecomp);
 	updated_ecomp_str = e_cal_component_get_as_string (updated_ecomp);
 	updated_icalcomp = icalparser_parse_string (updated_ecomp_str);
 	g_free (updated_ecomp_str);
@@ -1156,6 +1167,9 @@ modify_object_with_href (ECalBackendSync
 	g_free (real_comp_str);
 
 	icalcomponent_foreach_tzid (real_icalcomp, add_timezone_cb, cbdata);
+	if (mod == CALOBJ_MOD_THIS) {
+		icalcomponent_add_component (cbdata->vcal_comp, ecomp->icomp);	
+	}
 	icalcomponent_add_component (cbdata->vcal_comp, real_icalcomp);
 
 	body = icalcomponent_as_ical_string (cbdata->vcal_comp);
@@ -1208,12 +1222,30 @@ modify_object_with_href (ECalBackendSync
 	g_free (body_crlf);
 
 	cached_ecomp = e_cal_component_new ();
-	e_cal_component_set_icalcomponent (cached_ecomp, icalcomponent_new_clone (ecomp->icomp));
+	if (mod == CALOBJ_MOD_THIS) {
+		GList *l;
+		struct icaltimetype inst_rid, key_rid;
+		gboolean inst_found = FALSE;
+
+		for (l = ecomp->instances; l ; l = l->next) {
+			inst_rid = icalcomponent_get_recurrenceid (l->data);
+			if (icaltime_compare (inst_rid, key_rid) == 0) {
+				e_cal_component_set_icalcomponent (cached_ecomp,
+					 icalcomponent_new_clone (l->data));
+				break;
+			}
+		}
+
+	} else {
+		e_cal_component_set_icalcomponent (cached_ecomp, icalcomponent_new_clone (ecomp->icomp));
+	}
+	e_cal_component_commit_sequence (cached_ecomp);
 	*old_object = e_cal_component_get_as_string (cached_ecomp);
 	
 	ctx = exchange_account_get_context (E_CAL_BACKEND_EXCHANGE (cbexc)->account);	
 	
 	/* PUT the iCal object in the Exchange server */
+					
 	if (href)
 		new_href = href;
 	else
@@ -1274,8 +1306,10 @@ remove_object (ECalBackendSync *backend,
 		
 	comp = e_cal_component_new ();
 	e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (ecomp->icomp));
-	if (old_object)
+	if (old_object) {
+		e_cal_component_commit_sequence (comp);
 		*old_object = e_cal_component_get_as_string (comp);
+	}
 	
 	if (mod == CALOBJ_MOD_THIS && rid && *rid) {
 		/*remove a single instance of a recurring event and modify */
@@ -1310,7 +1344,9 @@ static ECalBackendSyncStatus
 receive_objects (ECalBackendSync *backend, EDataCal *cal,
 		 const char *calobj)
 {
+	d(printf ("ecbexc_modify_object(%p, %p, %s)", backend, cal, calobj ? calobj : NULL));
 	ECalBackendExchangeCalendar *cbexc;
+	ECalBackendExchangeComponent *ecomp;
 	ECalComponent *comp = NULL;
 	GList *comps, *l;
 	struct icaltimetype current;
@@ -1334,7 +1370,7 @@ receive_objects (ECalBackendSync *backen
 
 	for (l = comps; l; l= l->next) {
 		const char *uid, *rid;
-		char *calobj;
+		char *icalobj;
 		char *object = NULL;
 		
 		subcomp = l->data;
@@ -1350,14 +1386,16 @@ receive_objects (ECalBackendSync *backen
 		e_cal_component_get_uid (comp, &uid);
 		rid = e_cal_component_get_recurid_as_string (comp);
 
+		printf ("received object : \n%s\n", icalcomponent_as_ical_string (subcomp));
 		switch (method) {
 		case ICAL_METHOD_PUBLISH:
 		case ICAL_METHOD_REQUEST:
 		case ICAL_METHOD_REPLY:
-			if (get_exchange_comp (E_CAL_BACKEND_EXCHANGE (cbexc), uid)) {
+			if ((ecomp = get_exchange_comp (E_CAL_BACKEND_EXCHANGE (cbexc), uid)) != NULL ) {
 				char *old_object = NULL;
-				
-				calobj = (char *) icalcomponent_as_ical_string (subcomp);
+
+				d(printf ("uid : %s : found in the cache\n", uid));
+
 				if (check_owner_partstatus_for_declined (backend, subcomp)) {
 					status = remove_object (backend, cal, uid, NULL, 
 								CALOBJ_MOD_ALL, &old_object,
@@ -1367,24 +1405,37 @@ receive_objects (ECalBackendSync *backen
 					e_cal_backend_notify_object_removed (E_CAL_BACKEND (backend), uid,
 									     old_object, NULL);
 				} else {
-					status = modify_object_with_href (backend, cal, calobj,
+				/*	status = remove_object (backend, cal, uid, rid, 
+								CALOBJ_MOD_THIS, &calobj, NULL);
+					//icalcomponent_set_recurrenceid (subcomp, icaltime_from_string (rid)); */
+					struct icaltimetype time_rid;
+					time_rid = icaltime_from_string (rid);
+					e_cal_util_remove_instances (ecomp->icomp, time_rid, CALOBJ_MOD_THIS);
+					icalobj = (char *) icalcomponent_as_ical_string (subcomp);
+					status = modify_object_with_href (backend, cal, icalobj,
 									  CALOBJ_MOD_THIS,
 									  &old_object, NULL);
+					d(printf ("Modify this particular instance : %s\n", rid));
+					d(printf ("Modify object : %s\n", icalobj));
 					if (status != GNOME_Evolution_Calendar_Success)
 						goto error;
 					e_cal_backend_notify_object_modified (E_CAL_BACKEND (backend),
-									      old_object, calobj);
+									      old_object, icalobj);
+					d(printf ("Notify that the new object after modication is : %s\n", icalobj));
 				}
 
 				g_free (old_object);
 			} else if (!check_owner_partstatus_for_declined (backend, subcomp)) {
+				d(printf ("object : %s .. not found in the cache\n", uid));
 				char *returned_uid;
-				calobj = (char *) icalcomponent_as_ical_string (subcomp);
-				status = create_object (backend, cal, &calobj, &returned_uid);
+				icalobj = (char *) icalcomponent_as_ical_string (subcomp);
+				d(printf ("Create a new object : %s\n", icalobj));
+				status = create_object (backend, cal, &icalobj, &returned_uid);
 				if (status != GNOME_Evolution_Calendar_Success)
 					goto error;
 
-				e_cal_backend_notify_object_created (E_CAL_BACKEND (backend), calobj);
+				e_cal_backend_notify_object_created (E_CAL_BACKEND (backend), icalobj);
+				d(printf ("Notify that the new object is created : %s\n", icalobj));
 			} else
 				status = GNOME_Evolution_Calendar_Success;
 			break;
@@ -1393,13 +1444,13 @@ receive_objects (ECalBackendSync *backen
 			break;
 
 		case ICAL_METHOD_CANCEL:
-			calobj = (char *) icalcomponent_as_ical_string (subcomp);
+			icalobj = (char *) icalcomponent_as_ical_string (subcomp);
 			if (rid)
-				status = remove_object (backend, cal, uid, rid, CALOBJ_MOD_THIS, &calobj, &object);
+				status = remove_object (backend, cal, uid, rid, CALOBJ_MOD_THIS, &icalobj, &object);
 			else
-				status = remove_object (backend, cal, uid, NULL, CALOBJ_MOD_ALL, &calobj, &object);
+				status = remove_object (backend, cal, uid, NULL, CALOBJ_MOD_ALL, &icalobj, &object);
 			if (status == GNOME_Evolution_Calendar_Success) 
-				e_cal_backend_notify_object_removed (E_CAL_BACKEND (backend), uid, calobj, NULL);
+				e_cal_backend_notify_object_removed (E_CAL_BACKEND (backend), uid, icalobj, NULL);
 			if (object) {
 				g_free (object);
 				object = NULL;
@@ -1781,6 +1832,7 @@ send_objects (ECalBackendSync *backend, 
 	}
 												 
 	retval = GNOME_Evolution_Calendar_Success;
+	e_cal_component_commit_sequence (comp);
 	*modified_calobj = g_strdup (e_cal_component_get_as_string (comp));
 												 
  cleanup:
Index: calendar/e-cal-backend-exchange.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange.c,v
retrieving revision 1.44
diff -u -p -u -p -r1.44 e-cal-backend-exchange.c
--- calendar/e-cal-backend-exchange.c	21 Oct 2005 11:52:22 -0000	1.44
+++ calendar/e-cal-backend-exchange.c	11 Nov 2005 15:17:30 -0000
@@ -69,7 +69,7 @@ struct ECalBackendExchangePrivate {
 #define PARENT_TYPE E_TYPE_CAL_BACKEND_SYNC
 static GObjectClass *parent_class = NULL;
 
-#define d(x)
+#define d(x) (x)
 
 static ECalBackendSyncStatus
 is_read_only (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only)
@@ -224,10 +224,12 @@ save_object (gpointer key, gpointer valu
 	GList *l;
 
 	icalcomp = icalcomponent_new_clone (ecomp->icomp);
+	printf ("Saving comp : %s\n", icalcomponent_get_uid (icalcomp));
 	icalcomponent_add_component (vcalcomp, icalcomp);
 
 	for (l = ecomp->instances; l; l = l->next) {
 		icalcomp = icalcomponent_new_clone (l->data);
+		printf ("\tSaving instance : %s\n", icalcomponent_get_uid (icalcomp));
 		icalcomponent_add_component (vcalcomp, icalcomp);
 	}
 }
@@ -440,6 +442,7 @@ e_cal_backend_exchange_in_cache (ECalBac
 
 	if (strcmp (ecomp->lastmod, lastmod) < 0) {
 		g_hash_table_remove (cbex->priv->objects, uid);
+		printf ("more later update is present. remove the existing comp : %s\n", uid);
 		return FALSE;
 	}
 
@@ -459,6 +462,7 @@ uncache (gpointer key, gpointer value, g
 	ECalBackendExchange *cbex = data;
 
 	g_hash_table_remove (cbex->priv->objects, key);
+	printf ("uncache : %s\n", key);
 }
 
 void
@@ -495,7 +499,7 @@ e_cal_backend_exchange_add_object (ECalB
 	const char *uid;
 	struct icaltimetype rid;
 
-	d(printf("ecbe_add_object(%p, %s, %s)\n", cbex, href, lastmod));
+	printf("ecbe_add_object(%p, %s, %s)\n", cbex, href, lastmod);
 
 	uid = icalcomponent_get_uid (comp);
 	ecomp = g_hash_table_lookup (cbex->priv->objects, uid);
@@ -509,7 +513,8 @@ e_cal_backend_exchange_add_object (ECalB
 		ecomp = g_new0 (ECalBackendExchangeComponent, 1);
 		ecomp->uid = g_strdup (uid);
 		g_hash_table_insert (cbex->priv->objects, ecomp->uid, ecomp);
-	}
+		printf ("Adding new excomp : uid : %s\n", uid);
+	} else { printf ("excomp already found for : %s\n", uid); }
 
 	if (href) {
 		g_free (ecomp->href);
@@ -521,6 +526,7 @@ e_cal_backend_exchange_add_object (ECalB
 	}
 
 	if (is_instance) {
+		printf ("the object being added is an instance\n");
 		GList *l;
 		struct icaltimetype inst_rid;
 		gboolean inst_found = FALSE;
@@ -537,7 +543,10 @@ e_cal_backend_exchange_add_object (ECalB
 
 			ecomp->instances = g_list_prepend (ecomp->instances,
 						   icalcomponent_new_clone (comp));
+			if (ecomp->icomp)
+				e_cal_util_remove_instances (ecomp->icomp, rid, CALOBJ_MOD_THIS);
 		}
+
 	} else
 		ecomp->icomp = icalcomponent_new_clone (comp);
 
@@ -557,9 +566,14 @@ discard_detached_instance (ECalBackendEx
 		if (icaltime_compare (inst_rid, rid) == 0) {
 			ecomp->instances = g_list_remove (ecomp->instances, inst->data);
 			icalcomponent_free (inst->data);
-			return;
+			break;
 		}
 	}
+
+	if (ecomp->icomp) /* This check should ideally not be needed. */
+		e_cal_util_remove_instances (ecomp->icomp, rid, CALOBJ_MOD_THIS);
+
+	return;
 }
 
 /**
@@ -625,6 +639,7 @@ e_cal_backend_exchange_remove_object (EC
 		return FALSE;
 
 	g_hash_table_remove (cbex->priv->objects, uid);
+	printf ("explicitly remove the object : %s\n", uid);
 
 	save_cache (cbex);
 	return TRUE;
@@ -666,35 +681,94 @@ get_exchange_comp (ECalBackendExchange *
 	return NULL;			
 }
 
+static void
+add_instances_to_vcal (gpointer value, gpointer user_data)
+{
+	icalcomponent *recurrence = value;
+	icalcomponent *vcalendar = user_data;
+
+	icalcomponent_add_component (
+		vcalendar,
+		icalcomponent_new_clone (recurrence));		     
+
+}
+
 static ECalBackendSyncStatus
 get_object (ECalBackendSync *backend, EDataCal *cal,
 	    const char *uid, const char *rid, char **object)
 {
 	ECalBackendExchange *cbex = E_CAL_BACKEND_EXCHANGE (backend);
 	ECalBackendExchangeComponent *ecomp;
-	ECalComponent *comp;
 	
 	d(printf("ecbe_get_object(%p, %p, uid=%s, rid=%s)\n", backend, cal, uid, rid));
 	
 	g_return_val_if_fail (uid != NULL, GNOME_Evolution_Calendar_InvalidObject);
 	/*any other asserts?*/
 	
+	*object = NULL;
 	ecomp = g_hash_table_lookup (cbex->priv->objects, uid);
-	if ((!ecomp) || (!ecomp->icomp))
+	if (!ecomp)
 		return GNOME_Evolution_Calendar_ObjectNotFound;
-	
-	/*anything on recur id here????*/
-	
-	comp = e_cal_component_new ();
-	if (e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (ecomp->icomp))) {
-		*object = e_cal_component_get_as_string (comp);
-	} else {
-		*object = NULL;
-		g_object_unref (comp);
+
+	if (!rid && (!(ecomp->icomp)))	
 		return GNOME_Evolution_Calendar_ObjectNotFound;
+
+	if (rid && *rid) {
+		GList *l;
+		struct icaltimetype inst_rid, key_rid;
+		gboolean inst_found = FALSE;
+
+		for (l = ecomp->instances; l ; l = l->next) {
+			key_rid = icaltime_from_string (rid);
+			inst_rid = icalcomponent_get_recurrenceid (l->data);
+			if (icaltime_compare (inst_rid, key_rid) == 0) {
+				inst_found = TRUE;
+				break;
+			}
+		}
+		
+		if (inst_found) {
+			*object = g_strdup (icalcomponent_as_ical_string (l->data));
+		} else {
+			/* Instance is not found. Send the master object instead */	
+			if (ecomp->icomp) {
+				icalcomponent *new_inst;
+				struct icaltimetype itt;
+
+				itt = icaltime_from_string (rid);
+				new_inst = e_cal_util_construct_instance (
+					icalcomponent_new_clone (ecomp->icomp), itt);
+				if (!new_inst)
+					return GNOME_Evolution_Calendar_ObjectNotFound;
+				
+				*object = g_strdup (icalcomponent_as_ical_string (new_inst));
+				icalcomponent_free (new_inst);
+			} else {
+				/* Oops. No instance and no master as well !! */
+				return GNOME_Evolution_Calendar_ObjectNotFound;
+			} /* Close check for master object */
+		} /* Close check for instance */
+	}/* Close check if rid is being asked */
+	else {
+		/* rid is not asked */
+		if (g_list_length (ecomp->instances) > 0) {
+			/* Ok, we have detached instances, return a VCALENDAR */
+			/* Send the whole object including all its detatched instances */
+			icalcomponent *vcalcomp;
+
+			vcalcomp = e_cal_util_new_top_level ();
+			icalcomponent_add_component (vcalcomp,
+				icalcomponent_new_clone (ecomp->icomp));
+			g_list_foreach (ecomp->instances, (GFunc) add_instances_to_vcal, vcalcomp);
+			
+			*object = g_strdup (icalcomponent_as_ical_string (vcalcomp));
+			icalcomponent_free (vcalcomp);	
+		} else {
+			/* There are no detached instances. Send only the master object */
+			*object = g_strdup (icalcomponent_as_ical_string (ecomp->icomp));
+		}
 	}
-	
-	g_object_unref (comp);
+
 	return GNOME_Evolution_Calendar_Success;
 }
 
