/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* @APPLE_LICENSE_HEADER_END@
*/
-/* CFBundle_Resources.c
- Copyright (c) 1999-2007 Apple Inc. All rights reserved.
- Responsibility: Doug Davidson
+/* CFBundle_Resources.c
+ Copyright (c) 1999-2009, Apple Inc. All rights reserved.
+ Responsibility: Doug Davidson
*/
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
#define READ_DIRECTORIES 1
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define READ_DIRECTORIES 0
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
#define READ_DIRECTORIES_CACHE_CAPACITY 128
#include <CoreFoundation/CFPropertyList.h>
#include <CoreFoundation/CFByteOrder.h>
#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFLocale.h>
+#include <CoreFoundation/CFPreferences.h>
#include <string.h>
#include "CFInternal.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#if DEPLOYMENT_TARGET_MACOSX
-#include <CoreFoundation/CFPreferences.h>
#include <unistd.h>
+#elif DEPLOYMENT_TARGET_EMBEDDED
+#include <unistd.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
#if READ_DIRECTORIES
// All new-style bundles will have these extensions.
CF_INLINE CFStringRef _CFGetPlatformName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
return _CFBundleMacOSXPlatformName;
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return _CFBundleWindowsPlatformName;
#elif DEPLOYMENT_TARGET_SOLARIS
return _CFBundleSolarisPlatformName;
#elif DEPLOYMENT_TARGET_HPUX
}
CF_INLINE CFStringRef _CFGetAlternatePlatformName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
return _CFBundleAlternateMacOSXPlatformName;
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return CFSTR("");
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
}
if (!foundIt) tryToOpen = false;
}
__CFSpinUnlock(&CFBundleResourceGlobalDataLock);
-
CFRelease(name);
}
CFRelease(dirName);
// cheapStr is available for our use for whatever we want.
// URLs for found resources get added to result.
CFIndex savedPathLen;
- Boolean appendSucceeded = true, platformGenericFound = false, platformSpecificFound = false, platformGenericIsDir = false, platformSpecificIsDir = false, platformGenericIsUnknown = false, platformSpecificIsUnknown = false;
+ Boolean appendSucceeded = true, platformGenericFound = false, platformSpecificFound = false, platformGenericIsDir = false, platformSpecificIsDir = false;
+#if READ_DIRECTORIES
+ Boolean platformGenericIsUnknown = false, platformSpecificIsUnknown = false;
+#endif
CFStringRef platformGenericStr = NULL;
#if READ_DIRECTORIES
CFAllocatorRef alloc = (bundle ? CFGetAllocator(bundle) : (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()));
CFMutableArrayRef result;
UniChar *workingUniChars, *nameUniChars, *subDirUniChars;
- CFIndex nameLen = (resName ? CFStringGetLength(resName) : 0);
+ CFIndex nameLen = 0;
CFIndex subDirLen = (subDirName ? CFStringGetLength(subDirName) : 0);
CFIndex workingLen, savedWorkingLen;
CFURLRef absoluteURL;
CFStringRef bundlePath;
CFMutableStringRef cheapStr, tmpString;
+ char buff[CFMaxPathSize];
result = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
+ if (resName) {
+ CFStringRef newResName = NULL;
+ if (CFStringGetFileSystemRepresentation(resName, buff, CFMaxPathSize)) newResName = CFStringCreateWithFileSystemRepresentation(alloc, buff);
+ resName = newResName ? newResName : (CFStringRef)CFRetain(resName);
+ nameLen = CFStringGetLength(resName);
+ }
+
// Init the one-time-only unichar buffers.
_CFEnsureStaticBuffersInited();
// Build UniChar buffers for some of the string pieces we need.
// One malloc will do.
nameUniChars = (UniChar *)CFAllocatorAllocate(alloc, sizeof(UniChar) * (nameLen + subDirLen + CFMaxPathSize), 0);
- subDirUniChars = nameUniChars + nameLen;
- workingUniChars = subDirUniChars + subDirLen;
-
- if (nameLen > 0) CFStringGetCharacters(resName, CFRangeMake(0, nameLen), nameUniChars);
- if (subDirLen > 0) CFStringGetCharacters(subDirName, CFRangeMake(0, subDirLen), subDirUniChars);
- // Build a UniChar buffer with the absolute path to the bundle's resources directory.
- // If no URL was passed, we get it from the bundle.
- bundleURL = (bundleURL ? (CFURLRef)CFRetain(bundleURL) : CFBundleCopyBundleURL(bundle));
- absoluteURL = CFURLCopyAbsoluteURL(bundleURL);
- bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
- CFRelease(absoluteURL);
- if ((workingLen = CFStringGetLength(bundlePath)) > 0) CFStringGetCharacters(bundlePath, CFRangeMake(0, workingLen), workingUniChars);
- CFRelease(bundlePath);
- CFRelease(bundleURL);
- savedWorkingLen = workingLen;
- if (1 == version) {
- _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars1, _AppSupportLen1);
- } else if (2 == version) {
- _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars2, _AppSupportLen2);
- }
- if (0 == version || 1 == version || 2 == version) {
- _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _ResourcesUniChars, _ResourcesLen);
- }
+ if (nameUniChars) {
+ subDirUniChars = nameUniChars + nameLen;
+ workingUniChars = subDirUniChars + subDirLen;
+
+ if (nameLen > 0) CFStringGetCharacters(resName, CFRangeMake(0, nameLen), nameUniChars);
+ if (subDirLen > 0) CFStringGetCharacters(subDirName, CFRangeMake(0, subDirLen), subDirUniChars);
+ // Build a UniChar buffer with the absolute path to the bundle's resources directory.
+ // If no URL was passed, we get it from the bundle.
+ bundleURL = (bundleURL ? (CFURLRef)CFRetain(bundleURL) : CFBundleCopyBundleURL(bundle));
+ absoluteURL = CFURLCopyAbsoluteURL(bundleURL);
+ bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
+ if ((workingLen = CFStringGetLength(bundlePath)) > 0) CFStringGetCharacters(bundlePath, CFRangeMake(0, workingLen), workingUniChars);
+ savedWorkingLen = workingLen;
+ if (1 == version) {
+ _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars1, _AppSupportLen1);
+ } else if (2 == version) {
+ _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars2, _AppSupportLen2);
+ }
+ if (0 == version || 1 == version || 2 == version) _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _ResourcesUniChars, _ResourcesLen);
- // both of these used for temp string operations, for slightly
- // different purposes, where each type is appropriate
- cheapStr = CFStringCreateMutable(alloc, 0);
- _CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize);
- tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull);
+ // both of these used for temp string operations, for slightly different purposes, where each type is appropriate
+ cheapStr = CFStringCreateMutable(alloc, 0);
+ _CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize);
+ tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull);
- _CFFindBundleResourcesInResourcesDir(alloc, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, version, cheapStr, tmpString, result);
-
- // drd: This unfortunate hack is still necessary because of installer packages
- if (0 == version && CFArrayGetCount(result) == 0) {
- // Try looking directly in the bundle path
- workingLen = savedWorkingLen;
_CFFindBundleResourcesInResourcesDir(alloc, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, version, cheapStr, tmpString, result);
- }
+
+ // drd: This unfortunate hack is still necessary because of installer packages and Spotlight importers
+ if (CFArrayGetCount(result) == 0 && (0 == version || (2 == version && bundlePath && CFEqual(CFSTR("/Library/Spotlight"), bundlePath)))) {
+ // Try looking directly in the bundle path
+ workingLen = savedWorkingLen;
+ _CFFindBundleResourcesInResourcesDir(alloc, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, version, cheapStr, tmpString, result);
+ }
- CFRelease(cheapStr);
- CFRelease(tmpString);
- CFAllocatorDeallocate(alloc, nameUniChars);
+ CFRelease(absoluteURL);
+ CFRelease(bundlePath);
+ CFRelease(bundleURL);
+ CFRelease(cheapStr);
+ CFRelease(tmpString);
+ CFAllocatorDeallocate(alloc, nameUniChars);
+ }
+ if (resName) CFRelease(resName);
if (!bundle) CFRelease(alloc);
-
return result;
}
CFURLRef result = NULL;
CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle), types = NULL, array;
if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
array = _CFFindBundleResources(bundle, NULL, subDirName, languages, resourceName, types, 1, _CFBundleLayoutVersion(bundle));
-
if (types) CFRelease(types);
-
if (array) {
if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
CFRelease(array);
CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfType(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName) {
CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle), types = NULL, array;
if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
// MF:!!! Better "limit" than 1,000,000?
array = _CFFindBundleResources(bundle, NULL, subDirName, languages, NULL, types, 1000000, _CFBundleLayoutVersion(bundle));
-
if (types) CFRelease(types);
return array;
}
-CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {return CFBundleCopyResourceURLForLocalization(bundle, resourceName, resourceType, subDirName, language);}
+CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {
+ return CFBundleCopyResourceURLForLocalization(bundle, resourceName, resourceType, subDirName, language);
+}
CF_EXPORT CFURLRef CFBundleCopyResourceURLForLocalization(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) {
CFURLRef result = NULL;
if (localizationName) languages = CFArrayCreate(CFGetAllocator(bundle), (const void **)&localizationName, 1, &kCFTypeArrayCallBacks);
if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
array = _CFFindBundleResources(bundle, NULL, subDirName, languages, resourceName, types, 1, _CFBundleLayoutVersion(bundle));
if (array) {
if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
CFRelease(array);
}
-
if (types) CFRelease(types);
if (languages) CFRelease(languages);
-
return result;
}
-CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {return CFBundleCopyResourceURLsOfTypeForLocalization(bundle, resourceType, subDirName, language);}
+CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {
+ return CFBundleCopyResourceURLsOfTypeForLocalization(bundle, resourceType, subDirName, language);
+}
CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeForLocalization(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) {
CFArrayRef languages = NULL, types = NULL, array;
if (localizationName) languages = CFArrayCreate(CFGetAllocator(bundle), (const void **)&localizationName, 1, &kCFTypeArrayCallBacks);
if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
// MF:!!! Better "limit" than 1,000,000?
array = _CFFindBundleResources(bundle, NULL, subDirName, languages, NULL, types, 1000000, _CFBundleLayoutVersion(bundle));
-
if (types) CFRelease(types);
if (languages) CFRelease(languages);
-
return array;
}
CF_EXPORT CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName) {
CFStringRef result = NULL;
CFDictionaryRef stringTable = NULL;
+ static CFSpinLock_t CFBundleLocalizedStringLock = CFSpinLockInit;
if (!key) return (value ? (CFStringRef)CFRetain(value) : (CFStringRef)CFRetain(CFSTR("")));
if (!tableName || CFEqual(tableName, CFSTR(""))) tableName = _CFBundleDefaultStringTableName;
- if (__CFBundleGetResourceData(bundle)->_stringTableCache) stringTable = (CFDictionaryRef)CFDictionaryGetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName);
+
+ __CFSpinLock(&CFBundleLocalizedStringLock);
+ if (__CFBundleGetResourceData(bundle)->_stringTableCache) {
+ stringTable = (CFDictionaryRef)CFDictionaryGetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName);
+ if (stringTable) CFRetain(stringTable);
+ }
+ __CFSpinUnlock(&CFBundleLocalizedStringLock);
+
if (!stringTable) {
// Go load the table.
CFURLRef tableURL = CFBundleCopyResourceURL(bundle, tableName, _CFBundleStringTableType, NULL);
CFRelease(tableURL);
}
if (!stringTable) stringTable = CFDictionaryCreate(CFGetAllocator(bundle), NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (!__CFBundleGetResourceData(bundle)->_stringTableCache) __CFBundleGetResourceData(bundle)->_stringTableCache = CFDictionaryCreateMutable(CFGetAllocator(bundle), 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName, stringTable);
- CFRelease(stringTable);
+
+ if (!CFStringHasSuffix(tableName, CFSTR(".nocache")) || !_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) {
+ __CFSpinLock(&CFBundleLocalizedStringLock);
+ if (!__CFBundleGetResourceData(bundle)->_stringTableCache) __CFBundleGetResourceData(bundle)->_stringTableCache = CFDictionaryCreateMutable(CFGetAllocator(bundle), 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName, stringTable);
+ __CFSpinUnlock(&CFBundleLocalizedStringLock);
+ }
}
result = (CFStringRef)CFDictionaryGetValue(stringTable, key);
} else {
CFRetain(result);
}
- if (CFStringHasSuffix(tableName, CFSTR(".nocache")) && __CFBundleGetResourceData(bundle)->_stringTableCache && _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) CFDictionaryRemoveValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName);
-
+ CFRelease(stringTable);
return result;
}
uint8_t version = 0;
CFArrayRef languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, newURL, &version), types = NULL, array;
if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
array = _CFFindBundleResources(NULL, newURL, subDirName, languages, resourceName, types, 1, version);
-
if (types) CFRelease(types);
if (languages) CFRelease(languages);
-
if (array) {
if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
CFRelease(array);
uint8_t version = 0;
CFArrayRef languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, newURL, &version), types = NULL;
if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
// MF:!!! Better "limit" than 1,000,000?
array = _CFFindBundleResources(NULL, newURL, subDirName, languages, NULL, types, 1000000, version);
-
if (types) CFRelease(types);
if (languages) CFRelease(languages);
}
"ur_IN\0" "vi_VN\0" "fr_BE\0" "uz_UZ\0" "en_SG\0" "nn_NO\0" "af_ZA\0" "eo\0\0\0\0"
"mr_IN\0" "bo\0\0\0\0" "ne_NP\0" "kl\0\0\0\0" "en_IE\0";
-#define NUM_LOCALE_ABBREVIATIONS 109
-#define LOCALE_ABBREVIATION_LENGTH 6
+#define NUM_LOCALE_ABBREVIATIONS 109
+#define LOCALE_ABBREVIATION_LENGTH 6
static const char * const __CFBundleLanguageNamesArray[] = {
"English", "French", "German", "Italian", "Dutch", "Swedish", "Spanish", "Danish",
"Scottish", "Manx", "Irish", "Tongan", "Greek", "Greenlandic", "Azerbaijani", "Nynorsk"
};
-#define NUM_LANGUAGE_NAMES 152
-#define LANGUAGE_NAME_LENGTH 13
+#define NUM_LANGUAGE_NAMES 152
+#define LANGUAGE_NAME_LENGTH 13
// string, with groups of 3 characters being 1 element in the array of abbreviations
const char * __CFBundleLanguageAbbreviationsArray =
"ug\0" "dz\0" "jv\0" "su\0" "gl\0" "af\0" "br\0" "iu\0"
"gd\0" "gv\0" "ga\0" "to\0" "el\0" "kl\0" "az\0" "nn\0";
-#define NUM_LANGUAGE_ABBREVIATIONS 152
-#define LANGUAGE_ABBREVIATION_LENGTH 3
+#define NUM_LANGUAGE_ABBREVIATIONS 152
+#define LANGUAGE_ABBREVIATION_LENGTH 3
#if defined(__CONSTANT_CFSTRINGS__)
static SInt32 _CFBundleGetLanguageCodeForRegionCode(SInt32 regionCode) {
SInt32 result = -1, i;
- if (52 == regionCode) { // hack for mixed-up Chinese language codes
+ if (52 == regionCode) { // hack for mixed-up Chinese language codes
result = 33;
} else if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) {
const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH;
static SInt32 _CFBundleGetRegionCodeForLanguageCode(SInt32 languageCode) {
SInt32 result = -1, i;
- if (19 == languageCode) { // hack for mixed-up Chinese language codes
+ if (19 == languageCode) { // hack for mixed-up Chinese language codes
result = 53;
} else if (0 <= languageCode && languageCode < NUM_LANGUAGE_ABBREVIATIONS) {
const char *languageAbbreviation = __CFBundleLanguageAbbreviationsArray + languageCode * LANGUAGE_ABBREVIATION_LENGTH;
SInt32 result = -1, i;
char buff[LOCALE_ABBREVIATION_LENGTH];
CFIndex length = CFStringGetLength(localizationName);
- if ((length >= LANGUAGE_ABBREVIATION_LENGTH - 1) && (length <= LOCALE_ABBREVIATION_LENGTH - 1) && CFStringGetCString(localizationName, buff, LOCALE_ABBREVIATION_LENGTH, kCFStringEncodingASCII)) {
+ if (length >= LANGUAGE_ABBREVIATION_LENGTH - 1 && length <= LOCALE_ABBREVIATION_LENGTH - 1 && CFStringGetCString(localizationName, buff, LOCALE_ABBREVIATION_LENGTH, kCFStringEncodingASCII)) {
buff[LOCALE_ABBREVIATION_LENGTH - 1] = '\0';
for (i = 0; -1 == result && i < NUM_LOCALE_ABBREVIATIONS * LOCALE_ABBREVIATION_LENGTH; i += LOCALE_ABBREVIATION_LENGTH) {
if (0 == strcmp(buff, __CFBundleLocaleAbbreviationsArray + i)) result = i / LOCALE_ABBREVIATION_LENGTH;
if (!languages) languages = _CFBundleCopyUserLanguages(false);
if (languages && CFArrayGetCount(languages) > 0) localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
}
+ if (localizationName) {
+ LangCode langCode = -1;
+ RegionCode regCode = -1;
+ ScriptCode scrCode = 0;
+ CFStringEncoding enc = kCFStringEncodingMacRoman;
+ retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, ®Code, &scrCode, &enc);
+ if (retval) {
+ language = langCode;
+ region = regCode;
+ script = scrCode;
+ encoding = enc;
+ }
+ }
if (!retval) {
if (localizationName) {
language = _CFBundleGetLanguageCodeForLocalization(localizationName);
CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SInt32 regionCode, SInt32 scriptCode, CFStringEncoding stringEncoding) {
CFStringRef localizationName = NULL;
- if (!localizationName) {
- localizationName = _CFBundleCopyLocaleAbbreviationForRegionCode(regionCode);
- }
- if (!localizationName && 0 <= languageCode && languageCode < SHRT_MAX) {
- localizationName = CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(kCFAllocatorSystemDefault, (LangCode)languageCode, (RegionCode)-1);
- }
- if (!localizationName) {
- localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode);
- }
+ if (!localizationName) localizationName = _CFBundleCopyLocaleAbbreviationForRegionCode(regionCode);
+#if DEPLOYMENT_TARGET_MACOSX
+ if (!localizationName && 0 <= languageCode && languageCode < SHRT_MAX) localizationName = CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(kCFAllocatorSystemDefault, (LangCode)languageCode, (RegionCode)-1);
+#endif
+ if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode);
if (!localizationName) {
SInt32 language = -1, scriptLanguage = -1, encodingLanguage = -1;
unsigned int i;
extern void *__CFAppleLanguages;
+#if DEPLOYMENT_TARGET_WINDOWS
+
+extern CFStringRef copyLocaleLanguageName(void);
+extern CFStringRef copyLocaleCountryName(void);
+
+static CFArrayRef copyWindowsLanguagePrefsArray() {
+ CFArrayRef result;
+ CFStringRef locales[4];
+ CFStringRef languageName = copyLocaleLanguageName(), countryName = copyLocaleCountryName();
+ if (!languageName) languageName = CFSTR("en");
+ if (!countryName) countryName = CFSTR("");
+ CFIndex i, localesCount = 0;
+ if (CFStringGetLength(countryName) > 0) locales[localesCount++] = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@_%@"), languageName, countryName);
+ if (CFStringGetLength(languageName) != 0) {
+ // special-case for zh since we don't have a generic zh localization
+ if (CFStringCompare(languageName, CFSTR("zh"), kCFCompareCaseInsensitive) != 0) {
+ locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, languageName);//languageName;
+ } else {
+ CFStringRef moreSpecificLanguageName;
+
+ // See http://intrigue-build.apple.com/changeset/14948 for the details on the change. Copied below is the snippet of the code change.
+ // According to http://www.microsoft.com/globaldev/reference/win2k/setup/lcid.mspx, the locales that use
+ // 126 // simplified chinese are CN (PRC) and SG (Singapore). The rest use traditional chinese.
+ // 127 languageName = (countryName == TEXT("CN") || countryName == TEXT("SG")) ? TEXT("zh_CN") : TEXT("zh_TW");
+
+ // Compare for CN or SG
+ if (CFStringCompare(countryName, CFSTR("CN"), kCFCompareCaseInsensitive) == 0 || CFStringCompare(countryName, CFSTR("SG"), kCFCompareCaseInsensitive) == 0) {
+ moreSpecificLanguageName = CFSTR("zh_CN");
+ } else {
+ moreSpecificLanguageName = CFSTR("zh_TW");
+ }
+ locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, moreSpecificLanguageName);
+ }
+ // Don't need this now
+ if (languageName) CFRelease(languageName);
+ if (countryName) CFRelease(countryName);
+ }
+ if (localesCount == 0) locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, CFSTR("en"));
+ result = CFArrayCreate(kCFAllocatorDefault, (const void **)locales, localesCount, &kCFTypeArrayCallBacks);
+ for (i = 0; i < localesCount; i++) CFRelease(locales[i]);
+ return result;
+}
+
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
+static CFArrayRef _CFBundleUserLanguages = NULL;
+
__private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops) {
CFArrayRef result = NULL;
- static CFArrayRef userLanguages = NULL;
static Boolean didit = false;
CFArrayRef preferencesArray = NULL;
// This is a temporary solution, until the argument domain is moved down into CFPreferences
if (length > 0) {
data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)__CFAppleLanguages, length, kCFAllocatorNull);
if (data) {
- userLanguages = (CFArrayRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL);
+ _CFBundleUserLanguages = (CFArrayRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL);
CFRelease(data);
}
}
}
- if (!userLanguages && preferencesArray) userLanguages = (CFArrayRef)CFRetain(preferencesArray);
+ if (!_CFBundleUserLanguages && preferencesArray) _CFBundleUserLanguages = (CFArrayRef)CFRetain(preferencesArray);
Boolean useEnglishAsBackstop = true;
// could perhaps read out of LANG environment variable
- if (useEnglishAsBackstop && !userLanguages) {
+ if (useEnglishAsBackstop && !_CFBundleUserLanguages) {
CFStringRef english = CFSTR("en");
- userLanguages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&english, 1, &kCFTypeArrayCallBacks);
+ _CFBundleUserLanguages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&english, 1, &kCFTypeArrayCallBacks);
}
- if (userLanguages && CFGetTypeID(userLanguages) != CFArrayGetTypeID()) {
- CFRelease(userLanguages);
- userLanguages = NULL;
+ if (_CFBundleUserLanguages && CFGetTypeID(_CFBundleUserLanguages) != CFArrayGetTypeID()) {
+ CFRelease(_CFBundleUserLanguages);
+ _CFBundleUserLanguages = NULL;
}
didit = true;
}
__CFSpinUnlock(&CFBundleResourceGlobalDataLock);
if (preferencesArray) CFRelease(preferencesArray);
- if (!result && userLanguages) result = (CFArrayRef)CFRetain(userLanguages);
+ if (!result && _CFBundleUserLanguages) result = (CFArrayRef)CFRetain(_CFBundleUserLanguages);
return result;
}
Boolean retval = false;
LangCode langCode = -1;
RegionCode regCode = -1;
+ retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, ®Code, NULL, NULL);
+ if (retval) {
+ language = langCode;
+ region = regCode;
+ }
if (!retval) {
language = _CFBundleGetLanguageCodeForLocalization(localizationName);
region = _CFBundleGetRegionCodeForLocalization(localizationName);
}
-static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc, UniChar *pathUniChars, CFIndex pathLen, uint8_t version, CFDictionaryRef infoDict, CFStringRef curLangStr, CFMutableArrayRef lprojNames) {
+static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc, UniChar *pathUniChars, CFIndex pathLen, uint8_t version, CFDictionaryRef infoDict, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) {
CFIndex curLangLen = CFStringGetLength(curLangStr), savedPathLen;
UniChar curLangUniChars[255];
- CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL;
+ CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL;
CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL, predefinedCanonicalLanguageIdentifiers = NULL;
- Boolean foundOne = false;
+ Boolean foundOne = false, specifiesScript = false;
CFArrayRef predefinedLocalizations = NULL;
CFRange predefinedLocalizationsRange;
CFMutableStringRef cheapStr, tmpString;
}
}
}
- if (!altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
+ if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
curLangLen = CFStringGetLength(languageAbbreviation);
if (curLangLen > 255) curLangLen = 255;
CFStringGetCharacters(languageAbbreviation, CFRangeMake(0, curLangLen), curLangUniChars);
}
}
}
- if (!altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
+ if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
curLangLen = CFStringGetLength(languageName);
if (curLangLen > 255) curLangLen = 255;
CFStringGetCharacters(languageName, CFRangeMake(0, curLangLen), curLangUniChars);
if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier);
if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers);
if (predefinedCanonicalLanguageIdentifiers) CFRelease(predefinedCanonicalLanguageIdentifiers);
+ if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation);
CFRelease(cheapStr);
CFRelease(tmpString);
#if READ_DIRECTORIES
CFRelease(contents);
#endif /* READ_DIRECTORIES */
-
return foundOne;
}
return allowMixed;
}
+static Boolean _CFBundleLocalizationsHaveCommonPrefix(CFStringRef loc1, CFStringRef loc2) {
+ Boolean result = false;
+ CFIndex length1 = CFStringGetLength(loc1), length2 = CFStringGetLength(loc2), idx;
+ if (length1 > 3 && length2 > 3) {
+ for (idx = 0; idx < length1 && idx < length2; idx++) {
+ UniChar c1 = CFStringGetCharacterAtIndex(loc1, idx), c2 = CFStringGetCharacterAtIndex(loc2, idx);
+ if (idx >= 2 && (c1 == '-' || c1 == '_') && (c2 == '-' || c2 == '_')) {
+ result = true;
+ break;
+ } else if (c1 != c2) {
+ break;
+ }
+ }
+ }
+ return result;
+}
+
__private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, uint8_t version, CFDictionaryRef infoDict, CFMutableArrayRef lprojNames, CFStringRef devLang) {
// This function will add zero, one or two elements to the lprojNames array.
// It examines the users preferred language list and the lproj directories inside the bundle directory. It picks the lproj directory that is highest on the users list.
// The users list can contain region names (like "en_US" for US English). In this case, if the region lproj exists, it will be added, and, if the region's associated language lproj exists that will be added.
CFURLRef resourcesURL = _CFBundleCopyResourcesDirectoryURLInDirectory(alloc, bundleURL, version);
CFURLRef absoluteURL;
- CFIndex idx;
+ CFIndex idx, startIdx;
CFIndex count;
CFStringRef resourcesPath;
UniChar pathUniChars[CFMaxPathSize];
CFIndex pathLen;
- CFStringRef curLangStr;
+ CFStringRef curLangStr, nextLangStr;
Boolean foundOne = false;
-
CFArrayRef userLanguages;
// Init the one-time-only unichar buffers.
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);
- if (!CFEqual(bundleURL, mainBundleURL)) {
- // If there is a main bundle, and it isn't this one, try to use the language it prefers.
- CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle);
- if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) {
- curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0);
- foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames);
+ if (mainBundleURL) {
+ if (!CFEqual(bundleURL, mainBundleURL)) {
+ // If there is a main bundle, and it isn't this one, try to use the language it prefers.
+ CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle);
+ if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) {
+ curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0);
+ foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true);
+ }
}
+ CFRelease(mainBundleURL);
}
- CFRelease(mainBundleURL);
}
}
// If we didn't find the main bundle's preferred language, look at the users' prefs again and find the best one.
userLanguages = _CFBundleCopyUserLanguages(true);
count = (userLanguages ? CFArrayGetCount(userLanguages) : 0);
- for (idx = 0; !foundOne && idx < count; idx++) {
+ for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) {
curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx);
- foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames);
+ nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx + 1) : NULL;
+ if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) {
+ foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, false);
+ if (startIdx < 0) startIdx = idx;
+ } else if (startIdx >= 0 && startIdx <= idx) {
+ foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, false);
+ for (; !foundOne && startIdx <= idx; startIdx++) {
+ curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, startIdx);
+ foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true);
+ }
+ startIdx = -1;
+ } else {
+ foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true);
+ startIdx = -1;
+ }
}
// use development region and U.S. English as backstops
- if (!foundOne && devLang) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, devLang, lprojNames);
- if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, CFSTR("en_US"), lprojNames);
+ if (!foundOne && devLang) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, devLang, lprojNames, true);
+ if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, CFSTR("en_US"), lprojNames, true);
if (userLanguages) CFRelease(userLanguages);
}
}
-static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStringRef curLangStr, CFMutableArrayRef lprojNames) {
- Boolean foundOne = false;
+static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) {
+ Boolean foundOne = false, specifiesScript = false;
CFRange range = CFRangeMake(0, CFArrayGetCount(array));
- CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL;
+ CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL;
CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL;
if (range.length == 0) return foundOne;
foundOne = true;
}
}
- if (!altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
+ if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
if (CFArrayContainsValue(array, range, languageAbbreviation)) {
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageAbbreviation)) CFArrayAppendValue(lprojNames, languageAbbreviation);
foundOne = true;
}
}
- if (!altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
+ if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
if (CFArrayContainsValue(array, range, languageName)) {
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName);
foundOne = true;
if (languageName) CFRelease(languageName);
if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier);
if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers);
-
+ if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation);
return foundOne;
}
static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray, Boolean considerMain) {
CFMutableArrayRef lprojNames = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
Boolean foundOne = false, releasePrefArray = false;
- CFIndex idx, count;
+ CFIndex idx, count, startIdx;
if (considerMain && !CFBundleAllowMixedLocalizations()) {
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
// If there is a main bundle, try to use the language it prefers.
CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle);
- if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) {
- foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0), lprojNames);
- }
+ if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0), lprojNames, true);
}
}
+
if (!foundOne) {
+ CFStringRef curLangStr, nextLangStr;
if (!prefArray) {
prefArray = _CFBundleCopyUserLanguages(true);
if (prefArray) releasePrefArray = true;
}
count = (prefArray ? CFArrayGetCount(prefArray) : 0);
- for (idx = 0; !foundOne && idx < count; idx++) {
- foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx), lprojNames);
+ for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) {
+ curLangStr = (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx);
+ nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx + 1) : NULL;
+ if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) {
+ foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, false);
+ if (startIdx < 0) startIdx = idx;
+ } else if (startIdx >= 0 && startIdx <= idx) {
+ foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, false);
+ for (; !foundOne && startIdx <= idx; startIdx++) {
+ curLangStr = (CFStringRef)CFArrayGetValueAtIndex(prefArray, startIdx);
+ foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, true);
+ }
+ startIdx = -1;
+ } else {
+ foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, true);
+ startIdx = -1;
+ }
}
// use U.S. English as backstop
- if (!foundOne) {
- foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, CFSTR("en_US"), lprojNames);
- }
+ if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, CFSTR("en_US"), lprojNames, true);
// use random entry as backstop
- if (!foundOne && CFArrayGetCount(lprojNames) > 0) {
- foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(locArray, 0), lprojNames);
- }
+ if (!foundOne && CFArrayGetCount(locArray) > 0) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(locArray, 0), lprojNames, true);
}
if (CFArrayGetCount(lprojNames) == 0) {
// Total backstop behavior to avoid having an empty array.
return lprojNames;
}
-CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray) {return _CFBundleCopyLocalizationsForPreferences(locArray, prefArray, false);}
+CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray) {
+ return _CFBundleCopyLocalizationsForPreferences(locArray, prefArray, false);
+}
-CF_EXPORT CFArrayRef CFBundleCopyPreferredLocalizationsFromArray(CFArrayRef locArray) {return _CFBundleCopyLocalizationsForPreferences(locArray, NULL, true);}
+CF_EXPORT CFArrayRef CFBundleCopyPreferredLocalizationsFromArray(CFArrayRef locArray) {
+ return _CFBundleCopyLocalizationsForPreferences(locArray, NULL, true);
+}
__private_extern__ CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) {
CFMutableArrayRef langs = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
// Note that subDirName is expected to be the string for a URL
CF_INLINE Boolean _CFBundleURLHasSubDir(CFURLRef url, CFStringRef subDirName) {
- CFURLRef dirURL;
Boolean isDir = false, result = false;
-
- dirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, subDirName, url);
+ CFURLRef dirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, subDirName, url);
if (dirURL) {
if (_CFIsResourceAtURL(dirURL, &isDir) && isDir) result = true;
CFRelease(dirURL);
CFRelease(absoluteURL);
#endif /* READ_DIRECTORIES */
if (localVersion == 3) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX
if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/"))) {
if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
else if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
}
+#elif DEPLOYMENT_TARGET_WINDOWS
+ if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework\\"))) {
+ if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
+ else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
+ else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
+ } else {
+ if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
+ else if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
+ else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
+ }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
}
if (version) *version = localVersion;
- return !(localVersion == 3);
+ return (localVersion != 3);
}
__private_extern__ CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) {
infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension2;
infoURLFromBase = _CFBundleInfoURLFromBase2;
} else if (3 == version) {
-#if DEPLOYMENT_TARGET_MACOSX
- CFStringRef posixPath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
// this test is necessary to exclude the case where a bundle is spuriously created from the innards of another bundle
- if (posixPath) {
- if (!(CFStringHasSuffix(posixPath, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(posixPath, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(posixPath, _CFBundleResourcesDirectoryName))) {
+ if (path) {
+ if (!(CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(path, _CFBundleResourcesDirectoryName))) {
#if READ_DIRECTORIES
directoryURL = CFRetain(url);
#endif /* READ_DIRECTORIES */
infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension3;
infoURLFromBase = _CFBundleInfoURLFromBase3;
}
- CFRelease(posixPath);
+ CFRelease(path);
}
-#elif 0
- CFStringRef windowsPath = CFURLCopyFileSystemPath(url, kCFURLWindowsPathStyle);
- // this test is necessary to exclude the case where a bundle is spuriously created from the innards of another bundle
- if (windowsPath) {
- if (!(CFStringHasSuffix(windowsPath, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(windowsPath, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(windowsPath, _CFBundleResourcesDirectoryName))) {
-#if READ_DIRECTORIES
- directoryURL = CFRetain(url);
-#endif /* READ_DIRECTORIES */
- infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension3;
- infoURLFromBase = _CFBundleInfoURLFromBase3;
- }
- CFRelease(windowsPath);
- }
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
}
#if READ_DIRECTORIES
if (directoryURL) {
CFStringGetCharacters(urlStr, CFRangeMake(0, strLen), buff);
CFRelease(urlStr);
startOfExtension = _CFStartOfPathExtension(buff, strLen);
- if (((strLen - startOfExtension == 4) || (strLen - startOfExtension == 5)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'a') && (buff[startOfExtension+2] == (UniChar)'p') && (buff[startOfExtension+3] == (UniChar)'p') && ((strLen - startOfExtension == 4) || (buff[startOfExtension+4] == (UniChar)'/'))) {
+ if ((strLen - startOfExtension == 4 || strLen - startOfExtension == 5) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'a' && buff[startOfExtension+2] == (UniChar)'p' && buff[startOfExtension+3] == (UniChar)'p' && (strLen - startOfExtension == 4 || buff[startOfExtension+4] == (UniChar)'/')) {
// This is an app
*packageType = 0x4150504c; // 'APPL'
- } else if (((strLen - startOfExtension == 6) || (strLen - startOfExtension == 7)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'d') && (buff[startOfExtension+2] == (UniChar)'e') && (buff[startOfExtension+3] == (UniChar)'b') && (buff[startOfExtension+4] == (UniChar)'u') && (buff[startOfExtension+5] == (UniChar)'g') && ((strLen - startOfExtension == 6) || (buff[startOfExtension+6] == (UniChar)'/'))) {
+ } else if ((strLen - startOfExtension == 6 || strLen - startOfExtension == 7) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'d' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'b' && buff[startOfExtension+4] == (UniChar)'u' && buff[startOfExtension+5] == (UniChar)'g' && (strLen - startOfExtension == 6 || buff[startOfExtension+6] == (UniChar)'/')) {
// This is an app (debug version)
*packageType = 0x4150504c; // 'APPL'
- } else if (((strLen - startOfExtension == 8) || (strLen - startOfExtension == 9)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'p') && (buff[startOfExtension+2] == (UniChar)'r') && (buff[startOfExtension+3] == (UniChar)'o') && (buff[startOfExtension+4] == (UniChar)'f') && (buff[startOfExtension+5] == (UniChar)'i') && (buff[startOfExtension+6] == (UniChar)'l') && (buff[startOfExtension+7] == (UniChar)'e') && ((strLen - startOfExtension == 8) || (buff[startOfExtension+8] == (UniChar)'/'))) {
+ } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'p' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'o' && buff[startOfExtension+4] == (UniChar)'f' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'l' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)'/')) {
// This is an app (profile version)
*packageType = 0x4150504c; // 'APPL'
- } else if (((strLen - startOfExtension == 8) || (strLen - startOfExtension == 9)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'s') && (buff[startOfExtension+2] == (UniChar)'e') && (buff[startOfExtension+3] == (UniChar)'r') && (buff[startOfExtension+4] == (UniChar)'v') && (buff[startOfExtension+5] == (UniChar)'i') && (buff[startOfExtension+6] == (UniChar)'c') && (buff[startOfExtension+7] == (UniChar)'e') && ((strLen - startOfExtension == 8) || (buff[startOfExtension+8] == (UniChar)'/'))) {
+ } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'s' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'r' && buff[startOfExtension+4] == (UniChar)'v' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'c' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)'/')) {
// This is a service
*packageType = 0x4150504c; // 'APPL'
- } else if (((strLen - startOfExtension == 10) || (strLen - startOfExtension == 11)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'f') && (buff[startOfExtension+2] == (UniChar)'r') && (buff[startOfExtension+3] == (UniChar)'a') && (buff[startOfExtension+4] == (UniChar)'m') && (buff[startOfExtension+5] == (UniChar)'e') && (buff[startOfExtension+6] == (UniChar)'w') && (buff[startOfExtension+7] == (UniChar)'o') && (buff[startOfExtension+8] == (UniChar)'r') && (buff[startOfExtension+9] == (UniChar)'k') && ((strLen - startOfExtension == 10) || (buff[startOfExtension+10] == (UniChar)'/'))) {
+ } else if ((strLen - startOfExtension == 10 || strLen - startOfExtension == 11) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'f' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'a' && buff[startOfExtension+4] == (UniChar)'m' && buff[startOfExtension+5] == (UniChar)'e' && buff[startOfExtension+6] == (UniChar)'w' && buff[startOfExtension+7] == (UniChar)'o' && buff[startOfExtension+8] == (UniChar)'r' && buff[startOfExtension+9] == (UniChar)'k' && (strLen - startOfExtension == 10 || buff[startOfExtension+10] == (UniChar)'/')) {
// This is a framework
*packageType = 0x464d574b; // 'FMWK'
} else {
return retVal;
}
-CF_EXPORT Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {return _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(alloc, url, NULL, packageType, packageCreator);}
+CF_EXPORT Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {
+ return _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(alloc, url, NULL, packageType, packageCreator);
+}
CF_EXPORT void CFBundleGetPackageInfo(CFBundleRef bundle, UInt32 *packageType, UInt32 *packageCreator) {
CFURLRef bundleURL = CFBundleCopyBundleURL(bundle);
if (bundleURL) CFRelease(bundleURL);
}
-CF_EXPORT Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {return _CFBundleGetPackageInfoInDirectory(kCFAllocatorSystemDefault, url, packageType, packageCreator);}
+CF_EXPORT Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {
+ return _CFBundleGetPackageInfoInDirectory(kCFAllocatorSystemDefault, url, packageType, packageCreator);
+}
-__private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) {
+static void _CFBundleCheckSupportedPlatform(CFMutableArrayRef mutableArray, UniChar *buff, CFIndex startLen, CFStringRef platformName, CFStringRef platformIdentifier) {
+ CFIndex buffLen = startLen, platformLen = CFStringGetLength(platformName), extLen = CFStringGetLength(_CFBundleInfoExtension);
+ CFMutableStringRef str;
+ Boolean isDir;
+ if (buffLen + platformLen + extLen < CFMaxPathSize) {
+ CFStringGetCharacters(platformName, CFRangeMake(0, platformLen), buff + buffLen);
+ buffLen += platformLen;
+ buff[buffLen++] = (UniChar)'.';
+ CFStringGetCharacters(_CFBundleInfoExtension, CFRangeMake(0, extLen), buff + buffLen);
+ buffLen += extLen;
+ str = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+ CFStringAppendCharacters(str, buff, buffLen);
+ if (_CFIsResourceAtPath(str, &isDir) && !isDir && CFArrayGetFirstIndexOfValue(mutableArray, CFRangeMake(0, CFArrayGetCount(mutableArray)), platformIdentifier) < 0) CFArrayAppendValue(mutableArray, platformIdentifier);
+ CFRelease(str);
+ }
+}
+
+CF_EXPORT CFArrayRef _CFBundleGetSupportedPlatforms(CFBundleRef bundle) {
+ CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
+ CFArrayRef platformArray = infoDict ? (CFArrayRef)CFDictionaryGetValue(infoDict, _kCFBundleSupportedPlatformsKey) : NULL;
+ if (platformArray && CFGetTypeID(platformArray) != CFArrayGetTypeID()) {
+ platformArray = NULL;
+ CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleSupportedPlatformsKey);
+ }
+ if (!platformArray) {
+ CFURLRef infoPlistURL = infoDict ? (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleInfoPlistURLKey) : NULL, absoluteURL;
+ CFStringRef infoPlistPath;
+ UniChar buff[CFMaxPathSize];
+ CFIndex buffLen, infoLen = CFStringGetLength(_CFBundleInfoURLFromBaseNoExtension3), startLen, extLen = CFStringGetLength(_CFBundleInfoExtension);
+ if (infoPlistURL) {
+ CFMutableArrayRef mutableArray = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &kCFTypeArrayCallBacks);
+ absoluteURL = CFURLCopyAbsoluteURL(infoPlistURL);
+ infoPlistPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
+ CFRelease(absoluteURL);
+ buffLen = CFStringGetLength(infoPlistPath);
+ if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
+ CFStringGetCharacters(infoPlistPath, CFRangeMake(0, buffLen), buff);
+ CFRelease(infoPlistPath);
+ if (buffLen > 0) {
+ buffLen = _CFStartOfLastPathComponent(buff, buffLen);
+ if (buffLen > 0 && buffLen + infoLen + extLen < CFMaxPathSize) {
+ CFStringGetCharacters(_CFBundleInfoURLFromBaseNoExtension3, CFRangeMake(0, infoLen), buff + buffLen);
+ buffLen += infoLen;
+ buff[buffLen++] = (UniChar)'-';
+ startLen = buffLen;
+ _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("macos"), CFSTR("MacOS"));
+ _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("macosx"), CFSTR("MacOS"));
+ _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("iphoneos"), CFSTR("iPhoneOS"));
+ _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("windows"), CFSTR("Windows"));
+ }
+ }
+ if (CFArrayGetCount(mutableArray) > 0) {
+ platformArray = (CFArrayRef)mutableArray;
+ CFDictionarySetValue((CFMutableDictionaryRef)infoDict, _kCFBundleSupportedPlatformsKey, platformArray);
+ }
+ CFRelease(mutableArray);
+ }
+ }
+ return platformArray;
+}
+
+CF_EXPORT CFStringRef _CFBundleGetCurrentPlatform(void) {
#if DEPLOYMENT_TARGET_MACOSX
return CFSTR("MacOS");
+#elif DEPLOYMENT_TARGET_EMBEDDED
+ return CFSTR("iPhoneOS");
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return CFSTR("Windows");
+#elif DEPLOYMENT_TARGET_SOLARIS
+ return CFSTR("Solaris");
+#elif DEPLOYMENT_TARGET_HPUX
+ return CFSTR("HPUX");
+#elif DEPLOYMENT_TARGET_LINUX
+ return CFSTR("Linux");
+#elif DEPLOYMENT_TARGET_FREEBSD
+ return CFSTR("FreeBSD");
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+}
+
+__private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+ return CFSTR("MacOS");
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return CFSTR("Windows");
#elif DEPLOYMENT_TARGET_SOLARIS
return CFSTR("Solaris");
#elif DEPLOYMENT_TARGET_HPUX
}
__private_extern__ CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
return CFSTR("Mac OS X");
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return CFSTR("WinNT");
#elif DEPLOYMENT_TARGET_SOLARIS
return CFSTR("Solaris");
#elif DEPLOYMENT_TARGET_HPUX
}
__private_extern__ CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
return CFSTR("MacOSClassic");
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return CFSTR("Other");
#elif DEPLOYMENT_TARGET_HPUX
return CFSTR("Other");
#elif DEPLOYMENT_TARGET_SOLARIS
}
__private_extern__ CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
return CFSTR("Mac OS 8");
+#elif DEPLOYMENT_TARGET_WINDOWS
+ return CFSTR("Other");
#elif DEPLOYMENT_TARGET_HPUX
return CFSTR("Other");
#elif DEPLOYMENT_TARGET_SOLARIS
#endif
}
-__private_extern__ CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle) {return CFBundleCopyBundleLocalizations(bundle);}
+__private_extern__ CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle) {
+ return CFBundleCopyBundleLocalizations(bundle);
+}
CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) {
CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
}
}
if (resourcesURL) CFRelease(resourcesURL);
-
return result;
}