X-Git-Url: http://pileus.org/git/?p=lackey;a=blobdiff_plain;f=cal%2Fical.c;h=23844a335bcac64e1483c04abb966747431665d9;hp=f4709a93d16dbdbdd94c274c84c4a173d4fb7d4d;hb=c4a0c84c3e569bac79c82cb588d8fd600b234c0b;hpb=1eced58b01481c1658a00183f2f27f7c3cefef1a diff --git a/cal/ical.c b/cal/ical.c index f4709a9..23844a3 100644 --- a/cal/ical.c +++ b/cal/ical.c @@ -23,18 +23,135 @@ #include "date.h" #include "event.h" +/* Local types */ +typedef struct { + icalcomponent *comp; + struct icaltimetype start; + struct icaltimetype end; +} ical_inst; + /* Helper functions */ -static event_t *to_event(icalcomponent *comp) +static int ical_compare(const void *_a, const void *_b) +{ + const ical_inst *a = _a; + const ical_inst *b = _b; + int scomp = icaltime_compare(a->start, b->start); + int ecomp = icaltime_compare(a->end, b->end); + return scomp != 0 ? scomp : + ecomp != 0 ? ecomp : 0 ; +} + +static date_t to_date(struct icaltimetype time) +{ + return (date_t){ + .year = time.year, + .month = time.month-1, + .day = time.day-1, + .hour = time.hour, + .min = time.minute, + }; +} + +static event_t *to_event(ical_inst *inst) { - event_t *event = calloc(1, sizeof(event)); + event_t *event = calloc(1, sizeof(event_t)); + event->name = icalcomponent_get_summary(inst->comp); + event->desc = icalcomponent_get_description(inst->comp); + event->start = to_date(inst->start); + event->end = to_date(inst->end); return event; } +static event_t *to_list(icalarray *array) +{ + event_t list = {}; + event_t *tail = &list; + for (int i = 0; i < array->num_elements; i++) { + ical_inst *inst = icalarray_element_at(array, i); + tail->next = to_event(inst); + tail = tail->next; + } + return list.next; +} + +static void print_list(event_t *start) +{ + for (event_t *cur = start; cur; cur = cur->next) + printf("%04d-%02d-%02d %02d:%02d - %s\n", + cur->start.year, cur->start.month, cur->start.day, + cur->start.hour, cur->start.min, + cur->name ?: cur->desc ?: "[no summary]"); +} + +static void add_events(icalarray *array, icalcomponent *comp, + icaltimetype start, icaltimetype end) +{ + icalcomponent_kind kind = icalcomponent_isa(comp); + + if (kind == ICAL_VEVENT_COMPONENT || + kind == ICAL_VTODO_COMPONENT) { + /* Get recurrence data */ + struct icaltimetype cstart, cend; // Component times + struct icaltimetype istart, iend; // Instance times + struct icaldurationtype length; // Duration + + icalproperty *rrule; + struct icalrecurrencetype recur; + icalrecur_iterator *iter; + + cstart = icalcomponent_get_dtstart(comp); + cend = icalcomponent_get_dtend(comp); + length = icaltime_subtract(cend, cstart); + + rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY); + recur = icalproperty_get_rrule(rrule); + iter = icalrecur_iterator_new(recur, cstart); + + /* Add recurrences */ + while (1) { + istart = icalrecur_iterator_next(iter); + if (icaltime_is_null_time(istart)) + break; // no more instances + iend = icaltime_add(istart, length); + if (icaltime_compare(iend, start) <= 0) + continue; // instance ends before start time + if (icaltime_compare(istart, end) >= 0) + break; // instance begins after stop time + icalarray_append(array, &(ical_inst){ + .comp = comp, + .start = istart, + .end = iend, + }); + } + } + + /* Add children */ + icalcomponent_kind find = ICAL_ANY_COMPONENT; + icalcomponent *child = icalcomponent_get_first_component(comp, find); + while (child) { + add_events(array, child, start, end); + child = icalcomponent_get_next_component(comp, find); + } +} + /* Event functions */ event_t *ical_get(cal_t *cal, year_t year, month_t month, day_t day, int days) { - (void)to_event; - return NULL; + /* Load ical */ + FILE *file = fopen("data/all.ics", "r"); + icalparser *parser = icalparser_new(); + icalparser_set_gen_data(parser, file); + icalcomponent *ical = icalparser_parse(parser, (void*)fgets); + + /* Add events */ + icalarray *array = icalarray_new(sizeof(ical_inst), 1); + icaltimetype start = {.year = 2000}; + icaltimetype end = {.year = 2020}; + add_events(array, ical, start, end); + icalarray_sort(array, ical_compare); + return to_list(array); + + /* Todo, memory management */ } /* Test functions */ @@ -60,10 +177,24 @@ void ical_printr(icalcomponent *comp, int depth) void ical_test(void) { + /* Load ical */ FILE *file = fopen("data/all.ics", "r"); icalparser *parser = icalparser_new(); icalparser_set_gen_data(parser, file); icalcomponent *ical = icalparser_parse(parser, (void*)fgets); + + /* Test print */ ical_printr(ical, 0); + + /* Test Add */ + icalarray *array = icalarray_new(sizeof(ical_inst), 1); + icaltimetype start = {.year = 2000}; + icaltimetype end = {.year = 2020}; + add_events(array, ical, start, end); + icalarray_sort(array, ical_compare); + event_t *events = to_list(array); + print_list(events); + + /* Cleanup */ icalparser_free(parser); }