Monotone-Parent: 7e4ce901b4c13b7bc91a9cf02ff8ff0946502aaf
Monotone-Revision: e70b402803fd5be6062e9c2357b0a52a293a3440 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-03-26T20:30:53 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
f8a8a0c6dc
commit
de1bd56f2c
7
NEWS
7
NEWS
|
@ -5,9 +5,12 @@
|
|||
- pressing enter in the contact edition dialog will perform the creation/update operation
|
||||
- implemented more of the CalDAV specification for compatibility with Lightning 0.8
|
||||
- added Italian translation, thanks to Marco Lertora
|
||||
- improved restoration of drag hanldes state
|
||||
- improved restoration of drag handles state
|
||||
- improved contextual menu handling of Address Book module
|
||||
- fixed various bugs with Safari 3.1
|
||||
- fixed various bugs occuring with Safari 3.1
|
||||
- monthly events would not be returned properly
|
||||
- bi-weekly events would appear every week instead
|
||||
- weekly events with specified days of week would not appear on the correct days
|
||||
|
||||
0.9.0-20080208 (1.0 rc5)
|
||||
------------------------
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
2008-03-26 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* iCalRecurrenceRule.m ([iCalRecurrenceRule -byMonthDay]): check
|
||||
whether the "bymonthday" value is empty and returns an array only if
|
||||
not, otherwise returns nil.
|
||||
|
||||
* iCalRecurrenceCalculator.m ([iCalRecurrenceCalculator
|
||||
+recurrenceRangesWithinCalendarDateRange:_rfirstInstanceCalendarDateRange:_firrecurrenceRules:_rRulesexceptionRules:_exRulesexceptionDates:_exDates]):
|
||||
split method in many submethods for clarity.
|
||||
|
||||
2008-03-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* iCalTimeZonePeriod.m ([iCalTimeZonePeriod
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "NSString+NGCards.h"
|
||||
#import "NGCardsSaxHandler.h"
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
|
|
@ -43,14 +43,17 @@
|
|||
typedef BOOL NGMonthSet[12];
|
||||
typedef BOOL NGMonthDaySet[32]; // 0 is unused
|
||||
|
||||
static void NGMonthDaySet_clear(NGMonthDaySet *daySet) {
|
||||
static void
|
||||
NGMonthDaySet_clear(NGMonthDaySet *daySet)
|
||||
{
|
||||
register unsigned i;
|
||||
|
||||
for (i = 1; i <= 31; i++)
|
||||
for (i = 0; i <= 31; i++)
|
||||
(*daySet)[i] = NO;
|
||||
}
|
||||
|
||||
static void NGMonthDaySet_copyOrUnion(NGMonthDaySet *base, NGMonthDaySet *new,
|
||||
static void
|
||||
NGMonthDaySet_copyOrUnion(NGMonthDaySet *base, NGMonthDaySet *new,
|
||||
BOOL doCopy)
|
||||
{
|
||||
register unsigned i;
|
||||
|
@ -265,7 +268,7 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet,
|
|||
|
||||
|
||||
/* check whether the range to be processed is beyond the 'until' date */
|
||||
if (until != nil) {
|
||||
if (until) {
|
||||
if ([until compare:rStart] == NSOrderedAscending) /* until before start */
|
||||
return nil;
|
||||
if ([until compare:rEnd] == NSOrderedDescending) /* end before until */
|
||||
|
@ -275,7 +278,7 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet,
|
|||
|
||||
/* precalculate month days (same for all instances) */
|
||||
|
||||
if (byMonthDay != nil) {
|
||||
if (byMonthDay) {
|
||||
#if HEAVY_DEBUG
|
||||
NSLog(@"byMonthDay: %@", byMonthDay);
|
||||
#endif
|
||||
|
@ -343,7 +346,7 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet,
|
|||
|
||||
didByFill = NO;
|
||||
|
||||
if (byMonthDay != nil) { /* list of days in the month */
|
||||
if (byMonthDay) { /* list of days in the month */
|
||||
NGMonthDaySet_copyOrUnion(&monthDays, &byMonthDaySet, !didByFill);
|
||||
didByFill = YES;
|
||||
}
|
||||
|
|
|
@ -48,19 +48,22 @@
|
|||
@implementation iCalRecurrenceCalculator
|
||||
|
||||
static Class NSCalendarDateClass = Nil;
|
||||
static Class NSStringClass = Nil;
|
||||
static Class iCalRecurrenceRuleClass = Nil;
|
||||
static Class dailyCalcClass = Nil;
|
||||
static Class weeklyCalcClass = Nil;
|
||||
static Class monthlyCalcClass = Nil;
|
||||
static Class yearlyCalcClass = Nil;
|
||||
|
||||
+ (void)initialize {
|
||||
+ (void) initialize
|
||||
{
|
||||
static BOOL didInit = NO;
|
||||
|
||||
if (didInit) return;
|
||||
didInit = YES;
|
||||
|
||||
NSCalendarDateClass = [NSCalendarDate class];
|
||||
NSStringClass = [NSString class];
|
||||
iCalRecurrenceRuleClass = [iCalRecurrenceRule class];
|
||||
|
||||
dailyCalcClass = NSClassFromString(@"iCalDailyRecurrenceCalculator");
|
||||
|
@ -107,98 +110,122 @@ static Class yearlyCalcClass = Nil;
|
|||
|
||||
/* complex calculation convenience */
|
||||
|
||||
+ (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
|
||||
firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
|
||||
recurrenceRules:(NSArray *)_rRules
|
||||
exceptionRules:(NSArray *)_exRules
|
||||
exceptionDates:(NSArray *)_exDates
|
||||
+ (void) _fillRanges: (NSMutableArray *) ranges
|
||||
fromRules: (NSArray *) rrules
|
||||
withinRange: (NGCalendarDateRange *) limits
|
||||
startingWithDate: (NGCalendarDateRange *) first
|
||||
{
|
||||
id rule;
|
||||
NSEnumerator *rules;
|
||||
iCalRecurrenceRule *currentRule;
|
||||
iCalRecurrenceCalculator *calc;
|
||||
|
||||
rules = [rrules objectEnumerator];
|
||||
while ((currentRule = [rules nextObject]))
|
||||
{
|
||||
if ([currentRule isKindOfClass: NSStringClass])
|
||||
currentRule =
|
||||
[iCalRecurrenceRule
|
||||
recurrenceRuleWithICalRepresentation: (NSString *) currentRule];
|
||||
|
||||
calc = [self recurrenceCalculatorForRecurrenceRule: currentRule
|
||||
withFirstInstanceCalendarDateRange: first];
|
||||
[ranges addObjectsFromArray:
|
||||
[calc recurrenceRangesWithinCalendarDateRange: limits]];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) _removeExceptionsFromRanges: (NSMutableArray *) ranges
|
||||
withRules: (NSArray *) exrules
|
||||
withinRange: (NGCalendarDateRange *) limits
|
||||
startingWithDate: (NGCalendarDateRange *) first
|
||||
{
|
||||
NSEnumerator *rules;
|
||||
iCalRecurrenceRule *currentRule;
|
||||
iCalRecurrenceCalculator *calc;
|
||||
|
||||
rules = [exrules objectEnumerator];
|
||||
while ((currentRule = [rules nextObject]))
|
||||
{
|
||||
if ([currentRule isKindOfClass: NSStringClass])
|
||||
currentRule =
|
||||
[iCalRecurrenceRule
|
||||
recurrenceRuleWithICalRepresentation: (NSString *) currentRule];
|
||||
|
||||
calc = [self recurrenceCalculatorForRecurrenceRule: currentRule
|
||||
withFirstInstanceCalendarDateRange: first];
|
||||
[ranges removeObjectsInArray:
|
||||
[calc recurrenceRangesWithinCalendarDateRange: limits]];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSArray *) _dates: (NSArray *) dateList
|
||||
withinRange: (NGCalendarDateRange *) limits
|
||||
{
|
||||
NSMutableArray *newDates;
|
||||
NSEnumerator *dates;
|
||||
NSCalendarDate *currentDate;
|
||||
|
||||
newDates = [NSMutableArray array];
|
||||
|
||||
dates = [dateList objectEnumerator];
|
||||
while ((currentDate = [dates nextObject]))
|
||||
{
|
||||
if ([currentDate isKindOfClass: NSStringClass])
|
||||
currentDate
|
||||
= [NSCalendarDate
|
||||
calendarDateWithICalRepresentation: (NSString *) currentDate];
|
||||
if ([limits containsDate: currentDate])
|
||||
[newDates addObject: currentDate];
|
||||
}
|
||||
|
||||
return newDates;
|
||||
}
|
||||
|
||||
+ (void) _removeExceptionDatesFromRanges: (NSMutableArray *) ranges
|
||||
withDates: (NSArray *) exdates
|
||||
withinRange: (NGCalendarDateRange *) limits
|
||||
startingWithDate: (NGCalendarDateRange *) first
|
||||
{
|
||||
NSEnumerator *dates;
|
||||
NSCalendarDate *currentDate;
|
||||
NGCalendarDateRange *currentRange;
|
||||
int count, maxRanges;
|
||||
|
||||
maxRanges = [ranges count];
|
||||
dates = [[self _dates: exdates withinRange: limits] objectEnumerator];
|
||||
while ((currentDate = [dates nextObject]))
|
||||
for (count = (maxRanges - 1); count > -1; count++)
|
||||
{
|
||||
currentRange = [ranges objectAtIndex: count];
|
||||
if ([currentRange containsDate: currentDate])
|
||||
{
|
||||
[ranges removeObjectAtIndex: count];
|
||||
maxRanges--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSArray *)
|
||||
recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
|
||||
firstInstanceCalendarDateRange: (NGCalendarDateRange *) _fir
|
||||
recurrenceRules: (NSArray *) _rRules
|
||||
exceptionRules: (NSArray *) _exRules
|
||||
exceptionDates: (NSArray *) _exDates
|
||||
{
|
||||
NSMutableArray *ranges;
|
||||
NSMutableArray *exDates;
|
||||
unsigned i, count, rCount;
|
||||
|
||||
ranges = [NSMutableArray arrayWithCapacity:64];
|
||||
ranges = [NSMutableArray arrayWithCapacity: 64];
|
||||
|
||||
for (i = 0, count = [_rRules count]; 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 ([_rRules count] > 0)
|
||||
{
|
||||
[self _fillRanges: ranges fromRules: _rRules
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
[self _removeExceptionsFromRanges: ranges withRules: _exRules
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
[self _removeExceptionDatesFromRanges: ranges withDates: _exDates
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
}
|
||||
|
||||
if ([ranges count] == 0)
|
||||
return nil;
|
||||
|
||||
/* test if any exceptions do match */
|
||||
|
||||
for (i = 0, count = [_exRules count]; 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 isNotEmpty])
|
||||
return nil;
|
||||
|
||||
/* exception dates */
|
||||
|
||||
if ((count = [_exDates count]) == 0)
|
||||
return ranges;
|
||||
|
||||
/* sort out exDates not within range */
|
||||
|
||||
exDates = [NSMutableArray arrayWithCapacity:count];
|
||||
for (i = 0; i < count; i++) {
|
||||
id exDate;
|
||||
|
||||
exDate = [_exDates objectAtIndex:i];
|
||||
if (![exDate isKindOfClass:NSCalendarDateClass])
|
||||
exDate = [NSCalendarDate calendarDateWithICalRepresentation:exDate];
|
||||
|
||||
if ([_r containsDate:exDate])
|
||||
[exDates addObject:exDate];
|
||||
}
|
||||
|
||||
/* remove matching exDates from ranges */
|
||||
|
||||
if ((count = [exDates count]) == 0)
|
||||
return ranges;
|
||||
|
||||
for (i = 0, rCount = [ranges count]; i < count; i++) {
|
||||
NSCalendarDate *exDate;
|
||||
NGCalendarDateRange *r;
|
||||
unsigned k;
|
||||
|
||||
exDate = [exDates objectAtIndex:i];
|
||||
|
||||
for (k = 0; k < rCount; k++) {
|
||||
unsigned rIdx;
|
||||
|
||||
rIdx = (rCount - k) - 1;
|
||||
r = [ranges objectAtIndex:rIdx];
|
||||
if ([r containsDate:exDate]) {
|
||||
[ranges removeObjectAtIndex:rIdx];
|
||||
rCount--;
|
||||
break; /* this is safe because we know that ranges don't overlap */
|
||||
}
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
@ -265,23 +292,12 @@ static Class yearlyCalcClass = Nil;
|
|||
|
||||
- (iCalWeekDay) weekDayForJulianNumber: (long)_jn
|
||||
{
|
||||
unsigned int day;
|
||||
iCalWeekDay weekDay;
|
||||
iCalWeekDay weekDays[] = {iCalWeekDaySunday, iCalWeekDayMonday,
|
||||
iCalWeekDayTuesday, iCalWeekDayWednesday,
|
||||
iCalWeekDayThursday, iCalWeekDayFriday,
|
||||
iCalWeekDaySaturday};
|
||||
|
||||
if (day < 7)
|
||||
weekDay = weekDays[day];
|
||||
else
|
||||
{
|
||||
[self errorWithFormat:
|
||||
@"got unexpected weekday: %d (falling back on sunday)", day];
|
||||
weekDay = iCalWeekDaySunday;
|
||||
}
|
||||
|
||||
return weekDay;
|
||||
return weekDays[[self offsetFromSundayForJulianNumber: _jn]];
|
||||
}
|
||||
|
||||
/* calculation */
|
||||
|
|
|
@ -325,7 +325,16 @@
|
|||
|
||||
- (NSArray *) byMonthDay
|
||||
{
|
||||
return [[self namedValue: @"bymonthday"] componentsSeparatedByString: @","];
|
||||
NSArray *byMonthDay;
|
||||
NSString *byMonthDayStr;
|
||||
|
||||
byMonthDayStr = [self namedValue: @"bymonthday"];
|
||||
if ([byMonthDayStr length])
|
||||
byMonthDay = [byMonthDayStr componentsSeparatedByString: @","];
|
||||
else
|
||||
byMonthDay = nil;
|
||||
|
||||
return byMonthDay;
|
||||
}
|
||||
|
||||
- (BOOL) isInfinite
|
||||
|
@ -363,11 +372,13 @@
|
|||
foundDay = iCalWeekDayTuesday;
|
||||
else if (chars[1] == 'H')
|
||||
foundDay = iCalWeekDayThursday;
|
||||
break;
|
||||
case 'S':
|
||||
if (chars[1] == 'A')
|
||||
foundDay = iCalWeekDaySaturday;
|
||||
else if (chars[1] == 'U')
|
||||
foundDay = iCalWeekDaySunday;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,13 +32,13 @@
|
|||
|
||||
@interface iCalRecurrenceCalculator (PrivateAPI)
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate;
|
||||
- (NSCalendarDate *) lastInstanceStartDate;
|
||||
|
||||
- (unsigned)offsetFromSundayForJulianNumber:(long)_jn;
|
||||
- (unsigned)offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay;
|
||||
- (unsigned)offsetFromSundayForCurrentWeekStart;
|
||||
- (unsigned) offsetFromSundayForJulianNumber:(long)_jn;
|
||||
- (unsigned) offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay;
|
||||
- (unsigned) offsetFromSundayForCurrentWeekStart;
|
||||
|
||||
- (iCalWeekDay)weekDayForJulianNumber:(long)_jn;
|
||||
- (iCalWeekDay) weekDayForJulianNumber:(long)_jn;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -48,7 +48,9 @@
|
|||
*/
|
||||
@implementation iCalWeeklyRecurrenceCalculator
|
||||
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
|
||||
- (NSArray *)
|
||||
recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
|
||||
{
|
||||
NSMutableArray *ranges;
|
||||
NSCalendarDate *firStart;
|
||||
long i, jnFirst, jnStart, jnEnd, startEndCount;
|
||||
|
|
|
@ -907,10 +907,10 @@ static NSNumber *sharedYes = nil;
|
|||
forRange: (NGCalendarDateRange *) _r
|
||||
intoArray: (NSMutableArray *) _ma
|
||||
{
|
||||
NSMutableDictionary *row;
|
||||
NSMutableDictionary *row, *fixedRow;
|
||||
NSDictionary *cycleinfo;
|
||||
NSCalendarDate *startDate, *endDate;
|
||||
NGCalendarDateRange *fir;
|
||||
NGCalendarDateRange *fir, *rRange;
|
||||
NSArray *rules, *exRules, *exDates, *ranges;
|
||||
unsigned i, count;
|
||||
NSString *content;
|
||||
|
@ -918,47 +918,44 @@ static NSNumber *sharedYes = nil;
|
|||
content = [_row objectForKey: @"c_cycleinfo"];
|
||||
if (![content isNotNull])
|
||||
{
|
||||
[self errorWithFormat:@"cyclic record doesn't have cycleinfo -> %@", _row];
|
||||
[self errorWithFormat:@"cyclic record doesn't have cycleinfo -> %@",
|
||||
_row];
|
||||
return;
|
||||
}
|
||||
|
||||
cycleinfo = [content propertyList];
|
||||
if (!cycleinfo)
|
||||
{
|
||||
[self errorWithFormat:@"cyclic record doesn't have cycleinfo -> %@", _row];
|
||||
[self errorWithFormat:@"cyclic record doesn't have cycleinfo -> %@",
|
||||
_row];
|
||||
return;
|
||||
}
|
||||
|
||||
row = [self fixupRecord:_row fetchRange: _r];
|
||||
[row removeObjectForKey: @"c_cycleinfo"];
|
||||
[row setObject: sharedYes forKey:@"isRecurrentEvent"];
|
||||
[row setObject: sharedYes forKey: @"isRecurrentEvent"];
|
||||
|
||||
startDate = [row objectForKey:@"startDate"];
|
||||
endDate = [row objectForKey:@"endDate"];
|
||||
fir = [NGCalendarDateRange calendarDateRangeWithStartDate:startDate
|
||||
endDate:endDate];
|
||||
rules = [cycleinfo objectForKey:@"rules"];
|
||||
exRules = [cycleinfo objectForKey:@"exRules"];
|
||||
exDates = [cycleinfo objectForKey:@"exDates"];
|
||||
startDate = [row objectForKey: @"startDate"];
|
||||
endDate = [row objectForKey: @"endDate"];
|
||||
fir = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
|
||||
endDate: endDate];
|
||||
rules = [cycleinfo objectForKey: @"rules"];
|
||||
exRules = [cycleinfo objectForKey: @"exRules"];
|
||||
exDates = [cycleinfo objectForKey: @"exDates"];
|
||||
|
||||
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange:_r
|
||||
firstInstanceCalendarDateRange:fir
|
||||
recurrenceRules:rules
|
||||
exceptionRules:exRules
|
||||
exceptionDates:exDates];
|
||||
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: _r
|
||||
firstInstanceCalendarDateRange: fir
|
||||
recurrenceRules: rules
|
||||
exceptionRules: exRules
|
||||
exceptionDates: exDates];
|
||||
count = [ranges count];
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
NGCalendarDateRange *rRange;
|
||||
id fixedRow;
|
||||
|
||||
rRange = [ranges objectAtIndex:i];
|
||||
fixedRow = [self fixupCycleRecord:row cycleRange:rRange];
|
||||
if (fixedRow != nil)
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
rRange = [ranges objectAtIndex:i];
|
||||
fixedRow = [self fixupCycleRecord: row cycleRange: rRange];
|
||||
if (fixedRow)
|
||||
[_ma addObject:fixedRow];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) fixupCyclicRecords: (NSArray *) _records
|
||||
|
@ -966,19 +963,18 @@ static NSNumber *sharedYes = nil;
|
|||
{
|
||||
// TODO: is the result supposed to be sorted by date?
|
||||
NSMutableArray *ma;
|
||||
unsigned i, count;
|
||||
NSDictionary *row;
|
||||
unsigned int i, count;
|
||||
|
||||
if (_records == nil) return nil;
|
||||
if ((count = [_records count]) == 0)
|
||||
return _records;
|
||||
|
||||
ma = [NSMutableArray arrayWithCapacity:count];
|
||||
for (i = 0; i < count; i++) {
|
||||
id row; // TODO: what is the type of the record?
|
||||
|
||||
row = [_records objectAtIndex:i];
|
||||
[self _flattenCycleRecord:row forRange:_r intoArray:ma];
|
||||
count = [_records count];
|
||||
ma = [NSMutableArray arrayWithCapacity: count];
|
||||
if (count > 0)
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
row = [_records objectAtIndex: i];
|
||||
[self _flattenCycleRecord: row forRange: _r intoArray: ma];
|
||||
}
|
||||
|
||||
return ma;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue