~ubuntu-branches/ubuntu/jaunty/gnupg2/jaunty-security

« back to all changes in this revision

Viewing changes to jnlib/w32-gettext.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
4
 *
 
5
 * This file is part of JNLIB.
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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/>.
 
19
 */
 
20
 
 
21
/* 
 
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
 
27
 */
 
28
 
 
29
#include <config.h>
 
30
#ifdef USE_SIMPLE_GETTEXT
 
31
# if !defined (_WIN32) && !defined (__CYGWIN32__)
 
32
#  error This module may only be build for Windows or Cygwin32
 
33
# endif
 
34
 
 
35
# include <stdio.h>
 
36
# include <stdlib.h>
 
37
# include <string.h>
 
38
# include <ctype.h>
 
39
# include <errno.h>
 
40
# include <sys/types.h>
 
41
# include <sys/stat.h>
 
42
 
 
43
# include "libjnlib-config.h"
 
44
# include "types.h"
 
45
# include "stringhelp.h"
 
46
# include "utf8conv.h"
 
47
# include "w32help.h"
 
48
 
 
49
# include "windows.h" /* For GetModuleFileName.  */
 
50
 
 
51
 
 
52
 
 
53
/* The magic number of the GNU message catalog format.  */
 
54
#define MAGIC         0x950412de
 
55
#define MAGIC_SWAPPED 0xde120495
 
56
 
 
57
/* Revision number of the currently used .mo (binary) file format.  */
 
58
#define MO_REVISION_NUMBER 0
 
59
 
 
60
 
 
61
/* Header for binary .mo file format.  */
 
62
struct mo_file_header
 
63
{
 
64
  /* The magic number.  */
 
65
  u32 magic;
 
66
  /* The revision number of the file format.  */
 
67
  u32 revision;
 
68
  /* The number of strings pairs.  */
 
69
  u32 nstrings;
 
70
  /* Offset of table with start offsets of original strings.  */
 
71
  u32 orig_tab_offset;
 
72
  /* Offset of table with start offsets of translation strings.  */
 
73
  u32 trans_tab_offset;
 
74
  /* Size of hashing table.  */
 
75
  u32 hash_tab_size;
 
76
  /* Offset of first hashing entry.  */
 
77
  u32 hash_tab_offset;
 
78
};
 
79
 
 
80
struct string_desc
 
81
{
 
82
  /* Length of addressed string.  */
 
83
  u32 length;
 
84
  /* Offset of string in file.  */
 
85
  u32 offset;
 
86
};
 
87
 
 
88
 
 
89
struct overflow_space_s
 
90
{
 
91
  struct overflow_space_s *next;
 
92
  u32 idx;
 
93
  char d[1];
 
94
};
 
95
 
 
96
struct loaded_domain
 
97
{
 
98
  char *data;
 
99
  int must_swap;
 
100
  u32 nstrings;
 
101
  char *mapped;  /* 0 = not yet mapped, 1 = mapped,
 
102
                    2 = mapped to
 
103
                    overflow space */
 
104
  struct overflow_space_s *overflow_space;
 
105
  struct string_desc *orig_tab;
 
106
  struct string_desc *trans_tab;
 
107
  u32 hash_size;
 
108
  u32 *hash_tab;
 
109
};
 
110
 
 
111
 
 
112
static struct loaded_domain *the_domain;
 
113
static char *the_langid;
 
114
 
 
115
static __inline__ u32
 
116
do_swap_u32( u32 i )
 
117
{
 
118
  return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
 
119
}
 
120
 
 
121
#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) )
 
122
 
 
123
 
 
124
/* We assume to have `unsigned long int' value with at least 32 bits.  */
 
125
#define HASHWORDBITS 32
 
126
 
 
127
 
 
128
 
 
129
/* BEGIN parts of localname.c from gettext.  */
 
130
 
 
131
/* Written by Ulrich Drepper <drepper@gnu.org>, 1995.  */
 
132
/* Win32 code written by Tor Lillqvist <tml@iki.fi>.  */
 
133
 
 
134
/* List of language codes, sorted by value:
 
135
   0x01 LANG_ARABIC
 
136
   0x02 LANG_BULGARIAN
 
137
   0x03 LANG_CATALAN
 
138
   0x04 LANG_CHINESE
 
139
   0x05 LANG_CZECH
 
140
   0x06 LANG_DANISH
 
141
   0x07 LANG_GERMAN
 
142
   0x08 LANG_GREEK
 
143
   0x09 LANG_ENGLISH
 
144
   0x0a LANG_SPANISH
 
145
   0x0b LANG_FINNISH
 
146
   0x0c LANG_FRENCH
 
147
   0x0d LANG_HEBREW
 
148
   0x0e LANG_HUNGARIAN
 
149
   0x0f LANG_ICELANDIC
 
150
   0x10 LANG_ITALIAN
 
151
   0x11 LANG_JAPANESE
 
152
   0x12 LANG_KOREAN
 
153
   0x13 LANG_DUTCH
 
154
   0x14 LANG_NORWEGIAN
 
155
   0x15 LANG_POLISH
 
156
   0x16 LANG_PORTUGUESE
 
157
   0x17 LANG_RHAETO_ROMANCE
 
158
   0x18 LANG_ROMANIAN
 
159
   0x19 LANG_RUSSIAN
 
160
   0x1a LANG_CROATIAN == LANG_SERBIAN
 
161
   0x1b LANG_SLOVAK
 
162
   0x1c LANG_ALBANIAN
 
163
   0x1d LANG_SWEDISH
 
164
   0x1e LANG_THAI
 
165
   0x1f LANG_TURKISH
 
166
   0x20 LANG_URDU
 
167
   0x21 LANG_INDONESIAN
 
168
   0x22 LANG_UKRAINIAN
 
169
   0x23 LANG_BELARUSIAN
 
170
   0x24 LANG_SLOVENIAN
 
171
   0x25 LANG_ESTONIAN
 
172
   0x26 LANG_LATVIAN
 
173
   0x27 LANG_LITHUANIAN
 
174
   0x28 LANG_TAJIK
 
175
   0x29 LANG_FARSI
 
176
   0x2a LANG_VIETNAMESE
 
177
   0x2b LANG_ARMENIAN
 
178
   0x2c LANG_AZERI
 
179
   0x2d LANG_BASQUE
 
180
   0x2e LANG_SORBIAN
 
181
   0x2f LANG_MACEDONIAN
 
182
   0x30 LANG_SUTU
 
183
   0x31 LANG_TSONGA
 
184
   0x32 LANG_TSWANA
 
185
   0x33 LANG_VENDA
 
186
   0x34 LANG_XHOSA
 
187
   0x35 LANG_ZULU
 
188
   0x36 LANG_AFRIKAANS
 
189
   0x37 LANG_GEORGIAN
 
190
   0x38 LANG_FAEROESE
 
191
   0x39 LANG_HINDI
 
192
   0x3a LANG_MALTESE
 
193
   0x3b LANG_SAAMI
 
194
   0x3c LANG_GAELIC
 
195
   0x3d LANG_YIDDISH
 
196
   0x3e LANG_MALAY
 
197
   0x3f LANG_KAZAK
 
198
   0x40 LANG_KYRGYZ
 
199
   0x41 LANG_SWAHILI
 
200
   0x42 LANG_TURKMEN
 
201
   0x43 LANG_UZBEK
 
202
   0x44 LANG_TATAR
 
203
   0x45 LANG_BENGALI
 
204
   0x46 LANG_PUNJABI
 
205
   0x47 LANG_GUJARATI
 
206
   0x48 LANG_ORIYA
 
207
   0x49 LANG_TAMIL
 
208
   0x4a LANG_TELUGU
 
209
   0x4b LANG_KANNADA
 
210
   0x4c LANG_MALAYALAM
 
211
   0x4d LANG_ASSAMESE
 
212
   0x4e LANG_MARATHI
 
213
   0x4f LANG_SANSKRIT
 
214
   0x50 LANG_MONGOLIAN
 
215
   0x51 LANG_TIBETAN
 
216
   0x52 LANG_WELSH
 
217
   0x53 LANG_CAMBODIAN
 
218
   0x54 LANG_LAO
 
219
   0x55 LANG_BURMESE
 
220
   0x56 LANG_GALICIAN
 
221
   0x57 LANG_KONKANI
 
222
   0x58 LANG_MANIPURI
 
223
   0x59 LANG_SINDHI
 
224
   0x5a LANG_SYRIAC
 
225
   0x5b LANG_SINHALESE
 
226
   0x5c LANG_CHEROKEE
 
227
   0x5d LANG_INUKTITUT
 
228
   0x5e LANG_AMHARIC
 
229
   0x5f LANG_TAMAZIGHT
 
230
   0x60 LANG_KASHMIRI
 
231
   0x61 LANG_NEPALI
 
232
   0x62 LANG_FRISIAN
 
233
   0x63 LANG_PASHTO
 
234
   0x64 LANG_TAGALOG
 
235
   0x65 LANG_DIVEHI
 
236
   0x66 LANG_EDO
 
237
   0x67 LANG_FULFULDE
 
238
   0x68 LANG_HAUSA
 
239
   0x69 LANG_IBIBIO
 
240
   0x6a LANG_YORUBA
 
241
   0x70 LANG_IGBO
 
242
   0x71 LANG_KANURI
 
243
   0x72 LANG_OROMO
 
244
   0x73 LANG_TIGRINYA
 
245
   0x74 LANG_GUARANI
 
246
   0x75 LANG_HAWAIIAN
 
247
   0x76 LANG_LATIN
 
248
   0x77 LANG_SOMALI
 
249
   0x78 LANG_YI
 
250
   0x79 LANG_PAPIAMENTU
 
251
*/
 
252
/* Mingw headers don't have latest language and sublanguage codes.  */
 
253
# ifndef LANG_AFRIKAANS
 
254
# define LANG_AFRIKAANS 0x36
 
255
# endif
 
256
# ifndef LANG_ALBANIAN
 
257
# define LANG_ALBANIAN 0x1c
 
258
# endif
 
259
# ifndef LANG_AMHARIC
 
260
# define LANG_AMHARIC 0x5e
 
261
# endif
 
262
# ifndef LANG_ARABIC
 
263
# define LANG_ARABIC 0x01
 
264
# endif
 
265
# ifndef LANG_ARMENIAN
 
266
# define LANG_ARMENIAN 0x2b
 
267
# endif
 
268
# ifndef LANG_ASSAMESE
 
269
# define LANG_ASSAMESE 0x4d
 
270
# endif
 
271
# ifndef LANG_AZERI
 
272
# define LANG_AZERI 0x2c
 
273
# endif
 
274
# ifndef LANG_BASQUE
 
275
# define LANG_BASQUE 0x2d
 
276
# endif
 
277
# ifndef LANG_BELARUSIAN
 
278
# define LANG_BELARUSIAN 0x23
 
279
# endif
 
280
# ifndef LANG_BENGALI
 
281
# define LANG_BENGALI 0x45
 
282
# endif
 
283
# ifndef LANG_BURMESE
 
284
# define LANG_BURMESE 0x55
 
285
# endif
 
286
# ifndef LANG_CAMBODIAN
 
287
# define LANG_CAMBODIAN 0x53
 
288
# endif
 
289
# ifndef LANG_CATALAN
 
290
# define LANG_CATALAN 0x03
 
291
# endif
 
292
# ifndef LANG_CHEROKEE
 
293
# define LANG_CHEROKEE 0x5c
 
294
# endif
 
295
# ifndef LANG_DIVEHI
 
296
# define LANG_DIVEHI 0x65
 
297
# endif
 
298
# ifndef LANG_EDO
 
299
# define LANG_EDO 0x66
 
300
# endif
 
301
# ifndef LANG_ESTONIAN
 
302
# define LANG_ESTONIAN 0x25
 
303
# endif
 
304
# ifndef LANG_FAEROESE
 
305
# define LANG_FAEROESE 0x38
 
306
# endif
 
307
# ifndef LANG_FARSI
 
308
# define LANG_FARSI 0x29
 
309
# endif
 
310
# ifndef LANG_FRISIAN
 
311
# define LANG_FRISIAN 0x62
 
312
# endif
 
313
# ifndef LANG_FULFULDE
 
314
# define LANG_FULFULDE 0x67
 
315
# endif
 
316
# ifndef LANG_GAELIC
 
317
# define LANG_GAELIC 0x3c
 
318
# endif
 
319
# ifndef LANG_GALICIAN
 
320
# define LANG_GALICIAN 0x56
 
321
# endif
 
322
# ifndef LANG_GEORGIAN
 
323
# define LANG_GEORGIAN 0x37
 
324
# endif
 
325
# ifndef LANG_GUARANI
 
326
# define LANG_GUARANI 0x74
 
327
# endif
 
328
# ifndef LANG_GUJARATI
 
329
# define LANG_GUJARATI 0x47
 
330
# endif
 
331
# ifndef LANG_HAUSA
 
332
# define LANG_HAUSA 0x68
 
333
# endif
 
334
# ifndef LANG_HAWAIIAN
 
335
# define LANG_HAWAIIAN 0x75
 
336
# endif
 
337
# ifndef LANG_HEBREW
 
338
# define LANG_HEBREW 0x0d
 
339
# endif
 
340
# ifndef LANG_HINDI
 
341
# define LANG_HINDI 0x39
 
342
# endif
 
343
# ifndef LANG_IBIBIO
 
344
# define LANG_IBIBIO 0x69
 
345
# endif
 
346
# ifndef LANG_IGBO
 
347
# define LANG_IGBO 0x70
 
348
# endif
 
349
# ifndef LANG_INDONESIAN
 
350
# define LANG_INDONESIAN 0x21
 
351
# endif
 
352
# ifndef LANG_INUKTITUT
 
353
# define LANG_INUKTITUT 0x5d
 
354
# endif
 
355
# ifndef LANG_KANNADA
 
356
# define LANG_KANNADA 0x4b
 
357
# endif
 
358
# ifndef LANG_KANURI
 
359
# define LANG_KANURI 0x71
 
360
# endif
 
361
# ifndef LANG_KASHMIRI
 
362
# define LANG_KASHMIRI 0x60
 
363
# endif
 
364
# ifndef LANG_KAZAK
 
365
# define LANG_KAZAK 0x3f
 
366
# endif
 
367
# ifndef LANG_KONKANI
 
368
# define LANG_KONKANI 0x57
 
369
# endif
 
370
# ifndef LANG_KYRGYZ
 
371
# define LANG_KYRGYZ 0x40
 
372
# endif
 
373
# ifndef LANG_LAO
 
374
# define LANG_LAO 0x54
 
375
# endif
 
376
# ifndef LANG_LATIN
 
377
# define LANG_LATIN 0x76
 
378
# endif
 
379
# ifndef LANG_LATVIAN
 
380
# define LANG_LATVIAN 0x26
 
381
# endif
 
382
# ifndef LANG_LITHUANIAN
 
383
# define LANG_LITHUANIAN 0x27
 
384
# endif
 
385
# ifndef LANG_MACEDONIAN
 
386
# define LANG_MACEDONIAN 0x2f
 
387
# endif
 
388
# ifndef LANG_MALAY
 
389
# define LANG_MALAY 0x3e
 
390
# endif
 
391
# ifndef LANG_MALAYALAM
 
392
# define LANG_MALAYALAM 0x4c
 
393
# endif
 
394
# ifndef LANG_MALTESE
 
395
# define LANG_MALTESE 0x3a
 
396
# endif
 
397
# ifndef LANG_MANIPURI
 
398
# define LANG_MANIPURI 0x58
 
399
# endif
 
400
# ifndef LANG_MARATHI
 
401
# define LANG_MARATHI 0x4e
 
402
# endif
 
403
# ifndef LANG_MONGOLIAN
 
404
# define LANG_MONGOLIAN 0x50
 
405
# endif
 
406
# ifndef LANG_NEPALI
 
407
# define LANG_NEPALI 0x61
 
408
# endif
 
409
# ifndef LANG_ORIYA
 
410
# define LANG_ORIYA 0x48
 
411
# endif
 
412
# ifndef LANG_OROMO
 
413
# define LANG_OROMO 0x72
 
414
# endif
 
415
# ifndef LANG_PAPIAMENTU
 
416
# define LANG_PAPIAMENTU 0x79
 
417
# endif
 
418
# ifndef LANG_PASHTO
 
419
# define LANG_PASHTO 0x63
 
420
# endif
 
421
# ifndef LANG_PUNJABI
 
422
# define LANG_PUNJABI 0x46
 
423
# endif
 
424
# ifndef LANG_RHAETO_ROMANCE
 
425
# define LANG_RHAETO_ROMANCE 0x17
 
426
# endif
 
427
# ifndef LANG_SAAMI
 
428
# define LANG_SAAMI 0x3b
 
429
# endif
 
430
# ifndef LANG_SANSKRIT
 
431
# define LANG_SANSKRIT 0x4f
 
432
# endif
 
433
# ifndef LANG_SERBIAN
 
434
# define LANG_SERBIAN 0x1a
 
435
# endif
 
436
# ifndef LANG_SINDHI
 
437
# define LANG_SINDHI 0x59
 
438
# endif
 
439
# ifndef LANG_SINHALESE
 
440
# define LANG_SINHALESE 0x5b
 
441
# endif
 
442
# ifndef LANG_SLOVAK
 
443
# define LANG_SLOVAK 0x1b
 
444
# endif
 
445
# ifndef LANG_SOMALI
 
446
# define LANG_SOMALI 0x77
 
447
# endif
 
448
# ifndef LANG_SORBIAN
 
449
# define LANG_SORBIAN 0x2e
 
450
# endif
 
451
# ifndef LANG_SUTU
 
452
# define LANG_SUTU 0x30
 
453
# endif
 
454
# ifndef LANG_SWAHILI
 
455
# define LANG_SWAHILI 0x41
 
456
# endif
 
457
# ifndef LANG_SYRIAC
 
458
# define LANG_SYRIAC 0x5a
 
459
# endif
 
460
# ifndef LANG_TAGALOG
 
461
# define LANG_TAGALOG 0x64
 
462
# endif
 
463
# ifndef LANG_TAJIK
 
464
# define LANG_TAJIK 0x28
 
465
# endif
 
466
# ifndef LANG_TAMAZIGHT
 
467
# define LANG_TAMAZIGHT 0x5f
 
468
# endif
 
469
# ifndef LANG_TAMIL
 
470
# define LANG_TAMIL 0x49
 
471
# endif
 
472
# ifndef LANG_TATAR
 
473
# define LANG_TATAR 0x44
 
474
# endif
 
475
# ifndef LANG_TELUGU
 
476
# define LANG_TELUGU 0x4a
 
477
# endif
 
478
# ifndef LANG_THAI
 
479
# define LANG_THAI 0x1e
 
480
# endif
 
481
# ifndef LANG_TIBETAN
 
482
# define LANG_TIBETAN 0x51
 
483
# endif
 
484
# ifndef LANG_TIGRINYA
 
485
# define LANG_TIGRINYA 0x73
 
486
# endif
 
487
# ifndef LANG_TSONGA
 
488
# define LANG_TSONGA 0x31
 
489
# endif
 
490
# ifndef LANG_TSWANA
 
491
# define LANG_TSWANA 0x32
 
492
# endif
 
493
# ifndef LANG_TURKMEN
 
494
# define LANG_TURKMEN 0x42
 
495
# endif
 
496
# ifndef LANG_UKRAINIAN
 
497
# define LANG_UKRAINIAN 0x22
 
498
# endif
 
499
# ifndef LANG_URDU
 
500
# define LANG_URDU 0x20
 
501
# endif
 
502
# ifndef LANG_UZBEK
 
503
# define LANG_UZBEK 0x43
 
504
# endif
 
505
# ifndef LANG_VENDA
 
506
# define LANG_VENDA 0x33
 
507
# endif
 
508
# ifndef LANG_VIETNAMESE
 
509
# define LANG_VIETNAMESE 0x2a
 
510
# endif
 
511
# ifndef LANG_WELSH
 
512
# define LANG_WELSH 0x52
 
513
# endif
 
514
# ifndef LANG_XHOSA
 
515
# define LANG_XHOSA 0x34
 
516
# endif
 
517
# ifndef LANG_YI
 
518
# define LANG_YI 0x78
 
519
# endif
 
520
# ifndef LANG_YIDDISH
 
521
# define LANG_YIDDISH 0x3d
 
522
# endif
 
523
# ifndef LANG_YORUBA
 
524
# define LANG_YORUBA 0x6a
 
525
# endif
 
526
# ifndef LANG_ZULU
 
527
# define LANG_ZULU 0x35
 
528
# endif
 
529
# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
 
530
# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
 
531
# endif
 
532
# ifndef SUBLANG_ARABIC_IRAQ
 
533
# define SUBLANG_ARABIC_IRAQ 0x02
 
534
# endif
 
535
# ifndef SUBLANG_ARABIC_EGYPT
 
536
# define SUBLANG_ARABIC_EGYPT 0x03
 
537
# endif
 
538
# ifndef SUBLANG_ARABIC_LIBYA
 
539
# define SUBLANG_ARABIC_LIBYA 0x04
 
540
# endif
 
541
# ifndef SUBLANG_ARABIC_ALGERIA
 
542
# define SUBLANG_ARABIC_ALGERIA 0x05
 
543
# endif
 
544
# ifndef SUBLANG_ARABIC_MOROCCO
 
545
# define SUBLANG_ARABIC_MOROCCO 0x06
 
546
# endif
 
547
# ifndef SUBLANG_ARABIC_TUNISIA
 
548
# define SUBLANG_ARABIC_TUNISIA 0x07
 
549
# endif
 
550
# ifndef SUBLANG_ARABIC_OMAN
 
551
# define SUBLANG_ARABIC_OMAN 0x08
 
552
# endif
 
553
# ifndef SUBLANG_ARABIC_YEMEN
 
554
# define SUBLANG_ARABIC_YEMEN 0x09
 
555
# endif
 
556
# ifndef SUBLANG_ARABIC_SYRIA
 
557
# define SUBLANG_ARABIC_SYRIA 0x0a
 
558
# endif
 
559
# ifndef SUBLANG_ARABIC_JORDAN
 
560
# define SUBLANG_ARABIC_JORDAN 0x0b
 
561
# endif
 
562
# ifndef SUBLANG_ARABIC_LEBANON
 
563
# define SUBLANG_ARABIC_LEBANON 0x0c
 
564
# endif
 
565
# ifndef SUBLANG_ARABIC_KUWAIT
 
566
# define SUBLANG_ARABIC_KUWAIT 0x0d
 
567
# endif
 
568
# ifndef SUBLANG_ARABIC_UAE
 
569
# define SUBLANG_ARABIC_UAE 0x0e
 
570
# endif
 
571
# ifndef SUBLANG_ARABIC_BAHRAIN
 
572
# define SUBLANG_ARABIC_BAHRAIN 0x0f
 
573
# endif
 
574
# ifndef SUBLANG_ARABIC_QATAR
 
575
# define SUBLANG_ARABIC_QATAR 0x10
 
576
# endif
 
577
# ifndef SUBLANG_AZERI_LATIN
 
578
# define SUBLANG_AZERI_LATIN 0x01
 
579
# endif
 
580
# ifndef SUBLANG_AZERI_CYRILLIC
 
581
# define SUBLANG_AZERI_CYRILLIC 0x02
 
582
# endif
 
583
# ifndef SUBLANG_BENGALI_INDIA
 
584
# define SUBLANG_BENGALI_INDIA 0x01
 
585
# endif
 
586
# ifndef SUBLANG_BENGALI_BANGLADESH
 
587
# define SUBLANG_BENGALI_BANGLADESH 0x02
 
588
# endif
 
589
# ifndef SUBLANG_CHINESE_MACAU
 
590
# define SUBLANG_CHINESE_MACAU 0x05
 
591
# endif
 
592
# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
 
593
# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
 
594
# endif
 
595
# ifndef SUBLANG_ENGLISH_JAMAICA
 
596
# define SUBLANG_ENGLISH_JAMAICA 0x08
 
597
# endif
 
598
# ifndef SUBLANG_ENGLISH_CARIBBEAN
 
599
# define SUBLANG_ENGLISH_CARIBBEAN 0x09
 
600
# endif
 
601
# ifndef SUBLANG_ENGLISH_BELIZE
 
602
# define SUBLANG_ENGLISH_BELIZE 0x0a
 
603
# endif
 
604
# ifndef SUBLANG_ENGLISH_TRINIDAD
 
605
# define SUBLANG_ENGLISH_TRINIDAD 0x0b
 
606
# endif
 
607
# ifndef SUBLANG_ENGLISH_ZIMBABWE
 
608
# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
 
609
# endif
 
610
# ifndef SUBLANG_ENGLISH_PHILIPPINES
 
611
# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
 
612
# endif
 
613
# ifndef SUBLANG_ENGLISH_INDONESIA
 
614
# define SUBLANG_ENGLISH_INDONESIA 0x0e
 
615
# endif
 
616
# ifndef SUBLANG_ENGLISH_HONGKONG
 
617
# define SUBLANG_ENGLISH_HONGKONG 0x0f
 
618
# endif
 
619
# ifndef SUBLANG_ENGLISH_INDIA
 
620
# define SUBLANG_ENGLISH_INDIA 0x10
 
621
# endif
 
622
# ifndef SUBLANG_ENGLISH_MALAYSIA
 
623
# define SUBLANG_ENGLISH_MALAYSIA 0x11
 
624
# endif
 
625
# ifndef SUBLANG_ENGLISH_SINGAPORE
 
626
# define SUBLANG_ENGLISH_SINGAPORE 0x12
 
627
# endif
 
628
# ifndef SUBLANG_FRENCH_LUXEMBOURG
 
629
# define SUBLANG_FRENCH_LUXEMBOURG 0x05
 
630
# endif
 
631
# ifndef SUBLANG_FRENCH_MONACO
 
632
# define SUBLANG_FRENCH_MONACO 0x06
 
633
# endif
 
634
# ifndef SUBLANG_FRENCH_WESTINDIES
 
635
# define SUBLANG_FRENCH_WESTINDIES 0x07
 
636
# endif
 
637
# ifndef SUBLANG_FRENCH_REUNION
 
638
# define SUBLANG_FRENCH_REUNION 0x08
 
639
# endif
 
640
# ifndef SUBLANG_FRENCH_CONGO
 
641
# define SUBLANG_FRENCH_CONGO 0x09
 
642
# endif
 
643
# ifndef SUBLANG_FRENCH_SENEGAL
 
644
# define SUBLANG_FRENCH_SENEGAL 0x0a
 
645
# endif
 
646
# ifndef SUBLANG_FRENCH_CAMEROON
 
647
# define SUBLANG_FRENCH_CAMEROON 0x0b
 
648
# endif
 
649
# ifndef SUBLANG_FRENCH_COTEDIVOIRE
 
650
# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
 
651
# endif
 
652
# ifndef SUBLANG_FRENCH_MALI
 
653
# define SUBLANG_FRENCH_MALI 0x0d
 
654
# endif
 
655
# ifndef SUBLANG_FRENCH_MOROCCO
 
656
# define SUBLANG_FRENCH_MOROCCO 0x0e
 
657
# endif
 
658
# ifndef SUBLANG_FRENCH_HAITI
 
659
# define SUBLANG_FRENCH_HAITI 0x0f
 
660
# endif
 
661
# ifndef SUBLANG_GERMAN_LUXEMBOURG
 
662
# define SUBLANG_GERMAN_LUXEMBOURG 0x04
 
663
# endif
 
664
# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
 
665
# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
 
666
# endif
 
667
# ifndef SUBLANG_KASHMIRI_INDIA
 
668
# define SUBLANG_KASHMIRI_INDIA 0x02
 
669
# endif
 
670
# ifndef SUBLANG_MALAY_MALAYSIA
 
671
# define SUBLANG_MALAY_MALAYSIA 0x01
 
672
# endif
 
673
# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
 
674
# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
 
675
# endif
 
676
# ifndef SUBLANG_NEPALI_INDIA
 
677
# define SUBLANG_NEPALI_INDIA 0x02
 
678
# endif
 
679
# ifndef SUBLANG_PUNJABI_INDIA
 
680
# define SUBLANG_PUNJABI_INDIA 0x01
 
681
# endif
 
682
# ifndef SUBLANG_ROMANIAN_ROMANIA
 
683
# define SUBLANG_ROMANIAN_ROMANIA 0x01
 
684
# endif
 
685
# ifndef SUBLANG_SERBIAN_LATIN
 
686
# define SUBLANG_SERBIAN_LATIN 0x02
 
687
# endif
 
688
# ifndef SUBLANG_SERBIAN_CYRILLIC
 
689
# define SUBLANG_SERBIAN_CYRILLIC 0x03
 
690
# endif
 
691
# ifndef SUBLANG_SINDHI_INDIA
 
692
# define SUBLANG_SINDHI_INDIA 0x00
 
693
# endif
 
694
# ifndef SUBLANG_SINDHI_PAKISTAN
 
695
# define SUBLANG_SINDHI_PAKISTAN 0x01
 
696
# endif
 
697
# ifndef SUBLANG_SPANISH_GUATEMALA
 
698
# define SUBLANG_SPANISH_GUATEMALA 0x04
 
699
# endif
 
700
# ifndef SUBLANG_SPANISH_COSTA_RICA
 
701
# define SUBLANG_SPANISH_COSTA_RICA 0x05
 
702
# endif
 
703
# ifndef SUBLANG_SPANISH_PANAMA
 
704
# define SUBLANG_SPANISH_PANAMA 0x06
 
705
# endif
 
706
# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
 
707
# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
 
708
# endif
 
709
# ifndef SUBLANG_SPANISH_VENEZUELA
 
710
# define SUBLANG_SPANISH_VENEZUELA 0x08
 
711
# endif
 
712
# ifndef SUBLANG_SPANISH_COLOMBIA
 
713
# define SUBLANG_SPANISH_COLOMBIA 0x09
 
714
# endif
 
715
# ifndef SUBLANG_SPANISH_PERU
 
716
# define SUBLANG_SPANISH_PERU 0x0a
 
717
# endif
 
718
# ifndef SUBLANG_SPANISH_ARGENTINA
 
719
# define SUBLANG_SPANISH_ARGENTINA 0x0b
 
720
# endif
 
721
# ifndef SUBLANG_SPANISH_ECUADOR
 
722
# define SUBLANG_SPANISH_ECUADOR 0x0c
 
723
# endif
 
724
# ifndef SUBLANG_SPANISH_CHILE
 
725
# define SUBLANG_SPANISH_CHILE 0x0d
 
726
# endif
 
727
# ifndef SUBLANG_SPANISH_URUGUAY
 
728
# define SUBLANG_SPANISH_URUGUAY 0x0e
 
729
# endif
 
730
# ifndef SUBLANG_SPANISH_PARAGUAY
 
731
# define SUBLANG_SPANISH_PARAGUAY 0x0f
 
732
# endif
 
733
# ifndef SUBLANG_SPANISH_BOLIVIA
 
734
# define SUBLANG_SPANISH_BOLIVIA 0x10
 
735
# endif
 
736
# ifndef SUBLANG_SPANISH_EL_SALVADOR
 
737
# define SUBLANG_SPANISH_EL_SALVADOR 0x11
 
738
# endif
 
739
# ifndef SUBLANG_SPANISH_HONDURAS
 
740
# define SUBLANG_SPANISH_HONDURAS 0x12
 
741
# endif
 
742
# ifndef SUBLANG_SPANISH_NICARAGUA
 
743
# define SUBLANG_SPANISH_NICARAGUA 0x13
 
744
# endif
 
745
# ifndef SUBLANG_SPANISH_PUERTO_RICO
 
746
# define SUBLANG_SPANISH_PUERTO_RICO 0x14
 
747
# endif
 
748
# ifndef SUBLANG_SWEDISH_FINLAND
 
749
# define SUBLANG_SWEDISH_FINLAND 0x02
 
750
# endif
 
751
# ifndef SUBLANG_TAMAZIGHT_ARABIC
 
752
# define SUBLANG_TAMAZIGHT_ARABIC 0x01
 
753
# endif
 
754
# ifndef SUBLANG_TAMAZIGHT_LATIN
 
755
# define SUBLANG_TAMAZIGHT_LATIN 0x02
 
756
# endif
 
757
# ifndef SUBLANG_TIGRINYA_ETHIOPIA
 
758
# define SUBLANG_TIGRINYA_ETHIOPIA 0x00
 
759
# endif
 
760
# ifndef SUBLANG_TIGRINYA_ERITREA
 
761
# define SUBLANG_TIGRINYA_ERITREA 0x01
 
762
# endif
 
763
# ifndef SUBLANG_URDU_PAKISTAN
 
764
# define SUBLANG_URDU_PAKISTAN 0x01
 
765
# endif
 
766
# ifndef SUBLANG_URDU_INDIA
 
767
# define SUBLANG_URDU_INDIA 0x02
 
768
# endif
 
769
# ifndef SUBLANG_UZBEK_LATIN
 
770
# define SUBLANG_UZBEK_LATIN 0x01
 
771
# endif
 
772
# ifndef SUBLANG_UZBEK_CYRILLIC
 
773
# define SUBLANG_UZBEK_CYRILLIC 0x02
 
774
# endif
 
775
 
 
776
 
 
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
 
780
   codeset.  */
 
781
static const char *
 
782
_nl_locale_name (const char *categoryname)
 
783
{
 
784
  const char *retval;
 
785
  LCID lcid;
 
786
  LANGID langid;
 
787
  int primary, sub;
 
788
 
 
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')
 
793
    return retval;
 
794
  retval = getenv (categoryname);
 
795
  if (retval != NULL && retval[0] != '\0')
 
796
    return retval;
 
797
  retval = getenv ("LANG");
 
798
  if (retval != NULL && retval[0] != '\0')
 
799
    return retval;
 
800
 
 
801
  /* Use native Win32 API locale ID.  */
 
802
  lcid = GetThreadLocale ();
 
803
 
 
804
  /* Strip off the sorting rules, keep only the language part.  */
 
805
  langid = LANGIDFROMLCID (lcid);
 
806
 
 
807
  /* Split into language and territory part.  */
 
808
  primary = PRIMARYLANGID (langid);
 
809
  sub = SUBLANGID (langid);
 
810
 
 
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/ .  */
 
814
  switch (primary)
 
815
    {
 
816
    case LANG_AFRIKAANS: return "af_ZA";
 
817
    case LANG_ALBANIAN: return "sq_AL";
 
818
    case LANG_AMHARIC: return "am_ET";
 
819
    case LANG_ARABIC:
 
820
      switch (sub)
 
821
        {
 
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";
 
838
        }
 
839
      return "ar";
 
840
    case LANG_ARMENIAN: return "hy_AM";
 
841
    case LANG_ASSAMESE: return "as_IN";
 
842
    case LANG_AZERI:
 
843
      switch (sub)
 
844
        {
 
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";
 
848
        }
 
849
      return "az";
 
850
    case LANG_BASQUE:
 
851
      return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR".  */
 
852
    case LANG_BELARUSIAN: return "be_BY";
 
853
    case LANG_BENGALI:
 
854
      switch (sub)
 
855
        {
 
856
        case SUBLANG_BENGALI_INDIA: return "bn_IN";
 
857
        case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
 
858
        }
 
859
      return "bn";
 
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";
 
865
    case LANG_CHINESE:
 
866
      switch (sub)
 
867
        {
 
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";
 
873
        }
 
874
      return "zh";
 
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
 
880
                                 * or Croatian.)
 
881
                                 * (I can feel those flames coming already.)
 
882
                                 */
 
883
      switch (sub)
 
884
        {
 
885
        case SUBLANG_DEFAULT: return "hr_HR";
 
886
        case SUBLANG_SERBIAN_LATIN: return "sr_CS";
 
887
        case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
 
888
        }
 
889
      return "hr";
 
890
    case LANG_CZECH: return "cs_CZ";
 
891
    case LANG_DANISH: return "da_DK";
 
892
    case LANG_DIVEHI: return "div_MV";
 
893
    case LANG_DUTCH:
 
894
      switch (sub)
 
895
        {
 
896
        case SUBLANG_DUTCH: return "nl_NL";
 
897
        case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
 
898
        }
 
899
      return "nl";
 
900
    case LANG_EDO: return "bin_NG";
 
901
    case LANG_ENGLISH:
 
902
      switch (sub)
 
903
        {
 
904
        /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
 
905
         * English was the language spoken in England.
 
906
         * Oh well.
 
907
         */
 
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";
 
926
        }
 
927
      return "en";
 
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";
 
932
    case LANG_FRENCH:
 
933
      switch (sub)
 
934
        {
 
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";
 
950
        }
 
951
      return "fr";
 
952
    case LANG_FRISIAN: return "fy_NL";
 
953
    case LANG_FULFULDE: return "ful_NG";
 
954
    case LANG_GAELIC:
 
955
      switch (sub)
 
956
        {
 
957
        case 0x01: /* SCOTTISH */ return "gd_GB";
 
958
        case 0x02: /* IRISH */ return "ga_IE";
 
959
        }
 
960
      return "C";
 
961
    case LANG_GALICIAN: return "gl_ES";
 
962
    case LANG_GEORGIAN: return "ka_GE";
 
963
    case LANG_GERMAN:
 
964
      switch (sub)
 
965
        {
 
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";
 
971
        }
 
972
      return "de";
 
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";
 
977
    case LANG_HAWAIIAN:
 
978
      /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
 
979
         or Hawaii Creole English ("cpe_US", 600000 speakers)?  */
 
980
      return "cpe_US";
 
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";
 
989
    case LANG_ITALIAN:
 
990
      switch (sub)
 
991
        {
 
992
        case SUBLANG_ITALIAN: return "it_IT";
 
993
        case SUBLANG_ITALIAN_SWISS: return "it_CH";
 
994
        }
 
995
      return "it";
 
996
    case LANG_JAPANESE: return "ja_JP";
 
997
    case LANG_KANNADA: return "kn_IN";
 
998
    case LANG_KANURI: return "kau_NG";
 
999
    case LANG_KASHMIRI:
 
1000
      switch (sub)
 
1001
        {
 
1002
        case SUBLANG_DEFAULT: return "ks_PK";
 
1003
        case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
 
1004
        }
 
1005
      return "ks";
 
1006
    case LANG_KAZAK: return "kk_KZ";
 
1007
    case LANG_KONKANI:
 
1008
      /* FIXME: Adjust this when such locales appear on Unix.  */
 
1009
      return "kok_IN";
 
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";
 
1017
    case LANG_MALAY:
 
1018
      switch (sub)
 
1019
        {
 
1020
        case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
 
1021
        case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
 
1022
        }
 
1023
      return "ms";
 
1024
    case LANG_MALAYALAM: return "ml_IN";
 
1025
    case LANG_MALTESE: return "mt_MT";
 
1026
    case LANG_MANIPURI:
 
1027
      /* FIXME: Adjust this when such locales appear on Unix.  */
 
1028
      return "mni_IN";
 
1029
    case LANG_MARATHI: return "mr_IN";
 
1030
    case LANG_MONGOLIAN:
 
1031
      return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN".  */
 
1032
    case LANG_NEPALI:
 
1033
      switch (sub)
 
1034
        {
 
1035
        case SUBLANG_DEFAULT: return "ne_NP";
 
1036
        case SUBLANG_NEPALI_INDIA: return "ne_IN";
 
1037
        }
 
1038
      return "ne";
 
1039
    case LANG_NORWEGIAN:
 
1040
      switch (sub)
 
1041
        {
 
1042
        case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
 
1043
        case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
 
1044
        }
 
1045
      return "no";
 
1046
    case LANG_ORIYA: return "or_IN";
 
1047
    case LANG_OROMO: return "om_ET";
 
1048
    case LANG_PAPIAMENTU: return "pap_AN";
 
1049
    case LANG_PASHTO:
 
1050
      return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF".  */
 
1051
    case LANG_POLISH: return "pl_PL";
 
1052
    case LANG_PORTUGUESE:
 
1053
      switch (sub)
 
1054
        {
 
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";
 
1059
        }
 
1060
      return "pt";
 
1061
    case LANG_PUNJABI:
 
1062
      switch (sub)
 
1063
        {
 
1064
        case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
 
1065
        }
 
1066
      return "pa";
 
1067
    case LANG_RHAETO_ROMANCE: return "rm_CH";
 
1068
    case LANG_ROMANIAN:
 
1069
      switch (sub)
 
1070
        {
 
1071
        case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
 
1072
        }
 
1073
      return "ro";
 
1074
    case LANG_RUSSIAN:
 
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";
 
1078
    case LANG_SINDHI:
 
1079
      switch (sub)
 
1080
        {
 
1081
        case SUBLANG_SINDHI_INDIA: return "sd_IN";
 
1082
        case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
 
1083
        }
 
1084
      return "sd";
 
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";
 
1089
    case LANG_SORBIAN:
 
1090
      /* FIXME: Adjust this when such locales appear on Unix.  */
 
1091
      return "wen_DE";
 
1092
    case LANG_SPANISH:
 
1093
      switch (sub)
 
1094
        {
 
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";
 
1116
        }
 
1117
      return "es";
 
1118
    case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
 
1119
    case LANG_SWAHILI: return "sw_KE";
 
1120
    case LANG_SWEDISH:
 
1121
      switch (sub)
 
1122
        {
 
1123
        case SUBLANG_DEFAULT: return "sv_SE";
 
1124
        case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
 
1125
        }
 
1126
      return "sv";
 
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:
 
1131
      switch (sub)
 
1132
        {
 
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";
 
1136
        }
 
1137
      return "ber_MA";
 
1138
    case LANG_TAMIL:
 
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";
 
1144
    case LANG_TIGRINYA:
 
1145
      switch (sub)
 
1146
        {
 
1147
        case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
 
1148
        case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
 
1149
        }
 
1150
      return "ti";
 
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";
 
1156
    case LANG_URDU:
 
1157
      switch (sub)
 
1158
        {
 
1159
        case SUBLANG_URDU_PAKISTAN: return "ur_PK";
 
1160
        case SUBLANG_URDU_INDIA: return "ur_IN";
 
1161
        }
 
1162
      return "ur";
 
1163
    case LANG_UZBEK:
 
1164
      switch (sub)
 
1165
        {
 
1166
        case SUBLANG_UZBEK_LATIN: return "uz_UZ";
 
1167
        case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
 
1168
        }
 
1169
      return "uz";
 
1170
    case LANG_VENDA:
 
1171
      /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
 
1172
         "ve" or not.
 
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";
 
1184
    }
 
1185
}
 
1186
/* END parts of localname.c from gettext.  */
 
1187
 
 
1188
 
 
1189
 
 
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.]  */
 
1193
 
 
1194
static __inline__ ulong
 
1195
hash_string (const char *str_param)
 
1196
{
 
1197
  unsigned long int hval, g;
 
1198
  const char *str = str_param;
 
1199
  
 
1200
  hval = 0;
 
1201
  while (*str != '\0')
 
1202
    {
 
1203
      hval <<= 4;
 
1204
      hval += (unsigned long int) *str++;
 
1205
      g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
 
1206
      if (g != 0)
 
1207
        {
 
1208
          hval ^= g >> (HASHWORDBITS - 8);
 
1209
          hval ^= g;
 
1210
        }
 
1211
    }
 
1212
  return hval;
 
1213
}
 
1214
 
 
1215
 
 
1216
static struct loaded_domain *
 
1217
load_domain (const char *filename)
 
1218
{
 
1219
  FILE *fp;
 
1220
  size_t size;
 
1221
  struct stat st;
 
1222
  struct mo_file_header *data = NULL;
 
1223
  struct loaded_domain *domain = NULL;
 
1224
  size_t to_read;
 
1225
  char *read_ptr;
 
1226
  
 
1227
  fp = fopen( filename, "rb" );
 
1228
  if (!fp)
 
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) ) 
 
1234
    {
 
1235
      fclose (fp);
 
1236
      return NULL;
 
1237
    }
 
1238
 
 
1239
  data = jnlib_malloc (size);
 
1240
  if (!data)
 
1241
    {
 
1242
      fclose (fp);
 
1243
      return NULL; /* Out of memory. */
 
1244
    }
 
1245
 
 
1246
  to_read = size;
 
1247
  read_ptr = (char *) data;
 
1248
  do
 
1249
    {
 
1250
      long int nb;
 
1251
 
 
1252
      nb = fread (read_ptr, 1, to_read, fp);
 
1253
      if (nb < to_read ) 
 
1254
        {
 
1255
          fclose (fp);
 
1256
          jnlib_free (data);
 
1257
          return NULL; /* Read error. */
 
1258
        }
 
1259
      read_ptr += nb;
 
1260
      to_read -= nb;
 
1261
    } 
 
1262
  while (to_read > 0);
 
1263
  fclose (fp);
 
1264
 
 
1265
  /* Using the magic number we test whether it is really a message
 
1266
     catalog file.  */
 
1267
  if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
 
1268
    {
 
1269
      /* The magic number is wrong: not a message catalog file.  */
 
1270
      jnlib_free (data);
 
1271
      return NULL;
 
1272
    }
 
1273
 
 
1274
  domain = jnlib_calloc (1, sizeof *domain);
 
1275
  if (!domain) 
 
1276
    {
 
1277
      jnlib_free (data);
 
1278
      return NULL;
 
1279
    }
 
1280
  domain->data = (char *) data;
 
1281
  domain->must_swap = data->magic != MAGIC;
 
1282
 
 
1283
  /* Fill in the information about the available tables.  */
 
1284
    switch (SWAPIT(domain->must_swap, data->revision))
 
1285
      {
 
1286
      case 0:
 
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));
 
1295
        break;
 
1296
        
 
1297
      default: /* This is an invalid revision.  */
 
1298
        jnlib_free( data );
 
1299
        jnlib_free( domain );
 
1300
        return NULL;
 
1301
    }
 
1302
 
 
1303
    /* Allocate an array to keep track of code page mappings. */
 
1304
    domain->mapped = jnlib_calloc (1, domain->nstrings);
 
1305
    if (!domain->mapped)
 
1306
      {
 
1307
        jnlib_free (data);
 
1308
        jnlib_free (domain);
 
1309
        return NULL;
 
1310
      }
 
1311
 
 
1312
    return domain;
 
1313
}
 
1314
 
 
1315
 
 
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
 
1319
   gettext().
 
1320
 
 
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.
 
1325
 */
 
1326
int
 
1327
set_gettext_file ( const char *filename, const char *regkey )
 
1328
{
 
1329
  struct loaded_domain *domain = NULL;
 
1330
 
 
1331
  if ( filename && *filename )
 
1332
    {
 
1333
      if ( filename[0] == '/'
 
1334
#ifdef HAVE_DRIVE_LETTERS
 
1335
           || ( isalpha(filename[0])
 
1336
                && filename[1] == ':'
 
1337
                && (filename[2] == '/' || filename[2] == '\\') )
 
1338
#endif
 
1339
           )
 
1340
        {
 
1341
          /* Absolute path - use it as is.  */
 
1342
          domain = load_domain( filename );
 
1343
        }
 
1344
      else  /* Standard.  */
 
1345
        {
 
1346
          char *pgmdir, *instdir, *langid, *fname;
 
1347
          char *p;
 
1348
          int pass = 0;
 
1349
          const char *catval;
 
1350
          
 
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) )
 
1356
            {
 
1357
              jnlib_free (pgmdir);
 
1358
              return -1; /* Error getting the process' file name.  */
 
1359
            }
 
1360
          p = strrchr (pgmdir, DIRSEP_C);
 
1361
          if (!p)
 
1362
            {
 
1363
              jnlib_free (pgmdir);
 
1364
              return -1; /* Invalid file name returned.  */
 
1365
            }
 
1366
          *p = 0;
 
1367
          instdir = NULL;
 
1368
          langid = NULL;
 
1369
          fname = NULL;
 
1370
 
 
1371
          for (pass=0; pass < 3 && !domain; pass++)
 
1372
            {
 
1373
              jnlib_free (instdir);
 
1374
              instdir = NULL;
 
1375
              jnlib_free (langid);
 
1376
              langid = NULL;
 
1377
              jnlib_free (fname);
 
1378
              fname = NULL;
 
1379
              switch (pass)
 
1380
                {
 
1381
                case 0: /* Pass 0: Try LANGUAGE.  */
 
1382
                  if ((p = getenv ("LANGUAGE")) && *p)
 
1383
                    {
 
1384
                      langid = jnlib_malloc (strlen (p)+1);
 
1385
                      if (langid)
 
1386
                        {
 
1387
                          strcpy (langid, p);
 
1388
                          /* We only make use of the first language
 
1389
                             given.  Strip the rest.  */
 
1390
                          p = strchr (langid, ':');
 
1391
                          if (p)
 
1392
                            *p = 0;
 
1393
                        }
 
1394
                    }
 
1395
                  break;
 
1396
                  
 
1397
                case 1: /* Pass 1: Try registry. */
 
1398
                  if (regkey)
 
1399
                    {
 
1400
                      instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
 
1401
                                                          regkey,
 
1402
                                                          "Install Directory");
 
1403
                      if (instdir)
 
1404
                        /* Try HKCU then HKLM. */
 
1405
                        langid = read_w32_registry_string (NULL, 
 
1406
                                                           regkey, "Lang");
 
1407
                    }
 
1408
                  break;
 
1409
 
 
1410
                case 2: /* Pass 2: Try native local.  */
 
1411
                  catval = _nl_locale_name ("LC_MESSAGES");
 
1412
                  if (!catval ||
 
1413
                      !strcmp (catval, "C") || !strcmp (catval, "POSIX"))
 
1414
                    ;
 
1415
                  else
 
1416
                    {
 
1417
                      langid = jnlib_malloc (strlen (catval)+1);
 
1418
                      strcpy (langid, catval);
 
1419
                    }
 
1420
                  break;
 
1421
 
 
1422
                default:
 
1423
                  break;
 
1424
                }
 
1425
 
 
1426
              if (!langid)
 
1427
                continue; /* Next pass.  */
 
1428
 
 
1429
              /* Strip stuff after a dot in case the user tried to
 
1430
                 enter the entire locale syntacs as usual for
 
1431
                 POSIX.  */
 
1432
              p = strchr (langid, '.');
 
1433
              if (p)
 
1434
                *p = 0;
 
1435
                  
 
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
 
1440
                 same place.  */
 
1441
              fname = jnlib_malloc (strlen (instdir? instdir:pgmdir) + 1
 
1442
                                    + strlen (filename) + 5
 
1443
                                    + strlen (langid) + 3 + 1);
 
1444
              if (fname)
 
1445
                {
 
1446
                next_fname:
 
1447
                  strcpy (stpcpy 
 
1448
                          (stpcpy
 
1449
                           (stpcpy 
 
1450
                            (stpcpy 
 
1451
                             (stpcpy (fname,
 
1452
                                      instdir?instdir:pgmdir),"\\"),
 
1453
                             filename), ".nls\\"), 
 
1454
                           langid), ".mo");
 
1455
                      
 
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++) 
 
1460
                    {
 
1461
                      if (*p == '/')
 
1462
                        *p = '\\';
 
1463
                    }
 
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, '_')))
 
1468
                    {
 
1469
                      *p = 0;
 
1470
                      goto next_fname;
 
1471
                    }
 
1472
                  if (domain && !the_langid)
 
1473
                    {
 
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;
 
1478
                      langid = NULL;
 
1479
                    }
 
1480
                }  
 
1481
            } /* End passes.  */
 
1482
 
 
1483
          jnlib_free (pgmdir);
 
1484
          jnlib_free (instdir);
 
1485
          jnlib_free (langid);
 
1486
          jnlib_free (fname);
 
1487
        } 
 
1488
      
 
1489
      if (!domain)
 
1490
        return -1;
 
1491
    }
 
1492
  
 
1493
  if ( the_domain )
 
1494
    {
 
1495
      struct overflow_space_s *os, *os2;
 
1496
 
 
1497
      jnlib_free ( the_domain->data );
 
1498
      jnlib_free ( the_domain->mapped );
 
1499
      for (os=the_domain->overflow_space; os; os = os2)
 
1500
        {
 
1501
          os2 = os->next;
 
1502
          jnlib_free (os);
 
1503
        }
 
1504
      jnlib_free ( the_domain );
 
1505
      the_domain = NULL;
 
1506
    }
 
1507
  the_domain = domain;
 
1508
  return 0;
 
1509
}
 
1510
 
 
1511
 
 
1512
static const char*
 
1513
get_string( struct loaded_domain *domain, u32 idx )
 
1514
{
 
1515
  struct overflow_space_s *os;
 
1516
  char *p;
 
1517
 
 
1518
  p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset);
 
1519
  if (!domain->mapped[idx]) 
 
1520
    {
 
1521
      size_t plen, buflen;
 
1522
      char *buf;
 
1523
 
 
1524
      domain->mapped[idx] = 1;
 
1525
 
 
1526
      plen = strlen (p);
 
1527
      buf = utf8_to_native (p, plen, -1);
 
1528
      buflen = strlen (buf);
 
1529
      if (buflen <= plen)
 
1530
        strcpy (p, buf);
 
1531
      else
 
1532
        {
 
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);
 
1538
          if (os)
 
1539
            {
 
1540
              os->idx = idx;
 
1541
              strcpy (os->d, buf);
 
1542
              os->next = domain->overflow_space;
 
1543
              domain->overflow_space = os;
 
1544
              p = os->d;
 
1545
            }
 
1546
          else
 
1547
            p = "ERROR in GETTEXT MALLOC";
 
1548
        }
 
1549
      jnlib_free (buf);
 
1550
    }
 
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)
 
1554
        if (os->idx == idx)
 
1555
          return (const char*)os->d;
 
1556
      p = "ERROR in GETTEXT\n";
 
1557
    }
 
1558
  return (const char*)p;
 
1559
}
 
1560
 
 
1561
 
 
1562
 
 
1563
const char *
 
1564
gettext( const char *msgid )
 
1565
{
 
1566
  struct loaded_domain *domain;
 
1567
  size_t act = 0;
 
1568
  size_t top, bottom;
 
1569
  
 
1570
  if (!(domain = the_domain))
 
1571
    goto not_found;
 
1572
  
 
1573
  /* Locate the MSGID and its translation.  */
 
1574
  if (domain->hash_size > 2 && domain->hash_tab)
 
1575
    {
 
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]);
 
1582
 
 
1583
      if ( !nstr ) /* Hash table entry is empty.  */
 
1584
        goto not_found;
 
1585
      
 
1586
      if (SWAPIT(domain->must_swap,
 
1587
                 domain->orig_tab[nstr - 1].length) == len
 
1588
          && !strcmp (msgid,
 
1589
                      domain->data + SWAPIT(domain->must_swap,
 
1590
                                            domain->orig_tab[nstr-1].offset)))
 
1591
        return get_string( domain, nstr - 1 );
 
1592
 
 
1593
      for (;;) 
 
1594
        {
 
1595
          if (idx >= domain->hash_size - incr)
 
1596
            idx -= domain->hash_size - incr;
 
1597
          else
 
1598
            idx += incr;
 
1599
          
 
1600
          nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
 
1601
          if (!nstr)
 
1602
            goto not_found; /* Hash table entry is empty.  */
 
1603
 
 
1604
          if ( SWAPIT(domain->must_swap,
 
1605
                      domain->orig_tab[nstr - 1].length) == len
 
1606
               && !strcmp (msgid,
 
1607
                           domain->data 
 
1608
                           + SWAPIT(domain->must_swap,
 
1609
                                    domain->orig_tab[nstr-1].offset)))
 
1610
            return get_string( domain, nstr-1 );
 
1611
        }
 
1612
      /*NOTREACHED*/
 
1613
    }
 
1614
 
 
1615
  /* Now we try the default method: binary search in the sorted array
 
1616
     of messages.  */
 
1617
  bottom = 0;
 
1618
  top = domain->nstrings;
 
1619
  while (bottom < top)
 
1620
    {
 
1621
      int cmp_val;
 
1622
      
 
1623
      act = (bottom + top) / 2;
 
1624
      cmp_val = strcmp(msgid, domain->data
 
1625
                       + SWAPIT(domain->must_swap,
 
1626
                                domain->orig_tab[act].offset));
 
1627
      if (cmp_val < 0)
 
1628
        top = act;
 
1629
      else if (cmp_val > 0)
 
1630
        bottom = act + 1;
 
1631
      else
 
1632
        return get_string (domain, act);
 
1633
    }
 
1634
  
 
1635
 not_found:
 
1636
  return msgid;
 
1637
}
 
1638
 
 
1639
 
 
1640
const char *
 
1641
ngettext (const char *msgid1, const char *msgid2, unsigned long int n)
 
1642
{
 
1643
  /* We use the simple Germanic plural rule. */
 
1644
  return gettext (n==1? msgid1 : msgid2);
 
1645
}
 
1646
 
 
1647
 
 
1648
/* Return the locale name as used by gettext.  The return value will
 
1649
   never be NULL. */
 
1650
const char *
 
1651
gettext_localename (void)
 
1652
{
 
1653
  const char *s;
 
1654
 
 
1655
  if (the_langid)
 
1656
    s = the_langid;
 
1657
  else
 
1658
    s = _nl_locale_name ("LC_MESSAGES");
 
1659
  return s? s:"";
 
1660
}
 
1661
 
 
1662
 
 
1663
#endif /* USE_SIMPLE_GETTEXT */