summaryrefslogtreecommitdiffstats
path: root/intl/locale/windows/nsWin32Locale.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/windows/nsWin32Locale.cpp')
-rw-r--r--intl/locale/windows/nsWin32Locale.cpp748
1 files changed, 748 insertions, 0 deletions
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
+