/[cvs]/eggdrop1.9/src/language.c
ViewVC logotype

Contents of /eggdrop1.9/src/language.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Mon Sep 13 14:36:18 1999 UTC (19 years, 10 months ago) by segfault
Branch: MAIN
File MIME type: text/x-chdr
Initial commit based off of .29 cvs

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23