gecko-dev/intl/locale/windows/nsWin32Locale.cpp
Jonathan Kew 883e90e9df Bug 1256559 - To avoid VS2013 vs 2015 issues, just cast the size_t values to unsigned and print them with %u in the debug messages here; r=khuey
--HG--
extra : rebase_source : a285239f0b600164f58eaa11189c1c2c91a5bf51
extra : histedit_source : fe5ad5b950960a3e97fb5940201d525e8c342ab6
2016-03-21 12:14:13 +00:00

749 lines
18 KiB
C++

/* -*- 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