| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- /*
- * language.c -- handles:
- * language support code
- *
- */
- /*
- * DOES:
- * Nothing <- typical BB code :)
- *
- * ENVIRONMENT VARIABLES:
- * EGG_LANG - language to use (default: "english")
- * EGG_LANGDIR - directory with all lang files
- * (default: "./language")
- * WILL DO:
- * Upon loading:
- * o default loads section core, if possible.
- * Commands:
- * DCC .+lang <language>
- * DCC .-lang <language>
- * DCC .+lsec <section>
- * DCC .-lsec <section>
- * DCC .relang
- * DCC .ldump
- * DCC .lstat
- *
- * FILE FORMAT: language.lang
- * <textidx>,<text>
- * TEXT MESSAGE USAGE:
- * get_language(<textidx> [,<PARMS>])
- *
- * ADDING LANGUAGES:
- * o Copy an existing <section>.<oldlanguage>.lang to a
- * new .lang file and modify as needed.
- * Use %s or %d where necessary, for plug-in
- * insertions of parameters (see core.english.lang).
- * o Ensure <section>.<newlanguage>.lang is in the lang
- * directory.
- * o .+lang <newlanguage>
- * ADDING SECTIONS:
- * o Create a <newsection>.english.lang file.
- * o Add add_lang_section("<newsection>"); to your module
- * startup function.
- *
- */
- #include "main.h"
- extern struct dcc_t *dcc;
- typedef struct lang_st {
- struct lang_st *next;
- char *lang;
- char *section;
- } lang_sec;
- typedef struct lang_pr {
- struct lang_pr *next;
- char *lang;
- } lang_pri;
- typedef struct lang_t {
- int idx;
- char *text;
- struct lang_t *next;
- } lang_tab;
- static lang_tab *langtab[64];
- static lang_sec *langsection = NULL;
- static lang_pri *langpriority = NULL;
- static int add_message(int, char *);
- static void read_lang(char *);
- void add_lang_section(char *);
- int del_lang_section(char *);
- int exist_lang_section(char *);
- static char *get_specific_langfile(char *, lang_sec *);
- static char *get_langfile(lang_sec *);
- /* Add a new preferred language to the list of languages. Newly added
- * languages get the highest priority.
- */
- void add_lang(char *lang)
- {
- lang_pri *lp = langpriority, *lpo = NULL;
- while (lp) {
- /* The language already exists, moving to the beginning */
- if (!strcmp(lang, lp->lang)) {
- /* Already at the front? */
- if (!lpo)
- return;
- lpo->next = lp->next;
- lp->next = lpo;
- langpriority = lp;
- return;
- }
- lpo = lp;
- lp = lp->next;
- }
- /* No existing entry, create a new one */
- lp = nmalloc(sizeof(lang_pri));
- lp->lang = nmalloc(strlen(lang) + 1);
- strcpy(lp->lang, lang);
- lp->next = NULL;
- /* If we have other entries, point to the beginning of the old list */
- if (langpriority)
- lp->next = langpriority;
- langpriority = lp;
- debug1("LANG: Language loaded: %s", lang);
- }
- static int add_message(int lidx, char *ltext)
- {
- lang_tab *l = langtab[lidx & 63];
- while (l) {
- if (l->idx && (l->idx == lidx)) {
- nfree(l->text);
- l->text = nmalloc(strlen(ltext) + 1);
- strcpy(l->text, ltext);
- return 1;
- }
- if (!l->next)
- break;
- l = l->next;
- }
- if (l) {
- l->next = nmalloc(sizeof(lang_tab));
- l = l->next;
- } else
- l = langtab[lidx & 63] = nmalloc(sizeof(lang_tab));
- l->idx = lidx;
- l->text = nmalloc(strlen(ltext) + 1);
- strcpy(l->text, ltext);
- l->next = 0;
- return 0;
- }
- /* Parse a language file
- */
- static void read_lang(char *langfile)
- {
- FILE *FLANG;
- char lbuf[512];
- char *ltext = NULL;
- char *ctmp, *ctmp1;
- int lidx;
- int lline = 0;
- int lskip;
- int ltexts = 0;
- int ladd = 0, lupdate = 0;
- FLANG = fopen(langfile, "r");
- if (FLANG == NULL) {
- putlog(LOG_MISC, "*", "LANG: unexpected: reading from file %s failed.",
- langfile);
- return;
- }
- lskip = 0;
- while (fgets(lbuf, 511, FLANG)) {
- lline++;
- if (lbuf[0] != '#' || lskip) {
- ltext = nrealloc(ltext, 512);
- if (sscanf(lbuf, "%s", ltext) != EOF) {
- #ifdef LIBSAFE_HACKS
- if (sscanf(lbuf, "0x%x,%500c", &lidx, ltext) != 1) {
- #else
- if (sscanf(lbuf, "0x%x,%500c", &lidx, ltext) != 2) {
- #endif
- putlog(LOG_MISC, "*", "Malformed text line in %s at %d.",
- langfile, lline);
- } else {
- ltexts++;
- ctmp = strchr(ltext, '\n');
- *ctmp = 0;
- while (ltext[strlen(ltext) - 1] == '\\') {
- ltext[strlen(ltext) - 1] = 0;
- if (fgets(lbuf, 511, FLANG)) {
- lline++;
- ctmp = strchr(lbuf, '\n');
- *ctmp = 0;
- ltext = nrealloc(ltext, strlen(lbuf) + strlen(ltext) + 1);
- strcpy(strchr(ltext, 0), lbuf);
- }
- }
- }
- /* We gotta fix \n's here as, being arguments to sprintf(),
- * they won't get translated.
- */
- ctmp = ltext;
- ctmp1 = ltext;
- while (*ctmp1) {
- if ((*ctmp1 == '\\') && (*(ctmp1 + 1) == 'n')) {
- *ctmp = '\n';
- ctmp1++;
- } else if ((*ctmp1 == '\\') && (*(ctmp1 + 1) == 't')) {
- *ctmp = '\t';
- ctmp1++;
- } else
- *ctmp = *ctmp1;
- ctmp++;
- ctmp1++;
- }
- *ctmp = '\0';
- if (add_message(lidx, ltext)) {
- lupdate++;
- } else
- ladd++;
- }
- } else {
- ctmp = strchr(lbuf, '\n');
- if (lskip && (strlen(lbuf) == 1 || *(ctmp - 1) != '\\'))
- lskip = 0;
- }
- }
- nfree(ltext);
- fclose(FLANG);
- debug3("LANG: %d messages of %d lines loaded from %s", ltexts, lline,
- langfile);
- debug2("LANG: %d adds, %d updates to message table", ladd, lupdate);
- }
- /* Returns 1 if the section exists, otherwise 0.
- */
- int exist_lang_section(char *section)
- {
- lang_sec *ls;
- for (ls = langsection; ls; ls = ls->next)
- if (!strcmp(section, ls->section))
- return 1;
- return 0;
- }
- /* Add a new language section. e.g. section "core"
- * Load an apropriate language file for the specified section.
- */
- void add_lang_section(char *section)
- {
- char *langfile = NULL;
- lang_sec *ls, *ols = NULL;
- int ok = 0;
- for (ls = langsection; ls; ols = ls, ls = ls->next)
- /* Already know of that section? */
- if (!strcmp(section, ls->section))
- return;
- /* Create new section entry */
- ls = nmalloc(sizeof(lang_sec));
- ls->section = nmalloc(strlen(section) + 1);
- strcpy(ls->section, section);
- ls->lang = NULL;
- ls->next = NULL;
- /* Connect to existing list of sections */
- if (ols)
- ols->next = ls;
- else
- langsection = ls;
- debug1("LANG: Section loaded: %s", section);
- /* Always load base language */
- langfile = get_specific_langfile(BASELANG, ls);
- if (langfile) {
- read_lang(langfile);
- nfree(langfile);
- ok = 1;
- }
- /* Now overwrite base language with a more preferred one */
- langfile = get_langfile(ls);
- if (!langfile) {
- // if (!ok)
- // putlog(LOG_MISC, "*", "LANG: No lang files found for section %s.",section);
- return;
- }
- read_lang(langfile);
- nfree(langfile);
- }
- int del_lang_section(char *section)
- {
- lang_sec *ls, *ols;
- for (ls = langsection, ols = NULL; ls; ols = ls, ls = ls->next)
- if (ls->section && !strcmp(ls->section, section)) {
- if (ols)
- ols->next = ls->next;
- else
- langsection = ls->next;
- nfree(ls->section);
- if (ls->lang)
- nfree(ls->lang);
- nfree(ls);
- debug1("LANG: Section unloaded: %s", section);
- return 1;
- }
- return 0;
- }
- static char *get_specific_langfile(char *language, lang_sec *sec)
- {
- char *ldir = getenv("EGG_LANGDIR");
- char *langfile;
- FILE *sfile = NULL;
- if (!ldir)
- ldir = LANGDIR;
- langfile = nmalloc(strlen(ldir) + strlen(sec->section) + strlen(language)+8);
- sprintf(langfile, "%s/%s.%s.lang", ldir, sec->section, language);
- sfile = fopen(langfile, "r");
- if (sfile) {
- fclose(sfile);
- /* Save language used for this section */
- sec->lang = nrealloc(sec->lang, strlen(language) + 1);
- strcpy(sec->lang, language);
- return langfile;
- }
- nfree(langfile);
- return NULL;
- }
- /* Searches for available language files and returns the file with the
- * most preferred language.
- */
- static char *get_langfile(lang_sec *sec)
- {
- char *langfile;
- lang_pri *lp;
- for (lp = langpriority; lp; lp = lp->next) {
- /* There is no need to reload the same language */
- if (sec->lang && !strcmp(sec->lang, lp->lang))
- return NULL;
- langfile = get_specific_langfile(lp->lang, sec);
- if (langfile)
- return langfile;
- }
- /* We did not find any files, clear the language field */
- if (sec->lang)
- nfree(sec->lang);
- sec->lang = NULL;
- return NULL;
- }
- static char text[512];
- char *get_language(int idx)
- {
- lang_tab *l;
- if (!idx)
- return "MSG-0-";
- for (l = langtab[idx & 63]; l; l = l->next)
- if (idx == l->idx)
- return l->text;
- egg_snprintf(text, sizeof text, "MSG%03X", idx);
- return text;
- }
- int expmem_language()
- {
- lang_tab *l;
- lang_sec *ls;
- lang_pri *lp;
- int i, size = 0;
- for (i = 0; i < 64; i++)
- for (l = langtab[i]; l; l = l->next) {
- size += sizeof(lang_tab);
- size += (strlen(l->text) + 1);
- }
- for (ls = langsection; ls; ls = ls->next) {
- size += sizeof(lang_sec);
- if (ls->section)
- size += strlen(ls->section)+1;
- if (ls->lang)
- size += strlen(ls->lang)+1;
- }
- for (lp = langpriority; lp; lp = lp->next) {
- size += sizeof(lang_pri);
- if (lp->lang)
- size += strlen(lp->lang)+1;
- }
- return size;
- }
- void init_language(int flag)
- {
- int i;
- char *deflang;
- if (flag) {
- for (i = 0; i < 32; i++)
- langtab[i] = 0;
- /* The default language is always BASELANG as language files are
- * gauranteed to exist in that language.
- */
- add_lang(BASELANG);
- /* Let the user choose a different, preferred language */
- deflang = getenv("EGG_LANG");
- if (deflang)
- add_lang(deflang);
- add_lang_section("core");
- }
- }
|