From: helge Date: Mon, 19 Sep 2005 22:52:11 +0000 (+0000) Subject: moved cluster subclasses to own files X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=36123d033a97586a9516bb52f6083952e50826a8;p=sope moved cluster subclasses to own files git-svn-id: http://svn.opengroupware.org/SOPE/trunk@1119 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- diff --git a/sope-ical/NGiCal/ChangeLog b/sope-ical/NGiCal/ChangeLog index 77a68ba4..27203741 100644 --- a/sope-ical/NGiCal/ChangeLog +++ b/sope-ical/NGiCal/ChangeLog @@ -1,5 +1,8 @@ 2005-09-20 Helge Hess + * iCalRecurrenceCalculator.m: moved cluster subclasses to own source + files (v4.5.63) + * iCalRecurrenceRule.m: added some parsing/gen support for BYDAY (v4.5.62) diff --git a/sope-ical/NGiCal/GNUmakefile b/sope-ical/NGiCal/GNUmakefile index 4a3fba5b..dd0a74b3 100644 --- a/sope-ical/NGiCal/GNUmakefile +++ b/sope-ical/NGiCal/GNUmakefile @@ -74,6 +74,10 @@ libNGiCal_OBJC_FILES = \ iCalRenderer.m \ iCalRecurrenceRule.m \ iCalRecurrenceCalculator.m \ + iCalDailyRecurrenceCalculator.m \ + iCalWeeklyRecurrenceCalculator.m\ + iCalMonthlyRecurrenceCalculator.m \ + iCalYearlyRecurrenceCalculator.m\ \ NGICalSaxHandler.m \ \ diff --git a/sope-ical/NGiCal/Version b/sope-ical/NGiCal/Version index 2075e285..bae8b281 100644 --- a/sope-ical/NGiCal/Version +++ b/sope-ical/NGiCal/Version @@ -2,7 +2,7 @@ MAJOR_VERSION=4 MINOR_VERSION=5 -SUBMINOR_VERSION:=62 +SUBMINOR_VERSION:=63 # v4.5.40 requires NGExtensions v4.5.145 # v4.5.37 requires NGExtensions v4.5.140 diff --git a/sope-ical/NGiCal/iCalDailyRecurrenceCalculator.m b/sope-ical/NGiCal/iCalDailyRecurrenceCalculator.m new file mode 100644 index 00000000..6ba00f16 --- /dev/null +++ b/sope-ical/NGiCal/iCalDailyRecurrenceCalculator.m @@ -0,0 +1,125 @@ +/* + 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 + 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 + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +#include "iCalRecurrenceCalculator.h" + +@interface iCalDailyRecurrenceCalculator : iCalRecurrenceCalculator +@end + +#include +#include "iCalRecurrenceRule.h" +#include "NSCalendarDate+ICal.h" +#include "common.h" + +@interface iCalRecurrenceCalculator(PrivateAPI) +- (NSCalendarDate *)lastInstanceStartDate; +@end + +@implementation iCalDailyRecurrenceCalculator + +- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{ + NSMutableArray *ranges; + NSCalendarDate *firStart; + long i, jnFirst, jnStart, jnEnd, startEndCount; + unsigned interval; + + firStart = [self->firstRange startDate]; + jnFirst = [firStart julianNumber]; + jnEnd = [[_r endDate] julianNumber]; + + if (jnFirst > jnEnd) + return nil; + + jnStart = [[_r startDate] julianNumber]; + interval = [self->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]; + } + else { + jnRuleLast = (interval * [self->rrule repeatCount]) + + jnFirst; + if (jnRuleLast < jnStart) + return nil; + } + /* jnStart < jnRuleLast < jnEnd ? */ + if (jnEnd > jnRuleLast) + jnEnd = jnRuleLast; + } + + startEndCount = (jnEnd - jnStart) + 1; + ranges = [NSMutableArray arrayWithCapacity:startEndCount]; + for (i = 0 ; i < startEndCount; i++) { + long jnCurrent; + + jnCurrent = jnStart + i; + if (jnCurrent >= jnFirst) { + long jnTest; + + jnTest = jnCurrent - jnFirst; + if ((jnTest % interval) == 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]; + } + } + } + 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]) + + jnFirst; + until = [NSCalendarDate dateForJulianNumber:jnRuleLast]; + until = [until hour: [firStart hourOfDay] + minute:[firStart minuteOfHour] + second:[firStart secondOfMinute]]; + return until; + } + return [super lastInstanceStartDate]; +} + +@end /* iCalDailyRecurrenceCalculator */ diff --git a/sope-ical/NGiCal/iCalMonthlyRecurrenceCalculator.m b/sope-ical/NGiCal/iCalMonthlyRecurrenceCalculator.m new file mode 100644 index 00000000..1eacf1da --- /dev/null +++ b/sope-ical/NGiCal/iCalMonthlyRecurrenceCalculator.m @@ -0,0 +1,100 @@ +/* + 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 + 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 + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +#include "iCalRecurrenceCalculator.h" + +@interface iCalMonthlyRecurrenceCalculator : iCalRecurrenceCalculator +@end + +#include +#include "iCalRecurrenceRule.h" +#include "NSCalendarDate+ICal.h" +#include "common.h" + +@interface iCalRecurrenceCalculator(PrivateAPI) +- (NSCalendarDate *)lastInstanceStartDate; +@end + +@implementation iCalMonthlyRecurrenceCalculator + +- (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 monthsBetweenDate:rStart]; + if ((diff != 0) && [rStart compare:firStart] == NSOrderedAscending) + diff = -diff; + + count = [rStart monthsBetweenDate: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:0 + months:diff + i + 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]; + } + } + return ranges; +} + +- (NSCalendarDate *)lastInstanceStartDate { + if ([self->rrule repeatCount] > 0) { + NSCalendarDate *until; + unsigned months, interval; + + interval = [self->rrule repeatInterval]; + months = [self->rrule repeatCount] * interval; + until = [[self->firstRange startDate] dateByAddingYears:0 + months:months + days:0]; + return until; + } + return [super lastInstanceStartDate]; +} + +@end /* iCalMonthlyRecurrenceCalculator */ diff --git a/sope-ical/NGiCal/iCalRecurrenceCalculator.m b/sope-ical/NGiCal/iCalRecurrenceCalculator.m index b141038b..9d2febd7 100644 --- a/sope-ical/NGiCal/iCalRecurrenceCalculator.m +++ b/sope-ical/NGiCal/iCalRecurrenceCalculator.m @@ -1,22 +1,22 @@ /* - 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 - 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 - Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + 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 + 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 + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #include "iCalRecurrenceCalculator.h" @@ -27,25 +27,6 @@ /* class cluster */ -@interface iCalDailyRecurrenceCalculator : iCalRecurrenceCalculator -{ -} -@end - -@interface iCalWeeklyRecurrenceCalculator : iCalRecurrenceCalculator -{ -} -@end - -@interface iCalMonthlyRecurrenceCalculator : iCalRecurrenceCalculator -{ -} -@end - -@interface iCalYearlyRecurrenceCalculator : iCalRecurrenceCalculator -{ -} -@end /* Private */ @@ -77,10 +58,10 @@ static Class yearlyCalcClass = Nil; NSCalendarDateClass = [NSCalendarDate class]; iCalRecurrenceRuleClass = [iCalRecurrenceRule class]; - dailyCalcClass = [iCalDailyRecurrenceCalculator class]; - weeklyCalcClass = [iCalWeeklyRecurrenceCalculator class]; - monthlyCalcClass = [iCalMonthlyRecurrenceCalculator class]; - yearlyCalcClass = [iCalYearlyRecurrenceCalculator class]; + dailyCalcClass = NSClassFromString(@"iCalDailyRecurrenceCalculator"); + weeklyCalcClass = NSClassFromString(@"iCalWeeklyRecurrenceCalculator"); + monthlyCalcClass = NSClassFromString(@"iCalMonthlyRecurrenceCalculator"); + yearlyCalcClass = NSClassFromString(@"iCalYearlyRecurrenceCalculator"); } /* factory */ @@ -309,376 +290,3 @@ static Class yearlyCalcClass = Nil; } @end /* iCalRecurrenceCalculator */ - - -@implementation iCalDailyRecurrenceCalculator - -- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r { - NSMutableArray *ranges; - NSCalendarDate *firStart; - long i, jnFirst, jnStart, jnEnd, startEndCount; - unsigned interval; - - firStart = [self->firstRange startDate]; - jnFirst = [firStart julianNumber]; - jnEnd = [[_r endDate] julianNumber]; - - if (jnFirst > jnEnd) - return nil; - - jnStart = [[_r startDate] julianNumber]; - interval = [self->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]; - } - else { - jnRuleLast = (interval * [self->rrule repeatCount]) - + jnFirst; - if (jnRuleLast < jnStart) - return nil; - } - /* jnStart < jnRuleLast < jnEnd ? */ - if (jnEnd > jnRuleLast) - jnEnd = jnRuleLast; - } - - startEndCount = (jnEnd - jnStart) + 1; - ranges = [NSMutableArray arrayWithCapacity:startEndCount]; - for (i = 0 ; i < startEndCount; i++) { - long jnCurrent; - - jnCurrent = jnStart + i; - if (jnCurrent >= jnFirst) { - long jnTest; - - jnTest = jnCurrent - jnFirst; - if ((jnTest % interval) == 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]; - } - } - } - 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]) + - jnFirst; - until = [NSCalendarDate dateForJulianNumber:jnRuleLast]; - until = [until hour: [firStart hourOfDay] - minute:[firStart minuteOfHour] - second:[firStart secondOfMinute]]; - return until; - } - return [super lastInstanceStartDate]; -} - -@end /* iCalDailyRecurrenceCalculator */ - - -/* - TODO: If BYDAY is specified, lastInstanceStartDate and recurrences will - differ significantly! -*/ -@implementation iCalWeeklyRecurrenceCalculator - -- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r { - NSMutableArray *ranges; - NSCalendarDate *firStart; - long i, jnFirst, jnStart, jnEnd, startEndCount; - unsigned interval, byDayMask; - - firStart = [self->firstRange startDate]; - jnFirst = [firStart julianNumber]; - jnEnd = [[_r endDate] julianNumber]; - - if (jnFirst > jnEnd) - return nil; - - jnStart = [[_r startDate] julianNumber]; - interval = [self->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]; - } - 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]; - } - } - } - } - else { - long jnFirstWeekStart, weekStartOffset; - - /* calculate jnFirst's week start - this depends on our setting of week - start */ - weekStartOffset = [self offsetFromSundayForJulianNumber:jnFirst] - - [self offsetFromSundayForCurrentWeekStart]; - - jnFirstWeekStart = jnFirst - weekStartOffset; - - 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; - - 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]; - } - } - } - } - } - 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; - } - return [super lastInstanceStartDate]; -} - -@end /* iCalWeeklyRecurrenceCalculator */ - -@implementation iCalMonthlyRecurrenceCalculator - -- (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 monthsBetweenDate:rStart]; - if ((diff != 0) && [rStart compare:firStart] == NSOrderedAscending) - diff = -diff; - - count = [rStart monthsBetweenDate: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:0 - months:diff + i - 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]; - } - } - return ranges; -} - -- (NSCalendarDate *)lastInstanceStartDate { - if ([self->rrule repeatCount] > 0) { - NSCalendarDate *until; - unsigned months, interval; - - interval = [self->rrule repeatInterval]; - months = [self->rrule repeatCount] * interval; - until = [[self->firstRange startDate] dateByAddingYears:0 - months:months - days:0]; - return until; - } - return [super lastInstanceStartDate]; -} - -@end /* iCalMonthlyRecurrenceCalculator */ - -@implementation iCalYearlyRecurrenceCalculator - -- (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) - diff = -diff; - - 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]; - } - } - 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; - } - return [super lastInstanceStartDate]; -} - -@end /* iCalYearlyRecurrenceCalculator */ diff --git a/sope-ical/NGiCal/iCalWeeklyRecurrenceCalculator.m b/sope-ical/NGiCal/iCalWeeklyRecurrenceCalculator.m new file mode 100644 index 00000000..1db42c84 --- /dev/null +++ b/sope-ical/NGiCal/iCalWeeklyRecurrenceCalculator.m @@ -0,0 +1,190 @@ +/* + 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 + 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 + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +#include "iCalRecurrenceCalculator.h" + +@interface iCalWeeklyRecurrenceCalculator : iCalRecurrenceCalculator +@end + +#include +#include "iCalRecurrenceRule.h" +#include "NSCalendarDate+ICal.h" +#include "common.h" + +@interface iCalRecurrenceCalculator (PrivateAPI) + +- (NSCalendarDate *)lastInstanceStartDate; + +- (unsigned)offsetFromSundayForJulianNumber:(long)_jn; +- (unsigned)offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay; +- (unsigned)offsetFromSundayForCurrentWeekStart; + +- (iCalWeekDay)weekDayForJulianNumber:(long)_jn; + +@end + +/* + TODO: If BYDAY is specified, lastInstanceStartDate and recurrences will + differ significantly! +*/ +@implementation iCalWeeklyRecurrenceCalculator + +- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r { + NSMutableArray *ranges; + NSCalendarDate *firStart; + long i, jnFirst, jnStart, jnEnd, startEndCount; + unsigned interval, byDayMask; + + firStart = [self->firstRange startDate]; + jnFirst = [firStart julianNumber]; + jnEnd = [[_r endDate] julianNumber]; + + if (jnFirst > jnEnd) + return nil; + + jnStart = [[_r startDate] julianNumber]; + interval = [self->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]; + } + 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]; + } + } + } + } + else { + long jnFirstWeekStart, weekStartOffset; + + /* calculate jnFirst's week start - this depends on our setting of week + start */ + weekStartOffset = [self offsetFromSundayForJulianNumber:jnFirst] - + [self offsetFromSundayForCurrentWeekStart]; + + jnFirstWeekStart = jnFirst - weekStartOffset; + + 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; + + 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]; + } + } + } + } + } + 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; + } + return [super lastInstanceStartDate]; +} + +@end /* iCalWeeklyRecurrenceCalculator */ diff --git a/sope-ical/NGiCal/iCalYearlyRecurrenceCalculator.m b/sope-ical/NGiCal/iCalYearlyRecurrenceCalculator.m new file mode 100644 index 00000000..b940b26a --- /dev/null +++ b/sope-ical/NGiCal/iCalYearlyRecurrenceCalculator.m @@ -0,0 +1,100 @@ +/* + 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 + 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 + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +#include "iCalRecurrenceCalculator.h" + +@interface iCalYearlyRecurrenceCalculator : iCalRecurrenceCalculator +@end + +#include +#include "iCalRecurrenceRule.h" +#include "NSCalendarDate+ICal.h" +#include "common.h" + +@interface iCalRecurrenceCalculator(PrivateAPI) +- (NSCalendarDate *)lastInstanceStartDate; +@end + +@implementation iCalYearlyRecurrenceCalculator + +- (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) + diff = -diff; + + 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]; + } + } + 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; + } + return [super lastInstanceStartDate]; +} + +@end /* iCalYearlyRecurrenceCalculator */