intl/locale/src/windows/nsWin32Locale.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/ArrayUtils.h"
     8 #include "nscore.h"
     9 #include "nsString.h"
    10 #include "nsXPCOMStrings.h"
    11 #include "nsReadableUtils.h"
    12 #include "nsWin32Locale.h"
    13 #include "prprf.h"
    14 #include <windows.h>
    15 #include "nsCRT.h"
    17 using namespace mozilla;
    19 struct iso_pair 
    20 {
    21 	const char*	iso_code;
    22 	DWORD       win_code;
    23 };
    25 struct iso_map
    26 {
    27 	const char* iso_code;
    28 	DWORD       win_code;
    29 	iso_pair    sublang_list[20];
    30 };
    32 nsWin32Locale::LocaleNameToLCIDPtr nsWin32Locale::localeNameToLCID = nullptr;
    33 nsWin32Locale::LCIDToLocaleNamePtr nsWin32Locale::lcidToLocaleName = nullptr;
    35 // Older versions of VC++ and Win32 SDK  and mingw don't have 
    36 // macros for languages and sublanguages recently added to Win32. 
    37 // see http://www.tug.org/ftp/tex/texinfo/intl/localename.c
    39 #ifndef LANG_URDU
    40 #define LANG_URDU                           0x20
    41 #endif
    42 #ifndef LANG_ARMENIAN
    43 #define LANG_ARMENIAN                       0x2b
    44 #endif
    45 #ifndef LANG_AZERI
    46 #define LANG_AZERI                          0x2c
    47 #endif
    48 #ifndef LANG_MACEDONIAN
    49 #define LANG_MACEDONIAN                     0x2f
    50 #endif
    51 #ifndef LANG_GEORGIAN
    52 #define LANG_GEORGIAN                       0x37
    53 #endif
    54 #ifndef LANG_HINDI
    55 #define LANG_HINDI                          0x39
    56 #endif
    57 #ifndef LANG_MALAY
    58 #define LANG_MALAY                          0x3e
    59 #endif
    60 #ifndef LANG_KAZAK
    61 #define LANG_KAZAK                          0x3f
    62 #endif
    63 #ifndef LANG_KYRGYZ
    64 #define LANG_KYRGYZ                         0x40
    65 #endif
    66 #ifndef LANG_SWAHILI
    67 #define LANG_SWAHILI                        0x41
    68 #endif
    69 #ifndef LANG_UZBEK
    70 #define LANG_UZBEK                          0x43
    71 #endif
    72 #ifndef LANG_TATAR
    73 #define LANG_TATAR                          0x44
    74 #endif
    75 #ifndef LANG_PUNJABI
    76 #define LANG_PUNJABI                        0x46
    77 #endif
    78 #ifndef LANG_GUJARAT
    79 #define LANG_GUJARAT                        0x47
    80 #endif
    81 #ifndef LANG_TAMIL
    82 #define LANG_TAMIL                          0x49
    83 #endif
    84 #ifndef LANG_TELUGU
    85 #define LANG_TELUGU                         0x4a
    86 #endif
    87 #ifndef LANG_KANNADA
    88 #define LANG_KANNADA                        0x4b
    89 #endif
    90 #ifndef LANG_MARATHI
    91 #define LANG_MARATHI                        0x4e
    92 #endif
    93 #ifndef LANG_SANSKRIT
    94 #define LANG_SANSKRIT                       0x4f
    95 #endif
    96 #ifndef LANG_MONGOLIAN
    97 #define LANG_MONGOLIAN                      0x50
    98 #endif
    99 #ifndef LANG_GALICIAN
   100 #define LANG_GALICIAN                       0x56
   101 #endif
   102 #ifndef LANG_KONKANI
   103 #define LANG_KONKANI                        0x57
   104 #endif
   105 #ifndef LANG_DIVEHI
   106 #define LANG_DIVEHI                         0x65
   107 #endif
   109 #ifndef SUBLANG_MALAY_MALAYSIA
   110 #define SUBLANG_MALAY_MALAYSIA              0x01
   111 #endif
   112 #ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
   113 #define SUBLANG_MALAY_BRUNEI_DARUSSALAM     0x02
   114 #endif
   115 #ifndef SUBLANG_CHINESE_MACAU
   116 #define SUBLANG_CHINESE_MACAU               0x05
   117 #endif
   118 #ifndef SUBLANG_FRENCH_MONACO
   119 #define SUBLANG_FRENCH_MONACO               0x06
   120 #endif
   121 #ifndef SUBLANG_ENGLISH_ZIMBABWE
   122 #define SUBLANG_ENGLISH_ZIMBABWE            0x0c
   123 #endif
   124 #ifndef SUBLANG_ENGLISH_PHILIPPINES
   125 #define SUBLANG_ENGLISH_PHILIPPINES         0x0d
   126 #endif
   129 //
   130 // This list is used to map between ISO language
   131 // References : 
   132 // http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html
   133 // http://www.loc.gov/standards/iso639-2/
   134 // http://www.ethnologue.com/
   135 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_19ir.asp
   136 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_61df.asp
   138 static const
   139 iso_map iso_list[] =
   140 {
   141 	{"af",	LANG_AFRIKAANS, {
   142 		{ "ZA", SUBLANG_DEFAULT },
   143 		{ "",0}}
   144 	},
   145 	{ "ar", LANG_ARABIC, {
   146 		{ "SA", SUBLANG_ARABIC_SAUDI_ARABIA }, 
   147 		{ "IQ", SUBLANG_ARABIC_IRAQ },  
   148 		{ "EG",	SUBLANG_ARABIC_EGYPT },	
   149 		{ "LY", SUBLANG_ARABIC_LIBYA },
   150 		{ "DZ", SUBLANG_ARABIC_ALGERIA },
   151 		{ "MA", SUBLANG_ARABIC_MOROCCO },
   152 		{ "TN", SUBLANG_ARABIC_TUNISIA },
   153 		{ "OM", SUBLANG_ARABIC_OMAN }, 
   154 		{ "YE", SUBLANG_ARABIC_YEMEN },
   155 		{ "SY", SUBLANG_ARABIC_SYRIA },
   156 		{ "JO", SUBLANG_ARABIC_JORDAN },
   157 		{ "LB", SUBLANG_ARABIC_LEBANON },
   158 		{ "KW", SUBLANG_ARABIC_KUWAIT },
   159 		{ "AE", SUBLANG_ARABIC_UAE },
   160 		{ "BH", SUBLANG_ARABIC_BAHRAIN },
   161 		{ "QA", SUBLANG_ARABIC_QATAR },
   162 		{"",0}}
   163 	},
   164 	{"az",	LANG_AZERI, {
   165 		{ "AZ",SUBLANG_DEFAULT },  // XXX Latin vs Cyrillic vs Arabic
   166 		{ "",0}}
   167 	},
   168 	{"be",	LANG_BELARUSIAN, {
   169 		{ "BY",SUBLANG_DEFAULT },
   170 		{ "",0}}
   171 	},
   172 	{"bg",	LANG_BULGARIAN, {
   173 		{ "BG", SUBLANG_DEFAULT },
   174 		{ "",0}}
   175 	},
   176 	{"ca",	LANG_CATALAN, {
   177 		{ "ES", SUBLANG_DEFAULT},
   178 		{ "",0}}
   179 	},
   180 	{"cs",	LANG_CZECH, {
   181 		{ "CZ", SUBLANG_DEFAULT},
   182 		{"",0}}
   183 	},
   184 	{ "da", LANG_DANISH, { 
   185 		{ "DK", SUBLANG_DEFAULT },
   186 		{ "",0}}
   187 	},
   188 	{ "de", LANG_GERMAN, {
   189 		{ "DE", SUBLANG_GERMAN },
   190 		{ "CH", SUBLANG_GERMAN_SWISS },
   191 		{ "AT", SUBLANG_GERMAN_AUSTRIAN },
   192 		{ "LU", SUBLANG_GERMAN_LUXEMBOURG },
   193 		{ "LI", SUBLANG_GERMAN_LIECHTENSTEIN },
   194 		{ "" , 0}}
   195 	},
   196 	{"dv",	LANG_DIVEHI, {
   197 		{ "MV", SUBLANG_DEFAULT},
   198 		{ "", 0}}
   199 	},
   200 	{"el",	LANG_GREEK, {
   201 		{ "GR", SUBLANG_DEFAULT},
   202 		{ "", 0}}
   203 	},
   204 	{ "en", LANG_ENGLISH, {
   205 		{ "US", SUBLANG_ENGLISH_US },
   206 		{ "GB", SUBLANG_ENGLISH_UK },
   207 		{ "AU", SUBLANG_ENGLISH_AUS },
   208 		{ "CA", SUBLANG_ENGLISH_CAN },
   209 		{ "NZ", SUBLANG_ENGLISH_NZ },
   210 		{ "IE", SUBLANG_ENGLISH_EIRE },
   211 		{ "ZA", SUBLANG_ENGLISH_SOUTH_AFRICA },
   212 		{ "JM", SUBLANG_ENGLISH_JAMAICA },
   213 		{ "BZ", SUBLANG_ENGLISH_BELIZE },
   214 		{ "TT", SUBLANG_ENGLISH_TRINIDAD },
   215 		{ "ZW", SUBLANG_ENGLISH_ZIMBABWE },
   216 		{ "PH", SUBLANG_ENGLISH_PHILIPPINES },
   217 		{ "",0}}
   218 	},
   219 	{ "es", LANG_SPANISH, {  // XXX : SUBLANG_SPANISH_MODERN
   220 		{ "ES", SUBLANG_SPANISH },
   221 		{ "MX", SUBLANG_SPANISH_MEXICAN },
   222 		{ "GT", SUBLANG_SPANISH_GUATEMALA },
   223 		{ "CR", SUBLANG_SPANISH_COSTA_RICA },
   224 		{ "PA", SUBLANG_SPANISH_PANAMA },
   225 		{ "DO", SUBLANG_SPANISH_DOMINICAN_REPUBLIC },
   226 		{ "VE", SUBLANG_SPANISH_VENEZUELA },
   227 		{ "CO", SUBLANG_SPANISH_COLOMBIA },
   228 		{ "PE", SUBLANG_SPANISH_PERU },
   229 		{ "AR", SUBLANG_SPANISH_ARGENTINA },
   230 		{ "EC", SUBLANG_SPANISH_ECUADOR },
   231 		{ "CL", SUBLANG_SPANISH_CHILE },
   232 		{ "UY", SUBLANG_SPANISH_URUGUAY },
   233 		{ "PY", SUBLANG_SPANISH_PARAGUAY },
   234 		{ "BO", SUBLANG_SPANISH_BOLIVIA },
   235 		{ "SV", SUBLANG_SPANISH_EL_SALVADOR },
   236 		{ "HN", SUBLANG_SPANISH_HONDURAS },
   237 		{ "NI", SUBLANG_SPANISH_NICARAGUA },
   238 	    { "PR", SUBLANG_SPANISH_PUERTO_RICO },
   239 		{ "", 0 }}
   240 	},
   241 	{"et",	LANG_ESTONIAN, {
   242 		{ "EE", SUBLANG_DEFAULT },
   243 		{ "", 0}}
   244 	},
   245 	{"eu",	LANG_BASQUE, {
   246 		{ "ES" , SUBLANG_DEFAULT },
   247 		{ "" , 0 }}
   248 	},
   249 	{"fa",	LANG_FARSI, {
   250 		{ "IR", SUBLANG_DEFAULT},
   251 		{ "", 0}}
   252 	},
   253 	{"fi",	LANG_FINNISH, {
   254 		{ "FI", SUBLANG_DEFAULT },
   255 		{ "",0}}
   256 	},
   257 	{"fo",	LANG_FAEROESE, {
   258 		{ "FO", SUBLANG_DEFAULT },
   259 		{ "", 0}}
   260 	},
   261 	{ "fr", LANG_FRENCH, {
   262 		{ "FR", SUBLANG_FRENCH },
   263 		{ "BE", SUBLANG_FRENCH_BELGIAN },
   264 		{ "CA", SUBLANG_FRENCH_CANADIAN },
   265 		{ "CH", SUBLANG_FRENCH_SWISS },
   266 		{ "LU", SUBLANG_FRENCH_LUXEMBOURG },
   267 		{ "MC", SUBLANG_FRENCH_MONACO },
   268 		{"",0}}
   269 	},
   270 	{ "gl", LANG_GALICIAN, {
   271 		{ "ES", SUBLANG_DEFAULT }, 
   272 		{ "", 0}}
   273 	},
   274 	{ "gu", LANG_GUJARATI, {
   275 		{ "IN", SUBLANG_DEFAULT }, 
   276 		{ "", 0}}
   277 	},
   278 	{"he",	LANG_HEBREW, {
   279 		{ "IL", SUBLANG_DEFAULT},
   280 		{ "", 0}}
   281 	},
   282 	{"hi",	LANG_HINDI, {
   283 		{ "IN", SUBLANG_DEFAULT },
   284 		{ "", 0}}
   285 	},
   286 	/* Duplicate the SUBLANG codes for Croatian and Serbian, because the Windows
   287 	   LANG code is the same for both */
   288 	{"hr",	LANG_CROATIAN, {
   289 		{ "CS", SUBLANG_SERBIAN_LATIN },
   290 		{ "SP", SUBLANG_SERBIAN_CYRILLIC },
   291 		{ "HR", SUBLANG_DEFAULT},
   292 		{ "" ,0 }}
   293 	},
   294 	{"hu",	LANG_HUNGARIAN, {
   295 		{ "HU", SUBLANG_DEFAULT },
   296 		{ "" , 0 }}
   297 	},
   298 	{"hy",	LANG_ARMENIAN, {
   299 		{ "AM", SUBLANG_DEFAULT},
   300 		{ "" ,0 }}
   301 	},
   302 	{"id",	LANG_INDONESIAN, {
   303 		{ "ID", SUBLANG_DEFAULT },
   304 		{"", 0}}
   305 	},
   306 	{"is",	LANG_ICELANDIC, {
   307 		{ "IS", SUBLANG_DEFAULT },
   308 		{ "", 0}}
   309 	},
   310 	{ "it", LANG_ITALIAN, {
   311 		{ "IT", SUBLANG_ITALIAN },
   312 		{ "CH", SUBLANG_ITALIAN_SWISS },
   313 		{ "", 0}}
   314 	},
   315 	{"iw",	LANG_HEBREW, {
   316 		{ "IL", SUBLANG_DEFAULT},
   317 		{ "", 0}}
   318 	},
   319 	{"ja",	LANG_JAPANESE, {
   320 		{ "JP", SUBLANG_DEFAULT },
   321 		{ "", 0}}
   322 	},
   323 	{ "ka", LANG_GEORGIAN, {
   324 		{ "GE", SUBLANG_DEFAULT },
   325 		{ "", 0}}
   326 	},
   327 	{ "kk", LANG_KAZAK, {
   328 		{ "KZ", SUBLANG_DEFAULT }, // KAZAKHSTAN
   329 		{ "", 0}}
   330 	},
   331 	{ "kn", LANG_KANNADA, {
   332 		{ "IN", SUBLANG_DEFAULT }, 
   333 		{ "", 0}}
   334 	},
   335 	{ "ko", LANG_KOREAN, {
   336 		{ "KR", SUBLANG_KOREAN },
   337 		{ "", 0}}
   338 	},
   339 	{ "kok", LANG_KONKANI, {
   340 		{ "IN", SUBLANG_DEFAULT }, 
   341 		{ "", 0}}
   342 	},
   343 	{ "ky", LANG_KYRGYZ, {
   344 		{ "KG", SUBLANG_DEFAULT }, // Kygyzstan
   345 		{ "", 0}}
   346 	},
   347 	{"lt",	LANG_LITHUANIAN, {
   348 		{ "LT", SUBLANG_DEFAULT },
   349 		{ "" ,0 }}
   350 	},
   351 	{"lv",	LANG_LATVIAN, {
   352 		{ "LV", SUBLANG_DEFAULT},
   353 		{ "", 0}}
   354 	},
   355 	{"mk",	LANG_MACEDONIAN, {
   356 		{ "MK", SUBLANG_DEFAULT },
   357 		{ "", 0 }}
   358 	},
   359 	{ "mn", LANG_MONGOLIAN, {
   360 		{ "MN", SUBLANG_DEFAULT }, 
   361 		{ "", 0}}
   362 	},
   363 	{ "mr", LANG_MARATHI, {
   364 		{ "IN", SUBLANG_DEFAULT }, 
   365 		{ "", 0}}
   366 	},
   367 	{"ms",	LANG_MALAY, {
   368 		{ "MY", SUBLANG_MALAY_MALAYSIA },
   369 		{ "BN", SUBLANG_MALAY_BRUNEI_DARUSSALAM }, // XXX
   370 		{ "", 0}}
   371 	},
   372 	{"nb",	LANG_NORWEGIAN, {
   373 		{ "NO",  SUBLANG_NORWEGIAN_BOKMAL },
   374 		{ "", SUBLANG_NORWEGIAN_BOKMAL}}
   375 	},
   376 	{"nl",	LANG_DUTCH, {
   377 		{"NL", SUBLANG_DUTCH },
   378 		{"BE", SUBLANG_DUTCH_BELGIAN },
   379 		{ "", 0}}
   380 	},
   381 	{"nn",	LANG_NORWEGIAN, {
   382 		{ "NO",  SUBLANG_NORWEGIAN_NYNORSK },
   383 		{ "", SUBLANG_NORWEGIAN_NYNORSK}}
   384 	},
   385 	{"no",	LANG_NORWEGIAN, {
   386 		{ "NO",  SUBLANG_DEFAULT },
   387 		{ "", 0}}
   388 	},
   389 	{ "pa", LANG_PUNJABI, {
   390 		{ "IN", SUBLANG_DEFAULT }, 
   391 		{ "", 0}}
   392 	},
   393 	{"pl",	LANG_POLISH, {
   394 		{ "PL", SUBLANG_DEFAULT },
   395 		{ "", 0}}
   396 	},
   397 	{ "pt", LANG_PORTUGUESE, {
   398 		{ "PT", SUBLANG_PORTUGUESE },
   399 		{ "BR", SUBLANG_PORTUGUESE_BRAZILIAN },
   400 		{"",0}}
   401 	},
   402 	{"ro",	LANG_ROMANIAN, {
   403 		{ "RO", SUBLANG_DEFAULT },
   404 		{ "", 0}}
   405 	},
   406 	{"ru",	LANG_RUSSIAN, {
   407 		{ "RU", SUBLANG_DEFAULT },
   408 		{ "", 0 }}
   409 	},
   410 	{ "sa", LANG_SANSKRIT, {
   411 		{ "IN", SUBLANG_DEFAULT }, 
   412 		{ "", 0}}
   413 	},
   414 	{"sk",	LANG_SLOVAK, {
   415 		{ "SK", SUBLANG_DEFAULT },
   416 		{ "", 0}}
   417 	},
   418 	{"sl",	LANG_SLOVENIAN, {
   419 		{ "SI", SUBLANG_DEFAULT },
   420 		{ "", 0}}
   421 	},
   422 	{"sq",	LANG_ALBANIAN, {
   423 		{ "AL", SUBLANG_DEFAULT },
   424 		{ "", 0}}
   425 	},		
   426 	/* Duplicate the SUBLANG codes for Croatian and Serbian, because the Windows
   427 	   LANG code is the same for both */
   428 	{"sr",	LANG_SERBIAN, {
   429 		{ "CS", SUBLANG_SERBIAN_LATIN },
   430 		{ "SP", SUBLANG_SERBIAN_CYRILLIC },
   431 		{ "HR", SUBLANG_DEFAULT },
   432 		{ "", 0}}
   433 	},
   434 	{ "sv", LANG_SWEDISH, {
   435 		{ "SE", SUBLANG_SWEDISH },
   436 		{ "FI", SUBLANG_SWEDISH_FINLAND },
   437 		{ "", 0 }}
   438 	},
   439 	{"sw",	LANG_SWAHILI, {
   440 		{ "KE", SUBLANG_DEFAULT },
   441 		{ "", 0}}
   442 	},
   443 	{ "ta", LANG_TAMIL, {
   444 		{ "IN", SUBLANG_DEFAULT }, 
   445 		{ "", 0}}
   446 	},
   447 	{ "te", LANG_TELUGU, {
   448 		{ "IN", SUBLANG_DEFAULT }, 
   449 		{ "", 0}}
   450 	},
   451 	{"th",	LANG_THAI, {
   452 		{"TH", SUBLANG_DEFAULT},
   453 		{"",0}}
   454 	},
   455 	{"tr",	LANG_TURKISH, {
   456 		{ "TR", SUBLANG_DEFAULT },
   457 		{ "", 0}}
   458 	},
   459 	{ "tt", LANG_TATAR, {
   460 		{ "RU", SUBLANG_DEFAULT }, 
   461 		{ "", 0}}
   462 	},
   463 	{"uk",	LANG_UKRAINIAN, {
   464 		{ "UA", SUBLANG_DEFAULT },
   465 		{ "", 0}}
   466 	},
   467 	{"ur",	LANG_URDU, {
   468 		{ "PK", SUBLANG_URDU_PAKISTAN },
   469 		{ "IN", SUBLANG_URDU_INDIA },
   470 		{ "", 0}}
   471 	},
   472 	{"uz",	LANG_UZBEK, {   // XXX : Cyrillic, Latin
   473 		{ "UZ", SUBLANG_DEFAULT },
   474 		{ "", 0}}
   475 	},
   476 	{"vi",	LANG_VIETNAMESE, {
   477 		{ "VN", SUBLANG_DEFAULT },
   478 		{ "", 0}}
   479 	},
   480 	{ "zh", LANG_CHINESE, {
   481 		{ "TW", SUBLANG_CHINESE_TRADITIONAL },
   482 		{ "CN", SUBLANG_CHINESE_SIMPLIFIED },
   483 		{ "HK", SUBLANG_CHINESE_HONGKONG },
   484 		{ "SG", SUBLANG_CHINESE_SINGAPORE },
   485 		{ "MO", SUBLANG_CHINESE_MACAU },
   486 		{ "",0}}
   487 	}
   488 };
   490 #define LENGTH_MAPPING_LIST		ArrayLength(iso_list)
   492 //
   493 // This list maps ISO 2 digit country codes to Win32 country codes.
   494 // This list must be kept in alphabetic (by iso code) order and synchronized
   495 // with the list above.  This is only used in debug builds to check the consistentcy
   496 // of the internal tables.
   497 //
   498 #ifdef DEBUG
   499 static const
   500 iso_pair dbg_list[] =
   501 {
   502 	{"af",	LANG_AFRIKAANS},		
   503 	{"ar",	LANG_ARABIC},
   504 	{"az",	LANG_AZERI},
   505 	{"be",	LANG_BELARUSIAN},
   506 	{"bg",	LANG_BULGARIAN},
   507 	{"ca",	LANG_CATALAN},
   508 	{"cs",	LANG_CZECH},
   509 	{"da",	LANG_DANISH},
   510 	{"de",	LANG_GERMAN},
   511 	{"dv",  LANG_DIVEHI},
   512 	{"el",	LANG_GREEK},
   513 	{"en",	LANG_ENGLISH},
   514 	{"es",	LANG_SPANISH},
   515 	{"et",	LANG_ESTONIAN},
   516 	{"eu",	LANG_BASQUE},
   517 	{"fa",	LANG_FARSI},
   518 	{"fi",	LANG_FINNISH},
   519 	{"fo",	LANG_FAEROESE},
   520 	{"fr",	LANG_FRENCH},
   521 	{"gl",  LANG_GALICIAN},
   522 	{"gu",  LANG_GUJARATI},
   523 	{"he",	LANG_HEBREW},
   524 	{"hi",	LANG_HINDI},
   525 	{"hr",	LANG_CROATIAN},
   526 	{"hu",	LANG_HUNGARIAN},
   527 	{"hy",	LANG_ARMENIAN},
   528 	{"id",	LANG_INDONESIAN},
   529 	{"in",	LANG_INDONESIAN},
   530 	{"is",	LANG_ICELANDIC},
   531 	{"it",	LANG_ITALIAN},
   532 	{"iw",	LANG_HEBREW},
   533 	{"ja",	LANG_JAPANESE},
   534 	{"ka",	LANG_GEORGIAN},
   535 	{"kn",  LANG_KANNADA},
   536 	{"ko",	LANG_KOREAN},
   537 	{"kok", LANG_KONKANI},
   538 	{"lt",	LANG_LITHUANIAN},
   539 	{"lv",	LANG_LATVIAN},
   540 	{"mk",	LANG_MACEDONIAN},
   541 	{"mn",  LANG_MONGOLIAN},
   542 	{"mr",  LANG_MARATHI},
   543 	{"ms",	LANG_MALAY},
   544 	{"nb",	LANG_NORWEGIAN},
   545 	{"nl",	LANG_DUTCH},
   546 	{"nn",	LANG_NORWEGIAN},
   547 	{"no",	LANG_NORWEGIAN},
   548 	{"pa",  LANG_PUNJABI},
   549 	{"pl",	LANG_POLISH},
   550 	{"pt",	LANG_PORTUGUESE},
   551 	{"ro",	LANG_ROMANIAN},
   552 	{"ru",	LANG_RUSSIAN},
   553 	{"sa",  LANG_SANSKRIT},
   554 	{"sk",	LANG_SLOVAK},
   555 	{"sl",	LANG_SLOVENIAN},
   556 	{"sq",	LANG_ALBANIAN},		
   557 	{"sr",	LANG_SERBIAN},
   558 	{"sv",	LANG_SWEDISH},
   559 	{"sw",	LANG_SWAHILI},
   560 	{"ta",  LANG_TAMIL},
   561 	{"te",  LANG_TELUGU},
   562 	{"th",	LANG_THAI},
   563 	{"tr",	LANG_TURKISH},
   564 	{"tt",  LANG_TATAR},
   565 	{"uk",	LANG_UKRAINIAN},
   566 	{"ur",	LANG_URDU},
   567 	{"uz",	LANG_UZBEK},
   568 	{"vi",	LANG_VIETNAMESE},
   569 	{"zh",	LANG_CHINESE},
   570 	{"",0}
   571 };
   572 #endif
   574 #define CROATIAN_ISO_CODE "hr"
   575 #define SERBIAN_ISO_CODE "sr"
   577 void
   578 nsWin32Locale::initFunctionPointers(void)
   579 {
   580   static bool sInitialized = false;
   581   // We use the Vista and above functions if we have them
   582   if (!sInitialized) {
   583     HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
   584     if (kernelDLL) {
   585       localeNameToLCID = (LocaleNameToLCIDPtr) GetProcAddress(kernelDLL, "LocaleNameToLCID");
   586       lcidToLocaleName = (LCIDToLocaleNamePtr) GetProcAddress(kernelDLL, "LCIDToLocaleName");
   587     }
   588     sInitialized = true;
   589   }
   590 }
   592 //
   593 // the mapping routines are a first approximation to get us going on
   594 // the tier-1 languages.  we are making an assumption that we can map
   595 // language and country codes separately on Windows, which isn't true
   596 //
   597 nsresult
   598 nsWin32Locale::GetPlatformLocale(const nsAString& locale, LCID* winLCID)
   599 {
   600   initFunctionPointers ();
   602   if (localeNameToLCID) {
   603     nsAutoString locale_autostr(locale);
   604     LCID lcid = localeNameToLCID(locale_autostr.get(), 0);
   605     // The function returning 0 means that the locale name couldn't be matched,
   606     // so we fallback to the old function
   607     if (lcid != 0)
   608     {
   609       *winLCID = lcid;
   610       return NS_OK;
   611     }
   612   }
   614   char    locale_string[9] = {'\0','\0','\0','\0','\0','\0','\0','\0','\0'};
   615   char*   language_code;
   616   char*   country_code;
   617   size_t  i, j;
   619   // parse the locale
   620   const char16_t* data;
   621   j = NS_StringGetData(locale, &data);
   622   for (i = 0; i < 7 && i < j; i++) {
   623     locale_string[i] = data[i] == '-' ? '\0' : data[i];
   624   }
   626   language_code = locale_string;
   627   country_code = locale_string + strlen(locale_string) + 1;
   629   // convert parsed locale to Windows LCID
   630   for(i=0;i<LENGTH_MAPPING_LIST;i++) {
   631     if (strcmp(language_code,iso_list[i].iso_code)==0) {
   632       for(j=0;iso_list[i].sublang_list[j].win_code;j++) {
   633         if (strcmp(country_code,iso_list[i].sublang_list[j].iso_code)==0) {
   634           *winLCID = MAKELCID(MAKELANGID(iso_list[i].win_code,iso_list[i].sublang_list[j].win_code),SORT_DEFAULT);
   635           return NS_OK;
   636         }
   637       }
   638       // here we have a language match but no country match
   639       *winLCID = MAKELCID(MAKELANGID(iso_list[i].win_code,SUBLANG_DEFAULT),SORT_DEFAULT);
   640       return NS_OK;
   641     }
   642   }
   644   return NS_ERROR_FAILURE;
   645 }
   647 #ifndef LOCALE_NAME_MAX_LENGTH
   648 #define LOCALE_NAME_MAX_LENGTH 85
   649 #endif
   651 void
   652 nsWin32Locale::GetXPLocale(LCID winLCID, nsAString& locale)
   653 {
   654   initFunctionPointers ();
   656   if (lcidToLocaleName)
   657   {
   658     WCHAR ret_locale[LOCALE_NAME_MAX_LENGTH];
   659     int rv = lcidToLocaleName(winLCID, ret_locale, LOCALE_NAME_MAX_LENGTH, 0);
   660     // rv 0 means that the function failed to match up the LCID, so we fallback
   661     // to the old function
   662     if (rv != 0)
   663     {
   664       locale.Assign(ret_locale);
   665       return;
   666     }
   667   }
   669   DWORD    lang_id, sublang_id;
   670   size_t   i, j;
   672   lang_id = PRIMARYLANGID(LANGIDFROMLCID(winLCID));
   673   sublang_id = SUBLANGID(LANGIDFROMLCID(winLCID));
   675   /* Special-case Norwegian Bokmal and Norwegian Nynorsk, which have the same
   676      LANG_ID on Windows, but have separate ISO-639-2 codes */
   677   if (lang_id == LANG_NORWEGIAN) {
   678     if (sublang_id == SUBLANG_NORWEGIAN_BOKMAL) {
   679       locale.AssignASCII("nb-NO");
   680     } else if (sublang_id == SUBLANG_NORWEGIAN_NYNORSK) {
   681       locale.AssignASCII("nn-NO");
   682     } else {
   683       locale.AssignASCII("no-NO");
   684     }
   685     return;
   686   }
   688   for(i=0;i<LENGTH_MAPPING_LIST;i++) {
   689     if (lang_id==iso_list[i].win_code) {
   690       /* Special-case Croatian and Serbian, which have the same LANG_ID on
   691          Windows, but have been split into separate ISO-639-2 codes */
   692       if (lang_id == LANG_CROATIAN) {
   693         if (sublang_id == SUBLANG_DEFAULT) {
   694           locale.AssignLiteral(CROATIAN_ISO_CODE);
   695         } else {
   696           locale.AssignLiteral(SERBIAN_ISO_CODE);
   697         }
   698       } else {
   699         locale.AssignASCII(iso_list[i].iso_code);
   700       }
   701       for(j=0;iso_list[i].sublang_list[j].win_code;j++) {
   702         if (sublang_id == iso_list[i].sublang_list[j].win_code) {
   703           locale.Append(char16_t('-'));
   704           locale.AppendASCII(iso_list[i].sublang_list[j].iso_code);
   705           break;
   706         }
   707       }
   708       return;
   709     }
   710   }
   712   //
   713   // didn't find any match. fall back to en-US, which is better 
   714   // than unusable buttons without 'OK', 'Cancel', etc (bug 224546)       
   715   //
   716   locale.AssignLiteral("en-US"); 
   717   return;
   718 }
   720 #ifdef DEBUG
   721 void
   722 test_internal_tables(void)
   723 {
   724 	size_t i;
   726 	for(i=1;i<LENGTH_MAPPING_LIST;i++) {
   727 		if (strcmp(dbg_list[i-1].iso_code,dbg_list[i].iso_code)>=0)
   728 			fprintf(stderr,"nsLocale: language_list %s and %s are not ordered\n",dbg_list[i-1].iso_code,dbg_list[i].iso_code);
   729 	}
   731 	i=0;
   732 	while(strlen(dbg_list[i].iso_code)!=0) {
   733 		i++;
   734 	}
   735 	if (i!=LENGTH_MAPPING_LIST)
   736 		fprintf(stderr,"nsLocale: language_list length is %d, reported length is %d\n",i,LENGTH_MAPPING_LIST);
   738 	for(i=0;i<LENGTH_MAPPING_LIST;i++) {
   739 		if (strcmp(iso_list[i].iso_code,dbg_list[i].iso_code)!=0) {
   740 			fprintf(stderr,"nsLocale: iso_list and dbg_list differet at item: %d\n",i);
   741 		}
   742 	}
   743 }
   745 #endif

mercurial