1 |
/* |
2 |
* language.c -- handles: |
3 |
* language support code |
4 |
* |
5 |
* $Id: language.c,v 1.7 1999/12/24 23:59:43 fabian Exp $ |
6 |
*/ |
7 |
/* |
8 |
* Copyright (C) 1997 Robey Pointer |
9 |
* Copyright (C) 1999, 2000 Eggheads |
10 |
* |
11 |
* This program is free software; you can redistribute it and/or |
12 |
* modify it under the terms of the GNU General Public License |
13 |
* as published by the Free Software Foundation; either version 2 |
14 |
* of the License, or (at your option) any later version. |
15 |
* |
16 |
* This program is distributed in the hope that it will be useful, |
17 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 |
* GNU General Public License for more details. |
20 |
* |
21 |
* You should have received a copy of the GNU General Public License |
22 |
* along with this program; if not, write to the Free Software |
23 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
24 |
*/ |
25 |
|
26 |
/* |
27 |
* DOES: |
28 |
* Nothing <- typical BB code :) |
29 |
* |
30 |
* ENVIRONMENT VARIABLES: |
31 |
* EGG_LANG - language to use (default: "english") |
32 |
* EGG_LANGDIR - directory with all lang files |
33 |
* (default: "./language") |
34 |
* WILL DO: |
35 |
* Upon loading: |
36 |
* o default loads section core, if possible. |
37 |
* Commands: |
38 |
* DCC .+lang <language> |
39 |
* DCC .-lang <language> |
40 |
* DCC .+lsec <section> |
41 |
* DCC .-lsec <section> |
42 |
* DCC .relang |
43 |
* DCC .ldump |
44 |
* DCC .lstat |
45 |
* |
46 |
* FILE FORMAT: language.lang |
47 |
* <textidx>,<text> |
48 |
* TEXT MESSAGE USAGE: |
49 |
* get_language(<textidx> [,<PARMS>]) |
50 |
* |
51 |
* ADDING LANGUAGES: |
52 |
* o Copy an existing <section>.<oldlanguage>.lang to a |
53 |
* new .lang file and modify as needed. |
54 |
* Use %s or %d where necessary, for plug-in |
55 |
* insertions of parameters (see core.english.lang). |
56 |
* o Ensure <section>.<newlanguage>.lang is in the lang |
57 |
* directory. |
58 |
* o .+lang <newlanguage> |
59 |
* ADDING SECTIONS: |
60 |
* o Create a <newsection>.english.lang file. |
61 |
* o Add add_lang_section("<newsection>"); to your module |
62 |
* startup function. |
63 |
* |
64 |
*/ |
65 |
|
66 |
#include "main.h" |
67 |
|
68 |
extern struct dcc_t *dcc; |
69 |
|
70 |
typedef struct lang_st { |
71 |
struct lang_st *next; |
72 |
char *lang; |
73 |
char *section; |
74 |
} lang_sec; |
75 |
|
76 |
typedef struct lang_pr { |
77 |
struct lang_pr *next; |
78 |
char *lang; |
79 |
} lang_pri; |
80 |
|
81 |
typedef struct lang_t { |
82 |
int idx; |
83 |
char *text; |
84 |
struct lang_t *next; |
85 |
} lang_tab; |
86 |
|
87 |
static lang_tab *langtab[64]; |
88 |
static lang_sec *langsection = NULL; |
89 |
static lang_pri *langpriority = NULL; |
90 |
|
91 |
static int del_lang(char *); |
92 |
static int add_message(int, char *); |
93 |
static void recheck_lang_sections(void); |
94 |
static void read_lang(char *); |
95 |
void add_lang_section(char *); |
96 |
int del_lang_section(char *); |
97 |
static char *get_specific_langfile(char *, lang_sec *); |
98 |
static char *get_langfile(lang_sec *); |
99 |
static int split_lang(char *, char **, char **); |
100 |
int cmd_loadlanguage(struct userrec *, int, char *); |
101 |
|
102 |
|
103 |
/* add a new preferred language to the list of languages. Newly added |
104 |
* languages get the highest priority. |
105 |
*/ |
106 |
void add_lang(char *lang) |
107 |
{ |
108 |
lang_pri *lp = langpriority, *lpo = NULL; |
109 |
|
110 |
Context; |
111 |
while (lp) { |
112 |
/* the language already exists, moving to the beginning */ |
113 |
if (!strcmp(lang, lp->lang)) { |
114 |
/* already at the front? */ |
115 |
if (!lpo) |
116 |
return; |
117 |
lpo->next = lp->next; |
118 |
lp->next = lpo; |
119 |
langpriority = lp; |
120 |
return; |
121 |
} |
122 |
lpo = lp; |
123 |
lp = lp->next; |
124 |
} |
125 |
|
126 |
/* no existing entry, create a new one */ |
127 |
lp = nmalloc(sizeof(lang_pri)); |
128 |
lp->lang = nmalloc(strlen(lang) + 1); |
129 |
strcpy(lp->lang, lang); |
130 |
lp->next = NULL; |
131 |
|
132 |
/* if we have other entries, point to the beginning of the old list */ |
133 |
if (langpriority) |
134 |
lp->next = langpriority; |
135 |
langpriority = lp; |
136 |
putlog(LOG_MISC, "*", "LANG: Language loaded: %s", lang); |
137 |
} |
138 |
|
139 |
/* remove a language from the list of preferred languages. */ |
140 |
static int del_lang(char *lang) |
141 |
{ |
142 |
lang_pri *lp = langpriority, *lpo = NULL; |
143 |
|
144 |
Context; |
145 |
while (lp) { |
146 |
/* found the language? */ |
147 |
if (!strcmp(lang, lp->lang)) { |
148 |
if (lpo) |
149 |
lpo->next = lp->next; |
150 |
else |
151 |
langpriority = lp->next; |
152 |
if (lp->lang) |
153 |
nfree(lp->lang); |
154 |
nfree(lp); |
155 |
putlog(LOG_MISC, "*", "LANG: Language unloaded: %s", |
156 |
lang); |
157 |
return 1; |
158 |
} |
159 |
lpo = lp; |
160 |
lp = lp->next; |
161 |
} |
162 |
/* language not found */ |
163 |
return 0; |
164 |
} |
165 |
|
166 |
static int add_message(int lidx, char *ltext) |
167 |
{ |
168 |
lang_tab *l = langtab[lidx & 63]; |
169 |
|
170 |
while (l) { |
171 |
if (l->idx && (l->idx == lidx)) { |
172 |
nfree(l->text); |
173 |
l->text = nmalloc(strlen(ltext) + 1); |
174 |
strcpy(l->text, ltext); |
175 |
return 1; |
176 |
} |
177 |
if (!l->next) |
178 |
break; |
179 |
l = l->next; |
180 |
} |
181 |
if (l) { |
182 |
l->next = nmalloc(sizeof(lang_tab)); |
183 |
l = l->next; |
184 |
} else |
185 |
l = langtab[lidx & 63] = nmalloc(sizeof(lang_tab)); |
186 |
l->idx = lidx; |
187 |
l->text = nmalloc(strlen(ltext) + 1); |
188 |
strcpy(l->text, ltext); |
189 |
l->next = 0; |
190 |
return 0; |
191 |
} |
192 |
|
193 |
/* recheck all sections and check if any language files are available |
194 |
* which match the preferred language(s) more closely |
195 |
*/ |
196 |
static void recheck_lang_sections(void) |
197 |
{ |
198 |
lang_sec *ls = langsection; |
199 |
char *langfile; |
200 |
|
201 |
Context; |
202 |
while (ls) { |
203 |
if (ls->section) { |
204 |
langfile = get_langfile(ls); |
205 |
/* found a language with a more preferred language? */ |
206 |
if (langfile) { |
207 |
read_lang(langfile); |
208 |
nfree(langfile); |
209 |
} |
210 |
} |
211 |
ls = ls->next; |
212 |
} |
213 |
} |
214 |
|
215 |
/* parse a language file */ |
216 |
static void read_lang(char *langfile) |
217 |
{ |
218 |
FILE *FLANG; |
219 |
char lbuf[512]; |
220 |
char *ltext = NULL; |
221 |
char *ctmp, *ctmp1; |
222 |
int lidx; |
223 |
int lline = 0; |
224 |
int lskip; |
225 |
int ltexts = 0; |
226 |
int ladd = 0, lupdate = 0; |
227 |
|
228 |
Context; |
229 |
FLANG = fopen(langfile, "r"); |
230 |
if (FLANG == NULL) { |
231 |
putlog(LOG_MISC, "*", "LANG: unexpected: reading from file %s failed.", |
232 |
langfile); |
233 |
return; |
234 |
} |
235 |
|
236 |
lskip = 0; |
237 |
while (fgets(lbuf, 511, FLANG)) { |
238 |
lline++; |
239 |
if (lbuf[0] != '#' || lskip) { |
240 |
ltext = nrealloc(ltext, 512); |
241 |
if (sscanf(lbuf, "%s", ltext) != EOF) { |
242 |
if (sscanf(lbuf, "0x%x,%500c", &lidx, ltext) != 2) { |
243 |
putlog(LOG_MISC, "*", "Malformed text line in %s at %d.", |
244 |
langfile, lline); |
245 |
} else { |
246 |
ltexts++; |
247 |
ctmp = strchr(ltext, '\n'); |
248 |
*ctmp = 0; |
249 |
while (ltext[strlen(ltext) - 1] == '\\') { |
250 |
ltext[strlen(ltext) - 1] = 0; |
251 |
if (fgets(lbuf, 511, FLANG)) { |
252 |
lline++; |
253 |
ctmp = strchr(lbuf, '\n'); |
254 |
*ctmp = 0; |
255 |
ltext = nrealloc(ltext, strlen(lbuf) + strlen(ltext) + 1); |
256 |
strcpy(strchr(ltext, 0), lbuf); |
257 |
} |
258 |
} |
259 |
} |
260 |
/* We gotta fix \n's here as, being arguments to sprintf(), */ |
261 |
/* they won't get translated */ |
262 |
ctmp = ltext; |
263 |
ctmp1 = ltext; |
264 |
while (*ctmp1) { |
265 |
if (*ctmp1 == '\\' && *(ctmp1 + 1) == 'n') { |
266 |
*ctmp = '\n'; |
267 |
ctmp1++; |
268 |
} else |
269 |
*ctmp = *ctmp1; |
270 |
ctmp++; |
271 |
ctmp1++; |
272 |
} |
273 |
*ctmp = '\0'; |
274 |
if (add_message(lidx, ltext)) { |
275 |
lupdate++; |
276 |
} else |
277 |
ladd++; |
278 |
} |
279 |
} else { |
280 |
ctmp = strchr(lbuf, '\n'); |
281 |
if (lskip && (strlen(lbuf) == 1 || *(ctmp - 1) != '\\')) |
282 |
lskip = 0; |
283 |
} |
284 |
} |
285 |
nfree(ltext); |
286 |
fclose(FLANG); |
287 |
|
288 |
putlog(LOG_MISC, "*", "LANG: %d messages of %d lines loaded from %s", |
289 |
ltexts, lline, langfile); |
290 |
putlog(LOG_MISC, "*", "LANG: %d adds, %d updates to message table", |
291 |
ladd, lupdate); |
292 |
} |
293 |
|
294 |
/* Add a new language section. e.g. section "core" |
295 |
* Load an apropriate language file for the specified section. |
296 |
*/ |
297 |
void add_lang_section(char *section) |
298 |
{ |
299 |
char *langfile = NULL; |
300 |
lang_sec *ls = langsection, *ols = NULL; |
301 |
int ok = 0; |
302 |
|
303 |
Context; |
304 |
while (ls) { |
305 |
/* already know of that section? */ |
306 |
if (!strcmp(section, ls->section)) |
307 |
return; |
308 |
ols = ls; |
309 |
ls = ls->next; |
310 |
} |
311 |
|
312 |
/* create new section entry */ |
313 |
ls = nmalloc(sizeof(lang_sec)); |
314 |
ls->section = nmalloc(strlen(section) + 1); |
315 |
strcpy(ls->section, section); |
316 |
ls->lang = NULL; |
317 |
ls->next = NULL; |
318 |
|
319 |
/* connect to existing list of sections */ |
320 |
if (ols) |
321 |
ols->next = ls; |
322 |
else |
323 |
langsection = ls; |
324 |
putlog(LOG_MISC, "*", "LANG: Section loaded: %s", section); |
325 |
|
326 |
/* Always load base language */ |
327 |
langfile = get_specific_langfile(BASELANG, ls); |
328 |
if (langfile) { |
329 |
read_lang(langfile); |
330 |
nfree(langfile); |
331 |
ok = 1; |
332 |
} |
333 |
/* Now overwrite base language with a more preferred one */ |
334 |
langfile = get_langfile(ls); |
335 |
if (!langfile) { |
336 |
if (!ok) |
337 |
putlog(LOG_MISC, "*", "LANG: No lang files found for section %s.", |
338 |
section); |
339 |
return; |
340 |
} |
341 |
read_lang(langfile); |
342 |
nfree(langfile); |
343 |
} |
344 |
|
345 |
int del_lang_section(char *section) |
346 |
{ |
347 |
lang_sec *ls = langsection, *ols = NULL; |
348 |
|
349 |
while (ls) { |
350 |
if (ls->section && !strcmp(ls->section, section)) { |
351 |
if (ols) |
352 |
ols->next = ls->next; |
353 |
else |
354 |
langsection = ls->next; |
355 |
nfree(ls->section); |
356 |
if (ls->lang) |
357 |
nfree(ls->lang); |
358 |
nfree(ls); |
359 |
putlog(LOG_MISC, "*", "LANG: Section unloaded: %s", section); |
360 |
return 1; |
361 |
} |
362 |
ols = ls; |
363 |
ls = ls->next; |
364 |
} |
365 |
return 0; |
366 |
} |
367 |
|
368 |
static char *get_specific_langfile(char *language, lang_sec *sec) |
369 |
{ |
370 |
char *ldir = getenv("EGG_LANGDIR"); |
371 |
char *langfile; |
372 |
FILE *sfile = NULL; |
373 |
|
374 |
if (!ldir) |
375 |
ldir = LANGDIR; |
376 |
langfile = nmalloc(strlen(ldir) + strlen(sec->section) + strlen(language)+8); |
377 |
sprintf(langfile, "%s/%s.%s.lang", ldir, sec->section, language); |
378 |
sfile = fopen(langfile, "r"); |
379 |
if (sfile) { |
380 |
fclose(sfile); |
381 |
/* save language used for this section */ |
382 |
sec->lang = nrealloc(sec->lang, strlen(language) + 1); |
383 |
strcpy(sec->lang, language); |
384 |
return langfile; |
385 |
} |
386 |
nfree(langfile); |
387 |
return NULL; |
388 |
} |
389 |
|
390 |
/* Searches for available language files and returns the file with the |
391 |
* most preferred language. |
392 |
*/ |
393 |
static char *get_langfile(lang_sec *sec) |
394 |
{ |
395 |
char *langfile; |
396 |
lang_pri *lp = langpriority; |
397 |
|
398 |
Context; |
399 |
while (lp) { |
400 |
/* there is no need to reload the same language */ |
401 |
if (sec->lang && !strcmp(sec->lang, lp->lang)) { |
402 |
return NULL; |
403 |
} |
404 |
langfile = get_specific_langfile(lp->lang, sec); |
405 |
if (langfile) |
406 |
return langfile; |
407 |
lp = lp->next; |
408 |
} |
409 |
/* we did not find any files, clear the language field */ |
410 |
if (sec->lang) |
411 |
nfree(sec->lang); |
412 |
sec->lang = NULL; |
413 |
return NULL; |
414 |
} |
415 |
|
416 |
/* Split up a string /path/<section>.<language>.lang into the |
417 |
* needed information for the new language system. |
418 |
* Only needed for compability functions. |
419 |
*/ |
420 |
static int split_lang(char *par, char **lang, char **section) |
421 |
{ |
422 |
char *p; |
423 |
|
424 |
Context; |
425 |
p = strrchr(par, '/'); |
426 |
/* path attached? */ |
427 |
if (p) |
428 |
*section = p + 1; |
429 |
else |
430 |
*section = par; |
431 |
p = strchr(*section, '.'); |
432 |
if (p) |
433 |
p[0] = 0; |
434 |
else |
435 |
return 0; |
436 |
*lang = p + 1; |
437 |
p = strstr(*lang, ".lang"); |
438 |
if (p) |
439 |
p[0] = 0; |
440 |
return 1; |
441 |
} |
442 |
|
443 |
/* compability function to allow users/modules to use the old command. */ |
444 |
int cmd_loadlanguage(struct userrec *u, int idx, char *par) |
445 |
{ |
446 |
char *section, *lang, *buf; |
447 |
|
448 |
Context; |
449 |
dprintf(idx, "Note: This command is obsoleted by +lang.\n"); |
450 |
if (!par || !par[0]) { |
451 |
dprintf(idx, "Usage: language <section>.<language>\n"); |
452 |
return 0; |
453 |
} |
454 |
if (idx != DP_LOG) |
455 |
putlog(LOG_CMDS, "*", "#%s# language %s", dcc[idx].nick, par); |
456 |
buf = nmalloc(strlen(par)+1); |
457 |
strcpy(buf, par); |
458 |
if (!split_lang(buf, &lang, §ion)) { |
459 |
nfree(buf); |
460 |
dprintf(idx, "Invalid parameter %s.\n", par); |
461 |
return 0; |
462 |
} |
463 |
add_lang(lang); |
464 |
add_lang_section(section); |
465 |
nfree(buf); |
466 |
recheck_lang_sections(); |
467 |
return 0; |
468 |
} |
469 |
|
470 |
static int cmd_plslang(struct userrec *u, int idx, char *par) |
471 |
{ |
472 |
Context; |
473 |
if (!par || !par[0]) { |
474 |
dprintf(idx, "Usage: +lang <language>\n"); |
475 |
return 0; |
476 |
} |
477 |
putlog(LOG_CMDS, "*", "#%s# +lang %s", dcc[idx].nick, par); |
478 |
add_lang(par); |
479 |
recheck_lang_sections(); |
480 |
return 0; |
481 |
} |
482 |
|
483 |
static int cmd_mnslang(struct userrec *u, int idx, char *par) |
484 |
{ |
485 |
Context; |
486 |
if (!par || !par[0]) { |
487 |
dprintf(idx, "Usage: -lang <language>\n"); |
488 |
return 0; |
489 |
} |
490 |
putlog(LOG_CMDS, "*", "#%s# -lang %s", dcc[idx].nick, par); |
491 |
if (!del_lang(par)) |
492 |
dprintf(idx, "Language %s not found.\n", par); |
493 |
else |
494 |
recheck_lang_sections(); |
495 |
return 0; |
496 |
} |
497 |
|
498 |
static int cmd_plslsec(struct userrec *u, int idx, char *par) |
499 |
{ |
500 |
Context; |
501 |
if (!par || !par[0]) { |
502 |
dprintf(idx, "Usage: +lsec <section>\n"); |
503 |
return 0; |
504 |
} |
505 |
putlog(LOG_CMDS, "*", "#%s# +lsec %s", dcc[idx].nick, par); |
506 |
add_lang_section(par); |
507 |
return 0; |
508 |
} |
509 |
|
510 |
static int cmd_mnslsec(struct userrec *u, int idx, char *par) |
511 |
{ |
512 |
Context; |
513 |
if (!par || !par[0]) { |
514 |
dprintf(idx, "Usage: -lsec <section>\n"); |
515 |
return 0; |
516 |
} |
517 |
putlog(LOG_CMDS, "*", "#%s# -lsec %s", dcc[idx].nick, par); |
518 |
if (!del_lang_section(par)) |
519 |
dprintf(idx, "Section %s not found.\n", par); |
520 |
return 0; |
521 |
} |
522 |
|
523 |
static int cmd_relang(struct userrec *u, int idx, char *par) |
524 |
{ |
525 |
dprintf(idx, "Rechecking language sections...\n"); |
526 |
recheck_lang_sections(); |
527 |
return 0; |
528 |
} |
529 |
|
530 |
static int cmd_languagedump(struct userrec *u, int idx, char *par) |
531 |
{ |
532 |
lang_tab *l; |
533 |
char ltext2[512]; |
534 |
int idx2, i; |
535 |
|
536 |
Context; |
537 |
putlog(LOG_CMDS, "*", "#%s# ldump %s", dcc[idx].nick, par); |
538 |
if (par[0]) { |
539 |
/* atoi (hence strtol) don't work right here for hex */ |
540 |
if (strlen(par) > 2 && par[0] == '0' && par[1] == 'x') |
541 |
sscanf(par, "%x", &idx2); |
542 |
else |
543 |
idx2 = (int) strtol(par, (char **) NULL, 10); |
544 |
strcpy(ltext2, get_language(idx2)); |
545 |
dprintf(idx, "0x%x: %s\n", idx2, ltext2); |
546 |
return 0; |
547 |
} |
548 |
dprintf(idx, " LANGIDX TEXT\n"); |
549 |
for (i = 0; i < 64; i++) |
550 |
for (l = langtab[i]; l; l = l->next) |
551 |
dprintf(idx, "0x%x %s\n", l->idx, l->text); |
552 |
return 0; |
553 |
} |
554 |
|
555 |
static char text[512]; |
556 |
char *get_language(int idx) |
557 |
{ |
558 |
lang_tab *l = langtab[idx & 63]; |
559 |
|
560 |
if (!idx) |
561 |
return "MSG-0-"; |
562 |
while (l) { |
563 |
if (idx == l->idx) |
564 |
return l->text; |
565 |
l = l->next; |
566 |
} |
567 |
sprintf(text, "MSG%03X", idx); |
568 |
return text; |
569 |
} |
570 |
|
571 |
int expmem_language() |
572 |
{ |
573 |
lang_tab *l; |
574 |
lang_sec *ls = langsection; |
575 |
lang_pri *lp = langpriority; |
576 |
int i, size = 0; |
577 |
|
578 |
Context; |
579 |
for (i = 0; i < 64; i++) |
580 |
for (l = langtab[i]; l; l = l->next) { |
581 |
size += sizeof(lang_tab); |
582 |
size += (strlen(l->text) + 1); |
583 |
} |
584 |
while (ls) { |
585 |
size += sizeof(lang_sec); |
586 |
if (ls->section) |
587 |
size += strlen(ls->section)+1; |
588 |
if (ls->lang) |
589 |
size += strlen(ls->lang)+1; |
590 |
ls = ls->next; |
591 |
} |
592 |
while (lp) { |
593 |
size += sizeof(lang_pri); |
594 |
if (lp->lang) |
595 |
size += strlen(lp->lang)+1; |
596 |
lp = lp->next; |
597 |
} |
598 |
return size; |
599 |
} |
600 |
|
601 |
/* a report on the module status - not sure if we need this now :/ */ |
602 |
static int cmd_languagestatus(struct userrec *u, int idx, char *par) |
603 |
{ |
604 |
int ltexts = 0; |
605 |
register int i, c, maxdepth = 0, used = 0, empty = 0; |
606 |
lang_tab *l; |
607 |
lang_sec *ls = langsection; |
608 |
lang_pri *lp = langpriority; |
609 |
|
610 |
Context; |
611 |
putlog(LOG_CMDS, "*", "#%s# lstat %s", dcc[idx].nick, par); |
612 |
for (i = 0; i < 64; i++) { |
613 |
c = 0; |
614 |
for (l = langtab[i]; l; l = l->next) |
615 |
c++; |
616 |
if (c > maxdepth) |
617 |
maxdepth = c; |
618 |
if (c) |
619 |
used++; |
620 |
else |
621 |
empty++; |
622 |
ltexts += c; |
623 |
} |
624 |
Context; |
625 |
dprintf(idx, "Language code report:\n"); |
626 |
dprintf(idx, " Table size : %d bytes\n", expmem_language()); |
627 |
dprintf(idx, " Text messages: %d\n", ltexts); |
628 |
dprintf(idx, " %d used, %d unused, maxdepth %d, avg %f\n", |
629 |
used, empty, maxdepth, (float) ltexts / 64.0); |
630 |
if (lp) { |
631 |
int c = 0; |
632 |
|
633 |
dprintf(idx, " Supported languages:"); |
634 |
while (lp) { |
635 |
dprintf(idx, "%s %s", c ? "," : "", lp->lang); |
636 |
c = 1; |
637 |
lp = lp->next; |
638 |
} |
639 |
dprintf(idx, "\n"); |
640 |
} |
641 |
if (ls) { |
642 |
dprintf(idx, "\n SECTION LANG\n"); |
643 |
dprintf(idx, " ==============================\n"); |
644 |
while (ls) { |
645 |
dprintf(idx, " %-20s %s\n", ls->section, |
646 |
ls->lang ? ls->lang : "<none>"); |
647 |
ls = ls->next; |
648 |
} |
649 |
} |
650 |
return 0; |
651 |
} |
652 |
|
653 |
/* compability function to allow scripts to use the old command. */ |
654 |
static int tcl_language STDVAR |
655 |
{ |
656 |
char *lang, *section, *buf; |
657 |
BADARGS(2, 2, " language"); |
658 |
|
659 |
buf = nmalloc(strlen(argv[1])+1); |
660 |
strcpy(buf, argv[1]); |
661 |
if (!split_lang(buf, &lang, §ion)) { |
662 |
Tcl_AppendResult(irp, "Invalid parameter", NULL); |
663 |
nfree(buf); |
664 |
return TCL_ERROR; |
665 |
} |
666 |
add_lang(lang); |
667 |
add_lang_section(section); |
668 |
nfree(buf); |
669 |
recheck_lang_sections(); |
670 |
return TCL_OK; |
671 |
} |
672 |
|
673 |
static int tcl_plslang STDVAR |
674 |
{ |
675 |
BADARGS(2, 2, " language"); |
676 |
|
677 |
add_lang(argv[1]); |
678 |
recheck_lang_sections(); |
679 |
|
680 |
return TCL_OK; |
681 |
} |
682 |
|
683 |
static int tcl_mnslang STDVAR |
684 |
{ |
685 |
BADARGS(2, 2, " language"); |
686 |
|
687 |
if (!del_lang(argv[1])) { |
688 |
Tcl_AppendResult(irp, "Language not found.", NULL); |
689 |
return TCL_ERROR; |
690 |
} |
691 |
recheck_lang_sections(); |
692 |
|
693 |
return TCL_OK; |
694 |
} |
695 |
|
696 |
static int tcl_addlangsection STDVAR |
697 |
{ |
698 |
BADARGS(2, 2, " section"); |
699 |
|
700 |
add_lang_section(argv[1]); |
701 |
return TCL_OK; |
702 |
} |
703 |
|
704 |
static int tcl_dellangsection STDVAR |
705 |
{ |
706 |
BADARGS(2, 2, " section"); |
707 |
|
708 |
if (!del_lang_section(argv[1])) { |
709 |
Tcl_AppendResult(irp, "Section not found", NULL); |
710 |
return TCL_ERROR; |
711 |
} |
712 |
return TCL_OK; |
713 |
} |
714 |
|
715 |
static int tcl_relang STDVAR |
716 |
{ |
717 |
recheck_lang_sections(); |
718 |
return TCL_OK; |
719 |
} |
720 |
|
721 |
static cmd_t langdcc[] = |
722 |
{ |
723 |
{"language", "n", cmd_loadlanguage, NULL}, |
724 |
{"+lang", "n", cmd_plslang, NULL}, |
725 |
{"-lang", "n", cmd_mnslang, NULL}, |
726 |
{"+lsec", "n", cmd_plslsec, NULL}, |
727 |
{"-lsec", "n", cmd_mnslsec, NULL}, |
728 |
{"ldump", "n", cmd_languagedump, NULL}, |
729 |
{"lstat", "n", cmd_languagestatus, NULL}, |
730 |
{"relang", "n", cmd_relang, NULL}, |
731 |
{0, 0, 0, 0} |
732 |
}; |
733 |
|
734 |
static tcl_cmds langtcls[] = |
735 |
{ |
736 |
{"language", tcl_language}, |
737 |
{"addlang", tcl_plslang}, |
738 |
{"dellang", tcl_mnslang}, |
739 |
{"addlangsection", tcl_addlangsection}, |
740 |
{"dellangsection", tcl_dellangsection}, |
741 |
{"relang", tcl_relang}, |
742 |
{0, 0} |
743 |
}; |
744 |
|
745 |
void init_language(int flag) |
746 |
{ |
747 |
int i; |
748 |
char *deflang; |
749 |
|
750 |
Context; |
751 |
if (flag) { |
752 |
for (i = 0; i < 32; i++) |
753 |
langtab[i] = 0; |
754 |
/* The default language is always "english" as language files are |
755 |
* gauranteed to exist in english. */ |
756 |
add_lang("english"); |
757 |
/* Let the user choose a different, preferred language */ |
758 |
deflang = getenv("EGG_LANG"); |
759 |
if (deflang) |
760 |
add_lang(deflang); |
761 |
add_lang_section("core"); |
762 |
} else { |
763 |
add_tcl_commands(langtcls); |
764 |
add_builtins(H_dcc, langdcc); |
765 |
} |
766 |
} |