1 /*
2 * $Id: msg.c,v 1.13 2005/04/10 15:26:37 aonoto Exp $
3 */
4
5 /*
6 * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
7 * This file is part of FreeWnn.
8 *
9 * Copyright Kyoto University Research Institute for Mathematical Sciences
10 * 1987, 1988, 1989, 1990, 1991, 1992
11 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
12 * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
13 * Copyright FreeWnn Project 1999, 2000, 2002
14 *
15 * Maintainer: FreeWnn Project <freewnn@tomo.gr.jp>
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2 of the License, or (at your option) any later version.
21 *
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with this library; if not, write to the
29 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 * Boston, MA 02111-1307, USA.
31 */
32
33 /*
34 struct msg_cat msg_open(name, nlspath, lang)
35 char *name;
36 char *nlspath;
37 char *lang;
38
39 char * msg_get(cd, id, s, lang)
40 struct msg_cat cd;
41 int id;
42 char *s;
43
44 void msg_close(cd)
45 struct msg_cat cd;
46
47 format of message file
48 <message id>\t<message>
49 */
50 #ifdef HAVE_CONFIG_H
51 # include <config.h>
52 #endif
53
54 #include <stdio.h>
55 #if STDC_HEADERS
56 # include <stdlib.h>
57 # include <string.h>
58 #else
59 # if HAVE_MALLOC_H
60 # include <malloc.h>
61 # endif
62 # if HAVE_STRINGS_H
63 # include <strings.h>
64 # endif
65 #endif /* STDC_HEADERS */
66
67 #include "commonhd.h"
68 #include "wnn_os.h"
69 #include "msg.h"
70
71 static char *
getlang(char * lang)72 getlang(char *lang)
73 {
74 static char tmp[32];
75 char *p;
76 int i;
77
78 if (lang == NULL || *lang == '\0') {
79 #ifdef HAS_SETLOCALE
80 lang = setlocale(LC_ALL, NULL);
81 if (lang == NULL || *lang == '\0')
82 #endif
83 {
84 lang = getenv("LC_MESSAGES");
85 if (lang == NULL || *lang == '\0') {
86 lang = getenv("LANG");
87
88 if (lang == NULL || *lang == '\0') {
89 lang = DEF_LANG;
90 }
91 }
92 }
93 }
94 for (i = 0, p = lang; *p && *p != '.'; i++, p++)
95 tmp[i] = *p;
96
97 tmp[i] = '\0';
98
99 return (tmp);
100 /*
101 return(lang);
102 */
103 }
104
105 static int
_search(int * id,struct msg_bd * bd)106 _search(int *id,
107 struct msg_bd *bd)
108 {
109 return (*id - bd->msg_id);
110 }
111
112 static void
_escape(register char * op,register char * ip)113 _escape(register char *op,
114 register char *ip)
115 {
116 for (; *ip != 0; ip++, op++) {
117 if (*ip == '\\') {
118 switch (*++ip) {
119 case 'n':
120 *op = '\n';
121 break;
122 case 't':
123 *op = '\t';
124 break;
125 case 'b':
126 *op = '\b';
127 break;
128 case 'r':
129 *op = '\r';
130 break;
131 case 'f':
132 *op = '\f';
133 break;
134 case 'v':
135 *op = '\v';
136 break;
137 case '0':
138 *op = 0;
139 break;
140 /*
141 case 'a':
142 *op = '\a';
143 break;
144 case 'e':
145 case 'E':
146 case 'o':
147 case 'd':
148 case 'x':
149 break;
150 */
151 default:
152 *op = *ip;
153 break;
154 }
155 } else {
156 if (*ip == '\n')
157 *op = '\0';
158 else
159 *op = *ip;
160 }
161 }
162 *op = 0;
163 }
164
165 static char *
get_msg_bd(struct msg_cat * cd,int id)166 get_msg_bd(struct msg_cat *cd,
167 int id)
168 {
169 register struct msg_bd *bd;
170
171 if (cd->msg_bd == 0 || cd->msg_cnt == 0)
172 return (NULL);
173
174 bd = (struct msg_bd *)bsearch(&id,
175 cd->msg_bd,
176 cd->msg_cnt,
177 sizeof (struct msg_bd),
178 _search);
179 if (bd == NULL)
180 return (NULL);
181 return (bd->msg);
182 }
183
184 /* expand
185 %N: the value of the name parameter passed to msg_open()
186 %L: the value of LANG
187 %l: the language element from LANG
188 %t: the territory element from LANG
189 %c: the codeset element from LANG
190 %%: a single % charctor
191 */
192 static int
expand(register char * op,register char * ip,register char * name,register char * lang)193 expand (register char *op,
194 register char *ip,
195 register char *name,
196 register char *lang)
197 {
198 if (!ip || !*ip)
199 return (-1);
200
201 for (; *ip != 0; ip++) {
202 if (*ip == '%') {
203 switch (*++ip) {
204 case 'N':
205 if (!name || !*name)
206 return (-1);
207 strcpy(op, name);
208 op += strlen(name);
209 break;
210 case 'L':
211 if (!lang || !*lang)
212 return (-1);
213 strcpy(op, lang);
214 op += strlen(lang);
215 break;
216 /*
217 case 'l':
218 strcpy(op, language);
219 op += strlen(language);
220 break;
221 case 't':
222 strcpy(op, terr);
223 op += strlen(terr);
224 break;
225 case 'c':
226 strcpy(op, code);
227 op += strlen(code);
228 break;
229 case '%':
230 strcpy(op, "%");
231 op += strlen("%");
232 break;
233 */
234 default:
235 break;
236 }
237 } else {
238 *op = *ip;
239 op++;
240 }
241 }
242 *op = '\0';
243
244 return (0);
245 }
246
247
248 struct msg_cat *
msg_open(char * name,char * nlspath,char * lang)249 msg_open (char *name,
250 char *nlspath,
251 char *lang)
252 {
253 struct msg_cat *cd;
254
255 char fn[MAXPATHLEN];
256 FILE *fp;
257 char data[1024];
258 char save[1024];
259 int msg_cnt = 0;
260 int msg_byte = 0;
261 register char *dp;
262 register struct msg_bd *bd;
263 register char *msg, *l;
264
265 l = getlang(lang);
266
267 if (name && *name == '/')
268 strcpy (fn, name);
269 else {
270 if (expand (fn, nlspath, name, l) == -1)
271 return (NULL);
272 }
273
274 if (!(cd = (struct msg_cat *) malloc (sizeof (struct msg_cat))))
275 return (NULL);
276
277 strcpy (cd->name, name);
278 strcpy (cd->lang, l);
279 strcpy (cd->nlspath, nlspath);
280 cd->nextp = NULL;
281 cd->msg_cnt = 0;
282
283 if ((fp = fopen (fn, "r")) == NULL) {
284 /* message file not found */
285 cd->msg_bd = 0;
286 return (cd);
287 }
288
289 for (;;) {
290 /* first: count bytes */
291 if (fgets (data, 1024, fp) == NULL)
292 break;
293
294 /* comment */
295 if (*data == '#')
296 continue;
297
298 for (dp = data; *dp && *dp != '\t'; dp++);
299 /* msg_id:message\n */
300
301 if (*dp == '\0')
302 continue;
303
304 dp++;
305 msg_byte += strlen (dp);
306 msg_cnt++;
307 }
308
309 rewind(fp);
310
311 cd->msg_cnt = msg_cnt;
312
313 if (!(bd = cd->msg_bd =
314 (struct msg_bd *)malloc((sizeof (struct msg_bd)) * msg_cnt + msg_byte + 1))) {
315 fclose(fp);
316 free(cd);
317 return (NULL);
318 }
319
320 msg = (char *) bd + (sizeof (struct msg_bd)) * msg_cnt;
321
322 for (;;) {
323 /* second : get message */
324 if (fgets(data, 1024, fp) == NULL)
325 break;
326
327 if (*data == '#')
328 /* comment */
329 continue;
330
331 for (dp = data; *dp && *dp != '\t'; dp++);
332 /* msg_id:message\n */
333
334 if (*dp == '\0')
335 continue;
336
337 *dp = 0;
338 dp++;
339 bd->msg_id = atoi(data);
340 bd->msg = msg;
341 bd++;
342 _escape(save, dp);
343 strcpy(msg, save);
344 msg += strlen(save);
345 *msg = 0;
346 msg++;
347 }
348
349 fclose(fp);
350 return (cd);
351 }
352
353 char *
msg_get(struct msg_cat * catd,int id,char * msg,register char * lang)354 msg_get(struct msg_cat *catd,
355 int id,
356 char *msg,
357 register char *lang)
358 {
359 register struct msg_cat *cd;
360 register char *msg_bd;
361
362 if (catd == 0)
363 goto error;
364
365 cd = catd;
366
367 if (lang == 0 || *lang == '\0')
368 lang = cd->lang;
369 else {
370 for (;; cd = cd->nextp) {
371 if (strcmp(lang, cd->lang) == 0)
372 break;
373 if (cd->nextp == 0) {
374 cd->nextp = msg_open(cd->name, cd->nlspath, lang);
375 cd = cd->nextp;
376 break;
377 }
378 }
379 }
380
381 if (msg_bd = get_msg_bd(cd, id))
382 return (msg_bd);
383 error:
384
385 if (msg != 0 && *msg != '\0')
386 return (msg);
387
388 {
389 static char ret[128];
390 sprintf(ret, "mes_id = %d: %s", id, DEF_MSG);
391 return (ret);
392 }
393 }
394
395 void
msg_close(register struct msg_cat * cd)396 msg_close(register struct msg_cat *cd)
397 {
398 if (cd->nextp)
399 msg_close(cd->nextp);
400
401 if (cd->msg_bd)
402 free(cd->msg_bd);
403
404 if (cd)
405 free(cd);
406 }
407
408 #ifdef not_use
409 /* test */
main()410 main()
411 {
412 struct msg_cat *cd;
413
414 cd = msg_open("msg", "%L", "ja_JP");
415
416 printf (msg_get(cd, 5, "message not found\n", "ja_JP"), 555);
417 printf (msg_get(cd, 6, "message not found\n", "zh_CN"));
418 printf (msg_get(cd, -1, "", "ja_JP"), 555);
419 printf (msg_get(cd, 2, "message not found\n", "ja_JP"), "abc");
420 printf (msg_get(cd, 100, "message not found\n", "zh_CN"), "abc");
421 }
422 #endif /* not_use */
423