[Release] Webkit2-efl-123997_0.11.86
[framework/web/webkit-efl.git] / Source / WebKit / win / WebLocalizableStrings.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "WebKitDLL.h"
28
29 #include "WebLocalizableStrings.h"
30
31 #include <WebCore/PlatformString.h>
32 #include <wtf/text/CString.h>
33 #include <wtf/text/StringHash.h>
34
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>
40
41 class LocalizedString;
42
43 using namespace WebCore;
44
45 WebLocalizableStringsBundle WebKitLocalizableStringsBundle = { "com.apple.WebKit", 0 };
46
47 typedef HashMap<String, LocalizedString*> LocalizedStringMap;
48
49 static Mutex& mainBundleLocStringsMutex()
50 {
51     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
52     return mutex;
53 }
54
55 static LocalizedStringMap& mainBundleLocStrings()
56 {
57     DEFINE_STATIC_LOCAL(LocalizedStringMap, map, ());
58     return map;
59 }
60
61 static Mutex& frameworkLocStringsMutex()
62 {
63     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
64     return mutex;
65 }
66
67 static LocalizedStringMap frameworkLocStrings()
68 {
69     DEFINE_STATIC_LOCAL(LocalizedStringMap, map, ());
70     return map;
71 }
72
73 class LocalizedString {
74     WTF_MAKE_NONCOPYABLE(LocalizedString);
75 public:
76     LocalizedString(CFStringRef string)
77         : m_cfString(string)
78     {
79         ASSERT_ARG(string, string);
80     }
81
82     operator LPCTSTR() const;
83     operator CFStringRef() const { return m_cfString; }
84
85 private:
86     CFStringRef m_cfString;
87     mutable String m_string;
88 };
89
90 LocalizedString::operator LPCTSTR() const
91 {
92     if (!m_string.isEmpty())
93         return m_string.charactersWithNullTermination();
94
95     m_string = m_cfString;
96
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");
100
101     return m_string.charactersWithNullTermination();
102 }
103
104 static CFBundleRef createWebKitBundle()
105 {
106     static CFBundleRef bundle;
107     static bool initialized;
108
109     if (initialized)
110         return bundle;
111     initialized = true;
112
113     WCHAR pathStr[MAX_PATH];
114     DWORD length = ::GetModuleFileNameW(gInstance, pathStr, MAX_PATH);
115     if (!length || (length == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER))
116         return 0;
117
118     bool found = false;
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)
125             pathStr[i] = 0;
126             found = true;
127             break;
128         }
129     }
130     if (!found)
131         return 0;
132
133     if (wcscat_s(pathStr, MAX_PATH, L"\\WebKit.resources"))
134         return 0;
135
136     String bundlePathString(pathStr);
137     CFStringRef bundlePathCFString = bundlePathString.createCFString();
138     if (!bundlePathCFString)
139         return 0;
140
141     CFURLRef bundleURLRef = CFURLCreateWithFileSystemPath(0, bundlePathCFString, kCFURLWindowsPathStyle, true);
142     CFRelease(bundlePathCFString);
143     if (!bundleURLRef)
144         return 0;
145
146     bundle = CFBundleCreate(0, bundleURLRef);
147     CFRelease(bundleURLRef);
148     return bundle;
149 }
150
151 static CFBundleRef cfBundleForStringsBundle(WebLocalizableStringsBundle* stringsBundle)
152 {
153     if (!stringsBundle) {
154         static CFBundleRef mainBundle = CFBundleGetMainBundle();
155         return mainBundle;
156     }
157
158     createWebKitBundle();
159
160     if (!stringsBundle->bundle)
161         stringsBundle->bundle = CFBundleGetBundleWithIdentifier(RetainPtr<CFStringRef>(AdoptCF, CFStringCreateWithCString(0, stringsBundle->identifier, kCFStringEncodingASCII)).get());
162     return stringsBundle->bundle;
163 }
164
165 static CFStringRef copyLocalizedStringFromBundle(WebLocalizableStringsBundle* stringsBundle, const String& key)
166 {
167     static CFStringRef notFound = CFSTR("localized string not found");
168
169     CFBundleRef bundle = cfBundleForStringsBundle(stringsBundle);
170     if (!bundle)
171         return notFound;
172
173     RetainPtr<CFStringRef> keyString(AdoptCF, key.createCFString());
174     CFStringRef result = CFCopyLocalizedStringWithDefaultValue(keyString.get(), 0, bundle, notFound, 0);
175
176     ASSERT_WITH_MESSAGE(result != notFound, "could not find localizable string %s in bundle", key);
177     return result;
178 }
179
180 static LocalizedString* findCachedString(WebLocalizableStringsBundle* stringsBundle, const String& key)
181 {
182     if (!stringsBundle) {
183         MutexLocker lock(mainBundleLocStringsMutex());
184         return mainBundleLocStrings().get(key);
185     }
186
187     if (stringsBundle->bundle == WebKitLocalizableStringsBundle.bundle) {
188         MutexLocker lock(frameworkLocStringsMutex());
189         return frameworkLocStrings().get(key);
190     }
191
192     return 0;
193 }
194
195 static void cacheString(WebLocalizableStringsBundle* stringsBundle, const String& key, LocalizedString* value)
196 {
197     if (!stringsBundle) {
198         MutexLocker lock(mainBundleLocStringsMutex());
199         mainBundleLocStrings().set(key, value);
200         return;
201     }
202
203     MutexLocker lock(frameworkLocStringsMutex());
204     frameworkLocStrings().set(key, value);
205 }
206
207 static const LocalizedString& localizedString(WebLocalizableStringsBundle* stringsBundle, const String& key)
208 {
209     LocalizedString* string = findCachedString(stringsBundle, key);
210     if (string)
211         return *string;
212
213     string = new LocalizedString(copyLocalizedStringFromBundle(stringsBundle, key));
214     cacheString(stringsBundle, key, string);
215
216     return *string;
217 }
218
219 CFStringRef WebLocalizedStringUTF8(WebLocalizableStringsBundle* stringsBundle, LPCSTR key)
220 {
221     if (!key)
222         return 0;
223
224     return localizedString(stringsBundle, String::fromUTF8(key));
225 }
226
227 LPCTSTR WebLocalizedLPCTSTRUTF8(WebLocalizableStringsBundle* stringsBundle, LPCSTR key)
228 {
229     if (!key)
230         return 0;
231
232     return localizedString(stringsBundle, String::fromUTF8(key));
233 }
234
235 // These functions are deprecated.
236
237 CFStringRef WebLocalizedString(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
238 {
239     if (!key)
240         return 0;
241
242     return localizedString(stringsBundle, String(key));
243 }
244
245 LPCTSTR WebLocalizedLPCTSTR(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
246 {
247     if (!key)
248         return 0;
249
250     return localizedString(stringsBundle, String(key));
251 }
252
253 void SetWebLocalizedStringMainBundle(CFBundleRef)
254 {
255 }