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

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

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


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

1 segfault 1.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