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