2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "WebKitDLL.h"
29 #include "WebLocalizableStrings.h"
31 #include <WebCore/PlatformString.h>
32 #include <wtf/text/CString.h>
33 #include <wtf/text/StringHash.h>
35 #include <wtf/Assertions.h>
36 #include <wtf/HashMap.h>
37 #include <wtf/RetainPtr.h>
38 #include <wtf/StdLibExtras.h>
39 #include <CoreFoundation/CoreFoundation.h>
41 class LocalizedString;
43 using namespace WebCore;
45 WebLocalizableStringsBundle WebKitLocalizableStringsBundle = { "com.apple.WebKit", 0 };
47 typedef HashMap<String, LocalizedString*> LocalizedStringMap;
49 static Mutex& mainBundleLocStringsMutex()
51 DEFINE_STATIC_LOCAL(Mutex, mutex, ());
55 static LocalizedStringMap& mainBundleLocStrings()
57 DEFINE_STATIC_LOCAL(LocalizedStringMap, map, ());
61 static Mutex& frameworkLocStringsMutex()
63 DEFINE_STATIC_LOCAL(Mutex, mutex, ());
67 static LocalizedStringMap frameworkLocStrings()
69 DEFINE_STATIC_LOCAL(LocalizedStringMap, map, ());
73 class LocalizedString {
74 WTF_MAKE_NONCOPYABLE(LocalizedString);
76 LocalizedString(CFStringRef string)
79 ASSERT_ARG(string, string);
82 operator LPCTSTR() const;
83 operator CFStringRef() const { return m_cfString; }
86 CFStringRef m_cfString;
87 mutable String m_string;
90 LocalizedString::operator LPCTSTR() const
92 if (!m_string.isEmpty())
93 return m_string.charactersWithNullTermination();
95 m_string = m_cfString;
97 for (unsigned int i = 1; i < m_string.length(); i++)
98 if (m_string[i] == '@' && (m_string[i - 1] == '%' || (i > 2 && m_string[i - 1] == '$' && m_string[i - 2] >= '1' && m_string[i - 2] <= '9' && m_string[i - 3] == '%')))
99 m_string.replace(i, 1, "s");
101 return m_string.charactersWithNullTermination();
104 static CFBundleRef createWebKitBundle()
106 static CFBundleRef bundle;
107 static bool initialized;
113 WCHAR pathStr[MAX_PATH];
114 DWORD length = ::GetModuleFileNameW(gInstance, pathStr, MAX_PATH);
115 if (!length || (length == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER))
119 for (int i = length - 1; i >= 0; i--) {
120 // warning C6385: Invalid data: accessing 'pathStr', the readable size is '520' bytes, but '2000' bytes might be read
121 #pragma warning(suppress: 6385)
122 if (pathStr[i] == L'\\') {
123 // warning C6386: Buffer overrun: accessing 'pathStr', the writable size is '520' bytes, but '1996' bytes might be written
124 #pragma warning(suppress: 6386)
133 if (wcscat_s(pathStr, MAX_PATH, L"\\WebKit.resources"))
136 String bundlePathString(pathStr);
137 CFStringRef bundlePathCFString = bundlePathString.createCFString();
138 if (!bundlePathCFString)
141 CFURLRef bundleURLRef = CFURLCreateWithFileSystemPath(0, bundlePathCFString, kCFURLWindowsPathStyle, true);
142 CFRelease(bundlePathCFString);
146 bundle = CFBundleCreate(0, bundleURLRef);
147 CFRelease(bundleURLRef);
151 static CFBundleRef cfBundleForStringsBundle(WebLocalizableStringsBundle* stringsBundle)
153 if (!stringsBundle) {
154 static CFBundleRef mainBundle = CFBundleGetMainBundle();
158 createWebKitBundle();
160 if (!stringsBundle->bundle)
161 stringsBundle->bundle = CFBundleGetBundleWithIdentifier(RetainPtr<CFStringRef>(AdoptCF, CFStringCreateWithCString(0, stringsBundle->identifier, kCFStringEncodingASCII)).get());
162 return stringsBundle->bundle;
165 static CFStringRef copyLocalizedStringFromBundle(WebLocalizableStringsBundle* stringsBundle, const String& key)
167 static CFStringRef notFound = CFSTR("localized string not found");
169 CFBundleRef bundle = cfBundleForStringsBundle(stringsBundle);
173 RetainPtr<CFStringRef> keyString(AdoptCF, key.createCFString());
174 CFStringRef result = CFCopyLocalizedStringWithDefaultValue(keyString.get(), 0, bundle, notFound, 0);
176 ASSERT_WITH_MESSAGE(result != notFound, "could not find localizable string %s in bundle", key);
180 static LocalizedString* findCachedString(WebLocalizableStringsBundle* stringsBundle, const String& key)
182 if (!stringsBundle) {
183 MutexLocker lock(mainBundleLocStringsMutex());
184 return mainBundleLocStrings().get(key);
187 if (stringsBundle->bundle == WebKitLocalizableStringsBundle.bundle) {
188 MutexLocker lock(frameworkLocStringsMutex());
189 return frameworkLocStrings().get(key);
195 static void cacheString(WebLocalizableStringsBundle* stringsBundle, const String& key, LocalizedString* value)
197 if (!stringsBundle) {
198 MutexLocker lock(mainBundleLocStringsMutex());
199 mainBundleLocStrings().set(key, value);
203 MutexLocker lock(frameworkLocStringsMutex());
204 frameworkLocStrings().set(key, value);
207 static const LocalizedString& localizedString(WebLocalizableStringsBundle* stringsBundle, const String& key)
209 LocalizedString* string = findCachedString(stringsBundle, key);
213 string = new LocalizedString(copyLocalizedStringFromBundle(stringsBundle, key));
214 cacheString(stringsBundle, key, string);
219 CFStringRef WebLocalizedStringUTF8(WebLocalizableStringsBundle* stringsBundle, LPCSTR key)
224 return localizedString(stringsBundle, String::fromUTF8(key));
227 LPCTSTR WebLocalizedLPCTSTRUTF8(WebLocalizableStringsBundle* stringsBundle, LPCSTR key)
232 return localizedString(stringsBundle, String::fromUTF8(key));
235 // These functions are deprecated.
237 CFStringRef WebLocalizedString(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
242 return localizedString(stringsBundle, String(key));
245 LPCTSTR WebLocalizedLPCTSTR(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
250 return localizedString(stringsBundle, String(key));
253 void SetWebLocalizedStringMainBundle(CFBundleRef)