1 /* w32-gettext.h - A simple gettext implementation for Windows targets.
2 Copyright (C) 1995, 1996, 1997, 1999, 2005, 2007,
3 2008, 2010 Free Software Foundation, Inc.
5 This file is part of libgpg-error.
7 libgpg-error is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 libgpg-error is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #if !defined (_WIN32) && !defined (__CYGWIN32__)
25 # error This module may only be build for Windows or Cygwin32
33 #include <sys/types.h>
36 #ifndef HAVE_W32CE_SYSTEM
38 #endif /*HAVE_W32CE_SYSTEM*/
42 #include "libjnlib-config.h"
46 # define jnlib_malloc(a) malloc ((a))
47 # define jnlib_calloc(a,b) calloc ((a), (b))
48 # define jnlib_free(a) free ((a))
49 # define jnlib_xstrdup(a) not_used
50 #endif /*!jnlib_malloc*/
56 /* localname.c from gettext BEGIN. */
58 /* Determine the current selected locale.
59 Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
61 This program is free software; you can redistribute it and/or modify it
62 under the terms of the GNU Library General Public License as published
63 by the Free Software Foundation; either version 2, or (at your option)
66 This program is distributed in the hope that it will be useful,
67 but WITHOUT ANY WARRANTY; without even the implied warranty of
68 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
69 Library General Public License for more details.
71 You should have received a copy of the GNU Library General Public
72 License along with this program; if not, write to the Free Software
73 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
76 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
77 /* Win32 code written by Tor Lillqvist <tml@iki.fi>. */
78 /* Renamed _nl_locale_name, removed unsed args, removed include files,
79 non-W32 code and changed comments <wk@gnupg.org>. */
81 /* Mingw headers don't have latest language and sublanguage codes. */
82 #ifndef LANG_AFRIKAANS
83 #define LANG_AFRIKAANS 0x36
86 #define LANG_ALBANIAN 0x1c
89 #define LANG_AMHARIC 0x5e
92 #define LANG_ARABIC 0x01
95 #define LANG_ARMENIAN 0x2b
98 #define LANG_ASSAMESE 0x4d
101 #define LANG_AZERI 0x2c
104 #define LANG_BASQUE 0x2d
106 #ifndef LANG_BELARUSIAN
107 #define LANG_BELARUSIAN 0x23
110 #define LANG_BENGALI 0x45
113 #define LANG_BURMESE 0x55
115 #ifndef LANG_CAMBODIAN
116 #define LANG_CAMBODIAN 0x53
119 #define LANG_CATALAN 0x03
121 #ifndef LANG_CHEROKEE
122 #define LANG_CHEROKEE 0x5c
125 #define LANG_DIVEHI 0x65
128 #define LANG_EDO 0x66
130 #ifndef LANG_ESTONIAN
131 #define LANG_ESTONIAN 0x25
133 #ifndef LANG_FAEROESE
134 #define LANG_FAEROESE 0x38
137 #define LANG_FARSI 0x29
140 #define LANG_FRISIAN 0x62
142 #ifndef LANG_FULFULDE
143 #define LANG_FULFULDE 0x67
146 #define LANG_GAELIC 0x3c
148 #ifndef LANG_GALICIAN
149 #define LANG_GALICIAN 0x56
151 #ifndef LANG_GEORGIAN
152 #define LANG_GEORGIAN 0x37
155 #define LANG_GUARANI 0x74
157 #ifndef LANG_GUJARATI
158 #define LANG_GUJARATI 0x47
161 #define LANG_HAUSA 0x68
163 #ifndef LANG_HAWAIIAN
164 #define LANG_HAWAIIAN 0x75
167 #define LANG_HEBREW 0x0d
170 #define LANG_HINDI 0x39
173 #define LANG_IBIBIO 0x69
176 #define LANG_IGBO 0x70
178 #ifndef LANG_INDONESIAN
179 #define LANG_INDONESIAN 0x21
181 #ifndef LANG_INUKTITUT
182 #define LANG_INUKTITUT 0x5d
185 #define LANG_KANNADA 0x4b
188 #define LANG_KANURI 0x71
190 #ifndef LANG_KASHMIRI
191 #define LANG_KASHMIRI 0x60
194 #define LANG_KAZAK 0x3f
197 #define LANG_KONKANI 0x57
200 #define LANG_KYRGYZ 0x40
203 #define LANG_LAO 0x54
206 #define LANG_LATIN 0x76
209 #define LANG_LATVIAN 0x26
211 #ifndef LANG_LITHUANIAN
212 #define LANG_LITHUANIAN 0x27
214 #ifndef LANG_MACEDONIAN
215 #define LANG_MACEDONIAN 0x2f
218 #define LANG_MALAY 0x3e
220 #ifndef LANG_MALAYALAM
221 #define LANG_MALAYALAM 0x4c
224 #define LANG_MALTESE 0x3a
226 #ifndef LANG_MANIPURI
227 #define LANG_MANIPURI 0x58
230 #define LANG_MARATHI 0x4e
232 #ifndef LANG_MONGOLIAN
233 #define LANG_MONGOLIAN 0x50
236 #define LANG_NEPALI 0x61
239 #define LANG_ORIYA 0x48
242 #define LANG_OROMO 0x72
244 #ifndef LANG_PAPIAMENTU
245 #define LANG_PAPIAMENTU 0x79
248 #define LANG_PASHTO 0x63
251 #define LANG_PUNJABI 0x46
253 #ifndef LANG_RHAETO_ROMANCE
254 #define LANG_RHAETO_ROMANCE 0x17
257 #define LANG_SAAMI 0x3b
259 #ifndef LANG_SANSKRIT
260 #define LANG_SANSKRIT 0x4f
263 #define LANG_SERBIAN 0x1a
266 #define LANG_SINDHI 0x59
268 #ifndef LANG_SINHALESE
269 #define LANG_SINHALESE 0x5b
272 #define LANG_SLOVAK 0x1b
275 #define LANG_SOMALI 0x77
278 #define LANG_SORBIAN 0x2e
281 #define LANG_SUTU 0x30
284 #define LANG_SWAHILI 0x41
287 #define LANG_SYRIAC 0x5a
290 #define LANG_TAGALOG 0x64
293 #define LANG_TAJIK 0x28
295 #ifndef LANG_TAMAZIGHT
296 #define LANG_TAMAZIGHT 0x5f
299 #define LANG_TAMIL 0x49
302 #define LANG_TATAR 0x44
305 #define LANG_TELUGU 0x4a
308 #define LANG_THAI 0x1e
311 #define LANG_TIBETAN 0x51
313 #ifndef LANG_TIGRINYA
314 #define LANG_TIGRINYA 0x73
317 #define LANG_TSONGA 0x31
320 #define LANG_TSWANA 0x32
323 #define LANG_TURKMEN 0x42
325 #ifndef LANG_UKRAINIAN
326 #define LANG_UKRAINIAN 0x22
329 #define LANG_URDU 0x20
332 #define LANG_UZBEK 0x43
335 #define LANG_VENDA 0x33
337 #ifndef LANG_VIETNAMESE
338 #define LANG_VIETNAMESE 0x2a
341 #define LANG_WELSH 0x52
344 #define LANG_XHOSA 0x34
350 #define LANG_YIDDISH 0x3d
353 #define LANG_YORUBA 0x6a
356 #define LANG_ZULU 0x35
358 #ifndef SUBLANG_ARABIC_SAUDI_ARABIA
359 #define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
361 #ifndef SUBLANG_ARABIC_IRAQ
362 #define SUBLANG_ARABIC_IRAQ 0x02
364 #ifndef SUBLANG_ARABIC_EGYPT
365 #define SUBLANG_ARABIC_EGYPT 0x03
367 #ifndef SUBLANG_ARABIC_LIBYA
368 #define SUBLANG_ARABIC_LIBYA 0x04
370 #ifndef SUBLANG_ARABIC_ALGERIA
371 #define SUBLANG_ARABIC_ALGERIA 0x05
373 #ifndef SUBLANG_ARABIC_MOROCCO
374 #define SUBLANG_ARABIC_MOROCCO 0x06
376 #ifndef SUBLANG_ARABIC_TUNISIA
377 #define SUBLANG_ARABIC_TUNISIA 0x07
379 #ifndef SUBLANG_ARABIC_OMAN
380 #define SUBLANG_ARABIC_OMAN 0x08
382 #ifndef SUBLANG_ARABIC_YEMEN
383 #define SUBLANG_ARABIC_YEMEN 0x09
385 #ifndef SUBLANG_ARABIC_SYRIA
386 #define SUBLANG_ARABIC_SYRIA 0x0a
388 #ifndef SUBLANG_ARABIC_JORDAN
389 #define SUBLANG_ARABIC_JORDAN 0x0b
391 #ifndef SUBLANG_ARABIC_LEBANON
392 #define SUBLANG_ARABIC_LEBANON 0x0c
394 #ifndef SUBLANG_ARABIC_KUWAIT
395 #define SUBLANG_ARABIC_KUWAIT 0x0d
397 #ifndef SUBLANG_ARABIC_UAE
398 #define SUBLANG_ARABIC_UAE 0x0e
400 #ifndef SUBLANG_ARABIC_BAHRAIN
401 #define SUBLANG_ARABIC_BAHRAIN 0x0f
403 #ifndef SUBLANG_ARABIC_QATAR
404 #define SUBLANG_ARABIC_QATAR 0x10
406 #ifndef SUBLANG_AZERI_LATIN
407 #define SUBLANG_AZERI_LATIN 0x01
409 #ifndef SUBLANG_AZERI_CYRILLIC
410 #define SUBLANG_AZERI_CYRILLIC 0x02
412 #ifndef SUBLANG_BENGALI_INDIA
413 #define SUBLANG_BENGALI_INDIA 0x01
415 #ifndef SUBLANG_BENGALI_BANGLADESH
416 #define SUBLANG_BENGALI_BANGLADESH 0x02
418 #ifndef SUBLANG_CHINESE_MACAU
419 #define SUBLANG_CHINESE_MACAU 0x05
421 #ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
422 #define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
424 #ifndef SUBLANG_ENGLISH_JAMAICA
425 #define SUBLANG_ENGLISH_JAMAICA 0x08
427 #ifndef SUBLANG_ENGLISH_CARIBBEAN
428 #define SUBLANG_ENGLISH_CARIBBEAN 0x09
430 #ifndef SUBLANG_ENGLISH_BELIZE
431 #define SUBLANG_ENGLISH_BELIZE 0x0a
433 #ifndef SUBLANG_ENGLISH_TRINIDAD
434 #define SUBLANG_ENGLISH_TRINIDAD 0x0b
436 #ifndef SUBLANG_ENGLISH_ZIMBABWE
437 #define SUBLANG_ENGLISH_ZIMBABWE 0x0c
439 #ifndef SUBLANG_ENGLISH_PHILIPPINES
440 #define SUBLANG_ENGLISH_PHILIPPINES 0x0d
442 #ifndef SUBLANG_ENGLISH_INDONESIA
443 #define SUBLANG_ENGLISH_INDONESIA 0x0e
445 #ifndef SUBLANG_ENGLISH_HONGKONG
446 #define SUBLANG_ENGLISH_HONGKONG 0x0f
448 #ifndef SUBLANG_ENGLISH_INDIA
449 #define SUBLANG_ENGLISH_INDIA 0x10
451 #ifndef SUBLANG_ENGLISH_MALAYSIA
452 #define SUBLANG_ENGLISH_MALAYSIA 0x11
454 #ifndef SUBLANG_ENGLISH_SINGAPORE
455 #define SUBLANG_ENGLISH_SINGAPORE 0x12
457 #ifndef SUBLANG_FRENCH_LUXEMBOURG
458 #define SUBLANG_FRENCH_LUXEMBOURG 0x05
460 #ifndef SUBLANG_FRENCH_MONACO
461 #define SUBLANG_FRENCH_MONACO 0x06
463 #ifndef SUBLANG_FRENCH_WESTINDIES
464 #define SUBLANG_FRENCH_WESTINDIES 0x07
466 #ifndef SUBLANG_FRENCH_REUNION
467 #define SUBLANG_FRENCH_REUNION 0x08
469 #ifndef SUBLANG_FRENCH_CONGO
470 #define SUBLANG_FRENCH_CONGO 0x09
472 #ifndef SUBLANG_FRENCH_SENEGAL
473 #define SUBLANG_FRENCH_SENEGAL 0x0a
475 #ifndef SUBLANG_FRENCH_CAMEROON
476 #define SUBLANG_FRENCH_CAMEROON 0x0b
478 #ifndef SUBLANG_FRENCH_COTEDIVOIRE
479 #define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
481 #ifndef SUBLANG_FRENCH_MALI
482 #define SUBLANG_FRENCH_MALI 0x0d
484 #ifndef SUBLANG_FRENCH_MOROCCO
485 #define SUBLANG_FRENCH_MOROCCO 0x0e
487 #ifndef SUBLANG_FRENCH_HAITI
488 #define SUBLANG_FRENCH_HAITI 0x0f
490 #ifndef SUBLANG_GERMAN_LUXEMBOURG
491 #define SUBLANG_GERMAN_LUXEMBOURG 0x04
493 #ifndef SUBLANG_GERMAN_LIECHTENSTEIN
494 #define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
496 #ifndef SUBLANG_KASHMIRI_INDIA
497 #define SUBLANG_KASHMIRI_INDIA 0x02
499 #ifndef SUBLANG_MALAY_MALAYSIA
500 #define SUBLANG_MALAY_MALAYSIA 0x01
502 #ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
503 #define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
505 #ifndef SUBLANG_NEPALI_INDIA
506 #define SUBLANG_NEPALI_INDIA 0x02
508 #ifndef SUBLANG_PUNJABI_INDIA
509 #define SUBLANG_PUNJABI_INDIA 0x01
511 #ifndef SUBLANG_ROMANIAN_ROMANIA
512 #define SUBLANG_ROMANIAN_ROMANIA 0x01
514 #ifndef SUBLANG_SERBIAN_LATIN
515 #define SUBLANG_SERBIAN_LATIN 0x02
517 #ifndef SUBLANG_SERBIAN_CYRILLIC
518 #define SUBLANG_SERBIAN_CYRILLIC 0x03
520 #ifndef SUBLANG_SINDHI_INDIA
521 #define SUBLANG_SINDHI_INDIA 0x00
523 #ifndef SUBLANG_SINDHI_PAKISTAN
524 #define SUBLANG_SINDHI_PAKISTAN 0x01
526 #ifndef SUBLANG_SPANISH_GUATEMALA
527 #define SUBLANG_SPANISH_GUATEMALA 0x04
529 #ifndef SUBLANG_SPANISH_COSTA_RICA
530 #define SUBLANG_SPANISH_COSTA_RICA 0x05
532 #ifndef SUBLANG_SPANISH_PANAMA
533 #define SUBLANG_SPANISH_PANAMA 0x06
535 #ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
536 #define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
538 #ifndef SUBLANG_SPANISH_VENEZUELA
539 #define SUBLANG_SPANISH_VENEZUELA 0x08
541 #ifndef SUBLANG_SPANISH_COLOMBIA
542 #define SUBLANG_SPANISH_COLOMBIA 0x09
544 #ifndef SUBLANG_SPANISH_PERU
545 #define SUBLANG_SPANISH_PERU 0x0a
547 #ifndef SUBLANG_SPANISH_ARGENTINA
548 #define SUBLANG_SPANISH_ARGENTINA 0x0b
550 #ifndef SUBLANG_SPANISH_ECUADOR
551 #define SUBLANG_SPANISH_ECUADOR 0x0c
553 #ifndef SUBLANG_SPANISH_CHILE
554 #define SUBLANG_SPANISH_CHILE 0x0d
556 #ifndef SUBLANG_SPANISH_URUGUAY
557 #define SUBLANG_SPANISH_URUGUAY 0x0e
559 #ifndef SUBLANG_SPANISH_PARAGUAY
560 #define SUBLANG_SPANISH_PARAGUAY 0x0f
562 #ifndef SUBLANG_SPANISH_BOLIVIA
563 #define SUBLANG_SPANISH_BOLIVIA 0x10
565 #ifndef SUBLANG_SPANISH_EL_SALVADOR
566 #define SUBLANG_SPANISH_EL_SALVADOR 0x11
568 #ifndef SUBLANG_SPANISH_HONDURAS
569 #define SUBLANG_SPANISH_HONDURAS 0x12
571 #ifndef SUBLANG_SPANISH_NICARAGUA
572 #define SUBLANG_SPANISH_NICARAGUA 0x13
574 #ifndef SUBLANG_SPANISH_PUERTO_RICO
575 #define SUBLANG_SPANISH_PUERTO_RICO 0x14
577 #ifndef SUBLANG_SWEDISH_FINLAND
578 #define SUBLANG_SWEDISH_FINLAND 0x02
580 #ifndef SUBLANG_TAMAZIGHT_ARABIC
581 #define SUBLANG_TAMAZIGHT_ARABIC 0x01
583 #ifndef SUBLANG_TAMAZIGHT_LATIN
584 #define SUBLANG_TAMAZIGHT_LATIN 0x02
586 #ifndef SUBLANG_TIGRINYA_ETHIOPIA
587 #define SUBLANG_TIGRINYA_ETHIOPIA 0x00
589 #ifndef SUBLANG_TIGRINYA_ERITREA
590 #define SUBLANG_TIGRINYA_ERITREA 0x01
592 #ifndef SUBLANG_URDU_PAKISTAN
593 #define SUBLANG_URDU_PAKISTAN 0x01
595 #ifndef SUBLANG_URDU_INDIA
596 #define SUBLANG_URDU_INDIA 0x02
598 #ifndef SUBLANG_UZBEK_LATIN
599 #define SUBLANG_UZBEK_LATIN 0x01
601 #ifndef SUBLANG_UZBEK_CYRILLIC
602 #define SUBLANG_UZBEK_CYRILLIC 0x02
605 /* Return an XPG style locale name
606 language[_territory[.codeset]][@modifier].
607 Don't even bother determining the codeset; it's not useful in this
608 context, because message catalogs are not specific to a single
609 codeset. The result must not be freed; it is statically
612 my_nl_locale_name (const char *categoryname)
619 /* Let the user override the system settings through environment
620 variables, as on POSIX systems. */
621 #ifndef HAVE_W32CE_SYSTEM
622 retval = getenv ("LC_ALL");
623 if (retval != NULL && retval[0] != '\0')
625 retval = getenv (categoryname);
626 if (retval != NULL && retval[0] != '\0')
628 retval = getenv ("LANG");
629 if (retval != NULL && retval[0] != '\0')
631 #endif /*!HAVE_W32CE_SYSTEM*/
633 /* Use native Win32 API locale ID. */
634 #ifdef HAVE_W32CE_SYSTEM
635 lcid = GetSystemDefaultLCID ();
637 lcid = GetThreadLocale ();
640 /* Strip off the sorting rules, keep only the language part. */
641 langid = LANGIDFROMLCID (lcid);
643 /* Split into language and territory part. */
644 primary = PRIMARYLANGID (langid);
645 sub = SUBLANGID (langid);
647 /* Dispatch on language.
648 See also http://www.unicode.org/unicode/onlinedat/languages.html .
649 For details about languages, see http://www.ethnologue.com/ . */
652 case LANG_AFRIKAANS: return "af_ZA";
653 case LANG_ALBANIAN: return "sq_AL";
654 case LANG_AMHARIC: return "am_ET";
658 case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
659 case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
660 case SUBLANG_ARABIC_EGYPT: return "ar_EG";
661 case SUBLANG_ARABIC_LIBYA: return "ar_LY";
662 case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
663 case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
664 case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
665 case SUBLANG_ARABIC_OMAN: return "ar_OM";
666 case SUBLANG_ARABIC_YEMEN: return "ar_YE";
667 case SUBLANG_ARABIC_SYRIA: return "ar_SY";
668 case SUBLANG_ARABIC_JORDAN: return "ar_JO";
669 case SUBLANG_ARABIC_LEBANON: return "ar_LB";
670 case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
671 case SUBLANG_ARABIC_UAE: return "ar_AE";
672 case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
673 case SUBLANG_ARABIC_QATAR: return "ar_QA";
676 case LANG_ARMENIAN: return "hy_AM";
677 case LANG_ASSAMESE: return "as_IN";
681 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
682 case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
683 case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
687 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
688 case LANG_BELARUSIAN: return "be_BY";
692 case SUBLANG_BENGALI_INDIA: return "bn_IN";
693 case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
696 case LANG_BULGARIAN: return "bg_BG";
697 case LANG_BURMESE: return "my_MM";
698 case LANG_CAMBODIAN: return "km_KH";
699 case LANG_CATALAN: return "ca_ES";
700 case LANG_CHEROKEE: return "chr_US";
704 case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
705 case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
706 case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
707 case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
708 case SUBLANG_CHINESE_MACAU: return "zh_MO";
711 case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN
712 * What used to be called Serbo-Croatian
713 * should really now be two separate
714 * languages because of political reasons.
715 * (Says tml, who knows nothing about Serbian
717 * (I can feel those flames coming already.)
721 case SUBLANG_DEFAULT: return "hr_HR";
722 case SUBLANG_SERBIAN_LATIN: return "sr_CS";
723 case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
726 case LANG_CZECH: return "cs_CZ";
727 case LANG_DANISH: return "da_DK";
728 case LANG_DIVEHI: return "div_MV";
732 case SUBLANG_DUTCH: return "nl_NL";
733 case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
736 case LANG_EDO: return "bin_NG";
740 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
741 * English was the language spoken in England.
744 case SUBLANG_ENGLISH_US: return "en_US";
745 case SUBLANG_ENGLISH_UK: return "en_GB";
746 case SUBLANG_ENGLISH_AUS: return "en_AU";
747 case SUBLANG_ENGLISH_CAN: return "en_CA";
748 case SUBLANG_ENGLISH_NZ: return "en_NZ";
749 case SUBLANG_ENGLISH_EIRE: return "en_IE";
750 case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
751 case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
752 case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
753 case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
754 case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
755 case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
756 case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
757 case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
758 case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
759 case SUBLANG_ENGLISH_INDIA: return "en_IN";
760 case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
761 case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
764 case LANG_ESTONIAN: return "et_EE";
765 case LANG_FAEROESE: return "fo_FO";
766 case LANG_FARSI: return "fa_IR";
767 case LANG_FINNISH: return "fi_FI";
771 case SUBLANG_FRENCH: return "fr_FR";
772 case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
773 case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
774 case SUBLANG_FRENCH_SWISS: return "fr_CH";
775 case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
776 case SUBLANG_FRENCH_MONACO: return "fr_MC";
777 case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
778 case SUBLANG_FRENCH_REUNION: return "fr_RE";
779 case SUBLANG_FRENCH_CONGO: return "fr_CG";
780 case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
781 case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
782 case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
783 case SUBLANG_FRENCH_MALI: return "fr_ML";
784 case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
785 case SUBLANG_FRENCH_HAITI: return "fr_HT";
788 case LANG_FRISIAN: return "fy_NL";
789 case LANG_FULFULDE: return "ful_NG";
793 case 0x01: /* SCOTTISH */ return "gd_GB";
794 case 0x02: /* IRISH */ return "ga_IE";
797 case LANG_GALICIAN: return "gl_ES";
798 case LANG_GEORGIAN: return "ka_GE";
802 case SUBLANG_GERMAN: return "de_DE";
803 case SUBLANG_GERMAN_SWISS: return "de_CH";
804 case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
805 case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
806 case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
809 case LANG_GREEK: return "el_GR";
810 case LANG_GUARANI: return "gn_PY";
811 case LANG_GUJARATI: return "gu_IN";
812 case LANG_HAUSA: return "ha_NG";
814 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
815 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
817 case LANG_HEBREW: return "he_IL";
818 case LANG_HINDI: return "hi_IN";
819 case LANG_HUNGARIAN: return "hu_HU";
820 case LANG_IBIBIO: return "nic_NG";
821 case LANG_ICELANDIC: return "is_IS";
822 case LANG_IGBO: return "ibo_NG";
823 case LANG_INDONESIAN: return "id_ID";
824 case LANG_INUKTITUT: return "iu_CA";
828 case SUBLANG_ITALIAN: return "it_IT";
829 case SUBLANG_ITALIAN_SWISS: return "it_CH";
832 case LANG_JAPANESE: return "ja_JP";
833 case LANG_KANNADA: return "kn_IN";
834 case LANG_KANURI: return "kau_NG";
838 case SUBLANG_DEFAULT: return "ks_PK";
839 case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
842 case LANG_KAZAK: return "kk_KZ";
844 /* FIXME: Adjust this when such locales appear on Unix. */
846 case LANG_KOREAN: return "ko_KR";
847 case LANG_KYRGYZ: return "ky_KG";
848 case LANG_LAO: return "lo_LA";
849 case LANG_LATIN: return "la_VA";
850 case LANG_LATVIAN: return "lv_LV";
851 case LANG_LITHUANIAN: return "lt_LT";
852 case LANG_MACEDONIAN: return "mk_MK";
856 case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
857 case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
860 case LANG_MALAYALAM: return "ml_IN";
861 case LANG_MALTESE: return "mt_MT";
863 /* FIXME: Adjust this when such locales appear on Unix. */
865 case LANG_MARATHI: return "mr_IN";
867 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
871 case SUBLANG_DEFAULT: return "ne_NP";
872 case SUBLANG_NEPALI_INDIA: return "ne_IN";
878 case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
879 case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
882 case LANG_ORIYA: return "or_IN";
883 case LANG_OROMO: return "om_ET";
884 case LANG_PAPIAMENTU: return "pap_AN";
886 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
887 case LANG_POLISH: return "pl_PL";
888 case LANG_PORTUGUESE:
891 case SUBLANG_PORTUGUESE: return "pt_PT";
892 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
893 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
894 case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
900 case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
903 case LANG_RHAETO_ROMANCE: return "rm_CH";
907 case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
911 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
912 case LANG_SAAMI: /* actually Northern Sami */ return "se_NO";
913 case LANG_SANSKRIT: return "sa_IN";
917 case SUBLANG_SINDHI_INDIA: return "sd_IN";
918 case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
921 case LANG_SINHALESE: return "si_LK";
922 case LANG_SLOVAK: return "sk_SK";
923 case LANG_SLOVENIAN: return "sl_SI";
924 case LANG_SOMALI: return "so_SO";
926 /* FIXME: Adjust this when such locales appear on Unix. */
931 case SUBLANG_SPANISH: return "es_ES";
932 case SUBLANG_SPANISH_MEXICAN: return "es_MX";
933 case SUBLANG_SPANISH_MODERN:
934 return "es_ES@modern"; /* not seen on Unix */
935 case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
936 case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
937 case SUBLANG_SPANISH_PANAMA: return "es_PA";
938 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
939 case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
940 case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
941 case SUBLANG_SPANISH_PERU: return "es_PE";
942 case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
943 case SUBLANG_SPANISH_ECUADOR: return "es_EC";
944 case SUBLANG_SPANISH_CHILE: return "es_CL";
945 case SUBLANG_SPANISH_URUGUAY: return "es_UY";
946 case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
947 case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
948 case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
949 case SUBLANG_SPANISH_HONDURAS: return "es_HN";
950 case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
951 case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
954 case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
955 case LANG_SWAHILI: return "sw_KE";
959 case SUBLANG_DEFAULT: return "sv_SE";
960 case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
963 case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */
964 case LANG_TAGALOG: return "tl_PH";
965 case LANG_TAJIK: return "tg_TJ";
969 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
970 case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
971 case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin";
975 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
976 case LANG_TATAR: return "tt_RU";
977 case LANG_TELUGU: return "te_IN";
978 case LANG_THAI: return "th_TH";
979 case LANG_TIBETAN: return "bo_CN";
983 case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
984 case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
987 case LANG_TSONGA: return "ts_ZA";
988 case LANG_TSWANA: return "tn_BW";
989 case LANG_TURKISH: return "tr_TR";
990 case LANG_TURKMEN: return "tk_TM";
991 case LANG_UKRAINIAN: return "uk_UA";
995 case SUBLANG_URDU_PAKISTAN: return "ur_PK";
996 case SUBLANG_URDU_INDIA: return "ur_IN";
1002 case SUBLANG_UZBEK_LATIN: return "uz_UZ";
1003 case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
1007 /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
1009 http://www.loc.gov/standards/iso639-2/englangn.html has it, but
1010 http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't, */
1011 return "ven_ZA"; /* or "ve_ZA"? */
1012 case LANG_VIETNAMESE: return "vi_VN";
1013 case LANG_WELSH: return "cy_GB";
1014 case LANG_XHOSA: return "xh_ZA";
1015 case LANG_YI: return "sit_CN";
1016 case LANG_YIDDISH: return "yi_IL";
1017 case LANG_YORUBA: return "yo_NG";
1018 case LANG_ZULU: return "zu_ZA";
1019 default: return "C";
1023 /* localname.c from gettext END. */
1027 /* Support functions. */
1029 static __inline__ uint32_t
1030 do_swap_u32 (uint32_t i)
1032 return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
1035 #define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data))
1038 /* We assume to have `unsigned long int' value with at least 32 bits. */
1039 #define HASHWORDBITS 32
1041 /* The so called `hashpjw' function by P.J. Weinberger
1042 [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1043 1986, 1987 Bell Telephone Laboratories, Inc.] */
1044 static __inline__ unsigned long
1045 hash_string( const char *str_param )
1047 unsigned long int hval, g;
1048 const char *str = str_param;
1051 while (*str != '\0')
1054 hval += (unsigned long int) *str++;
1055 g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
1058 hval ^= g >> (HASHWORDBITS - 8);
1066 /* Generic message catalog and gettext stuff. */
1068 /* The magic number of the GNU message catalog format. */
1069 #define MAGIC 0x950412de
1070 #define MAGIC_SWAPPED 0xde120495
1072 /* Revision number of the currently used .mo (binary) file format. */
1073 #define MO_REVISION_NUMBER 0
1076 /* Header for binary .mo file format. */
1077 struct mo_file_header
1079 /* The magic number. */
1081 /* The revision number of the file format. */
1083 /* The number of strings pairs. */
1085 /* Offset of table with start offsets of original strings. */
1086 uint32_t orig_tab_offset;
1087 /* Offset of table with start offsets of translation strings. */
1088 uint32_t trans_tab_offset;
1089 /* Size of hashing table. */
1090 uint32_t hash_tab_size;
1091 /* Offset of first hashing entry. */
1092 uint32_t hash_tab_offset;
1098 /* Length of addressed string. */
1100 /* Offset of string in file. */
1105 struct overflow_space_s
1107 struct overflow_space_s *next;
1113 struct loaded_domain
1116 char *data_native; /* Data mapped to the native version of the
1117 string. (Allocated along with DATA). */
1119 uint16_t nstrings; /* Number of strings. */
1120 uint16_t *mapped; /* Array of mapping indicators:
1121 0 := Not mapped (original utf8).
1122 1 := Mapped to native encoding in overflow space.
1123 >=2 := Mapped to native encoding. The value
1124 gives the length of the mapped string.
1125 Because the terminating nul is included
1126 in the length and an empty string is
1127 not allowed, values are always > 1. */
1128 struct overflow_space_s *overflow_space;
1129 struct string_desc *orig_tab;
1130 struct string_desc *trans_tab;
1136 /* The list of domains we we are aware of. This list is protected by
1137 the criticla section DOMAINLIST_ACCESS_CS. */
1138 static struct domainlist_s *domainlist;
1140 /* A critical section to guard access to the domainlist. */
1141 static CRITICAL_SECTION domainlist_access_cs;
1143 /* The name of the current domain. This is a malloced string. This
1144 is a gobal variable which is not thread-safe. */
1145 static char *current_domainname;
1149 /* Constructor for this module. This can only be used if we are a
1150 DLL. IF used as a static lib we can't control the process set; for
1151 example it might be used with a main module which is not build with
1152 mingw and thus does not know how to call the constructors. */
1154 static void module_init (void) __attribute__ ((__constructor__));
1159 static int init_done;
1163 InitializeCriticalSection (&domainlist_access_cs);
1170 _gpg_w32__init_gettext_module (void)
1177 /* Free the domain data. */
1179 free_domain (struct loaded_domain *domain)
1181 struct overflow_space_s *os, *os2;
1183 jnlib_free (domain->data);
1184 jnlib_free (domain->mapped);
1185 for (os = domain->overflow_space; os; os = os2)
1190 jnlib_free (domain);
1194 static struct loaded_domain *
1195 load_domain (const char *filename)
1200 struct mo_file_header *data = NULL;
1201 struct loaded_domain *domain = NULL;
1205 fp = fopen (filename, "rb");
1210 if (fstat (fileno (fp), &st)
1211 || (size = (size_t) st.st_size) != st.st_size
1212 || size < sizeof (struct mo_file_header))
1218 data = (2*size <= size)? NULL : jnlib_malloc (2*size);
1226 read_ptr = (char *) data;
1229 long int nb = fread (read_ptr, 1, to_read, fp);
1239 while (to_read > 0);
1242 /* Using the magic number we can test whether it really is a message
1244 if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
1246 /* The magic number is wrong: not a message catalog file. */
1251 domain = jnlib_calloc (1, sizeof *domain);
1257 domain->data = (char *) data;
1258 domain->data_native = (char *) data + size;
1259 domain->must_swap = data->magic != MAGIC;
1261 /* Fill in the information about the available tables. */
1262 switch (SWAPIT (domain->must_swap, data->revision))
1264 case MO_REVISION_NUMBER:
1268 /* Because we use 16 bit values for the mapping array, we
1269 can't support more that 65534 strings (65535 would be okay,
1270 but it is often used as a special value). A PO file with
1271 that many translations is very unlikely given that GnuPG
1272 with its very large number of strings has only about 1600
1273 strings + variants. */
1274 nstrings = SWAPIT (domain->must_swap, data->nstrings);
1275 if (nstrings > 65534)
1277 domain->nstrings = nstrings;
1278 domain->orig_tab = (struct string_desc *)
1279 ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset));
1280 domain->trans_tab = (struct string_desc *)
1281 ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset));
1282 domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size);
1283 domain->hash_tab = (uint32_t *)
1284 ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset));
1288 default: /* This is an invalid revision. */
1292 /* Allocate an array to keep track of code page mappings. */
1293 domain->mapped = jnlib_calloc (domain->nstrings, sizeof *domain->mapped);
1295 return domain; /* Okay. */
1299 jnlib_free (domain);
1304 /* Return a malloced wide char string from an UTF-8 encoded input
1305 string STRING. Caller must free this value. On failure returns
1306 NULL. The result of calling this function with STRING set to NULL
1309 utf8_to_wchar (const char *string, size_t length, size_t *retlen)
1315 n = MultiByteToWideChar (CP_UTF8, 0, string, length, NULL, 0);
1316 if (n < 0 || (n+1) <= 0)
1319 nbytes = (size_t)(n+1) * sizeof(*result);
1320 if (nbytes / sizeof(*result) != (n+1))
1322 gpg_err_set_errno (ENOMEM);
1325 result = jnlib_malloc (nbytes);
1329 n = MultiByteToWideChar (CP_UTF8, 0, string, length, result, n);
1332 jnlib_free (result);
1340 /* Return a malloced string encoded in UTF-8 from the wide char input
1341 string STRING. Caller must free this value. On failure returns
1342 NULL. The result of calling this function with STRING set to NULL
1345 wchar_to_native (const wchar_t *string, size_t length, size_t *retlen)
1350 n = WideCharToMultiByte (CP_ACP, 0, string, length, NULL, 0, NULL, NULL);
1351 if (n < 0 || (n+1) <= 0)
1354 result = jnlib_malloc (n+1);
1358 n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL);
1361 jnlib_free (result);
1369 /* Convert UTF8 to the native codepage. Caller must free the return value. */
1371 utf8_to_native (const char *string, size_t length, size_t *retlen)
1377 wstring = utf8_to_wchar (string, length, &newlen);
1380 result = wchar_to_native (wstring, newlen, &newlen);
1381 jnlib_free (wstring);
1385 *retlen = result? newlen : 0;
1392 /* Specify that the DOMAINNAME message catalog will be found
1393 in DIRNAME rather than in the system locale data base. */
1395 _gpg_w32_bindtextdomain (const char *domainname, const char *dirname)
1397 const char *catval_full;
1400 const char *retvalue;
1404 struct domainlist_s *dl;
1407 EnterCriticalSection (&domainlist_access_cs);
1409 for (dl = domainlist; dl; dl = dl->next)
1410 if (!strcmp (dl->name, domainname))
1412 retvalue = dl->dname;
1416 LeaveCriticalSection (&domainlist_access_cs);
1420 /* DIRNAME is "$INSTALLDIR\share\locale". */
1422 /* First find out the category value. */
1424 catval_full = my_nl_locale_name ("LC_MESSAGES");
1426 /* Normally we would have to loop over all returned locales and
1427 search for the right file. See gettext intl/dcigettext.c for all
1428 the gory details. Here, we only support the basic category, and
1429 ignore everything else. */
1434 catval = jnlib_malloc (strlen (catval_full) + 1);
1437 strcpy (catval, catval_full);
1438 p = strchr (catval, '_');
1446 /* Now build the filename string. The complete filename is this:
1447 DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo */
1449 int len = (strlen (dirname) + 1 + strlen (catval) + 13
1450 + strlen (domainname) + 3 + 1);
1453 fname = jnlib_malloc (len);
1456 jnlib_free (catval);
1461 strcpy (p, dirname);
1462 p += strlen (dirname);
1465 p += strlen (catval);
1466 strcpy (p, "\\LC_MESSAGES\\");
1468 strcpy (p, domainname);
1469 p += strlen (domainname);
1473 jnlib_free (catval);
1475 /* Store the domain information in the domainlist. */
1477 struct domainlist_s *item, *dl;
1478 char *rel_ptr1 = NULL;
1479 char *rel_ptr2 = NULL;
1481 item = jnlib_calloc (1, sizeof *dl + strlen (domainname));
1487 strcpy (item->name, domainname);
1488 item->dname = jnlib_malloc (strlen (dirname) +1);
1495 strcpy (item->dname, dirname);
1496 retvalue = item->dname;
1498 EnterCriticalSection (&domainlist_access_cs);
1500 for (dl = domainlist; dl; dl = dl->next)
1501 if (!strcmp (dl->name, domainname))
1503 if (!dl) /* First time called for this domainname. */
1505 item->fname = fname;
1507 item->next = domainlist;
1511 else /* Update only. */
1513 rel_ptr1 = dl->fname;
1516 rel_ptr2 = dl->dname;
1517 dl->dname = item->dname;
1521 LeaveCriticalSection (&domainlist_access_cs);
1524 jnlib_free (rel_ptr1);
1525 jnlib_free (rel_ptr2);
1535 get_plural (const char *data, size_t datalen, unsigned long nplural)
1540 /* We only support the Germanic rule. */
1541 idx = (nplural == 1? 0 : 1);
1545 p = strchr (data, 0) + 1;
1546 if (p >= data+datalen)
1547 return "ERROR in GETTEXT (bad plural entry)";
1548 datalen -= (p-data);
1556 get_string (struct loaded_domain *domain, uint32_t idx,
1557 int use_plural, unsigned long nplural)
1559 struct tls_space_s *tls = get_tls ();
1560 struct overflow_space_s *os;
1561 const char *trans; /* Pointer to the translated entry. */
1562 size_t translen; /* Length of that entry. */
1565 return "ERROR in GETTEXT (too many strings)";
1567 if (tls->gt_use_utf8)
1569 trans = (domain->data
1570 + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1571 translen = SWAPIT(domain->must_swap, domain->trans_tab[idx].length);
1573 else if (!domain->mapped[idx])
1575 /* Not yet mapped. Map from utf-8 to native encoding now. */
1577 size_t plen_utf8, buflen;
1580 p_utf8 = (domain->data
1581 + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1582 plen_utf8 = SWAPIT(domain->must_swap, domain->trans_tab[idx].length);
1584 buf = utf8_to_native (p_utf8, plen_utf8, &buflen);
1587 trans = "ERROR in GETTEXT MALLOC";
1590 else if (buflen <= plen_utf8 && buflen > 1)
1592 /* Copy into the DATA_NATIVE area. */
1595 p_tmp = (domain->data_native
1596 + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1597 memcpy (p_tmp, buf, buflen);
1598 domain->mapped[idx] = buflen;
1604 /* There is not enough space for the translation (or for
1605 whatever reason an empty string is used): Store it in the
1606 overflow_space and mark that in the mapped array.
1607 Because UTF-8 strings are in general shorter than the
1608 Windows 2 byte encodings, we expect that this won't
1609 happen too often (if at all) and thus we use a linked
1610 list to manage this space. */
1611 os = jnlib_malloc (sizeof *os + buflen);
1615 memcpy (os->d, buf, buflen);
1616 os->length = buflen;
1617 os->next = domain->overflow_space;
1618 domain->overflow_space = os;
1619 domain->mapped[idx] = 1;
1621 translen = os->length;
1625 trans = "ERROR in GETTEXT MALLOC";
1631 else if (domain->mapped[idx] == 1)
1633 /* The translated string is in the overflow_space. */
1634 for (os=domain->overflow_space; os; os = os->next)
1640 translen = os->length;
1644 trans = "ERROR in GETTEXT (overflow space)\n";
1650 trans = (domain->data_native
1651 + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1652 translen = domain->mapped[idx];
1655 if (use_plural && translen)
1656 return get_plural (trans, translen, nplural);
1663 do_gettext (const char *domainname,
1664 const char *msgid, const char *msgid2, unsigned long nplural)
1666 struct domainlist_s *dl;
1667 struct loaded_domain *domain;
1669 uint32_t top, bottom, nstr;
1673 domainname = current_domainname? current_domainname : "";
1675 /* FIXME: The whole locking stuff is a bit questionable because
1676 gettext does not claim to be thread-safe. We need to investigate
1682 EnterCriticalSection (&domainlist_access_cs);
1684 for (dl = domainlist; dl; dl = dl->next)
1685 if (!strcmp (dl->name, domainname))
1687 load_failed = dl->load_failed;
1688 domain = dl->domain;
1691 if (dl && !domain && !load_failed && dl->fname)
1693 filename = jnlib_malloc (strlen (dl->fname) + 1);
1695 strcpy (filename, dl->fname);
1698 LeaveCriticalSection (&domainlist_access_cs);
1700 goto not_found; /* DOMAINNAME not bound. */
1703 /* No attempt so far to load the MO file. Try now. */
1706 domain = load_domain (filename);
1707 jnlib_free (filename);
1709 EnterCriticalSection (&domainlist_access_cs);
1711 for (dl = domainlist; dl; dl = dl->next)
1712 if (!strcmp (dl->name, domainname))
1715 dl->domain = domain;
1717 dl->load_failed = 1;
1722 LeaveCriticalSection (&domainlist_access_cs);
1725 /* Ooops - lost the domain. */
1726 free_domain (domain);
1732 goto not_found; /* No MO file. */
1734 /* First try to use the hash table. */
1735 if (domain->hash_size > 2 && domain->hash_tab)
1737 /* Use the hashing table. */
1738 uint32_t len = strlen (msgid);
1739 uint32_t hash_val = hash_string (msgid);
1740 uint32_t idx = hash_val % domain->hash_size;
1741 uint32_t incr = 1 + (hash_val % (domain->hash_size - 2));
1743 while ( (nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx])) )
1746 if (nstr < domain->nstrings
1747 && SWAPIT(domain->must_swap,
1748 domain->orig_tab[nstr].length) >= len
1749 && !strcmp (msgid, (domain->data
1750 + SWAPIT(domain->must_swap,
1751 domain->orig_tab[nstr].offset))))
1753 return get_string (domain, nstr, !!msgid2, nplural);
1756 if (idx >= domain->hash_size - incr)
1757 idx -= domain->hash_size - incr;
1763 /* Now we try the default method: binary search in the sorted array
1766 top = domain->nstrings;
1767 while (bottom < top)
1771 nstr = (bottom + top) / 2;
1772 cmp_val = strcmp (msgid, (domain->data
1773 + SWAPIT(domain->must_swap,
1774 domain->orig_tab[nstr].offset)));
1777 else if (cmp_val > 0)
1781 return get_string (domain, nstr, !!msgid2, nplural);
1786 /* We use the standard Germanic rule if plural has been requested. */
1787 return msgid2? (nplural == 1? msgid : msgid2) : msgid;
1792 _gpg_w32_textdomain (const char *domainname)
1798 if (!current_domainname)
1799 gpg_err_set_errno (0);
1803 string = malloc (strlen (domainname) + 1);
1806 strcpy (string, domainname);
1807 current_domainname = string;
1809 return current_domainname;
1813 /* A direct implementation of gettext instead of a macro calling
1814 dngettext. This is so that the caller does not need to push dummy
1815 values on the stack. The used domain is the first one registered
1816 with bindtextdomain. */
1818 _gpg_w32_gettext (const char *msgid)
1820 return do_gettext (NULL, msgid, NULL, 0);
1824 /* A direct implementation of dgettext instead of a macro calling
1825 dngettext. This is so that the caller does not need to push dummy
1826 values on the stack. */
1828 _gpg_w32_dgettext (const char *domainname, const char *msgid)
1830 return do_gettext (domainname, msgid, NULL, 0);
1834 /* Our implementation of dngettext. This is the most genereic
1835 function we have; a macro implements ngettext. */
1837 _gpg_w32_dngettext (const char *domainname, const char *msgid1,
1838 const char *msgid2, unsigned long int n)
1840 /* We use the simple Germanic plural rule. */
1841 return do_gettext (domainname, msgid1, msgid2, n);
1845 /* Return the locale name as used by gettext. The return value will
1848 _gpg_w32_gettext_localename (void)
1852 s = my_nl_locale_name ("LC_MESSAGES");
1857 /* With a VALUE of 1 switch the gettext functions into utf8 mode.
1858 That is the strings are returned without translation to the native
1859 charset. A VALUE of 0 switches back to translated strings. A VALUE
1860 of -1 returns the current value. */
1862 _gpg_w32_gettext_use_utf8 (int value)
1864 struct tls_space_s *tls = get_tls ();
1865 int last = tls->gt_use_utf8;
1867 tls->gt_use_utf8 = value;
1874 main (int argc, char **argv)
1876 const char atext1[] =
1877 "Warning: You have entered an insecure passphrase.%%0A"
1878 "A passphrase should be at least %u character long.";
1879 const char atext2[] =
1880 "Warning: You have entered an insecure passphrase.%%0A"
1881 "A passphrase should be at least %u characters long.";
1889 _gpg_err_w32_bindtextdomain ("gnupg2", "c:/programme/gnu/gnupg/share/locale");
1891 printf ("locale is `%s'\n", _gpg_err_w32_gettext_localename ());
1892 fputs ("text with N=1:\n", stdout);
1893 fputs (_gpg_err_w32_ngettext (atext1, atext2, 1), stdout);
1894 fputs ("\n\ntext with N=2:\n", stdout);
1895 fputs (_gpg_err_w32_ngettext (atext1, atext2, 2), stdout);
1896 fputs ("\nready\n", stdout);
1902 * compile-command: "i586-mingw32msvc-gcc -DTEST -Wall -g w32-gettext.c"