1 /*
2   LibRCC - language configuration: supported charsets and engines, various
3   options
4 
5   Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
6 
7   This library is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License version 2.1 or later
9   as published by the Free Software Foundation.
10 
11   This library is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
14   for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with this program; if not, write to the Free Software Foundation, Inc.,
18   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include <string.h>
25 #ifdef HAVE_STRINGS_H
26 # include <strings.h>
27 #endif /* HAVE_STRINGS_H */
28 
29 #include "../config.h"
30 
31 #include "internal.h"
32 #include "rccconfig.h"
33 #include "rcclocale.h"
34 #include "rcclist.h"
35 #include "lng.h"
36 
rccConfigGetLanguage(rcc_language_config config)37 rcc_language_id rccConfigGetLanguage(rcc_language_config config) {
38     unsigned long i;
39     rcc_language_ptr *llist;
40 
41     if (!config) return (rcc_language_id)-1;
42 
43     llist = rccGetLanguageList(config->ctx);
44     for (i=0;llist[i];i++)
45 	if (llist[i] == config->language) return (rcc_language_id)i;
46 
47     return (rcc_language_id)-1;
48 }
49 
rccConfigGetLanguagePointer(rcc_language_config config)50 rcc_language_ptr rccConfigGetLanguagePointer(rcc_language_config config) {
51     if (!config) return NULL;
52 
53     return config->language;
54 }
55 
rccConfigGetLanguageName(rcc_language_config config)56 const char *rccConfigGetLanguageName(rcc_language_config config) {
57     if ((!config)||(!config->language)) return NULL;
58 
59     return config->language->sn;
60 }
61 
rccConfigGetCharsetNumber(rcc_language_config config)62 int rccConfigGetCharsetNumber(rcc_language_config config) {
63     int i;
64     rcc_charset *charsets;
65 
66     if ((!config)||(!config->language)) return 0;
67 
68     charsets = config->language->charsets;
69 
70     for (i=0;charsets[i];i++);
71 
72     return i;
73 }
74 
rccConfigGetClassCharsetNumber(rcc_language_config config,rcc_class_id class_id)75 int rccConfigGetClassCharsetNumber(rcc_language_config config, rcc_class_id class_id) {
76     int sum, i;
77     rcc_charset *charsets;
78 
79     if ((!config)||(!config->language)) return 0;
80     if ((class_id<0)||(class_id>=config->ctx->n_classes)) return 0;
81 
82     sum = rccConfigGetCharsetNumber(config);
83 
84     charsets = config->ctx->iclass[class_id].additional;
85     if (charsets) {
86 	for (i=0;charsets[i];i++)
87 	    if (rccConfigGetCharsetByName(config, charsets[i]) == (rcc_language_id)-1) sum++;
88     }
89 
90     return sum;
91 }
92 
rccConfigGetEngineNumber(rcc_language_config config)93 int rccConfigGetEngineNumber(rcc_language_config config) {
94     int i;
95     rcc_engine_ptr *engines;
96 
97     if ((!config)||(!config->language)) return 0;
98     engines = config->language->engines;
99     for (i=0;engines[i];i++);
100     return i;
101 }
102 
103 
rccConfigGetEnginePointer(rcc_language_config config,rcc_engine_id engine_id)104 rcc_engine_ptr rccConfigGetEnginePointer(rcc_language_config config, rcc_engine_id engine_id) {
105     if ((!config)||(!config->language)) return NULL;
106     if (engine_id == (rcc_engine_id)-1) return NULL;
107     if (engine_id>=rccConfigGetEngineNumber(config)) return NULL;
108 
109     return config->language->engines[engine_id];
110 }
111 
rccConfigCheckEnginePointer(rcc_language_config config,rcc_engine_id engine_id)112 rcc_engine_ptr rccConfigCheckEnginePointer(rcc_language_config config, rcc_engine_id engine_id) {
113     rcc_engine_ptr engine;
114 
115     engine = rccConfigGetEnginePointer(config, engine_id);
116     if ((engine)||(engine->func)) return engine;
117     return NULL;
118 }
119 
rccConfigGetCurrentEnginePointer(rcc_language_config config)120 rcc_engine_ptr rccConfigGetCurrentEnginePointer(rcc_language_config config) {
121     rcc_engine_id engine_id;
122 
123     engine_id = rccConfigGetCurrentEngine(config);
124     if (engine_id == (rcc_engine_id)-1) return NULL;
125 
126     return rccConfigGetEnginePointer(config, engine_id);
127 }
128 
rccConfigCheckCurrentEnginePointer(rcc_language_config config)129 rcc_engine_ptr rccConfigCheckCurrentEnginePointer(rcc_language_config config) {
130     rcc_engine_ptr engine;
131 
132     engine = rccConfigGetCurrentEnginePointer(config);
133     if ((engine)||(engine->func)) return engine;
134     return NULL;
135 }
136 
137 
rccConfigGetEngineName(rcc_language_config config,rcc_engine_id engine_id)138 const char *rccConfigGetEngineName(rcc_language_config config, rcc_engine_id engine_id) {
139     rcc_engine_ptr engine;
140 
141     if (!engine_id) return rcc_disabled_engine_sn;
142     if ((!config)||(!config->language)) return NULL;
143 
144     if (engine_id == (rcc_engine_id)-1) return rcc_engine_nonconfigured;
145 
146     engine = rccConfigGetEnginePointer(config, engine_id);
147     if (!engine) return NULL;
148 
149     return engine->title;
150 }
151 
rccConfigGetCharsetName(rcc_language_config config,rcc_charset_id charset_id)152 const char *rccConfigGetCharsetName(rcc_language_config config, rcc_charset_id charset_id) {
153     if (!charset_id) return rcc_default_charset;
154 
155     if ((!config)||(!config->language)) return NULL;
156     if (charset_id>=rccConfigGetCharsetNumber(config)) return NULL;
157 
158     return config->language->charsets[charset_id];
159 }
160 
rccConfigGetClassCharsetName(rcc_language_config config,rcc_class_id class_id,rcc_charset_id charset_id)161 const char *rccConfigGetClassCharsetName(rcc_language_config config, rcc_class_id class_id, rcc_charset_id charset_id) {
162     unsigned int i, pos;
163     rcc_charset *charsets;
164 
165     if (!charset_id) return rcc_default_charset;
166 
167     if ((!config)||(!config->language)) return NULL;
168     if ((class_id<0)||(class_id>=config->ctx->n_classes)) return NULL;
169 
170     pos = rccConfigGetCharsetNumber(config);
171     if (charset_id < pos) return rccConfigGetCharsetName(config, charset_id);
172 
173     charset_id -= pos;
174 
175     charsets = config->ctx->iclass[class_id].additional;
176     if (!charsets) return NULL;
177 
178     for (i=0;charsets[i];i++)
179 	if (rccConfigGetCharsetByName(config, charsets[i]) == (rcc_language_id)-1) {
180 	    if (!charset_id) break;
181 	    charset_id--;
182 	}
183 
184     return charsets[i];
185 }
186 
rccConfigGetAutoCharsetName(rcc_language_config config,rcc_autocharset_id charset_id)187 const char *rccConfigGetAutoCharsetName(rcc_language_config config, rcc_autocharset_id charset_id) {
188     unsigned int i;
189     rcc_engine_id engine_id;
190     rcc_charset *charsets;
191     rcc_engine_ptr *engines;
192 
193     if ((!config)||(!config->language)) return NULL;
194     engine_id = rccConfigGetCurrentEngine(config);
195     if (engine_id == (rcc_engine_id)-1) return NULL;
196 
197     engines = config->language->engines;
198     charsets = engines[engine_id]->charsets;
199 
200     for (i=0;charsets[i];i++);
201     if (charset_id>=i) return NULL;
202 
203     return charsets[charset_id];
204 }
205 
206 
rccConfigGetEngineByName(rcc_language_config config,const char * name)207 rcc_engine_id rccConfigGetEngineByName(rcc_language_config config, const char *name) {
208     unsigned int i;
209     rcc_engine **engines;
210 
211     if ((!config)||(!config->language)||(!name)) return (rcc_engine_id)-1;
212 
213     engines = config->language->engines;
214     for (i=0;engines[i];i++)
215 	if (!strcasecmp(engines[i]->title,name)) return (rcc_engine_id)i;
216 
217     return (rcc_engine_id)-1;
218 }
219 
rccConfigGetCharsetByName(rcc_language_config config,const char * name)220 rcc_charset_id rccConfigGetCharsetByName(rcc_language_config config, const char *name) {
221     unsigned int i;
222     rcc_charset *charsets;
223 
224     if ((!config)||(!config->language)||(!name)) return (rcc_charset_id)-1;
225 
226     charsets = config->language->charsets;
227     for (i=0;charsets[i];i++)
228 	if (!strcasecmp(charsets[i],name)) return (rcc_charset_id)i;
229 
230     return (rcc_charset_id)-1;
231 }
232 
rccConfigGetClassCharsetByName(rcc_language_config config,rcc_class_id class_id,const char * name)233 rcc_charset_id rccConfigGetClassCharsetByName(rcc_language_config config, rcc_class_id class_id, const char *name) {
234     unsigned int pos, i = 0;
235     rcc_charset_id charset_id;
236     rcc_charset *charsets;
237 
238     if ((!config)||(!config->language)||(!name)) return (rcc_charset_id)-1;
239     if ((class_id<0)||(class_id>=config->ctx->n_classes)) return (rcc_charset_id)-1;
240 
241     charset_id = rccConfigGetCharsetByName(config, name);
242     if (charset_id != (rcc_charset_id)-1) return charset_id;
243 
244     pos = rccConfigGetCharsetNumber(config);
245 
246     charsets = config->ctx->iclass[class_id].additional;
247     if (!charsets) return (rcc_charset_id)-1;
248 
249     for (i=0;charsets[i];i++)
250 	if (rccConfigGetCharsetByName(config, charsets[i]) == (rcc_language_id)-1) {
251 	    if (!strcasecmp(charsets[i], name)) return pos;
252 	    pos++;
253 	}
254 
255     return (rcc_charset_id)-1;
256 }
257 
rccConfigGetAutoCharsetByName(rcc_language_config config,const char * name)258 rcc_autocharset_id rccConfigGetAutoCharsetByName(rcc_language_config config, const char *name) {
259     unsigned int i;
260     rcc_engine_id engine_id;
261     rcc_charset *charsets;
262     rcc_engine_ptr *engines;
263 
264     if ((!config)||(!config->language)||(!name)) return (rcc_autocharset_id)-1;
265 
266     engine_id = rccConfigGetCurrentEngine(config);
267     if (engine_id == (rcc_engine_id)-1) return (rcc_autocharset_id)-1;
268 
269     engines = config->language->engines;
270     charsets = engines[engine_id]->charsets;
271 
272     for (i=0;charsets[i];i++)
273 	if (!strcasecmp(charsets[i],name)) return (rcc_autocharset_id)i;
274 
275     return (rcc_autocharset_id)-1;
276 }
277 
rccConfigIsDisabledCharset(rcc_language_config config,rcc_class_id class_id,rcc_charset_id charset_id)278 int rccConfigIsDisabledCharset(rcc_language_config config, rcc_class_id class_id, rcc_charset_id charset_id) {
279     rcc_charset charset;
280 
281     if ((!config)||(!config->language)) return (rcc_autocharset_id)-1;
282 
283     charset = rccConfigGetClassCharsetName(config, class_id, charset_id);
284     if (!charset) return -1;
285 
286     return rccIsDisabledCharsetName(config->ctx, class_id, charset);
287 }
288 
rccConfigInit(rcc_language_config config,rcc_context ctx)289 int rccConfigInit(rcc_language_config config, rcc_context ctx) {
290     int err;
291     unsigned int i;
292     rcc_charset_id *charsets;
293     rcc_charset_id *dcharsets;
294     rcc_iconv *iconv_to;
295     rcc_mutex mutex;
296 
297     if ((!ctx)||(!config)) return -1;
298 
299     charsets = (rcc_charset_id*)malloc((ctx->max_classes)*sizeof(rcc_charset_id));
300     dcharsets = (rcc_charset_id*)malloc((ctx->max_classes)*sizeof(rcc_charset_id));
301     iconv_to = (rcc_iconv*)malloc((ctx->max_classes)*sizeof(rcc_iconv));
302     mutex = rccMutexCreate();
303     if ((!charsets)||(!dcharsets)||(!iconv_to)||(!mutex)) {
304 	if (mutex) rccMutexFree(mutex);
305 	if (dcharsets) free(dcharsets);
306 	if (charsets) free(charsets);
307 	if (iconv_to) free(iconv_to);
308 	return -1;
309     }
310 
311     err = rccEngineInitContext(&config->engine_ctx, config);
312     if (err) {
313 	if (mutex) rccMutexFree(mutex);
314 	if (dcharsets) free(dcharsets);
315 	if (charsets) free(charsets);
316 	if (iconv_to) free(iconv_to);
317 	return -1;
318     }
319 
320     for (i=0;i<ctx->max_classes;i++) {
321 	dcharsets[i] = 0;
322     	charsets[i] = 0;
323 	iconv_to[i] = NULL;
324     }
325 
326     config->fsiconv = NULL;
327     config->trans = NULL;
328     config->entrans = NULL;
329 
330     config->ctx = ctx;
331     config->language = NULL;
332     config->charset = charsets;
333     config->engine = -1;
334     config->default_charset = dcharsets;
335     config->configured = 0;
336     config->speller = NULL;
337     config->mutex = mutex;
338 
339     config->iconv_to = iconv_to;
340     config->configure = 1;
341 
342     return 0;
343 }
344 
rccConfigFreeIConv(rcc_language_config config)345 void rccConfigFreeIConv(rcc_language_config config) {
346     unsigned int i;
347 
348     if ((!config)||(!config->charset)) return;
349 
350     if (config->fsiconv) {
351 	rccIConvClose(config->fsiconv);
352 	config->fsiconv = NULL;
353     }
354 
355     for (i=0;i<config->ctx->n_classes;i++) {
356 	if (config->iconv_to[i]) {
357 	    rccIConvClose(config->iconv_to[i]);
358 	    config->iconv_to[i] = NULL;
359 	}
360     }
361 }
362 
rccConfigClear(rcc_language_config config)363 void rccConfigClear(rcc_language_config config) {
364     if ((config)&&(config->charset)) {
365 	rccEngineFreeContext(&config->engine_ctx);
366 	rccConfigFreeIConv(config);
367 	if (config->trans) {
368 	    rccTranslateClose(config->trans);
369 	    config->trans = NULL;
370 	}
371 	if (config->entrans) {
372 	    rccTranslateClose(config->entrans);
373 	    config->entrans = NULL;
374 	}
375 	if (config->iconv_to) {
376 	    free(config->iconv_to);
377 	    config->iconv_to = NULL;
378 	}
379 	if (config->charset) {
380 	    free(config->charset);
381 	    config->charset = NULL;
382         }
383 	if (config->default_charset) {
384 	    free(config->default_charset);
385 	    config->default_charset = NULL;
386 	}
387 	if (config->speller) {
388 	    rccSpellerFree(config->speller);
389 	    config->speller = NULL;
390 	}
391 	if (config->mutex) {
392 	    rccMutexFree(config->mutex);
393 	    config->mutex = NULL;
394 	}
395     }
396 }
397 
rccGetConfigPointer(rcc_context ctx,rcc_language_id language_id,rcc_language_id * r_language_id)398 static rcc_language_config rccGetConfigPointer(rcc_context ctx, rcc_language_id language_id, rcc_language_id *r_language_id) {
399 
400     language_id = rccGetRealLanguage(ctx, language_id);
401     if (!strcasecmp(ctx->languages[language_id]->sn, rcc_disabled_language_sn)) return NULL;
402     if (r_language_id) *r_language_id = language_id;
403 
404     return ctx->configs + language_id;
405 }
406 
rccCheckConfig(rcc_context ctx,rcc_language_id language_id)407 rcc_language_config rccCheckConfig(rcc_context ctx, rcc_language_id language_id) {
408     rcc_language_config config;
409 
410     config = rccGetConfigPointer(ctx, language_id, NULL);
411     if ((config)&&(!config->charset)) return NULL;
412 
413     return config;
414 }
415 
416 
rccGetUsableConfig(rcc_context ctx,rcc_language_id language_id)417 rcc_language_config rccGetUsableConfig(rcc_context ctx, rcc_language_id language_id) {
418     rcc_language_config config;
419 
420     config = rccGetConfigPointer(ctx, language_id, &language_id);
421     if (config) {
422 	if (!rccCheckLanguageUsability(ctx, language_id)) return NULL;
423 	if ((!config->charset)&&(rccConfigInit(config, ctx))) return NULL;
424 	config->language = ctx->languages[language_id];
425     }
426 
427     return config;
428 }
429 
rccGetConfig(rcc_context ctx,rcc_language_id language_id)430 rcc_language_config rccGetConfig(rcc_context ctx, rcc_language_id language_id) {
431     rcc_language_config config;
432 
433     config = rccGetConfigPointer(ctx, language_id, &language_id);
434     if (config) {
435 	if ((!config->charset)&&(rccConfigInit(config, ctx))) return NULL;
436 	config->language = ctx->languages[language_id];
437     }
438 
439     return config;
440 }
441 
rccGetConfigByName(rcc_context ctx,const char * name)442 rcc_language_config rccGetConfigByName(rcc_context ctx, const char *name) {
443     rcc_language_id language_id;
444 
445     language_id = rccGetLanguageByName(ctx, name);
446     if (language_id == (rcc_language_id)-1) return NULL;
447 
448     return rccGetConfig(ctx, language_id);
449 }
450 
rccGetCurrentConfig(rcc_context ctx)451 rcc_language_config rccGetCurrentConfig(rcc_context ctx) {
452     rcc_language_id language_id;
453 
454     language_id = rccGetCurrentLanguage(ctx);
455     if (language_id == (rcc_language_id)-1) return NULL;
456 
457     return rccGetConfig(ctx, language_id);
458 }
459 
rccConfigGetSpeller(rcc_language_config config)460 rcc_speller rccConfigGetSpeller(rcc_language_config config) {
461     unsigned int i;
462     rcc_speller speller;
463     rcc_language_config pconfig;
464     rcc_language_id *parents;
465     rcc_language_id language_id;
466     if (!config) return NULL;
467 
468     rccMutexLock(config->mutex);
469     if (!config->speller) {
470 	config->speller = rccSpellerCreate(config->language->sn);
471 
472 	if (config->speller) language_id = rccConfigGetLanguage(config);
473 	else language_id = (rcc_language_id)-1;
474 	if (language_id != (rcc_language_id)-1) parents = ((rcc_language_internal*)config->language)->parents;
475 	else parents = NULL;
476 
477 	if (parents) {
478 	    for (i = 0; parents[i]!=(rcc_language_id)-1; i++) {
479 		pconfig = rccGetConfig(config->ctx, parents[i]);
480 		if (pconfig) {
481 		    speller = rccConfigGetSpeller(pconfig);
482 		    rccSpellerAddParrent(config->speller, speller);
483 		}
484 	    }
485 	}
486     }
487     rccMutexUnLock(config->mutex);
488 
489     return config->speller;
490 }
491 
rccConfigGetTranslator(rcc_language_config config,rcc_language_id to)492 rcc_translate rccConfigGetTranslator(rcc_language_config config, rcc_language_id to) {
493     rcc_option_value timeout;
494     rcc_option_value offline;
495 
496     if (!config) return NULL;
497 
498     rccMutexLock(config->mutex);
499     if ((config->trans)&&(config->translang != to)) {
500 	rccTranslateClose(config->trans);
501 	config->trans = NULL;
502     }
503 
504     if (!config->trans) {
505 	config->trans = rccTranslateOpen(config->language->sn, rccGetLanguageName(config->ctx, to));
506 	if (config->trans) {
507 	    config->translang = to;
508 	    timeout = rccGetOption(config->ctx, RCC_OPTION_TIMEOUT);
509 	    if (timeout) rccTranslateSetTimeout(config->trans, timeout);
510 
511 	    offline = rccGetOption(config->ctx, RCC_OPTION_OFFLINE);
512 	    if (offline) rccTranslateAllowOfflineMode(config->trans);
513 	}
514     }
515     rccMutexUnLock(config->mutex);
516 
517     return config->trans;
518 }
519 
rccConfigGetEnglishTranslator(rcc_language_config config)520 rcc_translate rccConfigGetEnglishTranslator(rcc_language_config config) {
521     rcc_option_value timeout;
522 
523     if (!config) return NULL;
524 
525     rccMutexLock(config->mutex);
526     if (!config->entrans) {
527 	config->entrans = rccTranslateOpen(config->language->sn, rcc_english_language_sn);
528 	if (config->entrans) {
529 	    timeout = rccGetOption(config->ctx, RCC_OPTION_TIMEOUT);
530 	    if (timeout) rccTranslateSetTimeout(config->entrans, timeout);
531 	}
532     }
533     rccMutexUnLock(config->mutex);
534 
535     return config->entrans;
536 }
537 
rccConfigGetSelectedEngine(rcc_language_config config)538 rcc_engine_id rccConfigGetSelectedEngine(rcc_language_config config) {
539     if (!config) return (rcc_engine_id)-1;
540 
541     return config->engine;
542 }
543 
rccConfigGetSelectedEngineName(rcc_language_config config)544 const char *rccConfigGetSelectedEngineName(rcc_language_config config) {
545     rcc_engine_id engine_id;
546 
547     engine_id = rccConfigGetSelectedEngine(config);
548     if (engine_id == (rcc_engine_id)-1) return rcc_engine_nonconfigured;
549     if (!config->language) return NULL;
550 
551     return rccConfigGetEngineName(config, engine_id);
552 }
553 
rccConfigGetCurrentEngine(rcc_language_config config)554 rcc_engine_id rccConfigGetCurrentEngine(rcc_language_config config) {
555     rcc_engine **enginelist;
556     rcc_engine_id engine_id;
557 
558     if (!config) return (rcc_engine_id)-1;
559 
560     engine_id = rccConfigGetSelectedEngine(config);
561     if (engine_id != (rcc_engine_id)-1) return engine_id;
562 
563     if (!config->language) return (rcc_engine_id)-1;
564     else enginelist = config->language->engines;
565 
566     if (enginelist[0]) {
567 	if (enginelist[1]) return (rcc_engine_id)1;
568 	return (rcc_engine_id)0;
569     }
570     return (rcc_engine_id)-1;
571 }
572 
rccConfigGetCurrentEngineName(rcc_language_config config)573 const char *rccConfigGetCurrentEngineName(rcc_language_config config) {
574     rcc_engine_id engine_id;
575 
576     engine_id = rccConfigGetCurrentEngine(config);
577     if ((engine_id == (rcc_engine_id)-1)||(!config->language)) return NULL;
578 
579     return rccConfigGetEngineName(config, engine_id);
580 }
581 
rccConfigGetSelectedCharset(rcc_language_config config,rcc_class_id class_id)582 rcc_charset_id rccConfigGetSelectedCharset(rcc_language_config config, rcc_class_id class_id) {
583     if ((!config)||(!config->ctx)||(class_id<0)||(class_id>=config->ctx->n_classes)) return (rcc_charset_id)-1;
584 
585     return config->charset[class_id];
586 }
587 
rccConfigGetSelectedCharsetName(rcc_language_config config,rcc_class_id class_id)588 const char *rccConfigGetSelectedCharsetName(rcc_language_config config, rcc_class_id class_id) {
589     rcc_charset_id charset_id;
590 
591     charset_id = rccConfigGetSelectedCharset(config, class_id);
592     if ((charset_id == (rcc_charset_id)-1)||(!config->language)) return NULL;
593 
594     return rccConfigGetClassCharsetName(config, class_id, charset_id);
595 }
596 
rccConfigGetCurrentCharset(rcc_language_config config,rcc_class_id class_id)597 rcc_charset_id rccConfigGetCurrentCharset(rcc_language_config config, rcc_class_id class_id) {
598     rcc_language_config enconfig;
599     unsigned int i, max;
600     rcc_charset_id charset_id;
601     rcc_charset_id all_charset_id = (rcc_language_id)-1;
602     const char *charset;
603 
604     rcc_class_default_charset *defcharset;
605     const char *lang;
606 
607 //    rcc_language *language;
608     rcc_class_ptr *classes;
609 
610     rcc_class *cl;
611 
612     const char *defvalue;
613 
614     if ((!config)||(!config->ctx)||(class_id<0)||(class_id>=config->ctx->n_classes)) return -1;
615 
616     charset_id = config->charset[class_id];
617     if (charset_id) return charset_id;
618 
619     enconfig = rccGetConfigByName(config->ctx, rcc_english_language_sn);
620     if ((enconfig)&&(enconfig!=config)) {
621 	charset_id = enconfig->charset[class_id];
622 	if (charset_id) {
623 	    charset = rccConfigGetClassCharsetName(enconfig, class_id, charset_id);
624 	    if ((charset)&&(rccIsUnicode(charset))) return charset_id;
625 	}
626     }
627 
628     if (!config->language) return (rcc_charset_id)-1;
629 //    else language = config->language;
630 
631     classes = config->ctx->classes;
632 
633     cl = classes[class_id];
634     defvalue = cl->defvalue;
635     if (defvalue) {
636 	for (i=0;classes[i];i++) {
637 	    if (!strcmp(classes[i]->name, defvalue))
638 		return rccConfigGetCurrentCharset(config, i);
639 	}
640     }
641 
642     if (config->default_charset[class_id]) return config->default_charset[class_id];
643 
644     if (cl->defvalue) {
645 	charset_id = rccConfigGetLocaleClassCharset(config, class_id, defvalue);
646 	if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) {
647 	    if (!rccConfigIsDisabledCharset(config, class_id, charset_id)) {
648 		config->default_charset[class_id] = charset_id;
649 		return charset_id;
650 	    }
651 	}
652     }
653 
654     if (cl->defvalue) {
655 	charset_id = rccConfigGetClassCharsetByName(config, class_id, defvalue);
656 	if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) {
657 	    if (!rccConfigIsDisabledCharset(config, class_id, charset_id)) {
658 		config->default_charset[class_id] = charset_id;
659 		return charset_id;
660 	    }
661 	}
662     }
663 
664     defcharset = cl->defcharset;
665     if (defcharset) {
666 	    lang = config->language->sn;
667 
668 	    for (i = 0; cl->defcharset[i].lang; i++) {
669 		if (!strcasecmp(lang, defcharset[i].lang)) {
670 		    charset_id = rccConfigGetClassCharsetByName(config, class_id, defcharset[i].charset);
671 		    if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) {
672 			if (!rccConfigIsDisabledCharset(config, class_id, charset_id)) {
673 			    config->default_charset[class_id] = charset_id;
674 			    return charset_id;
675 			} else {
676 			    all_charset_id = (rcc_charset_id)-1;
677 			    break;
678 			}
679 		    } else {
680 			all_charset_id = (rcc_charset_id)-1;
681 			break;
682 		    }
683 		} else if (!strcasecmp(rcc_default_all, defcharset[i].lang)) {
684 		    charset_id = rccConfigGetClassCharsetByName(config, class_id, defcharset[i].charset);
685 		    if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) {
686 			all_charset_id = charset_id;
687 		    }
688 		}
689 	    }
690 
691 	    if (all_charset_id != (rcc_language_id)-1) {
692 		if (!rccConfigIsDisabledCharset(config, class_id, all_charset_id)) {
693 		    config->default_charset[class_id] = all_charset_id;
694 		    return all_charset_id;
695 		}
696 	    }
697     }
698 
699     charset_id = rccConfigGetLocaleClassCharset(config, class_id, config->ctx->locale_variable);
700     if ((charset_id != 0)&&(charset_id != (rcc_charset_id)-1)) {
701 	if (!rccConfigIsDisabledCharset(config, class_id, charset_id)) {
702 	    config->default_charset[class_id] = charset_id;
703 	    return charset_id;
704 	}
705     }
706 
707     max = rccConfigGetClassCharsetNumber(config, class_id);
708     for (i = 1; i< max; i++)
709 	if (!rccConfigIsDisabledCharset(config, class_id, (rcc_charset_id)i)) {
710 	    return (rcc_charset_id)i;
711 	}
712 
713     return (rcc_charset_id)-1;
714 }
715 
rccConfigGetCurrentCharsetName(rcc_language_config config,rcc_class_id class_id)716 const char *rccConfigGetCurrentCharsetName(rcc_language_config config, rcc_class_id class_id) {
717     rcc_charset_id charset_id;
718 
719     charset_id = rccConfigGetCurrentCharset(config, class_id);
720     if ((charset_id == (rcc_charset_id)-1)||(!config->language)) return NULL;
721 
722     return rccConfigGetClassCharsetName(config, class_id, charset_id);
723 }
724 
725 
rccConfigSetEngine(rcc_language_config config,rcc_engine_id engine_id)726 int rccConfigSetEngine(rcc_language_config config, rcc_engine_id engine_id) {
727     unsigned int i;
728 
729     if ((!config)||(!config->language)) return -1;
730 
731     if (engine_id != (rcc_engine_id)-1) {
732 	for (i=0;config->language->engines[i];i++);
733 	if (engine_id >= i) return -1;
734     }
735 
736     if (config->engine != engine_id) {
737 	rccMutexLock(config->mutex);
738 	if (config->ctx->current_config == config) config->ctx->configure = 1;
739 	config->configure = 1;
740 	config->engine = engine_id;
741 	rccMutexUnLock(config->mutex);
742     }
743 
744     config->configured = 1;
745 
746     return 0;
747 }
748 
rccConfigSetEngineByName(rcc_language_config config,const char * name)749 int rccConfigSetEngineByName(rcc_language_config config, const char *name) {
750     rcc_engine_id engine_id;
751 
752     if (!config) return -1;
753 
754     if ((!name)||(!strcasecmp(name,rcc_engine_nonconfigured)))
755 	return rccConfigSetEngine(config, (rcc_engine_id)-1);
756 
757     engine_id = rccConfigGetEngineByName(config, name);
758     if (engine_id == (rcc_engine_id)-1) return -1;
759 
760     return rccConfigSetEngine(config, engine_id);
761 }
762 
rccConfigSetCharset(rcc_language_config config,rcc_class_id class_id,rcc_charset_id charset_id)763 int rccConfigSetCharset(rcc_language_config config, rcc_class_id class_id, rcc_charset_id charset_id) {
764     if ((!config)||(!config->language)||(class_id < 0)||(class_id >= config->ctx->n_classes)) return -1;
765 
766     if (charset_id >= rccConfigGetClassCharsetNumber(config, class_id)) return -1;
767     if (rccConfigIsDisabledCharset(config, class_id, charset_id)) return -1;
768 
769     if (config->charset[class_id] != charset_id) {
770 	if (config->ctx->classes[class_id]->flags&RCC_CLASS_FLAG_CONST) return -1;
771 
772 	rccMutexLock(config->mutex);
773 	if (config->ctx->current_config == config) config->ctx->configure = 1;
774 	config->configure = 1;
775 	config->charset[class_id] = charset_id;
776 	rccMutexUnLock(config->mutex);
777     }
778 
779     config->configured = 1;
780 
781     return 0;
782 }
783 
rccConfigSetCharsetByName(rcc_language_config config,rcc_class_id class_id,const char * name)784 int rccConfigSetCharsetByName(rcc_language_config config, rcc_class_id class_id, const char *name) {
785     rcc_charset_id charset_id;
786 
787     charset_id = rccConfigGetClassCharsetByName(config, class_id, name);
788     if (charset_id == (rcc_charset_id)-1) return -1;
789 
790     return rccConfigSetCharset(config, class_id, charset_id);
791 }
792 
rccConfigGetLocaleCharset(rcc_language_config config,const char * locale_variable)793 rcc_charset_id rccConfigGetLocaleCharset(rcc_language_config config, const char *locale_variable) {
794     const char *lv;
795     rcc_language_id language_id;
796     char lang[RCC_MAX_CHARSET_CHARS+1];
797     char stmp[RCC_MAX_CHARSET_CHARS+1];
798 
799     if ((!config)||(!config->language)) return (rcc_charset_id)-1;
800 
801     lv = locale_variable?locale_variable:config->ctx->locale_variable;
802 
803     language_id = rccGetLanguageByName(config->ctx, config->language->sn);
804     if (language_id != (rcc_language_id)-1) {
805 	if (!rccLocaleGetCharset(stmp, lv, RCC_MAX_CHARSET_CHARS)) {
806 	    if (rccIsUnicode(stmp))
807 		return rccConfigGetCharsetByName(config, stmp);
808 	    if ((!rccLocaleGetLanguage(lang, lv, RCC_MAX_CHARSET_CHARS))&&(!strcmp(config->language->sn, lang)))
809 		return rccConfigGetCharsetByName(config, stmp);
810 	}
811     }
812 
813     return (rcc_charset_id)-1;
814 }
815 
rccConfigGetLocaleClassCharset(rcc_language_config config,rcc_class_id class_id,const char * locale_variable)816 rcc_charset_id rccConfigGetLocaleClassCharset(rcc_language_config config, rcc_class_id class_id, const char *locale_variable) {
817     const char *lv;
818     rcc_language_id language_id;
819     char lang[RCC_MAX_CHARSET_CHARS+1];
820     char stmp[RCC_MAX_CHARSET_CHARS+1];
821 
822     if ((!config)||(!config->language)) return (rcc_charset_id)-1;
823 
824     lv = locale_variable?locale_variable:config->ctx->locale_variable;
825 
826     language_id = rccGetLanguageByName(config->ctx, config->language->sn);
827     if (language_id != (rcc_language_id)-1) {
828 	if (!rccLocaleGetCharset(stmp, lv, RCC_MAX_CHARSET_CHARS)) {
829 	    if (rccIsUnicode(stmp))
830 		return rccConfigGetClassCharsetByName(config, class_id, stmp);
831 	    if ((!rccLocaleGetLanguage(lang, lv, RCC_MAX_CHARSET_CHARS))&&(!strcmp(config->language->sn, lang)))
832 		return rccConfigGetClassCharsetByName(config, class_id, stmp);
833 	}
834     }
835 
836     return (rcc_charset_id)-1;
837 }
838 
839 
rccConfigConfigure(rcc_language_config config)840 int rccConfigConfigure(rcc_language_config config) {
841     int err;
842     rcc_context ctx;
843     const char *charset;
844     unsigned int i;
845 
846     if (!config) return -1;
847     if (!config->configure) return 0;
848 
849     rccMutexLock(config->mutex);
850 
851     ctx = config->ctx;
852 
853     rccConfigFreeIConv(config);
854     for (i=0;i<ctx->n_classes;i++) {
855 	charset = rccConfigGetCurrentCharsetName(config, (rcc_class_id)i);
856 	if ((!charset)||(rccIsUTF8(charset))) continue;
857 	config->iconv_to[i] = rccIConvOpen(charset, "UTF-8");
858     }
859 
860     err = rccEngineConfigure(&config->engine_ctx);
861     if (!err) config->configure = 0;
862 
863     rccMutexUnLock(config->mutex);
864 
865 
866     return err;
867 }
868 
869 
870 /*
871     rcc_option_value options[RCC_MAX_OPTIONS];
872 
873 int rccConfigInit(rcc_language_config config, rcc_context ctx) {
874     for (i=0;i<RCC_MAX_OPTIONS;i++)
875 	config->options[i] = 0;
876 }
877 
878 rcc_option_value rccConfigGetOption(rcc_language_config config, rcc_option option) {
879     if ((!config)||(option<0)||(option>=RCC_MAX_OPTIONS)) return -1;
880 
881     return config->options[option];
882 }
883 
884 int rccConfigSetOption(rcc_language_config config, rcc_option option, rcc_option_value value) {
885     if ((!config)||(option>=RCC_MAX_OPTIONS)) return -1;
886     if (config->options[option] != value) {
887 	if (config->ctx->current_config == config) config->ctx->configure = 1;
888 	config->options[option]=value;
889     }
890 
891     return 0;
892 }
893 
894 rcc_option_value rccConfigGetOption(rcc_language_config config, rcc_option option);
895 int rccConfigSetOption(rcc_language_config config, rcc_option option, rcc_option_value value);
896 #define rccGetOption(ctx, option) rccConfigGetOption(ctx->current_config, option)
897 #define rccSetOption(ctx,option,value) rccConfigSetOption(ctx->current_config, option, value)
898 */
899