1
/* w32-gettext.c - A simplified version of gettext for use under W32.
2
* Copyright (C) 1995, 1996, 1997, 1999, 2000, 2003,
3
* 2005, 2007, 2088 Free Software Foundation, Inc.
5
* This file is part of JNLIB.
7
* JNLIB is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 3 of
10
* the License, or (at your option) any later version.
12
* JNLIB 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/>.
22
This is a simplified version of gettext written by Ulrich Drepper.
23
It is used for the Win32 version of GnuPG becaise all the overhead
24
of gettext is not needed and we have to do some special Win32
25
stuff. I decided that this is far easier than to tweak gettext for
26
the special cases (I tried it but it is a lot of code). wk 15.09.99
30
#ifdef USE_SIMPLE_GETTEXT
31
# if !defined (_WIN32) && !defined (__CYGWIN32__)
32
# error This module may only be build for Windows or Cygwin32
40
# include <sys/types.h>
41
# include <sys/stat.h>
43
# include "libjnlib-config.h"
45
# include "stringhelp.h"
46
# include "utf8conv.h"
49
# include "windows.h" /* For GetModuleFileName. */
53
/* The magic number of the GNU message catalog format. */
54
#define MAGIC 0x950412de
55
#define MAGIC_SWAPPED 0xde120495
57
/* Revision number of the currently used .mo (binary) file format. */
58
#define MO_REVISION_NUMBER 0
61
/* Header for binary .mo file format. */
64
/* The magic number. */
66
/* The revision number of the file format. */
68
/* The number of strings pairs. */
70
/* Offset of table with start offsets of original strings. */
72
/* Offset of table with start offsets of translation strings. */
74
/* Size of hashing table. */
76
/* Offset of first hashing entry. */
82
/* Length of addressed string. */
84
/* Offset of string in file. */
89
struct overflow_space_s
91
struct overflow_space_s *next;
101
char *mapped; /* 0 = not yet mapped, 1 = mapped,
104
struct overflow_space_s *overflow_space;
105
struct string_desc *orig_tab;
106
struct string_desc *trans_tab;
112
static struct loaded_domain *the_domain;
113
static char *the_langid;
115
static __inline__ u32
118
return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
121
#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) )
124
/* We assume to have `unsigned long int' value with at least 32 bits. */
125
#define HASHWORDBITS 32
129
/* BEGIN parts of localname.c from gettext. */
131
/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
132
/* Win32 code written by Tor Lillqvist <tml@iki.fi>. */
134
/* List of language codes, sorted by value:
157
0x17 LANG_RHAETO_ROMANCE
160
0x1a LANG_CROATIAN == LANG_SERBIAN
252
/* Mingw headers don't have latest language and sublanguage codes. */
253
# ifndef LANG_AFRIKAANS
254
# define LANG_AFRIKAANS 0x36
256
# ifndef LANG_ALBANIAN
257
# define LANG_ALBANIAN 0x1c
259
# ifndef LANG_AMHARIC
260
# define LANG_AMHARIC 0x5e
263
# define LANG_ARABIC 0x01
265
# ifndef LANG_ARMENIAN
266
# define LANG_ARMENIAN 0x2b
268
# ifndef LANG_ASSAMESE
269
# define LANG_ASSAMESE 0x4d
272
# define LANG_AZERI 0x2c
275
# define LANG_BASQUE 0x2d
277
# ifndef LANG_BELARUSIAN
278
# define LANG_BELARUSIAN 0x23
280
# ifndef LANG_BENGALI
281
# define LANG_BENGALI 0x45
283
# ifndef LANG_BURMESE
284
# define LANG_BURMESE 0x55
286
# ifndef LANG_CAMBODIAN
287
# define LANG_CAMBODIAN 0x53
289
# ifndef LANG_CATALAN
290
# define LANG_CATALAN 0x03
292
# ifndef LANG_CHEROKEE
293
# define LANG_CHEROKEE 0x5c
296
# define LANG_DIVEHI 0x65
299
# define LANG_EDO 0x66
301
# ifndef LANG_ESTONIAN
302
# define LANG_ESTONIAN 0x25
304
# ifndef LANG_FAEROESE
305
# define LANG_FAEROESE 0x38
308
# define LANG_FARSI 0x29
310
# ifndef LANG_FRISIAN
311
# define LANG_FRISIAN 0x62
313
# ifndef LANG_FULFULDE
314
# define LANG_FULFULDE 0x67
317
# define LANG_GAELIC 0x3c
319
# ifndef LANG_GALICIAN
320
# define LANG_GALICIAN 0x56
322
# ifndef LANG_GEORGIAN
323
# define LANG_GEORGIAN 0x37
325
# ifndef LANG_GUARANI
326
# define LANG_GUARANI 0x74
328
# ifndef LANG_GUJARATI
329
# define LANG_GUJARATI 0x47
332
# define LANG_HAUSA 0x68
334
# ifndef LANG_HAWAIIAN
335
# define LANG_HAWAIIAN 0x75
338
# define LANG_HEBREW 0x0d
341
# define LANG_HINDI 0x39
344
# define LANG_IBIBIO 0x69
347
# define LANG_IGBO 0x70
349
# ifndef LANG_INDONESIAN
350
# define LANG_INDONESIAN 0x21
352
# ifndef LANG_INUKTITUT
353
# define LANG_INUKTITUT 0x5d
355
# ifndef LANG_KANNADA
356
# define LANG_KANNADA 0x4b
359
# define LANG_KANURI 0x71
361
# ifndef LANG_KASHMIRI
362
# define LANG_KASHMIRI 0x60
365
# define LANG_KAZAK 0x3f
367
# ifndef LANG_KONKANI
368
# define LANG_KONKANI 0x57
371
# define LANG_KYRGYZ 0x40
374
# define LANG_LAO 0x54
377
# define LANG_LATIN 0x76
379
# ifndef LANG_LATVIAN
380
# define LANG_LATVIAN 0x26
382
# ifndef LANG_LITHUANIAN
383
# define LANG_LITHUANIAN 0x27
385
# ifndef LANG_MACEDONIAN
386
# define LANG_MACEDONIAN 0x2f
389
# define LANG_MALAY 0x3e
391
# ifndef LANG_MALAYALAM
392
# define LANG_MALAYALAM 0x4c
394
# ifndef LANG_MALTESE
395
# define LANG_MALTESE 0x3a
397
# ifndef LANG_MANIPURI
398
# define LANG_MANIPURI 0x58
400
# ifndef LANG_MARATHI
401
# define LANG_MARATHI 0x4e
403
# ifndef LANG_MONGOLIAN
404
# define LANG_MONGOLIAN 0x50
407
# define LANG_NEPALI 0x61
410
# define LANG_ORIYA 0x48
413
# define LANG_OROMO 0x72
415
# ifndef LANG_PAPIAMENTU
416
# define LANG_PAPIAMENTU 0x79
419
# define LANG_PASHTO 0x63
421
# ifndef LANG_PUNJABI
422
# define LANG_PUNJABI 0x46
424
# ifndef LANG_RHAETO_ROMANCE
425
# define LANG_RHAETO_ROMANCE 0x17
428
# define LANG_SAAMI 0x3b
430
# ifndef LANG_SANSKRIT
431
# define LANG_SANSKRIT 0x4f
433
# ifndef LANG_SERBIAN
434
# define LANG_SERBIAN 0x1a
437
# define LANG_SINDHI 0x59
439
# ifndef LANG_SINHALESE
440
# define LANG_SINHALESE 0x5b
443
# define LANG_SLOVAK 0x1b
446
# define LANG_SOMALI 0x77
448
# ifndef LANG_SORBIAN
449
# define LANG_SORBIAN 0x2e
452
# define LANG_SUTU 0x30
454
# ifndef LANG_SWAHILI
455
# define LANG_SWAHILI 0x41
458
# define LANG_SYRIAC 0x5a
460
# ifndef LANG_TAGALOG
461
# define LANG_TAGALOG 0x64
464
# define LANG_TAJIK 0x28
466
# ifndef LANG_TAMAZIGHT
467
# define LANG_TAMAZIGHT 0x5f
470
# define LANG_TAMIL 0x49
473
# define LANG_TATAR 0x44
476
# define LANG_TELUGU 0x4a
479
# define LANG_THAI 0x1e
481
# ifndef LANG_TIBETAN
482
# define LANG_TIBETAN 0x51
484
# ifndef LANG_TIGRINYA
485
# define LANG_TIGRINYA 0x73
488
# define LANG_TSONGA 0x31
491
# define LANG_TSWANA 0x32
493
# ifndef LANG_TURKMEN
494
# define LANG_TURKMEN 0x42
496
# ifndef LANG_UKRAINIAN
497
# define LANG_UKRAINIAN 0x22
500
# define LANG_URDU 0x20
503
# define LANG_UZBEK 0x43
506
# define LANG_VENDA 0x33
508
# ifndef LANG_VIETNAMESE
509
# define LANG_VIETNAMESE 0x2a
512
# define LANG_WELSH 0x52
515
# define LANG_XHOSA 0x34
518
# define LANG_YI 0x78
520
# ifndef LANG_YIDDISH
521
# define LANG_YIDDISH 0x3d
524
# define LANG_YORUBA 0x6a
527
# define LANG_ZULU 0x35
529
# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
530
# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
532
# ifndef SUBLANG_ARABIC_IRAQ
533
# define SUBLANG_ARABIC_IRAQ 0x02
535
# ifndef SUBLANG_ARABIC_EGYPT
536
# define SUBLANG_ARABIC_EGYPT 0x03
538
# ifndef SUBLANG_ARABIC_LIBYA
539
# define SUBLANG_ARABIC_LIBYA 0x04
541
# ifndef SUBLANG_ARABIC_ALGERIA
542
# define SUBLANG_ARABIC_ALGERIA 0x05
544
# ifndef SUBLANG_ARABIC_MOROCCO
545
# define SUBLANG_ARABIC_MOROCCO 0x06
547
# ifndef SUBLANG_ARABIC_TUNISIA
548
# define SUBLANG_ARABIC_TUNISIA 0x07
550
# ifndef SUBLANG_ARABIC_OMAN
551
# define SUBLANG_ARABIC_OMAN 0x08
553
# ifndef SUBLANG_ARABIC_YEMEN
554
# define SUBLANG_ARABIC_YEMEN 0x09
556
# ifndef SUBLANG_ARABIC_SYRIA
557
# define SUBLANG_ARABIC_SYRIA 0x0a
559
# ifndef SUBLANG_ARABIC_JORDAN
560
# define SUBLANG_ARABIC_JORDAN 0x0b
562
# ifndef SUBLANG_ARABIC_LEBANON
563
# define SUBLANG_ARABIC_LEBANON 0x0c
565
# ifndef SUBLANG_ARABIC_KUWAIT
566
# define SUBLANG_ARABIC_KUWAIT 0x0d
568
# ifndef SUBLANG_ARABIC_UAE
569
# define SUBLANG_ARABIC_UAE 0x0e
571
# ifndef SUBLANG_ARABIC_BAHRAIN
572
# define SUBLANG_ARABIC_BAHRAIN 0x0f
574
# ifndef SUBLANG_ARABIC_QATAR
575
# define SUBLANG_ARABIC_QATAR 0x10
577
# ifndef SUBLANG_AZERI_LATIN
578
# define SUBLANG_AZERI_LATIN 0x01
580
# ifndef SUBLANG_AZERI_CYRILLIC
581
# define SUBLANG_AZERI_CYRILLIC 0x02
583
# ifndef SUBLANG_BENGALI_INDIA
584
# define SUBLANG_BENGALI_INDIA 0x01
586
# ifndef SUBLANG_BENGALI_BANGLADESH
587
# define SUBLANG_BENGALI_BANGLADESH 0x02
589
# ifndef SUBLANG_CHINESE_MACAU
590
# define SUBLANG_CHINESE_MACAU 0x05
592
# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
593
# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
595
# ifndef SUBLANG_ENGLISH_JAMAICA
596
# define SUBLANG_ENGLISH_JAMAICA 0x08
598
# ifndef SUBLANG_ENGLISH_CARIBBEAN
599
# define SUBLANG_ENGLISH_CARIBBEAN 0x09
601
# ifndef SUBLANG_ENGLISH_BELIZE
602
# define SUBLANG_ENGLISH_BELIZE 0x0a
604
# ifndef SUBLANG_ENGLISH_TRINIDAD
605
# define SUBLANG_ENGLISH_TRINIDAD 0x0b
607
# ifndef SUBLANG_ENGLISH_ZIMBABWE
608
# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
610
# ifndef SUBLANG_ENGLISH_PHILIPPINES
611
# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
613
# ifndef SUBLANG_ENGLISH_INDONESIA
614
# define SUBLANG_ENGLISH_INDONESIA 0x0e
616
# ifndef SUBLANG_ENGLISH_HONGKONG
617
# define SUBLANG_ENGLISH_HONGKONG 0x0f
619
# ifndef SUBLANG_ENGLISH_INDIA
620
# define SUBLANG_ENGLISH_INDIA 0x10
622
# ifndef SUBLANG_ENGLISH_MALAYSIA
623
# define SUBLANG_ENGLISH_MALAYSIA 0x11
625
# ifndef SUBLANG_ENGLISH_SINGAPORE
626
# define SUBLANG_ENGLISH_SINGAPORE 0x12
628
# ifndef SUBLANG_FRENCH_LUXEMBOURG
629
# define SUBLANG_FRENCH_LUXEMBOURG 0x05
631
# ifndef SUBLANG_FRENCH_MONACO
632
# define SUBLANG_FRENCH_MONACO 0x06
634
# ifndef SUBLANG_FRENCH_WESTINDIES
635
# define SUBLANG_FRENCH_WESTINDIES 0x07
637
# ifndef SUBLANG_FRENCH_REUNION
638
# define SUBLANG_FRENCH_REUNION 0x08
640
# ifndef SUBLANG_FRENCH_CONGO
641
# define SUBLANG_FRENCH_CONGO 0x09
643
# ifndef SUBLANG_FRENCH_SENEGAL
644
# define SUBLANG_FRENCH_SENEGAL 0x0a
646
# ifndef SUBLANG_FRENCH_CAMEROON
647
# define SUBLANG_FRENCH_CAMEROON 0x0b
649
# ifndef SUBLANG_FRENCH_COTEDIVOIRE
650
# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
652
# ifndef SUBLANG_FRENCH_MALI
653
# define SUBLANG_FRENCH_MALI 0x0d
655
# ifndef SUBLANG_FRENCH_MOROCCO
656
# define SUBLANG_FRENCH_MOROCCO 0x0e
658
# ifndef SUBLANG_FRENCH_HAITI
659
# define SUBLANG_FRENCH_HAITI 0x0f
661
# ifndef SUBLANG_GERMAN_LUXEMBOURG
662
# define SUBLANG_GERMAN_LUXEMBOURG 0x04
664
# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
665
# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
667
# ifndef SUBLANG_KASHMIRI_INDIA
668
# define SUBLANG_KASHMIRI_INDIA 0x02
670
# ifndef SUBLANG_MALAY_MALAYSIA
671
# define SUBLANG_MALAY_MALAYSIA 0x01
673
# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
674
# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
676
# ifndef SUBLANG_NEPALI_INDIA
677
# define SUBLANG_NEPALI_INDIA 0x02
679
# ifndef SUBLANG_PUNJABI_INDIA
680
# define SUBLANG_PUNJABI_INDIA 0x01
682
# ifndef SUBLANG_ROMANIAN_ROMANIA
683
# define SUBLANG_ROMANIAN_ROMANIA 0x01
685
# ifndef SUBLANG_SERBIAN_LATIN
686
# define SUBLANG_SERBIAN_LATIN 0x02
688
# ifndef SUBLANG_SERBIAN_CYRILLIC
689
# define SUBLANG_SERBIAN_CYRILLIC 0x03
691
# ifndef SUBLANG_SINDHI_INDIA
692
# define SUBLANG_SINDHI_INDIA 0x00
694
# ifndef SUBLANG_SINDHI_PAKISTAN
695
# define SUBLANG_SINDHI_PAKISTAN 0x01
697
# ifndef SUBLANG_SPANISH_GUATEMALA
698
# define SUBLANG_SPANISH_GUATEMALA 0x04
700
# ifndef SUBLANG_SPANISH_COSTA_RICA
701
# define SUBLANG_SPANISH_COSTA_RICA 0x05
703
# ifndef SUBLANG_SPANISH_PANAMA
704
# define SUBLANG_SPANISH_PANAMA 0x06
706
# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
707
# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
709
# ifndef SUBLANG_SPANISH_VENEZUELA
710
# define SUBLANG_SPANISH_VENEZUELA 0x08
712
# ifndef SUBLANG_SPANISH_COLOMBIA
713
# define SUBLANG_SPANISH_COLOMBIA 0x09
715
# ifndef SUBLANG_SPANISH_PERU
716
# define SUBLANG_SPANISH_PERU 0x0a
718
# ifndef SUBLANG_SPANISH_ARGENTINA
719
# define SUBLANG_SPANISH_ARGENTINA 0x0b
721
# ifndef SUBLANG_SPANISH_ECUADOR
722
# define SUBLANG_SPANISH_ECUADOR 0x0c
724
# ifndef SUBLANG_SPANISH_CHILE
725
# define SUBLANG_SPANISH_CHILE 0x0d
727
# ifndef SUBLANG_SPANISH_URUGUAY
728
# define SUBLANG_SPANISH_URUGUAY 0x0e
730
# ifndef SUBLANG_SPANISH_PARAGUAY
731
# define SUBLANG_SPANISH_PARAGUAY 0x0f
733
# ifndef SUBLANG_SPANISH_BOLIVIA
734
# define SUBLANG_SPANISH_BOLIVIA 0x10
736
# ifndef SUBLANG_SPANISH_EL_SALVADOR
737
# define SUBLANG_SPANISH_EL_SALVADOR 0x11
739
# ifndef SUBLANG_SPANISH_HONDURAS
740
# define SUBLANG_SPANISH_HONDURAS 0x12
742
# ifndef SUBLANG_SPANISH_NICARAGUA
743
# define SUBLANG_SPANISH_NICARAGUA 0x13
745
# ifndef SUBLANG_SPANISH_PUERTO_RICO
746
# define SUBLANG_SPANISH_PUERTO_RICO 0x14
748
# ifndef SUBLANG_SWEDISH_FINLAND
749
# define SUBLANG_SWEDISH_FINLAND 0x02
751
# ifndef SUBLANG_TAMAZIGHT_ARABIC
752
# define SUBLANG_TAMAZIGHT_ARABIC 0x01
754
# ifndef SUBLANG_TAMAZIGHT_LATIN
755
# define SUBLANG_TAMAZIGHT_LATIN 0x02
757
# ifndef SUBLANG_TIGRINYA_ETHIOPIA
758
# define SUBLANG_TIGRINYA_ETHIOPIA 0x00
760
# ifndef SUBLANG_TIGRINYA_ERITREA
761
# define SUBLANG_TIGRINYA_ERITREA 0x01
763
# ifndef SUBLANG_URDU_PAKISTAN
764
# define SUBLANG_URDU_PAKISTAN 0x01
766
# ifndef SUBLANG_URDU_INDIA
767
# define SUBLANG_URDU_INDIA 0x02
769
# ifndef SUBLANG_UZBEK_LATIN
770
# define SUBLANG_UZBEK_LATIN 0x01
772
# ifndef SUBLANG_UZBEK_CYRILLIC
773
# define SUBLANG_UZBEK_CYRILLIC 0x02
777
/* Return an XPG style locale name language[_territory][@modifier].
778
Don't even bother determining the codeset; it's not useful in this
779
context, because message catalogs are not specific to a single
782
_nl_locale_name (const char *categoryname)
789
/* Let the user override the system settings through environment
790
variables, as on POSIX systems. */
791
retval = getenv ("LC_ALL");
792
if (retval != NULL && retval[0] != '\0')
794
retval = getenv (categoryname);
795
if (retval != NULL && retval[0] != '\0')
797
retval = getenv ("LANG");
798
if (retval != NULL && retval[0] != '\0')
801
/* Use native Win32 API locale ID. */
802
lcid = GetThreadLocale ();
804
/* Strip off the sorting rules, keep only the language part. */
805
langid = LANGIDFROMLCID (lcid);
807
/* Split into language and territory part. */
808
primary = PRIMARYLANGID (langid);
809
sub = SUBLANGID (langid);
811
/* Dispatch on language.
812
See also http://www.unicode.org/unicode/onlinedat/languages.html .
813
For details about languages, see http://www.ethnologue.com/ . */
816
case LANG_AFRIKAANS: return "af_ZA";
817
case LANG_ALBANIAN: return "sq_AL";
818
case LANG_AMHARIC: return "am_ET";
822
case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
823
case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
824
case SUBLANG_ARABIC_EGYPT: return "ar_EG";
825
case SUBLANG_ARABIC_LIBYA: return "ar_LY";
826
case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
827
case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
828
case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
829
case SUBLANG_ARABIC_OMAN: return "ar_OM";
830
case SUBLANG_ARABIC_YEMEN: return "ar_YE";
831
case SUBLANG_ARABIC_SYRIA: return "ar_SY";
832
case SUBLANG_ARABIC_JORDAN: return "ar_JO";
833
case SUBLANG_ARABIC_LEBANON: return "ar_LB";
834
case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
835
case SUBLANG_ARABIC_UAE: return "ar_AE";
836
case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
837
case SUBLANG_ARABIC_QATAR: return "ar_QA";
840
case LANG_ARMENIAN: return "hy_AM";
841
case LANG_ASSAMESE: return "as_IN";
845
/* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
846
case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
847
case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
851
return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
852
case LANG_BELARUSIAN: return "be_BY";
856
case SUBLANG_BENGALI_INDIA: return "bn_IN";
857
case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
860
case LANG_BULGARIAN: return "bg_BG";
861
case LANG_BURMESE: return "my_MM";
862
case LANG_CAMBODIAN: return "km_KH";
863
case LANG_CATALAN: return "ca_ES";
864
case LANG_CHEROKEE: return "chr_US";
868
case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
869
case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
870
case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
871
case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
872
case SUBLANG_CHINESE_MACAU: return "zh_MO";
875
case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN
876
* What used to be called Serbo-Croatian
877
* should really now be two separate
878
* languages because of political reasons.
879
* (Says tml, who knows nothing about Serbian
881
* (I can feel those flames coming already.)
885
case SUBLANG_DEFAULT: return "hr_HR";
886
case SUBLANG_SERBIAN_LATIN: return "sr_CS";
887
case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
890
case LANG_CZECH: return "cs_CZ";
891
case LANG_DANISH: return "da_DK";
892
case LANG_DIVEHI: return "div_MV";
896
case SUBLANG_DUTCH: return "nl_NL";
897
case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
900
case LANG_EDO: return "bin_NG";
904
/* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
905
* English was the language spoken in England.
908
case SUBLANG_ENGLISH_US: return "en_US";
909
case SUBLANG_ENGLISH_UK: return "en_GB";
910
case SUBLANG_ENGLISH_AUS: return "en_AU";
911
case SUBLANG_ENGLISH_CAN: return "en_CA";
912
case SUBLANG_ENGLISH_NZ: return "en_NZ";
913
case SUBLANG_ENGLISH_EIRE: return "en_IE";
914
case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
915
case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
916
case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
917
case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
918
case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
919
case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
920
case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
921
case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
922
case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
923
case SUBLANG_ENGLISH_INDIA: return "en_IN";
924
case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
925
case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
928
case LANG_ESTONIAN: return "et_EE";
929
case LANG_FAEROESE: return "fo_FO";
930
case LANG_FARSI: return "fa_IR";
931
case LANG_FINNISH: return "fi_FI";
935
case SUBLANG_FRENCH: return "fr_FR";
936
case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
937
case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
938
case SUBLANG_FRENCH_SWISS: return "fr_CH";
939
case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
940
case SUBLANG_FRENCH_MONACO: return "fr_MC";
941
case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
942
case SUBLANG_FRENCH_REUNION: return "fr_RE";
943
case SUBLANG_FRENCH_CONGO: return "fr_CG";
944
case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
945
case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
946
case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
947
case SUBLANG_FRENCH_MALI: return "fr_ML";
948
case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
949
case SUBLANG_FRENCH_HAITI: return "fr_HT";
952
case LANG_FRISIAN: return "fy_NL";
953
case LANG_FULFULDE: return "ful_NG";
957
case 0x01: /* SCOTTISH */ return "gd_GB";
958
case 0x02: /* IRISH */ return "ga_IE";
961
case LANG_GALICIAN: return "gl_ES";
962
case LANG_GEORGIAN: return "ka_GE";
966
case SUBLANG_GERMAN: return "de_DE";
967
case SUBLANG_GERMAN_SWISS: return "de_CH";
968
case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
969
case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
970
case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
973
case LANG_GREEK: return "el_GR";
974
case LANG_GUARANI: return "gn_PY";
975
case LANG_GUJARATI: return "gu_IN";
976
case LANG_HAUSA: return "ha_NG";
978
/* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
979
or Hawaii Creole English ("cpe_US", 600000 speakers)? */
981
case LANG_HEBREW: return "he_IL";
982
case LANG_HINDI: return "hi_IN";
983
case LANG_HUNGARIAN: return "hu_HU";
984
case LANG_IBIBIO: return "nic_NG";
985
case LANG_ICELANDIC: return "is_IS";
986
case LANG_IGBO: return "ibo_NG";
987
case LANG_INDONESIAN: return "id_ID";
988
case LANG_INUKTITUT: return "iu_CA";
992
case SUBLANG_ITALIAN: return "it_IT";
993
case SUBLANG_ITALIAN_SWISS: return "it_CH";
996
case LANG_JAPANESE: return "ja_JP";
997
case LANG_KANNADA: return "kn_IN";
998
case LANG_KANURI: return "kau_NG";
1002
case SUBLANG_DEFAULT: return "ks_PK";
1003
case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
1006
case LANG_KAZAK: return "kk_KZ";
1008
/* FIXME: Adjust this when such locales appear on Unix. */
1010
case LANG_KOREAN: return "ko_KR";
1011
case LANG_KYRGYZ: return "ky_KG";
1012
case LANG_LAO: return "lo_LA";
1013
case LANG_LATIN: return "la_VA";
1014
case LANG_LATVIAN: return "lv_LV";
1015
case LANG_LITHUANIAN: return "lt_LT";
1016
case LANG_MACEDONIAN: return "mk_MK";
1020
case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
1021
case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
1024
case LANG_MALAYALAM: return "ml_IN";
1025
case LANG_MALTESE: return "mt_MT";
1027
/* FIXME: Adjust this when such locales appear on Unix. */
1029
case LANG_MARATHI: return "mr_IN";
1030
case LANG_MONGOLIAN:
1031
return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
1035
case SUBLANG_DEFAULT: return "ne_NP";
1036
case SUBLANG_NEPALI_INDIA: return "ne_IN";
1039
case LANG_NORWEGIAN:
1042
case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
1043
case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
1046
case LANG_ORIYA: return "or_IN";
1047
case LANG_OROMO: return "om_ET";
1048
case LANG_PAPIAMENTU: return "pap_AN";
1050
return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
1051
case LANG_POLISH: return "pl_PL";
1052
case LANG_PORTUGUESE:
1055
case SUBLANG_PORTUGUESE: return "pt_PT";
1056
/* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
1057
Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
1058
case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
1064
case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
1067
case LANG_RHAETO_ROMANCE: return "rm_CH";
1071
case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
1075
return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
1076
case LANG_SAAMI: /* actually Northern Sami */ return "se_NO";
1077
case LANG_SANSKRIT: return "sa_IN";
1081
case SUBLANG_SINDHI_INDIA: return "sd_IN";
1082
case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
1085
case LANG_SINHALESE: return "si_LK";
1086
case LANG_SLOVAK: return "sk_SK";
1087
case LANG_SLOVENIAN: return "sl_SI";
1088
case LANG_SOMALI: return "so_SO";
1090
/* FIXME: Adjust this when such locales appear on Unix. */
1095
case SUBLANG_SPANISH: return "es_ES";
1096
case SUBLANG_SPANISH_MEXICAN: return "es_MX";
1097
case SUBLANG_SPANISH_MODERN:
1098
return "es_ES@modern"; /* not seen on Unix */
1099
case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
1100
case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
1101
case SUBLANG_SPANISH_PANAMA: return "es_PA";
1102
case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
1103
case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
1104
case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
1105
case SUBLANG_SPANISH_PERU: return "es_PE";
1106
case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
1107
case SUBLANG_SPANISH_ECUADOR: return "es_EC";
1108
case SUBLANG_SPANISH_CHILE: return "es_CL";
1109
case SUBLANG_SPANISH_URUGUAY: return "es_UY";
1110
case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
1111
case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
1112
case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
1113
case SUBLANG_SPANISH_HONDURAS: return "es_HN";
1114
case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
1115
case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
1118
case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
1119
case LANG_SWAHILI: return "sw_KE";
1123
case SUBLANG_DEFAULT: return "sv_SE";
1124
case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
1127
case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */
1128
case LANG_TAGALOG: return "tl_PH";
1129
case LANG_TAJIK: return "tg_TJ";
1130
case LANG_TAMAZIGHT:
1133
/* FIXME: Adjust this when Tamazight locales appear on Unix. */
1134
case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
1135
case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin";
1139
return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
1140
case LANG_TATAR: return "tt_RU";
1141
case LANG_TELUGU: return "te_IN";
1142
case LANG_THAI: return "th_TH";
1143
case LANG_TIBETAN: return "bo_CN";
1147
case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
1148
case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
1151
case LANG_TSONGA: return "ts_ZA";
1152
case LANG_TSWANA: return "tn_BW";
1153
case LANG_TURKISH: return "tr_TR";
1154
case LANG_TURKMEN: return "tk_TM";
1155
case LANG_UKRAINIAN: return "uk_UA";
1159
case SUBLANG_URDU_PAKISTAN: return "ur_PK";
1160
case SUBLANG_URDU_INDIA: return "ur_IN";
1166
case SUBLANG_UZBEK_LATIN: return "uz_UZ";
1167
case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
1171
/* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
1173
http://www.loc.gov/standards/iso639-2/englangn.html has it, but
1174
http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't, */
1175
return "ven_ZA"; /* or "ve_ZA"? */
1176
case LANG_VIETNAMESE: return "vi_VN";
1177
case LANG_WELSH: return "cy_GB";
1178
case LANG_XHOSA: return "xh_ZA";
1179
case LANG_YI: return "sit_CN";
1180
case LANG_YIDDISH: return "yi_IL";
1181
case LANG_YORUBA: return "yo_NG";
1182
case LANG_ZULU: return "zu_ZA";
1183
default: return "C";
1186
/* END parts of localname.c from gettext. */
1190
/* The so called `hashpjw' function by P.J. Weinberger
1191
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1192
1986, 1987 Bell Telephone Laboratories, Inc.] */
1194
static __inline__ ulong
1195
hash_string (const char *str_param)
1197
unsigned long int hval, g;
1198
const char *str = str_param;
1201
while (*str != '\0')
1204
hval += (unsigned long int) *str++;
1205
g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
1208
hval ^= g >> (HASHWORDBITS - 8);
1216
static struct loaded_domain *
1217
load_domain (const char *filename)
1222
struct mo_file_header *data = NULL;
1223
struct loaded_domain *domain = NULL;
1227
fp = fopen( filename, "rb" );
1229
return NULL; /* Can't open the file. */
1230
/* We need to know the size of the file. */
1231
if (fstat( fileno(fp ), &st )
1232
|| (size = (size_t)st.st_size) != st.st_size
1233
|| size < sizeof (struct mo_file_header) )
1239
data = jnlib_malloc (size);
1243
return NULL; /* Out of memory. */
1247
read_ptr = (char *) data;
1252
nb = fread (read_ptr, 1, to_read, fp);
1257
return NULL; /* Read error. */
1262
while (to_read > 0);
1265
/* Using the magic number we test whether it is really a message
1267
if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
1269
/* The magic number is wrong: not a message catalog file. */
1274
domain = jnlib_calloc (1, sizeof *domain);
1280
domain->data = (char *) data;
1281
domain->must_swap = data->magic != MAGIC;
1283
/* Fill in the information about the available tables. */
1284
switch (SWAPIT(domain->must_swap, data->revision))
1287
domain->nstrings = SWAPIT(domain->must_swap, data->nstrings);
1288
domain->orig_tab = (struct string_desc *)
1289
((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset));
1290
domain->trans_tab = (struct string_desc *)
1291
((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset));
1292
domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size);
1293
domain->hash_tab = (u32 *)
1294
((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset));
1297
default: /* This is an invalid revision. */
1299
jnlib_free( domain );
1303
/* Allocate an array to keep track of code page mappings. */
1304
domain->mapped = jnlib_calloc (1, domain->nstrings);
1305
if (!domain->mapped)
1308
jnlib_free (domain);
1316
/* Set the file used for translations. Pass a NULL to disable
1317
translation. A new filename may be set at anytime. WARNING: After
1318
changing the filename you should not access any data retrieved by
1321
If REGKEY is not NULL, the function tries to selected the language
1322
the registry key "Lang" below that key. If in addition the
1323
environment variable LANGUAGE has been set, that value will
1324
override a value set by the registry key.
1327
set_gettext_file ( const char *filename, const char *regkey )
1329
struct loaded_domain *domain = NULL;
1331
if ( filename && *filename )
1333
if ( filename[0] == '/'
1334
#ifdef HAVE_DRIVE_LETTERS
1335
|| ( isalpha(filename[0])
1336
&& filename[1] == ':'
1337
&& (filename[2] == '/' || filename[2] == '\\') )
1341
/* Absolute path - use it as is. */
1342
domain = load_domain( filename );
1344
else /* Standard. */
1346
char *pgmdir, *instdir, *langid, *fname;
1351
/* In the $LANGUAGE and native locale case we do not use the
1352
registered installation directory but the one where the
1353
gpg binary has been found. */
1354
pgmdir = jnlib_malloc (MAX_PATH+5);
1355
if ( !pgmdir || !GetModuleFileName (NULL, pgmdir, MAX_PATH) )
1357
jnlib_free (pgmdir);
1358
return -1; /* Error getting the process' file name. */
1360
p = strrchr (pgmdir, DIRSEP_C);
1363
jnlib_free (pgmdir);
1364
return -1; /* Invalid file name returned. */
1371
for (pass=0; pass < 3 && !domain; pass++)
1373
jnlib_free (instdir);
1375
jnlib_free (langid);
1381
case 0: /* Pass 0: Try LANGUAGE. */
1382
if ((p = getenv ("LANGUAGE")) && *p)
1384
langid = jnlib_malloc (strlen (p)+1);
1388
/* We only make use of the first language
1389
given. Strip the rest. */
1390
p = strchr (langid, ':');
1397
case 1: /* Pass 1: Try registry. */
1400
instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
1402
"Install Directory");
1404
/* Try HKCU then HKLM. */
1405
langid = read_w32_registry_string (NULL,
1410
case 2: /* Pass 2: Try native local. */
1411
catval = _nl_locale_name ("LC_MESSAGES");
1413
!strcmp (catval, "C") || !strcmp (catval, "POSIX"))
1417
langid = jnlib_malloc (strlen (catval)+1);
1418
strcpy (langid, catval);
1427
continue; /* Next pass. */
1429
/* Strip stuff after a dot in case the user tried to
1430
enter the entire locale syntacs as usual for
1432
p = strchr (langid, '.');
1436
/* Build the key: "<instdir>/<domain>.nls/<langid>.mo".
1437
We use a directory below the installation directory
1438
with the domain included in case the software has
1439
been installed with other software altogether at the
1441
fname = jnlib_malloc (strlen (instdir? instdir:pgmdir) + 1
1442
+ strlen (filename) + 5
1443
+ strlen (langid) + 3 + 1);
1452
instdir?instdir:pgmdir),"\\"),
1453
filename), ".nls\\"),
1456
/* Better make sure that we don't mix forward and
1457
backward slashes. It seems that some Windoze
1458
versions don't accept this. */
1459
for (p=fname; *p; p++)
1464
domain = load_domain (fname);
1465
/* In case we did not found it, we try again with
1466
just the first part. E.g. "pt_BR" -> "pt". */
1467
if (!domain && (p = strchr (langid, '_')))
1472
if (domain && !the_langid)
1474
/* We save the langid we found when setting up
1475
the first domain. This yields more
1476
consistent results from gettext_localename(). */
1477
the_langid = langid;
1483
jnlib_free (pgmdir);
1484
jnlib_free (instdir);
1485
jnlib_free (langid);
1495
struct overflow_space_s *os, *os2;
1497
jnlib_free ( the_domain->data );
1498
jnlib_free ( the_domain->mapped );
1499
for (os=the_domain->overflow_space; os; os = os2)
1504
jnlib_free ( the_domain );
1507
the_domain = domain;
1513
get_string( struct loaded_domain *domain, u32 idx )
1515
struct overflow_space_s *os;
1518
p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset);
1519
if (!domain->mapped[idx])
1521
size_t plen, buflen;
1524
domain->mapped[idx] = 1;
1527
buf = utf8_to_native (p, plen, -1);
1528
buflen = strlen (buf);
1533
/* There is not enough space for the translation - store it
1534
in the overflow_space else and mark that in the mapped
1535
array. Because we expect that this won't happen too
1536
often, we use a simple linked list. */
1537
os = jnlib_malloc (sizeof *os + buflen);
1541
strcpy (os->d, buf);
1542
os->next = domain->overflow_space;
1543
domain->overflow_space = os;
1547
p = "ERROR in GETTEXT MALLOC";
1551
else if (domain->mapped[idx] == 2)
1552
{ /* We need to get the string from the overflow_space. */
1553
for (os=domain->overflow_space; os; os = os->next)
1555
return (const char*)os->d;
1556
p = "ERROR in GETTEXT\n";
1558
return (const char*)p;
1564
gettext( const char *msgid )
1566
struct loaded_domain *domain;
1570
if (!(domain = the_domain))
1573
/* Locate the MSGID and its translation. */
1574
if (domain->hash_size > 2 && domain->hash_tab)
1576
/* Use the hashing table. */
1577
u32 len = strlen (msgid);
1578
u32 hash_val = hash_string (msgid);
1579
u32 idx = hash_val % domain->hash_size;
1580
u32 incr = 1 + (hash_val % (domain->hash_size - 2));
1581
u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
1583
if ( !nstr ) /* Hash table entry is empty. */
1586
if (SWAPIT(domain->must_swap,
1587
domain->orig_tab[nstr - 1].length) == len
1589
domain->data + SWAPIT(domain->must_swap,
1590
domain->orig_tab[nstr-1].offset)))
1591
return get_string( domain, nstr - 1 );
1595
if (idx >= domain->hash_size - incr)
1596
idx -= domain->hash_size - incr;
1600
nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
1602
goto not_found; /* Hash table entry is empty. */
1604
if ( SWAPIT(domain->must_swap,
1605
domain->orig_tab[nstr - 1].length) == len
1608
+ SWAPIT(domain->must_swap,
1609
domain->orig_tab[nstr-1].offset)))
1610
return get_string( domain, nstr-1 );
1615
/* Now we try the default method: binary search in the sorted array
1618
top = domain->nstrings;
1619
while (bottom < top)
1623
act = (bottom + top) / 2;
1624
cmp_val = strcmp(msgid, domain->data
1625
+ SWAPIT(domain->must_swap,
1626
domain->orig_tab[act].offset));
1629
else if (cmp_val > 0)
1632
return get_string (domain, act);
1641
ngettext (const char *msgid1, const char *msgid2, unsigned long int n)
1643
/* We use the simple Germanic plural rule. */
1644
return gettext (n==1? msgid1 : msgid2);
1648
/* Return the locale name as used by gettext. The return value will
1651
gettext_localename (void)
1658
s = _nl_locale_name ("LC_MESSAGES");
1663
#endif /* USE_SIMPLE_GETTEXT */