From ff33d95a42ef3ba28fe8d433891dfdee2b1ec0b2 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Wed, 10 Dec 2008 18:57:55 +0000 Subject: [PATCH] Monotone-Parent: 4e8caa9222644e6820515bbf312f74dbd372c2fc Monotone-Revision: 25c172f93ef4ab6ada0aeb6ff4267e98aef8b719 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-12-10T18:57:55 Monotone-Branch: ca.inverse.sogo --- SOPE/NGCards/iCalDailyRecurrenceCalculator.m | 25 +- .../NGCards/iCalMonthlyRecurrenceCalculator.m | 571 ++++++++++-------- SOPE/NGCards/iCalWeeklyRecurrenceCalculator.m | 276 +++++---- SOPE/NGCards/iCalYearlyRecurrenceCalculator.m | 123 ++-- 4 files changed, 526 insertions(+), 469 deletions(-) diff --git a/SOPE/NGCards/iCalDailyRecurrenceCalculator.m b/SOPE/NGCards/iCalDailyRecurrenceCalculator.m index a6cf31aa0..8ffa4e10a 100644 --- a/SOPE/NGCards/iCalDailyRecurrenceCalculator.m +++ b/SOPE/NGCards/iCalDailyRecurrenceCalculator.m @@ -128,25 +128,22 @@ return ranges; } -- (NSCalendarDate *) lastInstanceStartDate +- (NSCalendarDate *) lastInstanceStartDate { + NSCalendarDate *firStart, *lastInstanceStartDate; + if ([rrule repeatCount] > 0) { - long jnFirst, jnRuleLast; - NSCalendarDate *firStart, *until; - firStart = [firstRange startDate]; - jnFirst = [firStart julianNumber]; - jnRuleLast = ([rrule repeatInterval] * - [rrule repeatCount]) + - jnFirst; - until = [NSCalendarDate dateForJulianNumber:jnRuleLast]; - until = [until hour: [firStart hourOfDay] - minute: [firStart minuteOfHour] - second: [firStart secondOfMinute]]; - return until; + + lastInstanceStartDate = [firStart dateByAddingYears: 0 months: 0 + days: ([rrule repeatInterval] + * [rrule repeatCount])]; } - return [super lastInstanceStartDate]; + else + lastInstanceStartDate = [super lastInstanceStartDate]; + + return lastInstanceStartDate; } @end /* iCalDailyRecurrenceCalculator */ diff --git a/SOPE/NGCards/iCalMonthlyRecurrenceCalculator.m b/SOPE/NGCards/iCalMonthlyRecurrenceCalculator.m index 913fbf6da..6ff51d08e 100644 --- a/SOPE/NGCards/iCalMonthlyRecurrenceCalculator.m +++ b/SOPE/NGCards/iCalMonthlyRecurrenceCalculator.m @@ -32,8 +32,10 @@ #import "NSCalendarDate+ICal.h" #import -@interface iCalRecurrenceCalculator(PrivateAPI) -- (NSCalendarDate *)lastInstanceStartDate; +@interface iCalRecurrenceCalculator (PrivateAPI) + +- (NSCalendarDate *) lastInstanceStartDate; + @end // #define HEAVY_DEBUG 1 @@ -44,7 +46,8 @@ typedef BOOL NGMonthSet[12]; typedef BOOL NGMonthDaySet[32]; // 0 is unused static void -NGMonthDaySet_clear(NGMonthDaySet *daySet) +NGMonthDaySet_clear (NGMonthDaySet *daySet) + { register unsigned i; @@ -53,70 +56,81 @@ NGMonthDaySet_clear(NGMonthDaySet *daySet) } static void -NGMonthDaySet_copyOrUnion(NGMonthDaySet *base, NGMonthDaySet *new, - BOOL doCopy) +NGMonthDaySet_copyOrUnion (NGMonthDaySet *base, NGMonthDaySet *new, + BOOL doCopy) + { register unsigned i; if (doCopy) - memcpy(base, new, sizeof(NGMonthDaySet)); - else { - for (i = 1; i <= 31; i++) { - if (!(*new)[i]) - (*base)[i] = NO; + memcpy (base, new, sizeof (NGMonthDaySet)); + else + { + for (i = 1; i <= 31; i++) + { + if (! (*new)[i]) + (*base)[i] = NO; + } } - } } -static BOOL NGMonthDaySet_fillWithByMonthDay(NGMonthDaySet *daySet, - NSArray *byMonthDay) +static BOOL NGMonthDaySet_fillWithByMonthDay (NGMonthDaySet *daySet, + NSArray *byMonthDay) + { /* list of days in the month */ unsigned i, count; BOOL ok; - NGMonthDaySet_clear(daySet); + NGMonthDaySet_clear (daySet); - for (i = 0, count = [byMonthDay count], ok = YES; i < count; i++) { - int dayInMonth; /* -31..-1 and 1..31 */ + for (i = 0, count = [byMonthDay count], ok = YES; i < count; i++) + { + int dayInMonth; /* -31..-1 and 1..31 */ - if ((dayInMonth = [[byMonthDay objectAtIndex:i] intValue]) == 0) { - ok = NO; - continue; /* invalid value */ - } - if (dayInMonth > 31) { - ok = NO; - continue; /* error, value to large */ - } - if (dayInMonth < -31) { - ok = NO; - continue; /* error, value to large */ - } + if ((dayInMonth = [[byMonthDay objectAtIndex: i] intValue]) == 0) + { + ok = NO; + continue; /* invalid value */ + } + if (dayInMonth > 31) + { + ok = NO; + continue; /* error, value to large */ + } + if (dayInMonth < -31) + { + ok = NO; + continue; /* error, value to large */ + } - /* adjust negative days */ + /* adjust negative days */ - if (dayInMonth < 0) { - /* eg: -1 == last day in month, 30 days => 30 */ - dayInMonth = 32 - dayInMonth /* because we count from 1 */; - } + if (dayInMonth < 0) + { + /* eg: -1 == last day in month, 30 days => 30 */ + dayInMonth = 32 - dayInMonth /* because we count from 1 */; + } - (*daySet)[dayInMonth] = YES; - } + (*daySet)[dayInMonth] = YES; + } return ok; } -static inline unsigned iCalDoWForNSDoW(int dow) { - switch (dow) { - case 0: return iCalWeekDaySunday; - case 1: return iCalWeekDayMonday; - case 2: return iCalWeekDayTuesday; - case 3: return iCalWeekDayWednesday; - case 4: return iCalWeekDayThursday; - case 5: return iCalWeekDayFriday; - case 6: return iCalWeekDaySaturday; - case 7: return iCalWeekDaySunday; - default: return 0; - } +static inline unsigned iCalDoWForNSDoW (int dow) +{ + switch (dow) + { + case 0: return iCalWeekDaySunday; + case 1: return iCalWeekDayMonday; + case 2: return iCalWeekDayTuesday; + case 3: return iCalWeekDayWednesday; + case 4: return iCalWeekDayThursday; + case 5: return iCalWeekDayFriday; + case 6: return iCalWeekDaySaturday; + case 7: return iCalWeekDaySunday; + default: return 0; + } } #if HEAVY_DEBUG @@ -125,11 +139,12 @@ static NSString *dowEN[8] = { }; #endif -static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet, - unsigned dayMask, - unsigned firstDoWInMonth, - unsigned numberOfDaysInMonth, - int occurrence1) +static void NGMonthDaySet_fillWithByDayX (NGMonthDaySet *daySet, + unsigned dayMask, + unsigned firstDoWInMonth, + unsigned numberOfDaysInMonth, + int occurrence1) + { // TODO: this is called 'X' because the API doesn't allow for full iCalendar // functionality. The daymask must be a list of occurence+dow @@ -137,78 +152,86 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet, register int dow; /* current day of the week */ int occurrences[7] = { 0, 0, 0, 0, 0, 0, 0 } ; - NGMonthDaySet_clear(daySet); + NGMonthDaySet_clear (daySet); - if (occurrence1 >= 0) { - for (dayInMonth = 1, dow = firstDoWInMonth; dayInMonth<=31; dayInMonth++) { - // TODO: complete me + if (occurrence1 >= 0) + { + for (dayInMonth = 1, dow = firstDoWInMonth; dayInMonth<=31; dayInMonth++) + { + // TODO: complete me - if (dayMask & iCalDoWForNSDoW(dow)) { - if (occurrence1 == 0) - (*daySet)[dayInMonth] = YES; - else { /* occurrence1 > 0 */ - occurrences[dow] = occurrences[dow] + 1; + if (dayMask & iCalDoWForNSDoW (dow)) + { + if (occurrence1 == 0) + (*daySet)[dayInMonth] = YES; + else { /* occurrence1 > 0 */ + occurrences[dow] = occurrences[dow] + 1; - if (occurrences[dow] == occurrence1) - (*daySet)[dayInMonth] = YES; - } - } + if (occurrences[dow] == occurrence1) + (*daySet)[dayInMonth] = YES; + } + } - dow = (dow == 6 /* Sat */) ? 0 /* Sun */ : (dow + 1); - } - } - else { - int lastDoWInMonthSet; - - /* get the last dow in the set (not necessarily the month!) */ - for (dayInMonth = 1, dow = firstDoWInMonth; - dayInMonth < numberOfDaysInMonth;dayInMonth++) - dow = (dow == 6 /* Sat */) ? 0 /* Sun */ : (dow + 1); - lastDoWInMonthSet = dow; - -#if HEAVY_DEBUG - NSLog(@"LAST DOW IN SET: %i / %@", - lastDoWInMonthSet, dowEN[lastDoWInMonthSet]); -#endif - /* start at the end of the set */ - for (dayInMonth = numberOfDaysInMonth, dow = lastDoWInMonthSet; - dayInMonth >= 1; dayInMonth--) { - // TODO: complete me - -#if HEAVY_DEBUG - NSLog(@" CHECK day-of-month %02i, " - @" dow=%i/%@ (first=%i/%@, last=%i/%@)", - dayInMonth, - dow, dowEN[dow], - firstDoWInMonth, dowEN[firstDoWInMonth], - lastDoWInMonthSet, dowEN[lastDoWInMonthSet] - ); -#endif - - if (dayMask & iCalDoWForNSDoW(dow)) { - occurrences[dow] = occurrences[dow] + 1; -#if HEAVY_DEBUG - NSLog(@" MATCH %i/%@ count: %i occurences=%i", - dow, dowEN[dow], occurrences[dow], occurrence1); -#endif - - if (occurrences[dow] == -occurrence1) { -#if HEAVY_DEBUG - NSLog(@" COUNT MATCH"); -#endif - (*daySet)[dayInMonth] = YES; + dow = (dow == 6 /* Sat */) ? 0 /* Sun */ : (dow + 1); + } + } + else + { + int lastDoWInMonthSet; + + /* get the last dow in the set (not necessarily the month!) */ + for (dayInMonth = 1, dow = firstDoWInMonth; + dayInMonth < numberOfDaysInMonth;dayInMonth++) + dow = (dow == 6 /* Sat */) ? 0 /* Sun */ : (dow + 1); + lastDoWInMonthSet = dow; + +#if HEAVY_DEBUG + NSLog (@"LAST DOW IN SET: %i / %@", + lastDoWInMonthSet, dowEN[lastDoWInMonthSet]); +#endif + /* start at the end of the set */ + for (dayInMonth = numberOfDaysInMonth, dow = lastDoWInMonthSet; + dayInMonth >= 1; dayInMonth--) + { + // TODO: complete me + +#if HEAVY_DEBUG + NSLog (@" CHECK day-of-month %02i, " + @" dow=%i/%@ (first=%i/%@, last=%i/%@)", + dayInMonth, + dow, dowEN[dow], + firstDoWInMonth, dowEN[firstDoWInMonth], + lastDoWInMonthSet, dowEN[lastDoWInMonthSet] + ); +#endif + + if (dayMask & iCalDoWForNSDoW (dow)) + { + occurrences[dow] = occurrences[dow] + 1; +#if HEAVY_DEBUG + NSLog (@" MATCH %i/%@ count: %i occurences=%i", + dow, dowEN[dow], occurrences[dow], occurrence1); +#endif + + if (occurrences[dow] == -occurrence1) + { +#if HEAVY_DEBUG + NSLog (@" COUNT MATCH"); +#endif + (*daySet)[dayInMonth] = YES; + } + } + + dow = (dow == 0 /* Sun */) ? 6 /* Sat */ : (dow - 1); } - } - - dow = (dow == 0 /* Sun */) ? 6 /* Sat */ : (dow - 1); } - } } -- (BOOL)_addInstanceWithStartDate:(NSCalendarDate *)_startDate - limitDate:(NSCalendarDate *)_until - limitRange:(NGCalendarDateRange *)_r - toArray:(NSMutableArray *)_ranges +- (BOOL) _addInstanceWithStartDate: (NSCalendarDate *)_startDate + limitDate: (NSCalendarDate *)_until + limitRange: (NGCalendarDateRange *)_r + toArray: (NSMutableArray *)_ranges + { NGCalendarDateRange *r; NSCalendarDate *end; @@ -218,29 +241,32 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet, // TODO: I think we should check in here whether we succeeded the // repeatCount. Currently we precalculate that info in the // -lastInstanceStartDate method. - if (_until != nil) { - /* Note: the 'until' in the rrule is inclusive as per spec */ - if ([_until compare:_startDate] == NSOrderedAscending) - /* start after until */ - return NO; /* Note: we assume that the algorithm is sequential */ - } + if (_until != nil) + { + /* Note: the 'until' in the rrule is inclusive as per spec */ + if ([_until compare: _startDate] == NSOrderedAscending) + /* start after until */ + return NO; /* Note: we assume that the algorithm is sequential */ + } /* create end date */ - end = [_startDate addTimeInterval:[self->firstRange duration]]; - [end setTimeZone:[_startDate timeZone]]; + end = [_startDate addTimeInterval: [firstRange duration]]; + [end setTimeZone: [_startDate timeZone]]; /* create range and check whether its in the requested range */ - r = [[NGCalendarDateRange alloc] initWithStartDate:_startDate endDate:end]; - if ([_r containsDateRange:r]) - [_ranges addObject:r]; + r = [[NGCalendarDateRange alloc] initWithStartDate: _startDate endDate: end]; + if ([_r containsDateRange: r]) + [_ranges addObject: r]; [r release]; r = nil; return YES; } -- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{ +- (NSArray *) + recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r +{ /* main entry */ // TODO: check whether this is OK for multiday-events! NSMutableArray *ranges; @@ -257,214 +283,225 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet, NSArray *byMonthDay; // array of ints (-31..-1 and 1..31) NGMonthDaySet byMonthDaySet; - eventStartDate = [self->firstRange startDate]; + eventStartDate = [firstRange startDate]; eventDayOfMonth = [eventStartDate dayOfMonth]; timeZone = [eventStartDate timeZone]; rStart = [_r startDate]; rEnd = [_r endDate]; - interval = [self->rrule repeatInterval]; + interval = [rrule repeatInterval]; until = [self lastInstanceStartDate]; // TODO: maybe replace - byMonthDay = [self->rrule byMonthDay]; + byMonthDay = [rrule byMonthDay]; /* check whether the range to be processed is beyond the 'until' date */ - if (until) { - if ([until compare:rStart] == NSOrderedAscending) /* until before start */ - return nil; - if ([until compare:rEnd] == NSOrderedDescending) /* end before until */ - rEnd = until; // TODO: why is that? end is _before_ until? - } + if (until) + { + if ([until compare: rStart] == NSOrderedAscending) /* until before start */ + return nil; + if ([until compare: rEnd] == NSOrderedDescending) /* end before until */ + rEnd = until; // TODO: why is that? end is _before_ until? + } /* precalculate month days (same for all instances) */ - if (byMonthDay) { + if (byMonthDay) + { #if HEAVY_DEBUG - NSLog(@"byMonthDay: %@", byMonthDay); + NSLog (@"byMonthDay: %@", byMonthDay); #endif - NGMonthDaySet_fillWithByMonthDay(&byMonthDaySet, byMonthDay); - } + NGMonthDaySet_fillWithByMonthDay (&byMonthDaySet, byMonthDay); + } // TODO: I think the 'diff' is to skip recurrence which are before the // requested range. Not sure whether this is actually possible, eg // the repeatCount must be processed from the start. - diff = [eventStartDate monthsBetweenDate:rStart]; - if ((diff != 0) && [rStart compare:eventStartDate] == NSOrderedAscending) + diff = [eventStartDate monthsBetweenDate: rStart]; + if ((diff != 0) && [rStart compare: eventStartDate] == NSOrderedAscending) diff = -diff; - numberOfMonthsInRange = [rStart monthsBetweenDate:rEnd] + 1; - ranges = [NSMutableArray arrayWithCapacity:numberOfMonthsInRange]; + numberOfMonthsInRange = [rStart monthsBetweenDate: rEnd] + 1; + ranges = [NSMutableArray arrayWithCapacity: numberOfMonthsInRange]; /* Note: we do not add 'eventStartDate', this is intentional, the event date - itself is _not_ necessarily part of the sequence, eg with monthly - byday recurrences. + itself is _not_ necessarily part of the sequence, eg with monthly + byday recurrences. */ for (monthIdxInRange = 0; monthIdxInRange < numberOfMonthsInRange; - monthIdxInRange++) { - NSCalendarDate *cursor; - unsigned numDaysInMonth; - int monthIdxInRecurrence, dom; - NGMonthDaySet monthDays; - BOOL didByFill, doCont; + monthIdxInRange++) + { + NSCalendarDate *cursor; + unsigned numDaysInMonth; + int monthIdxInRecurrence, dom; + NGMonthDaySet monthDays; + BOOL didByFill, doCont; - monthIdxInRecurrence = diff + monthIdxInRange; + monthIdxInRecurrence = diff + monthIdxInRange; - if (monthIdxInRecurrence < 0) - continue; + if (monthIdxInRecurrence < 0) + continue; - /* first check whether we are in the interval */ + /* first check whether we are in the interval */ - if ((monthIdxInRecurrence % interval) != 0) - continue; + if ((monthIdxInRecurrence % interval) != 0) + continue; - /* - Then the sequence is: - - check whether the month is in the BYMONTH list - */ + /* + Then the sequence is: + - check whether the month is in the BYMONTH list + */ - /* - Note: the function below adds exactly a month, eg: - 2007-01-30 + 1month => 2007-02-*28*!! - */ - cursor = [eventStartDate dateByAddingYears:0 - months:(diff + monthIdxInRange) - days:0]; - [cursor setTimeZone:timeZone]; - numDaysInMonth = [cursor numberOfDaysInMonth]; + /* + Note: the function below adds exactly a month, eg: + 2007-01-30 + 1month => 2007-02-*28*!! + */ + cursor = [eventStartDate dateByAddingYears: 0 + months: (diff + monthIdxInRange) + days: 0]; + [cursor setTimeZone: timeZone]; + numDaysInMonth = [cursor numberOfDaysInMonth]; - /* check whether we match the bymonth specification */ + /* check whether we match the bymonth specification */ - if (!byMonthList[[cursor monthOfYear] - 1]) - continue; + if (!byMonthList[[cursor monthOfYear] - 1]) + continue; - /* check 'day level' byXYZ rules */ + /* check 'day level' byXYZ rules */ - didByFill = NO; + didByFill = NO; - if (byMonthDay) { /* list of days in the month */ - NGMonthDaySet_copyOrUnion(&monthDays, &byMonthDaySet, !didByFill); - didByFill = YES; - } + if (byMonthDay) + { /* list of days in the month */ + NGMonthDaySet_copyOrUnion (&monthDays, &byMonthDaySet, !didByFill); + didByFill = YES; + } - if ([self->rrule byDayMask] != 0) { // TODO: replace the mask with an array - NGMonthDaySet ruleset; - unsigned firstDoWInMonth; + if ([rrule byDayMask] != 0) + { // TODO: replace the mask with an array + NGMonthDaySet ruleset; + unsigned firstDoWInMonth; - firstDoWInMonth = [[cursor firstDayOfMonth] dayOfWeek]; + firstDoWInMonth = [[cursor firstDayOfMonth] dayOfWeek]; - NGMonthDaySet_fillWithByDayX(&ruleset, - [self->rrule byDayMask], - firstDoWInMonth, - [cursor numberOfDaysInMonth], - [self->rrule byDayOccurence1]); - NGMonthDaySet_copyOrUnion(&monthDays, &ruleset, !didByFill); - didByFill = YES; - } + NGMonthDaySet_fillWithByDayX (&ruleset, + [rrule byDayMask], + firstDoWInMonth, + [cursor numberOfDaysInMonth], + [rrule byDayOccurence1]); + NGMonthDaySet_copyOrUnion (&monthDays, &ruleset, !didByFill); + didByFill = YES; + } - if (!didByFill) { - /* no rules applied, take the dayOfMonth of the startDate */ - NGMonthDaySet_clear(&monthDays); - monthDays[eventDayOfMonth] = YES; - } + if (!didByFill) + { + /* no rules applied, take the dayOfMonth of the startDate */ + NGMonthDaySet_clear (&monthDays); + monthDays[eventDayOfMonth] = YES; + } - // TODO: add processing of byhour/byminute/bysecond etc + // TODO: add processing of byhour/byminute/bysecond etc - /* - Next step is to create NSCalendarDate instances from our 'monthDays' - set. We walk over each day of the 'monthDays' set. If its flag isn't - set, we continue. - If its set, we add the date to the instance. + /* + Next step is to create NSCalendarDate instances from our 'monthDays' + set. We walk over each day of the 'monthDays' set. If its flag isn't + set, we continue. + If its set, we add the date to the instance. - The 'cursor' is the *startdate* of the event (not necessarily a - component of the sequence!) plus the currently processed month. - Eg: + The 'cursor' is the *startdate* of the event (not necessarily a + component of the sequence!) plus the currently processed month. + Eg: startdate: 2007-01-30 cursor[1]: 2007-01-30 cursor[2]: 2007-02-28 <== Note: we have February! - */ + */ - for (dom = 1, doCont = YES; dom <= numDaysInMonth && doCont; dom++) { - NSCalendarDate *start; + for (dom = 1, doCont = YES; dom <= numDaysInMonth && doCont; dom++) + { + NSCalendarDate *start; - if (!monthDays[dom]) - continue; + if (!monthDays[dom]) + continue; - // TODO: what is this good for? - /* - Here we need to correct the date. Remember that the startdate given in - the event is not necessarily a date of the sequence! + // TODO: what is this good for? + /* + Here we need to correct the date. Remember that the startdate given in + the event is not necessarily a date of the sequence! - The 'numDaysInMonth' localvar contains the number of days in the - current month (eg 31 for Januar, 28 for most February's, etc) + The 'numDaysInMonth' localvar contains the number of days in the + current month (eg 31 for Januar, 28 for most February's, etc) - Eg: MONTHLY;BYDAY=-1WE (last wednesday, every month) + Eg: MONTHLY;BYDAY=-1WE (last wednesday, every month) - cursor: 2007-01-30 (eventDayOfMonth = 30) - =>start: 2007-01-31 (dom = 31) - cursor: 2007-02-28 (eventDayOfMonth = 30) - =>start: 2007-02-28 (dom = 28) + cursor: 2007-01-30 (eventDayOfMonth = 30) + =>start: 2007-01-31 (dom = 31) + cursor: 2007-02-28 (eventDayOfMonth = 30) + =>start: 2007-02-28 (dom = 28) - Note: in case the cursor already had an event-day overflow, that is the - 'eventDayOfMonth' is bigger than the 'numDaysInMonth', the cursor - will already be corrected! - Eg: - start was: 2007-01-30 - cursor will be: 2007-02-28 - */ - if (eventDayOfMonth == dom) { - start = cursor; - } - else { - int maxDay = - eventDayOfMonth > numDaysInMonth ? numDaysInMonth : eventDayOfMonth; + Note: in case the cursor already had an event-day overflow, that is the + 'eventDayOfMonth' is bigger than the 'numDaysInMonth', the cursor + will already be corrected! + Eg: + start was: 2007-01-30 + cursor will be: 2007-02-28 + */ + if (eventDayOfMonth == dom) + { + start = cursor; + } + else + { + int maxDay = + eventDayOfMonth > numDaysInMonth ? numDaysInMonth : eventDayOfMonth; - start = [cursor dateByAddingYears:0 months:0 days:(dom - maxDay)]; - } + start = [cursor dateByAddingYears: 0 months: 0 days: (dom - maxDay)]; + } - /* - Setup for 2007-02-28, MONTHLY;BYDAY=-1WE. - dom: 28 - eventDayOfMonth: 31 - cursor: 2007-02-28 - start: 2007-02-25 <== WRONG - */ + /* + Setup for 2007-02-28, MONTHLY;BYDAY=-1WE. + dom: 28 + eventDayOfMonth: 31 + cursor: 2007-02-28 + start: 2007-02-25 <== WRONG + */ #if HEAVY_DEBUG - NSLog(@"DOM %i EDOM %i NUMDAYS %i START: %@ CURSOR: %@", - dom, eventDayOfMonth, numDaysInMonth, - start, cursor); + NSLog (@"DOM %i EDOM %i NUMDAYS %i START: %@ CURSOR: %@", + dom, eventDayOfMonth, numDaysInMonth, + start, cursor); #endif - doCont = [self _addInstanceWithStartDate:start - limitDate:until - limitRange:_r - toArray:ranges]; + doCont = [self _addInstanceWithStartDate: start + limitDate: until + limitRange: _r + toArray: ranges]; + } + if (!doCont) break; /* reached some limit */ } - if (!doCont) break; /* reached some limit */ - } return ranges; } -- (NSCalendarDate *)lastInstanceStartDate { - if ([self->rrule repeatCount] > 0) { - NSCalendarDate *until; - unsigned months, interval; +- (NSCalendarDate *) lastInstanceStartDate +{ + if ([rrule repeatCount] > 0) + { + NSCalendarDate *until; + unsigned months, interval; - interval = [self->rrule repeatInterval]; - months = [self->rrule repeatCount] - 1 /* the first counts as one! */; + interval = [rrule repeatInterval]; + months = [rrule repeatCount] - 1 /* the first counts as one! */; - if (interval > 0) - months *= interval; + if (interval > 0) + months *= interval; - until = [[self->firstRange startDate] dateByAddingYears:0 - months:months - days:0]; - return until; - } + until = [[firstRange startDate] dateByAddingYears: 0 + months: months + days: 0]; + return until; + } return [super lastInstanceStartDate]; } diff --git a/SOPE/NGCards/iCalWeeklyRecurrenceCalculator.m b/SOPE/NGCards/iCalWeeklyRecurrenceCalculator.m index 4c2dd0b3e..4c3ac9421 100644 --- a/SOPE/NGCards/iCalWeeklyRecurrenceCalculator.m +++ b/SOPE/NGCards/iCalWeeklyRecurrenceCalculator.m @@ -1,20 +1,20 @@ /* Copyright (C) 2004-2005 SKYRIX Software AG - + This file is part of SOPE. - + SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + SOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public - License along with SOPE; see the file COPYING. If not, write to the + License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -34,17 +34,17 @@ - (NSCalendarDate *) lastInstanceStartDate; -- (unsigned) offsetFromSundayForJulianNumber:(long)_jn; -- (unsigned) offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay; +- (unsigned) offsetFromSundayForJulianNumber: (long) _jn; +- (unsigned) offsetFromSundayForWeekDay: (iCalWeekDay) _weekDay; - (unsigned) offsetFromSundayForCurrentWeekStart; - -- (iCalWeekDay) weekDayForJulianNumber:(long)_jn; + +- (iCalWeekDay) weekDayForJulianNumber: (long) _jn; @end /* - TODO: If BYDAY is specified, lastInstanceStartDate and recurrences will - differ significantly! + TODO: If BYDAY is specified, lastInstanceStartDate and recurrences will + differ significantly! */ @implementation iCalWeeklyRecurrenceCalculator @@ -53,140 +53,156 @@ { NSMutableArray *ranges; NSCalendarDate *firStart; - long i, jnFirst, jnStart, jnEnd, startEndCount; - unsigned interval, byDayMask; + long i, jnFirst, jnStart, jnEnd, startEndCount; + unsigned interval, byDayMask; - firStart = [self->firstRange startDate]; - jnFirst = [firStart julianNumber]; - jnEnd = [[_r endDate] julianNumber]; - + firStart = [firstRange startDate]; + jnFirst = [firStart julianNumber]; + jnEnd = [[_r endDate] julianNumber]; + if (jnFirst > jnEnd) return nil; - - jnStart = [[_r startDate] julianNumber]; - interval = [self->rrule repeatInterval]; - + + jnStart = [[_r startDate] julianNumber]; + interval = [rrule repeatInterval]; + /* if rule is bound, check the bounds */ - if (![self->rrule isInfinite]) { - NSCalendarDate *until; - long jnRuleLast; - - until = [self->rrule untilDate]; - if (until) { - if ([until compare:[_r startDate]] == NSOrderedAscending) - return nil; - jnRuleLast = [until julianNumber]; + if (![rrule isInfinite]) + { + NSCalendarDate *until; + long jnRuleLast; + + until = [rrule untilDate]; + if (until) + { + if ([until compare: [_r startDate]] == NSOrderedAscending) + return nil; + jnRuleLast = [until julianNumber]; + } + else + { + jnRuleLast = (interval * [rrule repeatCount] * 7) + + jnFirst; + if (jnRuleLast < jnStart) + return nil; + } + /* jnStart < jnRuleLast < jnEnd ? */ + if (jnEnd > jnRuleLast) + jnEnd = jnRuleLast; } - else { - jnRuleLast = (interval * [self->rrule repeatCount] * 7) - + jnFirst; - if (jnRuleLast < jnStart) - return nil; - } - /* jnStart < jnRuleLast < jnEnd ? */ - if (jnEnd > jnRuleLast) - jnEnd = jnRuleLast; - } - + startEndCount = (jnEnd - jnStart) + 1; - ranges = [NSMutableArray arrayWithCapacity:startEndCount]; - byDayMask = [self->rrule byDayMask]; - if (!byDayMask) { - for (i = 0 ; i < startEndCount; i++) { - long jnCurrent; - - jnCurrent = jnStart + i; - if (jnCurrent >= jnFirst) { - long jnDiff; - - jnDiff = jnCurrent - jnFirst; /* difference in days */ - if ((jnDiff % (interval * 7)) == 0) { - NSCalendarDate *start, *end; - NGCalendarDateRange *r; - - start = [NSCalendarDate dateForJulianNumber:jnCurrent]; - [start setTimeZone:[firStart timeZone]]; - start = [start hour: [firStart hourOfDay] - minute:[firStart minuteOfHour] - second:[firStart secondOfMinute]]; - end = [start addTimeInterval:[self->firstRange duration]]; - r = [NGCalendarDateRange calendarDateRangeWithStartDate:start - endDate:end]; - if ([_r containsDateRange:r]) - [ranges addObject:r]; - } - } + ranges = [NSMutableArray arrayWithCapacity: startEndCount]; + byDayMask = [rrule byDayMask]; + if (!byDayMask) + { + for (i = 0 ; i < startEndCount; i++) + { + long jnCurrent; + + jnCurrent = jnStart + i; + if (jnCurrent >= jnFirst) + { + long jnDiff; + + jnDiff = jnCurrent - jnFirst; /* difference in days */ + if ((jnDiff % (interval * 7)) == 0) + { + NSCalendarDate *start, *end; + NGCalendarDateRange *r; + + start = [NSCalendarDate dateForJulianNumber: jnCurrent]; + [start setTimeZone: [firStart timeZone]]; + start = [start hour: [firStart hourOfDay] + minute: [firStart minuteOfHour] + second: [firStart secondOfMinute]]; + end = [start addTimeInterval: [firstRange duration]]; + r = [NGCalendarDateRange calendarDateRangeWithStartDate: start + endDate: end]; + if ([_r containsDateRange: r]) + [ranges addObject: r]; + } + } + } } - } - else { - long jnFirstWeekStart, weekStartOffset; + else + { + long jnFirstWeekStart, weekStartOffset; - /* calculate jnFirst's week start - this depends on our setting of week - start */ - weekStartOffset = [self offsetFromSundayForJulianNumber:jnFirst] - - [self offsetFromSundayForCurrentWeekStart]; + /* calculate jnFirst's week start - this depends on our setting of week + start */ + weekStartOffset = [self offsetFromSundayForJulianNumber: jnFirst] - + [self offsetFromSundayForCurrentWeekStart]; - jnFirstWeekStart = jnFirst - weekStartOffset; + jnFirstWeekStart = jnFirst - weekStartOffset; - for (i = 0 ; i < startEndCount; i++) { - long jnCurrent; + for (i = 0 ; i < startEndCount; i++) + { + long jnCurrent; - jnCurrent = jnStart + i; - if (jnCurrent >= jnFirst) { - long jnDiff; - - /* we need to calculate a difference in weeks */ - jnDiff = (jnCurrent - jnFirstWeekStart) % 7; - if ((jnDiff % interval) == 0) { - BOOL isRecurrence = NO; - - if (jnCurrent == jnFirst) { - isRecurrence = YES; - } - else { - iCalWeekDay weekDay; + jnCurrent = jnStart + i; + if (jnCurrent >= jnFirst) + { + long jnDiff; + + /* we need to calculate a difference in weeks */ + jnDiff = (jnCurrent - jnFirstWeekStart) % 7; + if ((jnDiff % interval) == 0) + { + BOOL isRecurrence = NO; + + if (jnCurrent == jnFirst) + { + isRecurrence = YES; + } + else + { + iCalWeekDay weekDay; - weekDay = [self weekDayForJulianNumber:jnCurrent]; - isRecurrence = (weekDay & [self->rrule byDayMask]) ? YES : NO; - } - if (isRecurrence) { - NSCalendarDate *start, *end; - NGCalendarDateRange *r; - - start = [NSCalendarDate dateForJulianNumber:jnCurrent]; - [start setTimeZone:[firStart timeZone]]; - start = [start hour: [firStart hourOfDay] - minute:[firStart minuteOfHour] - second:[firStart secondOfMinute]]; - end = [start addTimeInterval:[self->firstRange duration]]; - r = [NGCalendarDateRange calendarDateRangeWithStartDate:start - endDate:end]; - if ([_r containsDateRange:r]) - [ranges addObject:r]; - } - } - } + weekDay = [self weekDayForJulianNumber: jnCurrent]; + isRecurrence = (weekDay & [rrule byDayMask]) ? YES : NO; + } + if (isRecurrence) + { + NSCalendarDate *start, *end; + NGCalendarDateRange *r; + + start = [NSCalendarDate dateForJulianNumber: jnCurrent]; + [start setTimeZone: [firStart timeZone]]; + start = [start hour: [firStart hourOfDay] + minute: [firStart minuteOfHour] + second: [firStart secondOfMinute]]; + end = [start addTimeInterval: [firstRange duration]]; + r = [NGCalendarDateRange calendarDateRangeWithStartDate: start + endDate: end]; + if ([_r containsDateRange: r]) + [ranges addObject: r]; + } + } + } + } } - } return ranges; } -- (NSCalendarDate *)lastInstanceStartDate { - if ([self->rrule repeatCount] > 0) { - long jnFirst, jnRuleLast; - NSCalendarDate *firStart, *until; - - firStart = [self->firstRange startDate]; - jnFirst = [firStart julianNumber]; - jnRuleLast = ([self->rrule repeatInterval] * - [self->rrule repeatCount] * 7) + - jnFirst; - until = [NSCalendarDate dateForJulianNumber:jnRuleLast]; - until = [until hour: [firStart hourOfDay] - minute:[firStart minuteOfHour] - second:[firStart secondOfMinute]]; - return until; - } +- (NSCalendarDate *) lastInstanceStartDate +{ + if ([rrule repeatCount] > 0) + { + long jnFirst, jnRuleLast; + NSCalendarDate *firStart, *until; + + firStart = [firstRange startDate]; + jnFirst = [firStart julianNumber]; + jnRuleLast = ([rrule repeatInterval] * + [rrule repeatCount] * 7) + + jnFirst; + until = [NSCalendarDate dateForJulianNumber: jnRuleLast]; + until = [until hour: [firStart hourOfDay] + minute: [firStart minuteOfHour] + second: [firStart secondOfMinute]]; + return until; + } return [super lastInstanceStartDate]; } diff --git a/SOPE/NGCards/iCalYearlyRecurrenceCalculator.m b/SOPE/NGCards/iCalYearlyRecurrenceCalculator.m index 53603d5e4..12112b0f2 100644 --- a/SOPE/NGCards/iCalYearlyRecurrenceCalculator.m +++ b/SOPE/NGCards/iCalYearlyRecurrenceCalculator.m @@ -1,20 +1,20 @@ /* Copyright (C) 2004-2005 SKYRIX Software AG - + This file is part of SOPE. - + SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + SOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public - License along with SOPE; see the file COPYING. If not, write to the + License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -30,71 +30,78 @@ #import "iCalRecurrenceRule.h" #import "NSCalendarDate+ICal.h" -@interface iCalRecurrenceCalculator(PrivateAPI) -- (NSCalendarDate *)lastInstanceStartDate; +@interface iCalRecurrenceCalculator (PrivateAPI) +- (NSCalendarDate *) lastInstanceStartDate; @end @implementation iCalYearlyRecurrenceCalculator -- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{ +- (NSArray *) + recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r +{ NSMutableArray *ranges; NSCalendarDate *firStart, *rStart, *rEnd, *until; - unsigned i, count, interval; - int diff; - - firStart = [self->firstRange startDate]; - rStart = [_r startDate]; - rEnd = [_r endDate]; - interval = [self->rrule repeatInterval]; - until = [self lastInstanceStartDate]; - - if (until) { - if ([until compare:rStart] == NSOrderedAscending) - return nil; - if ([until compare:rEnd] == NSOrderedDescending) - rEnd = until; - } - - diff = [firStart yearsBetweenDate:rStart]; - if ((diff != 0) && [rStart compare:firStart] == NSOrderedAscending) + unsigned i, count, interval; + int diff; + + firStart = [firstRange startDate]; + rStart = [_r startDate]; + rEnd = [_r endDate]; + interval = [rrule repeatInterval]; + until = [self lastInstanceStartDate]; + + if (until) + { + if ([until compare: rStart] == NSOrderedAscending) + return nil; + if ([until compare: rEnd] == NSOrderedDescending) + rEnd = until; + } + + diff = [firStart yearsBetweenDate: rStart]; + if ((diff != 0) && [rStart compare: firStart] == NSOrderedAscending) diff = -diff; - count = [rStart yearsBetweenDate:rEnd] + 1; - ranges = [NSMutableArray arrayWithCapacity:count]; - for (i = 0 ; i < count; i++) { - int test; + count = [rStart yearsBetweenDate: rEnd] + 1; + ranges = [NSMutableArray arrayWithCapacity: count]; + for (i = 0 ; i < count; i++) + { + int test; - test = diff + i; - if ((test >= 0) && (test % interval) == 0) { - NSCalendarDate *start, *end; - NGCalendarDateRange *r; - - start = [firStart dateByAddingYears:diff + i - months:0 - days:0]; - [start setTimeZone:[firStart timeZone]]; - end = [start addTimeInterval:[self->firstRange duration]]; - r = [NGCalendarDateRange calendarDateRangeWithStartDate:start - endDate:end]; - if ([_r containsDateRange:r]) - [ranges addObject:r]; + test = diff + i; + if ((test >= 0) && (test % interval) == 0) + { + NSCalendarDate *start, *end; + NGCalendarDateRange *r; + + start = [firStart dateByAddingYears: diff + i + months: 0 + days: 0]; + [start setTimeZone: [firStart timeZone]]; + end = [start addTimeInterval: [firstRange duration]]; + r = [NGCalendarDateRange calendarDateRangeWithStartDate: start + endDate: end]; + if ([_r containsDateRange: r]) + [ranges addObject: r]; + } } - } return ranges; } -- (NSCalendarDate *)lastInstanceStartDate { - if ([self->rrule repeatCount] > 0) { - NSCalendarDate *until; - unsigned years, interval; - - interval = [self->rrule repeatInterval]; - years = [self->rrule repeatCount] * interval; - until = [[self->firstRange startDate] dateByAddingYears:years - months:0 - days:0]; - return until; - } +- (NSCalendarDate *) lastInstanceStartDate +{ + if ([rrule repeatCount] > 0) + { + NSCalendarDate *until; + unsigned years, interval; + + interval = [rrule repeatInterval]; + years = [rrule repeatCount] * interval; + until = [[firstRange startDate] dateByAddingYears: years + months: 0 + days: 0]; + return until; + } return [super lastInstanceStartDate]; }