/* -*- Mode: C -*- ====================================================================== FILE: icalspanlist.c CREATOR: ebusboom 23 aug 2000 $Id$ $Locker$ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org This program is free software; you can redistribute it and/or modify it under the terms of either: The LGPL as published by the Free Software Foundation, version 2.1, available at: http://www.fsf.org/copyleft/lesser.html Or: The Mozilla Public License Version 1.0. You may obtain a copy of the License at http://www.mozilla.org/MPL/ ======================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ical.h" #include "icalspanlist.h" #include "pvl.h" #include /* for free and malloc */ struct icalspanlist_impl { pvl_list spans; }; int compare_span(void* a, void* b) { struct icaltime_span *span_a = (struct icaltime_span *)a ; struct icaltime_span *span_b = (struct icaltime_span *)b ; if(span_a->start == span_b->start){ return 0; } else if(span_a->start < span_b->start){ return -1; } else { /*if(span_a->start > span->b.start)*/ return 1; } } icalcomponent* icalspanlist_get_inner(icalcomponent* comp) { if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){ return icalcomponent_get_first_real_component(comp); } else { return comp; } } void print_span(int c, struct icaltime_span span ); /* Make a free list from a set of component */ icalspanlist* icalspanlist_new(icalset *set, struct icaltimetype start, struct icaltimetype end) { struct icaltime_span range; pvl_elem itr; icalcomponent *c,*inner; icalcomponent_kind kind, inner_kind; struct icalspanlist_impl *sl; struct icaltime_span *freetime; if ( ( sl = (struct icalspanlist_impl*) malloc(sizeof(struct icalspanlist_impl))) == 0) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } sl->spans = pvl_newlist(); range.start = icaltime_as_timet(start); range.end = icaltime_as_timet(end); printf("Range start: %s",ctime(&range.start)); printf("Range end : %s",ctime(&range.end)); /* Get a list of spans of busy time from the events in the set and order the spans based on the start time */ for(c = icalset_get_first_component(set); c != 0; c = icalset_get_next_component(set)){ struct icaltime_span span; kind = icalcomponent_isa(c); inner = icalcomponent_get_inner(c); if(!inner){ continue; } inner_kind = icalcomponent_isa(inner); if( kind != ICAL_VEVENT_COMPONENT && inner_kind != ICAL_VEVENT_COMPONENT){ continue; } icalerror_clear_errno(); span = icalcomponent_get_span(c); span.is_busy = 1; if(icalerrno != ICAL_NO_ERROR){ continue; } if ((range.start < span.end && icaltime_is_null_time(end)) || (range.start < span.end && range.end > span.start )){ struct icaltime_span *s; if ((s=(struct icaltime_span *) malloc(sizeof(struct icaltime_span))) == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } memcpy(s,&span,sizeof(span)); pvl_insert_ordered(sl->spans,compare_span,(void*)s); } } /* Now Fill in the free time spans. loop through the spans. if the start of the range is not within the span, create a free entry that runs from the start of the range to the start of the span. */ for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { struct icaltime_span *s = (icalproperty*)pvl_data(itr); if ((freetime=(struct icaltime_span *) malloc(sizeof(struct icaltime_span))) == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } if(range.start < s->start){ freetime->start = range.start; freetime->end = s->start; freetime->is_busy = 0; pvl_insert_ordered(sl->spans,compare_span,(void*)freetime); } else { free(freetime); } range.start = s->end; } /* If the end of the range is null, then assume that everything after the last item in the calendar is open and add a span that indicates this */ if( icaltime_is_null_time(end)){ struct icaltime_span* last_span; last_span = pvl_data(pvl_tail(sl->spans)); if (last_span != 0){ if ((freetime=(struct icaltime_span *) malloc(sizeof(struct icaltime_span))) == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } freetime->is_busy = 0; freetime->start = last_span->end; freetime->end = freetime->start; pvl_insert_ordered(sl->spans,compare_span,(void*)freetime); } } return sl; } void icalspanlist_free(icalspanlist* s) { struct icaltime_span *span; struct icalspanlist_impl* impl = (struct icalspanlist_impl*)s; while( (span=pvl_pop(impl->spans)) != 0){ free(span); } pvl_free(impl->spans); impl->spans = 0; } void icalspanlist_dump(icalspanlist* s){ int i = 0; struct icalspanlist_impl* sl = (struct icalspanlist_impl*)s; pvl_elem itr; for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { struct icaltime_span *s = (icalproperty*)pvl_data(itr); printf("#%02d %d start: %s",++i,s->is_busy,ctime(&s->start)); printf(" end : %s",ctime(&s->end)); } } icalcomponent* icalspanlist_make_free_list(icalspanlist* sl); icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl); struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl, struct icaltimetype t) { struct icalspanlist_impl* impl = (struct icalspanlist_impl*)sl; pvl_elem itr; struct icalperiodtype period; struct icaltime_span *s; time_t rangett= icaltime_as_timet(t); period.start = icaltime_null_time(); period.end = icaltime_null_time(); /* Is the reference time before the first span? If so, assume that the reference time is free */ itr = pvl_head(impl->spans); s = (icalproperty*)pvl_data(itr); if (s == 0){ /* No elements in span */ return period; } if(rangett start ){ /* End of period is start of first span if span is busy, end of the span if it is free */ period.start = t; if (s->is_busy == 0){ period.end = icaltime_from_timet(s->start,0); } else { period.end = icaltime_from_timet(s->end,0); } return period; } /* Otherwise, find the first free span that contains the reference time. */ for( itr = pvl_head(impl->spans); itr != 0; itr = pvl_next(itr)) { s = (icalproperty*)pvl_data(itr); if(s->is_busy == 0 && s->start >= rangett && ( rangett < s->end || s->end == s->start)){ if (rangett < s->start){ period.start = icaltime_from_timet(s->start,0); } else { period.start = icaltime_from_timet(rangett,0); } period.end = icaltime_from_timet(s->end,0); return period; } } period.start = icaltime_null_time(); period.end = icaltime_null_time(); return period; } struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl, struct icaltimetype t);