NS_IMETHODIMP calIcalProperty::RemoveParameter(const nsACString ¶m) { icalproperty_remove_parameter_by_name(mProperty, PromiseFlatCString(param).get()); // XXX check ical errno return NS_OK; }
/** * e_cal_util_split_at_instance: * @icalcomp: A (recurring) #icalcomponent * @rid: The base RECURRENCE-ID to remove * @master_dtstart: The DTSTART of the master object * * Splits a recurring @icalcomp into two at time @rid. The returned icalcomponent * is modified @icalcomp which contains recurrences beginning at @rid, inclusive. * The instance identified by @rid should exist. The @master_dtstart can be * a null time, then it is read from the @icalcomp. * * Use e_cal_util_remove_instances() with E_CAL_OBJ_MOD_THIS_AND_FUTURE mode * on the @icalcomp to remove the overlapping interval from it, if needed. * * Returns: the split icalcomponent, or %NULL. * * Since: 3.16 **/ icalcomponent * e_cal_util_split_at_instance (icalcomponent *icalcomp, struct icaltimetype rid, struct icaltimetype master_dtstart) { icalproperty *prop; struct instance_data instance; struct icaltimetype start, end; struct icaldurationtype duration; GSList *remove_props = NULL, *link; g_return_val_if_fail (icalcomp != NULL, NULL); g_return_val_if_fail (!icaltime_is_null_time (rid), NULL); /* Make sure this is really recurring */ if (!icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY) && !icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY)) return NULL; /* Make sure the specified instance really exists */ start = icaltime_convert_to_zone (rid, icaltimezone_get_utc_timezone ()); end = start; icaltime_adjust (&end, 0, 0, 0, 1); instance.start = icaltime_as_timet (start); instance.found = FALSE; icalcomponent_foreach_recurrence (icalcomp, start, end, check_instance, &instance); /* Make the copy */ icalcomp = icalcomponent_new_clone (icalcomp); e_cal_util_remove_instances_ex (icalcomp, rid, E_CAL_OBJ_MOD_THIS_AND_PRIOR, TRUE, FALSE); start = rid; if (icaltime_is_null_time (master_dtstart)) master_dtstart = icalcomponent_get_dtstart (icalcomp); duration = icalcomponent_get_duration (icalcomp); /* Expect that DTSTART and DTEND are already set when the instance could not be found */ if (instance.found) { icalcomponent_set_dtstart (icalcomp, start); /* Update either DURATION or DTEND */ if (icaltime_is_null_time (icalcomponent_get_dtend (icalcomp))) { icalcomponent_set_duration (icalcomp, duration); } else { end = start; if (duration.is_neg) icaltime_adjust (&end, -duration.days - 7 * duration.weeks, -duration.hours, -duration.minutes, -duration.seconds); else icaltime_adjust (&end, duration.days + 7 * duration.weeks, duration.hours, duration.minutes, duration.seconds); icalcomponent_set_dtend (icalcomp, end); } } /* any RRULE with 'count' should be shortened */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) { struct icaltimetype recur; struct icalrecurrencetype rule; rule = icalproperty_get_rrule (prop); if (rule.count != 0) { gint occurrences_count = 0; icalrecur_iterator *iter; iter = icalrecur_iterator_new (rule, master_dtstart); while (recur = icalrecur_iterator_next (iter), !icaltime_is_null_time (recur) && occurrences_count < rule.count) { if (icaltime_compare (recur, rid) >= 0) break; occurrences_count++; } icalrecur_iterator_free (iter); if (icaltime_is_null_time (recur)) { remove_props = g_slist_prepend (remove_props, prop); } else { rule.count -= occurrences_count; icalproperty_set_rrule (prop, rule); icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE"); } } } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); return icalcomp; }
static void e_cal_util_remove_instances_ex (icalcomponent *icalcomp, struct icaltimetype rid, ECalObjModType mod, gboolean keep_rid, gboolean can_add_exrule) { icalproperty *prop; struct icaltimetype itt, recur; struct icalrecurrencetype rule; icalrecur_iterator *iter; GSList *remove_props = NULL, *rrules = NULL, *link; g_return_if_fail (icalcomp != NULL); g_return_if_fail (mod != E_CAL_OBJ_MOD_ALL); /* First remove RDATEs and EXDATEs in the indicated range. */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RDATE_PROPERTY)) { struct icaldatetimeperiodtype period; period = icalproperty_get_rdate (prop); if (time_matches_rid (period.time, rid, mod) && (!keep_rid || icaltime_compare (period.time, rid) != 0)) remove_props = g_slist_prepend (remove_props, prop); } for (prop = icalcomponent_get_first_property (icalcomp, ICAL_EXDATE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_EXDATE_PROPERTY)) { itt = icalproperty_get_exdate (prop); if (time_matches_rid (itt, rid, mod) && (!keep_rid || icaltime_compare (itt, rid) != 0)) remove_props = g_slist_prepend (remove_props, prop); } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); remove_props = NULL; /* If we're only removing one instance, just add an EXDATE. */ if (mod == E_CAL_OBJ_MOD_THIS) { prop = icalproperty_new_exdate (rid); icalcomponent_add_property (icalcomp, prop); return; } /* Otherwise, iterate through RRULEs */ /* FIXME: this may generate duplicate EXRULEs */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) { rrules = g_slist_prepend (rrules, prop); } for (link = rrules; link; link = g_slist_next (link)) { prop = link->data; rule = icalproperty_get_rrule (prop); iter = icalrecur_iterator_new (rule, rid); recur = icalrecur_iterator_next (iter); if (mod & E_CAL_OBJ_MOD_THIS_AND_FUTURE) { /* Truncate the rule at rid. */ if (!icaltime_is_null_time (recur)) { /* Use count if it was used */ if (rule.count > 0) { gint occurrences_count = 0; icalrecur_iterator *count_iter; struct icaltimetype count_recur; count_iter = icalrecur_iterator_new (rule, icalcomponent_get_dtstart (icalcomp)); while (count_recur = icalrecur_iterator_next (count_iter), !icaltime_is_null_time (count_recur) && occurrences_count < rule.count) { if (icaltime_compare (count_recur, rid) >= 0) break; occurrences_count++; } icalrecur_iterator_free (count_iter); if (keep_rid && icaltime_compare (count_recur, rid) == 0) occurrences_count++; /* The caller should make sure that the remove will keep at least one instance */ g_warn_if_fail (occurrences_count > 0); rule.count = occurrences_count; } else { if (keep_rid && icaltime_compare (recur, rid) == 0) rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp)); else rule.until = rid; icaltime_adjust (&rule.until, 0, 0, 0, -1); } icalproperty_set_rrule (prop, rule); icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE"); } } else { /* (If recur == rid, skip to the next occurrence) */ if (!keep_rid && icaltime_compare (recur, rid) == 0) recur = icalrecur_iterator_next (iter); /* If there is a recurrence after rid, add * an EXRULE to block instances up to rid. * Otherwise, just remove the RRULE. */ if (!icaltime_is_null_time (recur)) { if (can_add_exrule) { rule.count = 0; /* iCalendar says we should just use rid * here, but Outlook/Exchange handle * UNTIL incorrectly. */ if (keep_rid && icaltime_compare (recur, rid) == 0) { struct icaldurationtype duration = icalcomponent_get_duration (icalcomp); duration.is_neg = !duration.is_neg; rule.until = icaltime_add (rid, duration); } else rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp)); prop = icalproperty_new_exrule (rule); icalcomponent_add_property (icalcomp, prop); } } else { remove_props = g_slist_prepend (remove_props, prop); } } icalrecur_iterator_free (iter); } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); g_slist_free (rrules); }