Index: Headers/Foundation/NSUserDefaults.h =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/base/Headers/Foundation/NSUserDefaults.h,v retrieving revision 1.8 diff -u -r1.8 NSUserDefaults.h --- Headers/Foundation/NSUserDefaults.h 8 Jul 2005 11:48:33 -0000 1.8 +++ Headers/Foundation/NSUserDefaults.h 11 Aug 2005 16:09:30 -0000 @@ -279,4 +279,16 @@ - (void) registerDefaults: (NSDictionary*)newVals; @end +#if defined(WIN32) && !defined(STRICT_OPENSTEP) +#include +@interface NSUserDefaultsWin32 : NSUserDefaults +{ + BOOL noLegacyFile; + NSString *registryPrefix; + NSMapTable *registryInfo; +} +- (void) setRegistryPrefix:(NSString*) p; +@end +#endif + #endif /* __NSUserDefaults_h_OBJECTS_INCLUDE */ Index: Source/NSUserDefaults.m =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/base/Source/NSUserDefaults.m,v retrieving revision 1.128 diff -u -r1.128 NSUserDefaults.m --- Source/NSUserDefaults.m 8 Jul 2005 11:48:35 -0000 1.128 +++ Source/NSUserDefaults.m 10 Aug 2005 21:39:30 -0000 @@ -1041,22 +1041,22 @@ [_lock lock]; obj = [_persDomains objectForKey: processName]; - obj = [(NSDictionary*)obj objectForKey: defaultName]; - if (obj != nil) - { - NSMutableDictionary *dict; + obj = [(NSDictionary*)obj objectForKey: defaultName]; + if (obj != nil) + { + NSMutableDictionary *dict; id obj = [_persDomains objectForKey: processName]; - if ([obj isKindOfClass: NSMutableDictionaryClass] == YES) - { - dict = obj; - } - else - { - dict = [obj mutableCopy]; + if ([obj isKindOfClass: NSMutableDictionaryClass] == YES) + { + dict = obj; + } + else + { + dict = [obj mutableCopy]; [_persDomains setObject: dict forKey: processName]; - } - [dict removeObjectForKey: defaultName]; + } + [dict removeObjectForKey: defaultName]; [self __changePersistentDomain: processName]; } [_lock unlock]; @@ -1346,69 +1346,39 @@ [_lock unlock]; } -/** - * Ensures that the in-memory and on-disk representations of the defaults - * are in sync. You may call this yourself, but probably don't need to - * since it is invoked at intervals whenever a runloop is running.
- * If any persistent domain is changed by reading new values from disk, - * an NSUserDefaultsDidChangeNotification is posted. - */ -- (BOOL) synchronize +- (BOOL) wantToReadDefaultsSince:(NSDate*)lastSyncDate { - NSFileManager *mgr = [NSFileManager defaultManager]; - NSMutableDictionary *newDict; - NSDictionary *attr; - NSDate *started = [NSDateClass date]; - unsigned long desired; - unsigned long attributes; - static BOOL isLocked = NO; - BOOL wasLocked; - - [_lock lock]; - - /* - * If we haven't changed anything, we only need to synchronise if - * the on-disk database has been changed by someone else. - */ - attr = [mgr fileAttributesAtPath: _defaultsDatabase - traverseLink: YES]; - if (_changedDomains == nil) - { - BOOL wantRead = NO; - - if (_lastSync == nil) - { - wantRead = YES; - } - else + NSFileManager *mgr = [NSFileManager defaultManager]; + NSDictionary *attr; + attr = [mgr fileAttributesAtPath: _defaultsDatabase traverseLink: YES]; + if (lastSyncDate == nil) + return YES; + else { if (attr == nil) - { - wantRead = YES; - } + return YES; else - { - NSDate *mod; + { + NSDate *mod; - /* - * If the database was modified since the last synchronisation - * we need to read it. - */ - mod = [attr objectForKey: NSFileModificationDate]; - if (mod != nil && [_lastSync laterDate: mod] != _lastSync) - { - wantRead = YES; - } - } - } - if (wantRead == NO) - { - [_lock unlock]; - return YES; + /* + * If the database was modified since the last synchronisation + * we need to read it. + */ + mod = [attr objectForKey: NSFileModificationDate]; + if (mod != nil && [lastSyncDate laterDate: mod] != lastSyncDate) + return YES; + } } - } + return NO; +} - wasLocked = isLocked; +static BOOL isLocked = NO; +- (BOOL) lockDefaultsFile:(BOOL*)wasLocked +{ + NSDate *started = [NSDateClass date]; + *wasLocked = isLocked; + if (isLocked == NO && _fileLock != nil) { while ([_fileLock tryLock] == NO) @@ -1430,7 +1400,6 @@ { NSLog(@"Failed to lock user defaults database even after " @"breaking old locks!"); - [_lock unlock]; return NO; } @@ -1451,21 +1420,31 @@ } isLocked = YES; } + return YES; +} + +- (void) unlockDefaultsFile +{ + [_fileLock unlock]; + isLocked = NO; +} + +- (NSMutableDictionary*) readDefaults +{ + NSMutableDictionary *newDict; + NSFileManager *mgr = [NSFileManager defaultManager]; + NSDictionary *attr; /* * Re-fetch database attributes in cased they changed while obtaining lock. */ attr = [mgr fileAttributesAtPath: _defaultsDatabase traverseLink: YES]; - - DESTROY(_dictionaryRep); - if (self == sharedDefaults) invalidatedLanguages = YES; - // Read the persistent data from the stored database if (attr == nil) { - newDict = [[NSMutableDictionaryClass allocWithZone: [self zone]] - initWithCapacity: 1]; + newDict = [[[NSMutableDictionaryClass allocWithZone: [self zone]] + initWithCapacity: 1] autorelease]; if (_fileLock != nil) { NSLog(@"Creating defaults database file %@", _defaultsDatabase); @@ -1482,8 +1461,8 @@ } else { - newDict = [[NSMutableDictionaryClass allocWithZone: [self zone]] - initWithContentsOfFile: _defaultsDatabase]; + newDict = [[[NSMutableDictionaryClass allocWithZone: [self zone]] + initWithContentsOfFile: _defaultsDatabase] autorelease]; } if (newDict == nil) { @@ -1494,27 +1473,23 @@ * initialised that way (possibly on a read-only filesystem) * so we just continue as best we can. */ - newDict = [[NSMutableDictionaryClass allocWithZone: [self zone]] - initWithCapacity: 4]; + newDict = [[[NSMutableDictionaryClass allocWithZone: [self zone]] + initWithCapacity: 4] autorelease]; } - else + else { /* * The defaults system has become unreadable singe we started... * probably a severe error of some sort */ NSLog(@"Unable to load defaults from '%@'", _defaultsDatabase); - if (wasLocked == NO) - { - [_fileLock unlock]; - isLocked = NO; - } - [_lock unlock]; - return NO; - } + } } } - + + if (attr) { + unsigned long desired; + unsigned long attributes; /* * We enforce the permission mode 0600 on the defaults database */ @@ -1539,6 +1514,67 @@ [mgr changeFileAttributes: enforced_attributes atPath: _defaultsDatabase]; } +} + return newDict; +} + +- (BOOL) writeDefaults:(NSDictionary*)defaults oldData:(NSDictionary*)oldData +{ + // Save the changes unless we are in read-only mode. + if (_fileLock != nil) + { + if (![defaults writeToFile: _defaultsDatabase atomically: YES]) + { + return NO; + } + } + return YES; +} + +/** + * Ensures that the in-memory and on-disk representations of the defaults + * are in sync. You may call this yourself, but probably don't need to + * since it is invoked at intervals whenever a runloop is running.
+ * If any persistent domain is changed by reading new values from disk, + * an NSUserDefaultsDidChangeNotification is posted. + */ +- (BOOL) synchronize +{ + NSMutableDictionary *newDict; + BOOL wasLocked; + + [_lock lock]; + + /* + * If we haven't changed anything, we only need to synchronise if + * the on-disk database has been changed by someone else. + */ + + if (_changedDomains == nil) + { + if (![self wantToReadDefaultsSince:_lastSync]) + { + [_lock unlock]; + return YES; + } + } + + DESTROY(_dictionaryRep); + if (self == sharedDefaults) invalidatedLanguages = YES; + + if (![self lockDefaultsFile:&wasLocked]) + return NO; + + newDict = [self readDefaults]; + + if (newDict == nil) + { + if (!wasLocked) + [self unlockDefaultsFile]; + + [_lock unlock]; + return NO; + } if (_changedDomains != nil) { // Synchronize both dictionaries @@ -1546,6 +1582,8 @@ NSString *domainName; NSDictionary *domain; + NSDictionary *oldData = [newDict copy]; + DESTROY(_changedDomains); // Retained by enumerator. while ((domainName = [enumerator nextObject]) != nil) { @@ -1560,21 +1598,15 @@ } } RELEASE(_persDomains); - _persDomains = newDict; - // Save the changes unless we are in read-only mode. - if (_fileLock != nil) - { - if (![_persDomains writeToFile: _defaultsDatabase atomically: YES]) - { - if (wasLocked == NO) - { - [_fileLock unlock]; - isLocked = NO; - } - [_lock unlock]; - return NO; - } - } + _persDomains = [newDict retain]; + + if (![self writeDefaults:_persDomains oldData:oldData]) { + if (!wasLocked) + [self unlockDefaultsFile]; + [_lock unlock]; + return NO; + } + ASSIGN(_lastSync, [NSDateClass date]); } else @@ -1583,23 +1615,16 @@ if ([_persDomains isEqual: newDict] == NO) { RELEASE(_persDomains); - _persDomains = newDict; + _persDomains = [newDict retain]; updateCache(self); [[NSNotificationCenter defaultCenter] postNotificationName: NSUserDefaultsDidChangeNotification object: self]; } - else - { - RELEASE(newDict); - } } - if (wasLocked == NO) - { - [_fileLock unlock]; - isLocked = NO; - } + if (!wasLocked) + [self unlockDefaultsFile]; [_lock unlock]; return YES; } Index: Source/win32/GNUmakefile =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/base/Source/win32/GNUmakefile,v retrieving revision 1.5 diff -u -r1.5 GNUmakefile --- Source/win32/GNUmakefile 22 May 2005 03:32:15 -0000 1.5 +++ Source/win32/GNUmakefile 11 Aug 2005 16:00:46 -0000 @@ -34,7 +34,7 @@ GSRunLoopWatcher.m \ NSRunLoopWin32.m \ Win32Support.m \ - Win32_Utilities.m + Win32_Utilities.m NSUserDefaultsWin32.m -include Makefile.preamble