g10: Fix card-edit/fetch to use keyserver_fetch.
[gnupg.git] / jnlib / w32-gettext.c
1 /* w32-gettext.h - A simple gettext implementation for Windows targets.
2    Copyright (C) 1995, 1996, 1997, 1999, 2005, 2007,
3                  2008 Free Software Foundation, Inc.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation; either version 2.1 of
8    the License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this program; if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #if HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #if !defined (_WIN32) && !defined (__CYGWIN32__)
23 #  error This module may only be build for Windows or Cygwin32
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <stdint.h>
34 #include <locale.h>
35 #ifdef HAVE_WINSOCK2_H
36 # include <winsock2.h>
37 #endif
38 #include <windows.h>
39
40 #ifdef JNLIB_IN_JNLIB
41 #include "libjnlib-config.h"
42 #endif
43
44 #ifndef jnlib_malloc
45 # define jnlib_malloc(a)    malloc ((a))
46 # define jnlib_calloc(a,b)  calloc ((a), (b))
47 # define jnlib_free(a)      free ((a))
48 # define jnlib_xstrdup(a)   my_xstrdup(a)
49 #endif /*!jnlib_malloc*/
50
51
52 \f
53 /* localname.c from gettext BEGIN.  */
54
55 /* Determine the current selected locale.
56    Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
57
58    This program is free software; you can redistribute it and/or modify it
59    under the terms of the GNU Library General Public License as published
60    by the Free Software Foundation; either version 2, or (at your option)
61    any later version.
62
63    This program is distributed in the hope that it will be useful,
64    but WITHOUT ANY WARRANTY; without even the implied warranty of
65    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
66    Library General Public License for more details.
67
68    You should have received a copy of the GNU Library General Public
69    License along with this program; if not, write to the Free Software
70    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
71    USA.  */
72
73 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
74 /* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
75 /* Renamed _nl_locale_name, removed unsed args, removed include files,
76    non-W32 code and changed comments <wk@gnupg.org>.  */
77
78 /* Mingw headers don't have latest language and sublanguage codes.  */
79 #ifndef LANG_AFRIKAANS
80 #define LANG_AFRIKAANS 0x36
81 #endif
82 #ifndef LANG_ALBANIAN
83 #define LANG_ALBANIAN 0x1c
84 #endif
85 #ifndef LANG_AMHARIC
86 #define LANG_AMHARIC 0x5e
87 #endif
88 #ifndef LANG_ARABIC
89 #define LANG_ARABIC 0x01
90 #endif
91 #ifndef LANG_ARMENIAN
92 #define LANG_ARMENIAN 0x2b
93 #endif
94 #ifndef LANG_ASSAMESE
95 #define LANG_ASSAMESE 0x4d
96 #endif
97 #ifndef LANG_AZERI
98 #define LANG_AZERI 0x2c
99 #endif
100 #ifndef LANG_BASQUE
101 #define LANG_BASQUE 0x2d
102 #endif
103 #ifndef LANG_BELARUSIAN
104 #define LANG_BELARUSIAN 0x23
105 #endif
106 #ifndef LANG_BENGALI
107 #define LANG_BENGALI 0x45
108 #endif
109 #ifndef LANG_BURMESE
110 #define LANG_BURMESE 0x55
111 #endif
112 #ifndef LANG_CAMBODIAN
113 #define LANG_CAMBODIAN 0x53
114 #endif
115 #ifndef LANG_CATALAN
116 #define LANG_CATALAN 0x03
117 #endif
118 #ifndef LANG_CHEROKEE
119 #define LANG_CHEROKEE 0x5c
120 #endif
121 #ifndef LANG_DIVEHI
122 #define LANG_DIVEHI 0x65
123 #endif
124 #ifndef LANG_EDO
125 #define LANG_EDO 0x66
126 #endif
127 #ifndef LANG_ESTONIAN
128 #define LANG_ESTONIAN 0x25
129 #endif
130 #ifndef LANG_FAEROESE
131 #define LANG_FAEROESE 0x38
132 #endif
133 #ifndef LANG_FARSI
134 #define LANG_FARSI 0x29
135 #endif
136 #ifndef LANG_FRISIAN
137 #define LANG_FRISIAN 0x62
138 #endif
139 #ifndef LANG_FULFULDE
140 #define LANG_FULFULDE 0x67
141 #endif
142 #ifndef LANG_GAELIC
143 #define LANG_GAELIC 0x3c
144 #endif
145 #ifndef LANG_GALICIAN
146 #define LANG_GALICIAN 0x56
147 #endif
148 #ifndef LANG_GEORGIAN
149 #define LANG_GEORGIAN 0x37
150 #endif
151 #ifndef LANG_GUARANI
152 #define LANG_GUARANI 0x74
153 #endif
154 #ifndef LANG_GUJARATI
155 #define LANG_GUJARATI 0x47
156 #endif
157 #ifndef LANG_HAUSA
158 #define LANG_HAUSA 0x68
159 #endif
160 #ifndef LANG_HAWAIIAN
161 #define LANG_HAWAIIAN 0x75
162 #endif
163 #ifndef LANG_HEBREW
164 #define LANG_HEBREW 0x0d
165 #endif
166 #ifndef LANG_HINDI
167 #define LANG_HINDI 0x39
168 #endif
169 #ifndef LANG_IBIBIO
170 #define LANG_IBIBIO 0x69
171 #endif
172 #ifndef LANG_IGBO
173 #define LANG_IGBO 0x70
174 #endif
175 #ifndef LANG_INDONESIAN
176 #define LANG_INDONESIAN 0x21
177 #endif
178 #ifndef LANG_INUKTITUT
179 #define LANG_INUKTITUT 0x5d
180 #endif
181 #ifndef LANG_KANNADA
182 #define LANG_KANNADA 0x4b
183 #endif
184 #ifndef LANG_KANURI
185 #define LANG_KANURI 0x71
186 #endif
187 #ifndef LANG_KASHMIRI
188 #define LANG_KASHMIRI 0x60
189 #endif
190 #ifndef LANG_KAZAK
191 #define LANG_KAZAK 0x3f
192 #endif
193 #ifndef LANG_KONKANI
194 #define LANG_KONKANI 0x57
195 #endif
196 #ifndef LANG_KYRGYZ
197 #define LANG_KYRGYZ 0x40
198 #endif
199 #ifndef LANG_LAO
200 #define LANG_LAO 0x54
201 #endif
202 #ifndef LANG_LATIN
203 #define LANG_LATIN 0x76
204 #endif
205 #ifndef LANG_LATVIAN
206 #define LANG_LATVIAN 0x26
207 #endif
208 #ifndef LANG_LITHUANIAN
209 #define LANG_LITHUANIAN 0x27
210 #endif
211 #ifndef LANG_MACEDONIAN
212 #define LANG_MACEDONIAN 0x2f
213 #endif
214 #ifndef LANG_MALAY
215 #define LANG_MALAY 0x3e
216 #endif
217 #ifndef LANG_MALAYALAM
218 #define LANG_MALAYALAM 0x4c
219 #endif
220 #ifndef LANG_MALTESE
221 #define LANG_MALTESE 0x3a
222 #endif
223 #ifndef LANG_MANIPURI
224 #define LANG_MANIPURI 0x58
225 #endif
226 #ifndef LANG_MARATHI
227 #define LANG_MARATHI 0x4e
228 #endif
229 #ifndef LANG_MONGOLIAN
230 #define LANG_MONGOLIAN 0x50
231 #endif
232 #ifndef LANG_NEPALI
233 #define LANG_NEPALI 0x61
234 #endif
235 #ifndef LANG_ORIYA
236 #define LANG_ORIYA 0x48
237 #endif
238 #ifndef LANG_OROMO
239 #define LANG_OROMO 0x72
240 #endif
241 #ifndef LANG_PAPIAMENTU
242 #define LANG_PAPIAMENTU 0x79
243 #endif
244 #ifndef LANG_PASHTO
245 #define LANG_PASHTO 0x63
246 #endif
247 #ifndef LANG_PUNJABI
248 #define LANG_PUNJABI 0x46
249 #endif
250 #ifndef LANG_RHAETO_ROMANCE
251 #define LANG_RHAETO_ROMANCE 0x17
252 #endif
253 #ifndef LANG_SAAMI
254 #define LANG_SAAMI 0x3b
255 #endif
256 #ifndef LANG_SANSKRIT
257 #define LANG_SANSKRIT 0x4f
258 #endif
259 #ifndef LANG_SERBIAN
260 #define LANG_SERBIAN 0x1a
261 #endif
262 #ifndef LANG_SINDHI
263 #define LANG_SINDHI 0x59
264 #endif
265 #ifndef LANG_SINHALESE
266 #define LANG_SINHALESE 0x5b
267 #endif
268 #ifndef LANG_SLOVAK
269 #define LANG_SLOVAK 0x1b
270 #endif
271 #ifndef LANG_SOMALI
272 #define LANG_SOMALI 0x77
273 #endif
274 #ifndef LANG_SORBIAN
275 #define LANG_SORBIAN 0x2e
276 #endif
277 #ifndef LANG_SUTU
278 #define LANG_SUTU 0x30
279 #endif
280 #ifndef LANG_SWAHILI
281 #define LANG_SWAHILI 0x41
282 #endif
283 #ifndef LANG_SYRIAC
284 #define LANG_SYRIAC 0x5a
285 #endif
286 #ifndef LANG_TAGALOG
287 #define LANG_TAGALOG 0x64
288 #endif
289 #ifndef LANG_TAJIK
290 #define LANG_TAJIK 0x28
291 #endif
292 #ifndef LANG_TAMAZIGHT
293 #define LANG_TAMAZIGHT 0x5f
294 #endif
295 #ifndef LANG_TAMIL
296 #define LANG_TAMIL 0x49
297 #endif
298 #ifndef LANG_TATAR
299 #define LANG_TATAR 0x44
300 #endif
301 #ifndef LANG_TELUGU
302 #define LANG_TELUGU 0x4a
303 #endif
304 #ifndef LANG_THAI
305 #define LANG_THAI 0x1e
306 #endif
307 #ifndef LANG_TIBETAN
308 #define LANG_TIBETAN 0x51
309 #endif
310 #ifndef LANG_TIGRINYA
311 #define LANG_TIGRINYA 0x73
312 #endif
313 #ifndef LANG_TSONGA
314 #define LANG_TSONGA 0x31
315 #endif
316 #ifndef LANG_TSWANA
317 #define LANG_TSWANA 0x32
318 #endif
319 #ifndef LANG_TURKMEN
320 #define LANG_TURKMEN 0x42
321 #endif
322 #ifndef LANG_UKRAINIAN
323 #define LANG_UKRAINIAN 0x22
324 #endif
325 #ifndef LANG_URDU
326 #define LANG_URDU 0x20
327 #endif
328 #ifndef LANG_UZBEK
329 #define LANG_UZBEK 0x43
330 #endif
331 #ifndef LANG_VENDA
332 #define LANG_VENDA 0x33
333 #endif
334 #ifndef LANG_VIETNAMESE
335 #define LANG_VIETNAMESE 0x2a
336 #endif
337 #ifndef LANG_WELSH
338 #define LANG_WELSH 0x52
339 #endif
340 #ifndef LANG_XHOSA
341 #define LANG_XHOSA 0x34
342 #endif
343 #ifndef LANG_YI
344 #define LANG_YI 0x78
345 #endif
346 #ifndef LANG_YIDDISH
347 #define LANG_YIDDISH 0x3d
348 #endif
349 #ifndef LANG_YORUBA
350 #define LANG_YORUBA 0x6a
351 #endif
352 #ifndef LANG_ZULU
353 #define LANG_ZULU 0x35
354 #endif
355 #ifndef SUBLANG_ARABIC_SAUDI_ARABIA
356 #define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
357 #endif
358 #ifndef SUBLANG_ARABIC_IRAQ
359 #define SUBLANG_ARABIC_IRAQ 0x02
360 #endif
361 #ifndef SUBLANG_ARABIC_EGYPT
362 #define SUBLANG_ARABIC_EGYPT 0x03
363 #endif
364 #ifndef SUBLANG_ARABIC_LIBYA
365 #define SUBLANG_ARABIC_LIBYA 0x04
366 #endif
367 #ifndef SUBLANG_ARABIC_ALGERIA
368 #define SUBLANG_ARABIC_ALGERIA 0x05
369 #endif
370 #ifndef SUBLANG_ARABIC_MOROCCO
371 #define SUBLANG_ARABIC_MOROCCO 0x06
372 #endif
373 #ifndef SUBLANG_ARABIC_TUNISIA
374 #define SUBLANG_ARABIC_TUNISIA 0x07
375 #endif
376 #ifndef SUBLANG_ARABIC_OMAN
377 #define SUBLANG_ARABIC_OMAN 0x08
378 #endif
379 #ifndef SUBLANG_ARABIC_YEMEN
380 #define SUBLANG_ARABIC_YEMEN 0x09
381 #endif
382 #ifndef SUBLANG_ARABIC_SYRIA
383 #define SUBLANG_ARABIC_SYRIA 0x0a
384 #endif
385 #ifndef SUBLANG_ARABIC_JORDAN
386 #define SUBLANG_ARABIC_JORDAN 0x0b
387 #endif
388 #ifndef SUBLANG_ARABIC_LEBANON
389 #define SUBLANG_ARABIC_LEBANON 0x0c
390 #endif
391 #ifndef SUBLANG_ARABIC_KUWAIT
392 #define SUBLANG_ARABIC_KUWAIT 0x0d
393 #endif
394 #ifndef SUBLANG_ARABIC_UAE
395 #define SUBLANG_ARABIC_UAE 0x0e
396 #endif
397 #ifndef SUBLANG_ARABIC_BAHRAIN
398 #define SUBLANG_ARABIC_BAHRAIN 0x0f
399 #endif
400 #ifndef SUBLANG_ARABIC_QATAR
401 #define SUBLANG_ARABIC_QATAR 0x10
402 #endif
403 #ifndef SUBLANG_AZERI_LATIN
404 #define SUBLANG_AZERI_LATIN 0x01
405 #endif
406 #ifndef SUBLANG_AZERI_CYRILLIC
407 #define SUBLANG_AZERI_CYRILLIC 0x02
408 #endif
409 #ifndef SUBLANG_BENGALI_INDIA
410 #define SUBLANG_BENGALI_INDIA 0x01
411 #endif
412 #ifndef SUBLANG_BENGALI_BANGLADESH
413 #define SUBLANG_BENGALI_BANGLADESH 0x02
414 #endif
415 #ifndef SUBLANG_CHINESE_MACAU
416 #define SUBLANG_CHINESE_MACAU 0x05
417 #endif
418 #ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
419 #define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
420 #endif
421 #ifndef SUBLANG_ENGLISH_JAMAICA
422 #define SUBLANG_ENGLISH_JAMAICA 0x08
423 #endif
424 #ifndef SUBLANG_ENGLISH_CARIBBEAN
425 #define SUBLANG_ENGLISH_CARIBBEAN 0x09
426 #endif
427 #ifndef SUBLANG_ENGLISH_BELIZE
428 #define SUBLANG_ENGLISH_BELIZE 0x0a
429 #endif
430 #ifndef SUBLANG_ENGLISH_TRINIDAD
431 #define SUBLANG_ENGLISH_TRINIDAD 0x0b
432 #endif
433 #ifndef SUBLANG_ENGLISH_ZIMBABWE
434 #define SUBLANG_ENGLISH_ZIMBABWE 0x0c
435 #endif
436 #ifndef SUBLANG_ENGLISH_PHILIPPINES
437 #define SUBLANG_ENGLISH_PHILIPPINES 0x0d
438 #endif
439 #ifndef SUBLANG_ENGLISH_INDONESIA
440 #define SUBLANG_ENGLISH_INDONESIA 0x0e
441 #endif
442 #ifndef SUBLANG_ENGLISH_HONGKONG
443 #define SUBLANG_ENGLISH_HONGKONG 0x0f
444 #endif
445 #ifndef SUBLANG_ENGLISH_INDIA
446 #define SUBLANG_ENGLISH_INDIA 0x10
447 #endif
448 #ifndef SUBLANG_ENGLISH_MALAYSIA
449 #define SUBLANG_ENGLISH_MALAYSIA 0x11
450 #endif
451 #ifndef SUBLANG_ENGLISH_SINGAPORE
452 #define SUBLANG_ENGLISH_SINGAPORE 0x12
453 #endif
454 #ifndef SUBLANG_FRENCH_LUXEMBOURG
455 #define SUBLANG_FRENCH_LUXEMBOURG 0x05
456 #endif
457 #ifndef SUBLANG_FRENCH_MONACO
458 #define SUBLANG_FRENCH_MONACO 0x06
459 #endif
460 #ifndef SUBLANG_FRENCH_WESTINDIES
461 #define SUBLANG_FRENCH_WESTINDIES 0x07
462 #endif
463 #ifndef SUBLANG_FRENCH_REUNION
464 #define SUBLANG_FRENCH_REUNION 0x08
465 #endif
466 #ifndef SUBLANG_FRENCH_CONGO
467 #define SUBLANG_FRENCH_CONGO 0x09
468 #endif
469 #ifndef SUBLANG_FRENCH_SENEGAL
470 #define SUBLANG_FRENCH_SENEGAL 0x0a
471 #endif
472 #ifndef SUBLANG_FRENCH_CAMEROON
473 #define SUBLANG_FRENCH_CAMEROON 0x0b
474 #endif
475 #ifndef SUBLANG_FRENCH_COTEDIVOIRE
476 #define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
477 #endif
478 #ifndef SUBLANG_FRENCH_MALI
479 #define SUBLANG_FRENCH_MALI 0x0d
480 #endif
481 #ifndef SUBLANG_FRENCH_MOROCCO
482 #define SUBLANG_FRENCH_MOROCCO 0x0e
483 #endif
484 #ifndef SUBLANG_FRENCH_HAITI
485 #define SUBLANG_FRENCH_HAITI 0x0f
486 #endif
487 #ifndef SUBLANG_GERMAN_LUXEMBOURG
488 #define SUBLANG_GERMAN_LUXEMBOURG 0x04
489 #endif
490 #ifndef SUBLANG_GERMAN_LIECHTENSTEIN
491 #define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
492 #endif
493 #ifndef SUBLANG_KASHMIRI_INDIA
494 #define SUBLANG_KASHMIRI_INDIA 0x02
495 #endif
496 #ifndef SUBLANG_MALAY_MALAYSIA
497 #define SUBLANG_MALAY_MALAYSIA 0x01
498 #endif
499 #ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
500 #define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
501 #endif
502 #ifndef SUBLANG_NEPALI_INDIA
503 #define SUBLANG_NEPALI_INDIA 0x02
504 #endif
505 #ifndef SUBLANG_PUNJABI_INDIA
506 #define SUBLANG_PUNJABI_INDIA 0x01
507 #endif
508 #ifndef SUBLANG_ROMANIAN_ROMANIA
509 #define SUBLANG_ROMANIAN_ROMANIA 0x01
510 #endif
511 #ifndef SUBLANG_SERBIAN_LATIN
512 #define SUBLANG_SERBIAN_LATIN 0x02
513 #endif
514 #ifndef SUBLANG_SERBIAN_CYRILLIC
515 #define SUBLANG_SERBIAN_CYRILLIC 0x03
516 #endif
517 #ifndef SUBLANG_SINDHI_INDIA
518 #define SUBLANG_SINDHI_INDIA 0x00
519 #endif
520 #ifndef SUBLANG_SINDHI_PAKISTAN
521 #define SUBLANG_SINDHI_PAKISTAN 0x01
522 #endif
523 #ifndef SUBLANG_SPANISH_GUATEMALA
524 #define SUBLANG_SPANISH_GUATEMALA 0x04
525 #endif
526 #ifndef SUBLANG_SPANISH_COSTA_RICA
527 #define SUBLANG_SPANISH_COSTA_RICA 0x05
528 #endif
529 #ifndef SUBLANG_SPANISH_PANAMA
530 #define SUBLANG_SPANISH_PANAMA 0x06
531 #endif
532 #ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
533 #define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
534 #endif
535 #ifndef SUBLANG_SPANISH_VENEZUELA
536 #define SUBLANG_SPANISH_VENEZUELA 0x08
537 #endif
538 #ifndef SUBLANG_SPANISH_COLOMBIA
539 #define SUBLANG_SPANISH_COLOMBIA 0x09
540 #endif
541 #ifndef SUBLANG_SPANISH_PERU
542 #define SUBLANG_SPANISH_PERU 0x0a
543 #endif
544 #ifndef SUBLANG_SPANISH_ARGENTINA
545 #define SUBLANG_SPANISH_ARGENTINA 0x0b
546 #endif
547 #ifndef SUBLANG_SPANISH_ECUADOR
548 #define SUBLANG_SPANISH_ECUADOR 0x0c
549 #endif
550 #ifndef SUBLANG_SPANISH_CHILE
551 #define SUBLANG_SPANISH_CHILE 0x0d
552 #endif
553 #ifndef SUBLANG_SPANISH_URUGUAY
554 #define SUBLANG_SPANISH_URUGUAY 0x0e
555 #endif
556 #ifndef SUBLANG_SPANISH_PARAGUAY
557 #define SUBLANG_SPANISH_PARAGUAY 0x0f
558 #endif
559 #ifndef SUBLANG_SPANISH_BOLIVIA
560 #define SUBLANG_SPANISH_BOLIVIA 0x10
561 #endif
562 #ifndef SUBLANG_SPANISH_EL_SALVADOR
563 #define SUBLANG_SPANISH_EL_SALVADOR 0x11
564 #endif
565 #ifndef SUBLANG_SPANISH_HONDURAS
566 #define SUBLANG_SPANISH_HONDURAS 0x12
567 #endif
568 #ifndef SUBLANG_SPANISH_NICARAGUA
569 #define SUBLANG_SPANISH_NICARAGUA 0x13
570 #endif
571 #ifndef SUBLANG_SPANISH_PUERTO_RICO
572 #define SUBLANG_SPANISH_PUERTO_RICO 0x14
573 #endif
574 #ifndef SUBLANG_SWEDISH_FINLAND
575 #define SUBLANG_SWEDISH_FINLAND 0x02
576 #endif
577 #ifndef SUBLANG_TAMAZIGHT_ARABIC
578 #define SUBLANG_TAMAZIGHT_ARABIC 0x01
579 #endif
580 #ifndef SUBLANG_TAMAZIGHT_LATIN
581 #define SUBLANG_TAMAZIGHT_LATIN 0x02
582 #endif
583 #ifndef SUBLANG_TIGRINYA_ETHIOPIA
584 #define SUBLANG_TIGRINYA_ETHIOPIA 0x00
585 #endif
586 #ifndef SUBLANG_TIGRINYA_ERITREA
587 #define SUBLANG_TIGRINYA_ERITREA 0x01
588 #endif
589 #ifndef SUBLANG_URDU_PAKISTAN
590 #define SUBLANG_URDU_PAKISTAN 0x01
591 #endif
592 #ifndef SUBLANG_URDU_INDIA
593 #define SUBLANG_URDU_INDIA 0x02
594 #endif
595 #ifndef SUBLANG_UZBEK_LATIN
596 #define SUBLANG_UZBEK_LATIN 0x01
597 #endif
598 #ifndef SUBLANG_UZBEK_CYRILLIC
599 #define SUBLANG_UZBEK_CYRILLIC 0x02
600 #endif
601
602 /* Return an XPG style locale name
603      language[_territory[.codeset]][@modifier].
604    Don't even bother determining the codeset; it's not useful in this
605    context, because message catalogs are not specific to a single
606    codeset.  The result must not be freed; it is statically
607    allocated.  */
608 static const char *
609 my_nl_locale_name (const char *categoryname)
610 {
611   const char *retval;
612   LCID lcid;
613   LANGID langid;
614   int primary, sub;
615
616   /* Let the user override the system settings through environment
617      variables, as on POSIX systems.  */
618   retval = getenv ("LC_ALL");
619   if (retval != NULL && retval[0] != '\0')
620     return retval;
621   retval = getenv (categoryname);
622   if (retval != NULL && retval[0] != '\0')
623     return retval;
624   retval = getenv ("LANG");
625   if (retval != NULL && retval[0] != '\0')
626     return retval;
627
628   /* Use native Win32 API locale ID.  */
629   lcid = GetThreadLocale ();
630
631   /* Strip off the sorting rules, keep only the language part.  */
632   langid = LANGIDFROMLCID (lcid);
633
634   /* Split into language and territory part.  */
635   primary = PRIMARYLANGID (langid);
636   sub = SUBLANGID (langid);
637
638   /* Dispatch on language.
639      See also http://www.unicode.org/unicode/onlinedat/languages.html .
640      For details about languages, see http://www.ethnologue.com/ .  */
641   switch (primary)
642     {
643     case LANG_AFRIKAANS: return "af_ZA";
644     case LANG_ALBANIAN: return "sq_AL";
645     case LANG_AMHARIC: return "am_ET";
646     case LANG_ARABIC:
647       switch (sub)
648         {
649         case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
650         case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
651         case SUBLANG_ARABIC_EGYPT: return "ar_EG";
652         case SUBLANG_ARABIC_LIBYA: return "ar_LY";
653         case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
654         case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
655         case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
656         case SUBLANG_ARABIC_OMAN: return "ar_OM";
657         case SUBLANG_ARABIC_YEMEN: return "ar_YE";
658         case SUBLANG_ARABIC_SYRIA: return "ar_SY";
659         case SUBLANG_ARABIC_JORDAN: return "ar_JO";
660         case SUBLANG_ARABIC_LEBANON: return "ar_LB";
661         case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
662         case SUBLANG_ARABIC_UAE: return "ar_AE";
663         case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
664         case SUBLANG_ARABIC_QATAR: return "ar_QA";
665         }
666       return "ar";
667     case LANG_ARMENIAN: return "hy_AM";
668     case LANG_ASSAMESE: return "as_IN";
669     case LANG_AZERI:
670       switch (sub)
671         {
672         /* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
673         case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
674         case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
675         }
676       return "az";
677     case LANG_BASQUE:
678       return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
679     case LANG_BELARUSIAN: return "be_BY";
680     case LANG_BENGALI:
681       switch (sub)
682         {
683         case SUBLANG_BENGALI_INDIA: return "bn_IN";
684         case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
685         }
686       return "bn";
687     case LANG_BULGARIAN: return "bg_BG";
688     case LANG_BURMESE: return "my_MM";
689     case LANG_CAMBODIAN: return "km_KH";
690     case LANG_CATALAN: return "ca_ES";
691     case LANG_CHEROKEE: return "chr_US";
692     case LANG_CHINESE:
693       switch (sub)
694         {
695         case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
696         case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
697         case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
698         case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
699         case SUBLANG_CHINESE_MACAU: return "zh_MO";
700         }
701       return "zh";
702     case LANG_CROATIAN:         /* LANG_CROATIAN == LANG_SERBIAN
703                                  * What used to be called Serbo-Croatian
704                                  * should really now be two separate
705                                  * languages because of political reasons.
706                                  * (Says tml, who knows nothing about Serbian
707                                  * or Croatian.)
708                                  * (I can feel those flames coming already.)
709                                  */
710       switch (sub)
711         {
712         case SUBLANG_DEFAULT: return "hr_HR";
713         case SUBLANG_SERBIAN_LATIN: return "sr_CS";
714         case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
715         }
716       return "hr";
717     case LANG_CZECH: return "cs_CZ";
718     case LANG_DANISH: return "da_DK";
719     case LANG_DIVEHI: return "div_MV";
720     case LANG_DUTCH:
721       switch (sub)
722         {
723         case SUBLANG_DUTCH: return "nl_NL";
724         case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
725         }
726       return "nl";
727     case LANG_EDO: return "bin_NG";
728     case LANG_ENGLISH:
729       switch (sub)
730         {
731         /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
732          * English was the language spoken in England.
733          * Oh well.
734          */
735         case SUBLANG_ENGLISH_US: return "en_US";
736         case SUBLANG_ENGLISH_UK: return "en_GB";
737         case SUBLANG_ENGLISH_AUS: return "en_AU";
738         case SUBLANG_ENGLISH_CAN: return "en_CA";
739         case SUBLANG_ENGLISH_NZ: return "en_NZ";
740         case SUBLANG_ENGLISH_EIRE: return "en_IE";
741         case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
742         case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
743         case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
744         case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
745         case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
746         case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
747         case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
748         case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
749         case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
750         case SUBLANG_ENGLISH_INDIA: return "en_IN";
751         case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
752         case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
753         }
754       return "en";
755     case LANG_ESTONIAN: return "et_EE";
756     case LANG_FAEROESE: return "fo_FO";
757     case LANG_FARSI: return "fa_IR";
758     case LANG_FINNISH: return "fi_FI";
759     case LANG_FRENCH:
760       switch (sub)
761         {
762         case SUBLANG_FRENCH: return "fr_FR";
763         case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
764         case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
765         case SUBLANG_FRENCH_SWISS: return "fr_CH";
766         case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
767         case SUBLANG_FRENCH_MONACO: return "fr_MC";
768         case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
769         case SUBLANG_FRENCH_REUNION: return "fr_RE";
770         case SUBLANG_FRENCH_CONGO: return "fr_CG";
771         case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
772         case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
773         case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
774         case SUBLANG_FRENCH_MALI: return "fr_ML";
775         case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
776         case SUBLANG_FRENCH_HAITI: return "fr_HT";
777         }
778       return "fr";
779     case LANG_FRISIAN: return "fy_NL";
780     case LANG_FULFULDE: return "ful_NG";
781     case LANG_GAELIC:
782       switch (sub)
783         {
784         case 0x01: /* SCOTTISH */ return "gd_GB";
785         case 0x02: /* IRISH */ return "ga_IE";
786         }
787       return "C";
788     case LANG_GALICIAN: return "gl_ES";
789     case LANG_GEORGIAN: return "ka_GE";
790     case LANG_GERMAN:
791       switch (sub)
792         {
793         case SUBLANG_GERMAN: return "de_DE";
794         case SUBLANG_GERMAN_SWISS: return "de_CH";
795         case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
796         case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
797         case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
798         }
799       return "de";
800     case LANG_GREEK: return "el_GR";
801     case LANG_GUARANI: return "gn_PY";
802     case LANG_GUJARATI: return "gu_IN";
803     case LANG_HAUSA: return "ha_NG";
804     case LANG_HAWAIIAN:
805       /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
806          or Hawaii Creole English ("cpe_US", 600000 speakers)?  */
807       return "cpe_US";
808     case LANG_HEBREW: return "he_IL";
809     case LANG_HINDI: return "hi_IN";
810     case LANG_HUNGARIAN: return "hu_HU";
811     case LANG_IBIBIO: return "nic_NG";
812     case LANG_ICELANDIC: return "is_IS";
813     case LANG_IGBO: return "ibo_NG";
814     case LANG_INDONESIAN: return "id_ID";
815     case LANG_INUKTITUT: return "iu_CA";
816     case LANG_ITALIAN:
817       switch (sub)
818         {
819         case SUBLANG_ITALIAN: return "it_IT";
820         case SUBLANG_ITALIAN_SWISS: return "it_CH";
821         }
822       return "it";
823     case LANG_JAPANESE: return "ja_JP";
824     case LANG_KANNADA: return "kn_IN";
825     case LANG_KANURI: return "kau_NG";
826     case LANG_KASHMIRI:
827       switch (sub)
828         {
829         case SUBLANG_DEFAULT: return "ks_PK";
830         case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
831         }
832       return "ks";
833     case LANG_KAZAK: return "kk_KZ";
834     case LANG_KONKANI:
835       /* FIXME: Adjust this when such locales appear on Unix.  */
836       return "kok_IN";
837     case LANG_KOREAN: return "ko_KR";
838     case LANG_KYRGYZ: return "ky_KG";
839     case LANG_LAO: return "lo_LA";
840     case LANG_LATIN: return "la_VA";
841     case LANG_LATVIAN: return "lv_LV";
842     case LANG_LITHUANIAN: return "lt_LT";
843     case LANG_MACEDONIAN: return "mk_MK";
844     case LANG_MALAY:
845       switch (sub)
846         {
847         case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
848         case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
849         }
850       return "ms";
851     case LANG_MALAYALAM: return "ml_IN";
852     case LANG_MALTESE: return "mt_MT";
853     case LANG_MANIPURI:
854       /* FIXME: Adjust this when such locales appear on Unix.  */
855       return "mni_IN";
856     case LANG_MARATHI: return "mr_IN";
857     case LANG_MONGOLIAN:
858       return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN".  */
859     case LANG_NEPALI:
860       switch (sub)
861         {
862         case SUBLANG_DEFAULT: return "ne_NP";
863         case SUBLANG_NEPALI_INDIA: return "ne_IN";
864         }
865       return "ne";
866     case LANG_NORWEGIAN:
867       switch (sub)
868         {
869         case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
870         case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
871         }
872       return "no";
873     case LANG_ORIYA: return "or_IN";
874     case LANG_OROMO: return "om_ET";
875     case LANG_PAPIAMENTU: return "pap_AN";
876     case LANG_PASHTO:
877       return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF".  */
878     case LANG_POLISH: return "pl_PL";
879     case LANG_PORTUGUESE:
880       switch (sub)
881         {
882         case SUBLANG_PORTUGUESE: return "pt_PT";
883         /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
884            Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
885         case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
886         }
887       return "pt";
888     case LANG_PUNJABI:
889       switch (sub)
890         {
891         case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
892         }
893       return "pa";
894     case LANG_RHAETO_ROMANCE: return "rm_CH";
895     case LANG_ROMANIAN:
896       switch (sub)
897         {
898         case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
899         }
900       return "ro";
901     case LANG_RUSSIAN:
902       return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD".  */
903     case LANG_SAAMI: /* actually Northern Sami */ return "se_NO";
904     case LANG_SANSKRIT: return "sa_IN";
905     case LANG_SINDHI:
906       switch (sub)
907         {
908         case SUBLANG_SINDHI_INDIA: return "sd_IN";
909         case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
910         }
911       return "sd";
912     case LANG_SINHALESE: return "si_LK";
913     case LANG_SLOVAK: return "sk_SK";
914     case LANG_SLOVENIAN: return "sl_SI";
915     case LANG_SOMALI: return "so_SO";
916     case LANG_SORBIAN:
917       /* FIXME: Adjust this when such locales appear on Unix.  */
918       return "wen_DE";
919     case LANG_SPANISH:
920       switch (sub)
921         {
922         case SUBLANG_SPANISH: return "es_ES";
923         case SUBLANG_SPANISH_MEXICAN: return "es_MX";
924         case SUBLANG_SPANISH_MODERN:
925           return "es_ES@modern";        /* not seen on Unix */
926         case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
927         case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
928         case SUBLANG_SPANISH_PANAMA: return "es_PA";
929         case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
930         case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
931         case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
932         case SUBLANG_SPANISH_PERU: return "es_PE";
933         case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
934         case SUBLANG_SPANISH_ECUADOR: return "es_EC";
935         case SUBLANG_SPANISH_CHILE: return "es_CL";
936         case SUBLANG_SPANISH_URUGUAY: return "es_UY";
937         case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
938         case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
939         case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
940         case SUBLANG_SPANISH_HONDURAS: return "es_HN";
941         case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
942         case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
943         }
944       return "es";
945     case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
946     case LANG_SWAHILI: return "sw_KE";
947     case LANG_SWEDISH:
948       switch (sub)
949         {
950         case SUBLANG_DEFAULT: return "sv_SE";
951         case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
952         }
953       return "sv";
954     case LANG_SYRIAC: return "syr_TR"; /* An extinct language.  */
955     case LANG_TAGALOG: return "tl_PH";
956     case LANG_TAJIK: return "tg_TJ";
957     case LANG_TAMAZIGHT:
958       switch (sub)
959         {
960         /* FIXME: Adjust this when Tamazight locales appear on Unix.  */
961         case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
962         case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin";
963         }
964       return "ber_MA";
965     case LANG_TAMIL:
966       return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG".  */
967     case LANG_TATAR: return "tt_RU";
968     case LANG_TELUGU: return "te_IN";
969     case LANG_THAI: return "th_TH";
970     case LANG_TIBETAN: return "bo_CN";
971     case LANG_TIGRINYA:
972       switch (sub)
973         {
974         case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
975         case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
976         }
977       return "ti";
978     case LANG_TSONGA: return "ts_ZA";
979     case LANG_TSWANA: return "tn_BW";
980     case LANG_TURKISH: return "tr_TR";
981     case LANG_TURKMEN: return "tk_TM";
982     case LANG_UKRAINIAN: return "uk_UA";
983     case LANG_URDU:
984       switch (sub)
985         {
986         case SUBLANG_URDU_PAKISTAN: return "ur_PK";
987         case SUBLANG_URDU_INDIA: return "ur_IN";
988         }
989       return "ur";
990     case LANG_UZBEK:
991       switch (sub)
992         {
993         case SUBLANG_UZBEK_LATIN: return "uz_UZ";
994         case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
995         }
996       return "uz";
997     case LANG_VENDA:
998       /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
999          "ve" or not.
1000          http://www.loc.gov/standards/iso639-2/englangn.html has it, but
1001          http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't,  */
1002       return "ven_ZA"; /* or "ve_ZA"? */
1003     case LANG_VIETNAMESE: return "vi_VN";
1004     case LANG_WELSH: return "cy_GB";
1005     case LANG_XHOSA: return "xh_ZA";
1006     case LANG_YI: return "sit_CN";
1007     case LANG_YIDDISH: return "yi_IL";
1008     case LANG_YORUBA: return "yo_NG";
1009     case LANG_ZULU: return "zu_ZA";
1010     default: return "C";
1011     }
1012 }
1013
1014 /* localname.c from gettext END.  */
1015
1016
1017 \f
1018 /* Support functions.  */
1019
1020 static __inline__ uint32_t
1021 do_swap_u32 (uint32_t i)
1022 {
1023   return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
1024 }
1025
1026 #define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data))
1027
1028
1029 /* We assume to have `unsigned long int' value with at least 32 bits.  */
1030 #define HASHWORDBITS 32
1031
1032 /* The so called `hashpjw' function by P.J. Weinberger
1033    [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1034    1986, 1987 Bell Telephone Laboratories, Inc.]  */
1035 static __inline__ unsigned long
1036 hash_string( const char *str_param )
1037 {
1038   unsigned long int hval, g;
1039   const char *str = str_param;
1040
1041   hval = 0;
1042   while (*str != '\0')
1043     {
1044       hval <<= 4;
1045       hval += (unsigned long int) *str++;
1046       g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
1047       if (g != 0)
1048         {
1049           hval ^= g >> (HASHWORDBITS - 8);
1050           hval ^= g;
1051         }
1052     }
1053   return hval;
1054 }
1055
1056 /* static char * */
1057 /* my_xstrdup (const char *s) */
1058 /* { */
1059 /*   size_t n = strlen (s) + 1; */
1060 /*   char *p = jnlib_malloc (n); */
1061 /*   if (!p) */
1062 /*     abort (); */
1063 /*   strcpy (p, s); */
1064 /*   return p; */
1065 /* } */
1066
1067
1068 \f
1069 /* Generic message catalog and gettext stuff.  */
1070
1071 /* The magic number of the GNU message catalog format.  */
1072 #define MAGIC         0x950412de
1073 #define MAGIC_SWAPPED 0xde120495
1074
1075 /* Revision number of the currently used .mo (binary) file format.  */
1076 #define MO_REVISION_NUMBER 0
1077
1078
1079 /* Header for binary .mo file format.  */
1080 struct mo_file_header
1081 {
1082   /* The magic number.  */
1083   uint32_t magic;
1084   /* The revision number of the file format.  */
1085   uint32_t revision;
1086   /* The number of strings pairs.  */
1087   uint32_t nstrings;
1088   /* Offset of table with start offsets of original strings.  */
1089   uint32_t orig_tab_offset;
1090   /* Offset of table with start offsets of translation strings.  */
1091   uint32_t trans_tab_offset;
1092   /* Size of hashing table.  */
1093   uint32_t hash_tab_size;
1094   /* Offset of first hashing entry.  */
1095   uint32_t hash_tab_offset;
1096 };
1097
1098
1099 struct string_desc
1100 {
1101   /* Length of addressed string.  */
1102   uint32_t length;
1103   /* Offset of string in file.  */
1104   uint32_t offset;
1105 };
1106
1107
1108 struct overflow_space_s
1109 {
1110   struct overflow_space_s *next;
1111   uint32_t idx;
1112   uint32_t length;
1113   char d[1];
1114 };
1115
1116 struct loaded_domain
1117 {
1118   char *data;
1119   char *data_native; /* Data mapped to the native version of the
1120                         string.  (Allocated along with DATA). */
1121   int must_swap;
1122   uint32_t nstrings;
1123   uint32_t *mapped;  /* 0   := Not mapped (original utf8).
1124                         1   := Mapped to native encoding in overflow space.
1125                         >=2 := Mapped to native encoding. The values
1126                                gives the length of the mapped string.
1127                                becuase the 0 is included and an empty
1128                                string is not allowed we will enver get
1129                                values 0 and 1.  */
1130   struct overflow_space_s *overflow_space;
1131   struct string_desc *orig_tab;
1132   struct string_desc *trans_tab;
1133   uint32_t hash_size;
1134   uint32_t *hash_tab;
1135 };
1136
1137
1138 /* The domain we use.  We only support one domain at this point.  This
1139    is why this implementation can not be shared.  Bindtextdomain and
1140    dgettext will simply cheat and always use this one domain.  */
1141 static struct loaded_domain *the_domain;
1142
1143 /* Global flag to switch gettext into an utf8 mode.  */
1144 static int want_utf8;
1145
1146
1147 \f
1148 /* Free the domain data.  */
1149 static void
1150 free_domain (struct loaded_domain *domain)
1151 {
1152   struct overflow_space_s *os, *os2;
1153
1154   jnlib_free (domain->data);
1155   jnlib_free (domain->mapped);
1156   for (os = domain->overflow_space; os; os = os2)
1157     {
1158       os2 = os->next;
1159       jnlib_free (os);
1160     }
1161   jnlib_free (domain);
1162 }
1163
1164
1165 static struct loaded_domain *
1166 load_domain (const char *filename)
1167 {
1168   FILE *fp;
1169   size_t size;
1170   struct stat st;
1171   struct mo_file_header *data = NULL;
1172   struct loaded_domain *domain = NULL;
1173   size_t to_read;
1174   char *read_ptr;
1175
1176   fp = fopen (filename, "rb");
1177   if (!fp)
1178     return NULL;
1179
1180   /* Determine the file size.  */
1181   if (fstat (fileno (fp), &st)
1182       || (size = (size_t) st.st_size) != st.st_size
1183       || size < sizeof (struct mo_file_header))
1184     {
1185       fclose (fp);
1186       return NULL;
1187     }
1188
1189   data = (2*size <= size)? NULL : jnlib_malloc (2*size);
1190   if (!data)
1191     {
1192       fclose (fp);
1193       return NULL;
1194     }
1195
1196   to_read = size;
1197   read_ptr = (char *) data;
1198   do
1199     {
1200       long int nb = fread (read_ptr, 1, to_read, fp);
1201       if (nb < to_read)
1202         {
1203           fclose (fp);
1204           jnlib_free (data);
1205           return NULL;
1206         }
1207       read_ptr += nb;
1208       to_read -= nb;
1209     }
1210   while (to_read > 0);
1211   fclose (fp);
1212
1213   /* Using the magic number we can test whether it really is a message
1214      catalog file.  */
1215   if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
1216     {
1217       /* The magic number is wrong: not a message catalog file.  */
1218       jnlib_free (data);
1219       return NULL;
1220     }
1221
1222   domain = jnlib_calloc (1, sizeof *domain);
1223   if (!domain)
1224     {
1225       jnlib_free (data);
1226       return NULL;
1227     }
1228   domain->data = (char *) data;
1229   domain->data_native = (char *) data + size;
1230   domain->must_swap = data->magic != MAGIC;
1231
1232   /* Fill in the information about the available tables.  */
1233   switch (SWAPIT (domain->must_swap, data->revision))
1234     {
1235     case MO_REVISION_NUMBER:
1236       domain->nstrings = SWAPIT (domain->must_swap, data->nstrings);
1237       domain->orig_tab = (struct string_desc *)
1238         ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset));
1239       domain->trans_tab = (struct string_desc *)
1240         ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset));
1241       domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size);
1242       domain->hash_tab = (uint32_t *)
1243         ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset));
1244       break;
1245
1246     default:
1247       /* This is an invalid revision.   */
1248       jnlib_free (data);
1249       jnlib_free (domain);
1250       return NULL;
1251     }
1252
1253   /* Allocate an array to keep track of code page mappings.  */
1254   domain->mapped = jnlib_calloc (domain->nstrings, sizeof *domain->mapped);
1255   if (!domain->mapped)
1256     {
1257       jnlib_free (data);
1258       jnlib_free (domain);
1259       return NULL;
1260     }
1261
1262   return domain;
1263 }
1264
1265
1266 /* Return a malloced wide char string from an UTF-8 encoded input
1267    string STRING.  Caller must free this value. On failure returns
1268    NULL.  The result of calling this function with STRING set to NULL
1269    is not defined. */
1270 static wchar_t *
1271 utf8_to_wchar (const char *string, size_t length, size_t *retlen)
1272 {
1273   int n;
1274   wchar_t *result;
1275   size_t nbytes;
1276
1277   n = MultiByteToWideChar (CP_UTF8, 0, string, length, NULL, 0);
1278   if (n < 0 || (n+1) <= 0)
1279     return NULL;
1280
1281   nbytes = (size_t)(n+1) * sizeof(*result);
1282   if (nbytes / sizeof(*result) != (n+1))
1283     {
1284       errno = ENOMEM;
1285       return NULL;
1286     }
1287   result = jnlib_malloc (nbytes);
1288   if (!result)
1289     return NULL;
1290
1291   n = MultiByteToWideChar (CP_UTF8, 0, string, length, result, n);
1292   if (n < 0)
1293     {
1294       jnlib_free (result);
1295       return NULL;
1296     }
1297   *retlen = n;
1298   return result;
1299 }
1300
1301
1302 /* Return a malloced string encoded in UTF-8 from the wide char input
1303    string STRING.  Caller must free this value. On failure returns
1304    NULL.  The result of calling this function with STRING set to NULL
1305    is not defined. */
1306 static char *
1307 wchar_to_native (const wchar_t *string, size_t length, size_t *retlen)
1308 {
1309   int n;
1310   char *result;
1311
1312   n = WideCharToMultiByte (CP_ACP, 0, string, length, NULL, 0, NULL, NULL);
1313   if (n < 0 || (n+1) <= 0)
1314     return NULL;
1315
1316   result = jnlib_malloc (n+1);
1317   if (!result)
1318     return NULL;
1319
1320   n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL);
1321   if (n < 0)
1322     {
1323       jnlib_free (result);
1324       return NULL;
1325     }
1326   *retlen = n;
1327   return result;
1328 }
1329
1330
1331 /* Convert UTF8 to the native codepage.  Caller must free the return value. */
1332 static char *
1333 utf8_to_native (const char *string, size_t length, size_t *retlen)
1334 {
1335   wchar_t *wstring;
1336   char *result;
1337   size_t newlen;
1338
1339   wstring = utf8_to_wchar (string, length, &newlen);
1340   if (wstring)
1341     {
1342       result = wchar_to_native (wstring, newlen, &newlen);
1343       jnlib_free (wstring);
1344     }
1345   else
1346     result = NULL;
1347   *retlen = result? newlen : 0;
1348   return result;
1349 }
1350
1351
1352
1353 \f
1354 /* Specify that the DOMAINNAME message catalog will be found
1355    in DIRNAME rather than in the system locale data base.  */
1356 char *
1357 bindtextdomain (const char *domainname, const char *dirname)
1358 {
1359   struct loaded_domain *domain = NULL;
1360   const char *catval_full;
1361   char *catval;
1362   char *fname;
1363
1364   /* DOMAINNAME is ignored.  We only support one domain.  */
1365
1366   /* DIRNAME is "$INSTALLDIR\share\locale".  */
1367
1368   /* First find out the category value.  */
1369   catval = NULL;
1370   catval_full = my_nl_locale_name ("LC_MESSAGES");
1371
1372   /* Normally, we would have to loop over all returned locales, and
1373      search for the right file.  See gettext intl/dcigettext.c for all
1374      the gory details.  Here, we only support the basic category, and
1375      ignore everything else.  */
1376   if (catval_full)
1377     {
1378       char *p;
1379
1380       catval = jnlib_malloc (strlen (catval_full) + 1);
1381       if (catval)
1382         {
1383           strcpy (catval, catval_full);
1384           p = strchr (catval, '_');
1385           if (p)
1386             *p = '\0';
1387         }
1388     }
1389   if (!catval)
1390     return NULL;
1391
1392   /* Now build the filename string.  The complete filename is this:
1393      DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo  */
1394   {
1395     int len = strlen (dirname) + 1 + strlen (catval) + 13
1396       + strlen (domainname) + 3 + 1;
1397     char *p;
1398
1399     fname = jnlib_malloc (len);
1400     if (!fname)
1401       {
1402         jnlib_free (catval);
1403         return NULL;
1404       }
1405
1406     p = fname;
1407     strcpy (p, dirname);
1408     p += strlen (dirname);
1409     *(p++) = '\\';
1410     strcpy (p, catval);
1411     p += strlen (catval);
1412     strcpy (p, "\\LC_MESSAGES\\");
1413     p += 13;
1414     strcpy (p, domainname);
1415     p += strlen (domainname);
1416     strcpy (p, ".mo");
1417   }
1418
1419   domain = load_domain (fname);
1420   jnlib_free (catval);
1421   jnlib_free (fname);
1422
1423   /* We should not be invoked twice, but this is how you would do
1424      it if it happened.  */
1425   if (the_domain)
1426     free_domain (the_domain);
1427   the_domain = domain;
1428
1429   /* For historic reasons we are not allowed to return a const char*. */
1430   return (char*)dirname;
1431 }
1432
1433
1434
1435 \f
1436 static const char *
1437 get_plural (const char *data, size_t datalen, unsigned long nplural)
1438 {
1439   const char *p;
1440   int idx;
1441
1442   /* We only support the Germanic rule.  */
1443   idx = (nplural == 1? 0 : 1);
1444
1445   for (; idx; idx--)
1446     {
1447       p = strchr (data, 0) + 1;
1448       if (p >= data+datalen)
1449         return "ERROR in GETTEXT (bad plural entry)";
1450       datalen -= (p-data);
1451       data = p;
1452     }
1453   return data;
1454 }
1455
1456
1457 static const char*
1458 get_string (struct loaded_domain *domain, uint32_t idx,
1459             int use_plural, unsigned long nplural)
1460 {
1461   struct overflow_space_s *os;
1462   const char *trans;  /* Pointer to the translated entry.  */
1463   size_t translen;    /* Length of that entry.  */
1464
1465   if (want_utf8)
1466     {
1467       trans = (domain->data
1468                + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1469       translen = SWAPIT(domain->must_swap, domain->trans_tab[idx].length);
1470     }
1471   else if (!domain->mapped[idx])
1472     {
1473       /* Not yet mapped.  Map from utf-8 to native encoding now.  */
1474       const char *p_utf8;
1475       size_t plen_utf8, buflen;
1476       char *buf;
1477
1478       p_utf8 = (domain->data
1479                 + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1480       plen_utf8 = SWAPIT(domain->must_swap, domain->trans_tab[idx].length);
1481
1482       buf = utf8_to_native (p_utf8, plen_utf8, &buflen);
1483       if (!buf)
1484         {
1485           trans = "ERROR in GETTEXT MALLOC";
1486           translen = 0;
1487         }
1488       else if (buflen <= plen_utf8 && buflen > 1)
1489         {
1490           /* Copy into the DATA_NATIVE area. */
1491           char *p_tmp;
1492
1493           p_tmp = (domain->data_native
1494                    + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1495           memcpy (p_tmp, buf, buflen);
1496           domain->mapped[idx] = buflen;
1497           trans = p_tmp;
1498           translen = buflen;
1499         }
1500       else
1501         {
1502           /* There is not enough space for the translation (or for
1503              whatever reason an empry string is used): Store it in the
1504              overflow_space and mark that in the mapped array.
1505              Because UTF-8 strings are in general longer than the
1506              Windows 2 byte encodings, we expect that this won't
1507              happen too often (if at all) and thus we use a linked
1508              list to manage this space. */
1509           os = jnlib_malloc (sizeof *os + buflen);
1510           if (os)
1511             {
1512               os->idx = idx;
1513               memcpy (os->d, buf, buflen);
1514               os->length = buflen;
1515               os->next = domain->overflow_space;
1516               domain->overflow_space = os;
1517               domain->mapped[idx] = 1;
1518               trans = os->d;
1519               translen = os->length;
1520             }
1521           else
1522             {
1523               trans = "ERROR in GETTEXT MALLOC";
1524               translen = 0;
1525             }
1526         }
1527       jnlib_free (buf);
1528     }
1529   else if (domain->mapped[idx] == 1)
1530     {
1531       /* The translated string is in the overflow_space. */
1532       for (os=domain->overflow_space; os; os = os->next)
1533         if (os->idx == idx)
1534           break;
1535       if (os)
1536         {
1537           trans = os->d;
1538           translen = os->length;
1539         }
1540       else
1541         {
1542           trans = "ERROR in GETTEXT (overflow space)\n";
1543           translen = 0;
1544         }
1545     }
1546   else
1547     {
1548       trans = (domain->data_native
1549                + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset));
1550       translen = domain->mapped[idx];
1551     }
1552
1553   if (use_plural && translen)
1554     return get_plural (trans, translen, nplural);
1555   else
1556     return trans;
1557 }
1558
1559
1560 static const char *
1561 do_gettext (const char *msgid, const char *msgid2, unsigned long nplural)
1562 {
1563   struct loaded_domain *domain;
1564   uint32_t top, bottom, nstr;
1565
1566   if (!(domain = the_domain))
1567     goto not_found;
1568
1569   /* First try to use the hash table.  */
1570   if (domain->hash_size > 2 && domain->hash_tab)
1571     {
1572       /* Use the hashing table.  */
1573       uint32_t len = strlen (msgid);
1574       uint32_t hash_val = hash_string (msgid);
1575       uint32_t idx = hash_val % domain->hash_size;
1576       uint32_t incr = 1 + (hash_val % (domain->hash_size - 2));
1577
1578       while ( (nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx])) )
1579         {
1580           nstr--;
1581           if (nstr < domain->nstrings
1582               && SWAPIT(domain->must_swap,
1583                         domain->orig_tab[nstr].length) >= len
1584               && !strcmp (msgid, (domain->data
1585                                   + SWAPIT(domain->must_swap,
1586                                            domain->orig_tab[nstr].offset))))
1587             {
1588               return get_string (domain, nstr, !!msgid2, nplural);
1589             }
1590
1591           if (idx >= domain->hash_size - incr)
1592             idx -= domain->hash_size - incr;
1593           else
1594             idx += incr;
1595         }
1596     }
1597
1598   /* Now we try the default method: binary search in the sorted array
1599      of messages.  */
1600   bottom = 0;
1601   top = domain->nstrings;
1602   while (bottom < top)
1603     {
1604       int cmp_val;
1605
1606       nstr = (bottom + top) / 2;
1607       cmp_val = strcmp (msgid, (domain->data
1608                                 + SWAPIT(domain->must_swap,
1609                                          domain->orig_tab[nstr].offset)));
1610       if (cmp_val < 0)
1611         top = nstr;
1612       else if (cmp_val > 0)
1613         bottom = nstr + 1;
1614       else
1615         return get_string (domain, nstr, !!msgid2, nplural);
1616     }
1617
1618  not_found:
1619   /* We use the standard Germanic rule if plural has been requested.  */
1620   return msgid2? (nplural == 1? msgid : msgid2) : msgid;
1621 }
1622
1623
1624 char *
1625 textdomain (const char *domainname)
1626 {
1627   /* For now, support only one domain.  */
1628   return (char*)domainname;
1629 }
1630
1631
1632 const char *
1633 gettext (const char *msgid)
1634 {
1635   return do_gettext (msgid, NULL, 0);
1636 }
1637
1638 char *
1639 dgettext (const char *domainname, const char *msgid)
1640 {
1641   (void)domainname;
1642
1643   /* For now, support only one domain.  */
1644   return (char*)do_gettext (msgid, NULL, 0);
1645 }
1646
1647 const char *
1648 ngettext (const char *msgid1, const char *msgid2, unsigned long int n)
1649 {
1650   /* We use the simple Germanic plural rule.  */
1651   return do_gettext (msgid1, msgid2, n);
1652 }
1653
1654
1655 /* Return the locale name as used by gettext.  The return value will
1656    never be NULL. */
1657 const char *
1658 gettext_localename (void)
1659 {
1660   const char *s;
1661
1662   s = my_nl_locale_name ("LC_MESSAGES");
1663   return s? s:"";
1664 }
1665
1666 void
1667 gettext_select_utf8 (int value)
1668 {
1669   want_utf8 = value;
1670 }
1671
1672
1673 #ifdef TEST
1674 int
1675 main (int argc, char **argv)
1676 {
1677   const char atext1[] =
1678     "Warning: You have entered an insecure passphrase.%%0A"
1679     "A passphrase should be at least %u character long.";
1680   const char atext2[] =
1681     "Warning: You have entered an insecure passphrase.%%0A"
1682     "A passphrase should be at least %u characters long.";
1683
1684   if (argc)
1685     {
1686       argc--;
1687       argv++;
1688     }
1689
1690   bindtextdomain ("gnupg2", "c:/programme/gnu/gnupg/share/locale");
1691
1692   printf ("locale is `%s'\n", gettext_localename ());
1693   fputs ("text with N=1:\n", stdout);
1694   fputs (ngettext (atext1, atext2, 1), stdout);
1695   fputs ("\n\ntext with N=2:\n", stdout);
1696   fputs (ngettext (atext1, atext2, 2), stdout);
1697   fputs ("\nready\n", stdout);
1698
1699   return 0;
1700 }
1701 /*
1702  * Local Variables:
1703  *  compile-command: "i586-mingw32msvc-gcc -DTEST -Wall -g w32-gettext.c"
1704  * End:
1705  */
1706 #endif /*TEST*/