]> err.no Git - sope/commitdiff
moved cluster subclasses to own files
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Mon, 19 Sep 2005 22:52:11 +0000 (22:52 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Mon, 19 Sep 2005 22:52:11 +0000 (22:52 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@1119 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

sope-ical/NGiCal/ChangeLog
sope-ical/NGiCal/GNUmakefile
sope-ical/NGiCal/Version
sope-ical/NGiCal/iCalDailyRecurrenceCalculator.m [new file with mode: 0644]
sope-ical/NGiCal/iCalMonthlyRecurrenceCalculator.m [new file with mode: 0644]
sope-ical/NGiCal/iCalRecurrenceCalculator.m
sope-ical/NGiCal/iCalWeeklyRecurrenceCalculator.m [new file with mode: 0644]
sope-ical/NGiCal/iCalYearlyRecurrenceCalculator.m [new file with mode: 0644]

index 77a68ba47980d9915973be56da04f2066df6601f..27203741b95cca31c354f61effe23ab97b37fd3f 100644 (file)
@@ -1,5 +1,8 @@
 2005-09-20  Helge Hess  <helge.hess@opengroupware.org>
 
+       * iCalRecurrenceCalculator.m: moved cluster subclasses to own source
+         files (v4.5.63)
+
        * iCalRecurrenceRule.m: added some parsing/gen support for BYDAY
          (v4.5.62)
 
index 4a3fba5b3b66526b5a6485e0d8bbb3aa3e0b7d08..dd0a74b3dfbcdf540bb311e9a7f086aaecfcabac 100644 (file)
@@ -74,6 +74,10 @@ libNGiCal_OBJC_FILES =               \
        iCalRenderer.m                  \
        iCalRecurrenceRule.m            \
        iCalRecurrenceCalculator.m      \
+       iCalDailyRecurrenceCalculator.m \
+       iCalWeeklyRecurrenceCalculator.m\
+       iCalMonthlyRecurrenceCalculator.m \
+       iCalYearlyRecurrenceCalculator.m\
        \
        NGICalSaxHandler.m              \
        \
index 2075e285c655698aad736b8cc4f6857b1ee301ea..bae8b2810feec535b16dc09cfc4b3e5fd68b2b73 100644 (file)
@@ -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 (file)
index 0000000..6ba00f1
--- /dev/null
@@ -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 <NGExtensions/NGCalendarDateRange.h>
+#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 (file)
index 0000000..1eacf1d
--- /dev/null
@@ -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 <NGExtensions/NGCalendarDateRange.h>
+#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 */
index b141038b9421c89f7b9caa2f9aa3e156f9043891..9d2febd729be97dc54fb69c474ddc40add207943 100644 (file)
@@ -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"
 
 /* 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 (file)
index 0000000..1db42c8
--- /dev/null
@@ -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 <NGExtensions/NGCalendarDateRange.h>
+#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 (file)
index 0000000..b940b26
--- /dev/null
@@ -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 <NGExtensions/NGCalendarDateRange.h>
+#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 */