+/* complex calculation convenience */
+
++ (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
+ firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
+ recurrenceRules:(NSArray *)_rRules
+ exceptionRules:(NSArray *)_exRules
+ exceptionDates:(NSArray *)_exDates
+{
+ id rule;
+ iCalRecurrenceCalculator *calc;
+ NSMutableArray *ranges;
+ unsigned i, count, rCount;
+
+ ranges = [NSMutableArray array];
+ count = [_rRules count];
+ for (i = 0; i < count; i++) {
+ NSArray *rs;
+
+ rule = [_rRules objectAtIndex:i];
+ if (![rule isKindOfClass:iCalRecurrenceRuleClass])
+ rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
+
+ calc = [self recurrenceCalculatorForRecurrenceRule:rule
+ withFirstInstanceCalendarDateRange:_fir];
+ rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
+ [ranges addObjectsFromArray:rs];
+ }
+
+ if (![ranges count])
+ return nil;
+
+ /* test if any exceptions do match */
+ count = [_exRules count];
+ for (i = 0; i < count; i++) {
+ NSArray *rs;
+
+ rule = [_exRules objectAtIndex:i];
+ if (![rule isKindOfClass:iCalRecurrenceRuleClass])
+ rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
+
+ calc = [self recurrenceCalculatorForRecurrenceRule:rule
+ withFirstInstanceCalendarDateRange:_fir];
+ rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
+ [ranges removeObjectsInArray:rs];
+ }
+
+ if (![ranges count])
+ return nil;
+
+ /* exception dates are also possible */
+ rCount = [ranges count];
+ count = [_exDates count];
+ for (i = 0; i < count; i++) {
+ id exDate;
+ NGCalendarDateRange *r;
+ unsigned k;
+
+ exDate = [_exDates objectAtIndex:i];
+ if (![exDate isKindOfClass:NSCalendarDateClass]) {
+ exDate = [NSCalendarDate calendarDateWithICalRepresentation:exDate];
+ }
+ for (k = 0; k < rCount; k++) {
+ r = [ranges objectAtIndex:(rCount - k) - 1];
+ if ([r containsDate:exDate]) {
+ [ranges removeObjectAtIndex:k];
+ }
+ }
+ }
+ return ranges;
+}
+
+
+/* init */
+