1
/* This file is based on gettext sources, but specialiced for freeciv.
2
It may not work with other programs, as the functions do not do the
3
stuff of gettext package. Also client and server cannot use one data file,
4
but need to load it individually.
6
And I did not want to port gettext completely, which would have been
10
08.08.2000 : Dirk Stöcker <stoecker@epost.de>
12
27.08.2000 : Dirk Stöcker <stoecker@epost.de>
13
fixes to match changed calling mechanism
14
26.09.2000 : Oliver Gantert <lucyg@t-online.de>
15
changed includes to work with vbcc WarpOS
16
16.12.2000 : Dirk Stöcker <stoecker@epost.de>
17
removed changes, as it works without also
18
26.12.2001 : Sebastian Bauer <sebauer@t-online.de>
19
uses now the prefered languages to determine the gmostr
20
26.12.2001 : Sebastian Bauer <sebauer@t-online.de>
21
lets SAS open the locale library for us now
22
19.02.2002 : Sebastian Bauer <sebauer@t-online.de>
23
added ngettext, but not fully working, only a dummy
24
12.04.2002 : Sebastian Bauer <sebauer@t-online.de>
25
convert KOI8-R charset to the chareset used on Amiga
35
#include <proto/exec.h>
36
#include <proto/locale.h>
38
/* The magic number of the GNU message catalog format. */
39
#define _MAGIC 0x950412de
40
#define _MAGIC_SWAPPED 0xde120495
42
#define SWAP(i) (((i) << 24) | (((i) & 0xff00) << 8) | (((i) >> 8) & 0xff00) | ((i) >> 24))
43
#define GET(data) (domain.must_swap ? SWAP (data) : (data))
45
typedef unsigned long nls_uint32;
47
/* Header for binary .mo file format. */
50
nls_uint32 magic; /* The magic number. */
51
nls_uint32 revision; /* The revision number of the file format. */
52
nls_uint32 nstrings; /* The number of strings pairs. */
53
nls_uint32 orig_tab_offset; /* Offset of table with start offsets of original strings. */
54
nls_uint32 trans_tab_offset; /* Offset of table with start offsets of translation strings. */
55
nls_uint32 hash_tab_size; /* Size of hashing table. */
56
nls_uint32 hash_tab_offset; /* Offset of first hashing entry. */
61
nls_uint32 length; /* Length of addressed string. */
62
nls_uint32 offset; /* Offset of string in file. */
70
struct string_desc *orig_tab;
71
struct string_desc *trans_tab;
76
static struct loaded_domain domain = {0, 0, 0, 0, 0, 0, 0};
78
char *gettext(const char *msgid);
80
static long openmo(char *dir, char *loc)
85
struct mo_file_header *data;
90
sprintf(filename, "%s/%s.mo", dir, loc);
92
printf("locale file name: %s\n", filename);
95
if((fd = fopen(filename, "rb")))
97
if(!fseek(fd, 0, SEEK_END))
99
if((size = ftell(fd)) != EOF)
101
if(!fseek(fd, 0, SEEK_SET))
103
if((data = (struct mo_file_header *) malloc(size)))
105
if(fread(data, size, 1, fd) == 1)
107
if((data->magic == _MAGIC || data->magic == _MAGIC_SWAPPED) && !data->revision) /* no need to swap! */
109
domain.data = (const char *) data;
110
domain.must_swap = data->magic != _MAGIC;
111
domain.nstrings = GET(data->nstrings);
112
domain.orig_tab = (struct string_desc *) ((char *) data + GET(data->orig_tab_offset));
113
domain.trans_tab = (struct string_desc *) ((char *) data + GET(data->trans_tab_offset));
114
domain.hash_size = GET(data->hash_tab_size);
115
domain.hash_tab = (nls_uint32 *) ((char *) data + GET(data->hash_tab_offset));
117
if (strstr(gettext(""),"charset=KOI8-R") /* This somehow doesn't work so we check for the ru string also */ || !strcmp("ru",loc))
121
/* convert the charset to AMI1251, this is the table */
122
static const unsigned char table[] = {
123
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
124
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
125
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
126
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
127
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
128
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
129
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
130
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
131
0xBF,0xB6,0xBE,0xAA,0xA1,0xB5,0x8D,0x8E,0x93,0x90,0x98,0x96,0x99,0x94,0x9A,0x80,
132
0x81,0x82,0x87,0x88,0x89,0x8A,0x8F,0x9E,0x9F,0xB4,0xAD,0xAC,0xAC,0xAC,0xAC,0xAC,
133
0xAC,0xAC,0xAC,0xB8,0xAC,0xAC,0xAC,0xBA,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAB,0xBB,
134
0x9B,0x9C,0x9E,0xA8,0xA5,0x83,0x84,0x85,0x86,0x97,0x95,0x91,0x92,0x8B,0x8C,0xAF,
135
0xFE,0xE0,0xE1,0xF6,0xE4,0xE5,0xF4,0xE3,0xF5,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,
136
0xEF,0xFF,0xF0,0xF1,0xF2,0xF3,0xE6,0xE2,0xFC,0xFB,0xE7,0xF8,0xFD,0xF9,0xF7,0xFA,
137
0xDE,0xC0,0xC1,0xD6,0xC4,0xC5,0xD4,0xC3,0xD5,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,
138
0xCF,0xDF,0xD0,0xD1,0xD2,0xD3,0xC6,0xC2,0xDC,0xDB,0xC7,0xD8,0xDD,0xD9,0xD7,0xDA
141
for (i=0;i<domain.nstrings;i++)
144
int off = GET(domain.trans_tab[i].offset);
145
char *trans_string = domain.data + off;
147
/* Now convert every char in size the string */
148
for (j=0;j<GET(domain.trans_tab[i].length) && j+off<size;j++)
150
trans_string[j] = table[trans_string[j]];
166
return (long) domain.data;
169
/* languages supported by freeciv */
173
} LocaleConvTab[] = {
175
/*{"", "en_GB"}, does not exist on Amiga */
181
{"nederlands", "nl"},
184
{"português" , "pt"},
185
{"português-brasil", "pt_BR"},
192
/* Returns NULL if is not in the list */
193
static char *find_gmostr(char *lang)
196
if (!lang) return NULL;
197
for (i=0;LocaleConvTab[i].langstr;i++)
199
if (!strcmp(LocaleConvTab[i].langstr,lang)) return LocaleConvTab[i].gmostr;
204
void bindtextdomain(char * pack, char * dir)
209
if(openmo(dir, getenv("LANG")))
212
if(openmo(dir, getenv("LANGUAGE")))
215
if((l = OpenLocale(0)))
219
if (!openmo(dir,find_gmostr(l->loc_PrefLanguages[i])))
221
if (openmo(dir,l->loc_PrefLanguages[i])) break;
229
#define HASHWORDBITS 32
230
static unsigned long hash_string(const char *str_param)
232
unsigned long int hval, g;
233
const char *str = str_param;
235
/* Compute the hash value for the given string. */
240
hval += (unsigned long) *str++;
241
g = hval & ((unsigned long) 0xf << (HASHWORDBITS - 4));
244
hval ^= g >> (HASHWORDBITS - 8);
251
static char *find_msg(const char * msgid)
253
long top, act, bottom;
255
if(!domain.data || !msgid)
258
/* Locate the MSGID and its translation. */
259
if(domain.hash_size > 2 && domain.hash_tab != NULL)
261
/* Use the hashing table. */
262
nls_uint32 len = strlen (msgid);
263
nls_uint32 hash_val = hash_string (msgid);
264
nls_uint32 idx = hash_val % domain.hash_size;
265
nls_uint32 incr = 1 + (hash_val % (domain.hash_size - 2));
270
if(!(nstr = GET(domain.hash_tab[idx]))) /* Hash table entry is empty. */
273
if(GET(domain.orig_tab[nstr - 1].length) == len && strcmp(msgid, domain.data +
274
GET(domain.orig_tab[nstr - 1].offset)) == 0)
275
return (char *) domain.data + GET(domain.trans_tab[nstr - 1].offset);
277
if(idx >= domain.hash_size - incr)
278
idx -= domain.hash_size - incr;
284
/* Now we try the default method: binary search in the sorted
285
array of messages. */
287
top = domain.nstrings;
292
act = (bottom + top) / 2;
293
cmp_val = strcmp(msgid, domain.data + GET(domain.orig_tab[act].offset));
302
/* If an translation is found return this. */
303
return bottom >= top ? NULL : (char *) domain.data + GET(domain.trans_tab[act].offset);
307
char *gettext(const char *msgid)
311
if(!(res = find_msg(msgid)))
313
res = (char *) msgid;
315
Printf("Did not find: '%s'\n", res);
322
char *ngettext(const char *msgid1, const char *msgid2, unsigned long int n)
324
return (n==1?msgid1:msgid2);
327
char *setlocale(int a, char *b)
332
void textdomain(char *package)