#include <glib.h>
#include <string.h>
#include <libical/icalproperty.h>
#include <libical/icaltimezone.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1