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.

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

mercurial