summaryrefslogtreecommitdiffstats
path: root/intl/locale/windows
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/windows')
-rw-r--r--intl/locale/windows/moz.build26
-rw-r--r--intl/locale/windows/nsCollationWin.cpp146
-rw-r--r--intl/locale/windows/nsCollationWin.h35
-rw-r--r--intl/locale/windows/nsDateTimeFormatWin.cpp253
-rw-r--r--intl/locale/windows/nsDateTimeFormatWin.h71
-rw-r--r--intl/locale/windows/nsWin32Locale.cpp748
-rw-r--r--intl/locale/windows/nsWinCharset.cpp101
-rw-r--r--intl/locale/windows/wincharset.properties23
8 files changed, 1403 insertions, 0 deletions
diff --git a/intl/locale/windows/moz.build b/intl/locale/windows/moz.build
new file mode 100644
index 000000000..5bde38b89
--- /dev/null
+++ b/intl/locale/windows/moz.build
@@ -0,0 +1,26 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+ 'nsCollationWin.cpp',
+ 'nsDateTimeFormatWin.cpp',
+ 'nsWin32Locale.cpp',
+ 'nsWinCharset.cpp',
+]
+
+FINAL_LIBRARY = 'xul'
+
+GENERATED_FILES = [
+ 'wincharset.properties.h',
+]
+wincharset = GENERATED_FILES['wincharset.properties.h']
+wincharset.script = '../props2arrays.py'
+wincharset.inputs = ['wincharset.properties']
+
+LOCAL_INCLUDES += [
+ '..',
+]
+
diff --git a/intl/locale/windows/nsCollationWin.cpp b/intl/locale/windows/nsCollationWin.cpp
new file mode 100644
index 000000000..8dcdb8f07
--- /dev/null
+++ b/intl/locale/windows/nsCollationWin.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+#include "nsCollationWin.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsILocaleService.h"
+#include "nsIPlatformCharset.h"
+#include "nsWin32Locale.h"
+#include "nsCOMPtr.h"
+#include "prmem.h"
+#include "plstr.h"
+#include <windows.h>
+
+#undef CompareString
+
+NS_IMPL_ISUPPORTS(nsCollationWin, nsICollation)
+
+
+nsCollationWin::nsCollationWin() : mCollation(nullptr)
+{
+}
+
+nsCollationWin::~nsCollationWin()
+{
+ if (mCollation)
+ delete mCollation;
+}
+
+nsresult nsCollationWin::Initialize(nsILocale* locale)
+{
+ NS_ASSERTION(!mCollation, "Should only be initialized once.");
+
+ nsresult res;
+
+ mCollation = new nsCollation;
+
+ // default LCID (en-US)
+ mLCID = 1033;
+
+ nsAutoString localeStr;
+
+ // get locale string, use app default if no locale specified
+ if (!locale) {
+ nsCOMPtr<nsILocaleService> localeService =
+ do_GetService(NS_LOCALESERVICE_CONTRACTID);
+ if (localeService) {
+ nsCOMPtr<nsILocale> appLocale;
+ res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
+ if (NS_SUCCEEDED(res)) {
+ res = appLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"),
+ localeStr);
+ }
+ }
+ }
+ else {
+ res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"),
+ localeStr);
+ }
+
+ // Get LCID and charset name from locale, if available
+ LCID lcid;
+ res = nsWin32Locale::GetPlatformLocale(localeStr, &lcid);
+ if (NS_SUCCEEDED(res)) {
+ mLCID = lcid;
+ }
+
+ nsCOMPtr <nsIPlatformCharset> platformCharset =
+ do_GetService(NS_PLATFORMCHARSET_CONTRACTID);
+ if (platformCharset) {
+ nsAutoCString mappedCharset;
+ res = platformCharset->GetDefaultCharsetForLocale(localeStr, mappedCharset);
+ if (NS_SUCCEEDED(res)) {
+ mCollation->SetCharset(mappedCharset.get());
+ }
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsCollationWin::CompareString(int32_t strength,
+ const nsAString & string1,
+ const nsAString & string2,
+ int32_t *result)
+{
+ int retval;
+ nsresult res;
+ DWORD dwMapFlags = 0;
+
+ if (strength == kCollationCaseInSensitive)
+ dwMapFlags |= NORM_IGNORECASE;
+
+ retval = ::CompareStringW(mLCID,
+ dwMapFlags,
+ (LPCWSTR) PromiseFlatString(string1).get(),
+ -1,
+ (LPCWSTR) PromiseFlatString(string2).get(),
+ -1);
+ if (retval) {
+ res = NS_OK;
+ *result = retval - 2;
+ } else {
+ res = NS_ERROR_FAILURE;
+ }
+
+ return res;
+}
+
+
+nsresult nsCollationWin::AllocateRawSortKey(int32_t strength,
+ const nsAString& stringIn, uint8_t** key, uint32_t* outLen)
+{
+ int byteLen;
+ void *buffer;
+ nsresult res = NS_OK;
+ DWORD dwMapFlags = LCMAP_SORTKEY;
+
+ if (strength == kCollationCaseInSensitive)
+ dwMapFlags |= NORM_IGNORECASE;
+
+ byteLen = LCMapStringW(mLCID, dwMapFlags,
+ (LPCWSTR) PromiseFlatString(stringIn).get(),
+ -1, nullptr, 0);
+ buffer = PR_Malloc(byteLen);
+ if (!buffer) {
+ res = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ *key = (uint8_t *)buffer;
+ *outLen = LCMapStringW(mLCID, dwMapFlags,
+ (LPCWSTR) PromiseFlatString(stringIn).get(),
+ -1, (LPWSTR) buffer, byteLen);
+ }
+ return res;
+}
+
+nsresult nsCollationWin::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
+ const uint8_t* key2, uint32_t len2,
+ int32_t* result)
+{
+ *result = PL_strcmp((const char *)key1, (const char *)key2);
+ return NS_OK;
+}
diff --git a/intl/locale/windows/nsCollationWin.h b/intl/locale/windows/nsCollationWin.h
new file mode 100644
index 000000000..901211344
--- /dev/null
+++ b/intl/locale/windows/nsCollationWin.h
@@ -0,0 +1,35 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsCollationWin_h__
+#define nsCollationWin_h__
+
+
+#include "nsICollation.h"
+#include "nsCollation.h" // static library
+#include "plstr.h"
+
+
+
+class nsCollationWin final : public nsICollation {
+ ~nsCollationWin();
+
+protected:
+ nsCollation *mCollation; // XP collation class
+ uint32_t mLCID; // Windows platform locale ID
+
+public:
+ nsCollationWin();
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsICollation interface
+ NS_DECL_NSICOLLATION
+
+};
+
+#endif /* nsCollationWin_h__ */
diff --git a/intl/locale/windows/nsDateTimeFormatWin.cpp b/intl/locale/windows/nsDateTimeFormatWin.cpp
new file mode 100644
index 000000000..f65868e1b
--- /dev/null
+++ b/intl/locale/windows/nsDateTimeFormatWin.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDateTimeFormatWin.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsILocaleService.h"
+#include "nsWin32Locale.h"
+#include "nsUnicharUtils.h"
+#include "nsCRT.h"
+#include "nsCOMPtr.h"
+
+
+#define NSDATETIMEFORMAT_BUFFER_LEN 80
+
+NS_IMPL_ISUPPORTS(nsDateTimeFormatWin, nsIDateTimeFormat)
+
+
+// init this interface to a specified locale
+nsresult nsDateTimeFormatWin::Initialize(nsILocale* locale)
+{
+ nsAutoString localeStr;
+ nsresult res = NS_OK;
+
+ // use cached info if match with stored locale
+ if (!locale) {
+ if (!mLocale.IsEmpty() &&
+ mLocale.Equals(mAppLocale, nsCaseInsensitiveStringComparator())) {
+ return NS_OK;
+ }
+ }
+ else {
+ res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), localeStr);
+ if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
+ if (!mLocale.IsEmpty() &&
+ mLocale.Equals(localeStr, nsCaseInsensitiveStringComparator())) {
+ return NS_OK;
+ }
+ }
+ }
+
+ // default LCID (en-US)
+ mLCID = 1033;
+
+ // get locale string, use app default if no locale specified
+ if (!locale) {
+ nsCOMPtr<nsILocaleService> localeService =
+ do_GetService(NS_LOCALESERVICE_CONTRACTID);
+ if (localeService) {
+ nsCOMPtr<nsILocale> appLocale;
+ res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
+ if (NS_SUCCEEDED(res)) {
+ res = appLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"),
+ localeStr);
+ if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
+ mAppLocale.Assign(localeStr); // cache app locale name
+ }
+ }
+ }
+ }
+ else {
+ res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_TIME"), localeStr);
+ }
+
+ // Get LCID and charset name from locale, if available
+ if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
+ mLocale.Assign(localeStr); // cache locale name
+ res = nsWin32Locale::GetPlatformLocale(mLocale, (LCID *) &mLCID);
+ }
+
+ return res;
+}
+
+// performs a locale sensitive date formatting operation on the time_t parameter
+nsresult nsDateTimeFormatWin::FormatTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const time_t timetTime,
+ nsAString& stringOut)
+{
+ return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, localtime( &timetTime ), stringOut);
+}
+
+// performs a locale sensitive date formatting operation on the struct tm parameter
+nsresult nsDateTimeFormatWin::FormatTMTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const struct tm* tmTime,
+ nsAString& stringOut)
+{
+ SYSTEMTIME system_time;
+ DWORD dwFlags_Date = 0, dwFlags_Time = 0;
+ int dateLen, timeLen;
+ char16_t dateBuffer[NSDATETIMEFORMAT_BUFFER_LEN], timeBuffer[NSDATETIMEFORMAT_BUFFER_LEN];
+
+ // set up locale data
+ (void) Initialize(locale);
+
+ // Map tm to SYSTEMTIME
+ system_time.wYear = 1900 + tmTime->tm_year;
+ system_time.wMonth = tmTime->tm_mon + 1;
+ system_time.wDayOfWeek = tmTime->tm_wday;
+ system_time.wDay = tmTime->tm_mday;
+ system_time.wHour = tmTime->tm_hour;
+ system_time.wMinute = tmTime->tm_min;
+ system_time.wSecond = tmTime->tm_sec;
+ system_time.wMilliseconds = 0;
+
+ // Map to WinAPI date format
+ switch (dateFormatSelector) {
+ case kDateFormatLong:
+ dwFlags_Date = DATE_LONGDATE;
+ break;
+ case kDateFormatShort:
+ dwFlags_Date = DATE_SHORTDATE;
+ break;
+ case kDateFormatWeekday:
+ dwFlags_Date = 0;
+ break;
+ case kDateFormatYearMonth:
+ dwFlags_Date = 0; // TODO:only availabe NT5
+ break;
+ }
+
+ // Map to WinAPI time format
+ switch (timeFormatSelector) {
+ case kTimeFormatSeconds:
+ dwFlags_Time = 0;
+ break;
+ case kTimeFormatNoSeconds:
+ dwFlags_Time = TIME_NOSECONDS;
+ break;
+ case kTimeFormatSecondsForce24Hour:
+ dwFlags_Time = TIME_FORCE24HOURFORMAT;
+ break;
+ case kTimeFormatNoSecondsForce24Hour:
+ dwFlags_Time = TIME_NOSECONDS + TIME_FORCE24HOURFORMAT;
+ break;
+ }
+
+ // Call GetDateFormatW
+ if (dateFormatSelector == kDateFormatNone) {
+ dateLen = 0;
+ }
+ else {
+ if (dateFormatSelector == kDateFormatYearMonth) {
+ dateLen = nsGetDateFormatW(0, &system_time, "yyyy/MM",
+ dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
+ }
+ else if (dateFormatSelector == kDateFormatWeekday) {
+ dateLen = nsGetDateFormatW(0, &system_time, "ddd",
+ dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
+ }
+ else {
+ dateLen = nsGetDateFormatW(dwFlags_Date, &system_time, nullptr,
+ dateBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
+ }
+ if (dateLen != 0) {
+ dateLen--; // Since the count includes the terminating null.
+ }
+ }
+
+ // Call GetTimeFormatW
+ if (timeFormatSelector == kTimeFormatNone) {
+ timeLen = 0;
+ }
+ else {
+ timeLen = nsGetTimeFormatW(dwFlags_Time, &system_time, nullptr,
+ timeBuffer, NSDATETIMEFORMAT_BUFFER_LEN);
+ if (timeLen != 0) {
+ timeLen--; // Since the count includes the terminating null.
+ }
+ }
+
+ NS_ASSERTION(NSDATETIMEFORMAT_BUFFER_LEN >= (uint32_t) (dateLen + 1), "internal date buffer is not large enough");
+ NS_ASSERTION(NSDATETIMEFORMAT_BUFFER_LEN >= (uint32_t) (timeLen + 1), "internal time buffer is not large enough");
+
+ // Copy the result
+ stringOut.Truncate();
+ if (dateLen != 0 && timeLen != 0) {
+ stringOut.Assign(dateBuffer, dateLen);
+ stringOut.Append((char16_t *)(L" "), 1);
+ stringOut.Append(timeBuffer, timeLen);
+ }
+ else if (dateLen != 0 && timeLen == 0) {
+ stringOut.Assign(dateBuffer, dateLen);
+ }
+ else if (dateLen == 0 && timeLen != 0) {
+ stringOut.Assign(timeBuffer, timeLen);
+ }
+
+ return NS_OK;
+}
+
+// performs a locale sensitive date formatting operation on the PRTime parameter
+nsresult nsDateTimeFormatWin::FormatPRTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRTime prTime,
+ nsAString& stringOut)
+{
+ PRExplodedTime explodedTime;
+ PR_ExplodeTime(prTime, PR_LocalTimeParameters, &explodedTime);
+
+ return FormatPRExplodedTime(locale, dateFormatSelector, timeFormatSelector, &explodedTime, stringOut);
+}
+
+// performs a locale sensitive date formatting operation on the PRExplodedTime parameter
+nsresult nsDateTimeFormatWin::FormatPRExplodedTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRExplodedTime* explodedTime,
+ nsAString& stringOut)
+{
+ struct tm tmTime;
+ memset( &tmTime, 0, sizeof(tmTime) );
+
+ tmTime.tm_yday = explodedTime->tm_yday;
+ tmTime.tm_wday = explodedTime->tm_wday;
+ tmTime.tm_year = explodedTime->tm_year;
+ tmTime.tm_year -= 1900;
+ tmTime.tm_mon = explodedTime->tm_month;
+ tmTime.tm_mday = explodedTime->tm_mday;
+ tmTime.tm_hour = explodedTime->tm_hour;
+ tmTime.tm_min = explodedTime->tm_min;
+ tmTime.tm_sec = explodedTime->tm_sec;
+
+ return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, &tmTime, stringOut);
+}
+
+int nsDateTimeFormatWin::nsGetTimeFormatW(DWORD dwFlags, const SYSTEMTIME *lpTime,
+ const char* format, char16_t *timeStr, int cchTime)
+{
+ int len = 0;
+ len = GetTimeFormatW(mLCID, dwFlags, lpTime,
+ format ?
+ NS_ConvertASCIItoUTF16(format).get() :
+ nullptr,
+ (LPWSTR) timeStr, cchTime);
+ return len;
+}
+
+int nsDateTimeFormatWin::nsGetDateFormatW(DWORD dwFlags, const SYSTEMTIME *lpDate,
+ const char* format, char16_t *dateStr, int cchDate)
+{
+ int len = 0;
+ len = GetDateFormatW(mLCID, dwFlags, lpDate,
+ format ? NS_ConvertASCIItoUTF16(format).get() : nullptr,
+ (LPWSTR) dateStr, cchDate);
+ return len;
+}
diff --git a/intl/locale/windows/nsDateTimeFormatWin.h b/intl/locale/windows/nsDateTimeFormatWin.h
new file mode 100644
index 000000000..1c84492ee
--- /dev/null
+++ b/intl/locale/windows/nsDateTimeFormatWin.h
@@ -0,0 +1,71 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsDateTimeFormatWin_h__
+#define nsDateTimeFormatWin_h__
+
+
+#include "nsIDateTimeFormat.h"
+#include <windows.h>
+
+
+// Locale sensitive date and time format interface
+//
+class nsDateTimeFormatWin : public nsIDateTimeFormat {
+ virtual ~nsDateTimeFormatWin() {}
+
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ // performs a locale sensitive date formatting operation on the time_t parameter
+ NS_IMETHOD FormatTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const time_t timetTime,
+ nsAString& stringOut);
+
+ // performs a locale sensitive date formatting operation on the struct tm parameter
+ NS_IMETHOD FormatTMTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const struct tm* tmTime,
+ nsAString& stringOut);
+
+ // performs a locale sensitive date formatting operation on the PRTime parameter
+ NS_IMETHOD FormatPRTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRTime prTime,
+ nsAString& stringOut);
+
+ // performs a locale sensitive date formatting operation on the PRExplodedTime parameter
+ NS_IMETHOD FormatPRExplodedTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRExplodedTime* explodedTime,
+ nsAString& stringOut);
+
+ nsDateTimeFormatWin() {mLocale.SetLength(0);mAppLocale.SetLength(0);}
+
+
+private:
+ // init this interface to a specified locale
+ NS_IMETHOD Initialize(nsILocale* locale);
+
+ // call GetTimeFormatW or TimeFormatA
+ int nsGetTimeFormatW(DWORD dwFlags, const SYSTEMTIME *lpTime,
+ const char* format, char16_t *timeStr, int cchTime);
+
+ // call GetDateFormatW or GetDateFormatA
+ int nsGetDateFormatW(DWORD dwFlags, const SYSTEMTIME *lpDate,
+ const char* format, char16_t *dateStr, int cchDate);
+
+ nsString mLocale;
+ nsString mAppLocale;
+ uint32_t mLCID; // Windows platform locale ID
+};
+
+#endif /* nsDateTimeFormatWin_h__ */
diff --git a/intl/locale/windows/nsWin32Locale.cpp b/intl/locale/windows/nsWin32Locale.cpp
new file mode 100644
index 000000000..8a66d2c64
--- /dev/null
+++ b/intl/locale/windows/nsWin32Locale.cpp
@@ -0,0 +1,748 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ArrayUtils.h"
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsXPCOMStrings.h"
+#include "nsReadableUtils.h"
+#include "nsWin32Locale.h"
+#include "prprf.h"
+#include <windows.h>
+#include "nsCRT.h"
+
+using namespace mozilla;
+
+struct iso_pair
+{
+ const char* iso_code;
+ DWORD win_code;
+};
+
+struct iso_map
+{
+ const char* iso_code;
+ DWORD win_code;
+ iso_pair sublang_list[20];
+};
+
+nsWin32Locale::LocaleNameToLCIDPtr nsWin32Locale::localeNameToLCID = nullptr;
+nsWin32Locale::LCIDToLocaleNamePtr nsWin32Locale::lcidToLocaleName = nullptr;
+
+// Older versions of VC++ and Win32 SDK and mingw don't have
+// macros for languages and sublanguages recently added to Win32.
+// see http://www.tug.org/ftp/tex/texinfo/intl/localename.c
+
+#ifndef LANG_URDU
+#define LANG_URDU 0x20
+#endif
+#ifndef LANG_ARMENIAN
+#define LANG_ARMENIAN 0x2b
+#endif
+#ifndef LANG_AZERI
+#define LANG_AZERI 0x2c
+#endif
+#ifndef LANG_MACEDONIAN
+#define LANG_MACEDONIAN 0x2f
+#endif
+#ifndef LANG_GEORGIAN
+#define LANG_GEORGIAN 0x37
+#endif
+#ifndef LANG_HINDI
+#define LANG_HINDI 0x39
+#endif
+#ifndef LANG_MALAY
+#define LANG_MALAY 0x3e
+#endif
+#ifndef LANG_KAZAK
+#define LANG_KAZAK 0x3f
+#endif
+#ifndef LANG_KYRGYZ
+#define LANG_KYRGYZ 0x40
+#endif
+#ifndef LANG_SWAHILI
+#define LANG_SWAHILI 0x41
+#endif
+#ifndef LANG_UZBEK
+#define LANG_UZBEK 0x43
+#endif
+#ifndef LANG_TATAR
+#define LANG_TATAR 0x44
+#endif
+#ifndef LANG_PUNJABI
+#define LANG_PUNJABI 0x46
+#endif
+#ifndef LANG_GUJARAT
+#define LANG_GUJARAT 0x47
+#endif
+#ifndef LANG_TAMIL
+#define LANG_TAMIL 0x49
+#endif
+#ifndef LANG_TELUGU
+#define LANG_TELUGU 0x4a
+#endif
+#ifndef LANG_KANNADA
+#define LANG_KANNADA 0x4b
+#endif
+#ifndef LANG_MARATHI
+#define LANG_MARATHI 0x4e
+#endif
+#ifndef LANG_SANSKRIT
+#define LANG_SANSKRIT 0x4f
+#endif
+#ifndef LANG_MONGOLIAN
+#define LANG_MONGOLIAN 0x50
+#endif
+#ifndef LANG_GALICIAN
+#define LANG_GALICIAN 0x56
+#endif
+#ifndef LANG_KONKANI
+#define LANG_KONKANI 0x57
+#endif
+#ifndef LANG_DIVEHI
+#define LANG_DIVEHI 0x65
+#endif
+
+#ifndef SUBLANG_MALAY_MALAYSIA
+#define SUBLANG_MALAY_MALAYSIA 0x01
+#endif
+#ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
+#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
+#endif
+#ifndef SUBLANG_CHINESE_MACAU
+#define SUBLANG_CHINESE_MACAU 0x05
+#endif
+#ifndef SUBLANG_FRENCH_MONACO
+#define SUBLANG_FRENCH_MONACO 0x06
+#endif
+#ifndef SUBLANG_ENGLISH_ZIMBABWE
+#define SUBLANG_ENGLISH_ZIMBABWE 0x0c
+#endif
+#ifndef SUBLANG_ENGLISH_PHILIPPINES
+#define SUBLANG_ENGLISH_PHILIPPINES 0x0d
+#endif
+
+
+//
+// This list is used to map between ISO language
+// References :
+// http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html
+// http://www.loc.gov/standards/iso639-2/
+// http://www.ethnologue.com/
+// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_19ir.asp
+// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_61df.asp
+
+static const
+iso_map iso_list[] =
+{
+ {"af", LANG_AFRIKAANS, {
+ { "ZA", SUBLANG_DEFAULT },
+ { "",0}}
+ },
+ { "ar", LANG_ARABIC, {
+ { "SA", SUBLANG_ARABIC_SAUDI_ARABIA },
+ { "IQ", SUBLANG_ARABIC_IRAQ },
+ { "EG", SUBLANG_ARABIC_EGYPT },
+ { "LY", SUBLANG_ARABIC_LIBYA },
+ { "DZ", SUBLANG_ARABIC_ALGERIA },
+ { "MA", SUBLANG_ARABIC_MOROCCO },
+ { "TN", SUBLANG_ARABIC_TUNISIA },
+ { "OM", SUBLANG_ARABIC_OMAN },
+ { "YE", SUBLANG_ARABIC_YEMEN },
+ { "SY", SUBLANG_ARABIC_SYRIA },
+ { "JO", SUBLANG_ARABIC_JORDAN },
+ { "LB", SUBLANG_ARABIC_LEBANON },
+ { "KW", SUBLANG_ARABIC_KUWAIT },
+ { "AE", SUBLANG_ARABIC_UAE },
+ { "BH", SUBLANG_ARABIC_BAHRAIN },
+ { "QA", SUBLANG_ARABIC_QATAR },
+ {"",0}}
+ },
+ {"az", LANG_AZERI, {
+ { "AZ",SUBLANG_DEFAULT }, // XXX Latin vs Cyrillic vs Arabic
+ { "",0}}
+ },
+ {"be", LANG_BELARUSIAN, {
+ { "BY",SUBLANG_DEFAULT },
+ { "",0}}
+ },
+ {"bg", LANG_BULGARIAN, {
+ { "BG", SUBLANG_DEFAULT },
+ { "",0}}
+ },
+ {"ca", LANG_CATALAN, {
+ { "ES", SUBLANG_DEFAULT},
+ { "",0}}
+ },
+ {"cs", LANG_CZECH, {
+ { "CZ", SUBLANG_DEFAULT},
+ {"",0}}
+ },
+ { "da", LANG_DANISH, {
+ { "DK", SUBLANG_DEFAULT },
+ { "",0}}
+ },
+ { "de", LANG_GERMAN, {
+ { "DE", SUBLANG_GERMAN },
+ { "CH", SUBLANG_GERMAN_SWISS },
+ { "AT", SUBLANG_GERMAN_AUSTRIAN },
+ { "LU", SUBLANG_GERMAN_LUXEMBOURG },
+ { "LI", SUBLANG_GERMAN_LIECHTENSTEIN },
+ { "" , 0}}
+ },
+ {"dv", LANG_DIVEHI, {
+ { "MV", SUBLANG_DEFAULT},
+ { "", 0}}
+ },
+ {"el", LANG_GREEK, {
+ { "GR", SUBLANG_DEFAULT},
+ { "", 0}}
+ },
+ { "en", LANG_ENGLISH, {
+ { "US", SUBLANG_ENGLISH_US },
+ { "GB", SUBLANG_ENGLISH_UK },
+ { "AU", SUBLANG_ENGLISH_AUS },
+ { "CA", SUBLANG_ENGLISH_CAN },
+ { "NZ", SUBLANG_ENGLISH_NZ },
+ { "IE", SUBLANG_ENGLISH_EIRE },
+ { "ZA", SUBLANG_ENGLISH_SOUTH_AFRICA },
+ { "JM", SUBLANG_ENGLISH_JAMAICA },
+ { "BZ", SUBLANG_ENGLISH_BELIZE },
+ { "TT", SUBLANG_ENGLISH_TRINIDAD },
+ { "ZW", SUBLANG_ENGLISH_ZIMBABWE },
+ { "PH", SUBLANG_ENGLISH_PHILIPPINES },
+ { "",0}}
+ },
+ { "es", LANG_SPANISH, { // XXX : SUBLANG_SPANISH_MODERN
+ { "ES", SUBLANG_SPANISH },
+ { "MX", SUBLANG_SPANISH_MEXICAN },
+ { "GT", SUBLANG_SPANISH_GUATEMALA },
+ { "CR", SUBLANG_SPANISH_COSTA_RICA },
+ { "PA", SUBLANG_SPANISH_PANAMA },
+ { "DO", SUBLANG_SPANISH_DOMINICAN_REPUBLIC },
+ { "VE", SUBLANG_SPANISH_VENEZUELA },
+ { "CO", SUBLANG_SPANISH_COLOMBIA },
+ { "PE", SUBLANG_SPANISH_PERU },
+ { "AR", SUBLANG_SPANISH_ARGENTINA },
+ { "EC", SUBLANG_SPANISH_ECUADOR },
+ { "CL", SUBLANG_SPANISH_CHILE },
+ { "UY", SUBLANG_SPANISH_URUGUAY },
+ { "PY", SUBLANG_SPANISH_PARAGUAY },
+ { "BO", SUBLANG_SPANISH_BOLIVIA },
+ { "SV", SUBLANG_SPANISH_EL_SALVADOR },
+ { "HN", SUBLANG_SPANISH_HONDURAS },
+ { "NI", SUBLANG_SPANISH_NICARAGUA },
+ { "PR", SUBLANG_SPANISH_PUERTO_RICO },
+ { "", 0 }}
+ },
+ {"et", LANG_ESTONIAN, {
+ { "EE", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"eu", LANG_BASQUE, {
+ { "ES" , SUBLANG_DEFAULT },
+ { "" , 0 }}
+ },
+ {"fa", LANG_FARSI, {
+ { "IR", SUBLANG_DEFAULT},
+ { "", 0}}
+ },
+ {"fi", LANG_FINNISH, {
+ { "FI", SUBLANG_DEFAULT },
+ { "",0}}
+ },
+ {"fo", LANG_FAEROESE, {
+ { "FO", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "fr", LANG_FRENCH, {
+ { "FR", SUBLANG_FRENCH },
+ { "BE", SUBLANG_FRENCH_BELGIAN },
+ { "CA", SUBLANG_FRENCH_CANADIAN },
+ { "CH", SUBLANG_FRENCH_SWISS },
+ { "LU", SUBLANG_FRENCH_LUXEMBOURG },
+ { "MC", SUBLANG_FRENCH_MONACO },
+ {"",0}}
+ },
+ { "gl", LANG_GALICIAN, {
+ { "ES", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "gu", LANG_GUJARATI, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"he", LANG_HEBREW, {
+ { "IL", SUBLANG_DEFAULT},
+ { "", 0}}
+ },
+ {"hi", LANG_HINDI, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ /* Duplicate the SUBLANG codes for Croatian and Serbian, because the Windows
+ LANG code is the same for both */
+ {"hr", LANG_CROATIAN, {
+ { "CS", SUBLANG_SERBIAN_LATIN },
+ { "SP", SUBLANG_SERBIAN_CYRILLIC },
+ { "HR", SUBLANG_DEFAULT},
+ { "" ,0 }}
+ },
+ {"hu", LANG_HUNGARIAN, {
+ { "HU", SUBLANG_DEFAULT },
+ { "" , 0 }}
+ },
+ {"hy", LANG_ARMENIAN, {
+ { "AM", SUBLANG_DEFAULT},
+ { "" ,0 }}
+ },
+ {"id", LANG_INDONESIAN, {
+ { "ID", SUBLANG_DEFAULT },
+ {"", 0}}
+ },
+ {"is", LANG_ICELANDIC, {
+ { "IS", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "it", LANG_ITALIAN, {
+ { "IT", SUBLANG_ITALIAN },
+ { "CH", SUBLANG_ITALIAN_SWISS },
+ { "", 0}}
+ },
+ {"iw", LANG_HEBREW, {
+ { "IL", SUBLANG_DEFAULT},
+ { "", 0}}
+ },
+ {"ja", LANG_JAPANESE, {
+ { "JP", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "ka", LANG_GEORGIAN, {
+ { "GE", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "kk", LANG_KAZAK, {
+ { "KZ", SUBLANG_DEFAULT }, // KAZAKHSTAN
+ { "", 0}}
+ },
+ { "kn", LANG_KANNADA, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "ko", LANG_KOREAN, {
+ { "KR", SUBLANG_KOREAN },
+ { "", 0}}
+ },
+ { "kok", LANG_KONKANI, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "ky", LANG_KYRGYZ, {
+ { "KG", SUBLANG_DEFAULT }, // Kygyzstan
+ { "", 0}}
+ },
+ {"lt", LANG_LITHUANIAN, {
+ { "LT", SUBLANG_DEFAULT },
+ { "" ,0 }}
+ },
+ {"lv", LANG_LATVIAN, {
+ { "LV", SUBLANG_DEFAULT},
+ { "", 0}}
+ },
+ {"mk", LANG_MACEDONIAN, {
+ { "MK", SUBLANG_DEFAULT },
+ { "", 0 }}
+ },
+ { "mn", LANG_MONGOLIAN, {
+ { "MN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "mr", LANG_MARATHI, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"ms", LANG_MALAY, {
+ { "MY", SUBLANG_MALAY_MALAYSIA },
+ { "BN", SUBLANG_MALAY_BRUNEI_DARUSSALAM }, // XXX
+ { "", 0}}
+ },
+ {"nb", LANG_NORWEGIAN, {
+ { "NO", SUBLANG_NORWEGIAN_BOKMAL },
+ { "", SUBLANG_NORWEGIAN_BOKMAL}}
+ },
+ {"nl", LANG_DUTCH, {
+ {"NL", SUBLANG_DUTCH },
+ {"BE", SUBLANG_DUTCH_BELGIAN },
+ { "", 0}}
+ },
+ {"nn", LANG_NORWEGIAN, {
+ { "NO", SUBLANG_NORWEGIAN_NYNORSK },
+ { "", SUBLANG_NORWEGIAN_NYNORSK}}
+ },
+ {"no", LANG_NORWEGIAN, {
+ { "NO", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "pa", LANG_PUNJABI, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"pl", LANG_POLISH, {
+ { "PL", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "pt", LANG_PORTUGUESE, {
+ { "PT", SUBLANG_PORTUGUESE },
+ { "BR", SUBLANG_PORTUGUESE_BRAZILIAN },
+ {"",0}}
+ },
+ {"ro", LANG_ROMANIAN, {
+ { "RO", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"ru", LANG_RUSSIAN, {
+ { "RU", SUBLANG_DEFAULT },
+ { "", 0 }}
+ },
+ { "sa", LANG_SANSKRIT, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"sk", LANG_SLOVAK, {
+ { "SK", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"sl", LANG_SLOVENIAN, {
+ { "SI", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"sq", LANG_ALBANIAN, {
+ { "AL", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ /* Duplicate the SUBLANG codes for Croatian and Serbian, because the Windows
+ LANG code is the same for both */
+ {"sr", LANG_SERBIAN, {
+ { "CS", SUBLANG_SERBIAN_LATIN },
+ { "SP", SUBLANG_SERBIAN_CYRILLIC },
+ { "HR", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "sv", LANG_SWEDISH, {
+ { "SE", SUBLANG_SWEDISH },
+ { "FI", SUBLANG_SWEDISH_FINLAND },
+ { "", 0 }}
+ },
+ {"sw", LANG_SWAHILI, {
+ { "KE", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "ta", LANG_TAMIL, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "te", LANG_TELUGU, {
+ { "IN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"th", LANG_THAI, {
+ {"TH", SUBLANG_DEFAULT},
+ {"",0}}
+ },
+ {"tr", LANG_TURKISH, {
+ { "TR", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "tt", LANG_TATAR, {
+ { "RU", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"uk", LANG_UKRAINIAN, {
+ { "UA", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"ur", LANG_URDU, {
+ { "PK", SUBLANG_URDU_PAKISTAN },
+ { "IN", SUBLANG_URDU_INDIA },
+ { "", 0}}
+ },
+ {"uz", LANG_UZBEK, { // XXX : Cyrillic, Latin
+ { "UZ", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ {"vi", LANG_VIETNAMESE, {
+ { "VN", SUBLANG_DEFAULT },
+ { "", 0}}
+ },
+ { "zh", LANG_CHINESE, {
+ { "TW", SUBLANG_CHINESE_TRADITIONAL },
+ { "CN", SUBLANG_CHINESE_SIMPLIFIED },
+ { "HK", SUBLANG_CHINESE_HONGKONG },
+ { "SG", SUBLANG_CHINESE_SINGAPORE },
+ { "MO", SUBLANG_CHINESE_MACAU },
+ { "",0}}
+ }
+};
+
+#define LENGTH_MAPPING_LIST ArrayLength(iso_list)
+
+//
+// This list maps ISO 2 digit country codes to Win32 country codes.
+// This list must be kept in alphabetic (by iso code) order and synchronized
+// with the list above. This is only used in debug builds to check the consistentcy
+// of the internal tables.
+//
+#ifdef DEBUG
+static const
+iso_pair dbg_list[] =
+{
+ {"af", LANG_AFRIKAANS},
+ {"ar", LANG_ARABIC},
+ {"az", LANG_AZERI},
+ {"be", LANG_BELARUSIAN},
+ {"bg", LANG_BULGARIAN},
+ {"ca", LANG_CATALAN},
+ {"cs", LANG_CZECH},
+ {"da", LANG_DANISH},
+ {"de", LANG_GERMAN},
+ {"dv", LANG_DIVEHI},
+ {"el", LANG_GREEK},
+ {"en", LANG_ENGLISH},
+ {"es", LANG_SPANISH},
+ {"et", LANG_ESTONIAN},
+ {"eu", LANG_BASQUE},
+ {"fa", LANG_FARSI},
+ {"fi", LANG_FINNISH},
+ {"fo", LANG_FAEROESE},
+ {"fr", LANG_FRENCH},
+ {"gl", LANG_GALICIAN},
+ {"gu", LANG_GUJARATI},
+ {"he", LANG_HEBREW},
+ {"hi", LANG_HINDI},
+ {"hr", LANG_CROATIAN},
+ {"hu", LANG_HUNGARIAN},
+ {"hy", LANG_ARMENIAN},
+ {"id", LANG_INDONESIAN},
+ {"in", LANG_INDONESIAN},
+ {"is", LANG_ICELANDIC},
+ {"it", LANG_ITALIAN},
+ {"iw", LANG_HEBREW},
+ {"ja", LANG_JAPANESE},
+ {"ka", LANG_GEORGIAN},
+ {"kn", LANG_KANNADA},
+ {"ko", LANG_KOREAN},
+ {"kok", LANG_KONKANI},
+ {"lt", LANG_LITHUANIAN},
+ {"lv", LANG_LATVIAN},
+ {"mk", LANG_MACEDONIAN},
+ {"mn", LANG_MONGOLIAN},
+ {"mr", LANG_MARATHI},
+ {"ms", LANG_MALAY},
+ {"nb", LANG_NORWEGIAN},
+ {"nl", LANG_DUTCH},
+ {"nn", LANG_NORWEGIAN},
+ {"no", LANG_NORWEGIAN},
+ {"pa", LANG_PUNJABI},
+ {"pl", LANG_POLISH},
+ {"pt", LANG_PORTUGUESE},
+ {"ro", LANG_ROMANIAN},
+ {"ru", LANG_RUSSIAN},
+ {"sa", LANG_SANSKRIT},
+ {"sk", LANG_SLOVAK},
+ {"sl", LANG_SLOVENIAN},
+ {"sq", LANG_ALBANIAN},
+ {"sr", LANG_SERBIAN},
+ {"sv", LANG_SWEDISH},
+ {"sw", LANG_SWAHILI},
+ {"ta", LANG_TAMIL},
+ {"te", LANG_TELUGU},
+ {"th", LANG_THAI},
+ {"tr", LANG_TURKISH},
+ {"tt", LANG_TATAR},
+ {"uk", LANG_UKRAINIAN},
+ {"ur", LANG_URDU},
+ {"uz", LANG_UZBEK},
+ {"vi", LANG_VIETNAMESE},
+ {"zh", LANG_CHINESE},
+ {"",0}
+};
+#endif
+
+#define CROATIAN_ISO_CODE "hr"
+#define SERBIAN_ISO_CODE "sr"
+
+void
+nsWin32Locale::initFunctionPointers(void)
+{
+ static bool sInitialized = false;
+ // We use the Vista and above functions if we have them
+ if (!sInitialized) {
+ HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
+ if (kernelDLL) {
+ localeNameToLCID = (LocaleNameToLCIDPtr) GetProcAddress(kernelDLL, "LocaleNameToLCID");
+ lcidToLocaleName = (LCIDToLocaleNamePtr) GetProcAddress(kernelDLL, "LCIDToLocaleName");
+ }
+ sInitialized = true;
+ }
+}
+
+//
+// the mapping routines are a first approximation to get us going on
+// the tier-1 languages. we are making an assumption that we can map
+// language and country codes separately on Windows, which isn't true
+//
+nsresult
+nsWin32Locale::GetPlatformLocale(const nsAString& locale, LCID* winLCID)
+{
+ initFunctionPointers ();
+
+ if (localeNameToLCID) {
+ nsAutoString locale_autostr(locale);
+ LCID lcid = localeNameToLCID(locale_autostr.get(), 0);
+ // The function returning 0 means that the locale name couldn't be matched,
+ // so we fallback to the old function
+ if (lcid != 0)
+ {
+ *winLCID = lcid;
+ return NS_OK;
+ }
+ }
+
+ char locale_string[9] = {'\0','\0','\0','\0','\0','\0','\0','\0','\0'};
+ char* language_code;
+ char* country_code;
+ size_t i, j;
+
+ // parse the locale
+ const char16_t* data;
+ j = NS_StringGetData(locale, &data);
+ for (i = 0; i < 7 && i < j; i++) {
+ locale_string[i] = data[i] == '-' ? '\0' : data[i];
+ }
+
+ language_code = locale_string;
+ country_code = locale_string + strlen(locale_string) + 1;
+
+ // convert parsed locale to Windows LCID
+ for(i=0;i<LENGTH_MAPPING_LIST;i++) {
+ if (strcmp(language_code,iso_list[i].iso_code)==0) {
+ for(j=0;iso_list[i].sublang_list[j].win_code;j++) {
+ if (strcmp(country_code,iso_list[i].sublang_list[j].iso_code)==0) {
+ *winLCID = MAKELCID(MAKELANGID(iso_list[i].win_code,iso_list[i].sublang_list[j].win_code),SORT_DEFAULT);
+ return NS_OK;
+ }
+ }
+ // here we have a language match but no country match
+ *winLCID = MAKELCID(MAKELANGID(iso_list[i].win_code,SUBLANG_DEFAULT),SORT_DEFAULT);
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+#ifndef LOCALE_NAME_MAX_LENGTH
+#define LOCALE_NAME_MAX_LENGTH 85
+#endif
+
+void
+nsWin32Locale::GetXPLocale(LCID winLCID, nsAString& locale)
+{
+ initFunctionPointers ();
+
+ if (lcidToLocaleName)
+ {
+ WCHAR ret_locale[LOCALE_NAME_MAX_LENGTH];
+ int rv = lcidToLocaleName(winLCID, ret_locale, LOCALE_NAME_MAX_LENGTH, 0);
+ // rv 0 means that the function failed to match up the LCID, so we fallback
+ // to the old function
+ if (rv != 0)
+ {
+ locale.Assign(ret_locale);
+ return;
+ }
+ }
+
+ DWORD lang_id, sublang_id;
+ size_t i, j;
+
+ lang_id = PRIMARYLANGID(LANGIDFROMLCID(winLCID));
+ sublang_id = SUBLANGID(LANGIDFROMLCID(winLCID));
+
+ /* Special-case Norwegian Bokmal and Norwegian Nynorsk, which have the same
+ LANG_ID on Windows, but have separate ISO-639-2 codes */
+ if (lang_id == LANG_NORWEGIAN) {
+ if (sublang_id == SUBLANG_NORWEGIAN_BOKMAL) {
+ locale.AssignASCII("nb-NO");
+ } else if (sublang_id == SUBLANG_NORWEGIAN_NYNORSK) {
+ locale.AssignASCII("nn-NO");
+ } else {
+ locale.AssignASCII("no-NO");
+ }
+ return;
+ }
+
+ for(i=0;i<LENGTH_MAPPING_LIST;i++) {
+ if (lang_id==iso_list[i].win_code) {
+ /* Special-case Croatian and Serbian, which have the same LANG_ID on
+ Windows, but have been split into separate ISO-639-2 codes */
+ if (lang_id == LANG_CROATIAN) {
+ if (sublang_id == SUBLANG_DEFAULT) {
+ locale.AssignLiteral(CROATIAN_ISO_CODE);
+ } else {
+ locale.AssignLiteral(SERBIAN_ISO_CODE);
+ }
+ } else {
+ locale.AssignASCII(iso_list[i].iso_code);
+ }
+ for(j=0;iso_list[i].sublang_list[j].win_code;j++) {
+ if (sublang_id == iso_list[i].sublang_list[j].win_code) {
+ locale.Append(char16_t('-'));
+ locale.AppendASCII(iso_list[i].sublang_list[j].iso_code);
+ break;
+ }
+ }
+ return;
+ }
+ }
+
+ //
+ // didn't find any match. fall back to en-US, which is better
+ // than unusable buttons without 'OK', 'Cancel', etc (bug 224546)
+ //
+ locale.AssignLiteral("en-US");
+ return;
+}
+
+#ifdef DEBUG
+void
+test_internal_tables(void)
+{
+ size_t i;
+
+ for(i=1;i<LENGTH_MAPPING_LIST;i++) {
+ if (strcmp(dbg_list[i-1].iso_code,dbg_list[i].iso_code)>=0)
+ fprintf(stderr,"nsLocale: language_list %s and %s are not ordered\n",dbg_list[i-1].iso_code,dbg_list[i].iso_code);
+ }
+
+ i=0;
+ while(strlen(dbg_list[i].iso_code)!=0) {
+ i++;
+ }
+ if (i!=LENGTH_MAPPING_LIST)
+ fprintf(stderr,"nsLocale: language_list length is %u, reported length is %u\n",
+ unsigned(i), unsigned(LENGTH_MAPPING_LIST));
+
+ for(i=0;i<LENGTH_MAPPING_LIST;i++) {
+ if (strcmp(iso_list[i].iso_code,dbg_list[i].iso_code)!=0) {
+ fprintf(stderr,"nsLocale: iso_list and dbg_list different at item: %u\n",
+ unsigned(i));
+ }
+ }
+}
+
+#endif
+
diff --git a/intl/locale/windows/nsWinCharset.cpp b/intl/locale/windows/nsWinCharset.cpp
new file mode 100644
index 000000000..c84307267
--- /dev/null
+++ b/intl/locale/windows/nsWinCharset.cpp
@@ -0,0 +1,101 @@
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ArrayUtils.h"
+
+#include "nsIPlatformCharset.h"
+#include "nsUConvPropertySearch.h"
+#include <windows.h>
+#include "nsWin32Locale.h"
+#include "nsCOMPtr.h"
+#include "nsReadableUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsPlatformCharset.h"
+#include "nsEncoderDecoderUtils.h"
+
+using namespace mozilla;
+
+static const nsUConvProp kWinCharsets[] = {
+#include "wincharset.properties.h"
+};
+
+NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
+
+nsPlatformCharset::nsPlatformCharset()
+{
+ nsAutoString acpKey(NS_LITERAL_STRING("acp."));
+ acpKey.AppendInt(int32_t(::GetACP() & 0x00FFFF), 10);
+ MapToCharset(acpKey, mCharset);
+}
+
+nsPlatformCharset::~nsPlatformCharset()
+{
+}
+
+nsresult
+nsPlatformCharset::MapToCharset(nsAString& inANSICodePage, nsACString& outCharset)
+{
+ nsAutoCString key;
+ LossyCopyUTF16toASCII(inANSICodePage, key);
+
+ nsresult rv = nsUConvPropertySearch::SearchPropertyValue(kWinCharsets,
+ ArrayLength(kWinCharsets), key, outCharset);
+ if (NS_FAILED(rv)) {
+ outCharset.AssignLiteral("windows-1252");
+ return NS_SUCCESS_USING_FALLBACK_LOCALE;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector,
+ nsACString& oResult)
+{
+ oResult = mCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString& oResult)
+{
+ LCID localeAsLCID;
+
+ //
+ // convert locale name to a code page (through the LCID)
+ //
+ nsresult rv;
+ oResult.Truncate();
+
+ rv = nsWin32Locale::GetPlatformLocale(localeName, &localeAsLCID);
+ if (NS_FAILED(rv)) { return rv; }
+
+ wchar_t acp_name[6];
+ if (GetLocaleInfoW(localeAsLCID, LOCALE_IDEFAULTANSICODEPAGE, acp_name,
+ ArrayLength(acp_name))==0) {
+ return NS_ERROR_FAILURE;
+ }
+ nsAutoString acp_key(NS_LITERAL_STRING("acp."));
+ acp_key.Append(acp_name);
+
+ return MapToCharset(acp_key, oResult);
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::Init()
+{
+ return NS_OK;
+}
+
+nsresult
+nsPlatformCharset::InitGetCharset(nsACString &oString)
+{
+ return NS_OK;
+}
+
+nsresult
+nsPlatformCharset::VerifyCharset(nsCString &aCharset)
+{
+ return NS_OK;
+}
diff --git a/intl/locale/windows/wincharset.properties b/intl/locale/windows/wincharset.properties
new file mode 100644
index 000000000..79a802492
--- /dev/null
+++ b/intl/locale/windows/wincharset.properties
@@ -0,0 +1,23 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file map a ACP to a charset name
+# We use this to figure out the charset of file system, clipboard, etc
+#
+
+acp.874=windows-874
+acp.932=Shift_JIS
+acp.936=gb18030
+acp.949=EUC-KR
+acp.950=Big5
+acp.951=Big5
+acp.1250=windows-1250
+acp.1251=windows-1251
+acp.1252=windows-1252
+acp.1253=windows-1253
+acp.1254=windows-1254
+acp.1255=windows-1255
+acp.1256=windows-1256
+acp.1257=windows-1257
+acp.1258=windows-1258