Use spaces for indentation, not tabs.
[gnulib.git] / lib / localename.c
1 /* Determine name of the currently selected locale.
2    Copyright (C) 1995-1999, 2000-2008 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify it
5    under the terms of the GNU Library General Public License as published
6    by the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17    USA.  */
18
19 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
20 /* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
21 /* MacOS X code written by Bruno Haible <bruno@clisp.org>.  */
22
23 #include <config.h>
24
25 /* Specification.  */
26 #ifdef IN_LIBINTL
27 # include "gettextP.h"
28 #else
29 # include "localename.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <locale.h>
34
35 #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
36 # include <string.h>
37 # include <CoreFoundation/CFString.h>
38 # if HAVE_CFLOCALECOPYCURRENT
39 #  include <CoreFoundation/CFLocale.h>
40 # elif HAVE_CFPREFERENCESCOPYAPPVALUE
41 #  include <CoreFoundation/CFPreferences.h>
42 # endif
43 #endif
44
45 #if defined _WIN32 || defined __WIN32__
46 # define WIN32_NATIVE
47 #endif
48
49 #ifdef WIN32_NATIVE
50 # define WIN32_LEAN_AND_MEAN
51 # include <windows.h>
52 /* List of language codes, sorted by value:
53    0x01 LANG_ARABIC
54    0x02 LANG_BULGARIAN
55    0x03 LANG_CATALAN
56    0x04 LANG_CHINESE
57    0x05 LANG_CZECH
58    0x06 LANG_DANISH
59    0x07 LANG_GERMAN
60    0x08 LANG_GREEK
61    0x09 LANG_ENGLISH
62    0x0a LANG_SPANISH
63    0x0b LANG_FINNISH
64    0x0c LANG_FRENCH
65    0x0d LANG_HEBREW
66    0x0e LANG_HUNGARIAN
67    0x0f LANG_ICELANDIC
68    0x10 LANG_ITALIAN
69    0x11 LANG_JAPANESE
70    0x12 LANG_KOREAN
71    0x13 LANG_DUTCH
72    0x14 LANG_NORWEGIAN
73    0x15 LANG_POLISH
74    0x16 LANG_PORTUGUESE
75    0x17 LANG_RHAETO_ROMANCE
76    0x18 LANG_ROMANIAN
77    0x19 LANG_RUSSIAN
78    0x1a LANG_CROATIAN == LANG_SERBIAN
79    0x1b LANG_SLOVAK
80    0x1c LANG_ALBANIAN
81    0x1d LANG_SWEDISH
82    0x1e LANG_THAI
83    0x1f LANG_TURKISH
84    0x20 LANG_URDU
85    0x21 LANG_INDONESIAN
86    0x22 LANG_UKRAINIAN
87    0x23 LANG_BELARUSIAN
88    0x24 LANG_SLOVENIAN
89    0x25 LANG_ESTONIAN
90    0x26 LANG_LATVIAN
91    0x27 LANG_LITHUANIAN
92    0x28 LANG_TAJIK
93    0x29 LANG_FARSI
94    0x2a LANG_VIETNAMESE
95    0x2b LANG_ARMENIAN
96    0x2c LANG_AZERI
97    0x2d LANG_BASQUE
98    0x2e LANG_SORBIAN
99    0x2f LANG_MACEDONIAN
100    0x30 LANG_SUTU
101    0x31 LANG_TSONGA
102    0x32 LANG_TSWANA
103    0x33 LANG_VENDA
104    0x34 LANG_XHOSA
105    0x35 LANG_ZULU
106    0x36 LANG_AFRIKAANS
107    0x37 LANG_GEORGIAN
108    0x38 LANG_FAEROESE
109    0x39 LANG_HINDI
110    0x3a LANG_MALTESE
111    0x3b LANG_SAAMI
112    0x3c LANG_GAELIC
113    0x3d LANG_YIDDISH
114    0x3e LANG_MALAY
115    0x3f LANG_KAZAK
116    0x40 LANG_KYRGYZ
117    0x41 LANG_SWAHILI
118    0x42 LANG_TURKMEN
119    0x43 LANG_UZBEK
120    0x44 LANG_TATAR
121    0x45 LANG_BENGALI
122    0x46 LANG_PUNJABI
123    0x47 LANG_GUJARATI
124    0x48 LANG_ORIYA
125    0x49 LANG_TAMIL
126    0x4a LANG_TELUGU
127    0x4b LANG_KANNADA
128    0x4c LANG_MALAYALAM
129    0x4d LANG_ASSAMESE
130    0x4e LANG_MARATHI
131    0x4f LANG_SANSKRIT
132    0x50 LANG_MONGOLIAN
133    0x51 LANG_TIBETAN
134    0x52 LANG_WELSH
135    0x53 LANG_CAMBODIAN
136    0x54 LANG_LAO
137    0x55 LANG_BURMESE
138    0x56 LANG_GALICIAN
139    0x57 LANG_KONKANI
140    0x58 LANG_MANIPURI
141    0x59 LANG_SINDHI
142    0x5a LANG_SYRIAC
143    0x5b LANG_SINHALESE
144    0x5c LANG_CHEROKEE
145    0x5d LANG_INUKTITUT
146    0x5e LANG_AMHARIC
147    0x5f LANG_TAMAZIGHT
148    0x60 LANG_KASHMIRI
149    0x61 LANG_NEPALI
150    0x62 LANG_FRISIAN
151    0x63 LANG_PASHTO
152    0x64 LANG_TAGALOG
153    0x65 LANG_DIVEHI
154    0x66 LANG_EDO
155    0x67 LANG_FULFULDE
156    0x68 LANG_HAUSA
157    0x69 LANG_IBIBIO
158    0x6a LANG_YORUBA
159    0x70 LANG_IGBO
160    0x71 LANG_KANURI
161    0x72 LANG_OROMO
162    0x73 LANG_TIGRINYA
163    0x74 LANG_GUARANI
164    0x75 LANG_HAWAIIAN
165    0x76 LANG_LATIN
166    0x77 LANG_SOMALI
167    0x78 LANG_YI
168    0x79 LANG_PAPIAMENTU
169 */
170 /* Mingw headers don't have latest language and sublanguage codes.  */
171 # ifndef LANG_AFRIKAANS
172 # define LANG_AFRIKAANS 0x36
173 # endif
174 # ifndef LANG_ALBANIAN
175 # define LANG_ALBANIAN 0x1c
176 # endif
177 # ifndef LANG_AMHARIC
178 # define LANG_AMHARIC 0x5e
179 # endif
180 # ifndef LANG_ARABIC
181 # define LANG_ARABIC 0x01
182 # endif
183 # ifndef LANG_ARMENIAN
184 # define LANG_ARMENIAN 0x2b
185 # endif
186 # ifndef LANG_ASSAMESE
187 # define LANG_ASSAMESE 0x4d
188 # endif
189 # ifndef LANG_AZERI
190 # define LANG_AZERI 0x2c
191 # endif
192 # ifndef LANG_BASQUE
193 # define LANG_BASQUE 0x2d
194 # endif
195 # ifndef LANG_BELARUSIAN
196 # define LANG_BELARUSIAN 0x23
197 # endif
198 # ifndef LANG_BENGALI
199 # define LANG_BENGALI 0x45
200 # endif
201 # ifndef LANG_BURMESE
202 # define LANG_BURMESE 0x55
203 # endif
204 # ifndef LANG_CAMBODIAN
205 # define LANG_CAMBODIAN 0x53
206 # endif
207 # ifndef LANG_CATALAN
208 # define LANG_CATALAN 0x03
209 # endif
210 # ifndef LANG_CHEROKEE
211 # define LANG_CHEROKEE 0x5c
212 # endif
213 # ifndef LANG_DIVEHI
214 # define LANG_DIVEHI 0x65
215 # endif
216 # ifndef LANG_EDO
217 # define LANG_EDO 0x66
218 # endif
219 # ifndef LANG_ESTONIAN
220 # define LANG_ESTONIAN 0x25
221 # endif
222 # ifndef LANG_FAEROESE
223 # define LANG_FAEROESE 0x38
224 # endif
225 # ifndef LANG_FARSI
226 # define LANG_FARSI 0x29
227 # endif
228 # ifndef LANG_FRISIAN
229 # define LANG_FRISIAN 0x62
230 # endif
231 # ifndef LANG_FULFULDE
232 # define LANG_FULFULDE 0x67
233 # endif
234 # ifndef LANG_GAELIC
235 # define LANG_GAELIC 0x3c
236 # endif
237 # ifndef LANG_GALICIAN
238 # define LANG_GALICIAN 0x56
239 # endif
240 # ifndef LANG_GEORGIAN
241 # define LANG_GEORGIAN 0x37
242 # endif
243 # ifndef LANG_GUARANI
244 # define LANG_GUARANI 0x74
245 # endif
246 # ifndef LANG_GUJARATI
247 # define LANG_GUJARATI 0x47
248 # endif
249 # ifndef LANG_HAUSA
250 # define LANG_HAUSA 0x68
251 # endif
252 # ifndef LANG_HAWAIIAN
253 # define LANG_HAWAIIAN 0x75
254 # endif
255 # ifndef LANG_HEBREW
256 # define LANG_HEBREW 0x0d
257 # endif
258 # ifndef LANG_HINDI
259 # define LANG_HINDI 0x39
260 # endif
261 # ifndef LANG_IBIBIO
262 # define LANG_IBIBIO 0x69
263 # endif
264 # ifndef LANG_IGBO
265 # define LANG_IGBO 0x70
266 # endif
267 # ifndef LANG_INDONESIAN
268 # define LANG_INDONESIAN 0x21
269 # endif
270 # ifndef LANG_INUKTITUT
271 # define LANG_INUKTITUT 0x5d
272 # endif
273 # ifndef LANG_KANNADA
274 # define LANG_KANNADA 0x4b
275 # endif
276 # ifndef LANG_KANURI
277 # define LANG_KANURI 0x71
278 # endif
279 # ifndef LANG_KASHMIRI
280 # define LANG_KASHMIRI 0x60
281 # endif
282 # ifndef LANG_KAZAK
283 # define LANG_KAZAK 0x3f
284 # endif
285 # ifndef LANG_KONKANI
286 # define LANG_KONKANI 0x57
287 # endif
288 # ifndef LANG_KYRGYZ
289 # define LANG_KYRGYZ 0x40
290 # endif
291 # ifndef LANG_LAO
292 # define LANG_LAO 0x54
293 # endif
294 # ifndef LANG_LATIN
295 # define LANG_LATIN 0x76
296 # endif
297 # ifndef LANG_LATVIAN
298 # define LANG_LATVIAN 0x26
299 # endif
300 # ifndef LANG_LITHUANIAN
301 # define LANG_LITHUANIAN 0x27
302 # endif
303 # ifndef LANG_MACEDONIAN
304 # define LANG_MACEDONIAN 0x2f
305 # endif
306 # ifndef LANG_MALAY
307 # define LANG_MALAY 0x3e
308 # endif
309 # ifndef LANG_MALAYALAM
310 # define LANG_MALAYALAM 0x4c
311 # endif
312 # ifndef LANG_MALTESE
313 # define LANG_MALTESE 0x3a
314 # endif
315 # ifndef LANG_MANIPURI
316 # define LANG_MANIPURI 0x58
317 # endif
318 # ifndef LANG_MAORI
319 # define LANG_MAORI 0x81
320 # endif
321 # ifndef LANG_MARATHI
322 # define LANG_MARATHI 0x4e
323 # endif
324 # ifndef LANG_MONGOLIAN
325 # define LANG_MONGOLIAN 0x50
326 # endif
327 # ifndef LANG_NEPALI
328 # define LANG_NEPALI 0x61
329 # endif
330 # ifndef LANG_ORIYA
331 # define LANG_ORIYA 0x48
332 # endif
333 # ifndef LANG_OROMO
334 # define LANG_OROMO 0x72
335 # endif
336 # ifndef LANG_PAPIAMENTU
337 # define LANG_PAPIAMENTU 0x79
338 # endif
339 # ifndef LANG_PASHTO
340 # define LANG_PASHTO 0x63
341 # endif
342 # ifndef LANG_PUNJABI
343 # define LANG_PUNJABI 0x46
344 # endif
345 # ifndef LANG_QUECHUA
346 # define LANG_QUECHUA 0x6b
347 # endif
348 # ifndef LANG_RHAETO_ROMANCE
349 # define LANG_RHAETO_ROMANCE 0x17
350 # endif
351 # ifndef LANG_SAAMI
352 # define LANG_SAAMI 0x3b
353 # endif
354 # ifndef LANG_SANSKRIT
355 # define LANG_SANSKRIT 0x4f
356 # endif
357 # ifndef LANG_SERBIAN
358 # define LANG_SERBIAN 0x1a
359 # endif
360 # ifndef LANG_SINDHI
361 # define LANG_SINDHI 0x59
362 # endif
363 # ifndef LANG_SINHALESE
364 # define LANG_SINHALESE 0x5b
365 # endif
366 # ifndef LANG_SLOVAK
367 # define LANG_SLOVAK 0x1b
368 # endif
369 # ifndef LANG_SOMALI
370 # define LANG_SOMALI 0x77
371 # endif
372 # ifndef LANG_SORBIAN
373 # define LANG_SORBIAN 0x2e
374 # endif
375 # ifndef LANG_SOTHO
376 # define LANG_SOTHO 0x6c
377 # endif
378 # ifndef LANG_SUTU
379 # define LANG_SUTU 0x30
380 # endif
381 # ifndef LANG_SWAHILI
382 # define LANG_SWAHILI 0x41
383 # endif
384 # ifndef LANG_SYRIAC
385 # define LANG_SYRIAC 0x5a
386 # endif
387 # ifndef LANG_TAGALOG
388 # define LANG_TAGALOG 0x64
389 # endif
390 # ifndef LANG_TAJIK
391 # define LANG_TAJIK 0x28
392 # endif
393 # ifndef LANG_TAMAZIGHT
394 # define LANG_TAMAZIGHT 0x5f
395 # endif
396 # ifndef LANG_TAMIL
397 # define LANG_TAMIL 0x49
398 # endif
399 # ifndef LANG_TATAR
400 # define LANG_TATAR 0x44
401 # endif
402 # ifndef LANG_TELUGU
403 # define LANG_TELUGU 0x4a
404 # endif
405 # ifndef LANG_THAI
406 # define LANG_THAI 0x1e
407 # endif
408 # ifndef LANG_TIBETAN
409 # define LANG_TIBETAN 0x51
410 # endif
411 # ifndef LANG_TIGRINYA
412 # define LANG_TIGRINYA 0x73
413 # endif
414 # ifndef LANG_TSONGA
415 # define LANG_TSONGA 0x31
416 # endif
417 # ifndef LANG_TSWANA
418 # define LANG_TSWANA 0x32
419 # endif
420 # ifndef LANG_TURKMEN
421 # define LANG_TURKMEN 0x42
422 # endif
423 # ifndef LANG_UIGHUR
424 # define LANG_UIGHUR 0x80
425 # endif
426 # ifndef LANG_UKRAINIAN
427 # define LANG_UKRAINIAN 0x22
428 # endif
429 # ifndef LANG_URDU
430 # define LANG_URDU 0x20
431 # endif
432 # ifndef LANG_UZBEK
433 # define LANG_UZBEK 0x43
434 # endif
435 # ifndef LANG_VENDA
436 # define LANG_VENDA 0x33
437 # endif
438 # ifndef LANG_VIETNAMESE
439 # define LANG_VIETNAMESE 0x2a
440 # endif
441 # ifndef LANG_WELSH
442 # define LANG_WELSH 0x52
443 # endif
444 # ifndef LANG_XHOSA
445 # define LANG_XHOSA 0x34
446 # endif
447 # ifndef LANG_YI
448 # define LANG_YI 0x78
449 # endif
450 # ifndef LANG_YIDDISH
451 # define LANG_YIDDISH 0x3d
452 # endif
453 # ifndef LANG_YORUBA
454 # define LANG_YORUBA 0x6a
455 # endif
456 # ifndef LANG_ZULU
457 # define LANG_ZULU 0x35
458 # endif
459 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
460 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
461 # endif
462 # ifndef SUBLANG_ARABIC_IRAQ
463 # define SUBLANG_ARABIC_IRAQ 0x02
464 # endif
465 # ifndef SUBLANG_ARABIC_EGYPT
466 # define SUBLANG_ARABIC_EGYPT 0x03
467 # endif
468 # ifndef SUBLANG_ARABIC_LIBYA
469 # define SUBLANG_ARABIC_LIBYA 0x04
470 # endif
471 # ifndef SUBLANG_ARABIC_ALGERIA
472 # define SUBLANG_ARABIC_ALGERIA 0x05
473 # endif
474 # ifndef SUBLANG_ARABIC_MOROCCO
475 # define SUBLANG_ARABIC_MOROCCO 0x06
476 # endif
477 # ifndef SUBLANG_ARABIC_TUNISIA
478 # define SUBLANG_ARABIC_TUNISIA 0x07
479 # endif
480 # ifndef SUBLANG_ARABIC_OMAN
481 # define SUBLANG_ARABIC_OMAN 0x08
482 # endif
483 # ifndef SUBLANG_ARABIC_YEMEN
484 # define SUBLANG_ARABIC_YEMEN 0x09
485 # endif
486 # ifndef SUBLANG_ARABIC_SYRIA
487 # define SUBLANG_ARABIC_SYRIA 0x0a
488 # endif
489 # ifndef SUBLANG_ARABIC_JORDAN
490 # define SUBLANG_ARABIC_JORDAN 0x0b
491 # endif
492 # ifndef SUBLANG_ARABIC_LEBANON
493 # define SUBLANG_ARABIC_LEBANON 0x0c
494 # endif
495 # ifndef SUBLANG_ARABIC_KUWAIT
496 # define SUBLANG_ARABIC_KUWAIT 0x0d
497 # endif
498 # ifndef SUBLANG_ARABIC_UAE
499 # define SUBLANG_ARABIC_UAE 0x0e
500 # endif
501 # ifndef SUBLANG_ARABIC_BAHRAIN
502 # define SUBLANG_ARABIC_BAHRAIN 0x0f
503 # endif
504 # ifndef SUBLANG_ARABIC_QATAR
505 # define SUBLANG_ARABIC_QATAR 0x10
506 # endif
507 # ifndef SUBLANG_AZERI_LATIN
508 # define SUBLANG_AZERI_LATIN 0x01
509 # endif
510 # ifndef SUBLANG_AZERI_CYRILLIC
511 # define SUBLANG_AZERI_CYRILLIC 0x02
512 # endif
513 # ifndef SUBLANG_BENGALI_INDIA
514 # define SUBLANG_BENGALI_INDIA 0x01
515 # endif
516 # ifndef SUBLANG_BENGALI_BANGLADESH
517 # define SUBLANG_BENGALI_BANGLADESH 0x02
518 # endif
519 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
520 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
521 # endif
522 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
523 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
524 # endif
525 # ifndef SUBLANG_CROATIAN_CROATIA
526 # define SUBLANG_CROATIAN_CROATIA 0x01
527 # endif
528 # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
529 # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
530 # endif
531 # ifndef SUBLANG_CHINESE_MACAU
532 # define SUBLANG_CHINESE_MACAU 0x05
533 # endif
534 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
535 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
536 # endif
537 # ifndef SUBLANG_ENGLISH_JAMAICA
538 # define SUBLANG_ENGLISH_JAMAICA 0x08
539 # endif
540 # ifndef SUBLANG_ENGLISH_CARIBBEAN
541 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
542 # endif
543 # ifndef SUBLANG_ENGLISH_BELIZE
544 # define SUBLANG_ENGLISH_BELIZE 0x0a
545 # endif
546 # ifndef SUBLANG_ENGLISH_TRINIDAD
547 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
548 # endif
549 # ifndef SUBLANG_ENGLISH_ZIMBABWE
550 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
551 # endif
552 # ifndef SUBLANG_ENGLISH_PHILIPPINES
553 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
554 # endif
555 # ifndef SUBLANG_ENGLISH_INDONESIA
556 # define SUBLANG_ENGLISH_INDONESIA 0x0e
557 # endif
558 # ifndef SUBLANG_ENGLISH_HONGKONG
559 # define SUBLANG_ENGLISH_HONGKONG 0x0f
560 # endif
561 # ifndef SUBLANG_ENGLISH_INDIA
562 # define SUBLANG_ENGLISH_INDIA 0x10
563 # endif
564 # ifndef SUBLANG_ENGLISH_MALAYSIA
565 # define SUBLANG_ENGLISH_MALAYSIA 0x11
566 # endif
567 # ifndef SUBLANG_ENGLISH_SINGAPORE
568 # define SUBLANG_ENGLISH_SINGAPORE 0x12
569 # endif
570 # ifndef SUBLANG_FRENCH_LUXEMBOURG
571 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
572 # endif
573 # ifndef SUBLANG_FRENCH_MONACO
574 # define SUBLANG_FRENCH_MONACO 0x06
575 # endif
576 # ifndef SUBLANG_FRENCH_WESTINDIES
577 # define SUBLANG_FRENCH_WESTINDIES 0x07
578 # endif
579 # ifndef SUBLANG_FRENCH_REUNION
580 # define SUBLANG_FRENCH_REUNION 0x08
581 # endif
582 # ifndef SUBLANG_FRENCH_CONGO
583 # define SUBLANG_FRENCH_CONGO 0x09
584 # endif
585 # ifndef SUBLANG_FRENCH_SENEGAL
586 # define SUBLANG_FRENCH_SENEGAL 0x0a
587 # endif
588 # ifndef SUBLANG_FRENCH_CAMEROON
589 # define SUBLANG_FRENCH_CAMEROON 0x0b
590 # endif
591 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
592 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
593 # endif
594 # ifndef SUBLANG_FRENCH_MALI
595 # define SUBLANG_FRENCH_MALI 0x0d
596 # endif
597 # ifndef SUBLANG_FRENCH_MOROCCO
598 # define SUBLANG_FRENCH_MOROCCO 0x0e
599 # endif
600 # ifndef SUBLANG_FRENCH_HAITI
601 # define SUBLANG_FRENCH_HAITI 0x0f
602 # endif
603 # ifndef SUBLANG_GERMAN_LUXEMBOURG
604 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
605 # endif
606 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
607 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
608 # endif
609 # ifndef SUBLANG_KASHMIRI_INDIA
610 # define SUBLANG_KASHMIRI_INDIA 0x02
611 # endif
612 # ifndef SUBLANG_MALAY_MALAYSIA
613 # define SUBLANG_MALAY_MALAYSIA 0x01
614 # endif
615 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
616 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
617 # endif
618 # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
619 # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
620 # endif
621 # ifndef SUBLANG_MONGOLIAN_PRC
622 # define SUBLANG_MONGOLIAN_PRC 0x02
623 # endif
624 # ifndef SUBLANG_NEPALI_INDIA
625 # define SUBLANG_NEPALI_INDIA 0x02
626 # endif
627 # ifndef SUBLANG_PUNJABI_INDIA
628 # define SUBLANG_PUNJABI_INDIA 0x01
629 # endif
630 # ifndef SUBLANG_PUNJABI_PAKISTAN
631 # define SUBLANG_PUNJABI_PAKISTAN 0x02
632 # endif
633 # ifndef SUBLANG_QUECHUA_BOLIVIA
634 # define SUBLANG_QUECHUA_BOLIVIA 0x01
635 # endif
636 # ifndef SUBLANG_QUECHUA_ECUADOR
637 # define SUBLANG_QUECHUA_ECUADOR 0x02
638 # endif
639 # ifndef SUBLANG_QUECHUA_PERU
640 # define SUBLANG_QUECHUA_PERU 0x03
641 # endif
642 # ifndef SUBLANG_ROMANIAN_ROMANIA
643 # define SUBLANG_ROMANIAN_ROMANIA 0x01
644 # endif
645 # ifndef SUBLANG_ROMANIAN_MOLDOVA
646 # define SUBLANG_ROMANIAN_MOLDOVA 0x02
647 # endif
648 # ifndef SUBLANG_RUSSIAN_RUSSIA
649 # define SUBLANG_RUSSIAN_RUSSIA 0x01
650 # endif
651 # ifndef SUBLANG_RUSSIAN_MOLDAVIA
652 # define SUBLANG_RUSSIAN_MOLDAVIA 0x02
653 # endif
654 # ifndef SUBLANG_SERBIAN_LATIN
655 # define SUBLANG_SERBIAN_LATIN 0x02
656 # endif
657 # ifndef SUBLANG_SERBIAN_CYRILLIC
658 # define SUBLANG_SERBIAN_CYRILLIC 0x03
659 # endif
660 # ifndef SUBLANG_SINDHI_INDIA
661 # define SUBLANG_SINDHI_INDIA 0x01
662 # endif
663 # undef SUBLANG_SINDHI_PAKISTAN
664 # define SUBLANG_SINDHI_PAKISTAN 0x02
665 # ifndef SUBLANG_SINDHI_AFGHANISTAN
666 # define SUBLANG_SINDHI_AFGHANISTAN 0x02
667 # endif
668 # ifndef SUBLANG_SPANISH_GUATEMALA
669 # define SUBLANG_SPANISH_GUATEMALA 0x04
670 # endif
671 # ifndef SUBLANG_SPANISH_COSTA_RICA
672 # define SUBLANG_SPANISH_COSTA_RICA 0x05
673 # endif
674 # ifndef SUBLANG_SPANISH_PANAMA
675 # define SUBLANG_SPANISH_PANAMA 0x06
676 # endif
677 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
678 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
679 # endif
680 # ifndef SUBLANG_SPANISH_VENEZUELA
681 # define SUBLANG_SPANISH_VENEZUELA 0x08
682 # endif
683 # ifndef SUBLANG_SPANISH_COLOMBIA
684 # define SUBLANG_SPANISH_COLOMBIA 0x09
685 # endif
686 # ifndef SUBLANG_SPANISH_PERU
687 # define SUBLANG_SPANISH_PERU 0x0a
688 # endif
689 # ifndef SUBLANG_SPANISH_ARGENTINA
690 # define SUBLANG_SPANISH_ARGENTINA 0x0b
691 # endif
692 # ifndef SUBLANG_SPANISH_ECUADOR
693 # define SUBLANG_SPANISH_ECUADOR 0x0c
694 # endif
695 # ifndef SUBLANG_SPANISH_CHILE
696 # define SUBLANG_SPANISH_CHILE 0x0d
697 # endif
698 # ifndef SUBLANG_SPANISH_URUGUAY
699 # define SUBLANG_SPANISH_URUGUAY 0x0e
700 # endif
701 # ifndef SUBLANG_SPANISH_PARAGUAY
702 # define SUBLANG_SPANISH_PARAGUAY 0x0f
703 # endif
704 # ifndef SUBLANG_SPANISH_BOLIVIA
705 # define SUBLANG_SPANISH_BOLIVIA 0x10
706 # endif
707 # ifndef SUBLANG_SPANISH_EL_SALVADOR
708 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
709 # endif
710 # ifndef SUBLANG_SPANISH_HONDURAS
711 # define SUBLANG_SPANISH_HONDURAS 0x12
712 # endif
713 # ifndef SUBLANG_SPANISH_NICARAGUA
714 # define SUBLANG_SPANISH_NICARAGUA 0x13
715 # endif
716 # ifndef SUBLANG_SPANISH_PUERTO_RICO
717 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
718 # endif
719 # ifndef SUBLANG_SPANISH_US
720 # define SUBLANG_SPANISH_US 0x15
721 # endif
722 # ifndef SUBLANG_SWEDISH_FINLAND
723 # define SUBLANG_SWEDISH_FINLAND 0x02
724 # endif
725 # ifndef SUBLANG_TAMAZIGHT_ARABIC
726 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
727 # endif
728 # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
729 # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
730 # endif
731 # ifndef SUBLANG_TIBETAN_PRC
732 # define SUBLANG_TIBETAN_PRC 0x01
733 # endif
734 # undef SUBLANG_TIBETAN_BHUTAN
735 # define SUBLANG_TIBETAN_BHUTAN 0x02
736 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
737 # define SUBLANG_TIGRINYA_ETHIOPIA 0x01
738 # endif
739 # ifndef SUBLANG_TIGRINYA_ERITREA
740 # define SUBLANG_TIGRINYA_ERITREA 0x02
741 # endif
742 # ifndef SUBLANG_UIGHUR_PRC
743 # define SUBLANG_UIGHUR_PRC 0x01
744 # endif
745 # ifndef SUBLANG_URDU_PAKISTAN
746 # define SUBLANG_URDU_PAKISTAN 0x01
747 # endif
748 # ifndef SUBLANG_URDU_INDIA
749 # define SUBLANG_URDU_INDIA 0x02
750 # endif
751 # ifndef SUBLANG_UZBEK_LATIN
752 # define SUBLANG_UZBEK_LATIN 0x01
753 # endif
754 # ifndef SUBLANG_UZBEK_CYRILLIC
755 # define SUBLANG_UZBEK_CYRILLIC 0x02
756 # endif
757 /* GetLocaleInfoA operations.  */
758 # ifndef LOCALE_SNAME
759 # define LOCALE_SNAME 0x5c
760 # endif
761 #endif
762
763
764 #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
765 /* MacOS X 10.2 or newer */
766
767 /* Canonicalize a MacOS X locale name to a Unix locale name.
768    NAME is a sufficiently large buffer.
769    On input, it contains the MacOS X locale name.
770    On output, it contains the Unix locale name.  */
771 # if !defined IN_LIBINTL
772 static
773 # endif
774 void
775 gl_locale_name_canonicalize (char *name)
776 {
777   /* This conversion is based on a posting by
778      Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
779      http://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
780
781   /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
782      ISO 3166) names.  Prior to MacOS X 10.3, there is no API for doing this.
783      Therefore we do it ourselves, using a table based on the results of the
784      MacOS X 10.3.8 function
785      CFLocaleCreateCanonicalLocaleIdentifierFromString().  */
786   typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
787           legacy_entry;
788   static const legacy_entry legacy_table[] = {
789     { "Afrikaans",             "af" },
790     { "Albanian",              "sq" },
791     { "Amharic",               "am" },
792     { "Arabic",                "ar" },
793     { "Armenian",              "hy" },
794     { "Assamese",              "as" },
795     { "Aymara",                "ay" },
796     { "Azerbaijani",           "az" },
797     { "Basque",                "eu" },
798     { "Belarusian",            "be" },
799     { "Belorussian",           "be" },
800     { "Bengali",               "bn" },
801     { "Brazilian Portugese",   "pt_BR" },
802     { "Brazilian Portuguese",  "pt_BR" },
803     { "Breton",                "br" },
804     { "Bulgarian",             "bg" },
805     { "Burmese",               "my" },
806     { "Byelorussian",          "be" },
807     { "Catalan",               "ca" },
808     { "Chewa",                 "ny" },
809     { "Chichewa",              "ny" },
810     { "Chinese",               "zh" },
811     { "Chinese, Simplified",   "zh_CN" },
812     { "Chinese, Traditional",  "zh_TW" },
813     { "Chinese, Tradtional",   "zh_TW" },
814     { "Croatian",              "hr" },
815     { "Czech",                 "cs" },
816     { "Danish",                "da" },
817     { "Dutch",                 "nl" },
818     { "Dzongkha",              "dz" },
819     { "English",               "en" },
820     { "Esperanto",             "eo" },
821     { "Estonian",              "et" },
822     { "Faroese",               "fo" },
823     { "Farsi",                 "fa" },
824     { "Finnish",               "fi" },
825     { "Flemish",               "nl_BE" },
826     { "French",                "fr" },
827     { "Galician",              "gl" },
828     { "Gallegan",              "gl" },
829     { "Georgian",              "ka" },
830     { "German",                "de" },
831     { "Greek",                 "el" },
832     { "Greenlandic",           "kl" },
833     { "Guarani",               "gn" },
834     { "Gujarati",              "gu" },
835     { "Hawaiian",              "haw" }, /* Yes, "haw", not "cpe".  */
836     { "Hebrew",                "he" },
837     { "Hindi",                 "hi" },
838     { "Hungarian",             "hu" },
839     { "Icelandic",             "is" },
840     { "Indonesian",            "id" },
841     { "Inuktitut",             "iu" },
842     { "Irish",                 "ga" },
843     { "Italian",               "it" },
844     { "Japanese",              "ja" },
845     { "Javanese",              "jv" },
846     { "Kalaallisut",           "kl" },
847     { "Kannada",               "kn" },
848     { "Kashmiri",              "ks" },
849     { "Kazakh",                "kk" },
850     { "Khmer",                 "km" },
851     { "Kinyarwanda",           "rw" },
852     { "Kirghiz",               "ky" },
853     { "Korean",                "ko" },
854     { "Kurdish",               "ku" },
855     { "Latin",                 "la" },
856     { "Latvian",               "lv" },
857     { "Lithuanian",            "lt" },
858     { "Macedonian",            "mk" },
859     { "Malagasy",              "mg" },
860     { "Malay",                 "ms" },
861     { "Malayalam",             "ml" },
862     { "Maltese",               "mt" },
863     { "Manx",                  "gv" },
864     { "Marathi",               "mr" },
865     { "Moldavian",             "mo" },
866     { "Mongolian",             "mn" },
867     { "Nepali",                "ne" },
868     { "Norwegian",             "nb" }, /* Yes, "nb", not the obsolete "no".  */
869     { "Nyanja",                "ny" },
870     { "Nynorsk",               "nn" },
871     { "Oriya",                 "or" },
872     { "Oromo",                 "om" },
873     { "Panjabi",               "pa" },
874     { "Pashto",                "ps" },
875     { "Persian",               "fa" },
876     { "Polish",                "pl" },
877     { "Portuguese",            "pt" },
878     { "Portuguese, Brazilian", "pt_BR" },
879     { "Punjabi",               "pa" },
880     { "Pushto",                "ps" },
881     { "Quechua",               "qu" },
882     { "Romanian",              "ro" },
883     { "Ruanda",                "rw" },
884     { "Rundi",                 "rn" },
885     { "Russian",               "ru" },
886     { "Sami",                  "se_NO" }, /* Not just "se".  */
887     { "Sanskrit",              "sa" },
888     { "Scottish",              "gd" },
889     { "Serbian",               "sr" },
890     { "Simplified Chinese",    "zh_CN" },
891     { "Sindhi",                "sd" },
892     { "Sinhalese",             "si" },
893     { "Slovak",                "sk" },
894     { "Slovenian",             "sl" },
895     { "Somali",                "so" },
896     { "Spanish",               "es" },
897     { "Sundanese",             "su" },
898     { "Swahili",               "sw" },
899     { "Swedish",               "sv" },
900     { "Tagalog",               "tl" },
901     { "Tajik",                 "tg" },
902     { "Tajiki",                "tg" },
903     { "Tamil",                 "ta" },
904     { "Tatar",                 "tt" },
905     { "Telugu",                "te" },
906     { "Thai",                  "th" },
907     { "Tibetan",               "bo" },
908     { "Tigrinya",              "ti" },
909     { "Tongan",                "to" },
910     { "Traditional Chinese",   "zh_TW" },
911     { "Turkish",               "tr" },
912     { "Turkmen",               "tk" },
913     { "Uighur",                "ug" },
914     { "Ukrainian",             "uk" },
915     { "Urdu",                  "ur" },
916     { "Uzbek",                 "uz" },
917     { "Vietnamese",            "vi" },
918     { "Welsh",                 "cy" },
919     { "Yiddish",               "yi" }
920   };
921
922   /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
923      to Unix (ISO 639 and ISO 3166) names.  */
924   typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
925           langtag_entry;
926   static const langtag_entry langtag_table[] = {
927     /* MacOS X has "az-Arab", "az-Cyrl", "az-Latn".
928        The default script for az on Unix is Latin.  */
929     { "az-Latn", "az" },
930     /* MacOS X has "ga-dots".  Does not yet exist on Unix.  */
931     { "ga-dots", "ga" },
932     /* MacOS X has "kk-Cyrl".  Does not yet exist on Unix.  */
933     /* MacOS X has "mn-Cyrl", "mn-Mong".
934        The default script for mn on Unix is Cyrillic.  */
935     { "mn-Cyrl", "mn" },
936     /* MacOS X has "ms-Arab", "ms-Latn".
937        The default script for ms on Unix is Latin.  */
938     { "ms-Latn", "ms" },
939     /* MacOS X has "tg-Cyrl".
940        The default script for tg on Unix is Cyrillic.  */
941     { "tg-Cyrl", "tg" },
942     /* MacOS X has "tk-Cyrl".  Does not yet exist on Unix.  */
943     /* MacOS X has "tt-Cyrl".
944        The default script for tt on Unix is Cyrillic.  */
945     { "tt-Cyrl", "tt" },
946     /* MacOS X has "zh-Hans", "zh-Hant".
947        Country codes are used to distinguish these on Unix.  */
948     { "zh-Hans", "zh_CN" },
949     { "zh-Hant", "zh_TW" }
950   };
951
952   /* Convert script names (ISO 15924) to Unix conventions.
953      See http://www.unicode.org/iso15924/iso15924-codes.html  */
954   typedef struct { const char script[4+1]; const char unixy[9+1]; }
955           script_entry;
956   static const script_entry script_table[] = {
957     { "Arab", "arabic" },
958     { "Cyrl", "cyrillic" },
959     { "Mong", "mongolian" }
960   };
961
962   /* Step 1: Convert using legacy_table.  */
963   if (name[0] >= 'A' && name[0] <= 'Z')
964     {
965       unsigned int i1, i2;
966       i1 = 0;
967       i2 = sizeof (legacy_table) / sizeof (legacy_entry);
968       while (i2 - i1 > 1)
969         {
970           /* At this point we know that if name occurs in legacy_table,
971              its index must be >= i1 and < i2.  */
972           unsigned int i = (i1 + i2) >> 1;
973           const legacy_entry *p = &legacy_table[i];
974           if (strcmp (name, p->legacy) < 0)
975             i2 = i;
976           else
977             i1 = i;
978         }
979       if (strcmp (name, legacy_table[i1].legacy) == 0)
980         {
981           strcpy (name, legacy_table[i1].unixy);
982           return;
983         }
984     }
985
986   /* Step 2: Convert using langtag_table and script_table.  */
987   if (strlen (name) == 7 && name[2] == '-')
988     {
989       unsigned int i1, i2;
990       i1 = 0;
991       i2 = sizeof (langtag_table) / sizeof (langtag_entry);
992       while (i2 - i1 > 1)
993         {
994           /* At this point we know that if name occurs in langtag_table,
995              its index must be >= i1 and < i2.  */
996           unsigned int i = (i1 + i2) >> 1;
997           const langtag_entry *p = &langtag_table[i];
998           if (strcmp (name, p->langtag) < 0)
999             i2 = i;
1000           else
1001             i1 = i;
1002         }
1003       if (strcmp (name, langtag_table[i1].langtag) == 0)
1004         {
1005           strcpy (name, langtag_table[i1].unixy);
1006           return;
1007         }
1008
1009       i1 = 0;
1010       i2 = sizeof (script_table) / sizeof (script_entry);
1011       while (i2 - i1 > 1)
1012         {
1013           /* At this point we know that if (name + 3) occurs in script_table,
1014              its index must be >= i1 and < i2.  */
1015           unsigned int i = (i1 + i2) >> 1;
1016           const script_entry *p = &script_table[i];
1017           if (strcmp (name + 3, p->script) < 0)
1018             i2 = i;
1019           else
1020             i1 = i;
1021         }
1022       if (strcmp (name + 3, script_table[i1].script) == 0)
1023         {
1024           name[2] = '@';
1025           strcpy (name + 3, script_table[i1].unixy);
1026           return;
1027         }
1028     }
1029
1030   /* Step 3: Convert new-style dash to Unix underscore. */
1031   {
1032     char *p;
1033     for (p = name; *p != '\0'; p++)
1034       if (*p == '-')
1035         *p = '_';
1036   }
1037 }
1038
1039 #endif
1040
1041
1042 #ifdef WIN32_NATIVE
1043
1044 /* Canonicalize a Win32 native locale name to a Unix locale name.
1045    NAME is a sufficiently large buffer.
1046    On input, it contains the Win32 locale name.
1047    On output, it contains the Unix locale name.  */
1048 # if !defined IN_LIBINTL
1049 static
1050 # endif
1051 void
1052 gl_locale_name_canonicalize (char *name)
1053 {
1054   /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1055      "zh-Hant".  */
1056   char *p;
1057
1058   for (p = name; *p != '\0'; p++)
1059     if (*p == '-')
1060       {
1061         *p = '_';
1062         p++;
1063         for (; *p != '\0'; p++)
1064           {
1065             if (*p >= 'a' && *p <= 'z')
1066               *p += 'A' - 'a';
1067             if (*p == '-')
1068               {
1069                 *p = '\0';
1070                 return;
1071               }
1072           }
1073         return;
1074       }
1075 }
1076
1077 # if !defined IN_LIBINTL
1078 static
1079 # endif
1080 const char *
1081 gl_locale_name_from_win32_LANGID (LANGID langid)
1082 {
1083   /* Activate the new code only when the GETTEXT_MUI environment variable is
1084      set, for the time being, since the new code is not well tested.  */
1085   if (getenv ("GETTEXT_MUI") != NULL)
1086     {
1087       static char namebuf[256];
1088
1089       /* Query the system's notion of locale name.
1090          On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1091          But we don't need to support systems that are so old.  */
1092       if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
1093                           namebuf, sizeof (namebuf) - 1))
1094         {
1095           /* Convert it to a Unix locale name.  */
1096           gl_locale_name_canonicalize (namebuf);
1097           return namebuf;
1098         }
1099     }
1100   /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1101      HKEY_CLASSES_ROOT\Mime\Database\Rfc1766.  But we better don't use that
1102      since IE's i18n subsystem is known to be inconsistent with the Win32 base
1103      (e.g. they have different character conversion facilities that produce
1104      different results).  */
1105   /* Use our own table.  */
1106   {
1107     int primary, sub;
1108
1109     /* Split into language and territory part.  */
1110     primary = PRIMARYLANGID (langid);
1111     sub = SUBLANGID (langid);
1112
1113     /* Dispatch on language.
1114        See also http://www.unicode.org/unicode/onlinedat/languages.html .
1115        For details about languages, see http://www.ethnologue.com/ .  */
1116     switch (primary)
1117       {
1118       case LANG_AFRIKAANS: return "af_ZA";
1119       case LANG_ALBANIAN: return "sq_AL";
1120       case LANG_AMHARIC: return "am_ET";
1121       case LANG_ARABIC:
1122         switch (sub)
1123           {
1124           case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
1125           case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
1126           case SUBLANG_ARABIC_EGYPT: return "ar_EG";
1127           case SUBLANG_ARABIC_LIBYA: return "ar_LY";
1128           case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
1129           case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
1130           case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
1131           case SUBLANG_ARABIC_OMAN: return "ar_OM";
1132           case SUBLANG_ARABIC_YEMEN: return "ar_YE";
1133           case SUBLANG_ARABIC_SYRIA: return "ar_SY";
1134           case SUBLANG_ARABIC_JORDAN: return "ar_JO";
1135           case SUBLANG_ARABIC_LEBANON: return "ar_LB";
1136           case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
1137           case SUBLANG_ARABIC_UAE: return "ar_AE";
1138           case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
1139           case SUBLANG_ARABIC_QATAR: return "ar_QA";
1140           }
1141         return "ar";
1142       case LANG_ARMENIAN: return "hy_AM";
1143       case LANG_ASSAMESE: return "as_IN";
1144       case LANG_AZERI:
1145         switch (sub)
1146           {
1147           /* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
1148           case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
1149           case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
1150           }
1151         return "az";
1152       case LANG_BASQUE:
1153         switch (sub)
1154           {
1155           case SUBLANG_DEFAULT: return "eu_ES";
1156           }
1157         return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
1158       case LANG_BELARUSIAN: return "be_BY";
1159       case LANG_BENGALI:
1160         switch (sub)
1161           {
1162           case SUBLANG_BENGALI_INDIA: return "bn_IN";
1163           case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
1164           }
1165         return "bn";
1166       case LANG_BULGARIAN: return "bg_BG";
1167       case LANG_BURMESE: return "my_MM";
1168       case LANG_CAMBODIAN: return "km_KH";
1169       case LANG_CATALAN: return "ca_ES";
1170       case LANG_CHEROKEE: return "chr_US";
1171       case LANG_CHINESE:
1172         switch (sub)
1173           {
1174           case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
1175           case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
1176           case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
1177           case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
1178           case SUBLANG_CHINESE_MACAU: return "zh_MO";
1179           }
1180         return "zh";
1181       case LANG_CROATIAN:       /* LANG_CROATIAN == LANG_SERBIAN
1182                                  * What used to be called Serbo-Croatian
1183                                  * should really now be two separate
1184                                  * languages because of political reasons.
1185                                  * (Says tml, who knows nothing about Serbian
1186                                  * or Croatian.)
1187                                  * (I can feel those flames coming already.)
1188                                  */
1189         switch (sub)
1190           {
1191           case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
1192           case SUBLANG_SERBIAN_LATIN: return "sr_CS";
1193           case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
1194           case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
1195           case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA";
1196           case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
1197           }
1198         return "hr";
1199       case LANG_CZECH: return "cs_CZ";
1200       case LANG_DANISH: return "da_DK";
1201       case LANG_DIVEHI: return "dv_MV";
1202       case LANG_DUTCH:
1203         switch (sub)
1204           {
1205           case SUBLANG_DUTCH: return "nl_NL";
1206           case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
1207           }
1208         return "nl";
1209       case LANG_EDO: return "bin_NG";
1210       case LANG_ENGLISH:
1211         switch (sub)
1212           {
1213           /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1214            * English was the language spoken in England.
1215            * Oh well.
1216            */
1217           case SUBLANG_ENGLISH_US: return "en_US";
1218           case SUBLANG_ENGLISH_UK: return "en_GB";
1219           case SUBLANG_ENGLISH_AUS: return "en_AU";
1220           case SUBLANG_ENGLISH_CAN: return "en_CA";
1221           case SUBLANG_ENGLISH_NZ: return "en_NZ";
1222           case SUBLANG_ENGLISH_EIRE: return "en_IE";
1223           case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
1224           case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
1225           case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
1226           case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
1227           case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
1228           case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
1229           case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
1230           case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
1231           case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
1232           case SUBLANG_ENGLISH_INDIA: return "en_IN";
1233           case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
1234           case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
1235           }
1236         return "en";
1237       case LANG_ESTONIAN: return "et_EE";
1238       case LANG_FAEROESE: return "fo_FO";
1239       case LANG_FARSI: return "fa_IR";
1240       case LANG_FINNISH: return "fi_FI";
1241       case LANG_FRENCH:
1242         switch (sub)
1243           {
1244           case SUBLANG_FRENCH: return "fr_FR";
1245           case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
1246           case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
1247           case SUBLANG_FRENCH_SWISS: return "fr_CH";
1248           case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
1249           case SUBLANG_FRENCH_MONACO: return "fr_MC";
1250           case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
1251           case SUBLANG_FRENCH_REUNION: return "fr_RE";
1252           case SUBLANG_FRENCH_CONGO: return "fr_CG";
1253           case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
1254           case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
1255           case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
1256           case SUBLANG_FRENCH_MALI: return "fr_ML";
1257           case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
1258           case SUBLANG_FRENCH_HAITI: return "fr_HT";
1259           }
1260         return "fr";
1261       case LANG_FRISIAN: return "fy_NL";
1262       case LANG_FULFULDE:
1263         /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin.  */
1264         return "ff_NG";
1265       case LANG_GAELIC:
1266         switch (sub)
1267           {
1268           case 0x01: /* SCOTTISH */ return "gd_GB";
1269           case 0x02: /* IRISH */ return "ga_IE";
1270           }
1271         return "C";
1272       case LANG_GALICIAN: return "gl_ES";
1273       case LANG_GEORGIAN: return "ka_GE";
1274       case LANG_GERMAN:
1275         switch (sub)
1276           {
1277           case SUBLANG_GERMAN: return "de_DE";
1278           case SUBLANG_GERMAN_SWISS: return "de_CH";
1279           case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
1280           case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
1281           case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
1282           }
1283         return "de";
1284       case LANG_GREEK: return "el_GR";
1285       case LANG_GUARANI: return "gn_PY";
1286       case LANG_GUJARATI: return "gu_IN";
1287       case LANG_HAUSA: return "ha_NG";
1288       case LANG_HAWAIIAN:
1289         /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1290            or Hawaii Creole English ("cpe_US", 600000 speakers)?  */
1291         return "cpe_US";
1292       case LANG_HEBREW: return "he_IL";
1293       case LANG_HINDI: return "hi_IN";
1294       case LANG_HUNGARIAN: return "hu_HU";
1295       case LANG_IBIBIO: return "nic_NG";
1296       case LANG_ICELANDIC: return "is_IS";
1297       case LANG_IGBO: return "ig_NG";
1298       case LANG_INDONESIAN: return "id_ID";
1299       case LANG_INUKTITUT: return "iu_CA";
1300       case LANG_ITALIAN:
1301         switch (sub)
1302           {
1303           case SUBLANG_ITALIAN: return "it_IT";
1304           case SUBLANG_ITALIAN_SWISS: return "it_CH";
1305           }
1306         return "it";
1307       case LANG_JAPANESE: return "ja_JP";
1308       case LANG_KANNADA: return "kn_IN";
1309       case LANG_KANURI: return "kr_NG";
1310       case LANG_KASHMIRI:
1311         switch (sub)
1312           {
1313           case SUBLANG_DEFAULT: return "ks_PK";
1314           case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
1315           }
1316         return "ks";
1317       case LANG_KAZAK: return "kk_KZ";
1318       case LANG_KONKANI:
1319         /* FIXME: Adjust this when such locales appear on Unix.  */
1320         return "kok_IN";
1321       case LANG_KOREAN: return "ko_KR";
1322       case LANG_KYRGYZ: return "ky_KG";
1323       case LANG_LAO: return "lo_LA";
1324       case LANG_LATIN: return "la_VA";
1325       case LANG_LATVIAN: return "lv_LV";
1326       case LANG_LITHUANIAN: return "lt_LT";
1327       case LANG_MACEDONIAN: return "mk_MK";
1328       case LANG_MALAY:
1329         switch (sub)
1330           {
1331           case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
1332           case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
1333           }
1334         return "ms";
1335       case LANG_MALAYALAM: return "ml_IN";
1336       case LANG_MALTESE: return "mt_MT";
1337       case LANG_MANIPURI:
1338         /* FIXME: Adjust this when such locales appear on Unix.  */
1339         return "mni_IN";
1340       case LANG_MAORI: return "mi_NZ";
1341       case LANG_MARATHI: return "mr_IN";
1342       case LANG_MONGOLIAN:
1343         switch (sub)
1344           {
1345           case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: return "mn_MN";
1346           case SUBLANG_MONGOLIAN_PRC: return "mn_CN";
1347           }
1348         return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN".  */
1349       case LANG_NEPALI:
1350         switch (sub)
1351           {
1352           case SUBLANG_DEFAULT: return "ne_NP";
1353           case SUBLANG_NEPALI_INDIA: return "ne_IN";
1354           }
1355         return "ne";
1356       case LANG_NORWEGIAN:
1357         switch (sub)
1358           {
1359           case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
1360           case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
1361           }
1362         return "no";
1363       case LANG_ORIYA: return "or_IN";
1364       case LANG_OROMO: return "om_ET";
1365       case LANG_PAPIAMENTU: return "pap_AN";
1366       case LANG_PASHTO:
1367         return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF".  */
1368       case LANG_POLISH: return "pl_PL";
1369       case LANG_PORTUGUESE:
1370         switch (sub)
1371           {
1372           case SUBLANG_PORTUGUESE: return "pt_PT";
1373           /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
1374              Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
1375           case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
1376           }
1377         return "pt";
1378       case LANG_PUNJABI:
1379         switch (sub)
1380           {
1381           case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
1382           case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
1383           }
1384         return "pa";
1385       case LANG_QUECHUA:
1386         switch (sub)
1387           {
1388           case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
1389           case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
1390           case SUBLANG_QUECHUA_PERU: return "qu_PE";
1391           }
1392         return "qu";
1393       case LANG_RHAETO_ROMANCE: return "rm_CH";
1394       case LANG_ROMANIAN:
1395         switch (sub)
1396           {
1397           case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
1398           case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
1399           }
1400         return "ro";
1401       case LANG_RUSSIAN:
1402         switch (sub)
1403           {
1404           case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
1405           case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
1406           }
1407         return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD".  */
1408       case LANG_SAAMI: /* actually Northern Sami */ return "se_NO";
1409       case LANG_SANSKRIT: return "sa_IN";
1410       case LANG_SINDHI:
1411         switch (sub)
1412           {
1413           case SUBLANG_SINDHI_INDIA: return "sd_IN";
1414           case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
1415           /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
1416           }
1417         return "sd";
1418       case LANG_SINHALESE: return "si_LK";
1419       case LANG_SLOVAK: return "sk_SK";
1420       case LANG_SLOVENIAN: return "sl_SI";
1421       case LANG_SOMALI: return "so_SO";
1422       case LANG_SORBIAN:
1423         /* FIXME: Adjust this when such locales appear on Unix.  */
1424         return "wen_DE";
1425       case LANG_SOTHO:
1426         /* <http://www.microsoft.com/globaldev/reference/lcid-all.mspx> calls
1427            it "Sepedi"; according to
1428            <http://www.ethnologue.com/show_language.asp?code=nso>
1429            <http://www.ethnologue.com/show_language.asp?code=sot>
1430            it's the same as Northern Sotho.  */
1431         return "nso_ZA";
1432       case LANG_SPANISH:
1433         switch (sub)
1434           {
1435           case SUBLANG_SPANISH: return "es_ES";
1436           case SUBLANG_SPANISH_MEXICAN: return "es_MX";
1437           case SUBLANG_SPANISH_MODERN:
1438             return "es_ES@modern";      /* not seen on Unix */
1439           case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
1440           case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
1441           case SUBLANG_SPANISH_PANAMA: return "es_PA";
1442           case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
1443           case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
1444           case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
1445           case SUBLANG_SPANISH_PERU: return "es_PE";
1446           case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
1447           case SUBLANG_SPANISH_ECUADOR: return "es_EC";
1448           case SUBLANG_SPANISH_CHILE: return "es_CL";
1449           case SUBLANG_SPANISH_URUGUAY: return "es_UY";
1450           case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
1451           case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
1452           case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
1453           case SUBLANG_SPANISH_HONDURAS: return "es_HN";
1454           case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
1455           case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
1456           case SUBLANG_SPANISH_US: return "es_US";
1457           }
1458         return "es";
1459       case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
1460       case LANG_SWAHILI: return "sw_KE";
1461       case LANG_SWEDISH:
1462         switch (sub)
1463           {
1464           case SUBLANG_DEFAULT: return "sv_SE";
1465           case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
1466           }
1467         return "sv";
1468       case LANG_SYRIAC: return "syr_TR"; /* An extinct language.  */
1469       case LANG_TAGALOG: return "tl_PH";
1470       case LANG_TAJIK: return "tg_TJ";
1471       case LANG_TAMAZIGHT:
1472         switch (sub)
1473           {
1474           /* FIXME: Adjust this when Tamazight locales appear on Unix.  */
1475           case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
1476           case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
1477           }
1478         return "ber_MA";
1479       case LANG_TAMIL:
1480         switch (sub)
1481           {
1482           case SUBLANG_DEFAULT: return "ta_IN";
1483           }
1484         return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG".  */
1485       case LANG_TATAR: return "tt_RU";
1486       case LANG_TELUGU: return "te_IN";
1487       case LANG_THAI: return "th_TH";
1488       case LANG_TIBETAN:
1489         switch (sub)
1490           {
1491           case SUBLANG_TIBETAN_PRC:
1492             /* Most Tibetans would not like "bo_CN".  But Tibet does not yet
1493                have a country code of its own.  */
1494             return "bo";
1495           case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
1496           }
1497         return "bo";
1498       case LANG_TIGRINYA:
1499         switch (sub)
1500           {
1501           case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
1502           case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
1503           }
1504         return "ti";
1505       case LANG_TSONGA: return "ts_ZA";
1506       case LANG_TSWANA: return "tn_BW";
1507       case LANG_TURKISH: return "tr_TR";
1508       case LANG_TURKMEN: return "tk_TM";
1509       case LANG_UIGHUR:
1510         switch (sub)
1511           {
1512           case SUBLANG_UIGHUR_PRC: return "ug_CN";
1513           }
1514         return "ug";
1515       case LANG_UKRAINIAN: return "uk_UA";
1516       case LANG_URDU:
1517         switch (sub)
1518           {
1519           case SUBLANG_URDU_PAKISTAN: return "ur_PK";
1520           case SUBLANG_URDU_INDIA: return "ur_IN";
1521           }
1522         return "ur";
1523       case LANG_UZBEK:
1524         switch (sub)
1525           {
1526           case SUBLANG_UZBEK_LATIN: return "uz_UZ";
1527           case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
1528           }
1529         return "uz";
1530       case LANG_VENDA: return "ve_ZA";
1531       case LANG_VIETNAMESE: return "vi_VN";
1532       case LANG_WELSH: return "cy_GB";
1533       case LANG_XHOSA: return "xh_ZA";
1534       case LANG_YI: return "sit_CN";
1535       case LANG_YIDDISH: return "yi_IL";
1536       case LANG_YORUBA: return "yo_NG";
1537       case LANG_ZULU: return "zu_ZA";
1538       default: return "C";
1539       }
1540   }
1541 }
1542
1543 # if !defined IN_LIBINTL
1544 static
1545 # endif
1546 const char *
1547 gl_locale_name_from_win32_LCID (LCID lcid)
1548 {
1549   LANGID langid;
1550
1551   /* Strip off the sorting rules, keep only the language part.  */
1552   langid = LANGIDFROMLCID (lcid);
1553
1554   return gl_locale_name_from_win32_LANGID (langid);
1555 }
1556
1557 #endif
1558
1559
1560 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
1561    "Directs 'setlocale()' to query 'category' and return the current
1562     setting of 'local'."
1563    However it does not specify the exact format.  Neither do SUSV2 and
1564    ISO C 99.  So we can use this feature only on selected systems (e.g.
1565    those using GNU C Library).  */
1566 #if defined _LIBC || (defined __GLIBC__ && __GLIBC__ >= 2)
1567 # define HAVE_LOCALE_NULL
1568 #endif
1569
1570 /* Determine the current locale's name, and canonicalize it into XPG syntax
1571      language[_territory][.codeset][@modifier]
1572    The codeset part in the result is not reliable; the locale_charset()
1573    should be used for codeset information instead.
1574    The result must not be freed; it is statically allocated.  */
1575
1576 const char *
1577 gl_locale_name_posix (int category, const char *categoryname)
1578 {
1579   /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
1580      On some systems this can be done by the 'setlocale' function itself.  */
1581 #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
1582   return setlocale (category, NULL);
1583 #else
1584   const char *retval;
1585
1586   /* Setting of LC_ALL overrides all other.  */
1587   retval = getenv ("LC_ALL");
1588   if (retval != NULL && retval[0] != '\0')
1589     return retval;
1590   /* Next comes the name of the desired category.  */
1591   retval = getenv (categoryname);
1592   if (retval != NULL && retval[0] != '\0')
1593     return retval;
1594   /* Last possibility is the LANG environment variable.  */
1595   retval = getenv ("LANG");
1596   if (retval != NULL && retval[0] != '\0')
1597     return retval;
1598
1599   return NULL;
1600 #endif
1601 }
1602
1603 const char *
1604 gl_locale_name_default (void)
1605 {
1606   /* POSIX:2001 says:
1607      "All implementations shall define a locale as the default locale, to be
1608       invoked when no environment variables are set, or set to the empty
1609       string.  This default locale can be the POSIX locale or any other
1610       implementation-defined locale.  Some implementations may provide
1611       facilities for local installation administrators to set the default
1612       locale, customizing it for each location.  POSIX:2001 does not require
1613       such a facility.  */
1614
1615 #if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined(WIN32_NATIVE))
1616
1617   /* The system does not have a way of setting the locale, other than the
1618      POSIX specified environment variables.  We use C as default locale.  */
1619   return "C";
1620
1621 #else
1622
1623   /* Return an XPG style locale name language[_territory][@modifier].
1624      Don't even bother determining the codeset; it's not useful in this
1625      context, because message catalogs are not specific to a single
1626      codeset.  */
1627
1628 # if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
1629   /* MacOS X 10.2 or newer */
1630   {
1631     /* Cache the locale name, since CoreFoundation calls are expensive.  */
1632     static const char *cached_localename;
1633
1634     if (cached_localename == NULL)
1635       {
1636         char namebuf[256];
1637 #  if HAVE_CFLOCALECOPYCURRENT /* MacOS X 10.3 or newer */
1638         CFLocaleRef locale = CFLocaleCopyCurrent ();
1639         CFStringRef name = CFLocaleGetIdentifier (locale);
1640
1641         if (CFStringGetCString (name, namebuf, sizeof(namebuf),
1642                                 kCFStringEncodingASCII))
1643           {
1644             gl_locale_name_canonicalize (namebuf);
1645             cached_localename = strdup (namebuf);
1646           }
1647         CFRelease (locale);
1648 #  elif HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.2 or newer */
1649         CFTypeRef value =
1650           CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
1651                                      kCFPreferencesCurrentApplication);
1652         if (value != NULL
1653             && CFGetTypeID (value) == CFStringGetTypeID ()
1654             && CFStringGetCString ((CFStringRef)value, namebuf, sizeof(namebuf),
1655                                    kCFStringEncodingASCII))
1656           {
1657             gl_locale_name_canonicalize (namebuf);
1658             cached_localename = strdup (namebuf);
1659           }
1660 #  endif
1661         if (cached_localename == NULL)
1662           cached_localename = "C";
1663       }
1664     return cached_localename;
1665   }
1666
1667 # endif
1668
1669 # if defined(WIN32_NATIVE) /* WIN32, not Cygwin */
1670   {
1671     LCID lcid;
1672
1673     /* Use native Win32 API locale ID.  */
1674     lcid = GetThreadLocale ();
1675
1676     return gl_locale_name_from_win32_LCID (lcid);
1677   }
1678 # endif
1679 #endif
1680 }
1681
1682 const char *
1683 gl_locale_name (int category, const char *categoryname)
1684 {
1685   const char *retval;
1686
1687   retval = gl_locale_name_posix (category, categoryname);
1688   if (retval != NULL)
1689     return retval;
1690
1691   return gl_locale_name_default ();
1692 }