Fixed and tidied up lookup of language information in NSUserDefaults

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@24905 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
nicola 2007-03-20 18:30:51 +00:00
parent 4b841c4468
commit 56b7d94f6a
2 changed files with 128 additions and 80 deletions

View file

@ -1,3 +1,14 @@
2007-03-20 Nicola Pero <nicola.pero@meta-innovation.com>
* Source/NSUserDefaults.m ([+standardUserDefaults]): Fixed bug
were the same enumerator variable was reused in the two nested
loops and language resources wouldn't be found. Optimized a
little by factoring some variables out of the inner loop.
Reorganized usage of information from the C locale so that we use
it whenever a language resource lookup can not be found and the C
locale information is precisely for that language, but not
otherwise.
2007-03-19 Nicola Pero <nicola.pero@meta-innovation.com> 2007-03-19 Nicola Pero <nicola.pero@meta-innovation.com>
* Tools/gsdoc.gsdoc: Removed reference to GNUSTEP_SYSTEM_ROOT; use * Tools/gsdoc.gsdoc: Removed reference to GNUSTEP_SYSTEM_ROOT; use

View file

@ -399,7 +399,7 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
+ (NSUserDefaults*) standardUserDefaults + (NSUserDefaults*) standardUserDefaults
{ {
BOOL added_locale, added_lang; BOOL added_lang, added_locale;
id lang; id lang;
NSArray *uL; NSArray *uL;
NSEnumerator *enumerator; NSEnumerator *enumerator;
@ -492,92 +492,129 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
} }
/* Set up language constants */ /* Set up language constants */
added_locale = NO;
added_lang = NO;
enumerator = [uL objectEnumerator];
while ((lang = [enumerator nextObject]))
{
/* We lookup gnustep-base resources manually here to prevent
* bootstrap problems. NSBundle's lookup routines depend on
* having NSUserDefaults already bootstrapped, but we're still
* bootstrapping here! So we can't really use NSBundle without
* incurring massive bootstrap complications (btw, most of the
* times we're here as a consequence of [NSBundle +initialize]
* creating the gnustep-base bundle! So trying to use the
* gnustep-base bundle here wouldn't really work.).
*/
/*
* We are looking for:
*
* GNUSTEP_LIBRARY/Libraries/gnustep-base/Versions/<interfaceVersion>/Resources/Languages/<language>
*/
NSDictionary *dict = nil;
NSString *path = nil;
NSFileManager *fm = [NSFileManager defaultManager];
NSString *tail = [[[[[[@"Libraries" stringByAppendingPathComponent: @"gnustep-base"]
stringByAppendingPathComponent: @"Versions"]
stringByAppendingPathComponent: OBJC_STRINGIFY(GNUSTEP_BASE_MAJOR_VERSION.GNUSTEP_BASE_MINOR_VERSION)]
stringByAppendingPathComponent: @"Resources"]
stringByAppendingPathComponent: @"Languages"]
stringByAppendingPathComponent: lang];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
NSAllDomainsMask, YES);
enumerator = [paths objectEnumerator];
while ((path = [enumerator nextObject]) != nil)
{
BOOL isDir;
path = [path stringByAppendingPathComponent: tail];
if ([fm fileExistsAtPath: path isDirectory: &isDir])
{
/* Path found! */
break;
}
}
if (path != nil)
{
dict = [NSDictionary dictionaryWithContentsOfFile: path];
}
if (dict)
{
[sharedDefaults setVolatileDomain: dict forName: lang];
added_lang = YES;
}
else if (added_locale == NO)
{
NSString *locale = nil;
/* We lookup gnustep-base resources manually here to prevent
* bootstrap problems. NSBundle's lookup routines depend on having
* NSUserDefaults already bootstrapped, but we're still
* bootstrapping here! So we can't really use NSBundle without
* incurring massive bootstrap complications (btw, most of the times
* we're here as a consequence of [NSBundle +initialize] creating
* the gnustep-base bundle! So trying to use the gnustep-base
* bundle here wouldn't really work.).
*/
/*
* We are looking for:
*
* GNUSTEP_LIBRARY/Libraries/gnustep-base/Versions/<interfaceVersion>/Resources/Languages/<language>
*
* We iterate over <language>, and for each <language> we iterate over GNUSTEP_LIBRARY.
*/
{
/* These variables are reused for all languages so we set them up
* once here and then reuse them.
*/
NSFileManager *fm = [NSFileManager defaultManager];
NSString *tail = [[[[[@"Libraries"
stringByAppendingPathComponent: @"gnustep-base"]
stringByAppendingPathComponent: @"Versions"]
stringByAppendingPathComponent:
OBJC_STRINGIFY(GNUSTEP_BASE_MAJOR_VERSION.GNUSTEP_BASE_MINOR_VERSION)]
stringByAppendingPathComponent: @"Resources"]
stringByAppendingPathComponent: @"Languages"];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
NSAllDomainsMask, YES);
added_lang = NO;
added_locale = NO;
enumerator = [uL objectEnumerator];
while ((lang = [enumerator nextObject]))
{
NSDictionary *dict = nil;
NSString *path = nil;
NSEnumerator *pathEnumerator = [paths objectEnumerator];
while ((path = [pathEnumerator nextObject]) != nil)
{
path = [[path stringByAppendingPathComponent: tail]
stringByAppendingPathComponent: lang];
if ([fm fileExistsAtPath: path])
{
/* Path found! */
break;
}
}
if (path != nil)
{
dict = [NSDictionary dictionaryWithContentsOfFile: path];
}
if (dict != nil)
{
[sharedDefaults setVolatileDomain: dict forName: lang];
added_lang = YES;
}
else if (added_locale == NO)
{
/* The resources for the language that we were looking for
* were not found. If this was the currently set locale
* in the C library, try to get the same information from
* the C library. This would usually happen for the
* language that was added to the list of languages
* precisely because it is the currently set locale in the
* C library.
*/
NSString *locale = nil;
#ifdef HAVE_LOCALE_H #ifdef HAVE_LOCALE_H
#ifdef LC_MESSAGES #ifdef LC_MESSAGES
locale = GSSetLocale(LC_MESSAGES, nil); locale = GSSetLocale(LC_MESSAGES, nil);
#endif #endif
#endif #endif
if (locale == nil) if (locale != nil)
{ {
continue; /* See if we can get the dictionary from i18n
} * functions. I don't think that the i18n routines
/* See if we can get the dictionary from i18n functions. * can handle more than one locale, so we don't try to
Note that we get the dict from the current locale regardless * look 'lang' up but just get what we get and use it
of what 'lang' is, since it should match anyway. */ * if it matches 'lang' ... but tell me if I'm wrong
/* Also, I don't think that the i18n routines can handle more than * ...
one locale, but tell me if I'm wrong... */ */
if (GSLanguageFromLocale(locale)) if ([lang isEqualToString: GSLanguageFromLocale (locale)])
{ {
lang = GSLanguageFromLocale(locale); /* We set added_locale to YES to avoid so that we
} * won't do this C library locale lookup again
dict = GSDomainFromDefaultLocale(); * later on.
if (dict != nil) */
{ added_locale = YES;
[sharedDefaults setVolatileDomain: dict forName: lang];
} dict = GSDomainFromDefaultLocale ();
added_locale = YES; if (dict != nil)
} {
} [sharedDefaults setVolatileDomain: dict forName: lang];
/* We do not set added_lang to YES here
* because we want the improper installation
* warning to be printed below if our own
* English language dictionary is not found,
* and we want the basic hardcoded defaults to
* be used in that case. (FIXME: Review this
* decision).
*/
}
}
}
}
}
}
if (added_lang == NO) if (added_lang == NO)
{ {
/* Ack! We should never get here */ /* Ack! We should never get here. */
NSWarnMLog(@"Improper installation: No language locale found"); NSWarnMLog(@"Improper installation: No language locale found");
/* FIXME - should we set this as volatile domain for English ? */
[sharedDefaults registerDefaults: [self _unlocalizedDefaults]]; [sharedDefaults registerDefaults: [self _unlocalizedDefaults]];
} }
RETAIN(sharedDefaults); RETAIN(sharedDefaults);
@ -632,7 +669,7 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
#endif #endif
#endif #endif
currLang = [[NSUserDefaults standardUserDefaults] currLang = [[NSUserDefaults standardUserDefaults]
stringArrayForKey: @"NSLanguages"]; stringArrayForKey: @"NSLanguages"];
userLanguages = [[NSMutableArray alloc] initWithCapacity: 5]; userLanguages = [[NSMutableArray alloc] initWithCapacity: 5];