WebKit/win/WebLocalizableStrings.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 #include <wtf/text/CString.h>
       
    35 #pragma warning(pop)
       
    36 
       
    37 #include <wtf/Assertions.h>
       
    38 #include <wtf/HashMap.h>
       
    39 #include <wtf/RetainPtr.h>
       
    40 #include <wtf/StdLibExtras.h>
       
    41 #include <CoreFoundation/CoreFoundation.h>
       
    42 
       
    43 class LocalizedString;
       
    44 
       
    45 using namespace WebCore;
       
    46 
       
    47 WebLocalizableStringsBundle WebKitLocalizableStringsBundle = { "com.apple.WebKit", 0 };
       
    48 
       
    49 typedef HashMap<String, LocalizedString*> LocalizedStringMap;
       
    50 
       
    51 static Mutex& mainBundleLocStringsMutex()
       
    52 {
       
    53     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
       
    54     return mutex;
       
    55 }
       
    56 
       
    57 static LocalizedStringMap& mainBundleLocStrings()
       
    58 {
       
    59     DEFINE_STATIC_LOCAL(LocalizedStringMap, map, ());
       
    60     return map;
       
    61 }
       
    62 
       
    63 static Mutex& frameworkLocStringsMutex()
       
    64 {
       
    65     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
       
    66     return mutex;
       
    67 }
       
    68 
       
    69 static LocalizedStringMap frameworkLocStrings()
       
    70 {
       
    71     DEFINE_STATIC_LOCAL(LocalizedStringMap, map, ());
       
    72     return map;
       
    73 }
       
    74 
       
    75 class LocalizedString : public Noncopyable {
       
    76 public:
       
    77     LocalizedString(CFStringRef string)
       
    78         : m_cfString(string)
       
    79     {
       
    80         ASSERT_ARG(string, string);
       
    81     }
       
    82 
       
    83     operator LPCTSTR() const;
       
    84     operator CFStringRef() const { return m_cfString; }
       
    85 
       
    86 private:
       
    87     CFStringRef m_cfString;
       
    88     mutable String m_string;
       
    89 };
       
    90 
       
    91 LocalizedString::operator LPCTSTR() const
       
    92 {
       
    93     if (!m_string.isEmpty())
       
    94         return m_string.charactersWithNullTermination();
       
    95 
       
    96     m_string = m_cfString;
       
    97 
       
    98     for (unsigned int i = 1; i < m_string.length(); i++)
       
    99         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] == '%')))
       
   100             m_string.replace(i, 1, "s");
       
   101 
       
   102     return m_string.charactersWithNullTermination();
       
   103 }
       
   104 
       
   105 static CFBundleRef createWebKitBundle()
       
   106 {
       
   107     static CFBundleRef bundle;
       
   108     static bool initialized;
       
   109 
       
   110     if (initialized)
       
   111         return bundle;
       
   112     initialized = true;
       
   113 
       
   114     WCHAR pathStr[MAX_PATH];
       
   115     DWORD length = ::GetModuleFileNameW(gInstance, pathStr, MAX_PATH);
       
   116     if (!length || (length == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER))
       
   117         return 0;
       
   118 
       
   119     bool found = false;
       
   120     for (int i = length - 1; i >= 0; i--) {
       
   121         // warning C6385: Invalid data: accessing 'pathStr', the readable size is '520' bytes, but '2000' bytes might be read
       
   122         #pragma warning(suppress: 6385)
       
   123         if (pathStr[i] == L'\\') {
       
   124             // warning C6386: Buffer overrun: accessing 'pathStr', the writable size is '520' bytes, but '1996' bytes might be written
       
   125             #pragma warning(suppress: 6386)
       
   126             pathStr[i] = 0;
       
   127             found = true;
       
   128             break;
       
   129         }
       
   130     }
       
   131     if (!found)
       
   132         return 0;
       
   133 
       
   134     if (wcscat_s(pathStr, MAX_PATH, L"\\WebKit.resources"))
       
   135         return 0;
       
   136 
       
   137     String bundlePathString(pathStr);
       
   138     CFStringRef bundlePathCFString = bundlePathString.createCFString();
       
   139     if (!bundlePathCFString)
       
   140         return 0;
       
   141 
       
   142     CFURLRef bundleURLRef = CFURLCreateWithFileSystemPath(0, bundlePathCFString, kCFURLWindowsPathStyle, true);
       
   143     CFRelease(bundlePathCFString);
       
   144     if (!bundleURLRef)
       
   145         return 0;
       
   146 
       
   147     bundle = CFBundleCreate(0, bundleURLRef);
       
   148     CFRelease(bundleURLRef);
       
   149     return bundle;
       
   150 }
       
   151 
       
   152 static CFBundleRef cfBundleForStringsBundle(WebLocalizableStringsBundle* stringsBundle)
       
   153 {
       
   154     if (!stringsBundle) {
       
   155         static CFBundleRef mainBundle = CFBundleGetMainBundle();
       
   156         return mainBundle;
       
   157     }
       
   158 
       
   159     createWebKitBundle();
       
   160 
       
   161     if (!stringsBundle->bundle)
       
   162         stringsBundle->bundle = CFBundleGetBundleWithIdentifier(RetainPtr<CFStringRef>(AdoptCF, CFStringCreateWithCString(0, stringsBundle->identifier, kCFStringEncodingASCII)).get());
       
   163     return stringsBundle->bundle;
       
   164 }
       
   165 
       
   166 static CFStringRef copyLocalizedStringFromBundle(WebLocalizableStringsBundle* stringsBundle, const String& key)
       
   167 {
       
   168     static CFStringRef notFound = CFSTR("localized string not found");
       
   169 
       
   170     CFBundleRef bundle = cfBundleForStringsBundle(stringsBundle);
       
   171     if (!bundle)
       
   172         return notFound;
       
   173 
       
   174     RetainPtr<CFStringRef> keyString(AdoptCF, key.createCFString());
       
   175     CFStringRef result = CFCopyLocalizedStringWithDefaultValue(keyString.get(), 0, bundle, notFound, 0);
       
   176 
       
   177     ASSERT_WITH_MESSAGE(result != notFound, "could not find localizable string %s in bundle", key);
       
   178     return result;
       
   179 }
       
   180 
       
   181 static LocalizedString* findCachedString(WebLocalizableStringsBundle* stringsBundle, const String& key)
       
   182 {
       
   183     if (!stringsBundle) {
       
   184         MutexLocker lock(mainBundleLocStringsMutex());
       
   185         return mainBundleLocStrings().get(key);
       
   186     }
       
   187 
       
   188     if (stringsBundle->bundle == WebKitLocalizableStringsBundle.bundle) {
       
   189         MutexLocker lock(frameworkLocStringsMutex());
       
   190         return frameworkLocStrings().get(key);
       
   191     }
       
   192 
       
   193     return 0;
       
   194 }
       
   195 
       
   196 static void cacheString(WebLocalizableStringsBundle* stringsBundle, const String& key, LocalizedString* value)
       
   197 {
       
   198     if (!stringsBundle) {
       
   199         MutexLocker lock(mainBundleLocStringsMutex());
       
   200         mainBundleLocStrings().set(key, value);
       
   201         return;
       
   202     }
       
   203 
       
   204     MutexLocker lock(frameworkLocStringsMutex());
       
   205     frameworkLocStrings().set(key, value);
       
   206 }
       
   207 
       
   208 static const LocalizedString& localizedString(WebLocalizableStringsBundle* stringsBundle, const String& key)
       
   209 {
       
   210     LocalizedString* string = findCachedString(stringsBundle, key);
       
   211     if (string)
       
   212         return *string;
       
   213 
       
   214     string = new LocalizedString(copyLocalizedStringFromBundle(stringsBundle, key));
       
   215     cacheString(stringsBundle, key, string);
       
   216 
       
   217     return *string;
       
   218 }
       
   219 
       
   220 CFStringRef WebLocalizedStringUTF8(WebLocalizableStringsBundle* stringsBundle, LPCSTR key)
       
   221 {
       
   222     if (!key)
       
   223         return 0;
       
   224 
       
   225     return localizedString(stringsBundle, String::fromUTF8(key));
       
   226 }
       
   227 
       
   228 LPCTSTR WebLocalizedLPCTSTRUTF8(WebLocalizableStringsBundle* stringsBundle, LPCSTR key)
       
   229 {
       
   230     if (!key)
       
   231         return 0;
       
   232 
       
   233     return localizedString(stringsBundle, String::fromUTF8(key));
       
   234 }
       
   235 
       
   236 // These functions are deprecated.
       
   237 
       
   238 CFStringRef WebLocalizedString(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
       
   239 {
       
   240     if (!key)
       
   241         return 0;
       
   242 
       
   243     return localizedString(stringsBundle, String(key));
       
   244 }
       
   245 
       
   246 LPCTSTR WebLocalizedLPCTSTR(WebLocalizableStringsBundle* stringsBundle, LPCTSTR key)
       
   247 {
       
   248     if (!key)
       
   249         return 0;
       
   250 
       
   251     return localizedString(stringsBundle, String(key));
       
   252 }
       
   253 
       
   254 void SetWebLocalizedStringMainBundle(CFBundleRef)
       
   255 {
       
   256 }