Turn on static code analysis.
[WebKit-https.git] / 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 #pragma warning(push, 0)
32 #include <WebCore/PlatformString.h>
33 #include <WebCore/StringHash.h>
34 #pragma warning(pop)
35
36 #include <WTF/Assertions.h>
37 #include <WTF/HashMap.h>
38 #include <CoreFoundation/CoreFoundation.h>
39
40 using namespace WebCore;
41
42 WebLocalizableStringsBundle WebKitLocalizableStringsBundle = { "com.apple.WebKit", 0 };
43
44 static CFBundleRef localizedStringsMainBundle;
45 static HashMap<String, String> mainBundleLocStrings;
46 static HashMap<String, String> frameworkLocStrings;
47
48 static CFBundleRef createWebKitBundle()
49 {
50     WCHAR pathStr[MAX_PATH];
51     DWORD length = ::GetModuleFileNameW(gInstance, pathStr, MAX_PATH);
52     if (!length || (length == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER))
53         return 0;
54
55     bool found = false;
56     for (int i = length - 1; i >= 0; i--) {
57         // warning C6385: Invalid data: accessing 'pathStr', the readable size is '520' bytes, but '2000' bytes might be read
58         #pragma warning(suppress: 6385)
59         if (pathStr[i] == L'\\') {
60             // warning C6386: Buffer overrun: accessing 'pathStr', the writable size is '520' bytes, but '1996' bytes might be written
61             #pragma warning(suppress: 6386)
62             pathStr[i] = 0;
63             found = true;
64             break;
65         }
66     }
67     if (!found)
68         return 0;
69
70     if (wcscat_s(pathStr, MAX_PATH, L"\\WebKit.resources"))
71         return 0;
72
73     String bundlePathString(pathStr);
74     CFStringRef bundlePathCFString = bundlePathString.createCFString();
75     if (!bundlePathCFString)
76         return 0;
77
78     CFURLRef bundleURLRef = CFURLCreateWithFileSystemPath(0, bundlePathCFString, kCFURLWindowsPathStyle, true);
79     CFRelease(bundlePathCFString);
80     if (!bundleURLRef)
81         return 0;
82
83     CFBundleRef bundle = CFBundleCreate(0, bundleURLRef);
84     CFRelease(bundleURLRef);
85     return bundle;
86 }
87
88 void SetWebLocalizedStringMainBundle(CFBundleRef bundle)
89 {
90     if (bundle)
91         CFRetain(bundle);
92     if (localizedStringsMainBundle)
93         CFRelease(localizedStringsMainBundle);
94     localizedStringsMainBundle = bundle;
95 }
96
97 CFStringRef WebLocalizedString(WebLocalizableStringsBundle* stringsBundle, const UniChar* key)
98 {
99     static CFStringRef notFound = CFSTR("localized string not found");
100
101     CFBundleRef bundle;
102     if (!stringsBundle) {
103         static CFBundleRef mainBundle;
104         if (!mainBundle) {
105             mainBundle = localizedStringsMainBundle;
106             if (!mainBundle)
107                 return notFound;
108         }
109         bundle = mainBundle;
110     } else {
111         bundle = stringsBundle->bundle;
112         if (!bundle) {
113             bundle = createWebKitBundle();
114             if (!bundle)
115                 return notFound;
116             stringsBundle->bundle = bundle;
117         }
118     }
119     CFStringRef keyString = CFStringCreateWithCharacters(0, key, (CFIndex)wcslen(reinterpret_cast<const wchar_t*>(key)));
120     CFStringRef result = CFCopyLocalizedStringWithDefaultValue(keyString, 0, bundle, notFound, 0);
121     CFRelease(keyString);
122     ASSERT_WITH_MESSAGE(result != notFound, "could not find localizable string %s in bundle", key);
123     return result;
124 }
125
126 LPCTSTR WebLocalizedLPCTSTR(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
127 {
128     if (!key)
129         return 0;
130     String keyString(key);
131     if (!stringsBundle && mainBundleLocStrings.contains(keyString))
132         return mainBundleLocStrings.get(keyString).charactersWithNullTermination();
133     if (stringsBundle && stringsBundle->bundle == WebKitLocalizableStringsBundle.bundle && frameworkLocStrings.contains(keyString))
134         return frameworkLocStrings.get(keyString).charactersWithNullTermination();
135
136     CFStringRef cfStr = WebLocalizedString(stringsBundle, reinterpret_cast<const UniChar*>(key));
137     String str(cfStr);
138     if (cfStr)
139         CFRelease(cfStr);
140     for (unsigned int i=1; i<str.length(); i++)
141         if (str[i] == '@' && str[i - 1] == '%')
142             str.replace(i, 1, "s");
143
144     LPCTSTR lpszStr = str.charactersWithNullTermination();
145
146     if (!stringsBundle)
147         mainBundleLocStrings.set(keyString, str);
148     else if (stringsBundle)
149         frameworkLocStrings.set(keyString, str);
150
151     return lpszStr;
152 }