Example #1
0
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;
}