diff --git a/ChangeLog b/ChangeLog index 7d72601d9..8999b7cb2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Mon Nov 30 10:20:00 1998 Richard Frith-Macdonald + + * src/NSTask: Minor bugfix -ignore SIGCHLD + * src/NSUserDefaults: bugfix in registerDefaults: was replacing rather + than addning defaults. Also changed to cache dictionaryRepresaentation. + * src/include/NSUserDefaults.h: Added ivar to cache dictionary + representation. + * src/include/NSDate.h: Updated header for a couple of fixes. + * src/NSDate.m: Initialise locale stuff. + * src/NSCalendarDate.m: Use locale stuff. + Fri Nov 27 21:30:00 1998 Richard Frith-Macdonald * src/NSPortNameServer.m: ([_open]) changed to stop attempts to restart diff --git a/Headers/gnustep/base/NSDate.h b/Headers/gnustep/base/NSDate.h index 88bd993c4..4bcb1b037 100644 --- a/Headers/gnustep/base/NSDate.h +++ b/Headers/gnustep/base/NSDate.h @@ -47,6 +47,9 @@ typedef double NSTimeInterval; + (id) date; + (id) dateWithString: (NSString*)description; ++ (id) dateWithNaturalLanguageString: (NSString *)string; ++ (id) dateWithNaturalLanguageString: (NSString *)string + locale: (NSDictionary *)localeDictionary; + (id) dateWithTimeIntervalSinceNow: (NSTimeInterval)seconds; + (id) dateWithTimeIntervalSince1970: (NSTimeInterval)seconds; + (id) dateWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds; @@ -69,7 +72,8 @@ typedef double NSTimeInterval; - (NSString*) description; - (NSString*) descriptionWithCalendarFormat: (NSString*)format - timeZone: (NSTimeZone*)aTimeZone; + timeZone: (NSTimeZone*)aTimeZone + locale: (NSDictionary *)localeDictionary; - (NSString *) descriptionWithLocale: (NSDictionary *)locale; // Adding and getting intervals @@ -79,12 +83,13 @@ typedef double NSTimeInterval; - (NSTimeInterval) timeIntervalSinceDate: (NSDate*)otherDate; - (NSTimeInterval) timeIntervalSinceNow; - (NSTimeInterval) timeIntervalSinceReferenceDate; +- (NSTimeInterval) timeIntervalSinceReferenceDate; // Comparing dates - (NSComparisonResult) compare: (NSDate*)otherDate; - (NSDate*) earlierDate: (NSDate*)otherDate; -- (BOOL) isEqual: (id)other; +- (BOOL) isEqualToDate: (NSDate*)otherDate; - (NSDate*) laterDate: (NSDate*)otherDate; @end diff --git a/Headers/gnustep/base/NSUserDefaults.h b/Headers/gnustep/base/NSUserDefaults.h index 833e7555d..24424b115 100644 --- a/Headers/gnustep/base/NSUserDefaults.h +++ b/Headers/gnustep/base/NSUserDefaults.h @@ -1,7 +1,7 @@ /* Interface for for GNUStep Copyright (C) 1995, 1996 Free Software Foundation, Inc. - Written by: Georg Tuparev, EMBL & Academia Naturalis, + Written by: Georg Tuparev, EMBL & Academia Naturalis, Heidelberg, Germany Tuparev@EMBL-Heidelberg.de @@ -62,7 +62,7 @@ extern NSString *NSCurrencyString; extern NSString *NSDecimalDigits; extern NSString *NSAMPMDesignation; -/* NeXTSTEP 4.0 includes some more language-dependent constarnts: +/* NeXTSTEP 4.0 includes some more language-dependent constants: extern NSString *NSHourNameDesignations; extern NSString *NSYearMonthWeekDesignations; extern NSString *NSEarlierTimeDesignations; @@ -82,100 +82,101 @@ extern NSString *NSHomeDirectory(void); extern NSString *NSHomeDirectoryForUser(NSString * userName); -/* General implementation notes: +/* General implementation notes: OpenStep spec currently is either complete nor consitent. Therefor we had to take several implementation decisions which make vary in different OpenStep implementations. - - We add a new instance method initWithFile: as a designated + - We add a new instance method initWithFile: as a designated initialization method because it allows to create user defaults database from a "default user" and also it will work for various non-posix implementations. - We add two new class methods for getting and setting a list of - user languages (userLanguages and setUserLanguages:). They are + user languages (userLanguages and setUserLanguages: ). They are somehow equivalent to the NS3.x Application's systemLanguages method. - Definition of argument (command line parameters) (-GSxxxx || --GSxxx) [value] - Note: As far as I know, there is nothing like home directory for + Note: As far as I know, there is nothing like home directory for the M$ hell. God help the Win95/WinNT users of NSUserDefaults ;-) - To Do: - - Add writeToFile: instance method; + To Do: + - Add writeToFile: instance method; - implement the description method; - test for UNIX (write test app); - ask somebody to test it for M$; - polish & optimize; - when tested, fix NSBundle (the system languages stuff); - - write docs :-( + - write docs : -( */ -@interface NSUserDefaults: NSObject +@interface NSUserDefaults: NSObject { @private - NSMutableArray *searchList; // Current search list; - NSMutableDictionary *persDomains; // Contains persistent defaults info; - NSMutableDictionary *tempDomains; // Contains volatile defaults info; - NSMutableArray *changedDomains; /* ..after first time that persistent - user defaults are changed */ - NSMutableString *defaultsDatabase; - NSMutableString *defaultsDatabaseLockName; - NSDistributedLock *defaultsDatabaseLock; - BOOL tickingTimer; // for synchronization + NSMutableArray *searchList; // Current search list; + NSMutableDictionary *persDomains; // Contains persistent defaults info; + NSMutableDictionary *tempDomains; // Contains volatile defaults info; + NSMutableArray *changedDomains; /* ..after first time that persistent + user defaults are changed */ + NSDictionary *dictionaryRep; // Cached dictionary representation + NSMutableString *defaultsDatabase; + NSMutableString *defaultsDatabaseLockName; + NSDistributedLock *defaultsDatabaseLock; + BOOL tickingTimer; // for synchronization } /* Getting the Shared Instance */ -+ (NSUserDefaults *)standardUserDefaults; -+ (NSArray *)userLanguages; -+ (void)setUserLanguages:(NSArray *)languages; ++ (NSUserDefaults*) standardUserDefaults; ++ (NSArray*) userLanguages; ++ (void) setUserLanguages: (NSArray*)languages; /* Initializing the User Defaults */ -- (id)init; -- (id)initWithUser:(NSString *)userName; -- (id)initWithContentsOfFile:(NSString *)path; // This is a new method +- (id) init; +- (id) initWithUser: (NSString*)userName; +- (id) initWithContentsOfFile: (NSString*)path; // This is a new method /* Getting and Setting a Default */ -- (NSArray *)arrayForKey:(NSString *)defaultName; -- (BOOL)boolForKey:(NSString *)defaultName; -- (NSData *)dataForKey:(NSString *)defaultName; -- (NSDictionary *)dictionaryForKey:(NSString *)defaultName; -- (float)floatForKey:(NSString *)defaultName; -- (int)integerForKey:(NSString *)defaultName; -- (id)objectForKey:(NSString *)defaultName; -- (void)removeObjectForKey:(NSString *)defaultName; -- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; -- (void)setFloat:(float)value forKey:(NSString *)defaultName; -- (void)setInteger:(int)value forKey:(NSString *)defaultName; -- (void)setObject:(id)value forKey:(NSString *)defaultName; -- (NSArray *)stringArrayForKey:(NSString *)defaultName; -- (NSString *)stringForKey:(NSString *)defaultName; +- (NSArray*) arrayForKey: (NSString*)defaultName; +- (BOOL) boolForKey: (NSString*)defaultName; +- (NSData*) dataForKey: (NSString*)defaultName; +- (NSDictionary*) dictionaryForKey: (NSString*)defaultName; +- (float) floatForKey: (NSString*)defaultName; +- (int) integerForKey: (NSString*)defaultName; +- (id) objectForKey: (NSString*)defaultName; +- (void) removeObjectForKey: (NSString*)defaultName; +- (void) setBool: (BOOL)value forKey: (NSString*)defaultName; +- (void) setFloat: (float)value forKey: (NSString*)defaultName; +- (void) setInteger: (int)value forKey: (NSString*)defaultName; +- (void) setObject: (id)value forKey: (NSString*)defaultName; +- (NSArray*) stringArrayForKey: (NSString*)defaultName; +- (NSString*) stringForKey: (NSString*)defaultName; /* Returning the Search List */ -- (NSMutableArray *)searchList; -- (void)setSearchList:(NSArray*)newList; +- (NSMutableArray*) searchList; +- (void)setSearchList: (NSArray*)newList; /* Maintaining Persistent Domains */ -- (NSDictionary *)persistentDomainForName:(NSString *)domainName; -- (NSArray *)persistentDomainNames; -- (void)removePersistentDomainForName:(NSString *)domainName; -- (void)setPersistentDomain:(NSDictionary *)domain - forName:(NSString *)domainName; -- (BOOL)synchronize; +- (NSDictionary*) persistentDomainForName: (NSString*)domainName; +- (NSArray*) persistentDomainNames; +- (void) removePersistentDomainForName: (NSString*)domainName; +- (void) setPersistentDomain: (NSDictionary*)domain + forName: (NSString*)domainName; +- (BOOL) synchronize; /* Maintaining Volatile Domains */ -- (void)removeVolatileDomainForName:(NSString *)domainName; -- (void)setVolatileDomain:(NSDictionary *)domain - forName:(NSString *)domainName; -- (NSDictionary *)volatileDomainForName:(NSString *)domainName; -- (NSArray *)volatileDomainNames; +- (void) removeVolatileDomainForName: (NSString*)domainName; +- (void) setVolatileDomain: (NSDictionary*)domain + forName: (NSString*)domainName; +- (NSDictionary*) volatileDomainForName: (NSString*)domainName; +- (NSArray*) volatileDomainNames; /* Making Advanced Use of Defaults */ -- (NSDictionary *)dictionaryRepresentation; -- (void)registerDefaults:(NSDictionary *)dictionary; +- (NSDictionary*) dictionaryRepresentation; +- (void) registerDefaults: (NSDictionary*)dictionary; @end #endif /* __NSUserDefaults_h_OBJECTS_INCLUDE */ diff --git a/Source/NSCalendarDate.m b/Source/NSCalendarDate.m index a7c70d82a..ea6917215 100644 --- a/Source/NSCalendarDate.m +++ b/Source/NSCalendarDate.m @@ -25,9 +25,11 @@ #include #include #include +#include #include #include #include +#include #ifndef __WIN32__ #include @@ -50,49 +52,6 @@ #define GREGORIAN_REFERENCE 730486 -// -// Short and long month names -// TODO: These should be localized for the language. -// -static id short_month[12] = {@"Jan", - @"Feb", - @"Mar", - @"Apr", - @"May", - @"Jun", - @"Jul", - @"Aug", - @"Sep", - @"Oct", - @"Nov", - @"Dec"}; -static id long_month[12] = {@"January", - @"February", - @"March", - @"April", - @"May", - @"June", - @"July", - @"August", - @"September", - @"October", - @"November", - @"December"}; -static id short_day[7] = {@"Sun", - @"Mon", - @"Tue", - @"Wed", - @"Thu", - @"Fri", - @"Sat"}; -static id long_day[7] = {@"Sunday", - @"Monday", - @"Tuesday", - @"Wednesday", - @"Thursday", - @"Friday", - @"Saturday"}; - @interface NSCalendarDate (Private) - (void)getYear:(int *)year month:(int *)month day:(int *)day @@ -192,7 +151,7 @@ static id long_day[7] = {@"Sunday", // - (id)initWithString:(NSString *)description calendarFormat:(NSString *)format - locale:(NSDictionary *)dictionary + locale:(NSDictionary *)locale { const char *d = [description cString]; const char *f = [format cString]; @@ -394,7 +353,6 @@ static id long_day[7] = {@"Sunday", yd += 1900; // Possibly convert month from string to decimal number - // +++ how do we take locale into account? if (mtag) { int i; @@ -402,14 +360,18 @@ static id long_day[7] = {@"Sunday", if (fullm) { + NSArray *names = [locale objectForKey: NSMonthNameArray]; + for (i = 0;i < 12; ++i) - if ([long_month[i] isEqual: m] == YES) + if ([[names objectAtIndex: i] isEqual: m] == YES) break; } else { + NSArray *names = [locale objectForKey: NSShortMonthNameArray]; + for (i = 0;i < 12; ++i) - if ([short_month[i] isEqual: m] == YES) + if ([[names objectAtIndex: i] isEqual: m] == YES) break; } md = i + 1; @@ -762,8 +724,8 @@ static id long_day[7] = {@"Sunday", locale:(NSDictionary *)locale { char buf[1024]; - const char *f = [format cString]; - int lf = strlen(f); + const char *f; + int lf; BOOL mtag = NO, dtag = NO, ycent = NO; BOOL mname = NO, dname = NO; double s; @@ -771,10 +733,18 @@ static id long_day[7] = {@"Sunday", int hd = 0, nhd; int i, j, k, z; + if (locale == nil) + locale = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]; + if (format == nil) + format = [locale objectForKey: NSTimeDateFormatString]; + // If the format is nil then return an empty string if (!format) return @""; + f = [format cString]; + lf = strlen(f); + [self getYear: &yd month: &md day: &dom hour: &hd minute: &mnd second: &sd]; nhd = hd; @@ -841,11 +811,16 @@ static id long_day[7] = {@"Sunday", ++i; if (mtag) { - // +++ Translate to locale character string + NSArray *months; + NSString *name; + if (mname) - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", [short_month[md-1] cString])); + months = [locale objectForKey: NSShortMonthNameArray]; else - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", [long_month[md-1] cString])); + months = [locale objectForKey: NSMonthNameArray]; + name = [months objectAtIndex: md-1]; + k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", + [name cString])); } else k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", md)); @@ -887,19 +862,26 @@ static id long_day[7] = {@"Sunday", case 'A': dtag = YES; // Day is character string case 'w': - ++i; - if (dow < 0) dow = [self dayOfWeek]; - if (dtag) - { - // +++ Translate to locale character string - if (dname) - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", [short_day[dow] cString])); - else - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", [long_day[dow] cString])); - } - else - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", dow)); - j += k; + { + ++i; + if (dow < 0) dow = [self dayOfWeek]; + if (dtag) + { + NSArray *days; + NSString *name; + + if (dname) + days = [locale objectForKey: NSShortWeekDayNameArray]; + else + days = [locale objectForKey: NSWeekDayNameArray]; + name = [days objectAtIndex: dow]; + k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", + [name cString])); + } + else + k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", dow)); + j += k; + } break; // is it the hour @@ -929,12 +911,18 @@ static id long_day[7] = {@"Sunday", // Is it the am/pm indicator case 'p': - ++i; - if (hd >= 12) - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "PM")); - else - k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "AM")); - j += k; + { + NSArray *a = [locale objectForKey: NSAMPMDesignation]; + NSString *ampm; + + ++i; + if (hd >= 12) + ampm = [a objectAtIndex: 1]; + else + ampm = [a objectAtIndex: 0]; + k = VSPRINTF_LENGTH(sprintf(&(buf[j]), [ampm cString])); + j += k; + } break; // is it the zone name diff --git a/Source/NSDate.m b/Source/NSDate.m index 1cd63b2ae..a9ba2b8d9 100644 --- a/Source/NSDate.m +++ b/Source/NSDate.m @@ -29,10 +29,13 @@ */ #include +#include +#include #include #include #include #include +#include #ifndef __WIN32__ #include #endif /* !__WIN32__ */ @@ -61,6 +64,75 @@ @implementation NSDate ++ (void) initialize +{ + if (self == [NSDate class]) + { + NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; + NSDictionary *registrationDefaults; + NSArray *ampm; + NSArray *long_day; + NSArray *long_month; + NSArray *short_day; + NSArray *short_month; + + ampm = [NSArray arrayWithObjects: @"AM", @"PM", nil]; + short_month = [NSArray arrayWithObjects: + @"Jan", + @"Feb", + @"Mar", + @"Apr", + @"May", + @"Jun", + @"Jul", + @"Aug", + @"Sep", + @"Oct", + @"Nov", + @"Dec", + nil]; + long_month = [NSArray arrayWithObjects: + @"January", + @"February", + @"March", + @"April", + @"May", + @"June", + @"July", + @"August", + @"September", + @"October", + @"November", + @"December", + nil]; + short_day = [NSArray arrayWithObjects: + @"Sun", + @"Mon", + @"Tue", + @"Wed", + @"Thu", + @"Fri", + @"Sat", + nil]; + long_day = [NSArray arrayWithObjects: + @"Sunday", + @"Monday", + @"Tuesday", + @"Wednesday", + @"Thursday", + @"Friday", + @"Saturday", + nil]; + registrationDefaults = [NSDictionary dictionaryWithObjectsAndKeys: + ampm, NSAMPMDesignation, + long_month, NSMonthNameArray, + long_day, NSWeekDayNameArray, + short_month, NSShortMonthNameArray, + short_day, NSShortWeekDayNameArray, + nil]; + [defs registerDefaults: registrationDefaults]; + } +} // Getting current time + (NSTimeInterval) timeIntervalSinceReferenceDate @@ -259,23 +331,22 @@ - (NSString*) descriptionWithCalendarFormat: (NSString*)format timeZone: (NSTimeZone*)aTimeZone + locale: (NSDictionary*)l { // Easiest to just have NSCalendarDate do the work for us NSString *s; NSCalendarDate *d = [NSCalendarDate alloc]; - id f, t; + id f; [d initWithTimeIntervalSinceReferenceDate: seconds_since_ref]; if (!format) f = [d calendarFormat]; else f = format; - if (!aTimeZone) - t = [d timeZoneDetail]; - else - t = aTimeZone; + if (aTimeZone) + [d setTimeZone: aTimeZone]; - s = [d descriptionWithCalendarFormat: f timeZone: t]; + s = [d descriptionWithCalendarFormat: f locale: l]; [d release]; return s; } @@ -349,6 +420,13 @@ return NO; } +- (BOOL) isEqualToDate: (NSDate*)other +{ + if (1.0 > ABS(seconds_since_ref - [other timeIntervalSinceReferenceDate])) + return YES; + return NO; +} + - (NSDate*) laterDate: (NSDate*)otherDate { if (seconds_since_ref < [otherDate timeIntervalSinceReferenceDate]) diff --git a/Source/NSUserDefaults.m b/Source/NSUserDefaults.m index 4fb41a953..8055ba71b 100644 --- a/Source/NSUserDefaults.m +++ b/Source/NSUserDefaults.m @@ -267,6 +267,7 @@ static NSMutableString *processName = nil; [persDomains release]; [tempDomains release]; [changedDomains release]; + [dictionaryRep release]; [super dealloc]; } @@ -467,6 +468,7 @@ static NSMutableString *processName = nil; - (void)setSearchList:(NSArray*)newList { + DESTROY(dictionaryRep); [searchList release]; searchList = [newList mutableCopy]; } @@ -528,6 +530,8 @@ static NSMutableString *processName = nil; else return NO; + DESTROY(dictionaryRep); + // Read the persistent data from the stored database if ([[NSFileManager defaultManager] fileExistsAtPath: defaultsDatabase]) newDict = [[NSMutableDictionary allocWithZone:[self zone]] @@ -583,8 +587,8 @@ static NSMutableString *processName = nil; *************************************************************************/ - (void)removeVolatileDomainForName:(NSString *)domainName { + DESTROY(dictionaryRep); [tempDomains removeObjectForKey:domainName]; - return; } - (void)setVolatileDomain:(NSDictionary *)domain @@ -599,6 +603,7 @@ static NSMutableString *processName = nil; domainName]; return; } + DESTROY(dictionaryRep); [tempDomains setObject:domain forKey:domainName]; return; } @@ -616,28 +621,41 @@ static NSMutableString *processName = nil; /************************************************************************* *** Making Advanced Use of Defaults *************************************************************************/ -- (NSDictionary *)dictionaryRepresentation +- (NSDictionary *) dictionaryRepresentation { - NSEnumerator *enumerator = [searchList reverseObjectEnumerator]; - NSMutableDictionary *dictRep = - [NSMutableDictionary dictionaryWithCapacity:10]; - id obj; - id dict; - - while ((obj = [enumerator nextObject])) + if (dictionaryRep == nil) { - if ( (dict = [persDomains objectForKey:obj]) - || (dict = [tempDomains objectForKey:obj]) ) - [dictRep addEntriesFromDictionary:dict]; + NSEnumerator *enumerator; + NSMutableDictionary *dictRep; + id obj; + id dict; + + enumerator = [searchList reverseObjectEnumerator]; + dictRep = [NSMutableDictionary allocWithZone: NSDefaultMallocZone()]; + dictRep = [dictRep initWithCapacity: 512]; + while ((obj = [enumerator nextObject])) + { + if ( (dict = [persDomains objectForKey: obj]) + || (dict = [tempDomains objectForKey: obj]) ) + [dictRep addEntriesFromDictionary: dict]; + } + dictionaryRep = [dictRep copy]; + [dictRep release]; } - // $$$ Should we return NSDictionary here ? - return dictRep; + return dictionaryRep; } -- (void)registerDefaults:(NSDictionary *)dictionary +- (void) registerDefaults: (NSDictionary*)newVals { - [tempDomains setObject:dictionary forKey:NSRegistrationDomain]; - return; + NSMutableDictionary *regDefs; + + regDefs = [tempDomains objectForKey: NSRegistrationDomain]; + if (regDefs == nil) + { + regDefs = [NSMutableDictionary dictionaryWithCapacity: [newVals count]]; + } + DESTROY(dictionaryRep); + [regDefs addEntriesFromDictionary: newVals]; } /************************************************************************* @@ -721,7 +739,8 @@ static NSMutableString *processName = nil; { NSEnumerator *enumerator = nil; id obj; - + + DESTROY(dictionaryRep); if (!changedDomains) { changedDomains = [[NSMutableArray arrayWithCapacity:5] retain];