[evolution-data-server/wip/mcrha/libical-glib] More ECalComponent API changes



commit 2ed8ee9082d6572b55b0fe2cb7bf58f5d4f86199
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jan 24 18:58:16 2019 +0100

    More ECalComponent API changes

 src/calendar/libecal/e-cal-component-alarm.c    |  636 +-
 src/calendar/libecal/e-cal-component-alarm.h    |   24 +-
 src/calendar/libecal/e-cal-component-datetime.c |   36 +-
 src/calendar/libecal/e-cal-component-datetime.h |    4 +
 src/calendar/libecal/e-cal-component.c          | 7661 ++++++++---------------
 src/calendar/libecal/e-cal-component.h          |  212 +-
 6 files changed, 3485 insertions(+), 5088 deletions(-)
---
diff --git a/src/calendar/libecal/e-cal-component-alarm.c b/src/calendar/libecal/e-cal-component-alarm.c
index c923445df..edf1a5db6 100644
--- a/src/calendar/libecal/e-cal-component-alarm.c
+++ b/src/calendar/libecal/e-cal-component-alarm.c
@@ -247,7 +247,7 @@ e_cal_component_alarm_set_from_component (ECalComponentAlarm *alarm,
 
        for (prop = i_cal_component_get_first_property (comp, I_CAL_ANY_PROPERTY);
             prop;
-            prop = i_cal_component_get_next_property (comp, I_CAL_ANY_PROPERTY)) {
+            g_object_unref (prop), prop = i_cal_component_get_next_property (comp, I_CAL_ANY_PROPERTY)) {
                ECalComponentAttendee *attendee;
                ECalComponentText *text;
                ICalAttach *attach;
@@ -295,6 +295,7 @@ e_cal_component_alarm_set_from_component (ECalComponentAlarm *alarm,
                                param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
                                alarm->description = e_cal_component_text_new (i_cal_property_get_description 
(prop),
                                        param ? i_cal_property_get_altrep (param) : NULL);
+                               g_clear_object (&param);
                        }
                        break;
 
@@ -329,8 +330,6 @@ e_cal_component_alarm_set_from_component (ECalComponentAlarm *alarm,
                default:
                        break;
                }
-
-               g_object_unref (prop);
        }
 
        alarm->attendees = g_slist_reverse (alarm->attendees);
@@ -344,16 +343,643 @@ e_cal_component_alarm_set_from_component (ECalComponentAlarm *alarm,
 
        g_clear_object (&duration);
        g_clear_object (&repeat);
+
+       /* Ensure mandatory property */
+       if (!alarm->uid)
+               alarm->uid = e_util_generate_uid ();
 }
 
+/**
+ * e_cal_component_alarm_get_as_component:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Creates a VALARM #ICalComponent filled with data from the @alarm.
+ * Free the returned component with g_object_unref(), when no longer
+ * needed.
+ *
+ * Returns: (transfer full): a newly created #ICalComponent
+ *    of %I_CAL_VALARM_COMPONENT kind
+ *
+ * Since: 3.36
+ **/
 ICalComponent *
-e_cal_component_alarm_get_as_component (ECalComponentAlarm *alarm)
+e_cal_component_alarm_get_as_component (const ECalComponentAlarm *alarm)
 {
-       xxxx
+       ICalComponent *valarm;
+
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       valarm = i_cal_component_new_valarm ();
+
+       e_cal_component_alarm_fill_component (alarm, valarm);
+
+       return valarm;
 }
 
+/**
+ * e_cal_component_alarm_fill_component:
+ * @alarm: an #ECalComponentAlarm
+ * @component: an #ICalComponent of %I_CAL_VALARM_COMPONENT kind
+ *
+ * Fills @component with data from @alarm. The @component should
+ * be of %I_CAL_VALARM_COMPONENT kind - the function does nothing,
+ * if it's not.
+ *
+ * Since: 3.36
+ **/
 void
 e_cal_component_alarm_fill_component (const ECalComponentAlarm *alarm,
                                      ICalComponent *component)
 {
+       ICalPropertyKind remove_props[] = {
+               I_CAL_ACTION_PROPERTY,
+               I_CAL_ATTACH_PROPERTY,
+               I_CAL_DESCRIPTION_PROPERTY,
+               I_CAL_DURATION_PROPERTY,
+               I_CAL_REPEAT_PROPERTY,
+               I_CAL_TRIGGER_PROPERTY,
+               I_CAL_ATTENDEE_PROPERTY };
+       ICalProperty *prop;
+       GSList *link;
+       gint ii;
+
+       g_return_if_fail (alarm != NULL);
+       g_return_if_fail (I_CAL_IS_COMPONENT (component));
+
+       if (i_cal_component_isa (component) != I_CAL_VALARM_COMPONENT)
+               return;
+
+       /* Remove used properties first */
+
+       for (ii = 0; ii < G_N_ELEMENTS (remove_props); ii++) {
+               if (remove_props == I_CAL_ACTION_PROPERTY &&
+                   alarm->action == E_CAL_COMPONENT_ALARM_UNKNOWN)
+                       continue;
+
+               while (prop = i_cal_component_get_first_property (component, remove_props[ii]), prop) {
+                       i_cal_component_remove_property (component, prop);
+                       g_object_unref (prop);
+               }
+       }
+
+       if (!alarm->uid)
+               alarm->uid = e_util_generate_uid ();
+
+       for (prop = i_cal_component_get_first_property (component, I_CAL_X_PROPERTY);
+            prop;
+            g_object_unref (prop), i_cal_component_get_first_property (component, I_CAL_X_PROPERTY)) {
+               const gchar *xname;
+
+               xname = i_cal_property_get_x_name (prop);
+               if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
+                       i_cal_property_set_x (prop, alarm->uid);
+                       /* Do not set to NULL, it's used below as a sentinel */
+                       g_object_unref (prop);
+                       break;
+               }
+       }
+
+       /* Tried all existing and none was the E_CAL_EVOLUTION_ALARM_UID_PROPERTY, thus add it */
+       if (!prop) {
+               prop = i_cal_property_new_x (alarm->uid);
+               i_cal_property_set_xname (prop, E_CAL_EVOLUTION_ALARM_UID_PROPERTY);
+               i_cal_component_take_property (component, prop);
+       }
+
+       prop = NULL;
+
+       switch (alarm->action) {
+       case E_CAL_COMPONENT_ALARM_AUDIO:
+               prop = i_cal_property_new_action (I_CAL_ACTION_AUDIO);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_DISPLAY:
+               prop = i_cal_property_new_action (I_CAL_ACTION_DISPLAY);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_EMAIL:
+               prop = i_cal_property_new_action (I_CAL_ACTION_EMAIL);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_PROCEDURE:
+               prop = i_cal_property_new_action (I_CAL_ACTION_PROCEDURE);
+               break;
+
+       case E_CAL_COMPONENT_ALARM_NONE:
+               prop = i_cal_property_new_action (I_CAL_ACTION_NONE);
+               break;
+       }
+
+       if (prop)
+               i_cal_component_take_property (component, prop);
+
+       if (alarm->description && e_cal_component_text_get_value (alarm->description)) {
+               prop = i_cal_property_new_description (e_cal_component_text_get_value (alarm->description));
+
+               if (prop) {
+                       const gchar *altrep = e_cal_component_text_get_altrep (alarm->description);
+
+                       if (altrep && *altrep) {
+                               ICalParameter *param;
+
+                               param = i_cal_parameter_new_altrep (altrep);
+                               if (param)
+                                       i_cal_property_take_parameter (prop, param);
+                       }
+
+                       i_cal_component_take_property (component, prop);
+               }
+       }
+
+       if (alarm->trigger) {
+               prop = e_cal_component_alarm_trigger_get_as_property (alarm->trigger);
+               if (prop)
+                       i_cal_component_take_property (component, prop);
+       }
+
+       if (alarm->repeat) {
+               ICalDurationType *interval;
+
+               interval = e_cal_component_alarm_repeat_get_interval (alarm->repeat);
+               if (interval) {
+                       prop = i_cal_property_new_repeat (e_cal_component_alarm_repeat_get_repetitions 
(alarm->repeat));
+                       i_cal_component_take_property (component, prop);
+
+                       prop = i_cal_property_new_duration (interval);
+                       i_cal_component_take_property (component, prop);
+               }
+       }
+
+       for (link = alarm->attendees; link; link = g_slist_next (link)) {
+               ECalComponentAttendee *attendee = link->data;
+
+               if (!attendee)
+                       continue
+
+               prop = e_cal_component_attendee_get_as_property (attendee);
+               if (prop)
+                       i_cal_component_take_property (component, prop);
+       }
+
+       for (link = alarm->attachments; link; link = g_slist_next (link)) {
+               ICalAttach *attach = link->data;
+
+               if (!attach)
+                       continue;
+
+               prop = i_cal_property_new_attach (attach);
+               if (prop)
+                       i_cal_component_take_property (component, prop);
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_uid:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm UID.
+ *
+ * Returns: (nullable): the @alarm UID, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+const gchar *
+e_cal_component_alarm_get_uid (const ECalComponentAlarm *alarm);
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->uid;
+}
+
+/**
+ * e_cal_component_alarm_set_uid:
+ * @alarm: an #ECalComponentAlarm
+ * @uid: (nullable): a UID to set, or %NULL or emptry string to generate new
+ *
+ * Set the @alarm UID, or generates a new UID, if @uid is %NULL or an empty string.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_uid (ECalComponentAlarm *alarm,
+                              const gchar *uid)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (!uid || !*uid) {
+               g_free (alarm->uid);
+               alarm->uid = e_util_generate_uid ();
+       } else if (g_strcmp0 (alarm->uid, uid) != 0) {
+               g_free (alarm->uid);
+               alarm->uid = g_strdup (uid);
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_action:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm action, as an #ECalComponentAlarmAction.
+ *
+ * Returns: the @alarm action, or %E_CAL_COMPONENT_ALARM_NONE, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmAction
+e_cal_component_alarm_get_action (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, E_CAL_COMPONENT_ALARM_NONE);
+
+       return alarm->action;
+}
+
+/**
+ * e_cal_component_alarm_set_action:
+ * @alarm: an #ECalComponentAlarm
+ * @action: an #ECalComponentAlarmAction
+ *
+ * Set the @alarm action, as an #ECalComponentAlarmAction.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_action (ECalComponentAlarm *alarm,
+                                 ECalComponentAlarmAction action)
+{
+       g_return_if_fail (alarm != NULL);
+
+       alarm->action = action;
+}
+
+/**
+ * e_cal_component_alarm_get_description:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm description, as an #ECalComponentText.
+ *
+ * Returns: (transfer none) (nullable): the @alarm description, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentText *
+e_cal_component_alarm_get_description (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->description;
+}
+
+/**
+ * e_cal_component_alarm_set_description:
+ * @alarm: an #ECalComponentAlarm
+ * @description: (transfer none) (nullable): a description to set, or %NULL to unset
+ *
+ * Set the @alarm description, as an #ECalComponentText.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_description (ECalComponentAlarm *alarm,
+                                      const ECalComponentText *description)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (description != alarm->description) {
+               e_cal_component_text_free (alarm->description);
+
+               alarm->description = description ? e_cal_component_text_copy (description) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_description: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @description: (transfer full) (nullable): a description to set, or %NULL to unset
+ *
+ * Set the @alarm description, as an #ECalComponentText, and assumes
+ * ownership of the @description.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_description (ECalComponentAlarm *alarm,
+                                       ECalComponentText *description)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (description != alarm->description) {
+               e_cal_component_text_free (alarm->description);
+               alarm->description = description;
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_repeat:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm repeat information, as an ECalComponentAlarmRepeat.
+ *
+ * Returns: (transfer none) (nullable): the @alarm repeat information,
+ *    or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmRepeat *
+e_cal_component_alarm_get_repeat (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->repeat;
+}
+
+/**
+ * e_cal_component_alarm_set_repeat:
+ * @alarm: an #ECalComponentAlarm
+ * @repeat: (transfer none) (nullable): a repeat information to set, or %NULL to unset
+ *
+ * Set the @alarm repeat information, as an #ECalComponentAlarmRepeat.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_repeat (ECalComponentAlarm *alarm,
+                                 const ECalComponentAlarmRepeat *repeat)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (repeat != alarm->repeat) {
+               e_cal_component_repeat_free (alarm->repeat);
+
+               alarm->repeat = repeat ? e_cal_component_repeat_copy (repeat) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_repeat: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @repeat: (transfer none) (nullable): a repeat information to set, or %NULL to unset
+ *
+ * Set the @alarm repeat information, as an #ECalComponentAlarmRepeat and assumes
+ * ownership of the @trigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_repeat (ECalComponentAlarm *alarm,
+                                  ECalComponentAlarmRepeat *repeat)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (repeat != alarm->repeat) {
+               e_cal_component_repeat_free (alarm->repeat);
+               alarm->repeat = repeat;
+       }
+}
+
+/**
+ * e_cal_component_alarm_get_trigger:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the @alarm trigger, as an #ECalComponentAlarmTrigger.
+ *
+ * Returns: (transfer none) (nullable): the @alarm trigger, or %NULL when, none is set
+ *
+ * Since: 3.36
+ **/
+ECalComponentAlarmTrigger *
+e_cal_component_alarm_get_trigger (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->trigger;
+}
+
+/**
+ * e_cal_component_alarm_set_trigger:
+ * @alarm: an #ECalComponentAlarm
+ * @trigger: (transfer none) (nullable): a trigger to set, or %NULL to unset
+ *
+ * Set the @alarm trigger, as an #ECalComponentAlarmTrigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_trigger (ECalComponentAlarm *alarm,
+                                  const ECalComponentAlarmTrigger *trigger)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (trigger != alarm->trigger) {
+               e_cal_component_trigger_free (alarm->trigger);
+
+               alarm->trigger = trigger ? e_cal_component_trigger_copy (trigger) : NULL;
+       }
+}
+
+/**
+ * e_cal_component_alarm_take_trigger: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @trigger: (transfer full) (nullable): a trigger to set, or %NULL to unset
+ *
+ * Set the @alarm trigger, as an #ECalComponentAlarmTrigger and assumes
+ * ownership of the @trigger.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_trigger (ECalComponentAlarm *alarm,
+                                   ECalComponentAlarmTrigger *trigger)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (trigger != alarm->trigger) {
+               e_cal_component_trigger_free (alarm->trigger);
+               alarm->trigger = trigger;
+       }
+}
+
+/**
+ * e_cal_component_alarm_has_attendees:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Returns: whether the @alarm has any attendees
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_alarm_has_attendees (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, FALSE);
+
+       return alarm->attendees != NULL;
+}
+
+/**
+ * e_cal_component_alarm_get_attendees:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the list of attendees, as #ECalComponentAttendee.
+ * The returned #GSList is owned by @alarm and should not be modified,
+ * neither its content.
+ *
+ * Returns: (transfer none) (nullable) (element-type ECalComponentAttendee): the @alarm attendees,
+ *    as a #GSList of an #ECalComponentAttendee, or %NULL when, none are set
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_alarm_get_attendees (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->attendees;
+}
+
+/**
+ * e_cal_component_alarm_set_attendees:
+ * @alarm: an #ECalComponentAlarm
+ * @attendees: (transfer none) (nullable) (element-type ECalComponentAttendee): a #GSList
+ *    of an #ECalComponentAttendee objects to set as attendees, or %NULL to unset
+ *
+ * Set the list of attendees, as a #GSList of an #ECalComponentAttendee.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_attendees (ECalComponentAlarm *alarm,
+                                    const GSList *attendees)
+{
+       GSList *to_take = NULL, *link;
+
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attendees == attendees)
+               return;
+
+       for (link = attendees; link; link = g_slist_next (link)) {
+               ECalComponentAttendee *attendee = link->data;
+
+               if (attendee)
+                       to_take = g_slist_prepend (to_take, e_cal_component_attendee_copy (attendee));
+       }
+
+       to_take = g_slist_reverse (to_take);
+
+       e_cal_component_alarm_take_attendees (to_take);
+}
+
+/**
+ * e_cal_component_alarm_take_attendees: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @attendees: (transfer full) (nullable) (element-type ECalComponentAttendee): a #GSList
+ *    of an #ECalComponentAttendee objects to set as attendees, or %NULL to unset
+ *
+ * Sets the list of attendees, as a #GSList of an #ECalComponentAttendee and assumes
+ * ownership of the @attendees and its content.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_attendees (ECalComponentAlarm *alarm,
+                                     GSList *attendees)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attendees != attendees) {
+               g_slist_free_full (alarm->attendees, e_cal_component_attendee_free);
+               alarm->attendees = attendees;
+       }
+}
+
+/**
+ * e_cal_component_alarm_has_attachments:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Returns: whether the @alarm has any attachments
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_cal_component_alarm_has_attachments (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, FALSE);
+
+       return alarm->attachments != NULL;
+}
+
+/**
+ * e_cal_component_alarm_get_attachments:
+ * @alarm: an #ECalComponentAlarm
+ *
+ * Get the list of attachments, as #ICalAttach.
+ * The returned #GSList is owned by @alarm and should not be modified,
+ * neither its content.
+ *
+ * Returns: (transfer none) (nullable) (element-type ICalAttach): the @alarm attachments,
+ *    as a #GSList of an #ICalAttach, or %NULL, when none is set
+ *
+ * Since: 3.36
+ **/
+GSList *
+e_cal_component_alarm_get_attachments (const ECalComponentAlarm *alarm)
+{
+       g_return_val_if_fail (alarm != NULL, NULL);
+
+       return alarm->attachments;
+}
+
+/**
+ * e_cal_component_alarm_set_attachments:
+ * @alarm: an #ECalComponentAlarm
+ * @attachemnts: (transfer none) (nullable) (element-type ICalAttach): a #GSList
+ *    of an #ICalAttach objects to set as attachments, or %NULL to unset
+ *
+ * Set the list of attachments, as a #GSList of an #ICalAttach.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_set_attachments (ECalComponentAlarm *alarm,
+                                      const GSList *attachments)
+{
+       GSList *to_take = NULL, *link;
+
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attachments == attachments)
+               return;
+
+       for (link = attachments; link; link = g_slist_next (link)) {
+               ICalAttach *attach = link->data;
+
+               if (attach)
+                       to_take = g_slist_prepend (to_take, g_object_ref (attach));
+       }
+
+       to_take = g_slist_reverse (to_take);
+
+       e_cal_component_alarm_take_attachments (to_take);
+}
+
+/**
+ * e_cal_component_alarm_take_attachments: (skip)
+ * @alarm: an #ECalComponentAlarm
+ * @attachemnts: (transfer full) (nullable) (element-type ICalAttach): a #GSList
+ *    of an #ICalAttach objects to set as attachments, or %NULL to unset
+ *
+ * Sets the list of attachments, as a #GSList of an #ICalAttach and assumes
+ * ownership of the @attachments and its content.
+ *
+ * Since: 3.36
+ **/
+void
+e_cal_component_alarm_take_attachments (ECalComponentAlarm *alarm,
+                                       GSList *attachments)
+{
+       g_return_if_fail (alarm != NULL);
+
+       if (alarm->attachments != attachments) {
+               g_slist_free_full (alarm->attachments, g_object_unref);
+               alarm->attachments = attachments;
+       }
 }
diff --git a/src/calendar/libecal/e-cal-component-alarm.h b/src/calendar/libecal/e-cal-component-alarm.h
index 8d6ea6112..c0a7ef986 100644
--- a/src/calendar/libecal/e-cal-component-alarm.h
+++ b/src/calendar/libecal/e-cal-component-alarm.h
@@ -58,24 +58,26 @@ ECalComponentAlarm *
                e_cal_component_alarm_new_from_component
                                                (const ICalComponent *component);
 ECalComponentAlarm *
-               e_cal_component_alarm_copy      (ECalComponentAlarm *alarm);
+               e_cal_component_alarm_copy      (const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_free      (ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_from_component
                                                (ECalComponentAlarm *alarm,
                                                 const ICalComponent *component);
 ICalComponent *        e_cal_component_alarm_get_as_component
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_fill_component
                                                (const ECalComponentAlarm *alarm,
                                                 ICalComponent *component);
-const gchar *  e_cal_component_alarm_get_uid   (ECalComponentAlarm *alarm);
+const gchar *  e_cal_component_alarm_get_uid   (const ECalComponentAlarm *alarm);
+void           e_cal_component_alarm_set_uid   (ECalComponentAlarm *alarm,
+                                                const gchar *uid);
 ECalComponentAlarmAction
-               e_cal_component_alarm_get_action(ECalComponentAlarm *alarm);
+               e_cal_component_alarm_get_action(const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_action(ECalComponentAlarm *alarm,
                                                 ECalComponentAlarmAction action);
 ECalComponentText *
                e_cal_component_alarm_get_description
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_description
                                                (ECalComponentAlarm *alarm,
                                                 const ECalComponentText *description);
@@ -83,7 +85,7 @@ void          e_cal_component_alarm_take_description
                                                (ECalComponentAlarm *alarm,
                                                 ECalComponentText *description);
 ECalComponentAlarmRepeat *
-               e_cal_component_alarm_get_repeat(ECalComponentAlarm *alarm);
+               e_cal_component_alarm_get_repeat(const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_repeat(ECalComponentAlarm *alarm,
                                                 const ECalComponentAlarmRepeat *repeat);
 void           e_cal_component_alarm_take_repeat
@@ -91,7 +93,7 @@ void          e_cal_component_alarm_take_repeat
                                                 ECalComponentAlarmRepeat *repeat);
 ECalComponentAlarmTrigger *
                e_cal_component_alarm_get_trigger
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_trigger
                                                (ECalComponentAlarm *alarm,
                                                 const ECalComponentAlarmTrigger *trigger);
@@ -99,9 +101,9 @@ void         e_cal_component_alarm_take_trigger
                                                (ECalComponentAlarm *alarm,
                                                 ECalComponentAlarmTrigger *trigger);
 gboolean       e_cal_component_alarm_has_attendees
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 GSList *       e_cal_component_alarm_get_attendees /* ECalComponentAttendee * */
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_attendees
                                                (ECalComponentAlarm *alarm,
                                                 const GSList *attendees); /* ECalComponentAttendee * */
@@ -109,9 +111,9 @@ void                e_cal_component_alarm_take_attendees
                                                (ECalComponentAlarm *alarm,
                                                 GSList *attendees); /* ECalComponentAttendee * */
 gboolean       e_cal_component_alarm_has_attachments
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 GSList *       e_cal_component_alarm_get_attachments /* ICalAttach * */
-                                               (ECalComponentAlarm *alarm);
+                                               (const ECalComponentAlarm *alarm);
 void           e_cal_component_alarm_set_attachments
                                                (ECalComponentAlarm *alarm,
                                                 const GSList *attachments); /* ICalAttach * */
diff --git a/src/calendar/libecal/e-cal-component-datetime.c b/src/calendar/libecal/e-cal-component-datetime.c
index cf6841abe..213edce41 100644
--- a/src/calendar/libecal/e-cal-component-datetime.c
+++ b/src/calendar/libecal/e-cal-component-datetime.c
@@ -65,6 +65,36 @@ e_cal_component_datetime_new (const ICalTimetype *value,
        return dt;
 }
 
+/**
+ * e_cal_component_datetime_new:
+ * @value: (transfer full) (not nullable): an #ICalTimetype as a value
+ * @tzid: (transfer full) (nullable): timezone ID for the @value, or %NULL
+ *
+ * Creates a new #ECalComponentDateTime instance, which holds
+ * the @value and @tzid. It is similar to e_cal_component_datetime_new(),
+ * except this function assumes ownership of the @value and @tzid.
+ * The returned structure should be freed with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): a new #ECalComponentDateTime
+ *
+ * Since: 3.36
+ **/
+ECalComponentDateTime *
+e_cal_component_datetime_new_take (ICalTimetype *value,
+                                  gchar *tzid)
+{
+       ECalComponentDateTime *dt;
+
+       g_return_val_if_fail (I_CAL_IS_TIMETYPE (value), NULL);
+
+       dt = g_new0 (ECalComponentDateTime, 1);
+       dt->value = value;
+       dt->tzid = tzid;
+
+       return dt;
+}
+
 /**
  * e_cal_component_datetime_copy:
  * @dt: (not nullable): an #ECalComponentDateTime
@@ -90,9 +120,9 @@ e_cal_component_datetime_copy (const ECalComponentDateTime *dt)
  * e_cal_component_datetime_free: (skip)
  * @dt: (type ECalComponentDateTime) (nullable): an #ECalComponentDateTime to free
  *
- * Free @dt, previously created by e_cal_component_datetime_new() or
- * e_cal_component_datetime_copy(). The function does nothing, if @dt
- * is %NULL.
+ * Free @dt, previously created by e_cal_component_datetime_new(),
+ * e_cal_component_datetime_new_take() or e_cal_component_datetime_copy().
+ * The function does nothing, if @dt is %NULL.
  *
  * Since: 3.36
  **/
diff --git a/src/calendar/libecal/e-cal-component-datetime.h b/src/calendar/libecal/e-cal-component-datetime.h
index 975333e90..39bc6986b 100644
--- a/src/calendar/libecal/e-cal-component-datetime.h
+++ b/src/calendar/libecal/e-cal-component-datetime.h
@@ -42,6 +42,10 @@ GType                e_cal_component_datetime_get_type
 ECalComponentDateTime *
                e_cal_component_datetime_new    (const ICalTimetype *value,
                                                 const gchar *tzid);
+ECalComponentDateTime *
+               e_cal_component_datetime_new_take
+                                               (ICalTimetype *value,
+                                                gchar *tzid);
 ECalComponentDateTime *
                e_cal_component_datetime_copy   (const ECalComponentDateTime *dt);
 void           e_cal_component_datetime_free   (gpointer dt); /* ECalComponentDateTime * */
diff --git a/src/calendar/libecal/e-cal-component.c b/src/calendar/libecal/e-cal-component.c
index 36eb65e5b..6a7dc423b 100644
--- a/src/calendar/libecal/e-cal-component.c
+++ b/src/calendar/libecal/e-cal-component.c
@@ -44,139 +44,11 @@
 #define getppid() 0
 #endif
 
-#define E_CAL_COMPONENT_GET_PRIVATE(obj) \
-       (G_TYPE_INSTANCE_GET_PRIVATE \
-       ((obj), E_TYPE_CAL_COMPONENT, ECalComponentPrivate))
-
 G_DEFINE_TYPE (ECalComponent, e_cal_component, G_TYPE_OBJECT)
-G_DEFINE_BOXED_TYPE (ECalComponentAlarm,
-               e_cal_component_alarm,
-               e_cal_component_alarm_clone,
-               e_cal_component_alarm_free)
-
-struct attendee {
-       icalproperty *prop;
-       icalparameter *cutype_param;
-       icalparameter *member_param;
-       icalparameter *role_param;
-       icalparameter *partstat_param;
-       icalparameter *rsvp_param;
-       icalparameter *delto_param;
-       icalparameter *delfrom_param;
-       icalparameter *sentby_param;
-       icalparameter *cn_param;
-       icalparameter *language_param;
-};
-
-struct attachment {
-       icalproperty *prop;
-       icalattach *attach;
-
-       /* for inline attachments, where the file is stored;
-        * it unlinks it on attachment free. */
-       gchar *temporary_filename;
-};
-
-struct text {
-       icalproperty *prop;
-       icalparameter *altrep_param;
-};
-
-struct datetime {
-       icalproperty *prop;
-       icalparameter *tzid_param;
-};
-
-struct organizer {
-       icalproperty *prop;
-       icalparameter *sentby_param;
-       icalparameter *cn_param;
-       icalparameter *language_param;
-};
-
-struct period {
-       icalproperty *prop;
-       icalparameter *value_param;
-};
-
-struct recur_id {
-       struct datetime recur_time;
-
-       icalparameter *range_param;
-};
 
-/* Private part of the CalComponent structure */
 struct _ECalComponentPrivate {
        /* The icalcomponent we wrap */
-       icalcomponent *icalcomp;
-
-       /* Properties */
-
-       icalproperty *uid;
-
-       icalproperty *status;
-       GSList *attendee_list;
-
-       GString *categories_str;
-
-       icalproperty *classification;
-
-       GSList *comment_list; /* list of struct text */
-
-       icalproperty *completed;
-
-       GSList *contact_list; /* list of struct text */
-
-       icalproperty *created;
-
-       GSList *description_list; /* list of struct text */
-
-       struct datetime dtstart;
-       struct datetime dtend;
-
-       icalproperty *dtstamp;
-
-       /* The DURATION property can be used instead of the VEVENT DTEND or
-        * the VTODO DUE dates. We do not use it directly ourselves, but we
-        * must be able to handle it from incoming data. If a DTEND or DUE
-        * is requested, we convert the DURATION if necessary. If DTEND or
-        * DUE is set, we remove any DURATION. */
-       icalproperty *duration;
-
-       struct datetime due;
-
-       GSList *exdate_list; /* list of struct datetime */
-       GSList *exrule_list; /* list of icalproperty objects */
-
-       struct organizer organizer;
-
-       icalproperty *geo;
-       icalproperty *last_modified;
-       icalproperty *percent;
-       icalproperty *priority;
-
-       struct recur_id recur_id;
-
-       GSList *rdate_list; /* list of struct period */
-
-       GSList *rrule_list; /* list of icalproperty objects */
-
-       icalproperty *sequence;
-
-       struct {
-               icalproperty *prop;
-               icalparameter *altrep_param;
-       } summary;
-
-       icalproperty *transparency;
-       icalproperty *url;
-       icalproperty *location;
-
-       GSList *attachment_list;
-
-       /* Subcomponents */
-
-       GHashTable *alarm_uid_hash;
+       ICalComponent *icalcomp;
 
        /* Whether we should increment the sequence number when piping the
         * object over the wire.
@@ -184,163 +56,201 @@ struct _ECalComponentPrivate {
        guint need_sequence_inc : 1;
 };
 
-/* Does a simple g_free() of the elements of a GSList and then frees the list
- * itself.  Returns NULL.
+/* Frees the internal icalcomponent only if it does not have a parent.  If it
+ * does, it means we don't own it and we shouldn't free it.
  */
-static GSList *
-free_slist (GSList *slist)
+static void
+free_icalcomponent (ECalComponent *comp,
+                    gboolean free)
 {
-       g_slist_free_full (slist, (GDestroyNotify) g_free);
+       if (!comp->priv->icalcomp)
+               return;
+
+       if (free) {
+               g_clear_object (&comp->priv->icalcomp);
+       }
 
-       return NULL;
+       /* Clean up */
+       comp->priv->need_sequence_inc = FALSE;
 }
 
-/* Used from g_hash_table_foreach_remove() to free the alarm UIDs hash table.
- * We do not need to do anything to individual elements since we were storing
- * the UID pointers inside the icalproperties themselves.
- */
 static gboolean
-free_alarm_cb (gpointer key,
-               gpointer value,
-               gpointer data)
+ecc_property_exists (ICalCompoennt *icalcomp,
+                    ICalPropertyKind prop_kind)
 {
+       ICalProperty *prop;
+
+       g_return_val_if_fail (I_CAL_IS_COMPONENT (icalcomp), FALSE);
+
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+       if (!prop)
+               return FALSE;
+
+       g_object_unref (prop);
+
        return TRUE;
 }
 
+
+/* The 'func' returns TRUE to continue */
 static void
-free_attachment (struct attachment *attachment)
+foreach_subcomponent (ICalComponent *icalcomp,
+                     ICalComponentKind comp_kind,
+                     gboolean (* func) (ICalComponent *icalcomp,
+                                        ICalComponent *subcomp,
+                                        gpointer user_data),
+                     gpointer user_data)
 {
-       if (!attachment)
-               return;
-
-       icalattach_unref (attachment->attach);
+       ICalCompIter *iter;
+       ICalComponent *subcomp;
 
-       if (attachment->temporary_filename) {
-               gchar *sep;
-
-               g_unlink (attachment->temporary_filename);
+       g_return_if_fail (icalcomp != NULL);
+       g_return_if_fail (func != NULL);
 
-               sep = strrchr (attachment->temporary_filename, G_DIR_SEPARATOR);
-               if (sep) {
-                       *sep = '\0';
-                       g_rmdir (attachment->temporary_filename);
+       iter = i_cal_component_begin_component (icalcomp, comp_kind);
+       subcomp = i_cal_comp_iter_deref (&iter);
+       while (subcomp) {
+               if (!func (icalcomp, subcomp, user_data)) {
+                       g_object_unref (subcomp);
+                       break;
                }
+
+               g_object_unref (subcomp);
+               subcomp = i_cal_comp_iter_next (iter);
        }
 
-       g_free (attachment->temporary_filename);
-       g_free (attachment);
+       g_clear_object (&iter);
 }
 
-/* Frees the internal icalcomponent only if it does not have a parent.  If it
- * does, it means we don't own it and we shouldn't free it.
- */
+/* The 'func' returns TRUE to continue */
 static void
-free_icalcomponent (ECalComponent *comp,
-                    gboolean free)
+foreach_property (ICalComponent *icalcomp,
+                 ICalPropertyKind prop_kind,
+                 gboolean (* func) (ICalComponent *icalcomp,
+                                    ICalProperty *prop,
+                                    gpointer user_data),
+                 gpointer user_data)
 {
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
+       g_return_if_fail (func != NULL);
 
-       if (!priv->icalcomp)
-               return;
-
-       /* Free the mappings */
-
-       priv->uid = NULL;
-       priv->recur_id.recur_time.prop = NULL;
+       for (prop = i_cal_component_get_first_property (icalcomp, kind);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (icalcomp, prop_kind)) {
+               if (!func (icalcomp, prop, user_data)
+                       break;
+       }
+}
 
-       priv->status = NULL;
+static gboolean
+gather_all_properties_cb (ICalComponent *icalcomp,
+                         ICalProperty *prop,
+                         gpointer user_data)
+{
+       GSList **pprops = user_data;
 
-       g_slist_foreach (priv->attachment_list, (GFunc) free_attachment, NULL);
-       g_slist_free (priv->attachment_list);
-       priv->attachment_list = NULL;
+       g_return_val_if_fail (pprops != NULL, FALSE);
 
-       g_slist_foreach (priv->attendee_list, (GFunc) g_free, NULL);
-       g_slist_free (priv->attendee_list);
-       priv->attendee_list = NULL;
+       *pprops = g_slist_prepend (*pprops, g_object_ref (prop));
 
-       if (priv->categories_str)
-               g_string_free (priv->categories_str, TRUE);
-       priv->categories_str = NULL;
+       return TRUE;
+}
 
-       priv->classification = NULL;
-       priv->comment_list = free_slist (priv->comment_list);
-       priv->completed = NULL;
-       priv->contact_list = free_slist (priv->contact_list);
-       priv->created = NULL;
+static GSList * /* ICalProperty * */
+gather_all_properties (ICalComponent *icalcomp,
+                      ICalPropertyKind prop_kind,
+                      gboolean in_original_order)
+{
+       GSList *props = NULL;
 
-       priv->description_list = free_slist (priv->description_list);
+       foreach_property (icalcomp, prop_kind, gather_all_properties_cb, &props);
 
-       priv->dtend.prop = NULL;
-       priv->dtend.tzid_param = NULL;
+       return in_original_order ? g_slist_reverse (props) : props;
+}
 
-       priv->dtstamp = NULL;
+static void
+remove_all_properties_of_kind (ICalComponent *icalcomp,
+                              ICalPropertyKind prop_kind)
+{
+       ICalProperty *prop;
+       GSList *to_remove, *link;
 
-       priv->dtstart.prop = NULL;
-       priv->dtstart.tzid_param = NULL;
+       to_remove = gather_all_properties (icalcomp, prop_kind, FALSE);
 
-       priv->due.prop = NULL;
-       priv->due.tzid_param = NULL;
+       for (link = to_remove; link; link = g_slist_next (link)) {
+               prop = link->data;
 
-       priv->duration = NULL;
+               i_cal_component_remove_property (icalcomp, prop);
+       }
 
-       priv->exdate_list = free_slist (priv->exdate_list);
+       g_slist_free_full (to_remove, g_object_unref);
+}
 
-       g_slist_free (priv->exrule_list);
-       priv->exrule_list = NULL;
+/* returns NULL when value is NULL or empty string */
+static ECalComponentText *
+get_text_from_prop (ICalProperty *prop,
+                   const gchar *(* get_prop_func) (ICalProperty *prop))
+{
+       ICalParameter *altrep_param;
+       const gchar *value, *altrep;
 
-       priv->geo = NULL;
-       priv->last_modified = NULL;
-       priv->percent = NULL;
-       priv->priority = NULL;
+       g_return_val_if_fail (prop != NULL, NULL);
+       g_return_val_if_fail (get_prop_func != NULL, NULL);
 
-       priv->rdate_list = free_slist (priv->rdate_list);
+       value = get_prop_func (prop);
 
-       g_slist_free (priv->rrule_list);
-       priv->rrule_list = NULL;
+       /* Skip empty values */
+       if (!value || !*value)
+               return NULL;
 
-       priv->sequence = NULL;
+       altrep_param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
+       altrep = altrep_param ? i_cal_parameter_get_altrep (altrep_param) : NULL;
 
-       priv->summary.prop = NULL;
-       priv->summary.altrep_param = NULL;
+       if (altrep && !*altrep)
+               altrep = NULL;
 
-       priv->transparency = NULL;
-       priv->url = NULL;
-       priv->location = NULL;
+       return e_cal_component_text_new (value, altrep);
+}
 
-       /* Free the subcomponents */
+static void
+set_text_altrep_on_prop (ICalProperty *prop,
+                        const ECalComponentText *text)
+{
+       ICalParameter *param;
+       const gchar *altrep;
 
-       g_hash_table_foreach_remove (priv->alarm_uid_hash, free_alarm_cb, NULL);
+       g_return_if_fail (prop != NULL);
+       g_return_if_fail (text != NULL);
 
-       /* Free the icalcomponent */
+       altrep = e_cal_component_text_get_altrep (text);
+       param = i_cal_property_get_first_param (prop, I_CAL_ALTREP_PARAMETER);
 
-       if (free && icalcomponent_get_parent (priv->icalcomp) == NULL) {
-               icalcomponent_free (priv->icalcomp);
-               priv->icalcomp = NULL;
+       if (altrep && *altrep) {
+               if (param) {
+                       i_cal_parameter_set_altrep (param, (gchar *) altrep);
+               } else {
+                       param = i_cal_parameter_new_altrep ((gchar *) altrep);
+                       i_cal_property_take_parameter (prop, param);
+                       param = NULL;
+               }
+       } else if (param) {
+               i_cal_property_remove_parameter_by_kind (prop, I_CAL_ALTREP_PARAMETER);
        }
 
-       /* Clean up */
-
-       priv->need_sequence_inc = FALSE;
+       g_clear_object (&param);
 }
 
+
 static void
 cal_component_finalize (GObject *object)
 {
-       ECalComponentPrivate *priv;
+       ECalComponent *comp = E_CAL_COMPONENT (object);
 
-       priv = E_CAL_COMPONENT_GET_PRIVATE (object);
-
-       free_icalcomponent (E_CAL_COMPONENT (object), TRUE);
-       g_hash_table_destroy (priv->alarm_uid_hash);
+       free_icalcomponent (comp, TRUE);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_cal_component_parent_class)->finalize (object);
 }
 
-
-
 /* Class initialization function for the calendar component object */
 static void
 e_cal_component_class_init (ECalComponentClass *class)
@@ -357,8 +267,7 @@ e_cal_component_class_init (ECalComponentClass *class)
 static void
 e_cal_component_init (ECalComponent *comp)
 {
-       comp->priv = E_CAL_COMPONENT_GET_PRIVATE (comp);
-       comp->priv->alarm_uid_hash = g_hash_table_new (g_str_hash, g_str_equal);
+       comp->priv = G_TYPE_INSTANCE_GET_PRIVATE (comp, E_TYPE_CAL_COMPONENT, ECalComponentPrivate);
 }
 
 /**
@@ -368,7 +277,7 @@ e_cal_component_init (ECalComponent *comp)
  * existing #icalcomponent structure by using e_cal_component_set_icalcomponent() or with a
  * new empty component type by using e_cal_component_set_new_vtype().
  *
- * Returns: A newly-created calendar component object.
+ * Returns: (transfer full): A newly-created calendar component object.
  **/
 ECalComponent *
 e_cal_component_new (void)
@@ -382,17 +291,17 @@ e_cal_component_new (void)
  *
  * Creates a new calendar component object from the given iCalendar string.
  *
- * Returns: A calendar component representing the given iCalendar string on
+ * Returns: (transfer full): A calendar component representing the given iCalendar string on
  * success, NULL if there was an error.
  **/
 ECalComponent *
 e_cal_component_new_from_string (const gchar *calobj)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *icalcomp;
 
        g_return_val_if_fail (calobj != NULL, NULL);
 
-       icalcomp = icalparser_parse_string (calobj);
+       icalcomp = i_cal_parser_parse_string (calobj);
        if (!icalcomp)
                return NULL;
 
@@ -401,15 +310,15 @@ e_cal_component_new_from_string (const gchar *calobj)
 
 /**
  * e_cal_component_new_from_icalcomponent:
- * @icalcomp: An #icalcomponent to use
+ * @icalcomp: (transfer full): An #ICalComponent to use
  *
  * Creates a new #ECalComponent which will has set @icalcomp as
- * an inner #icalcomponent. The newly created #ECalComponent takes
+ * an inner #ICalComponent. The newly created #ECalComponent takes
  * ownership of the @icalcomp, and if the call
  * to e_cal_component_set_icalcomponent() fails, then @icalcomp
  * is freed.
  *
- * Returns: An #ECalComponent with @icalcomp assigned on success,
+ * Returns: (transfer full): An #ECalComponent with @icalcomp assigned on success,
  * NULL if the @icalcomp cannot be assigned to #ECalComponent.
  *
  * Since: 3.4
@@ -423,7 +332,7 @@ e_cal_component_new_from_icalcomponent (icalcomponent *icalcomp)
 
        comp = e_cal_component_new ();
        if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
-               icalcomponent_free (icalcomp);
+               g_object_unref (icalcomp);
                g_object_unref (comp);
 
                return NULL;
@@ -445,5693 +354,3572 @@ e_cal_component_new_from_icalcomponent (icalcomponent *icalcomp)
 ECalComponent *
 e_cal_component_clone (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
        ECalComponent *new_comp;
-       icalcomponent *new_icalcomp;
+       ICalComponent *new_icalcomp;
 
-       g_return_val_if_fail (comp != NULL, NULL);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->need_sequence_inc == FALSE, NULL);
+       g_return_val_if_fail (comp->priv->need_sequence_inc == FALSE, NULL);
 
        new_comp = e_cal_component_new ();
 
-       if (priv->icalcomp) {
-               new_icalcomp = icalcomponent_new_clone (priv->icalcomp);
-               e_cal_component_set_icalcomponent (new_comp, new_icalcomp);
+       if (comp->priv->icalcomp) {
+               new_icalcomp = i_cal_component_new_clone (comp->priv->icalcomp);
+               if (!new_icalcomp || !e_cal_component_set_icalcomponent (new_comp, new_icalcomp)) {
+                       g_clear_object (&new_icalcomp);
+                       g_clear_object (&new_comp);
+               }
        }
 
        return new_comp;
 }
 
-/* Scans an attachment property */
+/* Ensures that the mandatory calendar component properties (uid, dtstamp) do
+ * exist.  If they don't exist, it creates them automatically.
+ */
 static void
-scan_attachment (GSList **attachment_list,
-                 icalproperty *prop)
+ensure_mandatory_properties (ECalComponent *comp)
 {
-       struct attachment *attachment;
+       ICalProperty *prop;
 
-       attachment = g_new0 (struct attachment, 1);
-       attachment->prop = prop;
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       attachment->attach = icalproperty_get_attach (prop);
-       icalattach_ref (attachment->attach);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_UID_PROPERTY);
+       if (prop) {
+               g_object_unref (prop);
+       } else {
+               gchar *uid;
 
-       *attachment_list = g_slist_append (*attachment_list, attachment);
-}
+               uid = e_util_generate_uid ();
+               i_cal_component_set_uid (comp->priv->icalcomp, uid);
+               g_free (uid);
+       }
 
-/* Scans an attendee property */
-static void
-scan_attendee (GSList **attendee_list,
-               icalproperty *prop)
-{
-       struct attendee *attendee;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DTSTAMP_PROPERTY);
+       if (prop) {
+               g_object_unref (prop);
+       } else {
+               ICalTimetype *tt;
 
-       attendee = g_new (struct attendee, 1);
-       attendee->prop = prop;
+               tt = i_cal_time_current_time_with_zone (i_cal_timezone_get_utc_timezone ());
 
-       attendee->cutype_param = icalproperty_get_first_parameter (prop, ICAL_CUTYPE_PARAMETER);
-       attendee->member_param = icalproperty_get_first_parameter (prop, ICAL_MEMBER_PARAMETER);
-       attendee->role_param = icalproperty_get_first_parameter (prop, ICAL_ROLE_PARAMETER);
-       attendee->partstat_param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
-       attendee->rsvp_param = icalproperty_get_first_parameter (prop, ICAL_RSVP_PARAMETER);
-       attendee->delto_param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDTO_PARAMETER);
-       attendee->delfrom_param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER);
-       attendee->sentby_param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
-       attendee->cn_param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
-       attendee->language_param = icalproperty_get_first_parameter (prop, ICAL_LANGUAGE_PARAMETER);
+               prop = i_cal_property_new_dtstamp (tt);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
 
-       *attendee_list = g_slist_append (*attendee_list, attendee);
+               g_object_unref (tt);
+       }
 }
 
-/* Scans a date/time and timezone pair property */
-static void
-scan_datetime (ECalComponent *comp,
-               struct datetime *datetime,
-               icalproperty *prop)
+/**
+ * e_cal_component_set_new_vtype:
+ * @comp: A calendar component object.
+ * @type: Type of calendar component to create.
+ *
+ * Clears any existing component data from a calendar component object and
+ * creates a new #ICalComponent of the specified type for it.  The only property
+ * that will be set in the new component will be its unique identifier.
+ **/
+void
+e_cal_component_set_new_vtype (ECalComponent *comp,
+                               ECalComponentVType type)
 {
-       datetime->prop = prop;
-       datetime->tzid_param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
-}
+       ICalComponent *icalcomp;
+       ICalComponentKind kind;
 
-/* Scans an exception date property */
-static void
-scan_exdate (ECalComponent *comp,
-             icalproperty *prop)
-{
-       ECalComponentPrivate *priv;
-       struct datetime *dt;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
 
-       priv = comp->priv;
+       free_icalcomponent (comp, TRUE);
 
-       dt = g_new (struct datetime, 1);
-       dt->prop = prop;
-       dt->tzid_param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
+       if (type == E_CAL_COMPONENT_NO_TYPE)
+               return;
 
-       priv->exdate_list = g_slist_append (priv->exdate_list, dt);
-}
+       /* Figure out the kind and create the icalcomponent */
 
-/* Scans and attendee property */
-static void
-scan_organizer (ECalComponent *comp,
-                struct organizer *organizer,
-                icalproperty *prop)
-{
-       organizer->prop = prop;
+       switch (type) {
+       case E_CAL_COMPONENT_EVENT:
+               kind = I_CAL_VEVENT_COMPONENT;
+               break;
 
-       organizer->sentby_param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
-       organizer->cn_param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
-       organizer->language_param = icalproperty_get_first_parameter (prop, ICAL_LANGUAGE_PARAMETER);
-}
+       case E_CAL_COMPONENT_TODO:
+               kind = I_CAL_VTODO_COMPONENT;
+               break;
 
-/* Scans an icalperiodtype property */
-static void
-scan_period (ECalComponent *comp,
-             GSList **list,
-             icalproperty *prop)
-{
-       struct period *period;
+       case E_CAL_COMPONENT_JOURNAL:
+               kind = I_CAL_VJOURNAL_COMPONENT;
+               break;
 
-       period = g_new (struct period, 1);
-       period->prop = prop;
-       period->value_param = icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER);
+       case E_CAL_COMPONENT_FREEBUSY:
+               kind = I_CAL_VFREEBUSY_COMPONENT;
+               break;
 
-       *list = g_slist_append (*list, period);
-}
+       case E_CAL_COMPONENT_TIMEZONE:
+               kind = I_CAL_VTIMEZONE_COMPONENT;
+               break;
 
-/* Scans an icalrecurtype property */
-static void
-scan_recur_id (ECalComponent *comp,
-               struct recur_id *recur_id,
-               icalproperty *prop)
-{
-       scan_datetime (comp, &recur_id->recur_time, prop);
+       default:
+               g_warn_if_reached ();
+               kind = I_CAL_NO_COMPONENT;
+       }
 
-       recur_id->range_param = icalproperty_get_first_parameter (prop, ICAL_RANGE_PARAMETER);
-}
+       icalcomp = i_cal_component_new (kind);
+       if (!icalcomp) {
+               g_message ("e_cal_component_set_new_vtype(): Could not create the ICalComponent of kind %d!", 
kind);
+               return;
+       }
 
-/* Scans an icalrecurtype property */
-static void
-scan_recur (ECalComponent *comp,
-            GSList **list,
-            icalproperty *prop)
-{
-       *list = g_slist_append (*list, prop);
-}
+       /* Scan the component to build our mapping table */
 
-/* Scans the summary property */
-static void
-scan_summary (ECalComponent *comp,
-              icalproperty *prop)
-{
-       ECalComponentPrivate *priv;
+       comp->priv->icalcomp = icalcomp;
 
-       priv = comp->priv;
+       /* Add missing stuff */
 
-       priv->summary.prop = prop;
-       priv->summary.altrep_param = icalproperty_get_first_parameter (prop, ICAL_ALTREP_PARAMETER);
+       ensure_mandatory_properties (comp);
 }
 
-/* Scans a text (i.e. text + altrep) property */
-static void
-scan_text (ECalComponent *comp,
-           GSList **text_list,
-           icalproperty *prop)
+/**
+ * e_cal_component_set_icalcomponent:
+ * @comp: A calendar component object.
+ * @icalcomp: (transfer full) (nullable): An #ICalComponent.
+ *
+ * Sets the contents of a calendar component object from an #ICalComponent.
+ * If the @comp already had an #ICalComponent set into it, it will
+ * be freed automatically.
+ *
+ * Supported component types are VEVENT, VTODO, VJOURNAL, VFREEBUSY, and VTIMEZONE.
+ *
+ * Returns: %TRUE on success, %FALSE if @icalcomp is an unsupported component type.
+ **/
+gboolean
+e_cal_component_set_icalcomponent (ECalComponent *comp,
+                                  ICalComponent *icalcomp)
 {
-       struct text *text;
+       ICalComponentKind kind;
 
-       text = g_new (struct text, 1);
-       text->prop = prop;
-       text->altrep_param = icalproperty_get_first_parameter (prop, ICAL_ALTREP_PARAMETER);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       *text_list = g_slist_append (*text_list, text);
-}
+       if (comp->priv->icalcomp == icalcomp)
+               return TRUE;
 
-/* Scans an icalproperty and adds its mapping to the component */
-static void
-scan_property (ECalComponent *comp,
-               icalproperty *prop)
-{
-       ECalComponentPrivate *priv;
-       icalproperty_kind kind;
+       free_icalcomponent (comp, TRUE);
 
-       priv = comp->priv;
+       if (!icalcomp) {
+               comp->priv->icalcomp = NULL;
+               return TRUE;
+       }
 
-       kind = icalproperty_isa (prop);
+       kind = i_cal_component_isa (icalcomp);
 
-       switch (kind) {
-       case ICAL_STATUS_PROPERTY:
-               priv->status = prop;
-               break;
+       if (!(kind == I_CAL_VEVENT_COMPONENT
+             || kind == I_CAL_VTODO_COMPONENT
+             || kind == I_CAL_VJOURNAL_COMPONENT
+             || kind == I_CAL_VFREEBUSY_COMPONENT
+             || kind == I_CAL_VTIMEZONE_COMPONENT))
+               return FALSE;
 
-       case ICAL_ATTACH_PROPERTY:
-               scan_attachment (&priv->attachment_list, prop);
-               break;
+       comp->priv->icalcomp = icalcomp;
 
-       case ICAL_ATTENDEE_PROPERTY:
-               scan_attendee (&priv->attendee_list, prop);
-               break;
+       ensure_mandatory_properties (comp);
 
-       case ICAL_CATEGORIES_PROPERTY:
-               if (icalproperty_get_categories (prop)) {
-                       const gchar *categories = icalproperty_get_categories (prop);
-                       if (*categories) {
-                               if (!priv->categories_str) {
-                                       priv->categories_str = g_string_new (categories);
-                               } else {
-                                       g_string_append_c (priv->categories_str, ',');
-                                       g_string_append (priv->categories_str, categories);
-                               }
-                       }
-               }
-               break;
+       return TRUE;
+}
 
-       case ICAL_CLASS_PROPERTY:
-               priv->classification = prop;
-               break;
+/**
+ * e_cal_component_get_icalcomponent:
+ * @comp: A calendar component object.
+ *
+ * Queries the #icalcomponent structure that a calendar component object is
+ * wrapping.
+ *
+ * Returns: (transfer none) (nullable): An #ICalComponent structure, or %NULL
+ *    if the @comp has no #ICalComponent set to it.
+ **/
+ICalComponent *
+e_cal_component_get_icalcomponent (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
 
-       case ICAL_COMMENT_PROPERTY:
-               scan_text (comp, &priv->comment_list, prop);
-               break;
+       return comp->priv->icalcomp;
+}
 
-       case ICAL_COMPLETED_PROPERTY:
-               priv->completed = prop;
-               break;
+/**
+ * e_cal_component_strip_errors:
+ * @comp: A calendar component object.
+ *
+ * Strips all error messages from the calendar component. Those error messages are
+ * added to the iCalendar string representation whenever an invalid is used for
+ * one of its fields.
+ */
+void
+e_cal_component_strip_errors (ECalComponent *comp)
+{
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
 
-       case ICAL_CONTACT_PROPERTY:
-               scan_text (comp, &priv->contact_list, prop);
-               break;
+       if (comp->priv->icalcomp)
+               i_cal_component_strip_errors (comp->priv->icalcomp);
+}
 
-       case ICAL_CREATED_PROPERTY:
-               priv->created = prop;
-               break;
+/**
+ * e_cal_component_get_vtype:
+ * @comp: A calendar component object.
+ *
+ * Queries the type of a calendar component object.
+ *
+ * Returns: The type of the component, as defined by RFC 2445.
+ **/
+ECalComponentVType
+e_cal_component_get_vtype (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_NO_TYPE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, E_CAL_COMPONENT_NO_TYPE);
 
-       case ICAL_DESCRIPTION_PROPERTY:
-               scan_text (comp, &priv->description_list, prop);
-               break;
+       switch (i_cal_component_isa (comp->priv->icalcomp)) {
+       case I_CAL_VEVENT_COMPONENT:
+               return E_CAL_COMPONENT_EVENT;
 
-       case ICAL_DTEND_PROPERTY:
-               scan_datetime (comp, &priv->dtend, prop);
-               break;
+       case I_CAL_VTODO_COMPONENT:
+               return E_CAL_COMPONENT_TODO;
 
-       case ICAL_DTSTAMP_PROPERTY:
-               priv->dtstamp = prop;
-               break;
+       case I_CAL_VJOURNAL_COMPONENT:
+               return E_CAL_COMPONENT_JOURNAL;
 
-       case ICAL_DTSTART_PROPERTY:
-               scan_datetime (comp, &priv->dtstart, prop);
-               break;
+       case I_CAL_VFREEBUSY_COMPONENT:
+               return E_CAL_COMPONENT_FREEBUSY;
 
-       case ICAL_DUE_PROPERTY:
-               scan_datetime (comp, &priv->due, prop);
-               break;
-
-       case ICAL_DURATION_PROPERTY:
-               priv->duration = prop;
-               break;
-
-       case ICAL_EXDATE_PROPERTY:
-               scan_exdate (comp, prop);
-               break;
-
-       case ICAL_EXRULE_PROPERTY:
-               scan_recur (comp, &priv->exrule_list, prop);
-               break;
-
-       case ICAL_GEO_PROPERTY:
-               priv->geo = prop;
-               break;
-
-       case ICAL_LASTMODIFIED_PROPERTY:
-               priv->last_modified = prop;
-               break;
-
-       case ICAL_ORGANIZER_PROPERTY:
-               scan_organizer (comp, &priv->organizer, prop);
-               break;
-
-       case ICAL_PERCENTCOMPLETE_PROPERTY:
-               priv->percent = prop;
-               break;
-
-       case ICAL_PRIORITY_PROPERTY:
-               priv->priority = prop;
-               break;
-
-       case ICAL_RECURRENCEID_PROPERTY:
-               scan_recur_id (comp, &priv->recur_id, prop);
-               break;
-
-       case ICAL_RDATE_PROPERTY:
-               scan_period (comp, &priv->rdate_list, prop);
-               break;
-
-       case ICAL_RRULE_PROPERTY:
-               scan_recur (comp, &priv->rrule_list, prop);
-               break;
-
-       case ICAL_SEQUENCE_PROPERTY:
-               priv->sequence = prop;
-               break;
-
-       case ICAL_SUMMARY_PROPERTY:
-               scan_summary (comp, prop);
-               break;
-
-       case ICAL_TRANSP_PROPERTY:
-               priv->transparency = prop;
-               break;
-
-       case ICAL_UID_PROPERTY:
-               priv->uid = prop;
-               break;
-
-       case ICAL_URL_PROPERTY:
-               priv->url = prop;
-               break;
-
-       case ICAL_LOCATION_PROPERTY :
-               priv->location = prop;
-               break;
-
-       default:
-               break;
-       }
-}
-
-/* Gets our alarm UID string from a property that is known to contain it */
-static const gchar *
-alarm_uid_from_prop (icalproperty *prop)
-{
-       const gchar *xstr;
-
-       g_return_val_if_fail (icalproperty_isa (prop) == ICAL_X_PROPERTY, NULL);
-
-       xstr = icalproperty_get_x (prop);
-       g_return_val_if_fail (xstr != NULL, NULL);
-
-       return xstr;
-}
-
-/* Sets our alarm UID extension property on an alarm component.  Returns a
- * pointer to the UID string inside the property itself.
- */
-static const gchar *
-set_alarm_uid (icalcomponent *alarm,
-               const gchar *auid)
-{
-       icalproperty *prop;
-       const gchar *inprop_auid;
-
-       /* Create the new property */
-
-       prop = icalproperty_new_x ((gchar *) auid);
-       icalproperty_set_x_name (prop, EVOLUTION_ALARM_UID_PROPERTY);
-
-       icalcomponent_add_property (alarm, prop);
-
-       inprop_auid = alarm_uid_from_prop (prop);
-       return inprop_auid;
-}
-
-/* Removes any alarm UID extension properties from an alarm subcomponent */
-static void
-remove_alarm_uid (icalcomponent *alarm)
-{
-       icalproperty *prop;
-       GSList *list, *l;
-
-       list = NULL;
-
-       for (prop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY)) {
-               const gchar *xname;
-
-               xname = icalproperty_get_x_name (prop);
-               g_return_if_fail (xname != NULL);
-
-               if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0)
-                       list = g_slist_prepend (list, prop);
-       }
-
-       for (l = list; l; l = l->next) {
-               prop = l->data;
-               icalcomponent_remove_property (alarm, prop);
-               icalproperty_free (prop);
-       }
-
-       g_slist_free (list);
-}
-
-/* Adds an alarm subcomponent to the calendar component's mapping table.  The
- * actual UID with which it gets added may not be the same as the specified one;
- * this function will change it if the table already had an alarm subcomponent
- * with the specified UID.  Returns the actual UID used.
- */
-static const gchar *
-add_alarm (ECalComponent *comp,
-           icalcomponent *alarm,
-           const gchar *auid)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent *old_alarm;
-
-       priv = comp->priv;
-
-       /* First we see if we already have an alarm with the requested UID.  In
-        * that case, we need to change the new UID to something else.  This
-        * should never happen, but who knows.
-        */
-
-       old_alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid);
-       if (old_alarm != NULL) {
-               gchar *new_auid;
-
-               g_message ("add_alarm(): Got alarm with duplicated UID `%s', changing it...", auid);
-
-               remove_alarm_uid (alarm);
-
-               new_auid = e_util_generate_uid ();
-               auid = set_alarm_uid (alarm, new_auid);
-               g_free (new_auid);
-       }
-
-       g_hash_table_insert (priv->alarm_uid_hash, (gchar *) auid, alarm);
-       return auid;
-}
-
-/* Scans an alarm subcomponent, adds an UID extension property to it (so that we
- * can reference alarms by unique IDs), and adds its mapping to the component.  */
-static void
-scan_alarm (ECalComponent *comp,
-            icalcomponent *alarm)
-{
-       icalproperty *prop;
-       const gchar *auid;
-       gchar *new_auid;
-
-       for (prop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY)) {
-               const gchar *xname;
-
-               xname = icalproperty_get_x_name (prop);
-               g_return_if_fail (xname != NULL);
-
-               if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0) {
-                       auid = alarm_uid_from_prop (prop);
-                       add_alarm (comp, alarm, auid);
-                       return;
-               }
-       }
-
-       /* The component has no alarm UID property, so we create one. */
-
-       new_auid = e_util_generate_uid ();
-       auid = set_alarm_uid (alarm, new_auid);
-       g_free (new_auid);
-
-       add_alarm (comp, alarm, auid);
-}
-
-/* Scans an icalcomponent for its properties so that we can provide
- * random-access to them.  It also builds a hash table of the component's alarm
- * subcomponents.
- */
-static void
-scan_icalcomponent (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       icalproperty *prop;
-       icalcompiter iter;
-
-       priv = comp->priv;
-
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* Scan properties */
-
-       for (prop = icalcomponent_get_first_property (priv->icalcomp, ICAL_ANY_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (priv->icalcomp, ICAL_ANY_PROPERTY))
-               scan_property (comp, prop);
-
-       /* Scan subcomponents */
-
-       for (iter = icalcomponent_begin_component (priv->icalcomp, ICAL_VALARM_COMPONENT);
-            icalcompiter_deref (&iter) != NULL;
-            icalcompiter_next (&iter)) {
-               icalcomponent *subcomp;
-
-               subcomp = icalcompiter_deref (&iter);
-               scan_alarm (comp, subcomp);
-       }
-}
-
-/* Ensures that the mandatory calendar component properties (uid, dtstamp) do
- * exist.  If they don't exist, it creates them automatically.
- */
-static void
-ensure_mandatory_properties (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->uid) {
-               gchar *uid;
-
-               uid = e_util_generate_uid ();
-               priv->uid = icalproperty_new_uid (uid);
-               g_free (uid);
-
-               icalcomponent_add_property (priv->icalcomp, priv->uid);
-       }
-
-       if (!priv->dtstamp) {
-               struct icaltimetype t;
-
-               t = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
-
-               priv->dtstamp = icalproperty_new_dtstamp (t);
-               icalcomponent_add_property (priv->icalcomp, priv->dtstamp);
-       }
-}
-
-/**
- * e_cal_component_set_new_vtype:
- * @comp: A calendar component object.
- * @type: Type of calendar component to create.
- *
- * Clears any existing component data from a calendar component object and
- * creates a new #icalcomponent of the specified type for it.  The only property
- * that will be set in the new component will be its unique identifier.
- **/
-void
-e_cal_component_set_new_vtype (ECalComponent *comp,
-                               ECalComponentVType type)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent *icalcomp;
-       icalcomponent_kind kind;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-
-       free_icalcomponent (comp, TRUE);
-
-       if (type == E_CAL_COMPONENT_NO_TYPE)
-               return;
-
-       /* Figure out the kind and create the icalcomponent */
-
-       switch (type) {
-       case E_CAL_COMPONENT_EVENT:
-               kind = ICAL_VEVENT_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_TODO:
-               kind = ICAL_VTODO_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_JOURNAL:
-               kind = ICAL_VJOURNAL_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_FREEBUSY:
-               kind = ICAL_VFREEBUSY_COMPONENT;
-               break;
-
-       case E_CAL_COMPONENT_TIMEZONE:
-               kind = ICAL_VTIMEZONE_COMPONENT;
-               break;
-
-       default:
-               g_warn_if_reached ();
-               kind = ICAL_NO_COMPONENT;
-       }
-
-       icalcomp = icalcomponent_new (kind);
-       if (!icalcomp) {
-               g_message ("e_cal_component_set_new_vtype(): Could not create the icalcomponent!");
-               return;
-       }
-
-       /* Scan the component to build our mapping table */
-
-       priv->icalcomp = icalcomp;
-       scan_icalcomponent (comp);
-
-       /* Add missing stuff */
-
-       ensure_mandatory_properties (comp);
-}
-
-/**
- * e_cal_component_set_icalcomponent:
- * @comp: A calendar component object.
- * @icalcomp: (type long): An #icalcomponent.
- *
- * Sets the contents of a calendar component object from an #icalcomponent
- * structure.  If the @comp already had an #icalcomponent set into it, it will
- * will be freed automatically if the #icalcomponent does not have a parent
- * component itself.
- *
- * Supported component types are VEVENT, VTODO, VJOURNAL, VFREEBUSY, and VTIMEZONE.
- *
- * Returns: TRUE on success, FALSE if @icalcomp is an unsupported component
- * type.
- **/
-gboolean
-e_cal_component_set_icalcomponent (ECalComponent *comp,
-                                   icalcomponent *icalcomp)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent_kind kind;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-
-       if (priv->icalcomp == icalcomp)
-               return TRUE;
-
-       free_icalcomponent (comp, TRUE);
-
-       if (!icalcomp) {
-               priv->icalcomp = NULL;
-               return TRUE;
-       }
-
-       kind = icalcomponent_isa (icalcomp);
-
-       if (!(kind == ICAL_VEVENT_COMPONENT
-             || kind == ICAL_VTODO_COMPONENT
-             || kind == ICAL_VJOURNAL_COMPONENT
-             || kind == ICAL_VFREEBUSY_COMPONENT
-             || kind == ICAL_VTIMEZONE_COMPONENT))
-               return FALSE;
-
-       priv->icalcomp = icalcomp;
-
-       scan_icalcomponent (comp);
-       ensure_mandatory_properties (comp);
-
-       return TRUE;
-}
-
-/**
- * e_cal_component_get_icalcomponent:
- * @comp: A calendar component object.
- *
- * Queries the #icalcomponent structure that a calendar component object is
- * wrapping.
- *
- * Returns: An #icalcomponent structure, or NULL if the @comp has no
- * #icalcomponent set to it.
- **/
-icalcomponent *
-e_cal_component_get_icalcomponent (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-
-       return priv->icalcomp;
-}
-
-/**
- * e_cal_component_rescan:
- * @comp: A calendar component object.
- *
- * Rescans the #icalcomponent being wrapped by the given calendar component. This
- * would replace any value that was changed in the wrapped #icalcomponent.
- */
-void
-e_cal_component_rescan (ECalComponent *comp)
-{
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       /* Clear everything out */
-       free_icalcomponent (comp, FALSE);
-
-       /* Rescan */
-       scan_icalcomponent (comp);
-       ensure_mandatory_properties (comp);
-}
-
-/**
- * e_cal_component_strip_errors:
- * @comp: A calendar component object.
- *
- * Strips all error messages from the calendar component. Those error messages are
- * added to the iCalendar string representation whenever an invalid is used for
- * one of its fields.
- */
-void
-e_cal_component_strip_errors (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-
-       icalcomponent_strip_errors (priv->icalcomp);
-}
-
-/**
- * e_cal_component_get_vtype:
- * @comp: A calendar component object.
- *
- * Queries the type of a calendar component object.
- *
- * Returns: The type of the component, as defined by RFC 2445.
- **/
-ECalComponentVType
-e_cal_component_get_vtype (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       icalcomponent_kind kind;
-
-       g_return_val_if_fail (comp != NULL, E_CAL_COMPONENT_NO_TYPE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_NO_TYPE);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, E_CAL_COMPONENT_NO_TYPE);
-
-       kind = icalcomponent_isa (priv->icalcomp);
-       switch (kind) {
-       case ICAL_VEVENT_COMPONENT:
-               return E_CAL_COMPONENT_EVENT;
-
-       case ICAL_VTODO_COMPONENT:
-               return E_CAL_COMPONENT_TODO;
-
-       case ICAL_VJOURNAL_COMPONENT:
-               return E_CAL_COMPONENT_JOURNAL;
-
-       case ICAL_VFREEBUSY_COMPONENT:
-               return E_CAL_COMPONENT_FREEBUSY;
-
-       case ICAL_VTIMEZONE_COMPONENT:
-               return E_CAL_COMPONENT_TIMEZONE;
-
-       default:
-               /* We should have been loaded with a supported type! */
-               g_warn_if_reached ();
-               return E_CAL_COMPONENT_NO_TYPE;
-       }
-}
-
-/**
- * e_cal_component_get_as_string:
- * @comp: A calendar component.
- *
- * Gets the iCalendar string representation of a calendar component.  You should
- * call e_cal_component_commit_sequence() before this function to ensure that the
- * component's sequence number is consistent with the state of the object.
- *
- * Returns: String representation of the calendar component according to
- * RFC 2445.
- **/
-gchar *
-e_cal_component_get_as_string (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       gchar *str;
-
-       g_return_val_if_fail (comp != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
-       /* Ensure that the user has committed the new SEQUENCE */
-       g_return_val_if_fail (priv->need_sequence_inc == FALSE, NULL);
-
-       str = icalcomponent_as_ical_string_r (priv->icalcomp);
-
-       return str;
-}
-
-/* Used from g_hash_table_foreach(); ensures that an alarm subcomponent
- * has the mandatory properties it needs.
- */
-static void
-ensure_alarm_properties_cb (gpointer key,
-                            gpointer value,
-                            gpointer data)
-{
-       ECalComponent *comp;
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm;
-       icalproperty *prop;
-       enum icalproperty_action action;
-       const gchar *str;
-
-       alarm = value;
-
-       comp = E_CAL_COMPONENT (data);
-       priv = comp->priv;
-
-       prop = icalcomponent_get_first_property (alarm, ICAL_ACTION_PROPERTY);
-       if (!prop)
-               return;
-
-       action = icalproperty_get_action (prop);
-
-       switch (action) {
-       case ICAL_ACTION_DISPLAY:
-               /* Ensure we have a DESCRIPTION property */
-               prop = icalcomponent_get_first_property (alarm, ICAL_DESCRIPTION_PROPERTY);
-               if (prop) {
-                       if (priv->summary.prop) {
-                               icalproperty *xprop;
-
-                               xprop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-                               while (xprop) {
-                                       str = icalproperty_get_x_name (xprop);
-                                       if (!strcmp (str, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
-                                               icalproperty_set_description (prop, icalproperty_get_summary 
(priv->summary.prop));
-
-                                               icalcomponent_remove_property (alarm, xprop);
-                                               icalproperty_free (xprop);
-                                               break;
-                                       }
-
-                                       xprop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY);
-                               }
-
-                               break;
-                       }
-               }
-
-               if (!priv->summary.prop) {
-                       str = _("Untitled appointment");
-
-                       /* add the X-EVOLUTION-NEEDS-DESCRIPTION property */
-                       prop = icalproperty_new_x ("1");
-                       icalproperty_set_x_name (prop, "X-EVOLUTION-NEEDS-DESCRIPTION");
-                       icalcomponent_add_property (alarm, prop);
-               } else
-                       str = icalproperty_get_summary (priv->summary.prop);
-
-               prop = icalproperty_new_description (str);
-               icalcomponent_add_property (alarm, prop);
-
-               break;
-
-       default:
-               break;
-               /* FIXME: add other action types here */
-       }
-}
-
-/* Ensures that alarm subcomponents have the mandatory properties they need,
- * even when clients may not have set them properly.
- */
-static void
-ensure_alarm_properties (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-
-       g_hash_table_foreach (priv->alarm_uid_hash, ensure_alarm_properties_cb, comp);
-}
-
-/**
- * e_cal_component_commit_sequence:
- * @comp: A calendar component object.
- *
- * Increments the sequence number property in a calendar component object if it
- * needs it.  This needs to be done when any of a number of properties listed in
- * RFC 2445 change values, such as the start and end dates of a component.
- *
- * This function must be called before calling e_cal_component_get_as_string() to
- * ensure that the component is fully consistent.
- **/
-void
-e_cal_component_commit_sequence (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       ensure_alarm_properties (comp);
-
-       if (!priv->need_sequence_inc)
-               return;
-
-       if (priv->sequence) {
-               gint seq;
-
-               seq = icalproperty_get_sequence (priv->sequence);
-               icalproperty_set_sequence (priv->sequence, seq + 1);
-       } else {
-               /* The component had no SEQUENCE property, so assume that the
-                * default would have been zero.  Since it needed incrementing
-                * anyways, we use a value of 1 here.
-                */
-               priv->sequence = icalproperty_new_sequence (1);
-               icalcomponent_add_property (priv->icalcomp, priv->sequence);
-       }
-
-       priv->need_sequence_inc = FALSE;
-}
-
-/**
- * e_cal_component_abort_sequence:
- * @comp: A calendar component object.
- *
- * Aborts the sequence change needed in the given calendar component,
- * which means it will not require a sequence commit (via
- * e_cal_component_commit_sequence()) even if the changes done require a
- * sequence increment.
- */
-void
-e_cal_component_abort_sequence (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-
-       priv->need_sequence_inc = FALSE;
-}
-
-/**
- * e_cal_component_get_id:
- * @comp: A calendar component object.
- *
- * Get the ID of the component as a #ECalComponentId.  The return value should
- * be freed with e_cal_component_free_id() when you have finished with it.
- *
- * Returns: the id of the component
- */
-ECalComponentId *
-e_cal_component_get_id (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-       ECalComponentId *id = NULL;
-
-       g_return_val_if_fail (comp != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
-       id = g_new0 (ECalComponentId, 1);
-       id->uid = g_strdup (icalproperty_get_uid (priv->uid));
-       id->rid = e_cal_component_get_recurid_as_string (comp);
-
-       return id;
-}
-
-/**
- * e_cal_component_get_uid:
- * @comp: A calendar component object.
- * @uid: (out) (transfer none): Return value for the UID string.
- *
- * Queries the unique identifier of a calendar component object.
- **/
-void
-e_cal_component_get_uid (ECalComponent *comp,
-                         const gchar **uid)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (uid != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->uid != NULL);
-
-       *uid = icalproperty_get_uid (priv->uid);
-}
-
-/**
- * e_cal_component_set_uid:
- * @comp: A calendar component object.
- * @uid: Unique identifier.
- *
- * Sets the unique identifier string of a calendar component object.
- **/
-void
-e_cal_component_set_uid (ECalComponent *comp,
-                         const gchar *uid)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (uid != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->uid != NULL);
-
-       icalproperty_set_uid (priv->uid, (gchar *) uid);
-}
-
-static gboolean
-case_contains (const gchar *where,
-               const gchar *what)
-{
-       gchar *lwhere, *lwhat;
-       gboolean res = FALSE;
-
-       if (!where || !what) {
-               return FALSE;
-       }
-
-       lwhere = g_ascii_strdown (where, -1);
-       lwhat = g_ascii_strdown (what, -1);
-
-       res = lwhere && lwhat && strstr (lwhere, lwhat) != NULL;
-
-       g_free (lwhat);
-       g_free (lwhere);
-
-       return res;
-}
-
-/* Gets a text list value */
-static void
-get_attachment_list (ECalComponent *comp,
-                     GSList *attachment_list,
-                     GSList **al)
-{
-       GSList *l;
-       gint index;
-
-       *al = NULL;
-
-       if (!attachment_list)
-               return;
-
-       for (index = 0, l = attachment_list; l; l = l->next, index++) {
-               struct attachment *attachment;
-               gchar *buf = NULL;
-
-               attachment = l->data;
-               g_return_if_fail (attachment->attach != NULL);
-
-               if (icalattach_get_is_url (attachment->attach)) {
-                       const gchar *data;
-                       gsize buf_size;
-
-                       /* FIXME : this ref count is screwed up
-                        * These structures are being leaked.
-                        */
-                       icalattach_ref (attachment->attach);
-                       data = icalattach_get_url (attachment->attach);
-                       buf_size = strlen (data);
-                       buf = g_malloc0 (buf_size + 1);
-                       icalvalue_decode_ical_string (data, buf, buf_size);
-               } else if (attachment->prop) {
-                       if (!attachment->temporary_filename) {
-                               icalparameter *encoding_par = icalproperty_get_first_parameter 
(attachment->prop, ICAL_ENCODING_PARAMETER);
-                               if (encoding_par) {
-                                       gchar *str_value = icalproperty_get_value_as_string_r 
(attachment->prop);
-
-                                       if (str_value) {
-                                               icalparameter_encoding encoding = icalparameter_get_encoding 
(encoding_par);
-                                               guint8 *data = NULL;
-                                               gsize data_len = 0;
-
-                                               switch (encoding) {
-                                               case ICAL_ENCODING_8BIT:
-                                                       data = (guint8 *) str_value;
-                                                       data_len = strlen (str_value);
-                                                       str_value = NULL;
-                                                       break;
-                                               case ICAL_ENCODING_BASE64:
-                                                       data = g_base64_decode (str_value, &data_len);
-                                                       break;
-                                               default:
-                                                       break;
-                                               }
-
-                                               if (data) {
-                                                       gchar *dir, *id_str;
-                                                       ECalComponentId *id = e_cal_component_get_id (comp);
-
-                                                       id_str = g_strconcat (id ? id->uid : NULL, "-", id ? 
id->rid : NULL, NULL);
-                                                       dir = g_build_filename (e_get_user_cache_dir (), 
"tmp", "calendar", id_str, NULL);
-                                                       e_cal_component_free_id (id);
-                                                       g_free (id_str);
-
-                                                       if (g_mkdir_with_parents (dir, 0700) >= 0) {
-                                                               icalparameter *param;
-                                                               gchar *file = NULL;
-
-                                                               for (param = icalproperty_get_first_parameter 
(attachment->prop, ICAL_X_PARAMETER);
-                                                                    param && !file;
-                                                                    param = icalproperty_get_next_parameter 
(attachment->prop, ICAL_X_PARAMETER)) {
-                                                                       if (case_contains 
(icalparameter_get_xname (param), "NAME") && icalparameter_get_xvalue (param) && *icalparameter_get_xvalue 
(param))
-                                                                               file = g_strdup 
(icalparameter_get_xvalue (param));
-                                                               }
-
-                                                               if (!file)
-                                                                       file = g_strdup_printf ("%d.dat", 
index);
-
-                                                               attachment->temporary_filename = 
g_build_filename (dir, file, NULL);
-                                                               if (!g_file_set_contents 
(attachment->temporary_filename, (const gchar *) data, data_len, NULL)) {
-                                                                       g_free 
(attachment->temporary_filename);
-                                                                       attachment->temporary_filename = NULL;
-                                                               }
-                                                       }
-
-                                                       g_free (dir);
-                                               }
-
-                                               g_free (str_value);
-                                               g_free (data);
-                                       }
-                               }
-                       }
-
-                       if (attachment->temporary_filename)
-                               buf = g_filename_to_uri (attachment->temporary_filename, NULL, NULL);
-               }
-
-               if (buf)
-                       *al = g_slist_prepend (*al, buf);
-       }
-
-       *al = g_slist_reverse (*al);
-}
-
-static void
-set_attachment_list (icalcomponent *icalcomp,
-                     GSList **attachment_list,
-                     GSList *al)
-{
-       GSList *l;
-
-       /* Remove old attachments */
-
-       if (*attachment_list) {
-               for (l = *attachment_list; l; l = l->next) {
-                       struct attachment *attachment;
-
-                       attachment = l->data;
-                       g_return_if_fail (attachment->prop != NULL);
-                       g_return_if_fail (attachment->attach != NULL);
-
-                       icalcomponent_remove_property (icalcomp, attachment->prop);
-                       free_attachment (attachment);
-               }
-
-               g_slist_free (*attachment_list);
-               *attachment_list = NULL;
-       }
-       /* Add in new attachments */
-
-       for (l = al; l; l = l->next) {
-               struct attachment *attachment;
-               gsize buf_size;
-               gchar *buf;
-
-               attachment = g_new0 (struct attachment, 1);
-               buf_size = 2 * strlen ((gchar *) l->data);
-               buf = g_malloc0 (buf_size);
-               icalvalue_encode_ical_string (l->data, buf, buf_size);
-               attachment->attach = icalattach_new_from_url ((gchar *) buf);
-               attachment->prop = icalproperty_new_attach (attachment->attach);
-               icalcomponent_add_property (icalcomp, attachment->prop);
-               g_free (buf);
-               *attachment_list = g_slist_prepend (*attachment_list, attachment);
-       }
-
-       *attachment_list = g_slist_reverse (*attachment_list);
-}
-
-/**
- * e_cal_component_get_attachment_list:
- * @comp: A calendar component object
- * @attachment_list: (out) (transfer full) (element-type utf8): Return list of
- * URIs to attachments
- *
- * Queries the attachment properties of the calendar component object. When done,
- * the @attachment_list should be freed by calling g_slist_free().
- **/
-void
-e_cal_component_get_attachment_list (ECalComponent *comp,
-                                     GSList **attachment_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (attachment_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_attachment_list (comp, priv->attachment_list, attachment_list);
-}
-
-/**
- * e_cal_component_set_attachment_list:
- * @comp: A calendar component object
- * @attachment_list: (element-type utf8): list of URIs to attachment pointers
- *
- * This currently handles only attachments that are URIs
- * in the file system - not inline binaries.
- *
- * Sets the attachments of a calendar component object
- **/
-void
-e_cal_component_set_attachment_list (ECalComponent *comp,
-                                     GSList *attachment_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_attachment_list (priv->icalcomp, &priv->attachment_list, attachment_list);
-}
-
-/**
- * e_cal_component_has_attachments:
- * @comp: A calendar component object.
- *
- * Queries the component to see if it has attachments.
- *
- * Returns: TRUE if there are attachments, FALSE otherwise.
- */
-gboolean
-e_cal_component_has_attachments (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-
-       if (g_slist_length (priv->attachment_list) > 0)
-               return TRUE;
-
-       return FALSE;
-}
-
-/**
- * e_cal_component_get_num_attachments:
- * @comp: A calendar component object.
- *
- * Get the number of attachments to this calendar component object.
- *
- * Returns: the number of attachments.
- */
-gint
-e_cal_component_get_num_attachments (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, 0);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), 0);
-
-       priv = comp->priv;
-
-       return g_slist_length (priv->attachment_list) > 0;
-
-}
-
-/**
- * e_cal_component_get_categories:
- * @comp: A calendar component object.
- * @categories: (out) (transfer none): Return holder for the categories.
- *
- * Queries the categories of the given calendar component. The categories
- * are returned in the @categories argument, which, on success, will contain
- * a comma-separated list of all categories set in the component.
- **/
-void
-e_cal_component_get_categories (ECalComponent *comp,
-                                const gchar **categories)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (categories != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (priv->categories_str)
-               *categories = priv->categories_str->str;
-       else
-               *categories = NULL;
-}
-
-static void
-remove_all_categories (icalcomponent *icalcomp)
-{
-       icalproperty *prop, *to_remove;
-
-       g_return_if_fail (icalcomp != NULL);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_CATEGORIES_PROPERTY);
-       while (prop) {
-               to_remove = prop;
-               prop = icalcomponent_get_next_property (icalcomp, ICAL_CATEGORIES_PROPERTY);
-
-               icalcomponent_remove_property (icalcomp, to_remove);
-               icalproperty_free (to_remove);
-       }
-}
-
-/**
- * e_cal_component_set_categories:
- * @comp: A calendar component object.
- * @categories: Comma-separated list of categories.
- *
- * Sets the list of categories for a calendar component.
- **/
-void
-e_cal_component_set_categories (ECalComponent *comp,
-                                const gchar *categories)
-{
-       ECalComponentPrivate *priv;
-       icalproperty *prop;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!categories || !(*categories)) {
-               remove_all_categories (priv->icalcomp);
-               if (priv->categories_str) {
-                       g_string_free (priv->categories_str, TRUE);
-                       priv->categories_str = NULL;
-               }
-
-               return;
-       }
-
-       remove_all_categories (priv->icalcomp);
-       prop = icalproperty_new_categories (categories);
-       icalcomponent_add_property (priv->icalcomp, prop);
-
-       if (priv->categories_str)
-               g_string_free (priv->categories_str, TRUE);
-       priv->categories_str = g_string_new (categories);
-}
-
-/**
- * e_cal_component_get_categories_list:
- * @comp: A calendar component object.
- * @categ_list: (out) (transfer full) (element-type utf8): Return value for the
- * list of strings, where each string is a category. This should be freed using
- * e_cal_component_free_categories_list().
- *
- * Queries the list of categories of a calendar component object.  Each element
- * in the returned categ_list is a string with the corresponding category.
- **/
-void
-e_cal_component_get_categories_list (ECalComponent *comp,
-                                     GSList **categ_list)
-{
-       ECalComponentPrivate *priv;
-       icalproperty *prop;
-       const gchar *categories;
-       const gchar *p;
-       const gchar *cat_start;
-       gchar *str;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (categ_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->categories_str) {
-               *categ_list = NULL;
-               return;
-       }
-
-       *categ_list = NULL;
-
-       for (prop = icalcomponent_get_first_property (priv->icalcomp, ICAL_CATEGORIES_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (priv->icalcomp, ICAL_CATEGORIES_PROPERTY)) {
-               categories = icalproperty_get_categories (prop);
-               g_return_if_fail (categories != NULL);
-
-               cat_start = categories;
-
-               for (p = categories; *p; p++) {
-                       if (*p == ',') {
-                               str = g_strndup (cat_start, p - cat_start);
-                               *categ_list = g_slist_prepend (*categ_list, str);
-
-                               cat_start = p + 1;
-                       }
-               }
-
-               str = g_strndup (cat_start, p - cat_start);
-               *categ_list = g_slist_prepend (*categ_list, str);
-       }
-
-       *categ_list = g_slist_reverse (*categ_list);
-}
-
-/* Creates a comma-delimited string of categories */
-static gchar *
-stringify_categories (GSList *categ_list)
-{
-       GString *s;
-       GSList *l;
-       gchar *str;
-
-       s = g_string_new (NULL);
-
-       for (l = categ_list; l; l = l->next) {
-               g_string_append (s, l->data);
-
-               if (l->next != NULL)
-                       g_string_append (s, ",");
-       }
-
-       str = s->str;
-       g_string_free (s, FALSE);
-
-       return str;
-}
-
-/**
- * e_cal_component_set_categories_list:
- * @comp: A calendar component object.
- * @categ_list: (element-type utf8): List of strings, one for each category.
- *
- * Sets the list of categories of a calendar component object.
- **/
-void
-e_cal_component_set_categories_list (ECalComponent *comp,
-                                     GSList *categ_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!categ_list) {
-               e_cal_component_set_categories (comp, NULL);
-       } else {
-               gchar *categories_str;
-
-               /* Create a single string of categories */
-               categories_str = stringify_categories (categ_list);
-
-               /* Set the categories */
-               e_cal_component_set_categories (comp, categories_str);
-               g_free (categories_str);
-       }
-}
-
-/**
- * e_cal_component_get_classification:
- * @comp: A calendar component object.
- * @classif: (out): Return value for the classification.
- *
- * Queries the classification of a calendar component object.  If the
- * classification property is not set on this component, this function returns
- * #E_CAL_COMPONENT_CLASS_NONE.
- **/
-void
-e_cal_component_get_classification (ECalComponent *comp,
-                                    ECalComponentClassification *classif)
-{
-       ECalComponentPrivate *priv;
-       icalproperty_class class;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (classif != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!priv->classification) {
-               *classif = E_CAL_COMPONENT_CLASS_NONE;
-               return;
-       }
-
-       class = icalproperty_get_class (priv->classification);
-
-       switch (class)
-       {
-       case ICAL_CLASS_PUBLIC:
-         *classif = E_CAL_COMPONENT_CLASS_PUBLIC;
-         break;
-       case ICAL_CLASS_PRIVATE:
-         *classif = E_CAL_COMPONENT_CLASS_PRIVATE;
-         break;
-       case ICAL_CLASS_CONFIDENTIAL:
-         *classif = E_CAL_COMPONENT_CLASS_CONFIDENTIAL;
-         break;
-       default:
-         *classif = E_CAL_COMPONENT_CLASS_UNKNOWN;
-         break;
-       }
-}
-
-/**
- * e_cal_component_set_classification:
- * @comp: A calendar component object.
- * @classif: Classification to use.
- *
- * Sets the classification property of a calendar component object.  To unset
- * the property, specify E_CAL_COMPONENT_CLASS_NONE for @classif.
- **/
-void
-e_cal_component_set_classification (ECalComponent *comp,
-                                    ECalComponentClassification classif)
-{
-       ECalComponentPrivate *priv;
-       icalproperty_class class;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (classif != E_CAL_COMPONENT_CLASS_UNKNOWN);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (classif == E_CAL_COMPONENT_CLASS_NONE) {
-               if (priv->classification) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->classification);
-                       icalproperty_free (priv->classification);
-                       priv->classification = NULL;
-               }
-
-               return;
-       }
-
-       switch (classif) {
-       case E_CAL_COMPONENT_CLASS_PUBLIC:
-         class = ICAL_CLASS_PUBLIC;
-               break;
-
-       case E_CAL_COMPONENT_CLASS_PRIVATE:
-         class = ICAL_CLASS_PRIVATE;
-               break;
-
-       case E_CAL_COMPONENT_CLASS_CONFIDENTIAL:
-         class = ICAL_CLASS_CONFIDENTIAL;
-               break;
-
-       default:
-               g_warn_if_reached ();
-               class = ICAL_CLASS_NONE;
-       }
-
-       if (priv->classification)
-               icalproperty_set_class (priv->classification, class);
-       else {
-               priv->classification = icalproperty_new_class (class);
-               icalcomponent_add_property (priv->icalcomp, priv->classification);
-       }
-}
-
-/* Gets a text list value */
-static void
-get_text_list (GSList *text_list,
-               const gchar *(* get_prop_func) (const icalproperty *prop),
-               GSList **tl)
-{
-       GSList *l;
-
-       *tl = NULL;
-
-       if (!text_list)
-               return;
-
-       for (l = text_list; l; l = l->next) {
-               struct text *text;
-               ECalComponentText *t;
-               const gchar *value;
-
-               text = l->data;
-               g_return_if_fail (text->prop != NULL);
-
-               value = (* get_prop_func) (text->prop);
-               /* Skip empty values */
-               if (!value || !*value)
-                       continue;
-
-               t = g_new (ECalComponentText, 1);
-               t->value = value;
-
-               if (text->altrep_param)
-                       t->altrep = icalparameter_get_altrep (text->altrep_param);
-               else
-                       t->altrep = NULL;
-
-               *tl = g_slist_prepend (*tl, t);
-       }
-
-       *tl = g_slist_reverse (*tl);
-}
-
-/* Sets a text list value */
-static void
-set_text_list (ECalComponent *comp,
-               icalproperty *(* new_prop_func) (const gchar *value),
-               GSList **text_list,
-               GSList *tl)
-{
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       priv = comp->priv;
-
-       /* Remove old texts */
-
-       for (l = *text_list; l; l = l->next) {
-               struct text *text;
-
-               text = l->data;
-               g_return_if_fail (text->prop != NULL);
-
-               icalcomponent_remove_property (priv->icalcomp, text->prop);
-               icalproperty_free (text->prop);
-               g_free (text);
-       }
-
-       g_slist_free (*text_list);
-       *text_list = NULL;
-
-       /* Add in new texts */
-
-       for (l = tl; l; l = l->next) {
-               ECalComponentText *t;
-               struct text *text;
-
-               t = l->data;
-               g_return_if_fail (t->value != NULL);
-
-               text = g_new (struct text, 1);
-
-               text->prop = (* new_prop_func) ((gchar *) t->value);
-               icalcomponent_add_property (priv->icalcomp, text->prop);
-
-               if (t->altrep) {
-                       text->altrep_param = icalparameter_new_altrep ((gchar *) t->altrep);
-                       icalproperty_add_parameter (text->prop, text->altrep_param);
-               } else
-                       text->altrep_param = NULL;
-
-               *text_list = g_slist_prepend (*text_list, text);
-       }
-
-       *text_list = g_slist_reverse (*text_list);
-}
-
-/**
- * e_cal_component_get_comment_list:
- * @comp: A calendar component object.
- * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
- * value for the comment properties and their parameters, as a list of
- * #ECalComponentText structures.  This should be freed using the
- * e_cal_component_free_text_list() function.
- *
- * Queries the comments of a calendar component object.  The comment property can
- * appear several times inside a calendar component, and so a list of
- * #ECalComponentText is returned.
- **/
-void
-e_cal_component_get_comment_list (ECalComponent *comp,
-                                  GSList **text_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (text_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_text_list (priv->comment_list, icalproperty_get_comment, text_list);
-}
-
-/**
- * e_cal_component_set_comment_list:
- * @comp: A calendar component object.
- * @text_list: (element-type ECalComponentText): List of #ECalComponentText
- * structures.
- *
- * Sets the comments of a calendar component object.  The comment property can
- * appear several times inside a calendar component, and so a list of
- * #ECalComponentText structures is used.
- **/
-void
-e_cal_component_set_comment_list (ECalComponent *comp,
-                                  GSList *text_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_text_list (comp, icalproperty_new_comment, &priv->comment_list, text_list);
-}
-
-/**
- * e_cal_component_get_contact_list:
- * @comp: A calendar component object.
- * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
- * value for the contact properties and their parameters, as a list of
- * #ECalComponentText structures.  This should be freed using the
- * e_cal_component_free_text_list() function.
- *
- * Queries the contact of a calendar component object.  The contact property can
- * appear several times inside a calendar component, and so a list of
- * #ECalComponentText is returned.
- **/
-void
-e_cal_component_get_contact_list (ECalComponent *comp,
-                                  GSList **text_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (text_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_text_list (priv->contact_list, icalproperty_get_contact, text_list);
-}
-
-/**
- * e_cal_component_set_contact_list:
- * @comp: A calendar component object.
- * @text_list: (element-type ECalComponentText): List of #ECalComponentText
- * structures.
- *
- * Sets the contact of a calendar component object.  The contact property can
- * appear several times inside a calendar component, and so a list of
- * #ECalComponentText structures is used.
- **/
-void
-e_cal_component_set_contact_list (ECalComponent *comp,
-                                  GSList *text_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_text_list (comp, icalproperty_new_contact, &priv->contact_list, text_list);
-}
-
-/* Gets a struct icaltimetype value */
-static void
-get_icaltimetype (icalproperty *prop,
-                  struct icaltimetype (*get_prop_func) (const icalproperty *prop),
-                                                        struct icaltimetype **t)
-{
-       if (!prop) {
-               *t = NULL;
-               return;
-       }
-
-       *t = g_new (struct icaltimetype, 1);
-       **t = (* get_prop_func) (prop);
-}
-
-/* Sets a struct icaltimetype value */
-static void
-set_icaltimetype (ECalComponent *comp,
-                  icalproperty **prop,
-                  icalproperty *(*prop_new_func) (struct icaltimetype v),
-                  void (* prop_set_func) (icalproperty *prop,
-                                          struct icaltimetype v),
-                  struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-
-       if (!t) {
-               if (*prop) {
-                       icalcomponent_remove_property (priv->icalcomp, *prop);
-                       icalproperty_free (*prop);
-                       *prop = NULL;
-               }
-
-               return;
-       }
-
-       if (*prop)
-               (* prop_set_func) (*prop, *t);
-       else {
-               *prop = (* prop_new_func) (*t);
-               icalcomponent_add_property (priv->icalcomp, *prop);
-       }
-}
-
-/**
- * e_cal_component_get_completed:
- * @comp: A calendar component object.
- * @t: (out): Return value for the completion date.  This should be freed using the
- * e_cal_component_free_icaltimetype() function.
- *
- * Queries the date at which a calendar compoment object was completed.
- **/
-void
-e_cal_component_get_completed (ECalComponent *comp,
-                               struct icaltimetype **t)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_icaltimetype (priv->completed, icalproperty_get_completed, t);
-}
-
-/**
- * e_cal_component_set_completed:
- * @comp: A calendar component object.
- * @t: Value for the completion date.
- *
- * Sets the date at which a calendar component object was completed.
- **/
-void
-e_cal_component_set_completed (ECalComponent *comp,
-                               struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-       struct icaltimetype tmp_tt;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (t && t->is_date) {
-               tmp_tt = *t;
-               t = &tmp_tt;
-
-               tmp_tt.is_date = 0;
-               tmp_tt.hour = 0;
-               tmp_tt.minute = 0;
-               tmp_tt.second = 0;
-               tmp_tt.zone = icaltimezone_get_utc_timezone ();
-       }
-
-       set_icaltimetype (
-               comp, &priv->completed,
-               icalproperty_new_completed,
-               icalproperty_set_completed,
-               t);
-}
-
-/**
- * e_cal_component_get_created:
- * @comp: A calendar component object.
- * @t: (out): Return value for the creation date.  This should be freed using the
- * e_cal_component_free_icaltimetype() function.
- *
- * Queries the date in which a calendar component object was created in the
- * calendar store.
- **/
-void
-e_cal_component_get_created (ECalComponent *comp,
-                             struct icaltimetype **t)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_icaltimetype (priv->created, icalproperty_get_created, t);
-}
-
-/**
- * e_cal_component_set_created:
- * @comp: A calendar component object.
- * @t: Value for the creation date.
- *
- * Sets the date in which a calendar component object is created in the calendar
- * store.  This should only be used inside a calendar store application, i.e.
- * not by calendar user agents.
- **/
-void
-e_cal_component_set_created (ECalComponent *comp,
-                             struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_icaltimetype (
-               comp, &priv->created,
-               icalproperty_new_created,
-               icalproperty_set_created,
-               t);
-}
-
-/**
- * e_cal_component_get_description_list:
- * @comp: A calendar component object.
- * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
- * value for the description properties and their parameters, as a list of
- * #ECalComponentText structures.  This should be freed using the
- * e_cal_component_free_text_list() function.
- *
- * Queries the description of a calendar component object.  Journal components
- * may have more than one description, and as such this function returns a list
- * of #ECalComponentText structures.  All other types of components can have at
- * most one description.
- **/
-void
-e_cal_component_get_description_list (ECalComponent *comp,
-                                      GSList **text_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (text_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_text_list (priv->description_list, icalproperty_get_description, text_list);
-}
-
-/**
- * e_cal_component_set_description_list:
- * @comp: A calendar component object.
- * @text_list: (element-type ECalComponentText): List of
- * #ECalComponentText structures.
- *
- * Sets the description of a calendar component object.  Journal components may
- * have more than one description, and as such this function takes in a list of
- * #ECalComponentText structures.  All other types of components can have
- * at most one description.
- **/
-void
-e_cal_component_set_description_list (ECalComponent *comp,
-                                      GSList *text_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_text_list (comp, icalproperty_new_description, &priv->description_list, text_list);
-}
-
-/* Gets a date/time and timezone pair */
-static void
-get_datetime (struct datetime *datetime,
-              struct icaltimetype (* get_prop_func) (const icalproperty *prop),
-              ECalComponentDateTime *dt)
-{
-       if (datetime->prop) {
-               dt->value = g_new (struct icaltimetype, 1);
-               *dt->value = (* get_prop_func) (datetime->prop);
-       } else
-               dt->value = NULL;
-
-       /* If the icaltimetype has is_utc set, we set "UTC" as the TZID.
-        * This makes the timezone code simpler. */
-       if (datetime->tzid_param)
-               dt->tzid = g_strdup (icalparameter_get_tzid (datetime->tzid_param));
-       else if (dt->value && icaltime_is_utc (*dt->value))
-               dt->tzid = g_strdup ("UTC");
-       else
-               dt->tzid = NULL;
-}
-
-/* Sets a date/time and timezone pair */
-static void
-set_datetime (ECalComponent *comp,
-              struct datetime *datetime,
-              icalproperty *(* prop_new_func) (struct icaltimetype v),
-              void (* prop_set_func) (icalproperty *prop,
-                                      struct icaltimetype v),
-              ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       priv = comp->priv;
-
-       /* If we are setting the property to NULL (i.e. removing it), then
-        * we remove it if it exists. */
-       if (!dt) {
-               if (datetime->prop) {
-                       icalcomponent_remove_property (priv->icalcomp, datetime->prop);
-                       icalproperty_free (datetime->prop);
-
-                       datetime->prop = NULL;
-                       datetime->tzid_param = NULL;
-               }
-
-               return;
-       }
-
-       g_return_if_fail (dt->value != NULL);
-
-       /* If the TZID is set to "UTC", we set the is_utc flag. */
-       if (dt->tzid && !strcmp (dt->tzid, "UTC"))
-               dt->value->zone = icaltimezone_get_utc_timezone ();
-       else if (dt->value->zone == icaltimezone_get_utc_timezone ())
-               dt->value->zone = NULL;
-
-       if (datetime->prop) {
-               /* make sure no VALUE property is left if not needed */
-               icalproperty_remove_parameter_by_kind (datetime->prop, ICAL_VALUE_PARAMETER);
-
-               (* prop_set_func) (datetime->prop, *dt->value);
-       } else {
-               datetime->prop = (* prop_new_func) (*dt->value);
-               icalcomponent_add_property (priv->icalcomp, datetime->prop);
-       }
-
-       /* If the TZID is set to "UTC", we don't want to save the TZID. */
-       if (dt->tzid && strcmp (dt->tzid, "UTC")) {
-               g_return_if_fail (datetime->prop != NULL);
-
-               if (datetime->tzid_param) {
-                       icalparameter_set_tzid (datetime->tzid_param, (gchar *) dt->tzid);
-               } else {
-                       datetime->tzid_param = icalparameter_new_tzid ((gchar *) dt->tzid);
-                       icalproperty_add_parameter (datetime->prop, datetime->tzid_param);
-               }
-       } else if (datetime->tzid_param) {
-               icalproperty_remove_parameter_by_kind (datetime->prop, ICAL_TZID_PARAMETER);
-               datetime->tzid_param = NULL;
-       }
-}
-
-/* This tries to get the DTSTART + DURATION for a VEVENT or VTODO. In a
- * VEVENT this is used for the DTEND if no DTEND exists, In a VTOTO it is
- * used for the DUE date if DUE doesn't exist. */
-static void
-e_cal_component_get_start_plus_duration (ECalComponent *comp,
-                                         ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-       struct icaldurationtype duration;
-
-       priv = comp->priv;
-
-       if (!priv->duration)
-               return;
-
-       /* Get the DTSTART time. */
-       get_datetime (&priv->dtstart, icalproperty_get_dtstart, dt);
-       if (!dt->value)
-               return;
-
-       duration = icalproperty_get_duration (priv->duration);
-
-       /* The DURATION shouldn't be negative, but just return DTSTART if it
-        * is, i.e. assume it is 0. */
-       if (duration.is_neg)
-               return;
-
-       /* If DTSTART is a DATE value, then we need to check if the DURATION
-        * includes any hours, minutes or seconds. If it does, we need to
-        * make the DTEND/DUE a DATE-TIME value. */
-       duration.days += duration.weeks * 7;
-       if (dt->value->is_date) {
-               if (duration.hours != 0 || duration.minutes != 0
-                   || duration.seconds != 0) {
-                       dt->value->is_date = 0;
-               }
-       }
-
-       /* Add on the DURATION. */
-       icaltime_adjust (
-               dt->value, duration.days, duration.hours,
-               duration.minutes, duration.seconds);
-}
-
-/**
- * e_cal_component_get_dtend:
- * @comp: A calendar component object.
- * @dt: (out): Return value for the date/time end.  This should be freed with the
- * e_cal_component_free_datetime() function.
- *
- * Queries the date/time end of a calendar component object.
- **/
-void
-e_cal_component_get_dtend (ECalComponent *comp,
-                           ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (dt != NULL);
-
-       dt->tzid = NULL;
-       dt->value = NULL;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_datetime (&priv->dtend, icalproperty_get_dtend, dt);
-
-       /* If we don't have a DTEND property, then we try to get DTSTART
-        * + DURATION. */
-       if (!dt->value)
-               e_cal_component_get_start_plus_duration (comp, dt);
-}
-
-/**
- * e_cal_component_set_dtend:
- * @comp: A calendar component object.
- * @dt: End date/time.
- *
- * Sets the date/time end property of a calendar component object.
- **/
-void
-e_cal_component_set_dtend (ECalComponent *comp,
-                           ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->dtend,
-               icalproperty_new_dtend,
-               icalproperty_set_dtend,
-               dt);
-
-       /* Make sure we remove any existing DURATION property, as it can't be
-        * used with a DTEND. If DTEND is set to NULL, i.e. removed, we also
-        * want to remove any DURATION. */
-       if (priv->duration) {
-               icalcomponent_remove_property (priv->icalcomp, priv->duration);
-               icalproperty_free (priv->duration);
-               priv->duration = NULL;
-       }
-
-       priv->need_sequence_inc = TRUE;
-}
-
-/**
- * e_cal_component_get_dtstamp:
- * @comp: A calendar component object.
- * @t: (out): A value for the date/timestamp.
- *
- * Queries the date/timestamp property of a calendar component object, which is
- * the last time at which the object was modified by a calendar user agent.
- **/
-void
-e_cal_component_get_dtstamp (ECalComponent *comp,
-                             struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->dtstamp != NULL);
-
-       *t = icalproperty_get_dtstamp (priv->dtstamp);
-}
-
-/**
- * e_cal_component_set_dtstamp:
- * @comp: A calendar component object.
- * @t: Date/timestamp value.
- *
- * Sets the date/timestamp of a calendar component object.  This should be
- * called whenever a calendar user agent makes a change to a component's
- * properties.
- **/
-void
-e_cal_component_set_dtstamp (ECalComponent *comp,
-                             struct icaltimetype *t)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* This MUST exist, since we ensured that it did */
-       g_return_if_fail (priv->dtstamp != NULL);
-
-       icalproperty_set_dtstamp (priv->dtstamp, *t);
-}
-
-/**
- * e_cal_component_get_dtstart:
- * @comp: A calendar component object.
- * @dt: (out): Return value for the date/time start.  This should be freed with the
- * e_cal_component_free_datetime() function.
- *
- * Queries the date/time start of a calendar component object.
- **/
-void
-e_cal_component_get_dtstart (ECalComponent *comp,
-                             ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (dt != NULL);
-
-       dt->tzid = NULL;
-       dt->value = NULL;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_datetime (&priv->dtstart, icalproperty_get_dtstart, dt);
-}
-
-/**
- * e_cal_component_set_dtstart:
- * @comp: A calendar component object.
- * @dt: Start date/time.
- *
- * Sets the date/time start property of a calendar component object.
- **/
-void
-e_cal_component_set_dtstart (ECalComponent *comp,
-                             ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->dtstart,
-               icalproperty_new_dtstart,
-               icalproperty_set_dtstart,
-               dt);
-
-       priv->need_sequence_inc = TRUE;
-}
-
-/**
- * e_cal_component_get_due:
- * @comp: A calendar component object.
- * @dt: (out): Return value for the due date/time.  This should be freed with the
- * e_cal_component_free_datetime() function.
- *
- * Queries the due date/time of a calendar component object.
- **/
-void
-e_cal_component_get_due (ECalComponent *comp,
-                         ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (dt != NULL);
-
-       dt->tzid = NULL;
-       dt->value = NULL;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_datetime (&priv->due, icalproperty_get_due, dt);
-
-       /* If we don't have a DTEND property, then we try to get DTSTART
-        * + DURATION. */
-       if (!dt->value)
-               e_cal_component_get_start_plus_duration (comp, dt);
-}
-
-/**
- * e_cal_component_set_due:
- * @comp: A calendar component object.
- * @dt: End date/time.
- *
- * Sets the due date/time property of a calendar component object.
- **/
-void
-e_cal_component_set_due (ECalComponent *comp,
-                         ECalComponentDateTime *dt)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->due,
-               icalproperty_new_due,
-               icalproperty_set_due,
-               dt);
-
-       /* Make sure we remove any existing DURATION property, as it can't be
-        * used with a DTEND. If DTEND is set to NULL, i.e. removed, we also
-        * want to remove any DURATION. */
-       if (priv->duration) {
-               icalcomponent_remove_property (priv->icalcomp, priv->duration);
-               icalproperty_free (priv->duration);
-               priv->duration = NULL;
-       }
-
-       priv->need_sequence_inc = TRUE;
-}
-
-/* Builds a list of ECalComponentPeriod structures based on a list of icalproperties */
-static void
-get_period_list (GSList *period_list,
-                 struct icaldatetimeperiodtype (* get_prop_func) (const icalproperty *prop),
-                 GSList **list)
-{
-       GSList *l;
-
-       *list = NULL;
-
-       if (!period_list)
-               return;
-
-       for (l = period_list; l; l = l->next) {
-               struct period *period;
-               ECalComponentPeriod *p;
-               struct icaldatetimeperiodtype ip;
-
-               period = l->data;
-               g_return_if_fail (period->prop != NULL);
-
-               p = g_new (ECalComponentPeriod, 1);
-
-               /* Get start and end/duration */
-               ip = (* get_prop_func) (period->prop);
-
-               /* Get value parameter */
-               if (period->value_param) {
-                       icalparameter_value value_type;
-
-                       value_type = icalparameter_get_value (period->value_param);
-
-                       if (value_type == ICAL_VALUE_DATE || value_type == ICAL_VALUE_DATETIME)
-                               p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
-                       else if (value_type == ICAL_VALUE_DURATION)
-                               p->type = E_CAL_COMPONENT_PERIOD_DURATION;
-                       else if (value_type == ICAL_VALUE_PERIOD) {
-                               if (icaldurationtype_is_null_duration (ip.period.duration) || 
icaldurationtype_is_bad_duration (ip.period.duration))
-                                       p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
-                               else
-                                       p->type = E_CAL_COMPONENT_PERIOD_DURATION;
-                       } else {
-                               g_message (
-                                       "get_period_list(): Unknown value for period %d; "
-                                       "using DATETIME", value_type);
-                               p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
-                       }
-               } else
-                       p->type = E_CAL_COMPONENT_PERIOD_DATETIME;
-
-               p->start = ip.period.start;
-
-               if (p->type == E_CAL_COMPONENT_PERIOD_DATETIME)
-                       p->u.end = ip.period.end;
-               else if (p->type == E_CAL_COMPONENT_PERIOD_DURATION)
-                       p->u.duration = ip.period.duration;
-               else
-                       g_return_if_reached ();
-
-               /* Put in list */
-
-               *list = g_slist_prepend (*list, p);
-       }
-
-       *list = g_slist_reverse (*list);
-}
-
-/* Sets a period list value */
-static void
-set_period_list (ECalComponent *comp,
-                 icalproperty *(* new_prop_func) (struct icaldatetimeperiodtype period),
-                 GSList **period_list,
-                 GSList *pl)
-{
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       priv = comp->priv;
-
-       /* Remove old periods */
-
-       for (l = *period_list; l; l = l->next) {
-               struct period *period;
-
-               period = l->data;
-               g_return_if_fail (period->prop != NULL);
-
-               icalcomponent_remove_property (priv->icalcomp, period->prop);
-               icalproperty_free (period->prop);
-               g_free (period);
-       }
-
-       g_slist_free (*period_list);
-       *period_list = NULL;
-
-       /* Add in new periods */
-
-       for (l = pl; l; l = l->next) {
-               ECalComponentPeriod *p;
-               struct period *period;
-               struct icaldatetimeperiodtype ip = {};
-               icalparameter_value value_type;
-
-               g_return_if_fail (l->data != NULL);
-               p = l->data;
-
-               /* Create libical value */
-
-               ip.period.start = p->start;
-
-               if (p->type == E_CAL_COMPONENT_PERIOD_DATETIME) {
-                       value_type = ICAL_VALUE_DATETIME;
-                       ip.period.end = p->u.end;
-               } else if (p->type == E_CAL_COMPONENT_PERIOD_DURATION) {
-                       value_type = ICAL_VALUE_DURATION;
-                       ip.period.duration = p->u.duration;
-               } else {
-                       g_return_if_reached ();
-               }
-
-               /* Create property */
-
-               period = g_new (struct period, 1);
-
-               period->prop = (* new_prop_func) (ip);
-               period->value_param = icalparameter_new_value (value_type);
-               icalproperty_add_parameter (period->prop, period->value_param);
-
-               /* Add to list */
-
-               *period_list = g_slist_prepend (*period_list, period);
-       }
-
-       *period_list = g_slist_reverse (*period_list);
-}
-
-/**
- * e_cal_component_get_exdate_list:
- * @comp: A calendar component object.
- * @exdate_list: (out) (transfer full) (element-type ECalComponentDateTime):
- * Return value for the list of exception dates, as a list of
- * #ECalComponentDateTime structures.  This should be freed using the
- * e_cal_component_free_exdate_list() function.
- *
- * Queries the list of exception date properties in a calendar component object.
- **/
-void
-e_cal_component_get_exdate_list (ECalComponent *comp,
-                                 GSList **exdate_list)
-{
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (exdate_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       *exdate_list = NULL;
-
-       for (l = priv->exdate_list; l; l = l->next) {
-               struct datetime *dt;
-               ECalComponentDateTime *cdt;
-
-               dt = l->data;
-
-               cdt = g_new (ECalComponentDateTime, 1);
-               cdt->value = g_new (struct icaltimetype, 1);
-
-               *cdt->value = icalproperty_get_exdate (dt->prop);
-
-               if (dt->tzid_param)
-                       cdt->tzid = g_strdup (icalparameter_get_tzid (dt->tzid_param));
-               else
-                       cdt->tzid = NULL;
-
-               *exdate_list = g_slist_prepend (*exdate_list, cdt);
-       }
-
-       *exdate_list = g_slist_reverse (*exdate_list);
-}
-
-/**
- * e_cal_component_set_exdate_list:
- * @comp: A calendar component object.
- * @exdate_list: (element-type ECalComponentDateTime): List of
- * #ECalComponentDateTime structures.
- *
- * Sets the list of exception dates in a calendar component object.
- **/
-void
-e_cal_component_set_exdate_list (ECalComponent *comp,
-                                 GSList *exdate_list)
-{
-       ECalComponentPrivate *priv;
-       GSList *l;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       /* Remove old exception dates */
-
-       for (l = priv->exdate_list; l; l = l->next) {
-               struct datetime *dt;
-
-               dt = l->data;
-
-               /* Removing the DATE or DATE-TIME property will also remove
-                * any TZID parameter. */
-               icalcomponent_remove_property (priv->icalcomp, dt->prop);
-               icalproperty_free (dt->prop);
-               g_free (dt);
-       }
-
-       g_slist_free (priv->exdate_list);
-       priv->exdate_list = NULL;
-
-       /* Add in new exception dates */
-
-       for (l = exdate_list; l; l = l->next) {
-               ECalComponentDateTime *cdt;
-               struct datetime *dt;
-
-               g_return_if_fail (l->data != NULL);
-               cdt = l->data;
-
-               g_return_if_fail (cdt->value != NULL);
-
-               dt = g_new (struct datetime, 1);
-               dt->prop = icalproperty_new_exdate (*cdt->value);
-
-               if (cdt->tzid) {
-                       dt->tzid_param = icalparameter_new_tzid ((gchar *) cdt->tzid);
-                       icalproperty_add_parameter (dt->prop, dt->tzid_param);
-               } else
-                       dt->tzid_param = NULL;
+       case I_CAL_VTIMEZONE_COMPONENT:
+               return E_CAL_COMPONENT_TIMEZONE;
 
-               icalcomponent_add_property (priv->icalcomp, dt->prop);
-               priv->exdate_list = g_slist_prepend (priv->exdate_list, dt);
+       default:
+               /* We should have been loaded with a supported type! */
+               g_warn_if_reached ();
+               return E_CAL_COMPONENT_NO_TYPE;
        }
-
-       priv->exdate_list = g_slist_reverse (priv->exdate_list);
-
-       priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_has_exdates:
- * @comp: A calendar component object.
+ * e_cal_component_get_as_string:
+ * @comp: A calendar component.
  *
- * Queries whether a calendar component object has any exception dates defined
- * for it.
+ * Gets the iCalendar string representation of a calendar component.  You should
+ * call e_cal_component_commit_sequence() before this function to ensure that the
+ * component's sequence number is consistent with the state of the object.
  *
- * Returns: TRUE if the component has exception dates, FALSE otherwise.
+ * Returns: String representation of the calendar component according to
+ * RFC 2445.
  **/
-gboolean
-e_cal_component_has_exdates (ECalComponent *comp)
+gchar *
+e_cal_component_get_as_string (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+       /* Ensure that the user has committed the new SEQUENCE */
+       g_return_val_if_fail (comp->priv->need_sequence_inc == FALSE, NULL);
 
-       return (priv->exdate_list != NULL);
+       return i_cal_component_as_ical_string_r (comp->priv->icalcomp);
 }
 
-/* Gets a list of recurrence rules */
-static void
-get_recur_list (GSList *recur_list,
-                struct icalrecurrencetype (* get_prop_func) (const icalproperty *prop),
-                GSList **list)
+/* Ensures that an alarm subcomponent has the mandatory properties it needs. */
+static gpointer
+ensure_alarm_properties_cb (ICalComponent *icalcomp,
+                           ICalComponent *subcomp,
+                           gpointer user_data)
 {
-       GSList *l;
-
-       *list = NULL;
-
-       for (l = recur_list; l; l = l->next) {
-               icalproperty *prop;
-               struct icalrecurrencetype *r;
-
-               prop = l->data;
-
-               r = g_new (struct icalrecurrencetype, 1);
-               *r = (* get_prop_func) (prop);
+       ECalComponent *comp = user_data;
+       ICalProperty *prop;
+       ICalPropertyAction action;
+       const gchar *str;
 
-               *list = g_slist_prepend (*list, r);
-       }
+       prop = i_cal_component_get_first_property (subcomp, I_CAL_ACTION_PROPERTY);
+       if (!prop)
+               return;
 
-       *list = g_slist_reverse (*list);
-}
+       action = i_cal_property_get_action (prop);
 
-/* Sets a list of recurrence rules */
-static void
-set_recur_list (ECalComponent *comp,
-                icalproperty *(* new_prop_func) (struct icalrecurrencetype recur),
-                GSList **recur_list,
-                GSList *rl)
-{
-       ECalComponentPrivate *priv;
-       GSList *l;
+       g_object_unref (prop);
 
-       priv = comp->priv;
+       switch (action) {
+       case I_CAL_ACTION_DISPLAY:
+               const gchar *summary;
 
-       /* Remove old recurrences */
+               summary = i_cal_component_get_summary (icalcomp);
 
-       for (l = *recur_list; l; l = l->next) {
-               icalproperty *prop;
+               /* Ensure we have a DESCRIPTION property */
+               prop = i_cal_component_get_first_property (subcomp, I_CAL_DESCRIPTION_PROPERTY);
+               if (prop) {
+                       if (summary && *summary) {
+                               ICalProperty *xprop;
+
+                               for (xprop = i_cal_component_get_first_property (subcomp, I_CAL_X_PROPERTY);
+                                    xprop;
+                                    g_object_unref (xprop), xprop = i_cal_component_get_next_property 
(subcomp, I_CAL_X_PROPERTY)) {
+                                       str = i_cal_property_get_x_name (xprop);
+                                       if (!g_strcmp0 (str, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
+                                               i_cal_property_set_description (prop, summary);
+
+                                               i_cal_component_remove_property (subcomp, xprop);
+                                               g_object_unref (xprop);
+                                               break;
+                                       }
+                               }
 
-               prop = l->data;
-               icalcomponent_remove_property (priv->icalcomp, prop);
-               icalproperty_free (prop);
-       }
+                               g_object_unref (prop);
+                               break;
+                       }
 
-       g_slist_free (*recur_list);
-       *recur_list = NULL;
+                       g_object_unref (prop);
+               }
 
-       /* Add in new recurrences */
+               if (!summary || !*summary) {
+                       summary = _("Untitled appointment");
 
-       for (l = rl; l; l = l->next) {
-               icalproperty *prop;
-               struct icalrecurrencetype *recur;
+                       /* add the X-EVOLUTION-NEEDS-DESCRIPTION property */
+                       prop = i_cal_property_new_x ("1");
+                       i_cal_property_set_x_name (prop, "X-EVOLUTION-NEEDS-DESCRIPTION");
+                       i_cal_component_take_property (subcomp, prop);
+               }
 
-               g_return_if_fail (l->data != NULL);
-               recur = l->data;
+               prop = i_cal_property_new_description (summary);
+               i_cal_component_take_property (subcomp, prop);
 
-               prop = (* new_prop_func) (*recur);
-               icalcomponent_add_property (priv->icalcomp, prop);
+               break;
 
-               *recur_list = g_slist_prepend (*recur_list, prop);
+       default:
+               break;
        }
-
-       *recur_list = g_slist_reverse (*recur_list);
-}
-
-/**
- * e_cal_component_get_exrule_list:
- * @comp: A calendar component object.
- * @recur_list: (out) (element-type icalrecurrencetype) (transfer full): List of
- * exception rules as struct #icalrecurrencetype structures.  This should be
- * freed using the e_cal_component_free_recur_list() function.
- *
- * Queries the list of exception rule properties of a calendar component
- * object.
- **/
-void
-e_cal_component_get_exrule_list (ECalComponent *comp,
-                                 GSList **recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       get_recur_list (priv->exrule_list, icalproperty_get_exrule, recur_list);
 }
 
 /**
- * e_cal_component_get_exrule_property_list:
+ * e_cal_component_commit_sequence:
  * @comp: A calendar component object.
- * @recur_list: (out) (transfer none) (element-type icalrecurrencetype):
- *
- * Queries the list of exception rule properties of a calendar component object.
  *
- * Returns: a list of exception rule properties
- **/
-void
-e_cal_component_get_exrule_property_list (ECalComponent *comp,
-                                          GSList **recur_list)
-{
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       *recur_list = priv->exrule_list;
-}
-
-/**
- * e_cal_component_set_exrule_list:
- * @comp: A calendar component object.
- * @recur_list: (element-type icalrecurrencetype): List of struct
- * #icalrecurrencetype structures.
+ * Increments the sequence number property in a calendar component object if it
+ * needs it.  This needs to be done when any of a number of properties listed in
+ * RFC 2445 change values, such as the start and end dates of a component.
  *
- * Sets the list of exception rules in a calendar component object.
+ * This function must be called before calling e_cal_component_get_as_string() to
+ * ensure that the component is fully consistent.
  **/
 void
-e_cal_component_set_exrule_list (ECalComponent *comp,
-                                 GSList *recur_list)
+e_cal_component_commit_sequence (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_recur_list (comp, icalproperty_new_exrule, &priv->exrule_list, recur_list);
-
-       priv->need_sequence_inc = TRUE;
-}
-
-/**
- * e_cal_component_has_exrules:
- * @comp: A calendar component object.
- *
- * Queries whether a calendar component object has any exception rules defined
- * for it.
- *
- * Returns: TRUE if the component has exception rules, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_exrules (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, ensure_alarm_properties_cb, comp);
 
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       if (!comp->priv->need_sequence_inc)
+               return;
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SEQUENCE_PROPERTY);
 
-       return (priv->exrule_list != NULL);
-}
+       if (prop) {
+               gint seq;
 
-/**
- * e_cal_component_has_exceptions:
- * @comp: A calendar component object
- *
- * Queries whether a calendar component object has any exception dates
- * or exception rules.
- *
- * Returns: TRUE if the component has exceptions, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_exceptions (ECalComponent *comp)
-{
-       return e_cal_component_has_exdates (comp) || e_cal_component_has_exrules (comp);
+               seq = i_cal_property_get_sequence (prop);
+               i_cal_property_set_sequence (prop, seq + 1);
+               g_object_unref (prop);
+       } else {
+               /* The component had no SEQUENCE property, so assume that the
+                * default would have been zero.  Since it needed incrementing
+                * anyways, we use a value of 1 here.
+                */
+               prop = i_cal_property_new_sequence (1);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
+
+       comp->priv->need_sequence_inc = FALSE;
 }
 
 /**
- * e_cal_component_get_geo:
+ * e_cal_component_abort_sequence:
  * @comp: A calendar component object.
- * @geo: (out): Return value for the geographic position property.  This should be
- * freed using the e_cal_component_free_geo() function.
  *
- * Gets the geographic position property of a calendar component object.
- **/
+ * Aborts the sequence change needed in the given calendar component,
+ * which means it will not require a sequence commit (via
+ * e_cal_component_commit_sequence()) even if the changes done require a
+ * sequence increment.
+ */
 void
-e_cal_component_get_geo (ECalComponent *comp,
-                         struct icalgeotype **geo)
+e_cal_component_abort_sequence (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (geo != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
 
-       if (priv->geo) {
-               *geo = g_new (struct icalgeotype, 1);
-               **geo = icalproperty_get_geo (priv->geo);
-       } else
-               *geo = NULL;
+       comp->priv->need_sequence_inc = FALSE;
 }
 
 /**
- * e_cal_component_set_geo:
+ * e_cal_component_get_id:
  * @comp: A calendar component object.
- * @geo: Value for the geographic position property.
  *
- * Sets the geographic position property on a calendar component object.
- **/
-void
-e_cal_component_set_geo (ECalComponent *comp,
-                         struct icalgeotype *geo)
+ * Get the ID of the component as an #ECalComponentId. The return value should
+ * be freed with e_cal_component_id_free(), when no longer needed.
+ *
+ * Returns: (transfer full): the id of the component
+ */
+ECalComponentId *
+e_cal_component_get_id (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ECalComponentId *id;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       if (!geo) {
-               if (priv->geo) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->geo);
-                       icalproperty_free (priv->geo);
-                       priv->geo = NULL;
-               }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               return;
-       }
+       id = g_new0 (ECalComponentId, 1);
+       id->uid = g_strdup (i_cal_component_get_uid (comp->priv->icalcomp));
+       id->rid = e_cal_component_get_recurid_as_string (comp);
 
-       if (priv->geo)
-               icalproperty_set_geo (priv->geo, *geo);
-       else {
-               priv->geo = icalproperty_new_geo (*geo);
-               icalcomponent_add_property (priv->icalcomp, priv->geo);
-       }
+       return id;
 }
 
 /**
- * e_cal_component_get_last_modified:
+ * e_cal_component_get_uid:
  * @comp: A calendar component object.
- * @t: Return value for the last modified time value.
  *
- * Queries the time at which a calendar component object was last modified in
- * the calendar store.
+ * Queries the unique identifier of a calendar component object.
+ *
+ * Returns: (transfer none): the UID string
  **/
-void
-e_cal_component_get_last_modified (ECalComponent *comp,
-                                   struct icaltimetype **t)
+const gchar *
+e_cal_component_get_uid (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (t != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_icaltimetype (priv->last_modified, icalproperty_get_lastmodified, t);
+       return i_cal_component_get_uid (comp->priv->icalcomp);
 }
 
 /**
- * e_cal_component_set_last_modified:
+ * e_cal_component_set_uid:
  * @comp: A calendar component object.
- * @t: Value for the last time modified.
+ * @uid: Unique identifier.
  *
- * Sets the time at which a calendar component object was last stored in the
- * calendar store.  This should not be called by plain calendar user agents.
+ * Sets the unique identifier string of a calendar component object.
  **/
 void
-e_cal_component_set_last_modified (ECalComponent *comp,
-                                   struct icaltimetype *t)
+e_cal_component_set_uid (ECalComponent *comp,
+                         const gchar *uid)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (uid != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_icaltimetype (
-               comp, &priv->last_modified,
-               icalproperty_new_lastmodified,
-               icalproperty_set_lastmodified,
-               t);
+       i_cal_component_set_uid (comp->priv->icalcomp, (gchar *) uid);
 }
 
-/**
- * e_cal_component_get_organizer:
- * @comp:  A calendar component object
- * @organizer: (out): A value for the organizer
- *
- * Queries the organizer property of a calendar component object
- **/
-void
-e_cal_component_get_organizer (ECalComponent *comp,
-                               ECalComponentOrganizer *organizer)
+static gboolean
+get_attachments_cb (ICalComponent *icalcomp,
+                   ICalProperty *prop,
+                   gpointer user_data)
 {
-       ECalComponentPrivate *priv;
+       GSList **pattaches = user_data;
+       ICalAttach *attach;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (organizer != NULL);
+       g_return_val_if_fail (pattaches != NULL, FALSE);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       attach = i_cal_property_get_attach (prop);
 
-       if (priv->organizer.prop)
-               organizer->value = icalproperty_get_organizer (priv->organizer.prop);
-       else
-               organizer->value = NULL;
+       if (attach)
+               *attaches = g_slist_prepend (*attaches, attach);
 
-       if (priv->organizer.sentby_param)
-               organizer->sentby = icalparameter_get_sentby (priv->organizer.sentby_param);
-       else
-               organizer->sentby = NULL;
+       return TRUE;
+}
 
-       if (priv->organizer.cn_param)
-               organizer->cn = icalparameter_get_sentby (priv->organizer.cn_param);
-       else
-               organizer->cn = NULL;
+/**
+ * e_cal_component_get_attachments:
+ * @comp: A calendar component object
+ *
+ * Queries the attachment properties of the calendar component object.
+ * Free the returned #GSList with g_slist_free_full (slist, g_object_unref);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalAttach): a #GSList of
+ *    attachments, as #ICalAttach objects
+ **/
+GSList *
+e_cal_component_get_attachments (ECalComponent *comp)
+{
+       GSList *attaches = NULL;
 
-       if (priv->organizer.language_param)
-               organizer->language = icalparameter_get_sentby (priv->organizer.language_param);
-       else
-               organizer->language = NULL;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
+       foreach_property (comp->priv->icalcomp, I_CAL_ATTACH_PROPERTY, get_attachments_cb, &attaches);
+
+       return g_slist_reverse (attaches);
 }
 
 /**
- * e_cal_component_set_organizer:
- * @comp:  A calendar component object.
- * @organizer: Value for the organizer property
+ * e_cal_component_get_attachments:
+ * @comp: A calendar component object
+ * @attachments: (nullable) (element-type ICalAttach): a #GSList of an #ICalAttach,
+ *    or %NULL to remove any existing
  *
- * Sets the organizer of a calendar component object
+ * Sets the attachments of the calendar component object.
  **/
 void
-e_cal_component_set_organizer (ECalComponent *comp,
-                               ECalComponentOrganizer *organizer)
+e_cal_component_set_attachments (ECalComponent *comp,
+                                const GSList *attachments)
 {
-       ECalComponentPrivate *priv;
+       GSList *link;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_ATTACH_PROPERTY);
 
-       if (!organizer) {
-               if (priv->organizer.prop) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->organizer.prop);
-                       icalproperty_free (priv->organizer.prop);
-
-                       priv->organizer.prop = NULL;
-                       priv->organizer.sentby_param = NULL;
-                       priv->organizer.cn_param = NULL;
-                       priv->organizer.language_param = NULL;
-               }
+       for (link = (GSList *) attachments; link; link = g_slist_next (link)) {
+               ICalAttach *attach = link->data;
+               ICalProperty *prop;
 
-               return;
-       }
+               if (!attach)
+                       continue;
 
-       g_return_if_fail (organizer->value != NULL);
+               prop = i_cal_property_new_attach (attach);
 
-       if (priv->organizer.prop)
-               icalproperty_set_organizer (priv->organizer.prop, (gchar *) organizer->value);
-       else {
-               priv->organizer.prop = icalproperty_new_organizer ((gchar *) organizer->value);
-               icalcomponent_add_property (priv->icalcomp, priv->organizer.prop);
+               if (prop)
+                       i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
+}
 
-       if (organizer->sentby) {
-               g_return_if_fail (priv->organizer.prop != NULL);
-
-               if (priv->organizer.sentby_param)
-                       icalparameter_set_sentby (
-                               priv->organizer.sentby_param,
-                               (gchar *) organizer->sentby);
-               else {
-                       priv->organizer.sentby_param = icalparameter_new_sentby (
-                               (gchar *) organizer->sentby);
-                       icalproperty_add_parameter (
-                               priv->organizer.prop,
-                               priv->organizer.sentby_param);
-               }
-       } else if (priv->organizer.sentby_param) {
-               icalproperty_remove_parameter_by_kind (priv->organizer.prop, ICAL_SENTBY_PARAMETER);
-               priv->organizer.sentby_param = NULL;
-       }
+/**
+ * e_cal_component_has_attachments:
+ * @comp: A calendar component object.
+ *
+ * Queries the component to see if it has attachments.
+ *
+ * Returns: TRUE if there are attachments, FALSE otherwise.
+ */
+gboolean
+e_cal_component_has_attachments (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       if (organizer->cn) {
-               g_return_if_fail (priv->organizer.prop != NULL);
-
-               if (priv->organizer.cn_param)
-                       icalparameter_set_cn (
-                               priv->organizer.cn_param,
-                               (gchar *) organizer->cn);
-               else {
-                       priv->organizer.cn_param = icalparameter_new_cn (
-                               (gchar *) organizer->cn);
-                       icalproperty_add_parameter (
-                               priv->organizer.prop,
-                               priv->organizer.cn_param);
-               }
-       } else if (priv->organizer.cn_param) {
-               icalproperty_remove_parameter_by_kind (priv->organizer.prop, ICAL_CN_PARAMETER);
-               priv->organizer.cn_param = NULL;
-       }
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_ATTACH_PROPERTY);
+}
+
+/* Creates a comma-delimited string of categories */
+static gchar *
+stringify_categories (const GSList *categ_list)
+{
+       GString *str;
+       GSList *link;
+
+       str = g_string_new (NULL);
 
-       if (organizer->language) {
-               g_return_if_fail (priv->organizer.prop != NULL);
-
-               if (priv->organizer.language_param)
-                       icalparameter_set_language (
-                               priv->organizer.language_param,
-                               (gchar *) organizer->language);
-               else {
-                       priv->organizer.language_param = icalparameter_new_language (
-                               (gchar *) organizer->language);
-                       icalproperty_add_parameter (
-                               priv->organizer.prop,
-                               priv->organizer.language_param);
+       for (link = (GSList *) categ_list; link; link = g_slist_next (link)) {
+               const gchar *category = link->data;
+
+               if (category && *category) {
+                       if (str->len)
+                               g_string_append_c (str, ',');
+                       g_string_append (str, category);
                }
-       } else if (priv->organizer.language_param) {
-               icalproperty_remove_parameter_by_kind (priv->organizer.prop, ICAL_LANGUAGE_PARAMETER);
-               priv->organizer.language_param = NULL;
        }
 
+       return g_string_free (str, !str->len);
 }
 
 /**
- * e_cal_component_has_organizer:
+ * e_cal_component_get_categories:
  * @comp: A calendar component object.
  *
- * Check whether a calendar component object has an organizer or not.
+ * Queries the categories of the given calendar component. The categories
+ * are returned in the @categories argument, which, on success, will contain
+ * a comma-separated list of all categories set in the component.
+ * Free the returned string with g_free(), when no longer needed.
  *
- * Returns: TRUE if there is an organizer, FALSE otherwise.
+ * Returns: (transfer full) (nullable): the categories as string, or %NULL
+ *    if none are set
  **/
-gboolean
-e_cal_component_has_organizer (ECalComponent *comp)
+gchar *
+e_cal_component_get_categories (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       GSList *categories;
+       gchar *str;
 
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
+       categories = e_cal_component_get_categories_list (comp);
+       if (!categories)
+               return NULL;
+
+       str = stringify_categories (categories);
 
-       return priv->organizer.prop != NULL;
+       g_slist_free_full (categories, g_free);
+
+       return str;
 }
 
 /**
- * e_cal_component_get_percent:
+ * e_cal_component_set_categories:
  * @comp: A calendar component object.
- * @percent: (out): Return value for the percent-complete property.  This should be
- * freed using the e_cal_component_free_percent() function.
+ * @categories: Comma-separated list of categories.
  *
- * Queries the percent-complete property of a calendar component object.
+ * Sets the list of categories for a calendar component.
  **/
 void
-e_cal_component_get_percent (ECalComponent *comp,
-                             gint **percent)
+e_cal_component_set_categories (ECalComponent *comp,
+                                const gchar *categories)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (percent != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_CATEGORIES_PROPERTY);
+
+       if (!categories || !*categories)
+               return;
 
-       if (priv->percent) {
-               *percent = g_new (int, 1);
-               **percent = icalproperty_get_percentcomplete (priv->percent);
-       } else
-               *percent = NULL;
+       prop = i_cal_property_new_categories (categories);
+       i_cal_component_take_property (comp->priv->icalcomp, prop);
 }
 
 /**
- * e_cal_component_set_percent_as_int:
- * @comp: an #ECalComponent
- * @percent: a percent to set, or -1 to remove the property
+ * e_cal_component_get_categories_list:
+ * @comp: A calendar component object.
  *
- * Sets percent complete as integer. The @percent can be between 0 and 100, inclusive.
- * A special value -1 can be used to remove the percent complete property.
+ * Queries the list of categories of a calendar component object. Each element
+ * in the returned categ_list is a string with the corresponding category.
+ * Free the returned #GSList with g_slist_free_full (categories, g_free); , when
+ * no longer needed.
  *
- * Since: 2.28
+ * Returns: (transfer full) (element-type utf8) (nullable): the #GSList of strings, where each
+ *    string is a category, or %NULL, when no category is set.
  **/
-void
-e_cal_component_set_percent_as_int (ECalComponent *comp,
-                                    gint percent)
+GSList *
+e_cal_component_get_categories_list (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       const gchar *categories;
+       const gchar *p;
+       const gchar *cat_start;
+       GSList *categ_list = NULL;
+       gchar *str;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       for (prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_CATEGORIES_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (comp->priv->icalcomp, 
I_CAL_CATEGORIES_PROPERTY)) {
+               categories = i_cal_property_get_categories (prop);
 
-       if (percent == -1) {
-               if (priv->percent) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->percent);
-                       icalproperty_free (priv->percent);
-                       priv->percent = NULL;
-               }
+               if (!categories)
+                       continue;
 
-               return;
-       }
+               cat_start = categories;
+
+               for (p = categories; *p; p++) {
+                       if (*p == ',') {
+                               str = g_strndup (cat_start, p - cat_start);
+                               categ_list = g_slist_prepend (categ_list, str);
 
-       g_return_if_fail (percent >= 0 && percent <= 100);
+                               cat_start = p + 1;
+                       }
+               }
 
-       if (priv->percent)
-               icalproperty_set_percentcomplete (priv->percent, percent);
-       else {
-               priv->percent = icalproperty_new_percentcomplete (percent);
-               icalcomponent_add_property (priv->icalcomp, priv->percent);
+               str = g_strndup (cat_start, p - cat_start);
+               categ_list = g_slist_prepend (categ_list, str);
        }
 
+       return g_slist_reverse (categ_list);
 }
 
 /**
- * e_cal_component_get_percent_as_int:
- * @comp: an #ECalComponent
- *
- * Get percent complete as an integer value
- *
- * Returns: percent complete as an integer value, -1 when the @comp doesn't have the property
+ * e_cal_component_set_categories_list:
+ * @comp: A calendar component object.
+ * @categ_list: (element-type utf8): List of strings, one for each category.
  *
- * Since: 2.28
+ * Sets the list of categories of a calendar component object.
  **/
-gint
-e_cal_component_get_percent_as_int (ECalComponent *comp)
+void
+e_cal_component_set_categories_list (ECalComponent *comp,
+                                     const GSList *categ_list)
 {
-       ECalComponentPrivate *priv;
-       gint percent;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, -1);
+       if (!categ_list) {
+               e_cal_component_set_categories (comp, NULL);
+       } else {
+               gchar *categories_str;
 
-       if (priv->percent) {
-               percent = icalproperty_get_percentcomplete (priv->percent);
-       } else
-               percent = -1;
+               /* Create a single string of categories */
+               categories_str = stringify_categories (categ_list);
 
-       return percent;
+               /* Set the categories */
+               e_cal_component_set_categories (comp, categories_str);
+               g_free (categories_str);
+       }
 }
 
 /**
- * e_cal_component_set_percent:
+ * e_cal_component_get_classification:
  * @comp: A calendar component object.
- * @percent: Value for the percent-complete property.
  *
- * Sets the percent-complete property of a calendar component object.
+ * Queries the classification of a calendar component object.  If the
+ * classification property is not set on this component, this function returns
+ * #E_CAL_COMPONENT_CLASS_NONE.
+ *
+ * Retuurns: a classification of the @comp, as an #ECalComponentClassification
  **/
-void
-e_cal_component_set_percent (ECalComponent *comp,
-                             gint *percent)
+ECalComponentClassification
+e_cal_component_get_classification (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       ECalComponentClassification classif;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_CLASS_UNKNOWN);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, E_CAL_COMPONENT_CLASS_UNKNOWN);
 
-       if (!percent) {
-               if (priv->percent) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->percent);
-                       icalproperty_free (priv->percent);
-                       priv->percent = NULL;
-               }
+       if (!comp->priv->classification)
+               return E_CAL_COMPONENT_CLASS_NONE;
 
-               return;
+       switch (i_cal_property_get_class (comp->priv->classification)) {
+       case I_CAL_CLASS_PUBLIC:
+               classif = E_CAL_COMPONENT_CLASS_PUBLIC;
+               break;
+       case I_CAL_CLASS_PRIVATE:
+               classif = E_CAL_COMPONENT_CLASS_PRIVATE;
+               break;
+       case I_CAL_CLASS_CONFIDENTIAL:
+               classif = E_CAL_COMPONENT_CLASS_CONFIDENTIAL;
+               break;
+       default:
+               classif = E_CAL_COMPONENT_CLASS_UNKNOWN;
+               break;
        }
 
-       g_return_if_fail (*percent >= 0 && *percent <= 100);
-
-       if (priv->percent)
-               icalproperty_set_percentcomplete (priv->percent, *percent);
-       else {
-               priv->percent = icalproperty_new_percentcomplete (*percent);
-               icalcomponent_add_property (priv->icalcomp, priv->percent);
-       }
+       return classif;
 }
 
 /**
- * e_cal_component_get_priority:
+ * e_cal_component_set_classification:
  * @comp: A calendar component object.
- * @priority: (out): Return value for the priority property.  This should be freed using
- * the e_cal_component_free_priority() function.
+ * @classif: Classification to use.
  *
- * Queries the priority property of a calendar component object.
+ * Sets the classification property of a calendar component object.  To unset
+ * the property, specify E_CAL_COMPONENT_CLASS_NONE for @classif.
  **/
 void
-e_cal_component_get_priority (ECalComponent *comp,
-                              gint **priority)
+e_cal_component_set_classification (ECalComponent *comp,
+                                    ECalComponentClassification classif)
 {
-       ECalComponentPrivate *priv;
+       ICalPropertyClass prop_class;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (priority != NULL);
+       g_return_if_fail (classif != E_CAL_COMPONENT_CLASS_UNKNOWN);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       if (classif == E_CAL_COMPONENT_CLASS_NONE) {
+               if (comp->priv->classification) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, comp->priv->classification);
+                       g_clear_object (&comp->priv->classification);
+               }
+
+               return;
+       }
+
+       switch (classif) {
+       case E_CAL_COMPONENT_CLASS_PUBLIC:
+               prop_class = I_CAL_CLASS_PUBLIC;
+               break;
+
+       case E_CAL_COMPONENT_CLASS_PRIVATE:
+               prop_class = I_CAL_CLASS_PRIVATE;
+               break;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       case E_CAL_COMPONENT_CLASS_CONFIDENTIAL:
+               prop_class = I_CAL_CLASS_CONFIDENTIAL;
+               break;
+
+       default:
+               g_warn_if_reached ();
+               prop_class = I_CAL_CLASS_NONE;
+               break;
+       }
 
-       if (priv->priority) {
-               *priority = g_new (int, 1);
-               **priority = icalproperty_get_priority (priv->priority);
-       } else
-               *priority = NULL;
+       if (comp->priv->classification) {
+               i_cal_property_set_class (comp->priv->classification, prop_class);
+       } else {
+               comp->priv->classification = i_cal_property_new_class (prop_class);
+               i_cal_component_add_property (comp->priv->icalcomp, comp->priv->classification);
+       }
 }
 
-/**
- * e_cal_component_set_priority:
- * @comp: A calendar component object.
- * @priority: Value for the priority property.
- *
- * Sets the priority property of a calendar component object.
- **/
-void
-e_cal_component_set_priority (ECalComponent *comp,
-                              gint *priority)
+/* Gets a text list value */
+static GSList *
+get_text_list (ICalComponent *icalcomp,
+              ICalPropertyKind prop_kind,
+               const gchar *(* get_prop_func) (ICalProperty *prop))
 {
-       ECalComponentPrivate *priv;
+       GSList *link, *props, *tl = NULL;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       if (!icalcomp)
+               return NULL;
 
-       if (!priority) {
-               if (priv->priority) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->priority);
-                       icalproperty_free (priv->priority);
-                       priv->priority = NULL;
-               }
+       props = gather_all_properties (icalcomp, prop_kind, FALSE);
+       for (link = props; link; link = g_slist_next (link)) {
+               ICalProperty *prop = link->data;
+               ECalComponentText *text;
 
-               return;
-       }
+               if (!prop)
+                       continue;
 
-       g_return_if_fail (*priority >= 0 && *priority <= 9);
+               text = get_text_from_prop (prop, get_prop_func);
+               if (!text)
+                       continue;
 
-       if (priv->priority)
-               icalproperty_set_priority (priv->priority, *priority);
-       else {
-               priv->priority = icalproperty_new_priority (*priority);
-               icalcomponent_add_property (priv->icalcomp, priv->priority);
+               tl = g_slist_prepend (tl, text);
        }
+
+       return g_slist_reverse (tl);
 }
 
-/**
- * e_cal_component_get_recurid:
- * @comp: A calendar component object.
- * @recur_id: (out): Return value for the recurrence id property
- *
- * Queries the recurrence id property of a calendar component object.
- **/
-void
-e_cal_component_get_recurid (ECalComponent *comp,
-                             ECalComponentRange *recur_id)
+/* Sets a text list value */
+static void
+set_text_list (ICalComponent *icalcomp,
+              ICalPropertyKind prop_kind,
+               ICalProperty * (* new_prop_func) (const gchar *value),
+               const GSList *tl)
 {
-       ECalComponentPrivate *priv;
+       GSList *link;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_id != NULL);
+       /* Remove old texts */
+       remove_all_properties_of_kind (icalcomp, prop_kind);
+
+       /* Add in new texts */
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       for (link = (GSList *) tl; link; link = g_slist_next (link)) {
+               ECalComponentText *text;
+               ICalProperty *prop;
 
-       recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
+               text = link->data;
+               if (!text || !e_cal_component_text_get_value (text))
+                       continue;
+
+               prop = new_prop_func ((gchar *) e_cal_component_text_get_value (text));
 
-       get_datetime (
-               &priv->recur_id.recur_time,
-               icalproperty_get_recurrenceid,
-               &recur_id->datetime);
+               set_text_altrep_on_prop (prop, text);
+
+               i_cal_component_take_property (icalcomp, prop);
+       }
 }
 
 /**
- * e_cal_component_get_recurid_as_string:
+ * e_cal_component_get_comment_list:
  * @comp: A calendar component object.
  *
- * Gets the recurrence ID property as a string.
+ * Queries the comments of a calendar component object.  The comment property can
+ * appear several times inside a calendar component, and so a list of
+ * #ECalComponentText is returned. Free the returned #GSList with
+ * g_slist_free_full (slist, e_cal_component_text_free);, when no longer needed.
  *
- * Returns: the recurrence ID as a string.
- */
-gchar *
-e_cal_component_get_recurid_as_string (ECalComponent *comp)
+ * Returns: (transfer full) (element-type ECalComponentText) (nullable): the comment properties
+ *    and their parameters, as a list of #ECalComponentText structures; or %NULL, when
+ *    the component doesn't contain any.
+ **/
+GSList *
+e_cal_component_get_comment_list (ECalComponent *comp)
 {
-       ECalComponentRange range;
-       struct icaltimetype tt;
-
-       if (!e_cal_component_is_instance (comp))
-               return NULL;
-
-       e_cal_component_get_recurid (comp, &range);
-       if (!range.datetime.value) {
-               e_cal_component_free_range (&range);
-               return g_strdup ("0");
-       }
-
-       tt = *range.datetime.value;
-       e_cal_component_free_range (&range);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       return icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt) ?
-               icaltime_as_ical_string_r (tt) : g_strdup ("0");
+       return get_text_list (comp->priv->icalcomp, I_CAL_COMMENT_PROPERTY, i_cal_property_get_comment);
 }
 
 /**
- * e_cal_component_set_recurid:
+ * e_cal_component_set_comment_list:
  * @comp: A calendar component object.
- * @recur_id: Value for the recurrence id property.
+ * @text_list: (element-type ECalComponentText): List of #ECalComponentText structures.
  *
- * Sets the recurrence id property of a calendar component object.
+ * Sets the comments of a calendar component object.  The comment property can
+ * appear several times inside a calendar component, and so a list of
+ * #ECalComponentText structures is used.
  **/
 void
-e_cal_component_set_recurid (ECalComponent *comp,
-                             ECalComponentRange *recur_id)
+e_cal_component_set_comment_list (ECalComponent *comp,
+                                  const GSList *text_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_datetime (
-               comp, &priv->recur_id.recur_time,
-               icalproperty_new_recurrenceid,
-               icalproperty_set_recurrenceid,
-               recur_id ? &recur_id->datetime : NULL);
+       set_text_list (comp->priv->icalcomp, I_CAL_COMMENT_PROPERTY, i_cal_property_new_comment, text_list);
 }
 
 /**
- * e_cal_component_get_rdate_list:
+ * e_cal_component_get_contact_list:
  * @comp: A calendar component object.
- * @period_list: (out) (transfer full) (element-type ECalComponentPeriod):
- * Return value for the list of recurrence dates, as a list of
- * #ECalComponentPeriod structures.  This should be freed using
- * e_cal_component_free_period_list()
+ * @text_list: (out) (transfer full) (element-type ECalComponentText): Return
+ * value for the contact properties and their parameters, as a list of
+ * #ECalComponentText structures.
  *
- * Queries the list of recurrence date properties in a calendar component
- * object.
+ * Queries the contact of a calendar component object.  The contact property can
+ * appear several times inside a calendar component, and so a list of
+ * #ECalComponentText is returned. Free the returned #GSList with
+ * g_slist_free_full (slist, e_cal_component_text_free);, when no longer needed.
  **/
 void
-e_cal_component_get_rdate_list (ECalComponent *comp,
-                                GSList **period_list)
+e_cal_component_get_contact_list (ECalComponent *comp,
+                                  GSList **text_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (period_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       get_period_list (priv->rdate_list, icalproperty_get_rdate, period_list);
+       return get_text_list (comp->priv->icalcomp, I_CAL_CONTACT_PROPERTY, i_cal_property_get_contact);
 }
 
 /**
- * e_cal_component_set_rdate_list:
+ * e_cal_component_set_contact_list:
  * @comp: A calendar component object.
- * @period_list: (element-type ECalComponentPeriod): List of
- * #ECalComponentPeriod structures
+ * @text_list: (element-type ECalComponentText): List of #ECalComponentText structures.
  *
- * Sets the list of recurrence dates in a calendar component object.
+ * Sets the contact of a calendar component object.  The contact property can
+ * appear several times inside a calendar component, and so a list of
+ * #ECalComponentText structures is used.
  **/
 void
-e_cal_component_set_rdate_list (ECalComponent *comp,
-                                GSList *period_list)
+e_cal_component_set_contact_list (ECalComponent *comp,
+                                  const GSList *text_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
-
-       set_period_list (comp, icalproperty_new_rdate, &priv->rdate_list, period_list);
-
-       priv->need_sequence_inc = TRUE;
+       set_text_list (comp->priv->icalcomp, I_CAL_CONTACT_PROPERTY, i_cal_property_new_contact, text_list);
 }
 
-/**
- * e_cal_component_has_rdates:
- * @comp: A calendar component object.
- *
- * Queries whether a calendar component object has any recurrence dates defined
- * for it.
- *
- * Returns: TRUE if the component has recurrence dates, FALSE otherwise.
- **/
-gboolean
-e_cal_component_has_rdates (ECalComponent *comp)
+/* Gets a struct icaltimetype value */
+static ICalTimetype *
+get_icaltimetype (ICalComponent *icalcomp,
+                 ICalPropertyKind prop_kind,
+                  ICalTimetype * (* get_prop_func) (ICalProperty *prop))
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       ICalTimetype *tt;
 
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+       if (!prop)
+               return NULL;
+
+       tt = get_prop_func (prop);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+       g_object_unref (prop);
 
-       return (priv->rdate_list != NULL);
+       return tt;
 }
 
-/**
- * e_cal_component_get_rrule_list:
- * @comp: A calendar component object.
- * @recur_list: (out) (transfer full) (element-type icalrecurrencetype): List of
- * recurrence rules as struct #icalrecurrencetype structures.  This should be
- * freed using e_cal_component_free_recur_list().
- *
- * Queries the list of recurrence rule properties of a calendar component
- * object.
- **/
-void
-e_cal_component_get_rrule_list (ECalComponent *comp,
-                                GSList **recur_list)
+/* Sets a struct icaltimetype value */
+static void
+set_icaltimetype (ICalComponent *icalcomp,
+                  ICalPropertyKind prop_kind,
+                  ICalProperty *(* prop_new_func) (ICalTimetype *tt),
+                  void (* prop_set_func) (ICalProperty *prop,
+                                          ICalTimetype *tt),
+                  const ICalTimetype *tt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       if (!tt) {
+               if (prop) {
+                       i_cal_component_remove_property (icalcomp, prop);
+                       g_clear_object (&prop);
+               }
+
+               return;
+       }
 
-       get_recur_list (priv->rrule_list, icalproperty_get_rrule, recur_list);
+       if (prop) {
+               prop_set_func (prop, tt);
+       } else {
+               prop = prop_new_func (tt);
+               i_cal_component_take_property (icalcomp, prop);
+       }
 }
 
 /**
- * e_cal_component_get_rrule_property_list:
+ * e_cal_component_get_completed:
  * @comp: A calendar component object.
- * @recur_list: (out) (transfer none) (element-type icalrecurrencetype): Returns
- * a list of recurrence rule properties.
  *
- * Queries a list of recurrence rule properties of a calendar component object.
+ * Queries the date at which a calendar compoment object was completed.
+ * Free the returned non-NULL pointer with g_object_unref(), when
+ * no longer needed.
+ *
+ * Returns: (transfer full): the completion date, as an #ICalTimetype, or %NULL, when none is set
  **/
-void
-e_cal_component_get_rrule_property_list (ECalComponent *comp,
-                                         GSList **recur_list)
+ICalTimetype *
+e_cal_component_get_completed (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (recur_list != NULL);
-
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       *recur_list = priv->rrule_list;
+       return get_icaltimetype (comp->priv->icalcomp, I_CAL_COMPLETED_PROPERTY, 
i_cal_property_get_completed);
 }
 
 /**
- * e_cal_component_set_rrule_list:
+ * e_cal_component_set_completed:
  * @comp: A calendar component object.
- * @recur_list: (element-type icalrecurrencetype): List of struct
- * #icalrecurrencetype structures.
+ * @tt: (nullable): Value for the completion date.
  *
- * Sets the list of recurrence rules in a calendar component object.
+ * Sets the date at which a calendar component object was completed.
  **/
 void
-e_cal_component_set_rrule_list (ECalComponent *comp,
-                                GSList *recur_list)
+e_cal_component_set_completed (ECalComponent *comp,
+                              const ICalTimetype *tt)
 {
-       ECalComponentPrivate *priv;
+       ICalTimetype *tmp_tt = NULL;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       if (tt && tt->is_date) {
+               tmp_tt = i_cal_timetype_new_clone (tt);
+               tt = tmp_tt;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+               i_cal_timetype_set_is_date (tmp_tt, FALSE);
+               i_cal_timetype_set_hour (tmp_tt, 0);
+               i_cal_timetype_set_minute (tmp_tt, 0);
+               i_cal_timetype_set_second (tmp_tt, 0);
+               i_cal_timetype_set_zone (tmp_tt, i_cal_timezone_get_utc_timezone ());
+       }
 
-       set_recur_list (comp, icalproperty_new_rrule, &priv->rrule_list, recur_list);
+       set_icaltimetype (comp->priv->icalcomp, I_CAL_COMPLETED_PROPERTY,
+               i_cal_property_new_completed,
+               i_cal_property_set_completed,
+               tt);
 
-       priv->need_sequence_inc = TRUE;
+       g_clear_object (&tmp_tt);
 }
 
 /**
- * e_cal_component_has_rrules:
+ * e_cal_component_get_created:
  * @comp: A calendar component object.
  *
- * Queries whether a calendar component object has any recurrence rules defined
- * for it.
+ * Queries the date in which a calendar component object was created in the
+ * calendar store. Free the returned non-NULL pointer with g_object_unref(), when
+ * no longer needed.
  *
- * Returns: TRUE if the component has recurrence rules, FALSE otherwise.
+ * Returns: (transfer full): the creation date, as an #ICalTimetype, or %NULL, when none is set
  **/
-gboolean
-e_cal_component_has_rrules (ECalComponent *comp)
+ICalTimetype *
+e_cal_component_get_created (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       return (priv->rrule_list != NULL);
+       return get_icaltimetype (comp->priv->icalcomp, I_CAL_CREATED_PROPERTY, i_cal_property_get_created);
 }
 
 /**
- * e_cal_component_has_recurrences:
- * @comp: A calendar component object
- *
- * Queries whether a calendar component object has any recurrence dates or
- * recurrence rules.
+ * e_cal_component_set_created:
+ * @comp: A calendar component object.
+ * @tt: (nullable): Value for the creation date.
  *
- * Returns: TRUE if the component has recurrences, FALSE otherwise.
+ * Sets the date in which a calendar component object is created in the calendar
+ * store.  This should only be used inside a calendar store application, i.e.
+ * not by calendar user agents.
  **/
-gboolean
-e_cal_component_has_recurrences (ECalComponent *comp)
-{
-       return e_cal_component_has_rdates (comp) || e_cal_component_has_rrules (comp);
-}
-
-/* Counts the elements in the by_xxx fields of an icalrecurrencetype */
-static gint
-count_by_xxx (gshort *field,
-              gint max_elements)
+void
+e_cal_component_set_created (ECalComponent *comp,
+                            const ICalTimetype *tt)
 {
-       gint i;
-
-       for (i = 0; i < max_elements; i++)
-               if (field[i] == ICAL_RECURRENCE_ARRAY_MAX)
-                       break;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       return i;
+       set_icaltimetype (comp->priv->icalcomp, I_CAL_CREATED_PROPERTY,
+               i_cal_property_new_created,
+               i_cal_property_set_created,
+               tt);
 }
 
 /**
- * e_cal_component_has_simple_recurrence:
+ * e_cal_component_get_description_list:
  * @comp: A calendar component object.
  *
- * Checks whether the given calendar component object has simple recurrence
- * rules or more complicated ones.
+ * Queries the description of a calendar component object.  Journal components
+ * may have more than one description, and as such this function returns a list
+ * of #ECalComponentText structures.  All other types of components can have at
+ * most one description. Free the returned #GSList with
+ * g_slist_free_full (slist, e_cal_component_text_free);, when no longer needed.
  *
- * Returns: TRUE if it has a simple recurrence rule, FALSE otherwise.
- */
-gboolean
-e_cal_component_has_simple_recurrence (ECalComponent *comp)
+ * Returns: (transfer full) (element-type ECalComponentText) (nullable): the description
+ *    properties and their parameters, as a #GSList of #ECalComponentText structures.
+ **/
+GSList *
+e_cal_component_get_description_list (ECalComponent *comp)
 {
-       GSList *rrule_list;
-       struct icalrecurrencetype *r;
-       gint n_by_second, n_by_minute, n_by_hour;
-       gint n_by_day, n_by_month_day, n_by_year_day;
-       gint n_by_week_no, n_by_month, n_by_set_pos;
-       gint len, i;
-       gboolean simple = FALSE;
-
-       if (!e_cal_component_has_recurrences (comp))
-               return TRUE;
-
-       e_cal_component_get_rrule_list (comp, &rrule_list);
-       len = g_slist_length (rrule_list);
-       if (len > 1
-           || e_cal_component_has_rdates (comp)
-           || e_cal_component_has_exrules (comp))
-               goto cleanup;
-
-       /* Down to one rule, so test that one */
-       r = rrule_list->data;
-
-       /* Any funky frequency? */
-       if (r->freq == ICAL_SECONDLY_RECURRENCE
-           || r->freq == ICAL_MINUTELY_RECURRENCE
-           || r->freq == ICAL_HOURLY_RECURRENCE)
-               goto cleanup;
-
-       /* Any funky BY_* */
-#define N_HAS_BY(field) (count_by_xxx (field, G_N_ELEMENTS (field)))
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       n_by_second = N_HAS_BY (r->by_second);
-       n_by_minute = N_HAS_BY (r->by_minute);
-       n_by_hour = N_HAS_BY (r->by_hour);
-       n_by_day = N_HAS_BY (r->by_day);
-       n_by_month_day = N_HAS_BY (r->by_month_day);
-       n_by_year_day = N_HAS_BY (r->by_year_day);
-       n_by_week_no = N_HAS_BY (r->by_week_no);
-       n_by_month = N_HAS_BY (r->by_month);
-       n_by_set_pos = N_HAS_BY (r->by_set_pos);
+       return get_text_list (comp->priv->icalcomp, I_CAL_DESCRIPTION_PROPERTY, 
i_cal_property_get_description);
+}
 
-       if (n_by_second != 0
-           || n_by_minute != 0
-           || n_by_hour != 0)
-               goto cleanup;
+/**
+ * e_cal_component_set_description_list:
+ * @comp: A calendar component object.
+ * @text_list: (element-type ECalComponentText): List of #ECalComponentText structures.
+ *
+ * Sets the description of a calendar component object.  Journal components may
+ * have more than one description, and as such this function takes in a list of
+ * #ECalComponentText structures.  All other types of components can have
+ * at most one description.
+ **/
+void
+e_cal_component_set_description_list (ECalComponent *comp,
+                                      const GSList *text_list)
+{
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       switch (r->freq) {
-       case ICAL_DAILY_RECURRENCE:
-               if (n_by_day != 0
-                   || n_by_month_day != 0
-                   || n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos != 0)
-                       goto cleanup;
+       set_text_list (comp->priv->icalcomp, I_CAL_DESCRIPTION_PROPERTY, i_cal_property_new_description, 
text_list);
+}
 
-               simple = TRUE;
-               break;
+/* Gets a date/time and timezone pair */
+static ECalComponentDateTime *
+get_datetime (ICalComponent *icalcomp,
+             ICalPropertyKind prop_kind,
+              ICalTimetype * (* get_prop_func) (ICalProperty *prop))
+{
+       ICalProperty *prop;
+       ICalParameter *param;
+       ICalTimetype *value = NULL;
+       gchar *tzid;
 
-       case ICAL_WEEKLY_RECURRENCE:
-               if (n_by_month_day != 0
-                   || n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos != 0)
-                       goto cleanup;
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
+       if (prop)
+               value = get_prop_func (prop);
 
-               for (i = 0; i < 8 && r->by_day[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) {
-                       gint pos;
-                       pos = icalrecurrencetype_day_position (r->by_day[i]);
+       if (!value)
+               return NULL;
 
-                       if (pos != 0)
-                               goto cleanup;
-               }
+       param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+       /* If the ICalTimetype has is_utc set, we set "UTC" as the TZID.
+        * This makes the timezone code simpler. */
+       if (param)
+               tzid = i_cal_parameter_get_tzid (param));
+       else if (value && i_cal_timetype_is_utc (value))
+               tzid = g_strdup ("UTC");
+       else
+               tzid = NULL;
 
-               simple = TRUE;
-               break;
+       return e_cal_component_datetime_new_take (value, tzid);
+}
 
-       case ICAL_MONTHLY_RECURRENCE:
-               if (n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos > 1)
-                       goto cleanup;
+/* Sets a date/time and timezone pair */
+static void
+set_datetime (ICalComponent *icalcomp,
+             ICalPropertyKind prop_kind,
+             ICalProperty *(* prop_new_func) (ICalTimetype *tt),
+              void (* prop_set_func) (ICalProperty *prop,
+                                     ICalTimetype *tt),
+             const ECalComponentDateTime *dt)
+{
+       ICalProperty *prop;
+       ICalParameter *param;
+       ICalTimetype *tt;
+       const gchar *tzid;
 
-               if (n_by_month_day == 1) {
-                       gint nth;
+       prop = i_cal_component_get_first_property (icalcomp, prop_kind);
 
-                       if (n_by_set_pos != 0)
-                               goto cleanup;
+       /* If we are setting the property to NULL (i.e. removing it), then
+        * we remove it if it exists. */
+       if (!dt) {
+               if (prop) {
+                       i_cal_component_remove_property (icalcomp, prop);
+                       g_clear_object (&prop);
+               }
 
-                       nth = r->by_month_day[0];
-                       if (nth < 1 && nth != -1)
-                               goto cleanup;
+               return;
+       }
 
-               } else if (n_by_day == 1) {
-                       enum icalrecurrencetype_weekday weekday;
-                       gint pos;
+       tt = e_cal_component_datetime_get_value (dt);
 
-                       /* Outlook 2000 uses BYDAY=TU;BYSETPOS=2, and will not
-                        * accept BYDAY=2TU. So we now use the same as Outlook
-                        * by default. */
+       g_return_if_fail (tt != NULL);
 
-                       weekday = icalrecurrencetype_day_day_of_week (r->by_day[0]);
-                       pos = icalrecurrencetype_day_position (r->by_day[0]);
+       tzid = e_cal_component_datetime_get_tzid (dt);
 
-                       if (pos == 0) {
-                               if (n_by_set_pos != 1)
-                                       goto cleanup;
-                               pos = r->by_set_pos[0];
-                       } else if (pos < 0) {
-                               goto cleanup;
-                       }
+       /* If the TZID is set to "UTC", we set the is_utc flag. */
+       if (!g_strcmp0 (tzid, "UTC"))
+               i_cal_timetype_set_zone (tt, i_cal_timezone_get_utc_timezone ());
+       else if (i_cal_timetype_is_utc (tt))
+               i_cal_timetype_set_zone (tt, NULL);
 
-                       switch (weekday) {
-                       case ICAL_MONDAY_WEEKDAY:
-                       case ICAL_TUESDAY_WEEKDAY:
-                       case ICAL_WEDNESDAY_WEEKDAY:
-                       case ICAL_THURSDAY_WEEKDAY:
-                       case ICAL_FRIDAY_WEEKDAY:
-                       case ICAL_SATURDAY_WEEKDAY:
-                       case ICAL_SUNDAY_WEEKDAY:
-                               break;
+       if (prop) {
+               /* make sure no VALUE property is left if not needed */
+               i_cal_property_remove_parameter_by_kind (prop, I_CAL_VALUE_PARAMETER);
 
-                       default:
-                               goto cleanup;
-                       }
+               prop_set_func (prop, tt);
+       } else {
+               prop = prop_new_func (tt);
+               i_cal_component_add_property (icalcomp, prop);
+       }
+
+       param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+
+       /* If the TZID is set to "UTC", we don't want to save the TZID. */
+       if (g_strcmp0 (tzid, "UTC") != 0) {
+               if (param) {
+                       i_cal_parameter_set_tzid (param, (gchar *) tzid);
                } else {
-                       goto cleanup;
+                       param = i_cal_parameter_new_tzid ((gchar *) tzid);
+                       i_cal_property_add_parameter (prop, param);
                }
+       } else if (param) {
+               i_cal_property_remove_parameter_by_kind (prop, I_CAL_TZID_PARAMETER);
+       }
 
-               simple = TRUE;
-               break;
+       g_clear_object (&param);
+       g_clear_object (&prop);
+}
 
-       case ICAL_YEARLY_RECURRENCE:
-               if (n_by_day != 0
-                   || n_by_month_day != 0
-                   || n_by_year_day != 0
-                   || n_by_week_no != 0
-                   || n_by_month != 0
-                   || n_by_set_pos != 0)
-                       goto cleanup;
+/* This tries to get the DTSTART + DURATION for a VEVENT or VTODO. In a
+ * VEVENT this is used for the DTEND if no DTEND exists, In a VTOTO it is
+ * used for the DUE date if DUE doesn't exist. */
+static ECalComponentDateTime *
+e_cal_component_get_start_plus_duration (ECalComponent *comp)
+{
+       ICalDurationType *duration;
+       ICalTimetype *tt;
+       ECalCoponentDateTime *dt;
+       guint dur_days, dur_hours, dur_minutes, dur_seconds;
 
-               simple = TRUE;
-               break;
+       duration = i_cal_component_get_duration (comp->priv->icalcomp);
+       if (!duration)
+               return NULL;
 
-       default:
-               goto cleanup;
+       /* Get the DTSTART time. */
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart);
+       if (!dt) {
+               g_object_unref (duration);
+               return;
        }
 
- cleanup:
-       e_cal_component_free_recur_list (rrule_list);
+       /* The DURATION shouldn't be negative, but just return DTSTART if it
+        * is, i.e. assume it is 0. */
+       if (i_cal_duration_type_is_neg (duration)) {
+               g_object_unref (duration);
+               return dt;
+       }
 
-       return simple;
+       /* If DTSTART is a DATE value, then we need to check if the DURATION
+        * includes any hours, minutes or seconds. If it does, we need to
+        * make the DTEND/DUE a DATE-TIME value. */
+       dur_days = i_cal_duration_type_get_days (duration) + (7 * i_cal_duration_type_get_weeks (duration));
+       dur_hours = i_cal_duration_type_get_hours (duration);
+       dur_minutes = i_cal_duration_type_get_minutes (duration);
+       dur_seconds = i_cal_duration_type_get_seconds (duration)
+
+       tt = e_cal_component_datetime_get_value (dt);
+       if (i_cal_timetype_get_is_date (tt) && (
+           dur_hours != 0 || dur_minutes != 0 || dur_seconds != 0)) {
+               i_cal_timetype_set_is_date (tt, FALSE);
+       }
+
+       /* Add on the DURATION. */
+       i_cal_time_adjust (tt, dur_days, dur_hours, dur_minutes, dur_seconds);
+
+       g_object_unref (duration);
+
+       return dt;
 }
 
 /**
- * e_cal_component_is_instance:
+ * e_cal_component_get_dtend:
  * @comp: A calendar component object.
  *
- * Checks whether a calendar component object is an instance of a recurring
- * event.
+ * Queries the date/time end of a calendar component object. In case there's no DTEND,
+ * but only DTSTART and DURATION, then the end is computed from the later two.
+ * Free the returned #ECalComponentDateTime with e_cal_component_datetime_free(),
+ * when no longer needed.
  *
- * Returns: TRUE if it is an instance, FALSE if not.
- */
-gboolean
-e_cal_component_is_instance (ECalComponent *comp)
+ * Returns: (transfer full) (nullable): the date/time end, as an #ECalComponentDateTime
+ **/
+ECalComponentDateTime *
+e_cal_component_get_dtend (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ECalComponentDateTime *dt;
 
-       g_return_val_if_fail (comp != NULL, FALSE);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       dt = get_datetime (comp->priv->icalcomp, I_CAl_DTEND_PROPERTY, i_cal_property_get_dtend);
 
-       priv = comp->priv;
+       /* If we don't have a DTEND property, then we try to get DTSTART
+        * + DURATION. */
+       if (!dt)
+               dt = e_cal_component_get_start_plus_duration (comp);
 
-       return !(priv->recur_id.recur_time.prop == NULL);
+       return dt;
 }
 
 /**
- * e_cal_component_get_sequence:
+ * e_cal_component_set_dtend:
  * @comp: A calendar component object.
- * @sequence: (out): Return value for the sequence number.  This should be freed using
- * e_cal_component_free_sequence().
+ * @dt: (nullable): End date/time, or %NULL, to remove the property.
  *
- * Queries the sequence number of a calendar component object.
+ * Sets the date/time end property of a calendar component object.
  **/
 void
-e_cal_component_get_sequence (ECalComponent *comp,
-                              gint **sequence)
+e_cal_component_set_dtend (ECalComponent *comp,
+                           const ECalComponentDateTime *dt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (sequence != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       set_datetime (comp->priv->icalcomp, I_CAL_DTEND_PROPERTY,
+               i_cal_property_new_dtend,
+               i_cal_property_set_dtend,
+               dt);
 
-       if (!priv->sequence) {
-               *sequence = NULL;
-               return;
-       }
+       /* Make sure we remove any existing DURATION property, as it can't be
+        * used with a DTEND. If DTEND is set to NULL, i.e. removed, we also
+        * want to remove any DURATION. */
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_DURATION_PROPERTY);
 
-       *sequence = g_new (int, 1);
-       **sequence = icalproperty_get_sequence (priv->sequence);
+       comp->priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_set_sequence:
+ * e_cal_component_get_dtstamp:
  * @comp: A calendar component object.
- * @sequence: Sequence number value.
  *
- * Sets the sequence number of a calendar component object.  Normally this
- * function should not be called, since the sequence number is incremented
- * automatically at the proper times.
+ * Queries the date/timestamp property of a calendar component object, which is
+ * the last time at which the object was modified by a calendar user agent.
+ *
+ * Free a non-NULL returned object with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): A value for the date/timestamp, or %NULL, when none found.
  **/
-void
-e_cal_component_set_sequence (ECalComponent *comp,
-                              gint *sequence)
+ICalTimetype *
+e_cal_component_get_dtstamp (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       ICalTimetype *tt;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DTSTAMP_PROPERTY);
 
-       priv->need_sequence_inc = FALSE;
+       /* This MUST exist, since we ensured that it did */
+       g_return_val_if_fail (prop != NULL, NULL);
 
-       if (!sequence) {
-               if (priv->sequence) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->sequence);
-                       icalproperty_free (priv->sequence);
-                       priv->sequence = NULL;
-               }
+       tt = i_cal_property_get_dtstamp (prop);
 
-               return;
-       }
+       g_clear_object (&prop);
 
-       if (priv->sequence)
-               icalproperty_set_sequence (priv->sequence, *sequence);
-       else {
-               priv->sequence = icalproperty_new_sequence (*sequence);
-               icalcomponent_add_property (priv->icalcomp, priv->sequence);
-       }
+       return tt;
 }
 
 /**
- * e_cal_component_get_status:
+ * e_cal_component_set_dtstamp:
  * @comp: A calendar component object.
- * @status: (out): Return value for the status value.  It is set to #ICAL_STATUS_NONE
- * if the component has no status property.
+ * @t: Date/timestamp value.
  *
- * Queries the status property of a calendar component object.
+ * Sets the date/timestamp of a calendar component object.  This should be
+ * called whenever a calendar user agent makes a change to a component's
+ * properties.
  **/
 void
-e_cal_component_get_status (ECalComponent *comp,
-                            icalproperty_status *status)
+e_cal_component_set_dtstamp (ECalComponent *comp,
+                            const ICalTimetype *tt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (status != NULL);
+       g_return_if_fail (I_CAL_IS_TIMETYPE (tt));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DTSTAMP_PROPERTY);
 
-       if (!priv->status) {
-               *status = ICAL_STATUS_NONE;
-               return;
-       }
+       /* This MUST exist, since we ensured that it did */
+       g_return_if_fail (prop != NULL);
+
+       i_cal_property_set_dtstamp (prop, tt);
 
-       *status = icalproperty_get_status (priv->status);
+       g_clear_object (&prop);
 }
 
 /**
- * e_cal_component_set_status:
+ * e_cal_component_get_dtstart:
  * @comp: A calendar component object.
- * @status: Status value.  You should use #ICAL_STATUS_NONE if you want to unset
- * this property.
  *
- * Sets the status property of a calendar component object.
+ * Queries the date/time start of a calendar component object.
+ * Free the returned #ECalComponentDateTime with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the date/time start, as an #ECalComponentDateTime
  **/
-void
-e_cal_component_set_status (ECalComponent *comp,
-                            icalproperty_status status)
+ECalComponentDateTime *
+e_cal_component_get_dtstart (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       return get_datetime (comp->priv->icalcomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart);
+}
 
-       g_return_if_fail (comp != NULL);
+/**
+ * e_cal_component_set_dtstart:
+ * @comp: A calendar component object.
+ * @dt: (nullable): Start date/time, or %NULL, to remove the property.
+ *
+ * Sets the date/time start property of a calendar component object.
+ **/
+void
+e_cal_component_set_dtstart (ECalComponent *comp,
+                            const ECalComponentDateTime *dt)
+{
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       set_datetime (comp->priv->icalcomp, I_CAL_DTSTART_PROPERTY,
+               i_cal_property_new_dtstart,
+               i_cal_property_set_dtstart,
+               dt);
 
        priv->need_sequence_inc = TRUE;
+}
 
-       if (status == ICAL_STATUS_NONE) {
-               if (priv->status) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->status);
-                       icalproperty_free (priv->status);
-                       priv->status = NULL;
-               }
+/**
+ * e_cal_component_get_due:
+ * @comp: A calendar component object.
+ * @dt: (out): Return value for the due date/time.  This should be freed with the
+ * e_cal_component_free_datetime() function.
+ *
+ * Queries the due date/time of a calendar component object. In case there's no DUE,
+ * but only DTSTART and DURATION, then the due is computed from the later two.
+ * Free the returned #ECalComponentDateTime with e_cal_component_datetime_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the due date/time, as an #ECalComponentDateTime
+ **/
+ECalComponentDateTime *
+e_cal_component_get_due (ECalComponent *comp)
+{
+       ECalComponentDateTime *dt;
 
-               return;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (priv->status) {
-               icalproperty_set_status (priv->status, status);
-       } else {
-               priv->status = icalproperty_new_status (status);
-               icalcomponent_add_property (priv->icalcomp, priv->status);
-       }
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_DUE_PROPERTY, i_cal_property_get_due);
+
+       /* If we don't have a DTEND property, then we try to get DTSTART
+        * + DURATION. */
+       if (!dt)
+               dt = e_cal_component_get_start_plus_duration (comp);
+
+       return dt;
 }
 
 /**
- * e_cal_component_get_summary:
+ * e_cal_component_set_due:
  * @comp: A calendar component object.
- * @summary: (out): Return value for the summary property and its parameters.
+ * @dt: (nullable): End date/time, or %NULL, to remove the property.
  *
- * Queries the summary of a calendar component object.
+ * Sets the due date/time property of a calendar component object.
  **/
 void
-e_cal_component_get_summary (ECalComponent *comp,
-                             ECalComponentText *summary)
+e_cal_component_set_due (ECalComponent *comp,
+                        const ECalComponentDateTime *dt)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (summary != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       set_datetime (comp->priv->icalcomp, I_CAL_DUE_PROPERTY,
+               i_cal_property_new_due,
+               i_cal_property_set_due,
+               dt);
 
-       if (priv->summary.prop)
-               summary->value = icalproperty_get_summary (priv->summary.prop);
-       else
-               summary->value = NULL;
+       /* Make sure we remove any existing DURATION property, as it can't be
+        * used with a DTEND. If DTEND is set to NULL, i.e. removed, we also
+        * want to remove any DURATION. */
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_DURATION_PROPERTY);
+       if (prop) {
+               i_cal_component_remove_property (comp->priv->icalcomp, prop);
+               g_clear_object (&prop);
+       }
 
-       if (priv->summary.altrep_param)
-               summary->altrep = icalparameter_get_altrep (priv->summary.altrep_param);
-       else
-               summary->altrep = NULL;
+       comp->priv->need_sequence_inc = TRUE;
 }
 
-typedef struct {
-       gchar *old_summary;
-       const gchar *new_summary;
-} SetAlarmDescriptionData;
+/* Builds a list of ECalComponentPeriod structures based on a list of icalproperties */
+static GSList * /* ECalComponentPeriod * */
+get_period_list (ICalComponent *icalcomp,
+                ICalPropertyKind prop_kind,
+                ICalDatetimeperiodType (* get_prop_func) (ICalProperty *prop),
+                const GSList **list)
+{
+       GSList *props, *link, *periods = NULL;
+
+       props = gather_all_properties (icalcomp, prop_kind, FALSE);
+
+       for (link = props; link; link = g_slist_next (link)) {
+               ICalProperty *prop = link->data;
+               ICalParameter *param;
+               ICalPeriodType *icalperiod;
+               ICalDatetimeperiodType *pt;
+               ICalDurationtype *duration = NULL;
+               ICalTimetype *start = NULL, *end = NULL;
+               ECalComponentPeriod *period;
+               ECalComponentPeriodKind period_kind;
+
+               if (!prop)
+                       continue;
+
+               /* Get start and end/duration */
+               pt = get_prop_func (prop);
+               if (!pt)
+                       continue;
+
+               icalperiod = i_cal_datetimeperiod_type_get_period (pt);
+
+               /* Get value parameter */
+               param = i_cal_property_get_first_parameter (prop, I_CAL_VALUE_PARAMETER);
+
+               if (param) {
+                       ICalParameterValue value_type;
 
+                       value_type = i_cal_parameter_get_value (param);
+
+                       if (value_type == I_CAL_VALUE_DATE || value_type == I_CAL_VALUE_DATETIME) {
+                               period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+                       } else if (value_type == I_CAL_VALUE_DURATION) {
+                               period_kind = E_CAL_COMPONENT_PERIOD_DURATION;
+                       } else if (value_type == I_CAL_VALUE_PERIOD) {
+                               duration = i_cal_period_type_get_duration (icalperiod);
+
+                               if (!duration ||
+                                   i_cal_durationtype_is_null_duration (duration) ||
+                                   i_cal_durationtype_is_bad_duration (duration))
+                                       period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+                               else
+                                       period_kind = E_CAL_COMPONENT_PERIOD_DURATION;
+
+                               g_clear_object (&duration);
+                       } else {
+                               g_message ("get_period_list(): Unknown value for period %d; using DATETIME", 
value_type);
+                               period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+                       }
+               } else {
+                       period_kind = E_CAL_COMPONENT_PERIOD_DATETIME;
+               }
+
+               start = i_cal_period_type_get_start (icalperiod);
+
+               if (period_kind == E_CAL_COMPONENT_PERIOD_DATETIME)
+                       end = i_cal_period_type_get_end (icalperiod);
+               else /* if (period_kind == E_CAL_COMPONENT_PERIOD_DURATION) */
+                       duration = i_cal_period_type_get_duration (icalperiod);
+
+               period = period_kind == E_CAL_COMPONENT_PERIOD_DATETIME ?
+                       e_cal_component_period_new_datetime (start, end) :
+                       e_cal_component_period_new_duration (start, duration);
+
+               if (period)
+                       periods = g_slist_prepend (periods, period);
+
+               g_clear_object (&param);
+               g_clear_object (&icalperiod);
+               g_clear_object (&pt);
+               g_clear_object (&duration);
+               g_clear_object (&start);
+               g_clear_object (&end);
+       }
+
+       g_slist_free_full (props, g_object_unref);
+
+       /* No need to reverse, it's prepended twice, thus in the correct order */
+       return periods;
+}
+
+/* Sets a period list value */
 static void
-set_alarm_description_cb (gpointer key,
-                          gpointer value,
-                          gpointer user_data)
+set_period_list (ICalComponent *icalcomp,
+                ICalPropertyKind prop_kind,
+                ICalProperty *(* new_prop_func) (ICalDatetimeperiodType *period),
+                const GSList *periods_list)
 {
-       icalcomponent *alarm;
-       icalproperty *icalprop, *desc_prop;
-       SetAlarmDescriptionData *sadd;
-       gboolean changed = FALSE;
-       const gchar *old_summary = NULL;
-       gboolean free_description = FALSE;
+       GSList *link;
 
-       alarm = value;
-       sadd = user_data;
+       /* Remove old periods */
 
-       /* set the new description on the alarm */
-       desc_prop = icalcomponent_get_first_property (alarm, ICAL_DESCRIPTION_PROPERTY);
-       if (desc_prop) {
-               old_summary = icalproperty_get_description (desc_prop);
-       } else {
-               desc_prop = icalproperty_new_description (sadd->new_summary);
-               free_description = TRUE;
-       }
+       remove_all_properties_of_kind (icalcomp, prop_kind);
 
-       /* remove the X-EVOLUTION-NEEDS_DESCRIPTION property */
-       icalprop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY);
-       while (icalprop) {
-               const gchar *x_name;
+       /* Add in new periods */
 
-               x_name = icalproperty_get_x_name (icalprop);
-               if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
-                       icalcomponent_remove_property (alarm, icalprop);
-                       icalproperty_free (icalprop);
+       for (link = (GSList *) periods_list; link; link = g_slist_next (link)) {
+               const ECalComponentPeriod *period = link->data;
+               ICalDatetimeperiodType *ic_datetimeperiod;
+               ICalPeriodType *ic_period;
+               ICalProperty *prop;
+               ICalParameter *param;
+               ICalParameterValue value_type = I_CAL_VALUE_UNKNOWN;
 
-                       icalproperty_set_description (desc_prop, sadd->new_summary);
-                       changed = TRUE;
+               if (!period)
+                       continue;
+
+               ic_period = i_cal_period_type_null_period ();
+
+               i_cal_period_type_set_start (ic_period, e_cal_component_period_get_start (period));
+
+               switch (e_cal_component_period_get_kind (period)) {
+               case E_CAL_COMPONENT_PERIOD_DATETIME:
+                       value_type = I_CAL_VALUE_DATETIME;
+                       i_cal_period_type_set_end (ic_period, e_cal_component_period_get_end (period));
                        break;
+               case E_CAL_COMPONENT_PERIOD_DURATION:
+                       value_type = I_CAL_VALUE_DURATION;
+                       i_cal_period_type_set_duration (ic_period, e_cal_component_period_get_end (duration));
                }
 
-               icalprop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY);
-       }
+               ic_datetimeperiod = i_cal_datetimeperiod_type_new ();
+               i_cal_datetimeperiod_type_set_period (ic_datetimeperiod, ic_period);
 
-       if (!changed) {
-               if (!strcmp (old_summary ? old_summary : "", sadd->old_summary ? sadd->old_summary : "")) {
-                       icalproperty_set_description (desc_prop, sadd->new_summary);
-               }
-       }
+               prop = new_prop_func (ic_datetimeperiod);
+
+               param = i_cal_parameter_new_value (value_type);
+               i_cal_property_take_parameter (prop, param);
 
-       if (free_description)
-               icalproperty_free (desc_prop);
+               i_cal_component_take_property (icalcomp, prop);
+
+               g_object_unref (ic_datetimeperiod);
+               g_object_unref (ic_period);
+       }
 }
 
-/**
- * e_cal_component_set_summary:
- * @comp: A calendar component object.
- * @summary: Summary property and its parameters.
- *
- * Sets the summary of a calendar component object.
- **/
-void
-e_cal_component_set_summary (ECalComponent *comp,
-                             ECalComponentText *summary)
+static gboolean
+extract_exdate_properties_cb (ICalComponent *icalcomp,
+                             ICalProperty *prop,
+                             gpointer user_data)
 {
-       ECalComponentPrivate *priv;
-       SetAlarmDescriptionData sadd;
+       GSList **pexdates = user_data;
+       ICalTimetype *tt;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_val_if_fail (pexdates != NULL, FALSE);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       tt = i_cal_property_get_exdate (prop);
+       if (tt) {
+               ICalParameter *param;
+               gchar *tzid;
 
-       if (!summary) {
-               if (priv->summary.prop) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->summary.prop);
-                       icalproperty_free (priv->summary.prop);
+               param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
+               if (param)
+                       tzid = g_strdup (i_cal_parameter_get_tzid (param));
+               else
+                       tzid = NULL;
 
-                       priv->summary.prop = NULL;
-                       priv->summary.altrep_param = NULL;
+               if (tzid && !*tzid) {
+                       g_free (tzid);
+                       tzid = NULL;
                }
 
-               return;
+               *pexdates = g_slist_prepend (*pexdates, e_cal_component_datetime_new_take (tt, tzid));
        }
 
-       g_return_if_fail (summary->value != NULL);
+       return TRUE;
+}
 
-       if (priv->summary.prop) {
-               /* Make a copy, to avoid use-after-free */
-               sadd.old_summary = g_strdup (icalproperty_get_summary (priv->summary.prop));
-               icalproperty_set_summary (priv->summary.prop, (gchar *) summary->value);
-       } else {
-               sadd.old_summary = NULL;
-               priv->summary.prop = icalproperty_new_summary ((gchar *) summary->value);
-               icalcomponent_add_property (priv->icalcomp, priv->summary.prop);
-       }
+/**
+ * e_cal_component_get_exdate_list:
+ * @comp: A calendar component object.
+ *
+ * Queries the list of exception date properties in a calendar component object.
+ * Free the returned #GSList with g_slist_free_full (exdates, e_cal_component_datetime_free);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ECalComponentDateTime):
+ *    the list of exception dates, as a #GSList of #ECalComponentDateTime
+ **/
+GSList *
+e_cal_component_get_exdate_list (ECalComponent *comp)
+{
+       GSList *exdates = NULL;
 
-       if (summary->altrep) {
-               g_return_if_fail (priv->summary.prop != NULL);
-
-               if (priv->summary.altrep_param)
-                       icalparameter_set_altrep (
-                               priv->summary.altrep_param,
-                               (gchar *) summary->altrep);
-               else {
-                       priv->summary.altrep_param = icalparameter_new_altrep (
-                               (gchar *) summary->altrep);
-                       icalproperty_add_parameter (
-                               priv->summary.prop,
-                               priv->summary.altrep_param);
-               }
-       } else if (priv->summary.altrep_param) {
-               icalproperty_remove_parameter_by_kind (priv->summary.prop, ICAL_ALTREP_PARAMETER);
-               priv->summary.altrep_param = NULL;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       /* look for alarms that need a description */
-       sadd.new_summary = summary->value;
-       g_hash_table_foreach (priv->alarm_uid_hash, set_alarm_description_cb, &sadd);
+       foreach_property (comp->priv->icalcomp, I_CAL_EXDATE_PROPERTY,
+               extract_exdate_properties_cb, &exdates);
 
-       g_free (sadd.old_summary);
+       return g_slist_reverse (exdates);
 }
 
 /**
- * e_cal_component_get_transparency:
+ * e_cal_component_set_exdate_list:
  * @comp: A calendar component object.
- * @transp: (out): Return value for the time transparency.
+ * @exdate_list: (nullable) (element-type ECalComponentDateTime): List of #ECalComponentDateTime structures.
  *
- * Queries the time transparency of a calendar component object.
+ * Sets the list of exception dates in a calendar component object.
  **/
 void
-e_cal_component_get_transparency (ECalComponent *comp,
-                                  ECalComponentTransparency *transp)
+e_cal_component_set_exdate_list (ECalComponent *comp,
+                                const GSList *exdate_list)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_transp ical_transp;
+       GSList *link;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (transp != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       /* Remove old exception dates */
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_EXDATE_PROPERTY);
 
-       if (!priv->transparency) {
-               *transp = E_CAL_COMPONENT_TRANSP_NONE;
-               return;
-       }
+       /* Add in new exception dates */
 
-       ical_transp = icalproperty_get_transp (priv->transparency);
+       for (link = (GSList *) exdate_list; link; link = g_slist_next (link)) {
+               const ECalComponentDateTime *dt = link->data;
+               ICalProperty *prop;
+               ICalTimetype *tt;
+               const gchar *tzid;
 
-       switch (ical_transp)
-       {
-       case ICAL_TRANSP_TRANSPARENT:
-       case ICAL_TRANSP_TRANSPARENTNOCONFLICT:
-         *transp = E_CAL_COMPONENT_TRANSP_TRANSPARENT;
-         break;
+               if (!dt)
+                       continue;
+
+               tt = e_cal_component_datetime_get_value (dt);
+               if (!tt)
+                       continue;
 
-       case ICAL_TRANSP_OPAQUE:
-       case ICAL_TRANSP_OPAQUENOCONFLICT:
-         *transp = E_CAL_COMPONENT_TRANSP_OPAQUE;
-         break;
+               tzid = e_cal_component_datetime_get_tzid (dt);
 
-       default:
-         *transp = E_CAL_COMPONENT_TRANSP_UNKNOWN;
-         break;
+               prop = i_cal_property_new_exdate (tt);
+
+               if (tzid && *tzid) {
+                       ICalParameter *param;
+
+                       param = i_cal_parameter_new_tzid ((gchar *) tzid);
+                       i_cal_property_take_parameter (prop, param);
+               }
+
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
+
+       priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_set_transparency:
+ * e_cal_component_has_exdates:
  * @comp: A calendar component object.
- * @transp: Time transparency value.
  *
- * Sets the time transparency of a calendar component object.
+ * Queries whether a calendar component object has any exception dates defined
+ * for it.
+ *
+ * Returns: TRUE if the component has exception dates, FALSE otherwise.
  **/
-void
-e_cal_component_set_transparency (ECalComponent *comp,
-                                  ECalComponentTransparency transp)
+gboolean
+e_cal_component_has_exdates (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalproperty_transp ical_transp;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (transp != E_CAL_COMPONENT_TRANSP_UNKNOWN);
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_EXDATE_PROPERTY);
+}
+
+/* Gets a list of recurrence rules */
+static GSList *
+get_recur_list (ICalComponent *icalcomp,
+               ICalPropertyKind prop_kind,
+                ICalRecurrenceType * (* get_prop_func) (ICalProperty *prop))
+{
+       GSList *props, *link, *recurs = NULL;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       props = gather_all_properties (icalcomp, prop_kind, FALSE);
 
-       if (transp == E_CAL_COMPONENT_TRANSP_NONE) {
-               if (priv->transparency) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->transparency);
-                       icalproperty_free (priv->transparency);
-                       priv->transparency = NULL;
-               }
+       for (link = props; link; link = g_slist_next (link)) {
+               ICalProperty *prop = link->data;
+               ICalRecurrenceType *rt;
 
-               return;
+               rt = get_prop_func (prop);
+               if (rc)
+                       recurs = g_slist_prepend (recurs, rt);
        }
 
-       switch (transp) {
-       case E_CAL_COMPONENT_TRANSP_TRANSPARENT:
-         ical_transp = ICAL_TRANSP_TRANSPARENT;
-               break;
+       g_slist_free_full (props, g_object_unref);
 
-       case E_CAL_COMPONENT_TRANSP_OPAQUE:
-         ical_transp = ICAL_TRANSP_OPAQUE;
-               break;
+       /* No need to reverse it, the props are in reverse order
+          and processed in the reverse roder, thus the result
+          is in the expected order. */
+       return recurs;
+}
 
-       default:
-               g_warn_if_reached ();
-               ical_transp = ICAL_TRANSP_NONE;
-       }
+/* Sets a list of recurrence rules */
+static void
+set_recur_list (ICalComponent *icalcomp,
+               ICalPropertyKind prop_kind,
+               ICalProperty * (* new_prop_func) (ICalRecurrenceType *recur),
+               const GSList *rl) /* ICalRecurrenceType * */
+{
+       GSList *link;
+
+       /* Remove old recurrences */
+       remove_all_properties_of_kind (icalcomp, prop_kind);
 
-       if (priv->transparency)
-               icalproperty_set_transp (priv->transparency, ical_transp);
-       else {
-               priv->transparency = icalproperty_new_transp (ical_transp);
-               icalcomponent_add_property (priv->icalcomp, priv->transparency);
+       /* Add in new recurrences */
+
+       for (link = (GSList *) rl; link; link = g_slist_next (link)) {
+               ICalProperty *prop;
+               ICalRecurrenceType *recur = l->data;
+
+               if (recur) {
+                       prop = (* new_prop_func) (recur);
+                       i_cal_component_take_property (comp->priv->icalcomp, prop);
+               }
        }
 }
 
 /**
- * e_cal_component_get_url:
+ * e_cal_component_get_exrule_list:
  * @comp: A calendar component object.
- * @url: (out) (transfer none): Return value for the URL.
  *
- * Queries the uniform resource locator property of a calendar component object.
+ * Queries the list of exception rule properties of a calendar component
+ * object. Free the returned list with g_slist_free_full (slist, g_object_unref);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalRecurrenceType): a #GSList
+ *    of exception rules as #ICalRecurrenceType structures, or %NULL, when none exist.
  **/
-void
-e_cal_component_get_url (ECalComponent *comp,
-                         const gchar **url)
+GSList *
+e_cal_component_get_exrule_list (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (url != NULL);
+       return get_recur_list (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY, i_cal_property_get_exrule);
+}
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+/**
+ * e_cal_component_get_exrule_property_list:
+ * @comp: A calendar component object.
+ *
+ * Queries the list of exception rule properties of a calendar component object.
+ * Free the list with g_slist_free_full (slist, g_object_unref);, when
+ * no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalProperty): a list of exception
+ *    rule properties
+ **/
+GSList *
+e_cal_component_get_exrule_property_list (ECalComponent *comp,
+                                          GSList **recur_list)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (priv->url)
-               *url = icalproperty_get_url (priv->url);
-       else
-               *url = NULL;
+       return gather_all_properties (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY, TRUE);
 }
 
 /**
- * e_cal_component_set_url:
+ * e_cal_component_set_exrule_list:
  * @comp: A calendar component object.
- * @url: URL value.
+ * @recur_list: (nullable): (element-type ICalRecurrenceType): a #GSList
+ *    of #ICalRecurrenceType structures, or %NULL.
  *
- * Sets the uniform resource locator property of a calendar component object.
+ * Sets the list of exception rules in a calendar component object.
  **/
 void
-e_cal_component_set_url (ECalComponent *comp,
-                         const gchar *url)
+e_cal_component_set_exrule_list (ECalComponent *comp,
+                                const GSList *recur_list)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       set_recur_list (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY, i_cal_property_new_exrule, recur_list);
 
-       if (!url || !(*url)) {
-               if (priv->url) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->url);
-                       icalproperty_free (priv->url);
-                       priv->url = NULL;
-               }
+       priv->need_sequence_inc = TRUE;
+}
 
-               return;
-       }
+/**
+ * e_cal_component_has_exrules:
+ * @comp: A calendar component object.
+ *
+ * Queries whether a calendar component object has any exception rules defined
+ * for it.
+ *
+ * Returns: TRUE if the component has exception rules, FALSE otherwise.
+ **/
+gboolean
+e_cal_component_has_exrules (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       if (priv->url)
-               icalproperty_set_url (priv->url, (gchar *) url);
-       else {
-               priv->url = icalproperty_new_url ((gchar *) url);
-               icalcomponent_add_property (priv->icalcomp, priv->url);
-       }
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_EXRULE_PROPERTY);
 }
 
-/* Gets a text list value */
-static void
-get_attendee_list (GSList *attendee_list,
-                   GSList **al)
+/**
+ * e_cal_component_has_exceptions:
+ * @comp: A calendar component object
+ *
+ * Queries whether a calendar component object has any exception dates
+ * or exception rules.
+ *
+ * Returns: TRUE if the component has exceptions, FALSE otherwise.
+ **/
+gboolean
+e_cal_component_has_exceptions (ECalComponent *comp)
 {
-       GSList *l;
-
-       *al = NULL;
+       return e_cal_component_has_exdates (comp) || e_cal_component_has_exrules (comp);
+}
 
-       if (!attendee_list)
-               return;
+/**
+ * e_cal_component_get_geo:
+ * @comp: A calendar component object.
+ *
+ * Gets the geographic position property of a calendar component object.
+ * Free the returned non-NULL object with g_object_unref(), when
+ * no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the geographic position as #ICalGeoType,
+ *    or %NULL, when none set.
+ **/
+ICalGeoType *
+e_cal_component_get_geo (ECalComponent *comp)
+{
+       ICalProperty *prop;
+       ICalGeoType *geo;
 
-       for (l = attendee_list; l; l = l->next) {
-               struct attendee *attendee;
-               ECalComponentAttendee *a;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               attendee = l->data;
-               g_return_if_fail (attendee->prop != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_GEO_PROPERTY);
+       if (!prop)
+               return NULL;
 
-               a = g_new0 (ECalComponentAttendee, 1);
-               a->value = icalproperty_get_attendee (attendee->prop);
+       geo = i_cal_property_get_geo (prop);
 
-               if (attendee->member_param)
-                       a->member = icalparameter_get_member (attendee->member_param);
-               if (attendee->cutype_param)
-                       a->cutype = icalparameter_get_cutype (attendee->cutype_param);
-               else
-                       a->cutype = ICAL_CUTYPE_UNKNOWN;
-               if (attendee->role_param)
-                       a->role = icalparameter_get_role (attendee->role_param);
-               else
-                       a->role = ICAL_ROLE_REQPARTICIPANT;
-               if (attendee->partstat_param)
-                       a->status = icalparameter_get_partstat (attendee->partstat_param);
-               else
-                       a->status = ICAL_PARTSTAT_NEEDSACTION;
-               if (attendee->rsvp_param && icalparameter_get_rsvp (attendee->rsvp_param) == ICAL_RSVP_TRUE)
-                       a->rsvp = TRUE;
-               else
-                       a->rsvp = FALSE;
-               if (attendee->delfrom_param)
-                       a->delfrom = icalparameter_get_delegatedfrom (attendee->delfrom_param);
-               if (attendee->delto_param)
-                       a->delto = icalparameter_get_delegatedto (attendee->delto_param);
-               if (attendee->sentby_param)
-                       a->sentby = icalparameter_get_sentby (attendee->sentby_param);
-               if (attendee->cn_param)
-                       a->cn = icalparameter_get_cn (attendee->cn_param);
-               if (attendee->language_param)
-                       a->language = icalparameter_get_language (attendee->language_param);
-
-               *al = g_slist_prepend (*al, a);
-       }
+       g_object_unref (prop);
 
-       *al = g_slist_reverse (*al);
+       return geo;
 }
 
-/* Sets a text list value */
-static void
-set_attendee_list (icalcomponent *icalcomp,
-                   GSList **attendee_list,
-                   GSList *al)
+/**
+ * e_cal_component_set_geo:
+ * @comp: A calendar component object.
+ * @geo: (nullable): Value for the geographic position property, or %NULL to unset.
+ *
+ * Sets the geographic position property on a calendar component object.
+ **/
+void
+e_cal_component_set_geo (ECalComponent *comp,
+                        const ICalGeoType *geo)
 {
-       GSList *l;
+       ICalProperty *prop;
 
-       /* Remove old attendees */
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       for (l = *attendee_list; l; l = l->next) {
-               struct attendee *attendee;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_GEO_PROPERTY);
 
-               attendee = l->data;
-               g_return_if_fail (attendee->prop != NULL);
+       if (!geo) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
+               }
 
-               icalcomponent_remove_property (icalcomp, attendee->prop);
-               icalproperty_free (attendee->prop);
-               g_free (attendee);
+               return;
        }
 
-       g_slist_free (*attendee_list);
-       *attendee_list = NULL;
-
-       /* Add in new attendees */
-
-       for (l = al; l; l = l->next) {
-               ECalComponentAttendee *a;
-               struct attendee *attendee;
+       if (prop) {
+               i_cal_property_set_geo (prop, geo);
+       } else {
+               prop = i_cal_property_new_geo (geo);
+               i_cal_component_add_property (comp->priv->icalcomp, prop);
+       }
 
-               a = l->data;
-               g_return_if_fail (a->value != NULL);
+       g_clear_object (&prop);
+}
 
-               attendee = g_new0 (struct attendee, 1);
+/**
+ * e_cal_component_get_last_modified:
+ * @comp: A calendar component object.
+ *
+ * Queries the time at which a calendar component object was last modified in
+ * the calendar store. Free the returned non-NULL pointer with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): the last modified time, as an #ICalTimetype, or %NULL, when none is set
+ **/
+ICalTimetype *
+e_cal_component_get_last_modified (ECalComponent *comp)
+{
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               attendee->prop = icalproperty_new_attendee (a->value);
-               icalcomponent_add_property (icalcomp, attendee->prop);
+       return get_icaltimetype (comp->priv->icalcomp, I_CAL_LASTMODIFIED_PROPERTY, 
i_cal_property_get_lastmodified);
+}
 
-               if (a->member) {
-                       attendee->member_param = icalparameter_new_member (a->member);
-                       icalproperty_add_parameter (attendee->prop, attendee->member_param);
-               }
+/**
+ * e_cal_component_set_last_modified:
+ * @comp: A calendar component object.
+ * @tt: (nullable): Value for the last time modified.
+ *
+ * Sets the time at which a calendar component object was last stored in the
+ * calendar store.  This should not be called by plain calendar user agents.
+ **/
+void
+e_cal_component_set_last_modified (ECalComponent *comp,
+                                  const ICalTimetype *tt)
+{
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-               attendee->cutype_param = icalparameter_new_cutype (a->cutype);
-               icalproperty_add_parameter (attendee->prop, attendee->cutype_param);
+       set_icaltimetype (comp->priv->icalcomp, I_CAL_LASTMODIFIED_PROPERTY,
+               i_cal_property_new_lastmodified,
+               i_cal_property_set_lastmodified,
+               tt);
+}
 
-               attendee->role_param = icalparameter_new_role (a->role);
-               icalproperty_add_parameter (attendee->prop, attendee->role_param);
+/**
+ * e_cal_component_get_organizer:
+ * @comp:  A calendar component object
+ *
+ * Queries the organizer property of a calendar component object.
+ * Free the returned structure with e_cal_component_organizer_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): an #ECalComponentOrganizer structure
+ *    destribing the organizer, or %NULL, when none exists.
+ **/
+ECalComponentOrganizer *
+e_cal_component_get_organizer (ECalComponent *comp)
+{
+       ECalComponentOrganizer *organizer;
+       ICalProperty *prop;
 
-               attendee->partstat_param = icalparameter_new_partstat (a->status);
-               icalproperty_add_parameter (attendee->prop, attendee->partstat_param);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-               if (a->rsvp)
-                       attendee->rsvp_param = icalparameter_new_rsvp (ICAL_RSVP_TRUE);
-               else
-                       attendee->rsvp_param = icalparameter_new_rsvp (ICAL_RSVP_FALSE);
-               icalproperty_add_parameter (attendee->prop, attendee->rsvp_param);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_ORGANIZER_PROPERTY);
+       if (!prop)
+               return NULL;
 
-               if (a->delfrom) {
-                       attendee->delfrom_param = icalparameter_new_delegatedfrom (a->delfrom);
-                       icalproperty_add_parameter (attendee->prop, attendee->delfrom_param);
-               }
-               if (a->delto) {
-                       attendee->delto_param = icalparameter_new_delegatedto (a->delto);
-                       icalproperty_add_parameter (attendee->prop, attendee->delto_param);
-               }
-               if (a->sentby) {
-                       attendee->sentby_param = icalparameter_new_sentby (a->sentby);
-                       icalproperty_add_parameter (attendee->prop, attendee->sentby_param);
-               }
-               if (a->cn) {
-                       attendee->cn_param = icalparameter_new_cn (a->cn);
-                       icalproperty_add_parameter (attendee->prop, attendee->cn_param);
-               }
-               if (a->language) {
-                       attendee->language_param = icalparameter_new_language (a->language);
-                       icalproperty_add_parameter (attendee->prop, attendee->language_param);
-               }
+       organizer = e_cal_component_organizer_new_from_property (prop);
 
-               *attendee_list = g_slist_prepend (*attendee_list, attendee);
-       }
+       g_object_unref (prop);
 
-       *attendee_list = g_slist_reverse (*attendee_list);
+       return organizer;
 }
 
 /**
- * e_cal_component_get_attendee_list:
- * @comp: A calendar component object.
- * @attendee_list: (out) (transfer full) (element-type ECalComponentAttendee):
- * Return value for the attendee property. This should be freed using
- * e_cal_component_free_attendee_list().
+ * e_cal_component_set_organizer:
+ * @comp:  A calendar component object.
+ * @organizer: (nullable): Value for the organizer property, as an #ECalComponentOrganizer
  *
- * Queries the attendee properties of the calendar component object
+ * Sets the organizer of a calendar component object
  **/
 void
-e_cal_component_get_attendee_list (ECalComponent *comp,
-                                   GSList **attendee_list)
+e_cal_component_set_organizer (ECalComponent *comp,
+                              const ECalComponentOrganizer *organizer)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (attendee_list != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_ORGANIZER_PROPERTY);
 
-       get_attendee_list (priv->attendee_list, attendee_list);
-}
+       if (!organizer) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
+               }
 
-/**
- * e_cal_component_set_attendee_list:
- * @comp: A calendar component object.
- * @attendee_list: (element-type ECalComponentAttendee): Values for attendee
- * properties
- *
- * Sets the attendees of a calendar component object
- **/
-void
-e_cal_component_set_attendee_list (ECalComponent *comp,
-                                   GSList *attendee_list)
-{
-       ECalComponentPrivate *priv;
+               return;
+       }
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       if (!prop) {
+               prop = i_cal_property_new (I_CAL_ORGANIZER_PROPERTY);
+               i_cal_component_add_property (comp->priv->icalcomp, prop);
+       }
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       e_cal_component_organizer_fill_property (organizer, prop);
 
-       set_attendee_list (priv->icalcomp, &priv->attendee_list, attendee_list);
+       g_clear_object (&prop);
 }
 
 /**
- * e_cal_component_has_attendees:
+ * e_cal_component_has_organizer:
  * @comp: A calendar component object.
  *
- * Queries a calendar component object for the existence of attendees.
+ * Check whether a calendar component object has an organizer or not.
  *
- * Returns: TRUE if there are attendees, FALSE if not.
- */
+ * Returns: TRUE if there is an organizer, FALSE otherwise.
+ **/
 gboolean
-e_cal_component_has_attendees (ECalComponent *comp)
+e_cal_component_has_organizer (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       priv = comp->priv;
-
-       if (g_slist_length (priv->attendee_list) > 0)
-               return TRUE;
-
-       return FALSE;
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_ORGANIZER_PROPERTY);
 }
 
 /**
- * e_cal_component_get_location:
- * @comp: A calendar component object
- * @location: (out) (transfer none): Return value for the location.
+ * e_cal_component_get_percent_complete:
+ * @comp: A calendar component object.
  *
- * Queries the location property of a calendar component object.
+ * Queries the percent-complete property of a calendar component object.
+ *
+ * Returns: the percent-complete property value, or -1 if not found
  **/
-void
-e_cal_component_get_location (ECalComponent *comp,
-                              const gchar **location)
+gint
+e_cal_component_get_percent_complete (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
+       gint percent;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (location != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp), -1);
+       g_return_if_fail (comp->priv->icalcomp != NULL, -1);
+
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PERCENTCOMPLETE_PROPERTY);
+       if (!prop)
+               return -1;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       percent = i_cal_property_get_percentcomplete (prop);
 
-       if (priv->location)
-               *location = icalproperty_get_location (priv->location);
-       else
-               *location = NULL;
+       g_object_unref (prop);
+
+       return percent;
 }
 
 /**
- * e_cal_component_set_location:
- * @comp: A calendar component object.
- * @location: Location value.
+ * e_cal_component_set_percent_complete:
+ * @comp: an #ECalComponent
+ * @percent: a percent to set, or -1 to remove the property
  *
- * Sets the location property of a calendar component object.
+ * Sets percent complete. The @percent can be between 0 and 100, inclusive.
+ * A special value -1 can be used to remove the percent complete property.
+ *
+ * Since: 2.28
  **/
 void
-e_cal_component_set_location (ECalComponent *comp,
-                              const gchar *location)
+e_cal_component_set_percent_complete (ECalComponent *comp,
+                                     gint percent)
 {
-       ECalComponentPrivate *priv;
+       ICalProperty *prop;
 
-       g_return_if_fail (comp != NULL);
        g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+       g_return_if_fail (percent >= -1 && percent <= 100);
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PERCENTCOMPLETE_PROPERTY);
 
-       if (!location || !(*location)) {
-               if (priv->location) {
-                       icalcomponent_remove_property (priv->icalcomp, priv->location);
-                       icalproperty_free (priv->location);
-                       priv->location = NULL;
+       if (percent == -1) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
                }
 
                return;
        }
 
-       if (priv->location)
-               icalproperty_set_location (priv->location, (gchar *) location);
-       else {
-               priv->location = icalproperty_new_location ((gchar *) location);
-               icalcomponent_add_property (priv->icalcomp, priv->location);
+       if (prop) {
+               i_cal_property_set_percentcomplete (prop, percent);
+               g_clear_object (&prop);
+       } else {
+               prop = i_cal_property_new_percentcomplete (percent);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
-
-
 /**
- * e_cal_component_free_categories_list:
- * @categ_list: (element-type utf8): List of category strings
+ * e_cal_component_get_priority:
+ * @comp: A calendar component object.
  *
- * Frees a list of category strings.
+ * Queries the priority property of a calendar component object.
+ *
+ * @priority: the priority property value, or -1 if not found
  **/
-void
-e_cal_component_free_categories_list (GSList *categ_list)
+gint
+e_cal_component_get_priority (ECalComponent *comp)
 {
-       GSList *l;
+       ICalProperty *prop;
+       gint priority;
 
-       for (l = categ_list; l; l = l->next)
-               g_free (l->data);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp), -1);
+       g_return_if_fail (comp->priv->icalcomp != NULL, -1);
 
-       g_slist_free (categ_list);
-}
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PRIORITY_PROPERTY);
+       if (!prop)
+               return -1;
 
-/**
- * e_cal_component_free_range:
- * @range: A #ECalComponentRange.
- *
- * Frees an #ECalComponentRange structure.
- */
-void
-e_cal_component_free_range (ECalComponentRange *range)
-{
-       g_return_if_fail (range != NULL);
+       priority = i_cal_property_get_priority (prop);
+
+       g_object_unref (prop);
 
-       e_cal_component_free_datetime (&range->datetime);
+       return priority;
 }
 
 /**
- * e_cal_component_free_exdate_list:
- * @exdate_list: (element-type ECalComponentDateTime): List of
- * #ECalComponentDateTime structures
+ * e_cal_component_set_priority:
+ * @comp: A calendar component object.
+ * @priority: Value for the priority property.
  *
- * Frees a list of #ECalComponentDateTime structures as returned by the
- * e_cal_component_get_exdate_list() function.
+ * Sets the priority property of a calendar component object.
+ * The @priority can be between 0 and 9, inclusive.
+ * A special value -1 can be used to remove the priority property.
  **/
 void
-e_cal_component_free_exdate_list (GSList *exdate_list)
+e_cal_component_set_priority (ECalComponent *comp,
+                             gint priority)
 {
-       GSList *l;
+       ICalProperty *prop;
 
-       for (l = exdate_list; l; l = l->next) {
-               ECalComponentDateTime *cdt;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+       g_return_if_fail (priority >= -1 && priority <= 9);
 
-               g_return_if_fail (l->data != NULL);
-               cdt = l->data;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_PRIORITY_PROPERTY);
 
-               g_return_if_fail (cdt->value != NULL);
-               g_free (cdt->value);
-               g_free ((gchar *) cdt->tzid);
+       if (priority == -1) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_clear_object (&prop);
+               }
 
-               g_free (cdt);
+               return;
        }
 
-       g_slist_free (exdate_list);
+       if (prop) {
+               i_cal_property_set_priority (prop, priority);
+               g_clear_object (&prop);
+       } else {
+               prop = i_cal_property_new_priority (priority);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
 }
 
 /**
- * e_cal_component_free_geo:
- * @geo: An #icalgeotype structure.
+ * e_cal_component_get_recurid:
+ * @comp: A calendar component object.
+ *
+ * Queries the recurrence id property of a calendar component object.
+ * Free the returned #ECalComponentRange with e_cal_component_range_free(),
+ * whe no longer needed.
  *
- * Frees a struct #icalgeotype structure as returned by the calendar component
- * functions.
+ * Returns: (transfer full) (nullable): the recurrence id property, as an #ECalComponentRange
  **/
-void
-e_cal_component_free_geo (struct icalgeotype *geo)
+ECalComponentRange *
+e_cal_component_get_recurid (ECalComponent *comp)
 {
-       g_return_if_fail (geo != NULL);
+       ECalComponentDatetime *dt;
 
-       g_free (geo);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
+
+       dt = get_datetime (comp->priv->icalcomp, I_CAL_RECURRENCEID_PROPERTY, 
i_cal_property_get_recurrenceid);
+
+       if (!dt)
+               return NULL;
+
+       return e_cal_component_range_new_take (E_CAL_COMPONENT_RANGE_SINGLE, dt);
 }
 
 /**
- * e_cal_component_free_icaltimetype:
- * @t: An #icaltimetype structure.
+ * e_cal_component_get_recurid_as_string:
+ * @comp: A calendar component object.
  *
- * Frees a struct #icaltimetype value as returned by the calendar component
- * functions.
- **/
-void
-e_cal_component_free_icaltimetype (struct icaltimetype *t)
+ * Gets the recurrence ID property as a string.
+ *
+ * Returns: the recurrence ID as a string.
+ */
+gchar *
+e_cal_component_get_recurid_as_string (ECalComponent *comp)
 {
-       g_return_if_fail (t != NULL);
+       ECalComponentRange *range;
+       ECalComponentDateTime *dt = NULL; /* owned by the 'range' */
+       ICalTimetype *tt = NULL; /* owned by the 'range' */
+       gchar *rid;
+
+       if (!e_cal_component_is_instance (comp))
+               return NULL;
+
+       range = e_cal_component_get_recurid (comp);
+       if (range)
+               dt = e_cal_component_range_get_datetime (range);
+       if (dt)
+               ii = e_cal_component_datetime_get_value (dt);
+
+       if (!range || !dt || !itt) {
+               e_cal_component_range_free (range);
+               return g_strdup ("0");
+       }
 
-       g_free (t);
+       if (i_cal_time_is_valid_time (tt) && !i_cal_time_is_null_time (tt))
+               rid = i_cal_time_as_ical_string_r (tt);
+       else
+               rid = g_strdup ("0");
+
+       e_cal_component_range_free (range);
+
+       return rid;
 }
 
 /**
- * e_cal_component_free_percent:
- * @percent: Percent value.
+ * e_cal_component_set_recurid:
+ * @comp: A calendar component object.
+ * @recur_id: (nullable): Value for the recurrence id property, or %NULL, to remove the property.
  *
- * Frees a percent value as returned by the e_cal_component_get_percent()
- * function.
+ * Sets the recurrence id property of a calendar component object.
  **/
 void
-e_cal_component_free_percent (gint *percent)
+e_cal_component_set_recurid (ECalComponent *comp,
+                            const ECalComponentRange *recur_id)
 {
-       g_return_if_fail (percent != NULL);
+       ECalComponentDateTime *dt;
 
-       g_free (percent);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       dt = recur_id ? e_cal_component_range_get_datetime (recur_id) : NULL;
+
+       set_datetime (comp->priv->icalcomp, I_CAL_RECURRENCEID_PROPERTY,
+               i_cal_property_new_recurrenceid,
+               i_cal_property_set_recurrenceid,
+               dt);
 }
 
 /**
- * e_cal_component_free_priority:
- * @priority: Priority value.
+ * e_cal_component_get_rdate_list:
+ * @comp: A calendar component object.
  *
- * Frees a priority value as returned by the e_cal_component_get_priority()
- * function.
+ * Queries the list of recurrence date properties in a calendar component
+ * object. Free the returned #GSList with g_slist_free_full (slist, e_cal_component_period_free);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ECalComponentPeriod): the list
+ *    of recurrence dates, as a #GSList of #ECalComponentPeriod structures.
  **/
-void
-e_cal_component_free_priority (gint *priority)
+GSList *
+e_cal_component_get_rdate_list (ECalComponent *comp)
 {
-       g_return_if_fail (priority != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       g_free (priority);
+       return get_period_list (comp->priv->icalcomp, I_CAL_RDATE_PROPERTY, i_cal_property_get_rdate);
 }
 
 /**
- * e_cal_component_free_period_list:
- * @period_list: (element-type ECalComponentPeriod): List of
- * #ECalComponentPeriod structures
+ * e_cal_component_set_rdate_list:
+ * @comp: A calendar component object.
+ * @rdate_list: (nullable) (element-type ECalComponentPeriod): List of
+ *    #ECalComponentPeriod structures, or %NULL to set none
  *
- * Frees a list of #ECalComponentPeriod structures.
+ * Sets the list of recurrence dates in a calendar component object.
  **/
 void
-e_cal_component_free_period_list (GSList *period_list)
+e_cal_component_set_rdate_list (ECalComponent *comp,
+                               const GSList *rdate_list)
 {
-       g_slist_foreach (period_list, (GFunc) g_free, NULL);
-       g_slist_free (period_list);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       set_period_list (comp->priv->icalcomp, I_CAL_RDATE_PROPERTY, i_cal_property_new_rdate, rdate_list);
+
+       priv->need_sequence_inc = TRUE;
 }
 
 /**
- * e_cal_component_free_recur_list:
- * @recur_list: (element-type icalrecurrencetype): List of struct
- * #icalrecurrencetype structures.
+ * e_cal_component_has_rdates:
+ * @comp: A calendar component object.
+ *
+ * Queries whether a calendar component object has any recurrence dates defined
+ * for it.
  *
- * Frees a list of struct #icalrecurrencetype structures.
+ * Returns: TRUE if the component has recurrence dates, FALSE otherwise.
  **/
-void
-e_cal_component_free_recur_list (GSList *recur_list)
+gboolean
+e_cal_component_has_rdates (ECalComponent *comp)
 {
-       g_slist_foreach (recur_list, (GFunc) g_free, NULL);
-       g_slist_free (recur_list);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
+
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_RDATE_PROPERTY);
 }
 
 /**
- * e_cal_component_free_sequence:
- * @sequence: Sequence number value.
+ * e_cal_component_get_rrule_list:
+ * @comp: A calendar component object.
  *
- * Frees a sequence number value.
+ * Queries the list of recurrence rule properties of a calendar component
+ * object. Free the returned list with g_slist_free_full (slist, g_object_unref);,
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable) (element-type ICalRecurrenceType): a #GSList
+ *    of recurrence rules as #ICalRecurrenceType structures, or %NULL, when none exist.
  **/
-void
-e_cal_component_free_sequence (gint *sequence)
+GSList *
+e_cal_component_get_rrule_list (ECalComponent *comp)
 {
-       g_return_if_fail (sequence != NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       g_free (sequence);
+       return get_recur_list (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY, i_cal_property_get_rrule);
 }
 
 /**
- * e_cal_component_free_text_list:
- * @text_list: (element-type ECalComponentText): List of #ECalComponentText
- * structures.
+ * e_cal_component_get_rrule_property_list:
+ * @comp: A calendar component object.
+ *
+ * Queries a list of recurrence rule properties of a calendar component object.
+ * Free the list with g_slist_free_full (slist, g_object_unref);, when
+ * no longer needed.
  *
- * Frees a list of #ECalComponentText structures.  This function should only be
- * used to free lists of text values as returned by the other getter functions
- * of #ECalComponent.
+ * Returns: (transfer full) (nullable) (element-type ICalProperty): a list of recurrence
+ *    rule properties
  **/
-void
-e_cal_component_free_text_list (GSList *text_list)
+GSList *
+e_cal_component_get_rrule_property_list (ECalComponent *comp)
 {
-       g_slist_foreach (text_list, (GFunc) g_free, NULL);
-       g_slist_free (text_list);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       return gather_all_properties (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY, TRUE);
 }
 
 /**
- * e_cal_component_free_attendee_list:
- * @attendee_list: (element-type ECalComponentAttendee): List of attendees
- *
- * Frees a list of #ECalComponentAttendee structures.
+ * e_cal_component_set_rrule_list:
+ * @comp: A calendar component object.
+ * @recur_list: (nullable) (element-type ICalRecurrenceType): List of #ICalRecurrenceType structures, or 
%NULL.
  *
+ * Sets the list of recurrence rules in a calendar component object.
  **/
 void
-e_cal_component_free_attendee_list (GSList *attendee_list)
+e_cal_component_set_rrule_list (ECalComponent *comp,
+                               const GSList *recur_list)
 {
-       g_slist_foreach (attendee_list, (GFunc) g_free, NULL);
-       g_slist_free (attendee_list);
-}
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-
+       set_recur_list (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY, i_cal_property_new_rrule, recur_list);
+
+       priv->need_sequence_inc = TRUE;
+}
 
 /**
- * e_cal_component_has_alarms:
+ * e_cal_component_has_rrules:
  * @comp: A calendar component object.
  *
- * Checks whether the component has any alarms.
+ * Queries whether a calendar component object has any recurrence rules defined
+ * for it.
  *
- * Returns: TRUE if the component has any alarms.
+ * Returns: TRUE if the component has recurrence rules, FALSE otherwise.
  **/
 gboolean
-e_cal_component_has_alarms (ECalComponent *comp)
+e_cal_component_has_rrules (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-
-       g_return_val_if_fail (comp != NULL, FALSE);
        g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
-
-       return g_hash_table_size (priv->alarm_uid_hash) != 0;
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_RRULE_PROPERTY);
 }
 
 /**
- * e_cal_component_add_alarm:
- * @comp: A calendar component.
- * @alarm: An alarm.
+ * e_cal_component_has_recurrences:
+ * @comp: A calendar component object
  *
- * Adds an alarm subcomponent to a calendar component.  You should have created
- * the @alarm by using e_cal_component_alarm_new(); it is invalid to use a
- * #ECalComponentAlarm structure that came from e_cal_component_get_alarm().  After
- * adding the alarm, the @alarm structure is no longer valid because the
- * internal structures may change and you should get rid of it by using
- * e_cal_component_alarm_free().
+ * Queries whether a calendar component object has any recurrence dates or
+ * recurrence rules.
+ *
+ * Returns: TRUE if the component has recurrences, FALSE otherwise.
  **/
-void
-e_cal_component_add_alarm (ECalComponent *comp,
-                           ECalComponentAlarm *alarm)
+gboolean
+e_cal_component_has_recurrences (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
+       return e_cal_component_has_rdates (comp) || e_cal_component_has_rrules (comp);
+}
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (alarm != NULL);
+/* Counts the elements in the by_xxx fields of an ICalRecurrenceType;
+   it also frees the 'field' array*/
+static gint
+count_by_xxx (GArray *field) /* gshort */
+{
+       gint ii;
 
-       priv = comp->priv;
+       if (!field)
+               return 0
 
-       add_alarm (comp, alarm->icalcomp, icalproperty_get_x (alarm->uid));
-       icalcomponent_add_component (priv->icalcomp, alarm->icalcomp);
+       for (ii = 0; ii < field->len; ii++) {
+               if (g_array_index (field, gshort, ii) == I_CAL_RECURRENCE_ARRAY_MAX)
+                       break;
+       }
+
+       g_array_unref (array);
+
+       return i;
 }
 
 /**
- * e_cal_component_remove_alarm:
- * @comp: A calendar component.
- * @auid: UID of the alarm to remove.
+ * e_cal_component_has_simple_recurrence:
+ * @comp: A calendar component object.
  *
- * Removes an alarm subcomponent from a calendar component.  If the alarm that
- * corresponds to the specified @auid had been fetched with
- * e_cal_component_get_alarm(), then those alarm structures will be invalid; you
- * should get rid of them with e_cal_component_alarm_free() before using this
- * function.
- **/
-void
-e_cal_component_remove_alarm (ECalComponent *comp,
-                              const gchar *auid)
+ * Checks whether the given calendar component object has simple recurrence
+ * rules or more complicated ones.
+ *
+ * Returns: TRUE if it has a simple recurrence rule, FALSE otherwise.
+ */
+gboolean
+e_cal_component_has_simple_recurrence (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm;
+       GSList *rrule_list;
+       GArray *array;
+       ICalRecurrenceType *rt;
+       gint n_by_second, n_by_minute, n_by_hour;
+       gint n_by_day, n_by_month_day, n_by_year_day;
+       gint n_by_week_no, n_by_month, n_by_set_pos;
+       gint len, i;
+       gboolean simple = FALSE;
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
-       g_return_if_fail (auid != NULL);
+       if (!e_cal_component_has_recurrences (comp))
+               return TRUE;
+
+       rrule_list = e_cal_component_get_rrule_list (comp);
+       len = g_slist_length (rrule_list);
+       if (len > 1
+           || e_cal_component_has_rdates (comp)
+           || e_cal_component_has_exrules (comp))
+               goto cleanup;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       /* Down to one rule, so test that one */
+       rt = rrule_list->data;
 
-       alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid);
-       if (!alarm)
-               return;
+       /* Any funky frequency? */
+       if (i_cal_recurrence_type_get_freq (rt) == I_CAL_SECONDLY_RECURRENCE ||
+           i_cal_recurrence_type_get_freq (rt) == I_CAL_MINUTELY_RECURRENCE ||
+           i_cal_recurrence_type_get_freq (rt) == I_CAL_HOURLY_RECURRENCE)
+               goto cleanup;
 
-       g_hash_table_remove (priv->alarm_uid_hash, auid);
-       icalcomponent_remove_component (priv->icalcomp, alarm);
-       icalcomponent_free (alarm);
-}
+       /* Any funky BY_* */
+#define N_HAS_BY(field) (count_by_xxx (field, G_N_ELEMENTS (field)))
+
+       n_by_second = N_HAS_BY (i_cal_recurrence_type_get_by_second_array (rt));
+       n_by_minute = N_HAS_BY (i_cal_recurrence_type_get_by_minute_array (rt));
+       n_by_hour = N_HAS_BY (i_cal_recurrence_type_get_by_hour_array (rt));
+       n_by_day = N_HAS_BY (i_cal_recurrence_type_get_by_day_array (rt));
+       n_by_month_day = N_HAS_BY (i_cal_recurrence_type_get_by_month_day_array (rt));
+       n_by_year_day = N_HAS_BY (i_cal_recurrence_type_get_by_year_day_array (rt));
+       n_by_week_no = N_HAS_BY (i_cal_recurrence_type_get_by_week_no_array (rt));
+       n_by_month = N_HAS_BY (i_cal_recurrence_type_get_by_month_array (rt));
+       n_by_set_pos = N_HAS_BY (i_cal_recurrence_type_get_by_set_pos_array (rt));
+
+       if (n_by_second != 0
+           || n_by_minute != 0
+           || n_by_hour != 0)
+               goto cleanup;
+
+       switch (i_cal_recurrence_type_get_freq (rt)) {
+       case I_CAL_DAILY_RECURRENCE:
+               if (n_by_day != 0
+                   || n_by_month_day != 0
+                   || n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos != 0)
+                       goto cleanup;
+
+               simple = TRUE;
+               break;
+
+       case I_CAL_WEEKLY_RECURRENCE:
+               if (n_by_month_day != 0
+                   || n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos != 0)
+                       goto cleanup;
 
-static gboolean
-for_each_remove_all_alarms (gpointer key,
-                            gpointer value,
-                            gpointer data)
-{
-       ECalComponent *comp = E_CAL_COMPONENT (data);
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm = value;
+               array = i_cal_recurrence_type_get_by_day (rt);
+               for (i = 0; i < 8; i++) {
+                       gint pos;
+                       gshort byday = i_cal_recurrence_type_get_by_day (rt, i);
 
-       priv = comp->priv;
+                       if (byday == I_CAL_RECURRENCE_ARRAY_MAX)
+                               break;
 
-       icalcomponent_remove_component (priv->icalcomp, alarm);
-       icalcomponent_free (alarm);
+                       pos = i_cal_recurrence_type_day_position (byday);
 
-       return TRUE;
-}
+                       if (pos != 0) {
+                               g_array_unref (array);
+                               goto cleanup;
+                       }
+               }
 
-/**
- * e_cal_component_remove_all_alarms:
- * @comp: A calendar component
- *
- * Remove all alarms from the calendar component
- **/
-void
-e_cal_component_remove_all_alarms (ECalComponent *comp)
-{
-       ECalComponentPrivate *priv;
+               g_array_unref (array);
 
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+               simple = TRUE;
+               break;
 
-       priv = comp->priv;
-       g_return_if_fail (priv->icalcomp != NULL);
+       case I_CAL_MONTHLY_RECURRENCE:
+               if (n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos > 1)
+                       goto cleanup;
 
-       g_hash_table_foreach_remove (priv->alarm_uid_hash, for_each_remove_all_alarms, comp);
-}
+               if (n_by_month_day == 1) {
+                       gint nth;
 
-/* Scans an icalproperty from a calendar component and adds its mapping to our
- * own alarm structure.
- */
-static void
-scan_alarm_property (ECalComponentAlarm *alarm,
-                     icalproperty *prop)
-{
-       icalproperty_kind kind;
-       const gchar *xname;
+                       if (n_by_set_pos != 0)
+                               goto cleanup;
 
-       kind = icalproperty_isa (prop);
+                       nth = i_cal_recurrence_type_get_by_month_day (rt, 0);
+                       if (nth < 1 && nth != -1)
+                               goto cleanup;
 
-       switch (kind) {
-       case ICAL_ACTION_PROPERTY:
-               alarm->action = prop;
-               break;
+               } else if (n_by_day == 1) {
+                       ICalRecurrenceTypeWeekday weekday;
+                       gint pos;
 
-       case ICAL_ATTACH_PROPERTY:
-               /* FIXME: mail alarms may have any number of these, not just one */
-               alarm->attach = prop;
-               break;
+                       /* Outlook 2000 uses BYDAY=TU;BYSETPOS=2, and will not
+                        * accept BYDAY=2TU. So we now use the same as Outlook
+                        * by default. */
 
-       case ICAL_DESCRIPTION_PROPERTY:
-               alarm->description.prop = prop;
-               alarm->description.altrep_param = icalproperty_get_first_parameter (
-                       prop, ICAL_ALTREP_PARAMETER);
-               break;
+                       weekday = i_cal_recurrence_type_day_day_of_week (i_cal_recurrence_type_get_by_day 
(rt, 0));
+                       pos = i_cal_recurrence_type_day_position (i_cal_recurrence_type_get_by_day (rt, 0));
 
-       case ICAL_DURATION_PROPERTY:
-               alarm->duration = prop;
-               break;
+                       if (pos == 0) {
+                               if (n_by_set_pos != 1)
+                                       goto cleanup;
+                               pos = i_cal_recurrence_type_get_by_set_pos (rt, 0);
+                       } else if (pos < 0) {
+                               goto cleanup;
+                       }
 
-       case ICAL_REPEAT_PROPERTY:
-               alarm->repeat = prop;
-               break;
+                       switch (weekday) {
+                       case I_CAL_MONDAY_WEEKDAY:
+                       case I_CAL_TUESDAY_WEEKDAY:
+                       case I_CAL_WEDNESDAY_WEEKDAY:
+                       case I_CAL_THURSDAY_WEEKDAY:
+                       case I_CAL_FRIDAY_WEEKDAY:
+                       case I_CAL_SATURDAY_WEEKDAY:
+                       case I_CAL_SUNDAY_WEEKDAY:
+                               break;
 
-       case ICAL_TRIGGER_PROPERTY:
-               alarm->trigger = prop;
-               break;
+                       default:
+                               goto cleanup;
+                       }
+               } else {
+                       goto cleanup;
+               }
 
-       case ICAL_ATTENDEE_PROPERTY:
-               scan_attendee (&alarm->attendee_list, prop);
+               simple = TRUE;
                break;
 
-       case ICAL_X_PROPERTY:
-               xname = icalproperty_get_x_name (prop);
-               g_return_if_fail (xname != NULL);
-
-               if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0)
-                       alarm->uid = prop;
+       case I_CAL_YEARLY_RECURRENCE:
+               if (n_by_day != 0
+                   || n_by_month_day != 0
+                   || n_by_year_day != 0
+                   || n_by_week_no != 0
+                   || n_by_month != 0
+                   || n_by_set_pos != 0)
+                       goto cleanup;
 
+               simple = TRUE;
                break;
 
        default:
-               break;
+               goto cleanup;
        }
+
+ cleanup:
+       g_slist_free_full (rrule_list, g_object_unref);
+
+       return simple;
 }
 
-/* Creates a ECalComponentAlarm from a libical alarm subcomponent */
-static ECalComponentAlarm *
-make_alarm (icalcomponent *subcomp)
+/**
+ * e_cal_component_is_instance:
+ * @comp: A calendar component object.
+ *
+ * Checks whether a calendar component object is an instance of a recurring
+ * event.
+ *
+ * Returns: TRUE if it is an instance, FALSE if not.
+ */
+gboolean
+e_cal_component_is_instance (ECalComponent *comp)
 {
-       ECalComponentAlarm *alarm;
-       icalproperty *prop;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+
+       return return ecc_property_exists (comp->priv->icalcomp, I_CAL_RECURRENCEID_PROPERTY);
+}
 
-       alarm = g_new (ECalComponentAlarm, 1);
+/**
+ * e_cal_component_get_sequence:
+ * @comp: A calendar component object.
+ *
+ * Queries the sequence number of a calendar component object.
+ *
+ * Returns: the sequence number, or -1 if not found
+ **/
+gint
+e_cal_component_get_sequence (ECalComponent *comp)
+{
+       ICalProperty *prop;
+       gint sequence;
 
-       alarm->icalcomp = subcomp;
-       alarm->uid = NULL;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), -1);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, -1);
 
-       alarm->action = NULL;
-       alarm->attach = NULL;
-       alarm->description.prop = NULL;
-       alarm->description.altrep_param = NULL;
-       alarm->duration = NULL;
-       alarm->repeat = NULL;
-       alarm->trigger = NULL;
-       alarm->attendee_list = NULL;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SEQUENCE_PROPERTY);
+       if (!prop)
+               return -1;
 
-       for (prop = icalcomponent_get_first_property (subcomp, ICAL_ANY_PROPERTY);
-            prop;
-            prop = icalcomponent_get_next_property (subcomp, ICAL_ANY_PROPERTY))
-               scan_alarm_property (alarm, prop);
+       sequence = i_cal_property_get_sequence (prop);
 
-       g_return_val_if_fail (alarm->uid != NULL, NULL);
+       g_object_unref (prop);
 
-       return alarm;
+       return sequence;
 }
 
 /**
- * e_cal_component_get_alarm_uids:
- * @comp: A calendar component.
+ * e_cal_component_set_sequence:
+ * @comp: A calendar component object.
+ * @sequence: a sequence number to set, or -1 to remove the property
  *
- * Builds a list of the unique identifiers of the alarm subcomponents inside a
- * calendar component.
+ * Sets the sequence number of a calendar component object.
+ * A special value -1 can be used to remove the sequence number property.
  *
- * Returns: (element-type utf8) (transfer full): List of unique identifiers for
- * alarms.  This should be freed using cal_obj_uid_list_free().
+ * Normally this function should not be called, since the sequence number
+ * is incremented automatically at the proper times.
  **/
-GList *
-e_cal_component_get_alarm_uids (ECalComponent *comp)
+void
+e_cal_component_set_sequence (ECalComponent *comp,
+                             gint sequence)
 {
-       ECalComponentPrivate *priv;
-       icalcompiter iter;
-       GList *l;
-
-       g_return_val_if_fail (comp != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
-
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
-       l = NULL;
-       for (iter = icalcomponent_begin_component (priv->icalcomp, ICAL_VALARM_COMPONENT);
-            icalcompiter_deref (&iter) != NULL;
-            icalcompiter_next (&iter)) {
-               icalcomponent *subcomp;
-               icalproperty *prop;
-
-               subcomp = icalcompiter_deref (&iter);
-               for (prop = icalcomponent_get_first_property (subcomp, ICAL_X_PROPERTY);
-                    prop;
-                    prop = icalcomponent_get_next_property (subcomp, ICAL_X_PROPERTY)) {
-                       const gchar *xname;
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-                       xname = icalproperty_get_x_name (prop);
-                       g_return_val_if_fail (xname != NULL, NULL);
+       comp->priv->need_sequence_inc = FALSE;
 
-                       if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0) {
-                               const gchar *auid;
+       if (sequence <= -1) {
+               ICalProperty *prop;
 
-                               auid = alarm_uid_from_prop (prop);
-                               l = g_list_append (l, g_strdup (auid));
-                       }
+               prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SEQUENCE_PROPERTY);
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
                }
+
+               return;
        }
 
-       return l;
+       i_cal_component_set_sequence (comp->priv->icalcomp, sequence);
 }
 
 /**
- * e_cal_component_get_alarm:
- * @comp: A calendar component.
- * @auid: Unique identifier for the sought alarm subcomponent.
+ * e_cal_component_get_status:
+ * @comp: A calendar component object.
  *
- * Queries a particular alarm subcomponent of a calendar component.
+ * Queries the status property of a calendar component object.
  *
- * Returns: The alarm subcomponent that corresponds to the specified @auid,
- * or %NULL if no alarm exists with that UID.  This should be freed using
- * e_cal_component_alarm_free().
+ * Returns: the status value; or %I_CAL_STATUS_NONE, if the component
+ *   has no status property
  **/
-ECalComponentAlarm *
-e_cal_component_get_alarm (ECalComponent *comp,
-                           const gchar *auid)
+ICalPropertyStatus
+e_cal_component_get_status (ECalComponent *comp)
 {
-       ECalComponentPrivate *priv;
-       icalcomponent *alarm;
+       ICalProperty *prop;
+       ICalPropertyStatus status;
 
-       g_return_val_if_fail (comp != NULL, NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), I_CAL_STATUS_NONE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, I_CAL_STATUS_NONE);
 
-       priv = comp->priv;
-       g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+       prop = i_cal_component_get_fist_property (comp->priv->icalcomp, I_CAL_STATUS_PROPERTY);
 
-       g_return_val_if_fail (auid != NULL, NULL);
+       if (!prop)
+               return I_CAL_STATUS_NONE;
 
-       alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid);
+       status = i_cal_property_get_status (prop);
 
-       if (alarm)
-               return make_alarm (alarm);
-       else
-               return NULL;
+       g_object_unref (prop);
+
+       return status;
 }
 
 /**
- * e_cal_component_alarms_free:
- * @alarms: Component alarms structure.
+ * e_cal_component_set_status:
+ * @comp: A calendar component object.
+ * @status: Status value, as an #ICalPropertyStatus. Use %I_CAL_STATUS_NONE, to unset the property
  *
- * Frees a #ECalComponentAlarms structure.
+ * Sets the status property of a calendar component object.
  **/
 void
-e_cal_component_alarms_free (ECalComponentAlarms *alarms)
+e_cal_component_set_status (ECalComponent *comp,
+                           ICalPropertyStatus status)
 {
-       GSList *l;
+       ICalProperty *prop;
 
-       g_return_if_fail (alarms != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       comp->priv->need_sequence_inc = TRUE;
 
-       if (alarms->comp != NULL)
-               g_object_unref (alarms->comp);
+       prop = i_cal_component_get_fist_property (comp->priv->icalcomp, I_CAL_STATUS_PROPERTY);
 
-       for (l = alarms->alarms; l; l = l->next) {
-               ECalComponentAlarmInstance *instance = l->data;
+       if (status == I_CAL_STATUS_NONE) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-               if (instance != NULL) {
-                       g_free (instance->auid);
-                       g_free (instance);
-               } else
-                       g_warn_if_reached ();
+               return;
        }
 
-       g_slist_free (alarms->alarms);
-       g_free (alarms);
+       if (prop) {
+               i_cal_property_set_status (prop, status);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_status (status);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
 }
 
 /**
- * e_cal_component_alarm_new:
+ * e_cal_component_get_summary:
+ * @comp: A calendar component object.
  *
- * Create a new alarm object.
+ * Queries the summary of a calendar component object.
+ * Free the returned pointer withe_cal_component_text_free(),
+ * when no longer needed.
  *
- * Returns: a new alarm component
+ * Returns: (transfer full) (nullable): the summary, as an #ECalComponentText,
+ *    or %NULL, when none is set
  **/
-ECalComponentAlarm *
-e_cal_component_alarm_new (void)
+ECalComponentText *
+e_cal_component_get_summary (ECalComponent *comp)
 {
-       ECalComponentAlarm *alarm;
-       gchar *new_auid;
+       ECalComponentText *text;
+       ICalProperty *prop;
 
-       alarm = g_new (ECalComponentAlarm, 1);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_val_if_fail (comp->priv->icalcomp != NULL);
 
-       alarm->icalcomp = icalcomponent_new (ICAL_VALARM_COMPONENT);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SUMMARY_PROPERTY);
+       if (!prop)
+               return NULL;
 
-       new_auid = e_util_generate_uid ();
-       alarm->uid = icalproperty_new_x (new_auid);
-       icalproperty_set_x_name (alarm->uid, EVOLUTION_ALARM_UID_PROPERTY);
-       icalcomponent_add_property (alarm->icalcomp, alarm->uid);
-       g_free (new_auid);
+       text = get_text_from_prop (prop, i_cal_property_get_summary);
 
-       alarm->action = NULL;
-       alarm->attach = NULL;
-       alarm->description.prop = NULL;
-       alarm->description.altrep_param = NULL;
-       alarm->duration = NULL;
-       alarm->repeat = NULL;
-       alarm->trigger = NULL;
-       alarm->attendee_list = NULL;
+       g_object_unref (prop);
 
-       return alarm;
+       return text;
 }
 
-/**
- * e_cal_component_alarm_clone:
- * @alarm: An alarm subcomponent.
- *
- * Creates a new alarm subcomponent by copying the information from another one.
- *
- * Returns: A newly-created alarm subcomponent with the same values as the
- * original one.  Should be freed with e_cal_component_alarm_free().
- **/
-ECalComponentAlarm *
-e_cal_component_alarm_clone (ECalComponentAlarm *alarm)
+typedef struct {
+       gchar *old_summary;
+       const gchar *new_summary;
+} SetAlarmDescriptionData;
+
+static void
+set_alarm_description_cb (gpointer key,
+                          gpointer value,
+                          gpointer user_data)
 {
-       icalcomponent *icalcomp;
+       ICalComponent *alarm;
+       ICalProperty *icalprop, *desc_prop;
+       SetAlarmDescriptionData *sadd;
+       gboolean changed = FALSE;
+       const gchar *old_summary = NULL;
+
+       alarm = value;
+       sadd = user_data;
+
+       /* set the new description on the alarm */
+       desc_prop = i_cal_component_get_first_property (alarm, I_CAL_DESCRIPTION_PROPERTY);
+       if (desc_prop) {
+               old_summary = i_cal_property_get_description (desc_prop);
+       } else {
+               desc_prop = i_cal_property_new_description (sadd->new_summary);
+       }
+
+       /* remove the X-EVOLUTION-NEEDS_DESCRIPTION property */
+       icalprop = i_cal_component_get_first_property (alarm, I_CAL_X_PROPERTY);
+       while (icalprop) {
+               const gchar *x_name;
+
+               x_name = i_cal_property_get_x_name (icalprop);
+               if (!g_strcmp0 (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
+                       i_cal_component_remove_property (alarm, icalprop);
+                       g_object_unref (icalprop);
+
+                       i_cal_property_set_description (desc_prop, sadd->new_summary);
+                       changed = TRUE;
+                       break;
+               }
+
+               g_object_unref (icalprop);
+               icalprop = i_cal_component_get_next_property (alarm, I_CAL_X_PROPERTY);
+       }
 
-       g_return_val_if_fail (alarm != NULL, NULL);
+       if (!changed) {
+               if (!g_strcmp0 (old_summary ? old_summary : "", sadd->old_summary ? sadd->old_summary : "")) {
+                       i_cal_property_set_description (desc_prop, sadd->new_summary);
+               }
+       }
 
-       icalcomp = icalcomponent_new_clone (alarm->icalcomp);
-       return make_alarm (icalcomp);
+       g_object_unref (desc_prop);
 }
 
 /**
- * e_cal_component_alarm_free:
- * @alarm: A calendar alarm.
+ * e_cal_component_set_summary:
+ * @comp: A calendar component object.
+ * @summary: Summary property and its parameters.
  *
- * Frees an alarm structure.
+ * Sets the summary of a calendar component object.
  **/
 void
-e_cal_component_alarm_free (ECalComponentAlarm *alarm)
+e_cal_component_set_summary (ECalComponent *comp,
+                            const ECalComponentText *summary)
 {
-       GSList *l;
+       ICalProperty *prop;
+       SetAlarmDescriptionData sadd;
 
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       if (icalcomponent_get_parent (alarm->icalcomp) == NULL)
-               icalcomponent_free (alarm->icalcomp);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_SUMMARY_PROPERTY);
 
-       alarm->icalcomp = NULL;
-       alarm->uid = NULL;
-       alarm->action = NULL;
-       alarm->attach = NULL;
-       alarm->description.prop = NULL;
-       alarm->description.altrep_param = NULL;
-       alarm->duration = NULL;
-       alarm->repeat = NULL;
-       alarm->trigger = NULL;
+       if (!summary) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       for (l = alarm->attendee_list; l != NULL; l = l->next)
-               g_free (l->data);
-       g_slist_free (alarm->attendee_list);
-       alarm->attendee_list = NULL;
+               return;
+       }
 
-       g_free (alarm);
-}
+       if (!e_cal_component_text_get_value (summary)) {
+               g_clear_object (&prop);
+               return;
+       }
 
-/**
- * e_cal_component_alarm_get_uid:
- * @alarm: An alarm subcomponent.
- *
- * Queries the unique identifier of an alarm subcomponent.
- *
- * Returns: UID of the alarm.
- **/
-const gchar *
-e_cal_component_alarm_get_uid (ECalComponentAlarm *alarm)
-{
-       g_return_val_if_fail (alarm != NULL, NULL);
+       if (prop) {
+               /* Make a copy, to avoid use-after-free */
+               sadd.old_summary = g_strdup (i_cal_property_get_summary (prop));
+               i_cal_property_set_summary (prop, (gchar *) e_cal_component_text_get_value (summary));
+               set_text_altrep_on_prop (prop, summary);
+       } else {
+               sadd.old_summary = NULL;
+               prop = i_cal_property_new_summary ((gchar *) e_cal_component_text_get_value (summary));
+               set_text_altrep_on_prop (prop, summary);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+               prop = NULL;
+       }
 
-       return alarm_uid_from_prop (alarm->uid);
+       g_clear_object (&prop);
+
+       /* look for alarms that need a description */
+       sadd.new_summary = e_cal_component_text_get_value (summary);
+       g_hash_table_foreach (comp->priv->alarm_uid_hash, set_alarm_description_cb, &sadd);
+
+       g_free (sadd.old_summary);
 }
 
 /**
- * e_cal_component_alarm_get_action:
- * @alarm: An alarm.
- * @action: (out): Return value for the alarm's action type.
+ * e_cal_component_get_transparency:
+ * @comp: A calendar component object.
+ *
+ * Queries the time transparency of a calendar component object.
  *
- * Queries the action type of an alarm.
+ * Returns: the time transparency, as an #ECalComponentTransparency;
+ *    value #E_CAL_COMPONENT_TRANSP_NONE is returned when none is set
  **/
-void
-e_cal_component_alarm_get_action (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmAction *action)
+ECalComponentTransparency
+e_cal_component_get_transparency (ECalComponent *comp)
 {
-       enum icalproperty_action ipa;
-
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (action != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       ECalComponentTransparency transp;
+       ICalProperty *prop;
 
-       if (!alarm->action) {
-               *action = E_CAL_COMPONENT_ALARM_NONE;
-               return;
-       }
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp), E_CAL_COMPONENT_TRANSP_NONE);
+       g_return_if_fail (comp->priv->icalcomp != NULL, E_CAL_COMPONENT_TRANSP_NONE);
 
-       ipa = icalproperty_get_action (alarm->action);
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_TRANSP_PROPERTY);
 
-       switch (ipa) {
-       case ICAL_ACTION_AUDIO:
-               *action = E_CAL_COMPONENT_ALARM_AUDIO;
-               break;
+       if (!prop)
+               return E_CAL_COMPONENT_TRANSP_NONE;
 
-       case ICAL_ACTION_DISPLAY:
-               *action = E_CAL_COMPONENT_ALARM_DISPLAY;
+       switch (i_cal_property_get_transp (prop)) {
+       case I_CAL_TRANSP_TRANSPARENT:
+       case I_CAL_TRANSP_TRANSPARENTNOCONFLICT:
+               transp = E_CAL_COMPONENT_TRANSP_TRANSPARENT;
                break;
 
-       case ICAL_ACTION_EMAIL:
-               *action = E_CAL_COMPONENT_ALARM_EMAIL;
+       case I_CAL_TRANSP_OPAQUE:
+       case I_CAL_TRANSP_OPAQUENOCONFLICT:
+               transp = E_CAL_COMPONENT_TRANSP_OPAQUE;
                break;
 
-       case ICAL_ACTION_PROCEDURE:
-               *action = E_CAL_COMPONENT_ALARM_PROCEDURE;
+       default:
+               transp = E_CAL_COMPONENT_TRANSP_UNKNOWN;
                break;
+       }
 
-       case ICAL_ACTION_NONE:
-               *action = E_CAL_COMPONENT_ALARM_NONE;
-               break;
+       g_object_unref (prop);
 
-       default:
-               *action = E_CAL_COMPONENT_ALARM_UNKNOWN;
-       }
+       return transp;
 }
 
 /**
- * e_cal_component_alarm_set_action:
- * @alarm: An alarm.
- * @action: Action type.
+ * e_cal_component_set_transparency:
+ * @comp: A calendar component object.
+ * @transp: Time transparency value.
  *
- * Sets the action type for an alarm.
+ * Sets the time transparency of a calendar component object.
+ * Use %E_CAL_COMPONENT_TRANSP_NONE to unset the property.
  **/
 void
-e_cal_component_alarm_set_action (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmAction action)
+e_cal_component_set_transparency (ECalComponent *comp,
+                                  ECalComponentTransparency transp)
 {
-       enum icalproperty_action ipa;
+       ICalProperty *prop;
+       ICalPropertyTransp ical_transp;
 
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (action != E_CAL_COMPONENT_ALARM_NONE);
-       g_return_if_fail (action != E_CAL_COMPONENT_ALARM_UNKNOWN);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (transp != E_CAL_COMPONENT_TRANSP_UNKNOWN);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       switch (action) {
-       case E_CAL_COMPONENT_ALARM_AUDIO:
-               ipa = ICAL_ACTION_AUDIO;
-               break;
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_TRANSP_PROPERTY);
+
+       if (transp == E_CAL_COMPONENT_TRANSP_NONE) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       case E_CAL_COMPONENT_ALARM_DISPLAY:
-               ipa = ICAL_ACTION_DISPLAY;
-               break;
+               return;
+       }
 
-       case E_CAL_COMPONENT_ALARM_EMAIL:
-               ipa = ICAL_ACTION_EMAIL;
+       switch (transp) {
+       case E_CAL_COMPONENT_TRANSP_TRANSPARENT:
+               ical_transp = I_CAL_TRANSP_TRANSPARENT;
                break;
 
-       case E_CAL_COMPONENT_ALARM_PROCEDURE:
-               ipa = ICAL_ACTION_PROCEDURE;
+       case E_CAL_COMPONENT_TRANSP_OPAQUE:
+               ical_transp = I_CAL_TRANSP_OPAQUE;
                break;
 
        default:
                g_warn_if_reached ();
-               ipa = ICAL_ACTION_NONE;
+               ical_transp = I_CAL_TRANSP_NONE;
+               break;
        }
 
-       if (alarm->action)
-               icalproperty_set_action (alarm->action, ipa);
-       else {
-               alarm->action = icalproperty_new_action (ipa);
-               icalcomponent_add_property (alarm->icalcomp, alarm->action);
+       if (prop) {
+               i_cal_property_set_transp (prop, ical_transp);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_transp (ical_transp);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
 /**
- * e_cal_component_alarm_get_attach:
- * @alarm: An alarm.
- * @attach: (out): Return value for the attachment; should be freed using icalattach_unref().
+ * e_cal_component_get_url:
+ * @comp: A calendar component object.
+ *
+ * Queries the uniform resource locator property of a calendar component object.
+ * Free the returned URL with g_free(), when no longer needed.
  *
- * Queries the attachment property of an alarm.
+ * Returns: (transfer full) (nullable): the URL, or %NULL, when none is set
  **/
-void
-e_cal_component_alarm_get_attach (ECalComponentAlarm *alarm,
-                                  icalattach **attach)
+gchar *
+e_cal_component_get_url (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (attach != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       ICalProperty *prop;
+       gchar *url;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_URL_PROPERTY);
+       if (!prop)
+               return NULL;
+
+       url = g_strdup (i_cal_property_get_url (prop));
 
-       if (alarm->attach) {
-               *attach = icalproperty_get_attach (alarm->attach);
-               icalattach_ref (*attach);
-       } else
-               *attach = NULL;
+       g_object_unref (prop);
+
+       return url;
 }
 
 /**
- * e_cal_component_alarm_set_attach:
- * @alarm: An alarm.
- * @attach: Attachment property or NULL to remove an existing property.
+ * e_cal_component_set_url:
+ * @comp: A calendar component object.
+ * @url: (nullable): URL value.
  *
- * Sets the attachment property of an alarm.
+ * Sets the uniform resource locator property of a calendar component object.
+ * A %NULL or an empty string removes the property.
  **/
 void
-e_cal_component_alarm_set_attach (ECalComponentAlarm *alarm,
-                                  icalattach *attach)
+e_cal_component_set_url (ECalComponent *comp,
+                         const gchar *url)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       ICalProperty *prop;
+
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_URL_PROPERTY);
+
+       if (!url || !(*url)) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-       if (alarm->attach) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->attach);
-               icalproperty_free (alarm->attach);
-               alarm->attach = NULL;
+               return;
        }
 
-       if (attach) {
-               alarm->attach = icalproperty_new_attach (attach);
-               icalcomponent_add_property (alarm->icalcomp, alarm->attach);
+       if (prop) {
+               i_cal_property_set_url (prop, (gchar *) url);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_url ((gchar *) url);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
+static gboolean
+get_attendee_list_cb (ICalComponent *icalcomp,
+                     ICalProperty *prop,
+                     gpointer user_data)
+{
+       GSList **pattendees = user_data;
+       ECalComponentAttendee *attendee;
+
+       g_return_val_if_fail (pattendees != NULL, FALSE);
+
+       attendee = e_cal_component_attendee_new_from_property (prop);
+
+       if (attendee)
+               *pattendees = g_slist_prepend (*pattendees, attendee);
+
+       return TRUE;
+}
+
 /**
- * e_cal_component_alarm_get_description:
- * @alarm: An alarm.
- * @description: (out): Return value for the description property and its parameters.
+ * e_cal_component_get_attendee_list:
+ * @comp: A calendar component object.
+ *
+ * Queries the attendee properties of the calendar component object.
+ * Free the returned #GSList with g_slist_free_full (slist, e_cal_component_attendee_free);,
+ * when no longer needed.
  *
- * Queries the description property of an alarm.
+ * Returns: (transfer full) (nullable) (element-type ECalComponentAttendee):
+ *    the attendees, as a #GSList of an #ECalComponentAttendee, or %NULL,
+ *    when none are set
  **/
-void
-e_cal_component_alarm_get_description (ECalComponentAlarm *alarm,
-                                       ECalComponentText *description)
+GSList *
+e_cal_component_get_attendee_list (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (description != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       GSList *attendees = NULL;
 
-       if (alarm->description.prop)
-               description->value = icalproperty_get_description (alarm->description.prop);
-       else
-               description->value = NULL;
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_val_if_fail (comp->priv->icalcomp != NULL);
 
-       if (alarm->description.altrep_param)
-               description->altrep = icalparameter_get_altrep (alarm->description.altrep_param);
-       else
-               description->altrep = NULL;
+       foreach_property (comp->priv->icalcomp, I_CAL_ATTENDEE_PROPERTY,
+               get_attendee_list_cb, &attendees);
+
+       return g_slist_reverse (attendees);
 }
 
 /**
- * e_cal_component_alarm_set_description:
- * @alarm: An alarm.
- * @description: Description property and its parameters, or NULL for no description.
+ * e_cal_component_set_attendee_list:
+ * @comp: A calendar component object.
+ * @attendee_list: (nullable) (element-type ECalComponentAttendee): Values for attendee
+ *    properties, or %NULL to unset
  *
- * Sets the description property of an alarm.
+ * Sets the attendees of a calendar component object
  **/
 void
-e_cal_component_alarm_set_description (ECalComponentAlarm *alarm,
-                                       ECalComponentText *description)
+e_cal_component_set_attendee_list (ECalComponent *comp,
+                                  const GSList *attendee_list)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
+       GSList *link;
 
-       if (alarm->description.prop) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->description.prop);
-               icalproperty_free (alarm->description.prop);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-               alarm->description.prop = NULL;
-               alarm->description.altrep_param = NULL;
-       }
+       remove_all_properties_of_kind (comp->priv->icalcomp, I_CAL_ATTENDEE_PROPERTY);
 
-       if (!description)
-               return;
+       for (link = (GSList *) attendee_list; link; link = g_slist_next (link)) {
+               const ECalComponentAttendee *attendee = link->data;
+               ICalProperty *prop;
 
-       g_return_if_fail (description->value != NULL);
+               if (!attendee)
+                       continue;
 
-       alarm->description.prop = icalproperty_new_description (description->value);
-       icalcomponent_add_property (alarm->icalcomp, alarm->description.prop);
+               prop = e_cal_component_attendee_get_as_property (attendee);
+               if (!prop)
+                       continue;
 
-       if (description->altrep) {
-               alarm->description.altrep_param = icalparameter_new_altrep (
-                       (gchar *) description->altrep);
-               icalproperty_add_parameter (
-                       alarm->description.prop,
-                       alarm->description.altrep_param);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
        }
 }
 
 /**
- * e_cal_component_alarm_get_repeat:
- * @alarm: An alarm.
- * @repeat: (out): Return value for the repeat/duration properties.
+ * e_cal_component_has_attendees:
+ * @comp: A calendar component object.
  *
- * Queries the repeat/duration properties of an alarm.
- **/
-void
-e_cal_component_alarm_get_repeat (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmRepeat *repeat)
+ * Queries a calendar component object for the existence of attendees.
+ *
+ * Returns: TRUE if there are attendees, FALSE if not.
+ */
+gboolean
+e_cal_component_has_attendees (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (repeat != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       if (!(alarm->repeat && alarm->duration)) {
-               repeat->repetitions = 0;
-               memset (&repeat->duration, 0, sizeof (repeat->duration));
-               return;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
 
-       repeat->repetitions = icalproperty_get_repeat (alarm->repeat);
-       repeat->duration = icalproperty_get_duration (alarm->duration);
+       return ecc_property_exists (comp->priv->icalcomp, I_CAL_ATTENDEE_PROPERTY);
 }
 
 /**
- * e_cal_component_alarm_set_repeat:
- * @alarm: An alarm.
- * @repeat: Repeat/duration values.  To remove any repetitions from the alarm,
- * set the @repeat.repetitions to 0.
+ * e_cal_component_get_location:
+ * @comp: A calendar component object
  *
- * Sets the repeat/duration values for an alarm.
+ * Queries the location property of a calendar component object.
+ *
+ * Returns: (transfer full) (nullable): the locatio, or %NULL, if none is set
  **/
-void
-e_cal_component_alarm_set_repeat (ECalComponentAlarm *alarm,
-                                  ECalComponentAlarmRepeat repeat)
+gchar *
+e_cal_component_get_location (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (repeat.repetitions >= 0);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       /* Delete old properties */
+       ICalProperty *prop;
+       gchar *location;
 
-       if (alarm->repeat) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->repeat);
-               icalproperty_free (alarm->repeat);
-               alarm->repeat = NULL;
-       }
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
 
-       if (alarm->duration) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->duration);
-               icalproperty_free (alarm->duration);
-               alarm->duration = NULL;
-       }
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_LOCATION_PROPERTY);
 
-       /* Set the new properties */
+       if (!prop)
+               return NULL;
 
-       if (repeat.repetitions == 0)
-               return; /* For zero extra repetitions the properties should not exist */
+       location = g_strdup (i_cal_property_get_location (prop);
 
-       alarm->repeat = icalproperty_new_repeat (repeat.repetitions);
-       icalcomponent_add_property (alarm->icalcomp, alarm->repeat);
+       g_object_unref (prop);
 
-       alarm->duration = icalproperty_new_duration (repeat.duration);
-       icalcomponent_add_property (alarm->icalcomp, alarm->duration);
+       return location;
 }
 
 /**
- * e_cal_component_alarm_get_trigger:
- * @alarm: An alarm.
- * @trigger: (out): Return value for the trigger time.
+ * e_cal_component_set_location:
+ * @comp: A calendar component object.
+ * @location: (nullable): Location value. Use %NULL or empty string, to unset the property.
  *
- * Queries the trigger time for an alarm.
+ * Sets the location property of a calendar component object.
  **/
 void
-e_cal_component_alarm_get_trigger (ECalComponentAlarm *alarm,
-                                   ECalComponentAlarmTrigger *trigger)
+e_cal_component_set_location (ECalComponent *comp,
+                              const gchar *location)
 {
-       icalparameter *param;
-       struct icaltriggertype t;
-       gboolean relative;
+       ICalProperty *prop;
 
-       g_return_if_fail (alarm != NULL);
-       g_return_if_fail (trigger != NULL);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       if (!alarm->trigger) {
-               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_NONE;
-               return;
-       }
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       /* Get trigger type */
+       prop = i_cal_component_get_first_property (comp->priv->icalcomp, I_CAL_LOCATION_PROPERTY);
 
-       param = icalproperty_get_first_parameter (alarm->trigger, ICAL_VALUE_PARAMETER);
-       if (param) {
-               icalparameter_value value;
+       if (!location || !*location) {
+               if (prop) {
+                       i_cal_component_remove_property (comp->priv->icalcomp, prop);
+                       g_object_unref (prop);
+               }
 
-               value = icalparameter_get_value (param);
+               return;
+       }
 
-               switch (value) {
-               case ICAL_VALUE_DURATION:
-                       relative = TRUE;
-                       break;
+       if (prop) {
+               i_cal_property_set_location (prop, (gchar *) location);
+               g_object_unref (prop);
+       } else {
+               prop = i_cal_property_new_location ((gchar *) location);
+               i_cal_component_take_property (comp->priv->icalcomp, prop);
+       }
+}
 
-               case ICAL_VALUE_DATETIME:
-                       relative = FALSE;
-                       break;
+/**
+ * e_cal_component_has_alarms:
+ * @comp: A calendar component object.
+ *
+ * Checks whether the component has any alarms.
+ *
+ * Returns: TRUE if the component has any alarms.
+ **/
+gboolean
+e_cal_component_has_alarms (ECalComponent *comp)
+{
+       ICalComponent *subcomp;
 
-               default:
-                       g_message (
-                               "e_cal_component_alarm_get_trigger(): "
-                               "Unknown value for trigger "
-                               "value %d; using RELATIVE", value);
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), FALSE);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, FALSE);
 
-                       relative = TRUE;
-                       break;
-               }
-       } else
-               relative = TRUE;
+       subcomp = i_cal_component_get_first_component (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT);
+       if (subcomp) {
+               g_object_unref (subcomp);
+               return TRUE;
+       }
 
-       /* Get trigger value and the RELATED parameter */
+       return FALSE;
+}
 
-       t = icalproperty_get_trigger (alarm->trigger);
+static gchar *
+dup_alarm_uid_from_component (ICalComponent *valarm)
+{
+       ICalProperty *prop;
+       gchar *auid = NULL;
 
-       if (relative) {
-               trigger->u.rel_duration = t.duration;
+       g_return_val_if_fail (valarm != NULL, NULL);
 
-               param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER);
-               if (param) {
-                       icalparameter_related rel;
+       for (prop = i_cal_component_get_first_property (valarm, I_CAL_X_PROPERTY);
+            prop;
+            g_object_unref (prop), prop = i_cal_component_get_next_property (valarm, I_CAL_X_PROPERTY)) {
+               const gchar *xname;
 
-                       rel = icalparameter_get_related (param);
+               xname = i_cal_property_get_x_name (prop);
 
-                       switch (rel) {
-                       case ICAL_RELATED_START:
-                               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
-                               break;
+               if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
+                       const gchar *xvalue;
 
-                       case ICAL_RELATED_END:
-                               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END;
+                       xvalue = i_cal_property_get_x (prop);
+                       if (xvalue) {
+                               auid = g_strdup (xvalue);
+                               g_object_unref (prop);
                                break;
-
-                       default:
-                               g_return_if_reached ();
                        }
-               } else
-                       trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
-       } else {
-               trigger->u.abs_time = t.time;
-               trigger->type = E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE;
+               }
        }
+
+       return auid;
 }
 
 /**
- * e_cal_component_alarm_set_trigger:
- * @alarm: An alarm.
- * @trigger: Trigger time structure.
+ * e_cal_component_add_alarm:
+ * @comp: A calendar component.
+ * @alarm: (transfer none): an alarm, as an #ECalComponentAlarm
  *
- * Sets the trigger time of an alarm.
+ * Adds an alarm subcomponent to a calendar component.  You should have created
+ * the @alarm by using e_cal_component_alarm_new(); it is invalid to use a
+ * #ECalComponentAlarm structure that came from e_cal_component_get_alarm().  After
+ * adding the alarm, the @alarm structure is no longer valid because the
+ * internal structures may change and you should get rid of it by using
+ * e_cal_component_alarm_free().
  **/
 void
-e_cal_component_alarm_set_trigger (ECalComponentAlarm *alarm,
-                                   ECalComponentAlarmTrigger trigger)
+e_cal_component_add_alarm (ECalComponent *comp,
+                          ECalComponentAlarm *alarm)
 {
-       struct icaltriggertype t;
-       icalparameter *param;
-       icalparameter_value value_type;
-       icalparameter_related related;
+       GSList *existing_uids, *link;
+       ICalComponent *valarm;
+       const gchar *auid;
 
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
        g_return_if_fail (alarm != NULL);
-       g_return_if_fail (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_NONE);
-       g_return_if_fail (alarm->icalcomp != NULL);
-
-       /* Delete old trigger */
+       g_return_if_fail (comp->priv->icalcomp);
 
-       if (alarm->trigger) {
-               icalcomponent_remove_property (alarm->icalcomp, alarm->trigger);
-               icalproperty_free (alarm->trigger);
-               alarm->trigger = NULL;
-       }
-
-       /* Set the value */
+       auid = e_cal_component_alarm_get_uid (alarm);
 
-       related = ICAL_RELATED_START; /* Keep GCC happy */
+       existing_uids = e_cal_component_get_alarm_uids (comp);
 
-       t.time = icaltime_null_time ();
-       t.duration = icaldurationtype_null_duration ();
-       switch (trigger.type) {
-       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
-               t.duration = trigger.u.rel_duration;
-               value_type = ICAL_VALUE_DURATION;
-               related = ICAL_RELATED_START;
-               break;
+       for (link = existing_uids; link; link = g_slist_next (link)) {
+               const gchar *existing_auid = link->data;
 
-       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
-               t.duration = trigger.u.rel_duration;
-               value_type = ICAL_VALUE_DURATION;
-               related = ICAL_RELATED_END;
-               break;
+               if (g_strcmp0 (auid, exisitng_auid) == 0)
+                       break;
+       }
 
-       case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
-               t.time = trigger.u.abs_time;
-               value_type = ICAL_VALUE_DATETIME;
-               break;
+       g_slist_free_full (existing_uids, g_free);
 
-       default:
-               g_return_if_reached ();
+       /* Not NULL, when found an alarm with the same UID */
+       if (link) {
+               /* This generates new UID for the alarm */
+               e_cal_component_alarm_set_uid (alarm, NULL);
        }
 
-       alarm->trigger = icalproperty_new_trigger (t);
-       icalcomponent_add_property (alarm->icalcomp, alarm->trigger);
+       valarm = e_cal_component_alarm_get_as_component (alarm);
+       if (valarm)
+               i_cal_component_take_component (comp->priv->icalcomp, valarm);
+}
 
-       /* Value parameters */
+static gboolean
+remove_alarm_cb (ICalComponent *icalcomp,
+                ICalComponent *subcomp,
+                gpointer user_data)
+{
+       const gchar *auid = user_data;
+       gchar *existing;
 
-       param = icalproperty_get_first_parameter (alarm->trigger, ICAL_VALUE_PARAMETER);
-       if (param)
-               icalparameter_set_value (param, value_type);
-       else {
-               param = icalparameter_new_value (value_type);
-               icalproperty_add_parameter (alarm->trigger, param);
-       }
+       g_return_val_if_fail (auid != NULL, FALSE);
 
-       /* Related parameter */
+       existing = dup_alarm_uid_from_component (subcomp);
+       if (g_strcmp0 (existing, auid) == 0) {
+               g_free (existing);
+               i_cal_component_remove_component (icalcomp, subcomp);
+               return FALSE;
+       }
 
-       if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
-               param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER);
+       g_free (existing);
 
-               if (param)
-                       icalparameter_set_related (param, related);
-               else {
-                       param = icalparameter_new_related (related);
-                       icalproperty_add_parameter (alarm->trigger, param);
-               }
-       }
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_get_attendee_list:
- * @alarm: An alarm.
- * @attendee_list: (out) (transfer full) (element-type ECalComponentAttendee): Return value for the list of 
attendees.
+ * e_cal_component_remove_alarm:
+ * @comp: A calendar component.
+ * @auid: UID of the alarm to remove.
  *
- * Gets the list of attendees associated with an alarm.
- */
+ * Removes an alarm subcomponent from a calendar component.  If the alarm that
+ * corresponds to the specified @auid had been fetched with
+ * e_cal_component_get_alarm(), then those alarm structures will be invalid; you
+ * should get rid of them with e_cal_component_alarm_free() before using this
+ * function.
+ **/
 void
-e_cal_component_alarm_get_attendee_list (ECalComponentAlarm *alarm,
-                                         GSList **attendee_list)
+e_cal_component_remove_alarm (ECalComponent *comp,
+                              const gchar *auid)
 {
-       g_return_if_fail (alarm != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (auid != NULL);
+       g_return_if_fail (comp->priv->icalcomp != NULL);
+
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, remove_alarm_cb, (gpointer) auid);
+}
 
-       get_attendee_list (alarm->attendee_list, attendee_list);
+static gboolean
+remove_all_alarms_cb (ICalComponent *icalcomp,
+                     ICalComponent *subcomp,
+                     gpointer user_data)
+{
+       i_cal_component_remove_component (icalcomp, subcomp);
+
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_set_attendee_list:
- * @alarm: An alarm.
- * @attendee_list: (element-type ECalComponentAttendee): List of attendees.
+ * e_cal_component_remove_all_alarms:
+ * @comp: A calendar component
  *
- * Sets the list of attendees for an alarm.
- */
+ * Remove all alarms from the calendar component
+ **/
 void
-e_cal_component_alarm_set_attendee_list (ECalComponentAlarm *alarm,
-                                         GSList *attendee_list)
+e_cal_component_remove_all_alarms (ECalComponent *comp)
 {
-       g_return_if_fail (alarm != NULL);
+       g_return_if_fail (E_IS_CAL_COMPONENT (comp));
+       g_return_if_fail (comp->priv->icalcomp != NULL);
 
-       set_attendee_list (alarm->icalcomp, &alarm->attendee_list, attendee_list);
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, remove_all_alarms_cb, NULL);
 }
 
-/**
- * e_cal_component_alarm_has_attendees:
- * @alarm: An alarm.
- *
- * Queries an alarm to see if it has attendees associated with it.
- *
- * Returns: TRUE if there are attendees in the alarm, FALSE if not.
- */
-gboolean
-e_cal_component_alarm_has_attendees (ECalComponentAlarm *alarm)
+static gboolean
+get_alarm_uids_cb (ICalComponent *icalcomp,
+                  ICalComponent *subcomp,
+                  gpointer user_data)
 {
+       GSList **puids = user_data;
+       gchar *auid;
 
-       g_return_val_if_fail (alarm != NULL, FALSE);
+       g_return_val_if_fail (puids != NULL, FALSE);
 
-       if (g_slist_length (alarm->attendee_list) > 0)
-               return TRUE;
+       auid = dup_alarm_uid_from_component (subcomp);
+       if (auid)
+               *puids = g_slist_prepend (*puids, auid);
 
-       return FALSE;
+       return TRUE;
 }
 
 /**
- * e_cal_component_alarm_get_icalcomponent:
- * @alarm: An alarm.
+ * e_cal_component_get_alarm_uids:
+ * @comp: A calendar component.
  *
- * Get the icalcomponent associated with the given #ECalComponentAlarm.
+ * Builds a list of the unique identifiers of the alarm subcomponents inside a
+ * calendar component. Free the returned #GSList with
+ * g_slist_free_full (slist, g_free);, when no longer needed.
  *
- * Returns: the icalcomponent.
- */
-icalcomponent *
-e_cal_component_alarm_get_icalcomponent (ECalComponentAlarm *alarm)
+ * Returns: (transfer full) (nullable) (element-type utf8): a #GSList of unique
+ *    identifiers for alarms.
+ **/
+GSList *
+e_cal_component_get_alarm_uids (ECalComponent *comp)
 {
-       g_return_val_if_fail (alarm != NULL, NULL);
-       return alarm->icalcomp;
+       GSList *uids = NULL;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, get_alarm_uids_cb, &uids);
+
+       return g_slist_reverse (uids);
 }
 
-/* Returns TRUE if both strings match, i.e. they are both NULL or the
- * strings are equal. */
+struct GetAlarmData {
+       const gchar *auid;
+       ICalComponent *valarm;
+};
+
 static gboolean
-e_cal_component_strings_match (const gchar *string1,
-                               const gchar *string2)
+get_alarm_cb (ICalComponent *icalcomp,
+             ICalComponent *subcomp,
+             gpointer user_data)
 {
-       if (string1 == NULL || string2 == NULL)
-               return (string1 == string2) ? TRUE : FALSE;
+       struct GetAlarmData *gad = user_data;
+       gchar *auid;
 
-       if (!strcmp (string1, string2))
-               return TRUE;
+       g_return_val_if_fail (gad != NULL, FALSE);
 
-       return FALSE;
+       auid = dup_alarm_uid_from_component (subcomp);
+       if (g_strcmp0 (auid, gad->auid) == 0) {
+               gad->valarm = g_object_ref (subcomp);
+       }
+
+       g_free (auid);
+
+       return !gad->valarm;
+}
+
+/**
+ * e_cal_component_get_alarm:
+ * @comp: A calendar component.
+ * @auid: Unique identifier for the sought alarm subcomponent.
+ *
+ * Queries a particular alarm subcomponent of a calendar component.
+ * Free the returned pointer with e_cal_component_alarm_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the alarm subcomponent that corresponds
+ *    to the specified @auid, or %NULL if no alarm exists with that UID
+ **/
+ECalComponentAlarm *
+e_cal_component_get_alarm (ECalComponent *comp,
+                           const gchar *auid)
+{
+       ECalComponentAlarm *alarm;
+       struct GetAlarmData gad;
+
+       g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
+       g_return_val_if_fail (comp->priv->icalcomp != NULL, NULL);
+       g_return_val_if_fail (auid != NULL, NULL);
+
+       gad.auid = auid;
+       gad.valarm = NULL;
+
+       foreach_subcomponent (comp->priv->icalcomp, I_CAL_VALARM_COMPONENT, get_alarm_cb, &gad);
+
+       if (gad.valarm) {
+               alarm = e_cal_component_alarm_new_from_component (gad.valarm);
+               g_object_unref (valarm);
+       }
+
+       return alarm;
 }
 
 /**
@@ -6149,61 +3937,60 @@ gboolean
 e_cal_component_event_dates_match (ECalComponent *comp1,
                                    ECalComponent *comp2)
 {
-       ECalComponentDateTime comp1_dtstart, comp1_dtend;
-       ECalComponentDateTime comp2_dtstart, comp2_dtend;
+       ECalComponentDateTime *comp1_dtstart, *comp1_dtend;
+       ECalComponentDateTime *comp2_dtstart, *comp2_dtend;
        gboolean retval = TRUE;
 
-       e_cal_component_get_dtstart (comp1, &comp1_dtstart);
-       e_cal_component_get_dtend   (comp1, &comp1_dtend);
-       e_cal_component_get_dtstart (comp2, &comp2_dtstart);
-       e_cal_component_get_dtend   (comp2, &comp2_dtend);
+       comp1_dtstart = e_cal_component_get_dtstart (comp1);
+       comp1_dtend = e_cal_component_get_dtend (comp1);
+       comp2_dtstart = e_cal_component_get_dtstart (comp2);
+       comp2_dtend = e_cal_component_get_dtend (comp2);
 
        /* If either value is NULL they must both be NULL to match. */
-       if (comp1_dtstart.value == NULL || comp2_dtstart.value == NULL) {
-               if (comp1_dtstart.value != comp2_dtstart.value) {
+       if (!comp1_dtstart || !comp2_dtstart) {
+               if (comp1_dtstart != comp2_dtstart) {
                        retval = FALSE;
                        goto out;
                }
        } else {
-               if (icaltime_compare (*comp1_dtstart.value,
-                                     *comp2_dtstart.value)) {
+               if (i_cal_time_compare (e_cal_component_datetime_get_value (comp1_dtstart),
+                                       e_cal_component_datetime_get_value (comp2_dtstart))) {
                        retval = FALSE;
                        goto out;
                }
        }
 
-       if (comp1_dtend.value == NULL || comp2_dtend.value == NULL) {
-               if (comp1_dtend.value != comp2_dtend.value) {
+       if (!comp1_dtend || !comp2_dtend) {
+               if (comp1_dtend != comp2_dtend) {
                        retval = FALSE;
                        goto out;
                }
        } else {
-               if (icaltime_compare (*comp1_dtend.value,
-                                     *comp2_dtend.value)) {
+               if (i_cal_time_compare (e_cal_component_datetime_get_value (comp1_dtend),
+                                       e_cal_component_datetime_get_value (comp2_dtend))) {
                        retval = FALSE;
                        goto out;
                }
        }
 
        /* Now check the timezones. */
-       if (!e_cal_component_strings_match (comp1_dtstart.tzid,
-                                         comp2_dtstart.tzid)) {
+       if (g_strcmp0 (comp1_dtstart ? e_cal_component_datetime_get_tzid (comp1_dtstart) : NULL,
+                      comp2_dtstart ? e_cal_component_datetime_get_tzid (comp2_dtstart) : NULL) != 0) {
                retval = FALSE;
                goto out;
        }
 
-       if (!e_cal_component_strings_match (comp1_dtend.tzid,
-                                         comp2_dtend.tzid)) {
+       if (g_strcmp0 (comp1_dtend ? e_cal_component_datetime_get_tzid (comp1_dtend) : NULL,
+                      comp2_dtend ? e_cal_component_datetime_get_tzid (comp2_dtend) : NULL) != 0) {
                retval = FALSE;
        }
 
  out:
 
-       e_cal_component_free_datetime (&comp1_dtstart);
-       e_cal_component_free_datetime (&comp1_dtend);
-       e_cal_component_free_datetime (&comp2_dtstart);
-       e_cal_component_free_datetime (&comp2_dtend);
+       e_cal_component_datetime_free (comp1_dtstart);
+       e_cal_component_datetime_free (comp1_dtend);
+       e_cal_component_datetime_free (comp2_dtstart);
+       e_cal_component_datetime_free (comp2_dtend);
 
        return retval;
 }
-
diff --git a/src/calendar/libecal/e-cal-component.h b/src/calendar/libecal/e-cal-component.h
index 43d5a7830..60709841f 100644
--- a/src/calendar/libecal/e-cal-component.h
+++ b/src/calendar/libecal/e-cal-component.h
@@ -90,12 +90,11 @@ ECalComponent *     e_cal_component_clone           (ECalComponent *comp);
 void           e_cal_component_set_new_vtype   (ECalComponent *comp,
                                                 ECalComponentVType type);
 
-icalcomponent *        e_cal_component_get_icalcomponent
+ICalComponent *        e_cal_component_get_icalcomponent
                                                (ECalComponent *comp);
 gboolean       e_cal_component_set_icalcomponent
                                                (ECalComponent *comp,
-                                                icalcomponent *icalcomp);
-void           e_cal_component_rescan          (ECalComponent *comp);
+                                                ICalComponent *icalcomp);
 void           e_cal_component_strip_errors    (ECalComponent *comp);
 
 ECalComponentVType
@@ -106,154 +105,132 @@ gchar *         e_cal_component_get_as_string   (ECalComponent *comp);
 void           e_cal_component_commit_sequence (ECalComponent *comp);
 void           e_cal_component_abort_sequence  (ECalComponent *comp);
 
-void           e_cal_component_get_uid         (ECalComponent *comp,
-                                                const gchar **uid);
+const gchar *  e_cal_component_get_uid         (ECalComponent *comp);
 void           e_cal_component_set_uid         (ECalComponent *comp,
                                                 const gchar *uid);
 
 ECalComponentId *
                e_cal_component_get_id          (ECalComponent *comp);
 
-void           e_cal_component_get_categories  (ECalComponent *comp,
-                                                const gchar **categories);
+gchar *                e_cal_component_get_categories  (ECalComponent *comp);
 void           e_cal_component_set_categories  (ECalComponent *comp,
                                                 const gchar *categories);
-void           e_cal_component_get_categories_list
-                                               (ECalComponent *comp,
-                                                GSList **categ_list);
+GSList *       e_cal_component_get_categories_list /* gchar * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_categories_list
                                                (ECalComponent *comp,
-                                                GSList *categ_list);
+                                                const GSList *categ_list); /* gchar * */
 
-void           e_cal_component_get_classification
-                                               (ECalComponent *comp,
-                                                ECalComponentClassification *classif);
+ECalComponentClassification
+               e_cal_component_get_classification
+                                               (ECalComponent *comp);
 void           e_cal_component_set_classification
                                                (ECalComponent *comp,
                                                 ECalComponentClassification classif);
 
-void           e_cal_component_get_comment_list
-                                               (ECalComponent *comp,
-                                                GSList **text_list);
+GSList *       e_cal_component_get_comment_list /* ECalComponentText * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_comment_list
                                                (ECalComponent *comp,
-                                                GSList *text_list);
+                                                const GSList *text_list); /* ECalComponentText * */
 
-void           e_cal_component_get_completed   (ECalComponent *comp,
-                                                struct icaltimetype **t);
+ICalTimetype * e_cal_component_get_completed   (ECalComponent *comp);
 void           e_cal_component_set_completed   (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTimetype *tt);
 
-void           e_cal_component_get_contact_list
-                                               (ECalComponent *comp,
-                                                GSList **text_list);
+GSList *       e_cal_component_get_contact_list /* ECalComponentText * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_contact_list
                                                (ECalComponent *comp,
-                                                GSList *text_list);
+                                                const GSList *text_list); /* ECalComponentText * */
 
-void           e_cal_component_get_created     (ECalComponent *comp,
-                                                struct icaltimetype **t);
+ICalTimetype * e_cal_component_get_created     (ECalComponent *comp);
 void           e_cal_component_set_created     (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTimetype *tt);
 
-void           e_cal_component_get_description_list
-                                               (ECalComponent *comp,
-                                                GSList **text_list);
+GSList *       e_cal_component_get_description_list /* ECalComponentText * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_description_list
                                                (ECalComponent *comp,
-                                                GSList *text_list);
+                                                const GSList *text_list); /* ECalComponentText * */
 
-void           e_cal_component_get_dtend       (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+ECalComponentDateTime *
+               e_cal_component_get_dtend       (ECalComponent *comp);
 void           e_cal_component_set_dtend       (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+                                                const ECalComponentDateTime *dt);
 
-void           e_cal_component_get_dtstamp     (ECalComponent *comp,
-                                                struct icaltimetype *t);
+ICalTimetype * e_cal_component_get_dtstamp     (ECalComponent *comp);
 void           e_cal_component_set_dtstamp     (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTimetype *tt);
 
-void           e_cal_component_get_dtstart     (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+ECalComponentDateTime *
+               e_cal_component_get_dtstart     (ECalComponent *comp);
 void           e_cal_component_set_dtstart     (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+                                                const ECalComponentDateTime *dt);
 
-void           e_cal_component_get_due         (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+ECalComponentDateTime *dt
+               e_cal_component_get_due         (ECalComponent *comp);
 void           e_cal_component_set_due         (ECalComponent *comp,
-                                                ECalComponentDateTime *dt);
+                                                const ECalComponentDateTime *dt);
 
-void           e_cal_component_get_exdate_list (ECalComponent *comp,
+GSList *       e_cal_component_get_exdate_list (ECalComponent *comp, /* ECalComponentDateTime * */
                                                 GSList **exdate_list);
 void           e_cal_component_set_exdate_list (ECalComponent *comp,
-                                                GSList *exdate_list);
+                                                const GSList *exdate_list); /* ECalComponentDateTime * */
 gboolean       e_cal_component_has_exdates     (ECalComponent *comp);
 
-void           e_cal_component_get_exrule_list (ECalComponent *comp,
-                                                GSList **recur_list);
-void           e_cal_component_get_exrule_property_list
-                                               (ECalComponent *comp,
-                                                GSList **recur_list);
+GSList *       e_cal_component_get_exrule_list (ECalComponent *comp); /* ICalRecurrenceType * */
+GSList *       e_cal_component_get_exrule_property_list /* ICalProperty * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_exrule_list (ECalComponent *comp,
-                                                GSList *recur_list);
+                                                const GSList *recur_list); /* ICalRecurrenceType * */
 gboolean       e_cal_component_has_exrules     (ECalComponent *comp);
 
 gboolean       e_cal_component_has_exceptions  (ECalComponent *comp);
 
-void           e_cal_component_get_geo         (ECalComponent *comp,
-                                                struct icalgeotype **geo);
+ICalGeoType *  e_cal_component_get_geo         (ECalComponent *comp);
 void           e_cal_component_set_geo         (ECalComponent *comp,
-                                                struct icalgeotype *geo);
+                                                const ICalGeoType *geo);
 
-void           e_cal_component_get_last_modified
-                                               (ECalComponent *comp,
-                                                struct icaltimetype **t);
+ICalTimetype * e_cal_component_get_last_modified
+                                               (ECalComponent *comp);
 void           e_cal_component_set_last_modified
                                                (ECalComponent *comp,
-                                                struct icaltimetype *t);
+                                                const ICalTimetype *tt);
 
-void           e_cal_component_get_organizer   (ECalComponent *comp,
-                                                ECalComponentOrganizer *organizer);
+ECalComponentOrganizer *
+               e_cal_component_get_organizer   (ECalComponent *comp);
 void           e_cal_component_set_organizer   (ECalComponent *comp,
-                                                ECalComponentOrganizer *organizer);
+                                                const ECalComponentOrganizer *organizer);
 gboolean       e_cal_component_has_organizer   (ECalComponent *comp);
 
-gint           e_cal_component_get_percent_as_int
+gint           e_cal_component_get_percent_complete
                                                (ECalComponent *comp);
-void           e_cal_component_set_percent_as_int
+void           e_cal_component_set_percent_complete
                                                (ECalComponent *comp,
                                                 gint percent);
 
-void           e_cal_component_get_percent     (ECalComponent *comp,
-                                                gint **percent);
-void           e_cal_component_set_percent     (ECalComponent *comp,
-                                                gint *percent);
-
-void           e_cal_component_get_priority    (ECalComponent *comp,
-                                                gint **priority);
+gint           e_cal_component_get_priority    (ECalComponent *comp);
 void           e_cal_component_set_priority    (ECalComponent *comp,
-                                                gint *priority);
+                                                gint priority);
 
-void           e_cal_component_get_recurid     (ECalComponent *comp,
-                                                ECalComponentRange *recur_id);
+ECalComponentRange *
+               e_cal_component_get_recurid     (ECalComponent *comp);
 gchar *                e_cal_component_get_recurid_as_string
                                                (ECalComponent *comp);
 void           e_cal_component_set_recurid     (ECalComponent *comp,
-                                                ECalComponentRange *recur_id);
+                                                const ECalComponentRange *recur_id);
 
-void           e_cal_component_get_rdate_list  (ECalComponent *comp,
-                                                GSList **period_list);
+GSList *       e_cal_component_get_rdate_list  (ECalComponent *comp); /* ECalComponentPeriod * */
 void           e_cal_component_set_rdate_list  (ECalComponent *comp,
-                                                GSList *period_list);
+                                                const GSList *rdate_list); /* ECalComponentPeriod * */
 gboolean       e_cal_component_has_rdates      (ECalComponent *comp);
 
-void           e_cal_component_get_rrule_list  (ECalComponent *comp,
-                                                GSList **recur_list);
-void           e_cal_component_get_rrule_property_list
-                                               (ECalComponent *comp,
-                                                GSList **recur_list);
+GSList *       e_cal_component_get_rrule_list  (ECalComponent *comp); /* ICalRecurrenceType * */
+GSList *       e_cal_component_get_rrule_property_list /* ICalProperty * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_rrule_list  (ECalComponent *comp,
-                                                GSList *recur_list);
+                                                const GSList *recur_list); /* ICalRecurrenceType * */
 gboolean       e_cal_component_has_rrules      (ECalComponent *comp);
 
 gboolean       e_cal_component_has_recurrences (ECalComponent *comp);
@@ -261,81 +238,51 @@ gboolean  e_cal_component_has_simple_recurrence
                                                (ECalComponent *comp);
 gboolean       e_cal_component_is_instance     (ECalComponent *comp);
 
-void           e_cal_component_get_sequence    (ECalComponent *comp,
-                                                gint **sequence);
+gint           e_cal_component_get_sequence    (ECalComponent *comp);
 void           e_cal_component_set_sequence    (ECalComponent *comp,
-                                                gint *sequence);
+                                                gint sequence);
 
-void           e_cal_component_get_status      (ECalComponent *comp,
-                                                icalproperty_status *status);
+ICalPropertyStatus
+               e_cal_component_get_status      (ECalComponent *comp);
 void           e_cal_component_set_status      (ECalComponent *comp,
-                                                icalproperty_status status);
+                                                ICalPropertyStatus status);
 
 void           e_cal_component_get_summary     (ECalComponent *comp,
                                                 ECalComponentText *summary);
 void           e_cal_component_set_summary     (ECalComponent *comp,
                                                 ECalComponentText *summary);
 
-void           e_cal_component_get_transparency
-                                               (ECalComponent *comp,
-                                                ECalComponentTransparency *transp);
-void           e_cal_component_set_transparency
-                                               (ECalComponent *comp,
+ECalComponentTransparency
+               e_cal_component_get_transparency(ECalComponent *comp);
+void           e_cal_component_set_transparency(ECalComponent *comp,
                                                 ECalComponentTransparency transp);
 
-void           e_cal_component_get_url         (ECalComponent *comp,
-                                                const gchar **url);
+gchar *                e_cal_component_get_url         (ECalComponent *comp);
 void           e_cal_component_set_url         (ECalComponent *comp,
                                                 const gchar *url);
 
-void           e_cal_component_get_attendee_list
-                                               (ECalComponent *comp,
-                                                GSList **attendee_list);
+GSList *       e_cal_component_get_attendee_list /* ECalComponentAttendee * */
+                                               (ECalComponent *comp);
 void           e_cal_component_set_attendee_list
                                                (ECalComponent *comp,
-                                                GSList *attendee_list);
+                                                const GSList *attendee_list); /* ECalComponentAttendee * */
 gboolean       e_cal_component_has_attendees   (ECalComponent *comp);
 
-void           e_cal_component_get_location    (ECalComponent *comp,
-                                                const gchar **location);
+gchar *                e_cal_component_get_location    (ECalComponent *comp);
 void           e_cal_component_set_location    (ECalComponent *comp,
                                                 const gchar *location);
 
 /* Attachment handling */
-void           e_cal_component_get_attachment_list
-                                               (ECalComponent *comp,
-                                                GSList **attachment_list);
-void           e_cal_component_set_attachment_list
-                                               (ECalComponent *comp,
-                                                GSList *attachment_list);
+GSList *       e_cal_component_get_attachments (ECalComponent *comp); /* ICalAttach * */
+void           e_cal_component_set_attachments (ECalComponent *comp,
+                                                const GSList *attachments); /* ICalAttach * */
 gboolean       e_cal_component_has_attachments (ECalComponent *comp);
-gint           e_cal_component_get_num_attachments
-                                               (ECalComponent *comp);
 
 gboolean       e_cal_component_event_dates_match
                                                (ECalComponent *comp1,
                                                 ECalComponent *comp2);
 
-/* Functions to free returned values */
-
-void           e_cal_component_free_categories_list
-                                               (GSList *categ_list);
-void           e_cal_component_free_range      (ECalComponentRange *range);
-void           e_cal_component_free_exdate_list
-                                               (GSList *exdate_list);
-void           e_cal_component_free_geo        (struct icalgeotype *geo);
-void           e_cal_component_free_icaltimetype
-                                               (struct icaltimetype *t);
-void           e_cal_component_free_percent    (gint *percent);
-void           e_cal_component_free_priority   (gint *priority);
-void           e_cal_component_free_period_list
-                                               (GSList *period_list);
-void           e_cal_component_free_recur_list (GSList *recur_list);
-void           e_cal_component_free_sequence   (gint *sequence);
-void           e_cal_component_free_text_list  (GSList *text_list);
-void           e_cal_component_free_attendee_list
-                                               (GSList *attendee_list);
-
+/* Alarms */
 gboolean       e_cal_component_has_alarms      (ECalComponent *comp);
 void           e_cal_component_add_alarm       (ECalComponent *comp,
                                                 ECalComponentAlarm *alarm);
@@ -344,10 +291,11 @@ void              e_cal_component_remove_alarm    (ECalComponent *comp,
 void           e_cal_component_remove_all_alarms
                                                (ECalComponent *comp);
 
-GList *                e_cal_component_get_alarm_uids  (ECalComponent *comp);
+GSList *       e_cal_component_get_alarm_uids  (ECalComponent *comp);
 ECalComponentAlarm *
                e_cal_component_get_alarm       (ECalComponent *comp,
                                                 const gchar *auid);
+GSList *       e_cal_component_get_all_alarms  (ECalComponent *comp);
 
 G_END_DECLS
 



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