1/*
2 * Copyright 1992, 1993 by TOSHIBA Corp.
3 *
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of TOSHIBA not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission. TOSHIBA make no representations about the
11 * suitability of this software for any purpose.  It is provided "as is"
12 * without express or implied warranty.
13 *
14 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 * SOFTWARE.
21 *
22 * Author: Katsuhisa Yano	TOSHIBA Corp.
23 *			   	mopi@osa.ilab.toshiba.co.jp
24 */
25/*
26 *  (c) Copyright 1995 FUJITSU LIMITED
27 *  This is source code modified by FUJITSU LIMITED under the Joint
28 *  Development Agreement for the CDE/Motif PST.
29 */
30
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34#include <stdio.h>
35#include "Xlibint.h"
36#include "XlcGeneric.h"
37#include "reallocarray.h"
38
39static XLCd create (const char *name, XLCdMethods methods);
40static Bool initialize (XLCd lcd);
41static void destroy (XLCd lcd);
42
43static XLCdPublicMethodsRec genericMethods = {
44    { NULL },                   /* use default methods */
45    {
46	NULL,
47	create,
48	initialize,
49	destroy,
50	NULL
51    }
52};
53
54XLCdMethods _XlcGenericMethods = (XLCdMethods) &genericMethods;
55
56static XLCd
57create(
58    const char *name,
59    XLCdMethods methods)
60{
61    XLCd lcd;
62    XLCdPublicMethods new;
63
64    lcd = Xcalloc(1, sizeof(XLCdRec));
65    if (lcd == NULL)
66        return (XLCd) NULL;
67
68    lcd->core = Xcalloc(1, sizeof(XLCdGenericRec));
69    if (lcd->core == NULL)
70	goto err;
71
72    new = Xmalloc(sizeof(XLCdPublicMethodsRec));
73    if (new == NULL)
74	goto err;
75    memcpy(new,methods,sizeof(XLCdPublicMethodsRec));
76    lcd->methods = (XLCdMethods) new;
77
78    return lcd;
79
80err:
81    Xfree(lcd->core);
82    Xfree(lcd);
83    return (XLCd) NULL;
84}
85
86static Bool
87string_to_encoding(
88    const char *str,
89    char *encoding)
90{
91    char *next;
92    long value;
93    int base;
94
95    while (*str) {
96	if (*str == '\\') {
97	    switch (*(str + 1)) {
98		case 'x':
99		case 'X':
100		    base = 16;
101		    break;
102		default:
103		    base = 8;
104		    break;
105	    }
106	    value = strtol(str + 2, &next, base);
107	    if (str + 2 != next) {
108		*((unsigned char *) encoding++) = (unsigned char) value;
109		str = next;
110		continue;
111	    }
112	}
113	*encoding++ = *str++;
114    }
115
116    *encoding = '\0';
117
118    return True;
119}
120
121static Bool
122string_to_ulong(
123    const char *str,
124    unsigned long *value)
125{
126     const char *tmp1 = str;
127     int base;
128
129     if (*tmp1++ != '\\') {
130	  tmp1--;
131	  base = 10;
132     } else {
133	  switch (*tmp1++) {
134	  case 'x':
135	       base = 16;
136	       break;
137	  case 'o':
138	       base = 8;
139	       break;
140	  case 'd':
141	       base = 10;
142	       break;
143	  default:
144	       return(False);
145	  }
146     }
147     *value = (unsigned long) strtol(tmp1, NULL, base);
148     return(True);
149}
150
151
152static Bool
153add_charset(
154    CodeSet codeset,
155    XlcCharSet charset)
156{
157    XlcCharSet *new_list;
158    int num;
159
160    if ((num = codeset->num_charsets))
161        new_list = Xreallocarray(codeset->charset_list,
162                                 num + 1, sizeof(XlcCharSet));
163    else
164        new_list = Xmalloc(sizeof(XlcCharSet));
165
166    if (new_list == NULL)
167	return False;
168
169    new_list[num] = charset;
170    codeset->charset_list = new_list;
171    codeset->num_charsets = num + 1;
172
173    return True;
174}
175
176static CodeSet
177add_codeset(
178    XLCdGenericPart *gen)
179{
180    CodeSet new, *new_list;
181    int num;
182
183    new = Xcalloc(1, sizeof(CodeSetRec));
184    if (new == NULL)
185        return NULL;
186
187    if ((num = gen->codeset_num))
188        new_list = Xreallocarray(gen->codeset_list,
189                                 num + 1, sizeof(CodeSet));
190    else
191        new_list = Xmalloc(sizeof(CodeSet));
192
193    if (new_list == NULL)
194        goto err;
195
196    new_list[num] = new;
197    gen->codeset_list = new_list;
198    gen->codeset_num = num + 1;
199
200    return new;
201
202err:
203    Xfree(new);
204
205    return NULL;
206}
207
208static Bool
209add_parse_list(
210    XLCdGenericPart *gen,
211    EncodingType type,
212    const char *encoding,
213    CodeSet codeset)
214{
215    ParseInfo new, *new_list;
216    char *str;
217    unsigned char ch;
218    int num;
219
220    str = strdup(encoding);
221    if (str == NULL)
222        return False;
223
224    new = Xcalloc(1, sizeof(ParseInfoRec));
225    if (new == NULL)
226        goto err;
227
228    if (gen->mb_parse_table == NULL) {
229        gen->mb_parse_table = Xcalloc(1, 256); /* 2^8 */
230        if (gen->mb_parse_table == NULL)
231            goto err;
232    }
233
234    if ((num = gen->mb_parse_list_num))
235        new_list = Xreallocarray(gen->mb_parse_list,
236                                 num + 2, sizeof(ParseInfo));
237    else {
238        new_list = Xmalloc(2 * sizeof(ParseInfo));
239    }
240
241    if (new_list == NULL)
242        goto err;
243
244    new_list[num] = new;
245    new_list[num + 1] = NULL;
246    gen->mb_parse_list = new_list;
247    gen->mb_parse_list_num = num + 1;
248
249    ch = (unsigned char) *str;
250    if (gen->mb_parse_table[ch] == 0)
251        gen->mb_parse_table[ch] = num + 1;
252
253    new->type = type;
254    new->encoding = str;
255    new->codeset = codeset;
256
257    if (codeset->parse_info == NULL)
258        codeset->parse_info = new;
259
260    return True;
261
262err:
263    Xfree(str);
264
265    Xfree(new);
266
267    return False;
268}
269
270static void
271free_charset(
272    XLCd lcd)
273{
274    XLCdGenericPart *gen = XLC_GENERIC_PART(lcd);
275    ParseInfo *parse_info;
276    int num;
277
278    Xfree(gen->mb_parse_table);
279    gen->mb_parse_table = NULL;
280    if ((num = gen->mb_parse_list_num) > 0) {
281        for (parse_info = gen->mb_parse_list; num-- > 0; parse_info++) {
282            Xfree((*parse_info)->encoding);
283            Xfree(*parse_info);
284        }
285        Xfree(gen->mb_parse_list);
286        gen->mb_parse_list = NULL;
287        gen->mb_parse_list_num = 0;
288    }
289
290    if ((num = gen->codeset_num) > 0) {
291        Xfree(gen->codeset_list);
292        gen->codeset_list = NULL;
293        gen->codeset_num = 0;
294    }
295}
296
297/* For VW/UDC */
298
299#define FORWARD  (unsigned long)'+'
300#define BACKWARD (unsigned long)'-'
301
302static const char *
303getscope(
304    const char *str,
305    FontScope scp)
306{
307    unsigned long start = 0;
308    unsigned long end = 0;
309    unsigned long dest = 0;
310    unsigned long shift = 0;
311    unsigned long direction = 0;
312    sscanf(str,"[\\x%lx,\\x%lx]->\\x%lx", &start, &end, &dest);
313    if (dest) {
314        if (dest >= start) {
315            shift = dest - start;
316            direction = FORWARD ;
317        } else {
318            shift = start - dest;
319            direction = BACKWARD;
320        }
321    }
322    scp->start = start      ;
323    scp->end   = end        ;
324    scp->shift = shift      ;
325    scp->shift_direction
326               = direction  ;
327    /* .......... */
328    while (*str) {
329        if (*str == ',' && *(str+1) == '[')
330            break;
331        str++;
332    }
333    return str+1;
334}
335
336static int
337count_scopemap(
338    const char *str)
339{
340    const char *ptr;
341    int num=0;
342    for (ptr=str; *ptr; ptr++) {
343        if (*ptr == ']') {
344            num++;
345        }
346    }
347    return num;
348}
349
350FontScope
351_XlcParse_scopemaps(
352    const char *str,
353    int *size)
354{
355    int num=0,i;
356    FontScope scope,sc_ptr;
357    const char *str_sc;
358
359    num = count_scopemap(str);
360    scope = Xmallocarray(num, sizeof(FontScopeRec));
361    if (scope == NULL)
362	return NULL;
363
364    for (i=0, str_sc=str, sc_ptr=scope; i < num; i++, sc_ptr++) {
365	str_sc = getscope(str_sc, sc_ptr);
366    }
367    *size = num;
368    return scope;
369}
370
371void
372_XlcDbg_printValue(
373    const char *str,
374    char **value,
375    int num)
376{
377/*
378    int i;
379    for (i = 0; i < num; i++)
380        fprintf(stderr, "%s value[%d] = %s\n", str, i, value[i]);
381*/
382}
383
384static void
385dmpscope(
386    const char* name,
387    FontScope sc,
388    int num)
389{
390/*
391    int i;
392    fprintf(stderr, "dmpscope %s\n", name);
393    for (i=0; i<num; i++)
394        fprintf(stderr,"%x %x %x %x \n",
395                sc[i].start,
396                sc[i].end,
397                sc[i].shift,
398                sc[i].shift_direction);
399    fprintf(stderr, "dmpscope end\n");
400*/
401}
402
403static XlcCharSet
404srch_charset_define(
405    const char *name,
406    int *new)
407{
408    XlcCharSet charset;
409
410    *new = 0;
411    charset = _XlcGetCharSet(name);
412    if (charset == NULL &&
413        (charset = _XlcCreateDefaultCharSet(name, ""))) {
414        _XlcAddCharSet(charset);
415        *new = 1;
416        charset->source = CSsrcXLC;
417    }
418    return charset;
419}
420
421static void
422read_charset_define(
423    XLCd lcd,
424    XLCdGenericPart *gen)
425{
426    int i;
427    char csd[16], cset_name[256];
428    char name[BUFSIZ];
429    XlcCharSet charsetd;
430    char **value;
431    int num, new = 0;
432    XlcSide side = XlcUnknown;
433    char *tmp;
434
435    for (i=0; ; i++) { /* loop start */
436        charsetd = 0;
437        snprintf(csd, sizeof(csd), "csd%d", i);
438
439        /* charset_name  */
440        snprintf(name, sizeof(name), "%s.%s", csd, "charset_name");
441        _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
442        _XlcDbg_printValue(name,value,num);
443        if (num > 0) {
444	    /* hackers will get truncated -- C'est la vie */
445            strncpy(cset_name,value[0], sizeof cset_name - 1);
446	    cset_name[(sizeof cset_name) - 1] = '\0';
447            snprintf(name, sizeof(name), "%s.%s", csd , "side");
448            _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
449            if (num > 0) {
450                _XlcDbg_printValue(name,value,num);
451                if (!_XlcNCompareISOLatin1(value[0], "none", 4)) {
452                    side =  XlcGLGR;
453                } else if (!_XlcNCompareISOLatin1(value[0], "GL", 2)) {
454                    side =  XlcGL;
455                    strcat(cset_name,":GL");
456                } else {
457                    side =  XlcGR;
458                    strcat(cset_name,":GR");
459                }
460                if (charsetd == NULL &&
461                    (charsetd = srch_charset_define(cset_name,&new)) == NULL)
462                    return;
463            }
464        } else {
465            if (i == 0)
466                continue;
467            else
468                break;
469        }
470        if (new) {
471            tmp = strdup(cset_name);
472            if (tmp == NULL)
473                return;
474            charsetd->name = tmp;
475        }
476        /* side   */
477        charsetd->side = side ;
478        /* length */
479        snprintf(name, sizeof(name), "%s.%s", csd, "length");
480        _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
481        if (num > 0) {
482            _XlcDbg_printValue(name,value,num);
483            charsetd->char_size = atoi(value[0]);
484        }
485        /* gc_number */
486        snprintf(name, sizeof(name), "%s.%s", csd, "gc_number");
487        _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
488        if (num > 0) {
489            _XlcDbg_printValue(name,value,num);
490            charsetd->set_size = atoi(value[0]);
491        }
492        /* string_encoding */
493        snprintf(name, sizeof(name), "%s.%s", csd, "string_encoding");
494        _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
495        if (num > 0) {
496            _XlcDbg_printValue(name,value,num);
497            if (!strcmp("False",value[0])) {
498                charsetd->string_encoding = False;
499            } else {
500                charsetd->string_encoding = True;
501            }
502        }
503        /* sequence */
504        snprintf(name, sizeof(name), "%s.%s", csd, "sequence");
505        _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
506        if (num > 0) {
507            _XlcDbg_printValue(name,value,num);
508/*
509            if (charsetd->ct_sequence) {
510                Xfree(charsetd->ct_sequence);
511            }
512*/
513            tmp = Xmalloc(strlen(value[0])+1);
514            if (tmp == NULL)
515                return;
516            charsetd->ct_sequence = tmp;
517            string_to_encoding(value[0],tmp);
518        }
519        /* encoding_name */
520        snprintf(name, sizeof(name), "%s.%s", csd, "encoding_name");
521        _XlcGetResource(lcd, "XLC_CHARSET_DEFINE", name, &value, &num);
522        if (num > 0) {
523            _XlcDbg_printValue(name,value,num);
524/*
525            if (charsetd->encoding_name) {
526                Xfree(charsetd->encoding_name);
527            }
528*/
529            tmp = strdup(value[0]);
530            charsetd->encoding_name = tmp;
531            charsetd->xrm_encoding_name = XrmStringToQuark(tmp);
532        }
533        _XlcAddCT(charsetd->name, charsetd->ct_sequence);
534    }
535}
536
537static SegConv
538add_conversion(
539    XLCdGenericPart *gen)
540{
541    SegConv new_list;
542    int num;
543
544    if ((num = gen->segment_conv_num) > 0) {
545        new_list = Xreallocarray(gen->segment_conv,
546                                 num + 1, sizeof(SegConvRec));
547    } else {
548        new_list = Xmalloc(sizeof(SegConvRec));
549    }
550
551    if (new_list == NULL)
552        return NULL;
553
554    gen->segment_conv = new_list;
555    gen->segment_conv_num = num + 1;
556
557    return &new_list[num];
558
559}
560
561static void
562read_segmentconversion(
563    XLCd lcd,
564    XLCdGenericPart *gen)
565{
566    int i;
567    char conv[16];
568    char name[BUFSIZ];
569    char **value;
570    int num,new;
571    SegConv conversion;
572    for (i=0 ; ; i++) { /* loop start */
573        conversion = 0;
574        snprintf(conv, sizeof(conv), "conv%d", i);
575
576        /* length                */
577        snprintf(name, sizeof(name), "%s.%s", conv, "length");
578        _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
579        if (num > 0) {
580            if (conversion == NULL &&
581                (conversion = add_conversion(gen)) == NULL) {
582                return;
583            }
584            _XlcDbg_printValue(name,value,num);
585        } else {
586            if (i == 0)
587                continue;
588            else
589                break;
590        }
591        conversion->length = atoi(value[0]);
592
593        /* source_encoding       */
594        snprintf(name, sizeof(name), "%s.%s", conv, "source_encoding");
595        _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
596        if (num > 0) {
597            char *tmp;
598            _XlcDbg_printValue(name,value,num);
599            tmp = strdup(value[0]);
600            if (tmp == NULL)
601                return;
602            conversion->source_encoding = tmp;
603            conversion->source = srch_charset_define(tmp,&new);
604        }
605        /* destination_encoding  */
606        snprintf(name, sizeof(name), "%s.%s", conv, "destination_encoding");
607        _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
608        if (num > 0) {
609            char *tmp;
610            _XlcDbg_printValue(name,value,num);
611            tmp = strdup(value[0]);
612            if (tmp == NULL)
613                return;
614            conversion->destination_encoding = tmp;
615            conversion->dest = srch_charset_define(tmp,&new);
616        }
617        /* range                 */
618        snprintf(name, sizeof(name), "%s.%s", conv, "range");
619        _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
620        if (num > 0) {
621            _XlcDbg_printValue(name,value,num);
622            sscanf(value[0],"\\x%lx,\\x%lx",
623                   &(conversion->range.start), &(conversion->range.end));
624        }
625        /* conversion            */
626        snprintf(name, sizeof(name), "%s.%s", conv, "conversion");
627        _XlcGetResource(lcd, "XLC_SEGMENTCONVERSION", name, &value, &num);
628        if (num > 0) {
629            _XlcDbg_printValue(name,value,num);
630            conversion->conv =
631                _XlcParse_scopemaps(value[0],&conversion->conv_num);
632        }
633    }  /* loop end */
634}
635
636static ExtdSegment
637create_ctextseg(
638    char **value,
639    int num)
640{
641    ExtdSegment ret;
642    char* ptr;
643    char* cset_name = NULL;
644    size_t cset_len;
645    int i,new;
646    FontScope scope;
647    ret = Xmalloc(sizeof(ExtdSegmentRec));
648    if (ret == NULL)
649        return NULL;
650    ret->name = strdup(value[0]);
651    if (ret->name == NULL) {
652        Xfree (ret);
653        return NULL;
654    }
655    cset_len = strlen(ret->name) + 1;
656    cset_name = Xmalloc (cset_len);
657    if (cset_name == NULL) {
658        Xfree (ret->name);
659        Xfree (ret);
660        return NULL;
661    }
662    if (strchr(value[0],':')) {
663        ptr = strchr(ret->name,':');
664        *ptr = '\0';
665        ptr++;
666        if (!_XlcNCompareISOLatin1(ptr, "GL", 2)) {
667            ret->side =  XlcGL;
668            snprintf(cset_name, cset_len, "%s:%s", ret->name, "GL");
669        } else {
670            ret->side =  XlcGR;
671            snprintf(cset_name, cset_len, "%s:%s", ret->name, "GR");
672        }
673    } else {
674        ret->side =  XlcGLGR;
675        strcpy(cset_name,ret->name);
676    }
677    ret->area = Xmallocarray(num - 1, sizeof(FontScopeRec));
678    if (ret->area == NULL) {
679	Xfree (cset_name);
680	Xfree (ret->name);
681	Xfree (ret);
682        return NULL;
683    }
684    ret->area_num = num - 1;
685    scope = ret->area ;
686    for (i = 1; i < num; i++) {
687        sscanf(value[i],"\\x%lx,\\x%lx",
688               &scope[i-1].start, &scope[i-1].end);
689    }
690    ret->charset = srch_charset_define(cset_name,&new);
691    Xfree (cset_name);
692
693    return ret;
694}
695/* For VW/UDC end */
696
697static Bool
698load_generic(
699    XLCd lcd)
700{
701    XLCdGenericPart *gen = XLC_GENERIC_PART(lcd);
702    char **value;
703    int num;
704    unsigned long l;
705    int i;
706    int M,ii;
707    XlcCharSet charset;
708
709    gen->codeset_num = 0;
710
711    /***** wc_encoding_mask *****/
712    _XlcGetResource(lcd, "XLC_XLOCALE", "wc_encoding_mask", &value, &num);
713    if (num > 0) {
714	if (string_to_ulong(value[0], &l) == False)
715	    goto err;
716	gen->wc_encode_mask = l;
717    }
718    /***** wc_shift_bits *****/
719    _XlcGetResource(lcd, "XLC_XLOCALE", "wc_shift_bits", &value, &num);
720    if (num > 0)
721	gen->wc_shift_bits = atoi(value[0]);
722    if (gen->wc_shift_bits < 1)
723	gen->wc_shift_bits = 8;
724    /***** use_stdc_env *****/
725    _XlcGetResource(lcd, "XLC_XLOCALE", "use_stdc_env", &value, &num);
726    if (num > 0 && !_XlcCompareISOLatin1(value[0], "True"))
727	gen->use_stdc_env = True;
728    else
729	gen->use_stdc_env = False;
730    /***** force_convert_to_mb *****/
731    _XlcGetResource(lcd, "XLC_XLOCALE", "force_convert_to_mb", &value, &num);
732    if (num > 0 && !_XlcCompareISOLatin1(value[0], "True"))
733	gen->force_convert_to_mb = True;
734    else
735	gen->force_convert_to_mb = False;
736
737    for (i = 0; ; i++) {
738	CodeSetRec *codeset = NULL;
739	char cs[16];
740	char name[BUFSIZ];
741
742	snprintf(cs, sizeof(cs), "cs%d", i);
743
744	/***** codeset.side *****/
745	snprintf(name, sizeof(name), "%s.%s", cs , "side");
746	_XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
747	if (num > 0) {
748	    char *tmp;
749
750	    if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
751		goto err;
752
753            /* 3.4.1 side */
754            if (!_XlcNCompareISOLatin1(value[0], "none", 4)) {
755                codeset->side =  XlcNONE;
756            } else if (!_XlcNCompareISOLatin1(value[0], "GL", 2)) {
757                codeset->side =  XlcGL;
758            } else {
759                codeset->side =  XlcGR;
760            }
761
762	    tmp = strrchr(value[0], ':');
763	    if (tmp != NULL && !_XlcCompareISOLatin1(tmp + 1, "Default")) {
764		if (codeset->side == XlcGR)
765		    gen->initial_state_GR = codeset;
766		else
767		    gen->initial_state_GL = codeset;
768	    }
769	}
770
771	/***** codeset.length *****/
772	snprintf(name, sizeof(name), "%s.%s", cs , "length");
773	_XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
774	if (num > 0) {
775	    if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
776		goto err;
777	    codeset->length = atoi(value[0]);
778	    if (codeset->length < 1)
779		codeset->length = 1;
780	}
781
782	/***** codeset.mb_encoding *****/
783	snprintf(name, sizeof(name), "%s.%s", cs, "mb_encoding");
784	_XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
785	if (num > 0) {
786	    static struct {
787		const char *str;
788		EncodingType type;
789	    } shifts[] = {
790		{"<SS>", E_SS},
791		{"<LSL>", E_LSL},
792		{"<LSR>", E_LSR},
793		{0}
794	    };
795	    int j;
796
797	    if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
798		goto err;
799	    for ( ; num-- > 0; value++) {
800		char encoding[256];
801		char *tmp = *value;
802		EncodingType type = E_SS;    /* for BC */
803		for (j = 0; shifts[j].str; j++) {
804		    if (!_XlcNCompareISOLatin1(tmp, shifts[j].str,
805					       (int) strlen(shifts[j].str))) {
806			type = shifts[j].type;
807			tmp += strlen(shifts[j].str);
808			break;
809		    }
810		}
811		if (strlen (tmp) > sizeof encoding ||
812		    string_to_encoding(tmp, encoding) == False)
813			goto err;
814		add_parse_list(gen, type, encoding, codeset);
815	    }
816	}
817
818	/***** codeset.wc_encoding *****/
819	snprintf(name, sizeof(name), "%s.%s", cs, "wc_encoding");
820	_XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
821	if (num > 0) {
822	    if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
823		goto err;
824	    if (string_to_ulong(value[0], &l) == False)
825		goto err;
826	    codeset->wc_encoding = l;
827	}
828
829	/***** codeset.ct_encoding *****/
830	snprintf(name, sizeof(name), "%s.%s", cs, "ct_encoding");
831	_XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
832	if (num > 0) {
833	    char *encoding;
834
835	    if (codeset == NULL && (codeset = add_codeset(gen)) == NULL)
836		goto err;
837	    for ( ; num-- > 0; value++) {
838		if (strlen (*value) > sizeof name)
839		    goto err;
840		string_to_encoding(*value, name);
841		charset = NULL;
842		if ((encoding = strchr(name, ':')) &&
843		    (encoding = strchr(encoding + 1, ':'))) {
844		    *encoding++ = '\0';
845		    charset = _XlcAddCT(name, encoding);
846		}
847		if (charset == NULL) {
848		    charset = _XlcGetCharSet(name);
849		    if (charset == NULL &&
850			(charset = _XlcCreateDefaultCharSet(name, ""))) {
851			charset->side = codeset->side;
852			charset->char_size = codeset->length;
853			_XlcAddCharSet(charset);
854		    }
855		}
856		if (charset) {
857		    if (add_charset(codeset, charset) == False)
858			goto err;
859		}
860	    }
861	}
862
863	if (codeset == NULL)
864	    break;
865	codeset->cs_num = i;
866        /* For VW/UDC */
867        /***** 3.4.2 byteM (1 <= M <= length)*****/
868        for (M=1; M-1  < codeset->length; M++) {
869            unsigned long start,end;
870            ByteInfo tmpb;
871
872            snprintf(name, sizeof(name),"%s.%s%d",cs,"byte",M);
873            _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
874
875            if (M == 1) {
876                if (num < 1) {
877                    codeset->byteM = NULL;
878                    break ;
879                }
880                codeset->byteM = Xmallocarray(codeset->length,
881                                              sizeof(ByteInfoListRec));
882                if (codeset->byteM == NULL) {
883                    goto err;
884                }
885            }
886
887            if (num > 0) {
888                _XlcDbg_printValue(name,value,num);
889                (codeset->byteM)[M-1].M = M;
890                (codeset->byteM)[M-1].byteinfo_num = num;
891                (codeset->byteM)[M-1].byteinfo =
892		    Xmallocarray(num, sizeof(ByteInfoRec));
893                for (ii = 0 ; ii < num ; ii++) {
894                    tmpb = (codeset->byteM)[M-1].byteinfo ;
895                    /* default 0x00 - 0xff */
896                    sscanf(value[ii],"\\x%lx,\\x%lx",&start,&end);
897                    tmpb[ii].start = (unsigned char)start;
898                    tmpb[ii].end  = (unsigned char)end;
899                }
900            }
901            /* .... */
902        }
903
904
905        /***** codeset.mb_conversion *****/
906        snprintf(name, sizeof(name), "%s.%s", cs, "mb_conversion");
907        _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
908        if (num > 0) {
909                _XlcDbg_printValue(name,value,num);
910                codeset->mbconv = Xmalloc(sizeof(ConversionRec));
911                codeset->mbconv->convlist =
912                _XlcParse_scopemaps(value[0],&(codeset->mbconv->conv_num));
913                dmpscope("mb_conv",codeset->mbconv->convlist,
914                         codeset->mbconv->conv_num);
915                /* [\x%x,\x%x]->\x%x,... */
916        }
917        /***** codeset.ct_conversion *****/
918        snprintf(name, sizeof(name), "%s.%s", cs, "ct_conversion");
919        _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
920        if (num > 0) {
921                _XlcDbg_printValue(name,value,num);
922                codeset->ctconv = Xmalloc(sizeof(ConversionRec));
923                codeset->ctconv->convlist =
924                _XlcParse_scopemaps(value[0],&(codeset->ctconv->conv_num));
925                dmpscope("ctconv",codeset->ctconv->convlist,
926                         codeset->ctconv->conv_num);
927                /* [\x%x,\x%x]->\x%x,... */
928        }
929        /***** codeset.ct_conversion_file *****/
930        snprintf(name, sizeof(name), "%s.%s", cs, "ct_conversion_file");
931        _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
932        if (num > 0) {
933                _XlcDbg_printValue(name,value,num);
934                /* [\x%x,\x%x]->\x%x,... */
935        }
936        /***** codeset.ct_extended_segment *****/
937        snprintf(name, sizeof(name), "%s.%s", cs, "ct_extended_segment");
938        _XlcGetResource(lcd, "XLC_XLOCALE", name, &value, &num);
939        if (num > 0) {
940                _XlcDbg_printValue(name,value,num);
941                codeset->ctextseg = create_ctextseg(value,num);
942                /* [\x%x,\x%x]->\x%x,... */
943        }
944        /* For VW/UDC end */
945
946    }
947
948    read_charset_define(lcd,gen);       /* For VW/UDC */
949    read_segmentconversion(lcd,gen);    /* For VW/UDC */
950
951    if (gen->initial_state_GL == NULL) {
952       CodeSetRec *codeset;
953       for (i = 0; i < gen->codeset_num; i++) {
954          codeset = gen->codeset_list[i];
955          if (codeset->side == XlcGL)
956             gen->initial_state_GL = codeset;
957       }
958    }
959
960    if (gen->initial_state_GR == NULL) {
961       CodeSetRec *codeset;
962       for (i = 0; i < gen->codeset_num; i++) {
963          codeset = gen->codeset_list[i];
964          if (codeset->side == XlcGR)
965             gen->initial_state_GR = codeset;
966       }
967    }
968
969    for (i = 0; i < gen->codeset_num; i++) {
970       CodeSetRec *codeset = gen->codeset_list[i];
971       for (ii = 0; ii < codeset->num_charsets; ii++) {
972          charset = codeset->charset_list[ii];
973          if (! strcmp(charset->encoding_name, "ISO8859-1"))
974              charset->string_encoding = True;
975          if ( charset->string_encoding )
976              codeset->string_encoding = True;
977       }
978    }
979    return True;
980
981err:
982    free_charset(lcd);
983
984    return False;
985}
986
987#ifdef USE_DYNAMIC_LC
988/* override the open_om and open_im methods which were set by
989   super_class's initialize method() */
990
991static Bool
992initialize_core(
993    XLCd lcd)
994{
995    _XInitDynamicOM(lcd);
996
997    _XInitDynamicIM(lcd);
998
999    return True;
1000}
1001#endif
1002
1003static Bool
1004initialize(XLCd lcd)
1005{
1006    XLCdPublicMethods superclass = (XLCdPublicMethods) _XlcPublicMethods;
1007
1008    XLC_PUBLIC_METHODS(lcd)->superclass = superclass;
1009
1010    if (superclass->pub.initialize) {
1011	if ((*superclass->pub.initialize)(lcd) == False)
1012	    return False;
1013    }
1014
1015#ifdef USE_DYNAMIC_LC
1016    if (initialize_core(lcd) == False)
1017	return False;
1018#endif
1019
1020    if (load_generic(lcd) == False)
1021	return False;
1022
1023    return True;
1024}
1025
1026/* VW/UDC start 95.01.08 */
1027static void
1028freeByteM(
1029    CodeSet codeset)
1030{
1031    int i;
1032    ByteInfoList blst;
1033    if (codeset->byteM == NULL) {
1034	return ;
1035    }
1036    blst = codeset->byteM;
1037    for (i = 0; i < codeset->length; i++) {
1038	    Xfree(blst[i].byteinfo);
1039	    blst[i].byteinfo = NULL;
1040    }
1041    Xfree(codeset->byteM);
1042    codeset->byteM = NULL;
1043}
1044
1045static void
1046freeConversion(
1047    CodeSet codeset)
1048{
1049    Conversion mbconv,ctconv;
1050    if (codeset->mbconv) {
1051	mbconv = codeset->mbconv;
1052	/*  ...  */
1053	Xfree(mbconv->convlist);
1054	mbconv->convlist = NULL;
1055
1056	Xfree(mbconv);
1057	codeset->mbconv = NULL;
1058    }
1059    if (codeset->ctconv) {
1060	ctconv = codeset->ctconv;
1061	/*  ...  */
1062	Xfree(ctconv->convlist);
1063	ctconv->convlist = NULL;
1064
1065	Xfree(ctconv);
1066	codeset->ctconv = NULL;
1067    }
1068}
1069
1070static void
1071freeExtdSegment(
1072    CodeSet codeset)
1073{
1074    ExtdSegment ctextseg;
1075    if (codeset->ctextseg == NULL) {
1076	return;
1077    }
1078    ctextseg = codeset->ctextseg;
1079    Xfree(ctextseg->name);
1080    ctextseg->name = NULL;
1081
1082    Xfree(ctextseg->area);
1083    ctextseg->area = NULL;
1084
1085    Xfree(codeset->ctextseg);
1086    codeset->ctextseg = NULL;
1087}
1088
1089static void
1090freeParseInfo(
1091    CodeSet codeset)
1092{
1093    ParseInfo parse_info;
1094    if (codeset->parse_info == NULL) {
1095	return;
1096    }
1097    parse_info = codeset->parse_info;
1098
1099    Xfree(parse_info->encoding);
1100    parse_info->encoding = NULL;
1101
1102    Xfree(codeset->parse_info);
1103    codeset->parse_info = NULL;
1104}
1105
1106static void
1107destroy_CodeSetList(
1108    XLCdGenericPart *gen)
1109{
1110    CodeSet *codeset = gen->codeset_list;
1111    int i;
1112    if (gen->codeset_num == 0) {
1113	return;
1114    }
1115    for (i=0;i<gen->codeset_num;i++) {
1116        freeByteM(codeset[i]);
1117	freeConversion(codeset[i]);
1118	freeExtdSegment(codeset[i]);
1119	freeParseInfo(codeset[i]);
1120
1121	Xfree(codeset[i]->charset_list);
1122	codeset[i]->charset_list = NULL;
1123
1124	Xfree(codeset[i]); codeset[i]=NULL;
1125    }
1126    Xfree(codeset); gen->codeset_list = NULL;
1127}
1128
1129static void
1130destroy_SegConv(
1131    XLCdGenericPart *gen)
1132{
1133    SegConv seg = gen->segment_conv;
1134    int i;
1135
1136    if (gen->segment_conv_num == 0) {
1137	return;
1138    }
1139    for (i=0;i<gen->segment_conv_num;i++) {
1140
1141	    Xfree(seg[i].source_encoding);
1142	    seg[i].source_encoding = NULL;
1143
1144	    Xfree(seg[i].destination_encoding);
1145	    seg[i].destination_encoding = NULL;
1146
1147	    Xfree(seg[i].conv);
1148            seg[i].conv = NULL;
1149    }
1150    Xfree(seg); gen->segment_conv = NULL;
1151}
1152
1153static void
1154destroy_gen(
1155    XLCd lcd)
1156{
1157    XLCdGenericPart *gen = XLC_GENERIC_PART(lcd);
1158    destroy_SegConv(gen);
1159    destroy_CodeSetList(gen);
1160
1161    Xfree(gen->mb_parse_table);
1162    gen->mb_parse_table = NULL;
1163
1164    Xfree(gen->mb_parse_list);
1165    gen->mb_parse_list = NULL;
1166
1167}
1168/* VW/UDC end 95.01.08 */
1169
1170static void
1171destroy(
1172    XLCd lcd)
1173{
1174    XLCdPublicMethods superclass = XLC_PUBLIC_METHODS(lcd)->superclass;
1175
1176    destroy_gen(lcd); /* ADD 1996.01.08 */
1177    if (superclass && superclass->pub.destroy)
1178	(*superclass->pub.destroy)(lcd);
1179}
1180