#include #include #include #include #include "e-cal-glue-comp.h" #include "e-cal-glue-recur.h" /* Following functions/defines are *SHAMELESSLY* copied from e-d-s/calendar/libecal/e-cal-recur.c */ /* The paramter we use to store the enddate in RRULE and EXRULE properties. */ #define EVOLUTION_END_DATE_PARAMETER "X-EVOLUTION-ENDDATE" /* If default_timezone is set, the saved ENDDATE parameter is assumed to be in that timezone. This is used when the DTSTART is a DATE or floating value, since the RRULE end date will change depending on the timezone that it is evaluated in. */ static time_t e_cal_recur_get_rule_end_date (icalproperty *prop, icaltimezone *default_timezone) { icalparameter *param; const char *xname, *xvalue; icalvalue *value; struct icaltimetype icaltime; icaltimezone *zone; param = icalproperty_get_first_parameter (prop, ICAL_X_PARAMETER); while (param) { xname = icalparameter_get_xname (param); if (xname && !strcmp (xname, EVOLUTION_END_DATE_PARAMETER)) { xvalue = icalparameter_get_x (param); value = icalvalue_new_from_string (ICAL_DATETIME_VALUE, xvalue); if (value) { icaltime = icalvalue_get_datetime (value); icalvalue_free (value); zone = default_timezone ? default_timezone : icaltimezone_get_utc_timezone (); return icaltime_as_timet_with_zone (icaltime, zone); } } param = icalproperty_get_next_parameter (prop, ICAL_X_PARAMETER); } return -1; } static gint e_cal_recur_ical_weekday_to_weekday (enum icalrecurrencetype_weekday day) { gint weekday; switch (day) { case ICAL_NO_WEEKDAY: /* Monday is the default in RFC2445. */ case ICAL_MONDAY_WEEKDAY: weekday = 0; break; case ICAL_TUESDAY_WEEKDAY: weekday = 1; break; case ICAL_WEDNESDAY_WEEKDAY: weekday = 2; break; case ICAL_THURSDAY_WEEKDAY: weekday = 3; break; case ICAL_FRIDAY_WEEKDAY: weekday = 4; break; case ICAL_SATURDAY_WEEKDAY: weekday = 5; break; case ICAL_SUNDAY_WEEKDAY: weekday = 6; break; default: g_warning ("e_cal_recur_ical_weekday_to_weekday(): Unknown week day %d", day); weekday = 0; } return weekday; } /** * e_cal_recur_from_icalproperty: * @prop: An RRULE or EXRULE #icalproperty. * @exception: TRUE if this is an EXRULE rather than an RRULE. * @zone: The DTSTART timezone, used for converting the UNTIL property if it * is given as a DATE value. * @convert_end_date: TRUE if the saved end date needs to be converted to the * given @zone timezone. This is needed if the DTSTART is a DATE or floating * time. * * Converts an #icalproperty to a #ECalRecurrence. This should be * freed using the e_cal_recur_free() function. * * Return value: #ECalRecurrence structure. **/ ECalGlueRecurrence * e_cal_recur_from_icalproperty (icalproperty *prop, gboolean exception, icaltimezone *zone, gboolean convert_end_date) { struct icalrecurrencetype ir; ECalGlueRecurrence *r; g_return_val_if_fail (prop != NULL, NULL); r = g_new (ECalGlueRecurrence, 1); if (exception) ir = icalproperty_get_exrule (prop); else ir = icalproperty_get_rrule (prop); r->handle = prop; r->freq = ir.freq; r->interval = ir.interval; r->count = ir.count; if (ir.count != 0) { /* If COUNT is set, we use the pre-calculated enddate. Note that this can be 0 if the RULE doesn't actually generate COUNT instances. */ r->until = e_cal_recur_get_rule_end_date (prop, convert_end_date ? zone : NULL); } else { if (icaltime_is_null_time (ir.until)) { /* If neither COUNT or UNTIL is set, the event recurs forever. */ r->until = 0; } else if (ir.until.is_date) { /* If UNTIL is a DATE, we stop at the end of the day, in local time (with the DTSTART timezone). Note that UNTIL is inclusive so we stop before midnight. */ ir.until.hour = 23; ir.until.minute = 59; ir.until.second = 59; ir.until.is_date = FALSE; r->until = icaltime_as_timet_with_zone (ir.until, zone); #if 0 g_print (" until: %li - %s", r->enddate, ctime (&r->enddate)); #endif } else { /* If UNTIL is a DATE-TIME, it must be in UTC. */ icaltimezone *utc_zone; utc_zone = icaltimezone_get_utc_timezone (); r->until = icaltime_as_timet_with_zone (ir.until, utc_zone); } } r->week_start_day = e_cal_recur_ical_weekday_to_weekday (ir.week_start); memcpy (r->by_second, ir.by_second, sizeof (ir.by_second)); memcpy (r->by_minute, ir.by_minute, sizeof (ir.by_minute)); memcpy (r->by_hour, ir.by_hour, sizeof (ir.by_hour)); memcpy (r->by_day, ir.by_day, sizeof (ir.by_day)); memcpy (r->by_month_day, ir.by_month_day, sizeof (ir.by_month_day)); memcpy (r->by_year_day, ir.by_year_day, sizeof (ir.by_year_day)); memcpy (r->by_week_no, ir.by_week_no, sizeof (ir.by_week_no)); memcpy (r->by_month, ir.by_month, sizeof (ir.by_month)); memcpy (r->by_set_pos, ir.by_set_pos, sizeof (ir.by_set_pos)); #if 0 r->by_month = array_to_list (ir.by_month, sizeof (ir.by_month) / sizeof (ir.by_month[0])); for (elem = r->by_month; elem; elem = elem->next) { /* We need to convert from 1-12 to 0-11, i.e. subtract 1. */ int month = GPOINTER_TO_INT (elem->data) - 1; elem->data = GINT_TO_POINTER (month); } r->by_week_no = array_to_list (ir.by_week_no, sizeof (ir.by_week_no) / sizeof (ir.by_week_no[0])); r->by_year_day = array_to_list (ir.by_year_day, sizeof (ir.by_year_day) / sizeof (ir.by_year_day[0])); r->by_month_day = array_to_list (ir.by_month_day, sizeof (ir.by_month_day) / sizeof (ir.by_month_day[0])); /* FIXME: libical only supports 8 values, out of possible 107 * 7. */ r->by_day = NULL; max_elements = sizeof (ir.by_day) / sizeof (ir.by_day[0]); for (i = 0; i < max_elements && ir.by_day[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) { enum icalrecurrencetype_weekday day; gint weeknum, weekday; day = icalrecurrencetype_day_day_of_week (ir.by_day[i]); weeknum = icalrecurrencetype_day_position (ir.by_day[i]); weekday = e_cal_recur_ical_weekday_to_weekday (day); r->by_day = g_slist_prepend (r->by_day, GINT_TO_POINTER (weeknum)); r->by_day = g_slist_prepend (r->by_day, GINT_TO_POINTER (weekday)); } r->by_hour = array_to_list (ir.by_hour, sizeof (ir.by_hour) / sizeof (ir.by_hour[0])); r->by_minute = array_to_list (ir.by_minute, sizeof (ir.by_minute) / sizeof (ir.by_minute[0])); r->by_second = array_to_list (ir.by_second, sizeof (ir.by_second) / sizeof (ir.by_second[0])); r->by_set_pos = array_to_list (ir.by_set_pos, sizeof (ir.by_set_pos) / sizeof (ir.by_set_pos[0])); #endif return r; }