fixed some missing includes
[NeonServV5.git] / src / lang.c
1 /* lang.c - NeonServ v5.6
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "lang.h"
18 #include "UserNode.h"
19 #include "DBHelper.h"
20 #include "mysqlConn.h"
21 #include "tools.h"
22
23 #define DEFAULT_LANG_TAG "EN"
24 #define DEFAULT_LANG_NAME "English"
25
26 static struct language **langdict;
27 static struct language *lang_c;
28
29 void init_lang() {
30     langdict = calloc(MAXLANGUAGES, sizeof(*langdict));
31 }
32
33 void free_lang() {
34     
35 }
36
37 void load_languages() {
38     MYSQL_RES *res;
39     MYSQL_ROW row;
40     printf_mysql_query("SELECT `lang`, `text` FROM `language` WHERE `ident` = 'name'");
41     res = mysql_use();
42     while((row = mysql_fetch_row(res)) != NULL) {
43         load_language(row[0], row[1]);
44     }
45 }
46
47 static struct language* add_language(char *langtag, char *langname) {
48     int cindex;
49     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
50         if(langdict[cindex] == NULL) break;
51         if(!strcmp(langdict[cindex]->langname, langname) || !strcmp(langdict[cindex]->langtag, langtag))
52             return langdict[cindex];
53     }
54     if(cindex == MAXLANGUAGES) return NULL;
55     struct language *lang = malloc(sizeof(*lang));
56     if (!lang) {
57         perror("malloc() failed");
58         return NULL;
59     }
60     lang->langtag = strdup(langtag);
61     lang->langname = strdup(langname);
62     struct language_table **entrys = calloc(27, sizeof(*entrys));
63     lang->entrys = entrys;
64     langdict[cindex] = lang;
65     return lang;
66 }
67
68 static int get_entry_index(const char *ident) {
69     const char *underscore = strstr(ident, "_");
70     if(!underscore || !(underscore[1] >= 65 && underscore[1] <= 90)) return 26;
71     return (underscore[1] - 'A');
72 }
73
74 void load_language(char *tag, char *name) {
75     struct language *lang = get_language_by_tag(tag);
76     if(lang == get_default_language()) return;
77     if(lang) {
78         //remove all entrys
79         int cindex;
80         struct language_table *entry, *next;
81         for(cindex = 0; cindex < 27; cindex++) {
82             for(entry = lang->entrys[cindex]; entry; entry = next) {
83                 next = entry->next;
84                 free(entry->ident);
85                 free(entry->text);
86                 free(entry);
87             }
88             lang->entrys[cindex] = NULL;
89         }
90     } else
91         lang = add_language(tag, name);
92     if(!lang) return;
93     MYSQL_RES *res;
94     MYSQL_ROW row;
95     printf_mysql_query("SELECT `ident`, `text` FROM `language` WHERE `lang` = '%s' AND `ident` != 'name'", escape_string(tag));
96     res = mysql_use();
97     while((row = mysql_fetch_row(res)) != NULL) {
98         register_language_string(lang, row[0], row[1]);
99     }
100 }
101
102 struct language* get_language_by_tag(char *tag) {
103     int cindex;
104     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
105         if(langdict[cindex] == NULL) break;
106         if(!stricmp(langdict[cindex]->langtag, tag))
107             return langdict[cindex];
108     }
109     return NULL;
110 }
111
112 struct language* get_language_by_name(char *name) {
113     int cindex;
114     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
115         if(langdict[cindex] == NULL) break;
116         if(!stricmp(langdict[cindex]->langname, name))
117             return langdict[cindex];
118     }
119     return NULL;
120 }
121
122 struct language* get_default_language() {
123     if(lang_c == NULL) 
124         lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
125     return lang_c;
126 }
127
128 void register_default_language_table(const struct default_language_entry *msgtab) {
129     if(lang_c == NULL) 
130         lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
131     while(msgtab->ident) {
132         register_language_string(lang_c, msgtab->ident, msgtab->text);
133         msgtab++;
134     }
135 }
136
137 void register_language_string(struct language *lang, char *ident, char *text) {
138     int cindex = get_entry_index(ident);
139     struct language_table *lang_entry;
140     for(lang_entry = lang->entrys[cindex]; lang_entry; lang_entry = lang_entry->next) {
141         if(!strcmp(lang_entry->ident, ident)) break;
142     }
143     if(!lang_entry) {
144         lang_entry = malloc(sizeof(*lang_entry));
145         if (!lang_entry) {
146             perror("malloc() failed");
147             return;
148         }
149         lang_entry->ident = strdup(ident);
150         lang_entry->next = lang->entrys[cindex];
151         lang->entrys[cindex] = lang_entry;
152     } else
153         free(lang_entry->text); //free old text (new one will be set below)
154     //replace all:
155     //$b to \002
156     //$k to \003
157     char txt[MAXLEN];
158     strcpy(txt, text);
159     char tmp[MAXLEN];
160     int tmppos = 0;
161     char *a, *b = txt;
162     do {
163         a = strstr(b, "$");
164         if(a) *a = '\0';
165         tmppos += sprintf(tmp + tmppos, "%s", b);
166         if(a) {
167             switch(a[1]) {
168                 case 'b':
169                     tmp[tmppos++] = 2;
170                     break;
171                 case 'k':
172                     tmp[tmppos++] = 3;
173                     break;
174                 case 'u':
175                     tmp[tmppos++] = 31;
176                     break;
177                 default:
178                     //unknown - just write it
179                     tmppos += sprintf(tmp + tmppos, "$%c", a[1]);
180             }
181             b = a+2;
182         }
183     } while(a);
184     lang_entry->text = strdup(tmp);
185 }
186
187 char *get_language_string(struct UserNode *user, const char* msg_ident) {
188     struct language* lang;
189     if(user && (user->flags & USERFLAG_ISAUTHED)) {
190         loadUserSettings(user);
191         lang = user->language;
192     } else
193         lang = lang_c;
194     int cindex = get_entry_index(msg_ident);
195     struct language_table* entry;
196     for(entry = lang->entrys[cindex]; entry; entry = entry->next) {
197         if(!strcmp(entry->ident, msg_ident))
198             return entry->text;
199     }
200     if(lang == lang_c) return NULL;
201     for(entry = lang_c->entrys[cindex]; entry; entry = entry->next) {
202         if(!strcmp(entry->ident, msg_ident))
203             return entry->text;
204     }
205     return NULL;
206 }
207
208 char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...) {
209     char *formatStr = get_language_string(user, msg_ident);
210     if(!formatStr) return NULL;
211     if(buffer == NULL) {
212         buffer = (char *)malloc((MAXLEN+1) * sizeof(char));
213         if (!buffer) {
214             perror("malloc() failed");
215             return NULL;
216         }
217     }
218     int pos;
219     va_list arg_list;
220     buffer[0] = '\0';
221     va_start(arg_list, msg_ident);
222     pos = vsnprintf(buffer, MAXLEN - 2, formatStr, arg_list);
223     va_end(arg_list);
224     if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
225     buffer[pos] = '\0';
226     return buffer;
227 }