Event* ICalendar::Query::GetNextEvent(bool WithAlarm) { static Event *RecurrentEvent = NULL; /* not all events have DtEnd, but we need some DtEnd for various checks, so we will use this for temporary DtEnd derived from DtStart (following RFC 2445, 4.6.1) */ Date DtEnd; unsigned long Difference; unsigned short Rest; if (RecurrentEvent != NULL) { RecurrentEvent->DtStart[RecurrentEvent->RRule.Freq] += RecurrentEvent->RRule.Interval; if (!RecurrentEvent->DtEnd.IsEmpty()) RecurrentEvent->DtEnd[RecurrentEvent->RRule.Freq] += RecurrentEvent->RRule.Interval; ++RecurrentEvent->RecurrenceNo; if ( (!WithAlarm && RecurrentEvent->DtStart <= Criteria.To && (RecurrentEvent->RRule.Until.IsEmpty() || RecurrentEvent->RRule.Until >= RecurrentEvent->DtStart) && (RecurrentEvent->RRule.Count == 0 || RecurrentEvent->RecurrenceNo < RecurrentEvent->RRule.Count)) || (WithAlarm && RecurrentEvent->HasAlarm(Criteria.From, Criteria.To)) ) { RecurrentEvents.push_back(new Event(*RecurrentEvent)); return RecurrentEvents.back(); } delete RecurrentEvent; RecurrentEvent = NULL; } if (RecurrentEvent == NULL) { for (; EventsIterator != Calendar->Events.end(); ++EventsIterator) { if ((*EventsIterator)->DtEnd.IsEmpty()) { DtEnd = (*EventsIterator)->DtStart; if ((*EventsIterator)->DtStart.WithTime == false) ++DtEnd[DAY]; } else { DtEnd = (*EventsIterator)->DtEnd; } if ( Criteria.AllEvents == true || ( !WithAlarm && // DtEnd is non-inclusive (according to RFC 2445) (DtEnd > Criteria.From || (*EventsIterator)->DtStart >= Criteria.From) && (*EventsIterator)->DtStart <= Criteria.To ) || (WithAlarm && (*EventsIterator)->HasAlarm(Criteria.From, Criteria.To)) ) { if (Criteria.AllEvents == false && Criteria.IncludeRecurrent == true && (*EventsIterator)->RRule.IsEmpty() == false) RecurrentEvent = new Event(**EventsIterator); return *(EventsIterator++); } else if ( (*EventsIterator)->RRule.IsEmpty() == false && (*EventsIterator)->DtStart < Criteria.From && ((*EventsIterator)->RRule.Until.IsEmpty() || (*EventsIterator)->RRule.Until >= Criteria.From) && Criteria.IncludeRecurrent == true ) { RecurrentEvent = new Event(**EventsIterator); Difference = Criteria.From.Difference(DtEnd, RecurrentEvent->RRule.Freq); Rest = Difference%RecurrentEvent->RRule.Interval; if (Rest != 0) Difference += RecurrentEvent->RRule.Interval - Rest; cout << Criteria.From.Format() << endl; cout << DtEnd.Format() << endl; cout << Difference << endl; RecurrentEvent->DtStart[RecurrentEvent->RRule.Freq] += Difference; DtEnd[RecurrentEvent->RRule.Freq] += Difference; RecurrentEvent->RecurrenceNo = Difference / RecurrentEvent->RRule.Interval; // <= because DtEnd is non-inclusive (according to RFC 2445) while (DtEnd <= Criteria.From) { RecurrentEvent->DtStart[RecurrentEvent->RRule.Freq] += RecurrentEvent->RRule.Interval; DtEnd[RecurrentEvent->RRule.Freq] += RecurrentEvent->RRule.Interval; ++RecurrentEvent->RecurrenceNo; } if ( (!WithAlarm && RecurrentEvent->DtStart <= Criteria.To && // < because DtStart counts as the first occurence (RecurrentEvent->RRule.Count == 0 || RecurrentEvent->RecurrenceNo < RecurrentEvent->RRule.Count)) || (WithAlarm && RecurrentEvent->HasAlarm(Criteria.From, Criteria.To)) ) { ++EventsIterator; if (!RecurrentEvent->DtEnd.IsEmpty()) RecurrentEvent->DtEnd = DtEnd; RecurrentEvents.push_back(new Event(*RecurrentEvent)); return RecurrentEvents.back(); } delete RecurrentEvent; RecurrentEvent = NULL; } } } return NULL; }