changed Makefile; build all commands as an own file
[NeonServV5.git] / lang.c
1 #include "lang.h"
2 #include "UserNode.h"
3 #include "DBHelper.h"
4 #include "mysqlConn.h"
5
6 #define DEFAULT_LANG_TAG "EN"
7 #define DEFAULT_LANG_NAME "English"
8
9 static struct language **langdict;
10 static struct language *lang_c;
11
12 void init_lang() {
13     langdict = calloc(MAXLANGUAGES, sizeof(*langdict));
14 }
15
16 void free_lang() {
17     
18 }
19
20 void load_languages() {
21     MYSQL_RES *res;
22     MYSQL_ROW row;
23     printf_mysql_query("SELECT `lang`, `text` FROM `language` WHERE `ident` = 'name'");
24     res = mysql_use();
25     while((row = mysql_fetch_row(res)) != NULL) {
26         load_language(row[0], row[1]);
27     }
28 }
29
30 static struct language* add_language(char *langtag, char *langname) {
31     int cindex;
32     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
33         if(langdict[cindex] == NULL) break;
34         if(!strcmp(langdict[cindex]->langname, langname) || !strcmp(langdict[cindex]->langtag, langtag))
35             return langdict[cindex];
36     }
37     if(cindex == MAXLANGUAGES) return NULL;
38     struct language *lang = malloc(sizeof(*lang));
39     if (!lang) {
40         perror("malloc() failed");
41         return NULL;
42     }
43     lang->langtag = strdup(langtag);
44     lang->langname = strdup(langname);
45     struct language_table **entrys = calloc(27, sizeof(*entrys));
46     lang->entrys = entrys;
47     langdict[cindex] = lang;
48     return lang;
49 }
50
51 static int get_entry_index(const char *ident) {
52     const char *underscore = strstr(ident, "_");
53     if(!underscore || !(underscore[1] >= 65 && underscore[1] <= 90)) return 26;
54     return (underscore[1] - 'A');
55 }
56
57 void load_language(char *tag, char *name) {
58     struct language *lang = get_language_by_tag(tag);
59     if(lang == get_default_language()) return;
60     if(lang) {
61         //remove all entrys
62         int cindex;
63         struct language_table *entry, *next;
64         for(cindex = 0; cindex < 27; cindex++) {
65             for(entry = lang->entrys[cindex]; entry; entry = next) {
66                 next = entry->next;
67                 free(entry->ident);
68                 free(entry->text);
69                 free(entry);
70             }
71             lang->entrys[cindex] = NULL;
72         }
73     } else
74         lang = add_language(tag, name);
75     if(!lang) return;
76     MYSQL_RES *res;
77     MYSQL_ROW row;
78     printf_mysql_query("SELECT `ident`, `text` FROM `language` WHERE `lang` = '%s' AND `ident` != 'name'", escape_string(tag));
79     res = mysql_use();
80     while((row = mysql_fetch_row(res)) != NULL) {
81         register_language_string(lang, row[0], row[1]);
82     }
83 }
84
85 struct language* get_language_by_tag(char *tag) {
86     int cindex;
87     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
88         if(langdict[cindex] == NULL) break;
89         if(!stricmp(langdict[cindex]->langtag, tag))
90             return langdict[cindex];
91     }
92     return NULL;
93 }
94
95 struct language* get_language_by_name(char *name) {
96     int cindex;
97     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
98         if(langdict[cindex] == NULL) break;
99         if(!stricmp(langdict[cindex]->langname, name))
100             return langdict[cindex];
101     }
102     return NULL;
103 }
104
105 struct language* get_default_language() {
106     if(lang_c == NULL) 
107         lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
108     return lang_c;
109 }
110
111 void register_default_language_table(const struct default_language_entry *msgtab) {
112     if(lang_c == NULL) 
113         lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
114     while(msgtab->ident) {
115         register_language_string(lang_c, msgtab->ident, msgtab->text);
116         msgtab++;
117     }
118 }
119
120 void register_language_string(struct language *lang, char *ident, char *text) {
121     int cindex = get_entry_index(ident);
122     struct language_table *lang_entry = malloc(sizeof(*lang_entry));
123     if (!lang_entry) {
124         perror("malloc() failed");
125         return;
126     }
127     
128     lang_entry->ident = strdup(ident);
129     //replace all:
130     //$b to \002
131     //$k to \003
132     char txt[MAXLEN];
133     strcpy(txt, text);
134     char tmp[MAXLEN];
135     int tmppos = 0;
136     char *a, *b = txt;
137     do {
138         a = strstr(b, "$");
139         if(a) *a = '\0';
140         tmppos += sprintf(tmp + tmppos, "%s", b);
141         if(a) {
142             switch(a[1]) {
143                 case 'b':
144                     tmp[tmppos++] = '\002';
145                     break;
146                 case 'k':
147                     tmp[tmppos++] = '\003';
148                     break;
149                 default:
150                     //unknown - just write it
151                     tmppos += sprintf(tmp + tmppos, "$%c", a[1]);
152             }
153             b = a+2;
154         }
155     } while(a);
156     lang_entry->text = strdup(tmp);
157     lang_entry->next = lang->entrys[cindex];
158     lang->entrys[cindex] = lang_entry;
159 }
160
161 char *get_language_string(struct UserNode *user, const char* msg_ident) {
162     struct language* lang;
163     if((user->flags & USERFLAG_ISAUTHED)) {
164         loadUserSettings(user);
165         lang = user->language;
166     } else
167         lang = lang_c;
168     int cindex = get_entry_index(msg_ident);
169     struct language_table* entry;
170     for(entry = lang->entrys[cindex]; entry; entry = entry->next) {
171         if(!strcmp(entry->ident, msg_ident))
172             return entry->text;
173     }
174     if(lang == lang_c) return NULL;
175     for(entry = lang_c->entrys[cindex]; entry; entry = entry->next) {
176         if(!strcmp(entry->ident, msg_ident))
177             return entry->text;
178     }
179     return NULL;
180 }
181
182 char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...) {
183     char *formatStr = get_language_string(user, msg_ident);
184     if(!formatStr) return NULL;
185     if(buffer == NULL) {
186         buffer = (char *)malloc((MAXLEN+1) * sizeof(char));
187         if (!buffer) {
188             perror("malloc() failed");
189             return NULL;
190         }
191     }
192     int pos;
193     va_list arg_list;
194     buffer[0] = '\0';
195     va_start(arg_list, msg_ident);
196     pos = vsnprintf(buffer, MAXLEN - 2, formatStr, arg_list);
197     va_end(arg_list);
198     if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
199     buffer[pos] = '\0';
200     return buffer;
201 }