/* Evolution calendar - iCalendar component object * * Copyright (C) 2000 Helix Code, Inc. * Copyright (C) 2000 Ximian, Inc. * * Author: Federico Mena-Quintero * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "cal-component.h" #include "timeutil.h" /* Extension property for alarm components so that we can reference them by UID */ #define EVOLUTION_ALARM_UID_PROPERTY "X-EVOLUTION-ALARM-UID" /* Private part of the CalComponent structure */ struct _CalComponentPrivate { /* The icalcomponent we wrap */ icalcomponent *icalcomp; /* Properties */ icalproperty *uid; icalproperty *status; icalproperty *categories; icalproperty *classification; struct text { icalproperty *prop; icalparameter *altrep_param; }; GSList *comment_list; /* list of struct text */ icalproperty *completed; icalproperty *created; GSList *description_list; /* list of struct text */ struct datetime { icalproperty *prop; icalparameter *tzid_param; }; struct datetime dtstart; struct datetime dtend; icalproperty *dtstamp; struct datetime due; GSList *exdate_list; /* list of struct datetime */ GSList *exrule_list; /* list of icalproperty objects */ icalproperty *geo; icalproperty *last_modified; icalproperty *percent; icalproperty *priority; struct period { icalproperty *prop; icalparameter *value_param; }; 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; /* Subcomponents */ GHashTable *alarm_uid_hash; /* Whether we should increment the sequence number when piping the * object over the wire. */ guint need_sequence_inc : 1; }; /* Private structure for alarms */ struct _CalComponentAlarm { /* Alarm icalcomponent we wrap */ icalcomponent *icalcomp; /* Our extension UID property */ icalproperty *uid; /* Properties */ icalproperty *action; icalproperty *trigger; }; static void cal_component_class_init (CalComponentClass *class); static void cal_component_init (CalComponent *comp); static void cal_component_destroy (GtkObject *object); static GtkObjectClass *parent_class; /** * cal_component_get_type: * * Registers the #CalComponent class if necessary, and returns the type ID * associated to it. * * Return value: The type ID of the #CalComponent class. **/ GtkType cal_component_get_type (void) { static GtkType cal_component_type = 0; if (!cal_component_type) { static const GtkTypeInfo cal_component_info = { "CalComponent", sizeof (CalComponent), sizeof (CalComponentClass), (GtkClassInitFunc) cal_component_class_init, (GtkObjectInitFunc) cal_component_init, NULL, /* reserved_1 */ NULL, /* reserved_2 */ (GtkClassInitFunc) NULL }; cal_component_type = gtk_type_unique (GTK_TYPE_OBJECT, &cal_component_info); } return cal_component_type; } /* Class initialization function for the calendar component object */ static void cal_component_class_init (CalComponentClass *class) { GtkObjectClass *object_class; object_class = (GtkObjectClass *) class; parent_class = gtk_type_class (GTK_TYPE_OBJECT); object_class->destroy = cal_component_destroy; } /* Object initialization function for the calendar component object */ static void cal_component_init (CalComponent *comp) { CalComponentPrivate *priv; priv = g_new0 (CalComponentPrivate, 1); comp->priv = priv; priv->alarm_uid_hash = g_hash_table_new (g_str_hash, g_str_equal); } /* Does a simple g_free() of the elements of a GSList and then frees the list * itself. Returns NULL. */ static GSList * free_slist (GSList *slist) { GSList *l; for (l = slist; l; l = l->next) g_free (l->data); g_slist_free (slist); return NULL; } /* 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) { return TRUE; } /* 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 void free_icalcomponent (CalComponent *comp) { CalComponentPrivate *priv; priv = comp->priv; if (!priv->icalcomp) return; /* Free the icalcomponent */ if (icalcomponent_get_parent (priv->icalcomp) == NULL) icalcomponent_free (priv->icalcomp); priv->icalcomp = NULL; /* Free the mappings */ priv->uid = NULL; priv->status = NULL; priv->categories = NULL; priv->classification = NULL; priv->comment_list = NULL; priv->completed = NULL; priv->created = NULL; priv->description_list = free_slist (priv->description_list); priv->dtend.prop = NULL; priv->dtend.tzid_param = NULL; priv->dtstamp = NULL; priv->dtstart.prop = NULL; priv->dtstart.tzid_param = NULL; priv->due.prop = NULL; priv->due.tzid_param = NULL; priv->exdate_list = free_slist (priv->exdate_list); g_slist_free (priv->exrule_list); priv->exrule_list = NULL; priv->geo = NULL; priv->last_modified = NULL; priv->percent = NULL; priv->priority = NULL; priv->rdate_list = free_slist (priv->rdate_list); g_slist_free (priv->rrule_list); priv->rrule_list = NULL; priv->sequence = NULL; priv->summary.prop = NULL; priv->summary.altrep_param = NULL; priv->transparency = NULL; priv->url = NULL; /* Free the subcomponents */ g_hash_table_foreach_remove (priv->alarm_uid_hash, free_alarm_cb, NULL); /* Clean up */ priv->need_sequence_inc = FALSE; } /* Destroy handler for the calendar component object */ static void cal_component_destroy (GtkObject *object) { CalComponent *comp; CalComponentPrivate *priv; g_return_if_fail (object != NULL); g_return_if_fail (IS_CAL_COMPONENT (object)); comp = CAL_COMPONENT (object); priv = comp->priv; free_icalcomponent (comp); g_hash_table_destroy (priv->alarm_uid_hash); priv->alarm_uid_hash = NULL; g_free (priv); comp->priv = NULL; if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } /** * cal_component_gen_uid: * * Generates a unique identifier suitable for calendar components. * * Return value: A unique identifier string. Every time this function is called * a different string is returned. **/ char * cal_component_gen_uid (void) { char *iso, *ret; static char *hostname; time_t t = time (NULL); static int serial; if (!hostname) { static char buffer [512]; if ((gethostname (buffer, sizeof (buffer) - 1) == 0) && (buffer [0] != 0)) hostname = buffer; else hostname = "localhost"; } iso = isodate_from_time_t (t); ret = g_strdup_printf ("%s-%d-%d-%d-%d@%s", iso, getpid (), getgid (), getppid (), serial++, hostname); g_free (iso); return ret; } /** * cal_component_new: * * Creates a new empty calendar component object. You should set it from an * #icalcomponent structure by using cal_component_set_icalcomponent() or with a * new empty component type by using cal_component_set_new_vtype(). * * Return value: A newly-created calendar component object. **/ CalComponent * cal_component_new (void) { return CAL_COMPONENT (gtk_type_new (CAL_COMPONENT_TYPE)); } /** * cal_component_clone: * @comp: A calendar component object. * * Creates a new calendar component object by copying the information from * another one. * * Return value: A newly-created calendar component with the same values as the * original one. **/ CalComponent * cal_component_clone (CalComponent *comp) { CalComponentPrivate *priv; CalComponent *new_comp; icalcomponent *new_icalcomp; g_return_val_if_fail (comp != NULL, NULL); g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); priv = comp->priv; g_return_val_if_fail (priv->need_sequence_inc == FALSE, NULL); new_comp = cal_component_new (); if (priv->icalcomp) { new_icalcomp = icalcomponent_new_clone (priv->icalcomp); cal_component_set_icalcomponent (new_comp, new_icalcomp); } return new_comp; } /* Scans a date/time and timezone pair property */ static void scan_datetime (CalComponent *comp, struct datetime *datetime, icalproperty *prop) { CalComponentPrivate *priv; priv = comp->priv; datetime->prop = prop; datetime->tzid_param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER); } /* Scans an exception date property */ static void scan_exdate (CalComponent *comp, icalproperty *prop) { CalComponentPrivate *priv; struct datetime *dt; priv = comp->priv; dt = g_new (struct datetime, 1); dt->prop = prop; dt->tzid_param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER); priv->exdate_list = g_slist_append (priv->exdate_list, dt); } /* Scans an icalperiodtype property */ static void scan_period (CalComponent *comp, GSList **list, icalproperty *prop) { struct period *period; period = g_new (struct period, 1); period->prop = prop; period->value_param = icalproperty_get_first_parameter (prop, ICAL_VALUE_PARAMETER); *list = g_slist_append (*list, period); } /* Scans an icalrecurtype property */ static void scan_recur (CalComponent *comp, GSList **list, icalproperty *prop) { *list = g_slist_append (*list, prop); } /* Scans the summary property */ static void scan_summary (CalComponent *comp, icalproperty *prop) { CalComponentPrivate *priv; priv = comp->priv; priv->summary.prop = prop; priv->summary.altrep_param = icalproperty_get_first_parameter (prop, ICAL_ALTREP_PARAMETER); } /* Scans a text (i.e. text + altrep) property */ static void scan_text (CalComponent *comp, GSList **text_list, icalproperty *prop) { struct text *text; text = g_new (struct text, 1); text->prop = prop; text->altrep_param = icalproperty_get_first_parameter (prop, ICAL_ALTREP_PARAMETER); *text_list = g_slist_append (*text_list, text); } /* Scans an icalproperty and adds its mapping to the component */ static void scan_property (CalComponent *comp, icalproperty *prop) { CalComponentPrivate *priv; icalproperty_kind kind; priv = comp->priv; kind = icalproperty_isa (prop); switch (kind) { case ICAL_STATUS_PROPERTY: priv->status = prop; break; case ICAL_CATEGORIES_PROPERTY: priv->categories = prop; break; case ICAL_CLASS_PROPERTY: priv->classification = prop; break; case ICAL_COMMENT_PROPERTY: scan_text (comp, &priv->comment_list, prop); break; case ICAL_COMPLETED_PROPERTY: priv->completed = prop; break; case ICAL_CREATED_PROPERTY: priv->created = prop; break; case ICAL_DESCRIPTION_PROPERTY: scan_text (comp, &priv->description_list, prop); break; case ICAL_DTEND_PROPERTY: scan_datetime (comp, &priv->dtend, prop); break; case ICAL_DTSTAMP_PROPERTY: priv->dtstamp = prop; break; case ICAL_DTSTART_PROPERTY: scan_datetime (comp, &priv->dtstart, prop); break; case ICAL_DUE_PROPERTY: scan_datetime (comp, &priv->due, 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_PERCENTCOMPLETE_PROPERTY: priv->percent = prop; break; case ICAL_PRIORITY_PROPERTY: priv->priority = 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; default: break; } } /* Gets our alarm UID string from a property that is known to contain it */ static const char * alarm_uid_from_prop (icalproperty *prop) { const char *xstr; g_assert (icalproperty_isa (prop) == ICAL_X_PROPERTY); xstr = icalproperty_get_x (prop); g_assert (xstr != 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 char * set_alarm_uid (icalcomponent *alarm, const char *auid) { icalproperty *prop; const char *inprop_auid; /* Create the new property */ prop = icalproperty_new_x ((char *) 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 char *xname; xname = icalproperty_get_x_name (prop); g_assert (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 char * add_alarm (CalComponent *comp, icalcomponent *alarm, const char *auid) { CalComponentPrivate *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) { char *new_auid; g_message ("add_alarm(): Got alarm with duplicated UID `%s', changing it...", auid); remove_alarm_uid (alarm); new_auid = cal_component_gen_uid (); auid = set_alarm_uid (alarm, new_auid); g_free (new_auid); } g_hash_table_insert (priv->alarm_uid_hash, (char *) 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 (CalComponent *comp, icalcomponent *alarm) { CalComponentPrivate *priv; icalproperty *prop; const char *auid; char *new_auid; priv = comp->priv; for (prop = icalcomponent_get_first_property (alarm, ICAL_X_PROPERTY); prop; prop = icalcomponent_get_next_property (alarm, ICAL_X_PROPERTY)) { const char *xname; xname = icalproperty_get_x_name (prop); g_assert (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 = cal_component_gen_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 (CalComponent *comp) { CalComponentPrivate *priv; icalproperty *prop; icalcompiter iter; priv = comp->priv; g_assert (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 (CalComponent *comp) { CalComponentPrivate *priv; priv = comp->priv; g_assert (priv->icalcomp != NULL); if (!priv->uid) { char *uid; uid = cal_component_gen_uid (); priv->uid = icalproperty_new_uid (uid); g_free (uid); icalcomponent_add_property (priv->icalcomp, priv->uid); } if (!priv->dtstamp) { time_t tim; struct icaltimetype t; tim = time (NULL); t = icaltime_from_timet (tim, FALSE); priv->dtstamp = icalproperty_new_dtstamp (t); icalcomponent_add_property (priv->icalcomp, priv->dtstamp); } } /** * 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 cal_component_set_new_vtype (CalComponent *comp, CalComponentVType type) { CalComponentPrivate *priv; icalcomponent *icalcomp; icalcomponent_kind kind; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; free_icalcomponent (comp); if (type == CAL_COMPONENT_NO_TYPE) return; /* Figure out the kind and create the icalcomponent */ switch (type) { case CAL_COMPONENT_EVENT: kind = ICAL_VEVENT_COMPONENT; break; case CAL_COMPONENT_TODO: kind = ICAL_VTODO_COMPONENT; break; case CAL_COMPONENT_JOURNAL: kind = ICAL_VJOURNAL_COMPONENT; break; case CAL_COMPONENT_FREEBUSY: kind = ICAL_VFREEBUSY_COMPONENT; break; case CAL_COMPONENT_TIMEZONE: kind = ICAL_VTIMEZONE_COMPONENT; break; default: g_assert_not_reached (); kind = ICAL_NO_COMPONENT; } icalcomp = icalcomponent_new (kind); if (!icalcomp) { g_message ("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); } /** * cal_component_set_icalcomponent: * @comp: A calendar component object. * @icalcomp: 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. * * Return value: TRUE on success, FALSE if @icalcomp is an unsupported component * type. **/ gboolean cal_component_set_icalcomponent (CalComponent *comp, icalcomponent *icalcomp) { CalComponentPrivate *priv; icalcomponent_kind kind; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); priv = comp->priv; if (priv->icalcomp == icalcomp) return TRUE; free_icalcomponent (comp); 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; } /** * cal_component_get_icalcomponent: * @comp: A calendar component object. * * Queries the #icalcomponent structure that a calendar component object is * wrapping. * * Return value: An #icalcomponent structure, or NULL if the @comp has no * #icalcomponent set to it. **/ icalcomponent * cal_component_get_icalcomponent (CalComponent *comp) { CalComponentPrivate *priv; g_return_val_if_fail (comp != NULL, NULL); g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); priv = comp->priv; g_return_val_if_fail (priv->need_sequence_inc == FALSE, NULL); return priv->icalcomp; } /** * cal_component_get_vtype: * @comp: A calendar component object. * * Queries the type of a calendar component object. * * Return value: The type of the component, as defined by RFC 2445. **/ CalComponentVType cal_component_get_vtype (CalComponent *comp) { CalComponentPrivate *priv; icalcomponent_kind kind; g_return_val_if_fail (comp != NULL, CAL_COMPONENT_NO_TYPE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), CAL_COMPONENT_NO_TYPE); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, CAL_COMPONENT_NO_TYPE); kind = icalcomponent_isa (priv->icalcomp); switch (kind) { case ICAL_VEVENT_COMPONENT: return CAL_COMPONENT_EVENT; case ICAL_VTODO_COMPONENT: return CAL_COMPONENT_TODO; case ICAL_VJOURNAL_COMPONENT: return CAL_COMPONENT_JOURNAL; case ICAL_VFREEBUSY_COMPONENT: return CAL_COMPONENT_FREEBUSY; case ICAL_VTIMEZONE_COMPONENT: return CAL_COMPONENT_TIMEZONE; default: /* We should have been loaded with a supported type! */ g_assert_not_reached (); return CAL_COMPONENT_NO_TYPE; } } /** * cal_component_get_as_string: * @comp: A calendar component. * * Gets the iCalendar string representation of a calendar component. You should * call cal_component_commit_sequence() before this function to ensure that the * component's sequence number is consistent with the state of the object. * * Return value: String representation of the calendar component according to * RFC 2445. **/ char * cal_component_get_as_string (CalComponent *comp) { CalComponentPrivate *priv; char *str, *buf; g_return_val_if_fail (comp != NULL, NULL); g_return_val_if_fail (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); /* We dup the string; libical owns that memory */ str = icalcomponent_as_ical_string (priv->icalcomp); if (str) buf = g_strdup (str); else buf = NULL; return buf; } /** * cal_component_commit_sequence: * @comp: * * 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 cal_component_get_as_string() to * ensure that the component is fully consistent. **/ void cal_component_commit_sequence (CalComponent *comp) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priv->need_sequence_inc) return; if (priv->sequence) { int 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; } /** * cal_component_get_uid: * @comp: A calendar component object. * @uid: Return value for the UID string. * * Queries the unique identifier of a calendar component object. **/ void cal_component_get_uid (CalComponent *comp, const char **uid) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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_assert (priv->uid != NULL); *uid = icalproperty_get_uid (priv->uid); } /** * cal_component_set_uid: * @comp: A calendar component object. * @uid: Unique identifier. * * Sets the unique identifier string of a calendar component object. **/ void cal_component_set_uid (CalComponent *comp, const char *uid) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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_assert (priv->uid != NULL); icalproperty_set_uid (priv->uid, (char *) uid); } /** * cal_component_get_categories: * @comp: A calendar component object. * @categories: * * **/ void cal_component_get_categories (CalComponent *comp, const char **categories) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (categories != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (priv->categories) *categories = icalproperty_get_categories (priv->categories); else *categories = NULL; } /** * cal_component_set_categories: * @comp: A calendar component object. * @categories: * * **/ void cal_component_set_categories (CalComponent *comp, const char *categories) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!categories || !(*categories)) { if (priv->categories) { icalcomponent_remove_property (priv->icalcomp, priv->categories); icalproperty_free (priv->categories); priv->url = NULL; } return; } if (priv->categories) icalproperty_set_categories (priv->categories, (char *) categories); else { priv->categories = icalproperty_new_categories ((char *) categories); icalcomponent_add_property (priv->icalcomp, priv->categories); } } /** * cal_component_get_categories_list: * @comp: A calendar component object. * @categ_list: Return value for the list of strings, where each string is a * category. This should be freed using 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 cal_component_get_categories_list (CalComponent *comp, GSList **categ_list) { CalComponentPrivate *priv; const char *categories; const char *p; const char *cat_start; char *str; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (categ_list != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priv->categories) { *categ_list = NULL; return; } categories = icalproperty_get_categories (priv->categories); g_assert (categories != NULL); cat_start = categories; *categ_list = NULL; 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 char * stringify_categories (GSList *categ_list) { GString *s; GSList *l; char *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; } /** * cal_component_set_categories_list: * @comp: A calendar component object. * @categ_list: List of strings, one for each category. * * Sets the list of categories of a calendar component object. **/ void cal_component_set_categories_list (CalComponent *comp, GSList *categ_list) { CalComponentPrivate *priv; char *categories_str; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!categ_list) { if (priv->categories) { icalcomponent_remove_property (priv->icalcomp, priv->categories); icalproperty_free (priv->categories); } return; } /* Create a single string of categories */ categories_str = stringify_categories (categ_list); /* Set the categories */ priv->categories = icalproperty_new_categories (categories_str); g_free (categories_str); icalcomponent_add_property (priv->icalcomp, priv->categories); } /** * cal_component_get_classification: * @comp: A calendar component object. * @classif: 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 * #CAL_COMPONENT_CLASS_NONE. **/ void cal_component_get_classification (CalComponent *comp, CalComponentClassification *classif) { CalComponentPrivate *priv; const char *class; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (classif != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priv->classification) { *classif = CAL_COMPONENT_CLASS_NONE; return; } class = icalproperty_get_class (priv->classification); if (strcasecmp (class, "PUBLIC") == 0) *classif = CAL_COMPONENT_CLASS_PUBLIC; else if (strcasecmp (class, "PRIVATE") == 0) *classif = CAL_COMPONENT_CLASS_PRIVATE; else if (strcasecmp (class, "CONFIDENTIAL") == 0) *classif = CAL_COMPONENT_CLASS_CONFIDENTIAL; else *classif = CAL_COMPONENT_CLASS_UNKNOWN; } /** * 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 CAL_COMPONENT_CLASS_NONE for @classif. **/ void cal_component_set_classification (CalComponent *comp, CalComponentClassification classif) { CalComponentPrivate *priv; char *str; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (classif != CAL_COMPONENT_CLASS_UNKNOWN); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (classif == 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 CAL_COMPONENT_CLASS_PUBLIC: str = "PUBLIC"; break; case CAL_COMPONENT_CLASS_PRIVATE: str = "PRIVATE"; break; case CAL_COMPONENT_CLASS_CONFIDENTIAL: str = "CONFIDENTIAL"; break; default: g_assert_not_reached (); str = NULL; } if (priv->classification) icalproperty_set_class (priv->classification, str); else { priv->classification = icalproperty_new_class (str); icalcomponent_add_property (priv->icalcomp, priv->classification); } } /* Gets a text list value */ static void get_text_list (GSList *text_list, const char *(* get_prop_func) (icalproperty *prop), GSList **tl) { GSList *l; *tl = NULL; if (!text_list) return; for (l = text_list; l; l = l->next) { struct text *text; CalComponentText *t; text = l->data; g_assert (text->prop != NULL); t = g_new (CalComponentText, 1); t->value = (* get_prop_func) (text->prop); 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 (CalComponent *comp, icalproperty *(* new_prop_func) (const char *value), GSList **text_list, GSList *tl) { CalComponentPrivate *priv; GSList *l; priv = comp->priv; /* Remove old texts */ for (l = *text_list; l; l = l->next) { struct text *text; text = l->data; g_assert (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) { CalComponentText *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) ((char *) t->value); icalcomponent_add_property (priv->icalcomp, text->prop); if (t->altrep) { text->altrep_param = icalparameter_new_altrep ((char *) 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); } /** * cal_component_get_comment_list: * @comp: A calendar component object. * @text_list: Return value for the comment properties and their parameters, as * a list of #CalComponentText structures. This should be freed using the * cal_component_free_text_list() function. * * Queries the comment of a calendar component object. The comment property can * appear several times inside a calendar component, and so a list of * #CalComponentText is returned. **/ void cal_component_get_comment_list (CalComponent *comp, GSList **text_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /** * cal_component_set_comment_list: * @comp: A calendar component object. * @text_list: List of #CalComponentText structures. * * Sets the comment of a calendar component object. The comment property can * appear several times inside a calendar component, and so a list of * #CalComponentText structures is used. **/ void cal_component_set_comment_list (CalComponent *comp, GSList *text_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /* Gets a struct icaltimetype value */ static void get_icaltimetype (icalproperty *prop, struct icaltimetype (* get_prop_func) (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 (CalComponent *comp, icalproperty **prop, icalproperty *(* prop_new_func) (struct icaltimetype v), void (* prop_set_func) (icalproperty *prop, struct icaltimetype v), struct icaltimetype *t) { CalComponentPrivate *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); } } /** * cal_component_get_completed: * @comp: A calendar component object. * @t: Return value for the completion date. This should be freed using the * cal_component_free_icaltimetype() function. * * Queries the date at which a calendar compoment object was completed. **/ void cal_component_get_completed (CalComponent *comp, struct icaltimetype **t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /** * 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 cal_component_set_completed (CalComponent *comp, struct icaltimetype *t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); set_icaltimetype (comp, &priv->completed, icalproperty_new_completed, icalproperty_set_completed, t); } /** * cal_component_get_created: * @comp: A calendar component object. * @t: Return value for the creation date. This should be freed using the * cal_component_free_icaltimetype() function. * * Queries the date in which a calendar component object was created in the * calendar store. **/ void cal_component_get_created (CalComponent *comp, struct icaltimetype **t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /** * 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 cal_component_set_created (CalComponent *comp, struct icaltimetype *t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /** * cal_component_get_description_list: * @comp: A calendar component object. * @text_list: Return value for the description properties and their parameters, * as a list of #CalComponentText structures. This should be freed using the * 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 #CalComponentText structures. All other types of components can have at * most one description. **/ void cal_component_get_description_list (CalComponent *comp, GSList **text_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /** * cal_component_set_description_list: * @comp: A calendar component object. * @text_list: List of #CalComponentSummary 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 * #CalComponentDescription structures. All other types of components can have * at most one description. **/ void cal_component_set_description_list (CalComponent *comp, GSList *text_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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) (icalproperty *prop), CalComponentDateTime *dt) { if (datetime->prop) { dt->value = g_new (struct icaltimetype, 1); *dt->value = (* get_prop_func) (datetime->prop); } else dt->value = NULL; if (datetime->tzid_param) dt->tzid = icalparameter_get_tzid (datetime->tzid_param); else dt->tzid = NULL; } /* Sets a date/time and timezone pair */ static void set_datetime (CalComponent *comp, struct datetime *datetime, icalproperty *(* prop_new_func) (struct icaltimetype v), void (* prop_set_func) (icalproperty * prop, struct icaltimetype v), CalComponentDateTime *dt) { CalComponentPrivate *priv; priv = comp->priv; 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 (datetime->prop) (* prop_set_func) (datetime->prop, *dt->value); else { datetime->prop = (* prop_new_func) (*dt->value); icalcomponent_add_property (priv->icalcomp, datetime->prop); } if (dt->tzid) { g_assert (datetime->prop != NULL); if (datetime->tzid_param) icalparameter_set_tzid (datetime->tzid_param, (char *) dt->tzid); else { datetime->tzid_param = icalparameter_new_tzid ((char *) dt->tzid); icalproperty_add_parameter (datetime->prop, datetime->tzid_param); } } else if (datetime->tzid_param) { icalproperty_remove_parameter (datetime->prop, ICAL_TZID_PARAMETER); icalparameter_free (datetime->tzid_param); datetime->tzid_param = NULL; } } /** * cal_component_get_dtend: * @comp: A calendar component object. * @dt: Return value for the date/time end. This should be freed with the * cal_component_free_datetime() function. * * Queries the date/time end of a calendar component object. **/ void cal_component_get_dtend (CalComponent *comp, CalComponentDateTime *dt) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (dt != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); get_datetime (&priv->dtend, icalproperty_get_dtend, dt); } /** * 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 cal_component_set_dtend (CalComponent *comp, CalComponentDateTime *dt) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); priv->need_sequence_inc = TRUE; } /** * cal_component_get_dtstamp: * @comp: A calendar component object. * @t: Return 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 cal_component_get_dtstamp (CalComponent *comp, struct icaltimetype *t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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_assert (priv->dtstamp != NULL); *t = icalproperty_get_dtstamp (priv->dtstamp); } /** * 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 cal_component_set_dtstamp (CalComponent *comp, struct icaltimetype *t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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_assert (priv->dtstamp != NULL); icalproperty_set_dtstamp (priv->dtstamp, *t); } /** * cal_component_get_dtstart: * @comp: A calendar component object. * @dt: Return value for the date/time start. This should be freed with the * cal_component_free_datetime() function. * * Queries the date/time start of a calendar component object. **/ void cal_component_get_dtstart (CalComponent *comp, CalComponentDateTime *dt) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (dt != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); get_datetime (&priv->dtstart, icalproperty_get_dtstart, dt); } /** * 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 cal_component_set_dtstart (CalComponent *comp, CalComponentDateTime *dt) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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; } /** * cal_component_get_due: * @comp: A calendar component object. * @dt: Return value for the due date/time. This should be freed with the * cal_component_free_datetime() function. * * Queries the due date/time of a calendar component object. **/ void cal_component_get_due (CalComponent *comp, CalComponentDateTime *dt) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (dt != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); get_datetime (&priv->due, icalproperty_get_due, dt); } /** * 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 cal_component_set_due (CalComponent *comp, CalComponentDateTime *dt) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); priv->need_sequence_inc = TRUE; } /* Builds a list of CalComponentPeriod structures based on a list of icalproperties */ static void get_period_list (GSList *period_list, struct icaldatetimeperiodtype (* get_prop_func) (icalproperty *prop), GSList **list) { GSList *l; *list = NULL; if (!period_list) return; for (l = period_list; l; l = l->next) { struct period *period; CalComponentPeriod *p; struct icaldatetimeperiodtype ip; period = l->data; g_assert (period->prop != NULL); p = g_new (CalComponentPeriod, 1); /* 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 = CAL_COMPONENT_PERIOD_DATETIME; else if (value_type == ICAL_VALUE_DURATION) p->type = CAL_COMPONENT_PERIOD_DURATION; else { g_message ("get_period_list(): Unknown value for period %d; " "using DATETIME", value_type); p->type = CAL_COMPONENT_PERIOD_DATETIME; } } else p->type = CAL_COMPONENT_PERIOD_DATETIME; /* Get start and end/duration */ ip = (* get_prop_func) (period->prop); p->start = ip.period.start; if (p->type == CAL_COMPONENT_PERIOD_DATETIME) p->u.end = ip.period.end; else if (p->type == CAL_COMPONENT_PERIOD_DURATION) p->u.duration = ip.period.duration; else g_assert_not_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 (CalComponent *comp, icalproperty *(* new_prop_func) (struct icaldatetimeperiodtype period), GSList **period_list, GSList *pl) { CalComponentPrivate *priv; GSList *l; priv = comp->priv; /* Remove old periods */ for (l = *period_list; l; l = l->next) { struct period *period; period = l->data; g_assert (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) { CalComponentPeriod *p; struct period *period; struct icaldatetimeperiodtype ip; icalparameter_value value_type; g_assert (l->data != NULL); p = l->data; /* Create libical value */ ip.period.start = p->start; if (p->type == CAL_COMPONENT_PERIOD_DATETIME) { value_type = ICAL_VALUE_DATETIME; ip.period.end = p->u.end; } else if (p->type == CAL_COMPONENT_PERIOD_DURATION) { value_type = ICAL_VALUE_DURATION; ip.period.duration = p->u.duration; } else { g_assert_not_reached (); return; } /* 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); } /** * cal_component_get_exdate_list: * @comp: A calendar component object. * @exdate_list: Return value for the list of exception dates, as a list of * #CalComponentDateTime structures. This should be freed using the * cal_component_free_exdate_list() function. * * Queries the list of exception date properties in a calendar component object. **/ void cal_component_get_exdate_list (CalComponent *comp, GSList **exdate_list) { CalComponentPrivate *priv; GSList *l; g_return_if_fail (comp != NULL); g_return_if_fail (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; CalComponentDateTime *cdt; dt = l->data; cdt = g_new (CalComponentDateTime, 1); cdt->value = g_new (struct icaltimetype, 1); *cdt->value = icalproperty_get_exdate (dt->prop); if (dt->tzid_param) cdt->tzid = 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); } /** * cal_component_set_exdate_list: * @comp: A calendar component object. * @exdate_list: List of #CalComponentDateTime structures. * * Sets the list of exception dates in a calendar component object. **/ void cal_component_set_exdate_list (CalComponent *comp, GSList *exdate_list) { CalComponentPrivate *priv; GSList *l; g_return_if_fail (comp != NULL); g_return_if_fail (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; 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) { CalComponentDateTime *cdt; struct datetime *dt; g_assert (l->data != NULL); cdt = l->data; g_assert (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 ((char *) cdt->tzid); icalproperty_add_parameter (dt->prop, dt->tzid_param); } else dt->tzid_param = NULL; icalcomponent_add_property (priv->icalcomp, dt->prop); priv->exdate_list = g_slist_prepend (priv->exdate_list, dt); } priv->exdate_list = g_slist_reverse (priv->exdate_list); priv->need_sequence_inc = TRUE; } /** * cal_component_has_exdates: * @comp: A calendar component object. * * Queries whether a calendar component object has any exception dates defined * for it. * * Return value: TRUE if the component has exception dates, FALSE otherwise. **/ gboolean cal_component_has_exdates (CalComponent *comp) { CalComponentPrivate *priv; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, FALSE); return (priv->exdate_list != NULL); } /* Gets a list of recurrence rules */ static void get_recur_list (GSList *recur_list, struct icalrecurrencetype (* get_prop_func) (icalproperty *prop), GSList **list) { 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); *list = g_slist_prepend (*list, r); } *list = g_slist_reverse (*list); } /* Sets a list of recurrence rules */ static void set_recur_list (CalComponent *comp, icalproperty *(* new_prop_func) (struct icalrecurrencetype recur), GSList **recur_list, GSList *rl) { CalComponentPrivate *priv; GSList *l; priv = comp->priv; /* Remove old recurrences */ for (l = *recur_list; l; l = l->next) { icalproperty *prop; prop = l->data; icalcomponent_remove_property (priv->icalcomp, prop); icalproperty_free (prop); } g_slist_free (*recur_list); *recur_list = NULL; /* Add in new recurrences */ for (l = rl; l; l = l->next) { icalproperty *prop; struct icalrecurrencetype *recur; g_assert (l->data != NULL); recur = l->data; prop = (* new_prop_func) (*recur); icalcomponent_add_property (priv->icalcomp, prop); *recur_list = g_slist_prepend (*recur_list, prop); } *recur_list = g_slist_reverse (*recur_list); } /** * cal_component_get_exrule_list: * @comp: A calendar component object. * @recur_list: List of exception rules as struct #icalrecurrencetype * structures. This should be freed using the cal_component_free_recur_list() * function. * * Queries the list of exception rule properties of a calendar component * object. **/ void cal_component_get_exrule_list (CalComponent *comp, GSList **recur_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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); } /** * cal_component_get_exrule_property_list: * @comp: A calendar component object. * @recur_list: Returns a list of exception rule properties. * * Queries the list of exception rule properties of a calendar component object. **/ void cal_component_get_exrule_property_list (CalComponent *comp, GSList **recur_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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; } /** * cal_component_set_exrule_list: * @comp: A calendar component object. * @recur_list: List of struct #icalrecurrencetype structures. * * Sets the list of exception rules in a calendar component object. **/ void cal_component_set_exrule_list (CalComponent *comp, GSList *recur_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); 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; } /** * cal_component_has_exrules: * @comp: A calendar component object. * * Queries whether a calendar component object has any exception rules defined * for it. * * Return value: TRUE if the component has exception rules, FALSE otherwise. **/ gboolean cal_component_has_exrules (CalComponent *comp) { CalComponentPrivate *priv; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, FALSE); return (priv->exrule_list != NULL); } /** * cal_component_has_exceptions: * @comp: A calendar component object * * Queries whether a calendar component object has any exception dates * or exception rules. * * Return value: TRUE if the component has exceptions, FALSE otherwise. **/ gboolean cal_component_has_exceptions (CalComponent *comp) { return cal_component_has_exdates (comp) || cal_component_has_exrules (comp); } /** * cal_component_get_geo: * @comp: A calendar component object. * @geo: Return value for the geographic position property. This should be * freed using the cal_component_free_geo() function. * * Sets the geographic position property of a calendar component object. **/ void cal_component_get_geo (CalComponent *comp, struct icalgeotype **geo) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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; } /** * cal_component_set_geo: * @comp: A calendar component object. * @geo: Value for the geographic position property. * * Sets the geographic position property on a calendar component object. **/ void cal_component_set_geo (CalComponent *comp, struct icalgeotype *geo) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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; } return; } if (priv->geo) icalproperty_set_geo (priv->geo, *geo); else { priv->geo = icalproperty_new_geo (*geo); icalcomponent_add_property (priv->icalcomp, priv->geo); } } /** * cal_component_get_last_modified: * @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. **/ void cal_component_get_last_modified (CalComponent *comp, struct icaltimetype **t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (t != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); get_icaltimetype (priv->last_modified, icalproperty_get_lastmodified, t); } /** * cal_component_set_last_modified: * @comp: A calendar component object. * @t: 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 cal_component_set_last_modified (CalComponent *comp, struct icaltimetype *t) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); set_icaltimetype (comp, &priv->last_modified, icalproperty_new_lastmodified, icalproperty_set_lastmodified, t); } /** * cal_component_get_percent: * @comp: A calendar component object. * @percent: Return value for the percent-complete property. This should be * freed using the cal_component_free_percent() function. * * Queries the percent-complete property of a calendar component object. **/ void cal_component_get_percent (CalComponent *comp, int **percent) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (percent != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (priv->percent) { *percent = g_new (int, 1); **percent = icalproperty_get_percentcomplete (priv->percent); } else *percent = NULL; } /** * cal_component_set_percent: * @comp: A calendar component object. * @percent: Value for the percent-complete property. * * Sets the percent-complete property of a calendar component object. **/ void cal_component_set_percent (CalComponent *comp, int *percent) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!percent) { if (priv->percent) { icalcomponent_remove_property (priv->icalcomp, priv->percent); icalproperty_free (priv->percent); priv->percent = NULL; } return; } 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); } } /** * cal_component_get_priority: * @comp: A calendar component object. * @priority: Return value for the priority property. This should be freed using * the cal_component_free_priority() function. * * Queries the priority property of a calendar component object. **/ void cal_component_get_priority (CalComponent *comp, int **priority) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (priority != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (priv->priority) { *priority = g_new (int, 1); **priority = icalproperty_get_priority (priv->priority); } else *priority = NULL; } /** * 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 cal_component_set_priority (CalComponent *comp, int *priority) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priority) { if (priv->priority) { icalcomponent_remove_property (priv->icalcomp, priv->priority); icalproperty_free (priv->priority); priv->priority = NULL; } return; } g_return_if_fail (*priority >= 0 && *priority <= 9); if (priv->priority) icalproperty_set_priority (priv->priority, *priority); else { priv->priority = icalproperty_new_priority (*priority); icalcomponent_add_property (priv->icalcomp, priv->priority); } } /** * cal_component_get_rdate_list: * @comp: A calendar component object. * @period_list: Return value for the list of recurrence dates, as a list of * #CalComponentPeriod structures. This should be freed using the * cal_component_free_period_list() function. * * Queries the list of recurrence date properties in a calendar component * object. **/ void cal_component_get_rdate_list (CalComponent *comp, GSList **period_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (period_list != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); get_period_list (priv->rdate_list, icalproperty_get_rdate, period_list); } /** * cal_component_set_rdate_list: * @comp: A calendar component object. * @period_list: List of #CalComponentPeriod structures. * * Sets the list of recurrence dates in a calendar component object. **/ void cal_component_set_rdate_list (CalComponent *comp, GSList *period_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); 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; } /** * cal_component_has_rdates: * @comp: A calendar component object. * * Queries whether a calendar component object has any recurrence dates defined * for it. * * Return value: TRUE if the component has recurrence dates, FALSE otherwise. **/ gboolean cal_component_has_rdates (CalComponent *comp) { CalComponentPrivate *priv; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, FALSE); return (priv->rdate_list != NULL); } /** * cal_component_get_rrule_list: * @comp: A calendar component object. * @recur_list: List of recurrence rules as struct #icalrecurrencetype * structures. This should be freed using the cal_component_free_recur_list() * function. * * Queries the list of recurrence rule properties of a calendar component * object. **/ void cal_component_get_rrule_list (CalComponent *comp, GSList **recur_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (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->rrule_list, icalproperty_get_rrule, recur_list); } /** * cal_component_get_rrule_property_list: * @comp: A calendar component object. * @recur_list: Returns a list of recurrence rule properties. * * Queries a list of recurrence rule properties of a calendar component object. **/ void cal_component_get_rrule_property_list (CalComponent *comp, GSList **recur_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (recur_list != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); *recur_list = priv->rrule_list; } /** * cal_component_set_rrule_list: * @comp: A calendar component object. * @recur_list: List of struct #icalrecurrencetype structures. * * Sets the list of recurrence rules in a calendar component object. **/ void cal_component_set_rrule_list (CalComponent *comp, GSList *recur_list) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); set_recur_list (comp, icalproperty_new_rrule, &priv->rrule_list, recur_list); priv->need_sequence_inc = TRUE; } /** * cal_component_has_rrules: * @comp: A calendar component object. * * Queries whether a calendar component object has any recurrence rules defined * for it. * * Return value: TRUE if the component has recurrence rules, FALSE otherwise. **/ gboolean cal_component_has_rrules (CalComponent *comp) { CalComponentPrivate *priv; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, FALSE); return (priv->rrule_list != NULL); } /** * cal_component_has_recurrences: * @comp: A calendar component object * * Queries whether a calendar component object has any recurrence dates or * recurrence rules. * * Return value: TRUE if the component has recurrences, FALSE otherwise. **/ gboolean cal_component_has_recurrences (CalComponent *comp) { return cal_component_has_rdates (comp) || cal_component_has_rrules (comp); } /** * cal_component_get_sequence: * @comp: A calendar component object. * @sequence: Return value for the sequence number. This should be freed using * cal_component_free_sequence(). * * Queries the sequence number of a calendar component object. **/ void cal_component_get_sequence (CalComponent *comp, int **sequence) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (sequence != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priv->sequence) { *sequence = NULL; return; } *sequence = g_new (int, 1); **sequence = icalproperty_get_sequence (priv->sequence); } /** * cal_component_set_sequence: * @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. **/ void cal_component_set_sequence (CalComponent *comp, int *sequence) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); priv->need_sequence_inc = FALSE; if (!sequence) { if (priv->sequence) { icalcomponent_remove_property (priv->icalcomp, priv->sequence); icalproperty_free (priv->sequence); priv->sequence = NULL; } return; } if (priv->sequence) icalproperty_set_sequence (priv->sequence, *sequence); else { priv->sequence = icalproperty_new_sequence (*sequence); icalcomponent_add_property (priv->icalcomp, priv->sequence); } } /** * cal_component_get_status: * @comp: A calendar component object. * @status: Return value for the status value. It is set to #ICAL_STATUS_NONE * if the component has no status property. * * Queries the status property of a calendar component object. **/ void cal_component_get_status (CalComponent *comp, icalproperty_status *status) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (status != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priv->status) { *status = ICAL_STATUS_NONE; return; } *status = icalproperty_get_status (priv->status); } /** * cal_component_set_status: * @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. **/ void cal_component_set_status (CalComponent *comp, icalproperty_status status) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); 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; } return; } if (priv->status) { icalproperty_set_status (priv->status, status); } else { priv->status = icalproperty_new_status (status); icalcomponent_add_property (priv->icalcomp, priv->status); } } /** * cal_component_get_summary: * @comp: A calendar component object. * @summary: Return value for the summary property and its parameters. * * Queries the summary of a calendar component object. **/ void cal_component_get_summary (CalComponent *comp, CalComponentText *summary) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (summary != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (priv->summary.prop) summary->value = icalproperty_get_summary (priv->summary.prop); else summary->value = NULL; if (priv->summary.altrep_param) summary->altrep = icalparameter_get_altrep (priv->summary.altrep_param); else summary->altrep = NULL; } /** * cal_component_set_summary: * @comp: A calendar component object. * @summary: Summary property and its parameters. * * Sets the summary of a calendar component object. **/ void cal_component_set_summary (CalComponent *comp, CalComponentText *summary) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!summary) { if (priv->summary.prop) { icalcomponent_remove_property (priv->icalcomp, priv->summary.prop); icalproperty_free (priv->summary.prop); priv->summary.prop = NULL; priv->summary.altrep_param = NULL; } return; } g_return_if_fail (summary->value != NULL); if (priv->summary.prop) icalproperty_set_summary (priv->summary.prop, (char *) summary->value); else { priv->summary.prop = icalproperty_new_summary ((char *) summary->value); icalcomponent_add_property (priv->icalcomp, priv->summary.prop); } if (summary->altrep) { g_assert (priv->summary.prop != NULL); if (priv->summary.altrep_param) icalparameter_set_altrep (priv->summary.altrep_param, (char *) summary->altrep); else { priv->summary.altrep_param = icalparameter_new_altrep ( (char *) summary->altrep); icalproperty_add_parameter (priv->summary.prop, priv->summary.altrep_param); } } else if (priv->summary.altrep_param) { icalproperty_remove_parameter (priv->summary.prop, ICAL_ALTREP_PARAMETER); icalparameter_free (priv->summary.altrep_param); priv->summary.altrep_param = NULL; } } /** * cal_component_get_transparency: * @comp: A calendar component object. * @transp: Return value for the time transparency. * * Queries the time transparency of a calendar component object. **/ void cal_component_get_transparency (CalComponent *comp, CalComponentTransparency *transp) { CalComponentPrivate *priv; const char *val; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (transp != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!priv->transparency) { *transp = CAL_COMPONENT_TRANSP_NONE; return; } val = icalproperty_get_transp (priv->transparency); if (strcasecmp (val, "TRANSPARENT") == 0) *transp = CAL_COMPONENT_TRANSP_TRANSPARENT; else if (strcasecmp (val, "OPAQUE") == 0) *transp = CAL_COMPONENT_TRANSP_OPAQUE; else *transp = CAL_COMPONENT_TRANSP_UNKNOWN; } /** * cal_component_set_transparency: * @comp: A calendar component object. * @transp: Time transparency value. * * Sets the time transparency of a calendar component object. **/ void cal_component_set_transparency (CalComponent *comp, CalComponentTransparency transp) { CalComponentPrivate *priv; char *str; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (transp != CAL_COMPONENT_TRANSP_UNKNOWN); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (transp == CAL_COMPONENT_TRANSP_NONE) { if (priv->transparency) { icalcomponent_remove_property (priv->icalcomp, priv->transparency); icalproperty_free (priv->transparency); priv->transparency = NULL; } return; } switch (transp) { case CAL_COMPONENT_TRANSP_TRANSPARENT: str = "TRANSPARENT"; break; case CAL_COMPONENT_TRANSP_OPAQUE: str = "OPAQUE"; break; default: g_assert_not_reached (); str = NULL; } if (priv->transparency) icalproperty_set_transp (priv->transparency, str); else { priv->transparency = icalproperty_new_transp (str); icalcomponent_add_property (priv->icalcomp, priv->transparency); } } /** * cal_component_get_url: * @comp: A calendar component object. * @url: Return value for the URL. * * Queries the uniform resource locator property of a calendar component object. **/ void cal_component_get_url (CalComponent *comp, const char **url) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (url != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (priv->url) *url = icalproperty_get_url (priv->url); else *url = NULL; } /** * cal_component_set_url: * @comp: A calendar component object. * @url: URL value. * * Sets the uniform resource locator property of a calendar component object. **/ void cal_component_set_url (CalComponent *comp, const char *url) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); if (!url || !(*url)) { if (priv->url) { icalcomponent_remove_property (priv->icalcomp, priv->url); icalproperty_free (priv->url); priv->url = NULL; } return; } if (priv->url) icalproperty_set_url (priv->url, (char *) url); else { priv->url = icalproperty_new_url ((char *) url); icalcomponent_add_property (priv->icalcomp, priv->url); } } /** * cal_component_free_categories_list: * @categ_list: List of category strings. * * Frees a list of category strings. **/ void cal_component_free_categories_list (GSList *categ_list) { GSList *l; for (l = categ_list; l; l = l->next) g_free (l->data); g_slist_free (categ_list); } /** * cal_component_free_datetime: * @dt: A date/time structure. * * Frees a date/time structure. **/ void cal_component_free_datetime (CalComponentDateTime *dt) { g_return_if_fail (dt != NULL); if (dt->value) g_free (dt->value); } /** * cal_component_free_exdate_list: * @exdate_list: List of #CalComponentDateTime structures. * * Frees a list of #CalComponentDateTime structures as returned by the * cal_component_get_exdate_list() function. **/ void cal_component_free_exdate_list (GSList *exdate_list) { GSList *l; for (l = exdate_list; l; l = l->next) { CalComponentDateTime *cdt; g_assert (l->data != NULL); cdt = l->data; g_assert (cdt->value != NULL); g_free (cdt->value); g_free (cdt); } g_slist_free (exdate_list); } /** * cal_component_free_geo: * @geo: An #icalgeotype structure. * * Frees a struct #icalgeotype structure as returned by the calendar component * functions. **/ void cal_component_free_geo (struct icalgeotype *geo) { g_return_if_fail (geo != NULL); g_free (geo); } /** * cal_component_free_icaltimetype: * @t: An #icaltimetype structure. * * Frees a struct #icaltimetype value as returned by the calendar component * functions. **/ void cal_component_free_icaltimetype (struct icaltimetype *t) { g_return_if_fail (t != NULL); g_free (t); } /** * cal_component_free_percent: * @percent: Percent value. * * Frees a percent value as returned by the cal_component_get_percent() * function. **/ void cal_component_free_percent (int *percent) { g_return_if_fail (percent != NULL); g_free (percent); } /** * cal_component_free_priority: * @priority: Priority value. * * Frees a priority value as returned by the cal_component_get_priority() * function. **/ void cal_component_free_priority (int *priority) { g_return_if_fail (priority != NULL); g_free (priority); } /** * cal_component_free_period_list: * @period_list: List of #CalComponentPeriod structures. * * Frees a list of #CalComponentPeriod structures. **/ void cal_component_free_period_list (GSList *period_list) { GSList *l; for (l = period_list; l; l = l->next) { CalComponentPeriod *period; g_assert (l->data != NULL); period = l->data; g_free (period); } g_slist_free (period_list); } /** * cal_component_free_recur_list: * @recur_list: List of struct #icalrecurrencetype structures. * * Frees a list of struct #icalrecurrencetype structures. **/ void cal_component_free_recur_list (GSList *recur_list) { GSList *l; for (l = recur_list; l; l = l->next) { struct icalrecurrencetype *r; g_assert (l->data != NULL); r = l->data; g_free (r); } g_slist_free (recur_list); } /** * cal_component_free_sequence: * @sequence: Sequence number value. * * Frees a sequence number value. **/ void cal_component_free_sequence (int *sequence) { g_return_if_fail (sequence != NULL); g_free (sequence); } /** * cal_component_free_text_list: * @text_list: List of #CalComponentText structures. * * Frees a list of #CalComponentText structures. This function should only be * used to free lists of text values as returned by the other getter functions * of #CalComponent. **/ void cal_component_free_text_list (GSList *text_list) { GSList *l; for (l = text_list; l; l = l->next) { CalComponentText *text; g_assert (l->data != NULL); text = l->data; g_return_if_fail (text != NULL); g_free (text); } g_slist_free (text_list); } /** * cal_component_has_alarms: * @comp: A calendar component object. * * Checks whether the component has any alarms. * * Return value: TRUE if the component has any alarms. **/ gboolean cal_component_has_alarms (CalComponent *comp) { CalComponentPrivate *priv; g_return_val_if_fail (comp != NULL, FALSE); g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, FALSE); return g_hash_table_size (priv->alarm_uid_hash) != 0; } /** * cal_component_add_alarm: * @comp: A calendar component. * @alarm: An alarm. * * Adds an alarm subcomponent to a calendar component. You should have created * the @alarm by using cal_component_alarm_new(); it is invalid to use a * #CalComponentAlarm structure that came from 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 * cal_component_alarm_free(). **/ void cal_component_add_alarm (CalComponent *comp, CalComponentAlarm *alarm) { CalComponentPrivate *priv; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (alarm != NULL); priv = comp->priv; add_alarm (comp, alarm->icalcomp, icalproperty_get_x (alarm->uid)); icalcomponent_add_component (priv->icalcomp, alarm->icalcomp); } /** * cal_component_remove_alarm: * @comp: A calendar component. * @auid: UID of the alarm to remove. * * Removes an alarm subcomponent from a calendar component. If the alarm that * corresponds to the specified @auid had been fetched with * cal_component_get_alarm(), then those alarm structures will be invalid; you * should get rid of them with cal_component_alarm_free() before using this * function. **/ void cal_component_remove_alarm (CalComponent *comp, const char *auid) { CalComponentPrivate *priv; icalcomponent *alarm; g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); g_return_if_fail (auid != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid); if (!alarm) return; g_hash_table_remove (priv->alarm_uid_hash, auid); icalcomponent_remove_component (priv->icalcomp, alarm); icalcomponent_free (alarm); } /* Scans an icalproperty from a calendar component and adds its mapping to our * own alarm structure. */ static void scan_alarm_property (CalComponentAlarm *alarm, icalproperty *prop) { icalproperty_kind kind; const char *xname; kind = icalproperty_isa (prop); switch (kind) { case ICAL_ACTION_PROPERTY: alarm->action = prop; break; case ICAL_TRIGGER_PROPERTY: alarm->trigger = prop; break; case ICAL_X_PROPERTY: xname = icalproperty_get_x_name (prop); g_assert (xname != NULL); if (strcmp (xname, EVOLUTION_ALARM_UID_PROPERTY) == 0) alarm->uid = prop; break; default: break; } } /* Creates a CalComponentAlarm from a libical alarm subcomponent */ static CalComponentAlarm * make_alarm (icalcomponent *subcomp) { CalComponentAlarm *alarm; icalproperty *prop; alarm = g_new (CalComponentAlarm, 1); alarm->icalcomp = subcomp; alarm->uid = NULL; 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); g_assert (alarm->uid != NULL); return alarm; } /* Used from g_hash_table_foreach(); adds an alarm UID to a list */ static void add_alarm_uid (gpointer key, gpointer value, gpointer data) { const char *auid; GList **l; auid = key; l = data; *l = g_list_prepend (*l, g_strdup (auid)); } /** * cal_component_get_alarm_uids: * @comp: A calendar component. * * Builds a list of the unique identifiers of the alarm subcomponents inside a * calendar component. * * Return value: List of unique identifiers for alarms. This should be freed * using cal_obj_uid_list_free(). **/ GList * cal_component_get_alarm_uids (CalComponent *comp) { CalComponentPrivate *priv; GList *l; g_return_val_if_fail (comp != NULL, NULL); g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, NULL); l = NULL; g_hash_table_foreach (priv->alarm_uid_hash, add_alarm_uid, &l); return l; } /** * 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. * * Return value: The alarm subcomponent that corresponds to the specified @auid, * or #NULL if no alarm exists with that UID. This should be freed using * cal_component_alarm_free(). **/ CalComponentAlarm * cal_component_get_alarm (CalComponent *comp, const char *auid) { CalComponentPrivate *priv; icalcomponent *alarm; g_return_val_if_fail (comp != NULL, NULL); g_return_val_if_fail (IS_CAL_COMPONENT (comp), NULL); priv = comp->priv; g_return_val_if_fail (priv->icalcomp != NULL, NULL); g_return_val_if_fail (auid != NULL, NULL); alarm = g_hash_table_lookup (priv->alarm_uid_hash, auid); if (alarm) return make_alarm (alarm); else return NULL; } /** * cal_component_alarms_free: * @alarms: Component alarms structure. * * Frees a #CalComponentAlarms structure. **/ void cal_component_alarms_free (CalComponentAlarms *alarms) { GSList *l; g_return_if_fail (alarms != NULL); g_assert (alarms->comp != NULL); gtk_object_unref (GTK_OBJECT (alarms->comp)); for (l = alarms->alarms; l; l = l->next) { CalAlarmInstance *instance; instance = l->data; g_assert (instance != NULL); g_free (instance); } g_slist_free (alarms->alarms); g_free (alarms); } /** * cal_component_alarm_new: * * * * Return value: a new alarm component **/ CalComponentAlarm * cal_component_alarm_new (void) { CalComponentAlarm *alarm; char *new_auid ; alarm = g_new (CalComponentAlarm, 1); alarm->icalcomp = icalcomponent_new (ICAL_VALARM_COMPONENT); new_auid = cal_component_gen_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); alarm->action = NULL; alarm->trigger = NULL; return alarm; } /** * cal_component_alarm_clone: * @alarm: An alarm subcomponent. * * Creates a new alarm subcomponent by copying the information from another one. * * Return value: A newly-created alarm subcomponent with the same values as the * original one. Should be freed with cal_component_alarm_free(). **/ CalComponentAlarm * cal_component_alarm_clone (CalComponentAlarm *alarm) { icalcomponent *icalcomp; g_return_val_if_fail (alarm != NULL, NULL); icalcomp = icalcomponent_new_clone (alarm->icalcomp); return make_alarm (icalcomp); } /** * cal_component_alarm_get_uid: * @alarm: An alarm subcomponent. * * Queries the unique identifier of an alarm subcomponent. * * Return value: UID of the alarm. **/ const char * cal_component_alarm_get_uid (CalComponentAlarm *alarm) { g_return_val_if_fail (alarm != NULL, NULL); return alarm_uid_from_prop (alarm->uid); } /** * cal_component_alarm_get_action: * @alarm: An alarm. * @action: Return value for the alarm's action type. * * Queries the action type of an alarm. **/ void cal_component_alarm_get_action (CalComponentAlarm *alarm, CalAlarmAction *action) { enum icalproperty_action ipa; g_return_if_fail (alarm != NULL); g_return_if_fail (action != NULL); g_assert (alarm->icalcomp != NULL); if (!alarm->action) { *action = CAL_ALARM_NONE; return; } ipa = icalproperty_get_action (alarm->action); switch (ipa) { case ICAL_ACTION_AUDIO: *action = CAL_ALARM_AUDIO; break; case ICAL_ACTION_DISPLAY: *action = CAL_ALARM_DISPLAY; break; case ICAL_ACTION_EMAIL: *action = CAL_ALARM_EMAIL; break; case ICAL_ACTION_PROCEDURE: *action = CAL_ALARM_PROCEDURE; break; case ICAL_ACTION_NONE: *action = CAL_ALARM_NONE; break; default: *action = CAL_ALARM_UNKNOWN; } } /** * cal_component_alarm_set_action: * @alarm: An alarm. * @action: Action type. * * Sets the action type for an alarm. **/ void cal_component_alarm_set_action (CalComponentAlarm *alarm, CalAlarmAction action) { enum icalproperty_action ipa; g_return_if_fail (alarm != NULL); g_return_if_fail (action != CAL_ALARM_NONE); g_return_if_fail (action != CAL_ALARM_UNKNOWN); g_assert (alarm->icalcomp != NULL); switch (action) { case CAL_ALARM_AUDIO: ipa = ICAL_ACTION_AUDIO; break; case CAL_ALARM_DISPLAY: ipa = ICAL_ACTION_DISPLAY; break; case CAL_ALARM_EMAIL: ipa = ICAL_ACTION_EMAIL; break; case CAL_ALARM_PROCEDURE: ipa = ICAL_ACTION_PROCEDURE; break; default: g_assert_not_reached (); ipa = ICAL_ACTION_NONE; } if (alarm->action) icalproperty_set_action (alarm->action, ipa); else { alarm->action = icalproperty_new_action (ipa); icalcomponent_add_property (alarm->icalcomp, alarm->action); } } /** * cal_component_alarm_get_trigger: * @alarm: An alarm. * @trigger: Return value for the trigger time. * * Queries the trigger time for an alarm. **/ void cal_component_alarm_get_trigger (CalComponentAlarm *alarm, CalAlarmTrigger *trigger) { icalparameter *param; struct icaltriggertype t; gboolean relative; g_return_if_fail (alarm != NULL); g_return_if_fail (trigger != NULL); g_assert (alarm->icalcomp != NULL); if (!alarm->trigger) { trigger->type = CAL_ALARM_TRIGGER_NONE; return; } /* Get trigger type */ param = icalproperty_get_first_parameter (alarm->trigger, ICAL_VALUE_PARAMETER); if (param) { icalparameter_value value; value = icalparameter_get_value (param); switch (value) { case ICAL_VALUE_DURATION: relative = TRUE; break; case ICAL_VALUE_DATETIME: relative = FALSE; break; default: g_message ("cal_component_alarm_get_trigger(): Unknown value for trigger " "value %d; using RELATIVE", value); relative = TRUE; break; } } else relative = TRUE; /* Get trigger value and the RELATED parameter */ t = icalproperty_get_trigger (alarm->trigger); if (relative) { trigger->u.rel_duration = t.duration; param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER); if (param) { icalparameter_related rel; rel = icalparameter_get_related (param); switch (rel) { case ICAL_RELATED_START: trigger->type = CAL_ALARM_TRIGGER_RELATIVE_START; break; case ICAL_RELATED_END: trigger->type = CAL_ALARM_TRIGGER_RELATIVE_END; break; default: g_assert_not_reached (); } } else trigger->type = CAL_ALARM_TRIGGER_RELATIVE_START; } else { trigger->u.abs_time = t.time; trigger->type = CAL_ALARM_TRIGGER_ABSOLUTE; } } /** * cal_component_alarm_set_trigger: * @alarm: An alarm. * @trigger: Trigger time structure. * * Sets the trigger time of an alarm. **/ void cal_component_alarm_set_trigger (CalComponentAlarm *alarm, CalAlarmTrigger trigger) { struct icaltriggertype t; icalparameter *param; icalparameter_value value_type; icalparameter_related related; g_return_if_fail (alarm != NULL); g_return_if_fail (trigger.type != CAL_ALARM_TRIGGER_NONE); g_assert (alarm->icalcomp != NULL); /* Delete old trigger */ if (alarm->trigger) { icalcomponent_remove_property (alarm->icalcomp, alarm->trigger); icalproperty_free (alarm->trigger); alarm->trigger = NULL; } /* Set the value */ related = ICAL_RELATED_START; /* Keep GCC happy */ t.time = icaltime_null_time (); t.duration = icaldurationtype_null_duration (); switch (trigger.type) { case CAL_ALARM_TRIGGER_RELATIVE_START: t.duration = trigger.u.rel_duration; t.time.is_date = -1; value_type = ICAL_VALUE_DURATION; related = ICAL_RELATED_START; break; case CAL_ALARM_TRIGGER_RELATIVE_END: t.duration = trigger.u.rel_duration; t.time.is_date = -1; value_type = ICAL_VALUE_DURATION; related = ICAL_RELATED_END; break; case CAL_ALARM_TRIGGER_ABSOLUTE: t.time = trigger.u.abs_time; value_type = ICAL_VALUE_DATETIME; break; default: g_assert_not_reached (); return; } alarm->trigger = icalproperty_new_trigger (t); icalcomponent_add_property (alarm->icalcomp, alarm->trigger); /* Value parameters */ 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); } /* Related parameter */ if (trigger.type != CAL_ALARM_TRIGGER_ABSOLUTE) { param = icalproperty_get_first_parameter (alarm->trigger, ICAL_RELATED_PARAMETER); if (param) icalparameter_set_related (param, related); else { param = icalparameter_new_related (related); icalproperty_add_parameter (alarm->trigger, param); } } } /** * cal_component_alarm_free: * @alarm: A calendar alarm. * * Frees an alarm structure. **/ void cal_component_alarm_free (CalComponentAlarm *alarm) { g_return_if_fail (alarm != NULL); g_assert (alarm->icalcomp != NULL); if (icalcomponent_get_parent (alarm->icalcomp) == NULL) icalcomponent_free (alarm->icalcomp); alarm->icalcomp = NULL; alarm->uid = NULL; alarm->action = NULL; alarm->trigger = NULL; g_free (alarm); } /* Returns TRUE if both strings match, i.e. they are both NULL or the strings are equal. */ static gboolean cal_component_strings_match (const gchar *string1, const gchar *string2) { if (string1 == NULL || string2 == NULL) return (string1 == string2) ? TRUE : FALSE; if (!strcmp (string1, string2)) return TRUE; return FALSE; } /** * cal_component_event_dates_match: * @comp1: A calendar component object. * @comp2: A calendar component object. * * Checks if the DTSTART and DTEND properties of the 2 components match. * Note that the events may have different recurrence properties which are not * taken into account here. * * Returns: TRUE if the DTSTART and DTEND properties of the 2 components match. **/ gboolean cal_component_event_dates_match (CalComponent *comp1, CalComponent *comp2) { CalComponentDateTime comp1_dtstart, comp1_dtend; CalComponentDateTime comp2_dtstart, comp2_dtend; cal_component_get_dtstart (comp1, &comp1_dtstart); cal_component_get_dtend (comp1, &comp1_dtend); cal_component_get_dtstart (comp2, &comp2_dtstart); cal_component_get_dtend (comp2, &comp2_dtend); /* 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) return FALSE; } else { if (icaltime_compare (*comp1_dtstart.value, *comp2_dtstart.value)) return FALSE; } if (comp1_dtend.value == NULL || comp2_dtend.value == NULL) { if (comp1_dtend.value != comp2_dtend.value) return FALSE; } else { if (icaltime_compare (*comp1_dtend.value, *comp2_dtend.value)) return FALSE; } /* Now check the timezones. */ if (!cal_component_strings_match (comp1_dtstart.tzid, comp2_dtstart.tzid)) return FALSE; if (!cal_component_strings_match (comp1_dtend.tzid, comp2_dtend.tzid)) return FALSE; return TRUE; }