442e3090f1afc6b5815fb4e10540d3086f1f81d0
[platform/upstream/libX11.git] / modules / lc / xlocale / lcEuc.c
1 /******************************************************************
2
3         Copyright 1992, 1993 by FUJITSU LIMITED
4         Copyright 1993 by Fujitsu Open Systems Solutions, Inc.
5
6 Permission to use, copy, modify, distribute and sell this software
7 and its documentation for any purpose is hereby granted without fee,
8 provided that the above copyright notice appear in all copies and
9 that both that copyright notice and this permission notice appear
10 in supporting documentation, and that the name of FUJITSU LIMITED and
11 Fujitsu Open Systems Solutions, Inc. not be used in advertising or
12 publicity pertaining to distribution of the software without specific,
13 written prior permission.
14 FUJITSU LIMITED and Fujitsu Open Systems Solutions, Inc. makes no
15 representations about the suitability of this software for any purpose.
16 It is provided "as is" without express or implied warranty.
17
18 FUJITSU LIMITED AND FUJITSU OPEN SYSTEMS SOLUTIONS, INC. DISCLAIMS ALL
19 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FUJITSU OPEN SYSTEMS
21 SOLUTIONS, INC. AND FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT
22 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
23 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
25 OF THIS SOFTWARE.
26
27     Authors: Shigeru Yamada             (yamada@ossi.com)
28              Jeffrey Bloomfield         (jeffb@ossi.com)
29              Yoshiyuki Segawa           (segawa@ossi.com)
30
31 *****************************************************************/
32
33 /*
34  * An EUC locale.
35  * Supports: all locales with codeset eucJP, eucKR, eucCN, eucTW.
36  * How: Provides converters for euc*.
37  * Platforms: Only those defining X_LOCALE (only Lynx, Linux-libc5, OS/2).
38  */
39
40 #ifdef X_LOCALE
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45 #include "Xlibint.h"
46 #include "XlcGeneric.h"
47
48 #include <ctype.h>
49 #ifdef WIN32
50 #define isascii __isascii
51 #endif
52
53 #define CS0     codesets[0]             /* Codeset 0 - 7-bit ASCII      */
54 #define CS1     codesets[1]             /* Codeset 1 - Kanji            */
55 #define CS2     codesets[2]             /* Codeset 2 - Half-Kana        */
56 #define CS3     codesets[3]             /* Codeset 3 - User defined     */
57
58 #define SS2     0x8e    /* Single-shift char: CS2 */
59 #define SS3     0x8f    /* Single-shift char: CS3 */
60
61 #define ASCII_CODESET   0
62 #define KANJI_CODESET   1
63 #define KANA_CODESET    2
64 #define USERDEF_CODESET 3
65 #define MAX_CODESETS
66
67 #define GR      0x80    /* begins right-side (non-ascii) region */
68 #define GL      0x7f    /* ends left-side (ascii) region        */
69
70 #define isleftside(c)   (((c) & GR) ? 0 : 1)
71 #define isrightside(c)  (!isleftside(c))
72
73 #define BIT8OFF(c)      ((c) & GL)
74 #define BIT8ON(c)       ((c) | GR)
75
76 typedef unsigned char   Uchar;
77 typedef unsigned long   Ulong;
78 typedef unsigned int    Uint;
79
80 static CodeSet GetCodeSetFromCharSet (XLCd lcd, XlcCharSet charset);
81 static CodeSet wc_codeset (XLCd lcd, wchar_t wch);
82
83 #define BADCHAR(min_ch, c)  (BIT8OFF(c) < (char)min_ch && BIT8OFF(c) != 0x0 && \
84                              BIT8OFF(c) != '\t' && BIT8OFF(c) != '\n' && \
85                              BIT8OFF(c) != 0x1b)
86
87 /*
88  * Notes:
89  * 1. Defining FORCE_INDIRECT_CONVERTER (see _XlcEucLoader())
90  *    forces indirect (charset) conversions (e.g. wcstocs()<->cstombs()).
91  * 2. Using direct converters (e.g. mbstowcs()) decreases conversion
92  *    times by 20-40% (depends on specific converter used).
93  */
94
95 static int
96 euc_mbstowcs(
97     XlcConv conv,
98     XPointer *from,
99     int *from_left,
100     XPointer *to,
101     int *to_left,
102     XPointer *args,
103     int num_args)
104 {
105     XLCd lcd = (XLCd)conv->state;
106
107     Uchar ch;
108     int chr_len = 0;
109     int sshift =  False;
110     int shift_mult = 0;
111     Uint chrcode;
112
113     Uint wc_encode = 0;
114     Uint wc_tmp = 0;
115
116     int cs0flg = False;
117     int cs1flg = False;
118     int length = 0;
119     int unconv_num = 0;
120
121     Bool new_char;
122
123     const char *inbufptr = *from;
124     wchar_t *outbufptr = (wchar_t *) *to;
125
126     CodeSet *codesets = XLC_GENERIC(lcd, codeset_list);
127     int codeset_num = XLC_GENERIC(lcd, codeset_num);
128     Ulong wc_shift = XLC_GENERIC(lcd, wc_shift_bits);
129
130     for (new_char = True; *from_left > 0 && *to_left > 0;) {
131
132         ch = *inbufptr++;
133
134         if (isleftside(ch)) {                           /* CS0 */
135             if (ASCII_CODESET >= codeset_num) {
136                 unconv_num++;
137                 (*from_left)--;
138                 continue;
139             }
140             if( cs0flg == True) {
141                 new_char = True;
142                 cs0flg = False;
143             }
144             length = CS0->length;
145             *outbufptr++ = (wchar_t)ch;
146             (*from_left)--;
147             (*to_left)--;
148             continue;
149         }
150         else if (ch == SS2) {                           /* CS2 */
151             if (KANA_CODESET >= codeset_num) {
152                 unconv_num++;
153                 (*from_left)--;
154                 continue;
155             }
156             if (sshift == True || cs1flg == True) {
157                 cs1flg = False;
158                 unconv_num++;
159                 continue;
160             }
161             length = CS2->length;
162             wc_encode = CS2->wc_encoding;
163             chrcode = 0;
164             sshift = True;
165             cs0flg = True;
166             (*from_left)--;
167             continue;
168         }
169         else if (ch == SS3) {                           /* CS3 */
170             if (USERDEF_CODESET >= codeset_num) {
171                 unconv_num++;
172                 (*from_left)--;
173                 continue;
174             }
175             if (sshift == True || cs1flg == True) {
176                 cs1flg = False;
177                 unconv_num++;
178                 continue;
179             }
180             length = CS3->length;
181             if (*from_left < 1 )
182                 unconv_num++;
183             wc_encode = CS3->wc_encoding;
184             chrcode = 0;
185             sshift = True;
186             cs0flg = True;
187             (*from_left)--;
188             continue;
189
190         } else {                                        /* CS1 */
191             if (KANJI_CODESET >= codeset_num) {
192                 unconv_num++;
193                 (*from_left)--;
194                 continue;
195             }
196             if (sshift == False) {
197                 length = CS1->length;
198                 if (*from_left < 1)
199                     unconv_num++;
200                 wc_encode = CS1->wc_encoding;
201             }
202             chrcode = BIT8OFF(ch);
203             cs0flg = True;
204             cs1flg = True;
205             (*from_left)--;
206         }
207
208         if (new_char) {                         /* begin new character */
209             chr_len = length;
210             shift_mult = length - 1;
211             new_char = False;
212         }
213
214         chrcode <<= (wc_shift * shift_mult);
215         shift_mult--;
216         wc_tmp |= chrcode;
217
218         if (--chr_len == 0) {
219             wc_tmp |= wc_encode;
220             *outbufptr++ = wc_tmp;
221             (*to_left)--;
222
223             new_char = True;
224             sshift = False;
225             cs0flg = False;
226             cs1flg = False;
227             wc_tmp  = (Uint)0;
228         }
229
230     }   /* end for */
231
232     *to = (XPointer)outbufptr;
233
234     if (cs0flg == True || cs1flg == True)       /* error check on last char */
235         unconv_num++;
236
237     return unconv_num;
238 }
239
240
241 static int
242 euc_wcstombs(
243     XlcConv conv,
244     XPointer *from,
245     int *from_left,
246     XPointer *to,
247     int *to_left,
248     XPointer *args,
249     int num_args)
250 {
251     const wchar_t *inbufptr = (const wchar_t *) *from;
252     XPointer outbufptr = *to;
253     wchar_t  wch;
254     int length;
255     Uchar tmp;
256     int unconv_num = 0;
257
258     XLCd lcd = (XLCd)conv->state;
259     CodeSet codeset;
260     Ulong wc_shift = XLC_GENERIC(lcd, wc_shift_bits);
261
262     for (; *from_left > 0 && *to_left > 0; (*from_left)-- ) {
263
264         wch = *inbufptr++;
265
266         if (!(codeset = wc_codeset(lcd, wch))) {
267             unconv_num++;
268             (*from_left)--;
269             continue;
270         }
271
272         length = codeset->length;
273         wch ^= (wchar_t)codeset->wc_encoding;
274
275         if (codeset->parse_info) {      /* put out SS2 or SS3 */
276             if (*to_left < length + 1) {
277                 unconv_num++;
278                 break;
279             }
280             *outbufptr++ = *codeset->parse_info->encoding;
281             (*to_left)--;
282         } else {
283             if (*to_left < length) {
284                 unconv_num++;
285                 break;
286             }
287         }
288
289         do {
290             length--;
291             tmp = (wch>>(wchar_t)(length * wc_shift));
292
293             if (codeset->side == XlcGR)
294                 tmp = BIT8ON(tmp);
295
296             *outbufptr++ = (Uchar)tmp;
297             (*to_left)--;
298         } while (length);
299     }
300
301     *to = (XPointer)outbufptr;
302
303     return unconv_num;
304 }
305
306
307 static int
308 euc_mbtocs(
309     XlcConv conv,
310     XPointer *from,
311     int *from_left,
312     XPointer *to,
313     int *to_left,
314     XPointer *args,
315     int num_args)
316 {
317     XLCd lcd = (XLCd)conv->state;
318     XlcCharSet charset;
319     CodeSet *codesets = XLC_GENERIC(lcd, codeset_list);
320     int codeset_num = XLC_GENERIC(lcd, codeset_num);
321     int length;
322     int unconv_num = 0;
323     int min_ch = 0;
324     const char *src = *from;
325     char *dst = *to;
326
327     if (isleftside(*src)) {                     /* 7-bit (CS0) */
328         if (ASCII_CODESET >= codeset_num)
329             return -1;
330         charset = *CS0->charset_list;
331     }
332     else if ((Uchar)*src == SS2) {              /* half-kana (CS2) */
333         if (KANA_CODESET >= codeset_num)
334             return -1;
335         charset = *CS2->charset_list;
336         src++;
337         (*from_left)--;
338     }
339     else if ((Uchar)*src == SS3) {              /* user-def */
340         if (USERDEF_CODESET >= codeset_num)
341             return -1;
342         charset = *CS3->charset_list;
343         src++;
344         (*from_left)--;
345     }
346     else  {                                     /* Kanji (CS1) */
347         if (KANJI_CODESET >= codeset_num)
348             return -1;
349         charset = *CS1->charset_list;
350     }
351
352     if(*from_left < charset->char_size || *to_left < charset->char_size)
353         return -1;
354
355     min_ch = 0x20;
356     if (charset->set_size == 94)
357         if (charset->char_size > 1 || charset->side == XlcGR)
358             min_ch = 0x21;
359
360     length = charset->char_size;
361     do {
362         if(BADCHAR(min_ch, *src)) {
363             unconv_num++;
364             src++;
365             break;
366         }
367         switch (charset->side) {
368             case XlcGL:
369                 *dst++ = BIT8OFF(*src++);
370                 break;
371             case XlcGR:
372                 *dst++ = BIT8ON(*src++);
373                 break;
374             default:
375                 *dst++ = *src++;
376                 break;
377             }
378     } while (--length);
379
380     *to = dst;
381     *from = (XPointer) src;
382     *from_left -= charset->char_size;
383     *to_left -= charset->char_size - length;
384
385     if (num_args > 0)
386         *((XlcCharSet *) args[0]) = charset;
387
388     return unconv_num;
389 }
390
391
392 static int
393 euc_mbstocs(
394     XlcConv conv,
395     XPointer *from,
396     int *from_left,
397     XPointer *to,
398     int *to_left,
399     XPointer *args,
400     int num_args)
401 {
402     const char *tmp_from;
403     char *tmp_to;
404     int tmp_from_left, tmp_to_left;
405     XlcCharSet charset, tmp_charset;
406     XPointer tmp_args[1];
407     int unconv_num = 0, ret;
408
409 /* Determine the charset of the segment and convert one characater: */
410
411     tmp_args[0] = (XPointer) &charset; /* charset from euc_mbtocs() */
412     while
413       ((ret = euc_mbtocs(conv, from, from_left, to, to_left, tmp_args, 1)) > 0)
414         unconv_num += ret;
415     if ( ret < 0 )
416         return ret;
417
418     tmp_from = *from;
419     tmp_from_left = *from_left;
420     tmp_to_left = *to_left;
421     tmp_to = *to;
422
423 /* Convert remainder of the segment: */
424
425     tmp_args[0] = (XPointer) &tmp_charset;
426     while( (ret = euc_mbtocs(conv, (XPointer *) &tmp_from, &tmp_from_left,
427                      (XPointer *) &tmp_to, &tmp_to_left, tmp_args, 1)) >= 0 ) {
428
429         if (ret > 0) {
430             unconv_num += ret;
431             continue;
432         }
433
434         if (tmp_charset != charset)  /* quit on end of segment */
435             break;
436
437         *from = (XPointer) tmp_from;
438         *from_left = tmp_from_left;
439         *to = (XPointer) tmp_to;
440         *to_left = tmp_to_left;
441     }
442
443     if (num_args > 0)
444         *((XlcCharSet *) args[0]) = charset;
445
446     return unconv_num;
447 }
448
449
450 static int
451 euc_wcstocs(
452     XlcConv conv,
453     XPointer *from,
454     int *from_left,
455     XPointer *to,
456     int *to_left,
457     XPointer *args,
458     int num_args)
459 {
460     XLCd lcd = (XLCd)conv->state;
461     const wchar_t *wcptr = (const wchar_t *) *from;
462     char *bufptr = (char *) *to;
463     wchar_t wch;
464     char *tmpptr;
465     int length;
466     CodeSet codeset;
467     Ulong wc_encoding;
468     int wcstr_len = *from_left, buf_len = *to_left;
469
470     if (!(codeset = wc_codeset(lcd, *wcptr)))
471         return -1;
472
473     wc_encoding = codeset->wc_encoding;
474
475     if (wcstr_len < buf_len / codeset->length)
476         buf_len = wcstr_len * codeset->length;
477
478     for ( ; wcstr_len > 0 && buf_len > 0; wcptr++, wcstr_len--) {
479         wch = *wcptr;
480
481         if ((wch & XLC_GENERIC(lcd, wc_encode_mask)) != wc_encoding)
482             break;
483
484         length = codeset->length;
485
486         buf_len -= length;
487         bufptr += length;
488         tmpptr = bufptr - 1;
489
490         while (length--) {
491             *tmpptr-- = codeset->length == 1 && codeset->side == XlcGR ?
492               BIT8ON(wch) : BIT8OFF(wch);
493             wch >>= (wchar_t)XLC_GENERIC(lcd, wc_shift_bits);
494         }
495     }
496
497     if (num_args > 0)
498         *((XlcCharSet *) args[0]) = *codeset->charset_list;
499
500     *from_left -= wcptr - (wchar_t *) *from;
501     *from = (XPointer) wcptr;
502
503     *to_left -= bufptr - *to;
504     *to = bufptr;
505
506     return 0;
507 }
508
509
510 static int
511 euc_cstombs(
512     XlcConv conv,
513     XPointer *from,
514     int *from_left,
515     XPointer *to,
516     int *to_left,
517     XPointer *args,
518     int num_args)
519 {
520     XLCd lcd = (XLCd)conv->state;
521     const char *csptr = *from;
522     char *bufptr = *to;
523     int csstr_len = *from_left;
524     int buf_len = *to_left;
525     int length;
526     CodeSet codeset;
527     int cvt_length;
528
529     if (num_args < 1)
530         return -1;
531
532     if (!(codeset = GetCodeSetFromCharSet(lcd, (XlcCharSet) args[0])))
533         return -1;
534
535     cvt_length = 0;
536     csstr_len /= codeset->length;
537     buf_len /= codeset->length;
538
539     if (codeset->parse_info)
540         csstr_len *= 2;
541
542     if (csstr_len < buf_len)
543         buf_len = csstr_len;
544
545     cvt_length += buf_len * codeset->length;
546
547     if (bufptr) {
548         while (buf_len--) {
549             if (codeset->parse_info)    /* put out SS2 or SS3 */
550                 *bufptr++ = *codeset->parse_info->encoding;
551
552             length = codeset->length;
553             while (length--)
554                 *bufptr++ = codeset->side == XlcGR ?
555                   BIT8ON(*csptr++) : BIT8OFF(*csptr++);
556         }
557     }
558
559     *from_left -= csptr - *from;
560     *from = (XPointer) csptr;
561     if (bufptr)
562         *to += cvt_length;
563     *to_left -= cvt_length;
564
565     return 0;
566 }
567
568
569 static int
570 euc_cstowcs(
571     XlcConv conv,
572     XPointer *from,
573     int *from_left,
574     XPointer *to,
575     int *to_left,
576     XPointer *args,
577     int num_args)
578 {
579     XLCd lcd = (XLCd)conv->state;
580     const char *csptr = *from;
581     wchar_t *bufptr = (wchar_t *) *to;
582     wchar_t *toptr = (wchar_t *) *to;
583     int csstr_len = *from_left;
584     int buf_len = *to_left;
585     wchar_t wch;
586     int length;
587     Ulong wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits);
588     CodeSet codeset;
589
590     if (num_args < 1)
591         return -1;
592
593     if (!(codeset = GetCodeSetFromCharSet(lcd, (XlcCharSet) args[0])))
594         return -1;
595
596     csstr_len /= codeset->length;
597     if (csstr_len < buf_len)
598         buf_len = csstr_len;
599     *to_left -= buf_len;
600
601     if (bufptr) {
602
603         toptr += buf_len;
604         *to = (XPointer) toptr;
605
606         while (buf_len--) {
607
608             wch = (wchar_t) BIT8OFF(*csptr);
609             csptr++;
610
611             length = codeset->length - 1;
612             while (length--) {
613                 wch = (wch << wc_shift_bits) | BIT8OFF(*csptr);
614                 csptr++;
615             }
616             *bufptr++ = wch | codeset->wc_encoding;
617         }
618     }
619     *from_left -= csptr - *from;
620     *from = (XPointer) csptr;
621
622     return 0;
623 }
624
625
626 static CodeSet
627 wc_codeset(
628     XLCd lcd,
629     wchar_t wch)
630 {
631     CodeSet *codesets = XLC_GENERIC(lcd, codeset_list);
632     int end = XLC_GENERIC(lcd, codeset_num);
633     Ulong widech = (Ulong)(wch & XLC_GENERIC(lcd, wc_encode_mask));
634
635     for (; --end >= 0; codesets++)
636         if ( widech == (*codesets)->wc_encoding )
637             return *codesets;
638
639     return NULL;
640 }
641
642
643 static CodeSet
644 GetCodeSetFromCharSet(
645     XLCd lcd,
646     XlcCharSet charset)
647 {
648     CodeSet *codeset = XLC_GENERIC(lcd, codeset_list);
649     XlcCharSet *charset_list;
650     int codeset_num, num_charsets;
651
652     codeset_num = XLC_GENERIC(lcd, codeset_num);
653
654     for ( ; codeset_num-- > 0; codeset++) {
655         num_charsets = (*codeset)->num_charsets;
656         charset_list = (*codeset)->charset_list;
657
658         for ( ; num_charsets-- > 0; charset_list++)
659             if (*charset_list == charset)
660                 return *codeset;
661     }
662
663     return (CodeSet) NULL;
664 }
665
666
667 static XlcConv
668 create_conv(
669     XLCd lcd,
670     XlcConvMethods methods)
671 {
672     XlcConv conv;
673
674     conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
675     if (conv == NULL)
676         return (XlcConv) NULL;
677
678     conv->methods = methods;
679     conv->state = (XPointer) lcd;
680     return conv;
681 }
682
683
684 /*
685  *    Stripped down Direct CT converters for EUC
686  *
687  */
688
689 typedef struct _CTDataRec {
690     int side;
691     int length;
692     char *name;
693     Ulong wc_encoding;
694     char sshift;
695     char *ct_encoding;
696     int ct_encoding_len;
697     int set_size;
698     Uchar min_ch;
699     Uchar ct_type;
700 } CTDataRec, *CTData;
701
702 typedef struct _StateRec {
703     CTData GL_charset;
704     CTData GR_charset;
705     CTData charset;
706 } StateRec, *State;
707
708 #define CT_STD  0
709 #define CT_NSTD 1
710 #define CT_DIR  2
711 #define CT_EXT0 3
712 #define CT_EXT1 4
713 #define CT_EXT2 5
714 #define CT_VER  6
715
716 static CTDataRec ctdata[] =
717 {
718   { XlcGL,      1, "ISO8859-1:GL",       0, 0, "\033(B"   ,  3, 0, 0, CT_STD  },
719   { XlcGR,      1, "ISO8859-1:GR",       0, 0, "\033-A"   ,  3, 0, 0, CT_STD  },
720   { XlcGL,      1, "JISX0201.1976-0:GL", 0, 0, "\033(J"   ,  3, 0, 0, CT_STD  },
721   { XlcGR,      1, "JISX0201.1976-0:GR", 0, 0, "\033)I"   ,  3, 0, 0, CT_STD  },
722   { XlcGL,      2, "JISX0208.1983-0:GL", 0, 0, "\033$(B"  ,  4, 0, 0, CT_STD  },
723   { XlcGR,      2, "JISX0208.1983-0:GR", 0, 0, "\033$)B"  ,  4, 0, 0, CT_STD  },
724   { XlcGL,      2, "JISX0212.1990-0:GL", 0, 0, "\033$(D"  ,  4, 0, 0, CT_STD  },
725   { XlcGR,      2, "JISX0212.1990-0:GR", 0, 0, "\033$)D"  ,  4, 0, 0, CT_STD  },
726   { XlcUnknown, 0, "Ignore-Ext-Status?", 0, 0, "\033#"    ,  2, 0, 0, CT_VER  },
727   { XlcUnknown, 0, "NonStd-?-OctetChar", 0, 0, "\033%/0"  ,  4, 0, 0, CT_NSTD },
728   { XlcUnknown, 1, "NonStd-1-OctetChar", 0, 0, "\033%/1"  ,  4, 0, 0, CT_NSTD },
729   { XlcUnknown, 2, "NonStd-2-OctetChar", 0, 0, "\033%/2"  ,  4, 0, 0, CT_NSTD },
730   { XlcUnknown, 3, "NonStd-3-OctetChar", 0, 0, "\033%/3"  ,  4, 0, 0, CT_NSTD },
731   { XlcUnknown, 4, "NonStd-4-OctetChar", 0, 0, "\033%/4"  ,  4, 0, 0, CT_NSTD },
732   { XlcUnknown, 0, "Extension-2"       , 0, 0, "\033%/"   ,  3, 0, 0, CT_EXT2 },
733   { XlcUnknown, 0, "Extension-0"       , 0, 0, "\033"     ,  1, 0, 0, CT_EXT0 },
734   { XlcUnknown, 0, "Begin-L-to-R-Text",  0, 0, "\2331]"   ,  3, 0, 0, CT_DIR  },
735   { XlcUnknown, 0, "Begin-R-to-L-Text",  0, 0, "\2332]"   ,  3, 0, 0, CT_DIR  },
736   { XlcUnknown, 0, "End-Of-String",      0, 0, "\233]"    ,  2, 0, 0, CT_DIR  },
737   { XlcUnknown, 0, "Extension-1"       , 0, 0, "\233"     ,  1, 0, 0, CT_EXT1 },
738 };
739
740 /* Note on above table:  euc_ctstombs() and euc_ctstowcs() parser depends on
741  * certain table entries occuring in decreasing string length--
742  *   1.  CT_EXT2 and CT_EXT0 entries must occur after CT_NSTD entries.
743  *   2.  CT_DIR and CT_EXT1 entries must occur after CT_DIR entries.
744  */
745
746 static CTData ctd_endp = ctdata + ((sizeof(ctdata) / sizeof(CTDataRec))) - 1;
747 static CTData ctdptr[sizeof(ctdata) / sizeof(CTDataRec)];
748
749 #define Ascii   0
750 #define Kanji   1
751 #define Kana    2
752 #define Userdef 3
753
754 /*
755  * initCTptr(): Set ctdptr[] to point at ctdata[], indexed by codeset_num.
756  */
757 static void
758 initCTptr(
759     XLCd lcd)
760 {
761     int num_codesets = XLC_GENERIC(lcd, codeset_num);
762     int num_charsets;
763     int i, j;
764     CodeSet *codesets = XLC_GENERIC(lcd, codeset_list);
765     CodeSet codeset;
766     XlcCharSet charset;
767     CTData ctdp = ctdata;
768
769     ctdptr[Ascii] = &ctdata[0];         /* failsafe */
770
771     for (i = 0; i < num_codesets; i++) {
772
773         codeset = codesets[i];
774         num_charsets = codeset->num_charsets;
775
776         for (j = 0; j < num_charsets; j++) {
777
778             charset = codeset->charset_list[j];
779
780             for (ctdp = ctdata; ctdp <= ctd_endp; ctdp++)
781
782                 if (! strcmp(ctdp->name, charset->name)) {
783
784                     ctdptr[codeset->cs_num] = ctdp;
785
786                     ctdptr[codeset->cs_num]->wc_encoding = codeset->wc_encoding;
787
788                     ctdptr[codeset->cs_num]->set_size =
789                       charset->set_size;
790
791                     ctdptr[codeset->cs_num]->min_ch =
792                       charset->set_size == 94 &&
793                       (ctdptr[codeset->cs_num]->length > 1 ||
794                       ctdptr[codeset->cs_num]->side == XlcGR) ? 0x21 : 0x20;
795
796                     if (codeset->parse_info) {
797                         ctdptr[codeset->cs_num]->sshift =
798                           *codeset->parse_info->encoding;
799                     }
800
801                     break;
802                 }
803         }
804     }
805 }
806
807
808 #define SKIP_I(str)     while (*(str) >= 0x20 && *(str) <=  0x2f) (str)++;
809 #define SKIP_P(str)     while (*(str) >= 0x30 && *(str) <=  0x3f) (str)++;
810
811 static int
812 euc_ctstowcs(
813     XlcConv conv,
814     XPointer *from,
815     int *from_left,
816     XPointer *to,
817     int *to_left,
818     XPointer *args,
819     int num_args)
820 {
821     XLCd lcd = (XLCd)conv->state;
822     Ulong wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits);
823     const char *inbufptr = *from;
824     const char *inbuf_base;
825     wchar_t *outbufptr = (wchar_t *) *to;
826     wchar_t *outbuf_base = outbufptr;
827     int clen, length;
828     int unconv_num = 0;
829     unsigned int ct_seglen = 0;
830     Uchar ct_type = 0;
831     int shift_mult;
832     wchar_t wc_tmp;
833     wchar_t wch;
834     Ulong wc_encoding;
835     CTData ctdp = ctdata;
836     CTData GL_ctdp = ctdp;      /* GL ctdp save */
837     CTData GR_ctdp = ctdp;      /* GR ctdp save */
838     Bool save_outbuf = True;
839     /* If outbufptr is NULL, doen't save output, but just counts
840        a length to hold the output */
841     if (outbufptr == NULL) save_outbuf = False;
842
843     for (length = ctdata[Ascii].length; *from_left > 0; (*from_left) -= length)
844     {
845         ct_type = CT_STD;
846         /* change GL/GR charset */
847         if(ctdp->side == XlcGR && isleftside(*inbufptr)){
848             /* select GL side */
849             ctdp = GL_ctdp;
850             length = ctdp->length;
851             ct_type = ctdp->ct_type;
852         }else if(ctdp->side == XlcGL && isrightside(*inbufptr)){
853             /* select GR side */
854             ctdp = GR_ctdp;
855             length = ctdp->length;
856             ct_type = ctdp->ct_type;
857         }
858         if (*inbufptr == '\033' || *inbufptr == (char)'\233') {
859             for (ctdp = ctdata; ctdp <= ctd_endp ; ctdp++) {
860
861                 if(!strncmp(inbufptr, ctdp->ct_encoding, ctdp->ct_encoding_len))
862                 {
863                     inbufptr += ctdp->ct_encoding_len;
864                     (*from_left) -= ctdp->ct_encoding_len;
865                     if (ctdp->length) {
866                         length = ctdp->length;
867                         if( *from_left < length ) {
868                             *to = (XPointer)outbufptr;
869                             *to_left -= outbufptr - outbuf_base;
870                             return( unconv_num + *from_left );
871                         }
872                     }
873                     ct_type = ctdp->ct_type;
874                     if(ctdp->side == XlcGL){
875                         GL_ctdp = ctdp; /* save GL ctdp */
876                     }else{
877                         GR_ctdp = ctdp; /* save GR ctdp */
878                     }
879                     break;
880                 }
881             }
882             if (ctdp > ctd_endp)        /* failed to match CT sequence */
883                 unconv_num++;
884         }
885
886 /* The following code insures that non-standard encodings, direction, extension,
887  * and version strings are ignored; subject to change in future.
888  */
889         switch (ct_type) {
890         case CT_STD:
891             break;
892         case CT_EXT2:
893             inbufptr++;
894             (*from_left)--;
895         case CT_NSTD:
896             ct_seglen = (BIT8OFF(*inbufptr) << 7) + BIT8OFF(*(inbufptr+1)) + 2;
897             inbufptr += ct_seglen;
898             (*from_left) -= ct_seglen;
899             continue;
900         case CT_EXT0:
901             inbuf_base = inbufptr;
902             SKIP_I(inbufptr);
903             inbufptr++;
904             ct_seglen = (unsigned)(inbufptr - inbuf_base);
905             *(from_left) -= ct_seglen;
906             continue;
907         case CT_EXT1:
908             inbuf_base = inbufptr;
909             SKIP_P(inbufptr);
910             SKIP_I(inbufptr);
911             inbufptr++;
912             ct_seglen = (unsigned)(inbufptr - inbuf_base);
913             *(from_left) -= ct_seglen;
914             continue;
915         case CT_DIR:
916             continue;
917         case CT_VER:
918             inbufptr += 2;
919             *(from_left) -= 2;
920             continue;
921         }
922
923         wc_encoding = (ctdp == ctdptr[Kana] && isleftside(*inbufptr)) ?
924             ctdptr[Ascii]->wc_encoding: ctdp->wc_encoding;
925
926         shift_mult = length - 1;
927         wch = (wchar_t)0;
928         clen = length;
929
930         do {
931             wc_tmp = BIT8OFF(*inbufptr++) << (wc_shift_bits * shift_mult);
932             wch |= wc_tmp;
933             shift_mult--;
934         } while (--clen);
935
936         if (save_outbuf == True)
937             *outbufptr++ = wch | wc_encoding;
938         if (--*to_left == 0 && *from_left != length) {
939             *to = (XPointer)outbufptr;
940             unconv_num = *from_left;
941             return unconv_num;
942         }
943     }
944
945     *to = (XPointer)outbufptr;
946
947     return unconv_num;
948
949 }
950
951
952 #define byte1                   (length == codeset->length - 1)
953 #define byte2                   (byte1 == 0)
954 #define kanji                   (codeset->cs_num == 1)
955 #define kana                    (codeset->cs_num == 2)
956 #define userdef                 (codeset->cs_num == 3)
957
958 static int
959 euc_wcstocts(
960     XlcConv conv,
961     XPointer *from,
962     int *from_left,
963     XPointer *to,
964     int *to_left,
965     XPointer *args,
966     int num_args)
967 {
968     int ct_len = *to_left;
969     const wchar_t *inbufptr = (const wchar_t *) *from;
970     char *ctptr = *to;
971     XPointer ct_base = ctptr;
972     wchar_t  wch;
973     int length;
974     int unconv_num = 0;
975     Uchar tmp;
976     Uchar t1 = 0;
977     int num_conv;
978
979     StateRec ct_state;
980     XLCd lcd = (XLCd)conv->state;
981     CTData charset;
982     CodeSet codeset;
983     Ulong wc_shift = XLC_GENERIC(lcd, wc_shift_bits);
984
985 /* Initial State: */
986     ct_state.GL_charset = ctdptr[0]; /* Codeset 0 */
987     ct_state.GR_charset = NULL;
988
989     if (*from_left > *to_left)
990         *from_left = *to_left;
991
992     for (; *from_left > 0 ; (*from_left)-- ) {
993
994         wch = *inbufptr++;
995
996         if (!(codeset = wc_codeset(lcd, wch))) {
997             unconv_num++;
998             (*from_left)--;
999             continue;
1000         }
1001
1002         charset = ctdptr[codeset->cs_num];
1003
1004         length = codeset->length;
1005         wch ^= (wchar_t)codeset->wc_encoding;
1006
1007         if ( (charset->side == XlcGR && charset != ct_state.GR_charset) ||
1008              (charset->side == XlcGL && charset != ct_state.GL_charset) ) {
1009
1010             ct_len -= ctdptr[codeset->cs_num]->ct_encoding_len;
1011
1012             if (ct_len < 0) {
1013                 unconv_num++;
1014                 break;
1015             }
1016
1017             if (ctptr) {
1018                 strcpy(ctptr, ctdptr[codeset->cs_num]->ct_encoding);
1019                 ctptr += ctdptr[codeset->cs_num]->ct_encoding_len;
1020             }
1021         }
1022
1023         if (charset->side == XlcGR) {
1024             ct_state.GR_charset = charset;
1025             ct_state.GL_charset = NULL;
1026         } else if (charset->side == XlcGL) {
1027             ct_state.GL_charset = charset;
1028             ct_state.GR_charset = NULL;
1029         }
1030
1031         do {
1032
1033             length--;
1034             tmp = wch>>(wchar_t)( (Ulong)length * wc_shift);
1035
1036             if (kana) {
1037                 if (BADCHAR(charset->min_ch, (char)tmp)) {
1038                     unconv_num++;
1039                     break;
1040                 }
1041                 *ctptr++ = (char)BIT8ON(tmp);
1042             }
1043
1044             else if (byte1 && (kanji || userdef))
1045                 t1 = tmp;
1046
1047             else if (byte2 && (kanji || userdef)) {
1048                 if (BADCHAR(charset->min_ch, (char)t1) ||
1049                   BADCHAR(charset->min_ch, (char)tmp)) {
1050                     unconv_num++;
1051                     break;
1052                 }
1053                 if (charset->side == XlcGR) {
1054                     *ctptr++ = (char)BIT8ON(t1);
1055                     *ctptr++ = (char)BIT8ON(tmp);
1056                 } else {
1057                     *ctptr++ = (char)BIT8OFF(t1);
1058                     *ctptr++ = (char)BIT8OFF(tmp);
1059                 }
1060             }
1061
1062             else {
1063                 if (BADCHAR(charset->min_ch, (char)tmp)) {
1064                     unconv_num++;
1065                     break;
1066                 }
1067                 *ctptr++ = (char)tmp;
1068             }
1069
1070
1071         } while (length);
1072
1073     }   /* end for */
1074
1075     *to = (XPointer)ctptr;
1076
1077     if ((num_conv = (int)(ctptr - ct_base)) > 0)
1078         (*to_left) -= num_conv;
1079
1080     return unconv_num;
1081 }
1082 #undef byte1
1083 #undef byte2
1084 #undef kana
1085 #undef kanji
1086 #undef userdef
1087
1088
1089 #define byte1   (ctdp->length == clen)
1090 #define kana    (ctdp == ctdptr[Kana] && isrightside(*inbufptr))
1091 /* #define kanji   (ctdp == ctdptr[Kanji]) */
1092 #define kanji   (strstr(ctdp->name, "JISX0208"))
1093 #define userdef (ctdp == ctdptr[Userdef])
1094
1095 static int
1096 euc_ctstombs(
1097     XlcConv conv,
1098     XPointer *from,
1099     int *from_left,
1100     XPointer *to,
1101     int *to_left,
1102     XPointer *args,
1103     int num_args)
1104 {
1105     char *inbufptr = *from;
1106     XPointer outbufptr = *to;
1107     const char *inbuf_base;
1108     XPointer outbuf_base = outbufptr;
1109     int clen, length;
1110     int unconv_num = 0;
1111     unsigned int ct_seglen = 0;
1112     Uchar ct_type = 0;
1113     CTData ctdp = &ctdata[0];   /* default */
1114     CTData GL_ctdp = ctdp;      /* GL ctdp save */
1115     CTData GR_ctdp = ctdp;      /* GR ctdp save */
1116     Bool save_outbuf = True;
1117     /* If outbufptr is NULL, doen't save output, but just counts
1118        a length to hold the output */
1119     if (outbufptr == NULL) save_outbuf = False;
1120
1121     for (length = ctdata[Ascii].length; *from_left > 0; (*from_left) -= length)
1122     {
1123         ct_type = CT_STD;
1124         /* change GL/GR charset */
1125         if(ctdp->side == XlcGR && isleftside(*inbufptr)){
1126             /* select GL side */
1127             ctdp = GL_ctdp;
1128             length = ctdp->length;
1129             ct_type = ctdp->ct_type;
1130         }else if(ctdp->side == XlcGL && isrightside(*inbufptr)){
1131             /* select GR side */
1132             ctdp = GR_ctdp;
1133             length = ctdp->length;
1134             ct_type = ctdp->ct_type;
1135         }
1136         if (*inbufptr == '\033' || *inbufptr == (char)'\233') {
1137
1138             for (ctdp = ctdata; ctdp <= ctd_endp ; ctdp++) {
1139
1140                 if(!strncmp(inbufptr, ctdp->ct_encoding, ctdp->ct_encoding_len))
1141                 {
1142                     inbufptr += ctdp->ct_encoding_len;
1143                     (*from_left) -= ctdp->ct_encoding_len;
1144                     if (ctdp->length) {
1145                         length = ctdp->length;
1146                         if( *from_left < length ) {
1147                             *to = (XPointer)outbufptr;
1148                             *to_left -= outbufptr - outbuf_base;
1149                             return( unconv_num + *from_left );
1150                         }
1151                     }
1152                     ct_type = ctdp->ct_type;
1153                     if(ctdp->side == XlcGL){
1154                         GL_ctdp = ctdp; /* save GL ctdp */
1155                     }else{
1156                         GR_ctdp = ctdp; /* save GR ctdp */
1157                     }
1158                     break;
1159                 }
1160             }
1161             if (ctdp > ctd_endp)        /* failed to match CT sequence */
1162                 unconv_num++;
1163         }
1164
1165 /* The following code insures that non-standard encodings, direction, extension,
1166  * and version strings are ignored; subject to change in future.
1167  */
1168         switch (ct_type) {
1169         case CT_STD:
1170             break;
1171         case CT_EXT2:
1172             inbufptr++;
1173             (*from_left)--;
1174         case CT_NSTD:
1175             ct_seglen = (BIT8OFF(*inbufptr) << 7) + BIT8OFF(*(inbufptr+1)) + 2;
1176             inbufptr += ct_seglen;
1177             (*from_left) -= ct_seglen;
1178             continue;
1179         case CT_EXT0:
1180             inbuf_base = inbufptr;
1181             SKIP_I(inbufptr);
1182             inbufptr++;
1183             ct_seglen = (unsigned)(inbufptr - inbuf_base);
1184             *(from_left) -= ct_seglen;
1185             continue;
1186         case CT_EXT1:
1187             inbuf_base = inbufptr;
1188             SKIP_P(inbufptr);
1189             SKIP_I(inbufptr);
1190             inbufptr++;
1191             ct_seglen = (unsigned)(inbufptr - inbuf_base);
1192             *(from_left) -= ct_seglen;
1193             continue;
1194         case CT_DIR:
1195             continue;
1196         case CT_VER:
1197             inbufptr += 2;
1198             *(from_left) -= 2;
1199             continue;
1200         }
1201
1202         clen = length;
1203         do {
1204
1205             if (byte1) {
1206                 if (kanji) {
1207                     /* FIXME: assignment of read-only location */
1208                     *inbufptr = BIT8ON(*inbufptr);
1209                     *(inbufptr+1) = BIT8ON(*(inbufptr+1));
1210                 }
1211                 else if (kana || userdef) {
1212                     if (save_outbuf == True) {
1213                         *outbufptr++ = ctdp->sshift;
1214                     }
1215                     (*to_left)--;
1216                 }
1217             }
1218             if (save_outbuf == True) {
1219                 *outbufptr++ = *inbufptr;
1220             }
1221             (*to_left)--;
1222             inbufptr++;
1223
1224             if (*to_left == 0 && *from_left != length) {
1225                 *to = (XPointer)outbufptr;
1226                 unconv_num = *from_left;
1227                 return unconv_num;
1228             }
1229         } while (--clen);
1230     }
1231
1232     *to = outbufptr;
1233
1234     return unconv_num;
1235
1236 }
1237 #undef byte1
1238 #undef kana
1239 #undef kanji
1240 #undef userdef
1241
1242
1243 static int
1244 euc_mbstocts(
1245     XlcConv conv,
1246     XPointer *from,
1247     int *from_left,
1248     XPointer *to,
1249     int *to_left,
1250     XPointer *args,
1251     int num_args)
1252 {
1253     int ct_len = *to_left;
1254     int cs_num;
1255     int clen, length = 0;
1256     int unconv_num = 0;
1257     int num_conv;
1258     const char *inbufptr = *from;
1259     char *ctptr = *to;
1260     XPointer ct_base = ctptr;
1261
1262     StateRec ct_state;
1263     CTData charset;
1264     XLCd lcd = (XLCd) conv->state;
1265     int codeset_num = XLC_GENERIC(lcd, codeset_num);
1266
1267 /* Initial State: */
1268     ct_state.GL_charset = NULL;
1269     ct_state.GR_charset = NULL;
1270
1271     if (*from_left > *to_left)
1272         *from_left = *to_left;
1273
1274     for (;*from_left > 0; (*from_left) -= length) {
1275
1276         if (isleftside(*inbufptr)) {            /* 7-bit (CS0) */
1277             if (ASCII_CODESET >= codeset_num) {
1278                 unconv_num++;
1279                 (*from_left)--;
1280                 continue;
1281             }
1282             cs_num = Ascii;
1283             charset = ctdptr[Ascii];
1284         }
1285         else if ((Uchar)*inbufptr == SS2) {     /* Kana */
1286             if (KANA_CODESET >= codeset_num) {
1287                 unconv_num++;
1288                 (*from_left)--;
1289                 continue;
1290             }
1291             cs_num = Kana;
1292             charset = ctdptr[Kana];
1293             inbufptr++;
1294             (*from_left)--;
1295         }
1296         else if ((Uchar)*inbufptr == SS3) {     /* Userdef */
1297             if (USERDEF_CODESET >= codeset_num) {
1298                 unconv_num++;
1299                 (*from_left)--;
1300                 continue;
1301             }
1302             cs_num = Userdef;
1303             charset = ctdptr[Userdef];
1304             inbufptr++;
1305             (*from_left)--;
1306         }
1307         else {
1308             if (KANJI_CODESET >= codeset_num) {
1309                 unconv_num++;
1310                 (*from_left)--;
1311                 continue;
1312             }
1313             cs_num = Kanji;
1314             charset = ctdptr[Kanji];
1315         }
1316
1317         length = charset->length;
1318
1319         if (BADCHAR(charset->min_ch, *inbufptr))
1320             continue;
1321
1322         if ( (charset->side == XlcGR && charset != ct_state.GR_charset) ||
1323              (charset->side == XlcGL && charset != ct_state.GL_charset) ) {
1324
1325             ct_len -= ctdptr[cs_num]->ct_encoding_len;
1326             if (ct_len < 0) {
1327                 unconv_num++;
1328                 break;
1329             }
1330
1331             if (ctptr) {
1332                 strcpy(ctptr, ctdptr[cs_num]->ct_encoding);
1333                 ctptr += ctdptr[cs_num]->ct_encoding_len;
1334             }
1335         }
1336
1337         if (charset->side == XlcGR) {
1338             ct_state.GR_charset = charset;
1339             ct_state.GL_charset = NULL;
1340         } else if (charset->side == XlcGL) {
1341             ct_state.GL_charset = charset;
1342             ct_state.GR_charset = NULL;
1343         }
1344
1345         clen = length;
1346
1347         do {
1348             *ctptr++ = charset == ct_state.GR_charset ?
1349                 BIT8ON(*inbufptr++) : BIT8OFF(*inbufptr++);
1350         } while (--clen);
1351     }
1352
1353     *to = (XPointer)ctptr;
1354
1355     if ((num_conv = (int)(ctptr - ct_base)) > 0)
1356         (*to_left) -= num_conv;
1357     return unconv_num;
1358
1359 }
1360
1361
1362 static void
1363 close_converter(
1364     XlcConv conv)
1365 {
1366         Xfree((char *) conv);
1367 }
1368
1369 enum { MBSTOCS, WCSTOCS, MBTOCS, CSTOMBS, CSTOWCS, MBSTOWCS, WCSTOMBS,
1370        CTSTOWCS, CTSTOMBS, WCSTOCTS, MBSTOCTS };
1371
1372 static XlcConvMethodsRec conv_methods[] = {
1373     {close_converter, euc_mbstocs,  NULL },
1374     {close_converter, euc_wcstocs,  NULL },
1375     {close_converter, euc_mbtocs,   NULL },
1376     {close_converter, euc_cstombs,  NULL },
1377     {close_converter, euc_cstowcs,  NULL },
1378     {close_converter, euc_mbstowcs, NULL },
1379     {close_converter, euc_wcstombs, NULL },
1380     {close_converter, euc_ctstowcs, NULL },
1381     {close_converter, euc_ctstombs, NULL },
1382     {close_converter, euc_wcstocts, NULL },
1383     {close_converter, euc_mbstocts, NULL },
1384 };
1385
1386
1387 static XlcConv
1388 open_mbstocs(
1389     XLCd from_lcd,
1390     const char *from_type,
1391     XLCd to_lcd,
1392     const char *to_type)
1393 {
1394     return create_conv(from_lcd, &conv_methods[MBSTOCS]);
1395 }
1396
1397 static XlcConv
1398 open_wcstocs(
1399     XLCd from_lcd,
1400     const char *from_type,
1401     XLCd to_lcd,
1402     const char *to_type)
1403 {
1404     return create_conv(from_lcd, &conv_methods[WCSTOCS]);
1405 }
1406
1407 static XlcConv
1408 open_mbtocs(
1409     XLCd from_lcd,
1410     const char *from_type,
1411     XLCd to_lcd,
1412     const char *to_type)
1413 {
1414     return create_conv(from_lcd, &conv_methods[MBTOCS]);
1415 }
1416
1417 static XlcConv
1418 open_cstombs(
1419     XLCd from_lcd,
1420     const char *from_type,
1421     XLCd to_lcd,
1422     const char *to_type)
1423 {
1424     return create_conv(from_lcd, &conv_methods[CSTOMBS]);
1425 }
1426
1427 static XlcConv
1428 open_cstowcs(
1429     XLCd from_lcd,
1430     const char *from_type,
1431     XLCd to_lcd,
1432     const char *to_type)
1433 {
1434     return create_conv(from_lcd, &conv_methods[CSTOWCS]);
1435 }
1436
1437 static XlcConv
1438 open_mbstowcs(
1439     XLCd from_lcd,
1440     const char *from_type,
1441     XLCd to_lcd,
1442     const char *to_type)
1443 {
1444     return create_conv(from_lcd, &conv_methods[MBSTOWCS]);
1445 }
1446
1447 static XlcConv
1448 open_wcstombs(
1449     XLCd from_lcd,
1450     const char *from_type,
1451     XLCd to_lcd,
1452     const char *to_type)
1453 {
1454     return create_conv(from_lcd, &conv_methods[WCSTOMBS]);
1455 }
1456
1457 static XlcConv
1458 open_ctstowcs(
1459     XLCd from_lcd,
1460     const char *from_type,
1461     XLCd to_lcd,
1462     const char *to_type)
1463 {
1464     return create_conv(from_lcd, &conv_methods[CTSTOWCS]);
1465 }
1466
1467 static XlcConv
1468 open_ctstombs(
1469     XLCd from_lcd,
1470     const char *from_type,
1471     XLCd to_lcd,
1472     const char *to_type)
1473 {
1474     return create_conv(from_lcd, &conv_methods[CTSTOMBS]);
1475 }
1476
1477 static XlcConv
1478 open_wcstocts(
1479     XLCd from_lcd,
1480     const char *from_type,
1481     XLCd to_lcd,
1482     const char *to_type)
1483 {
1484     return create_conv(from_lcd, &conv_methods[WCSTOCTS]);
1485 }
1486
1487 static XlcConv
1488 open_mbstocts(
1489     XLCd from_lcd,
1490     const char *from_type,
1491     XLCd to_lcd,
1492     const char *to_type)
1493 {
1494     return create_conv(from_lcd, &conv_methods[MBSTOCTS]);
1495 }
1496
1497 XLCd
1498 _XlcEucLoader(
1499     const char *name)
1500 {
1501     XLCd lcd;
1502
1503     lcd = _XlcCreateLC(name, _XlcGenericMethods);
1504     if (lcd == NULL)
1505         return lcd;
1506
1507     if (!XLC_PUBLIC_PART(lcd)->codeset ||
1508         (_XlcNCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "euc", 3))) {
1509         _XlcDestroyLC(lcd);
1510         return (XLCd) NULL;
1511     }
1512
1513     initCTptr(lcd);
1514
1515     _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs);
1516     _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs);
1517     _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs);
1518     _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs);
1519     _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbtocs);
1520
1521 #ifndef FORCE_INDIRECT_CONVERTER
1522     _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte, open_ctstombs);
1523     _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar, open_ctstowcs);
1524     _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCompoundText, open_mbstocts);
1525     _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs);
1526     _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCompoundText, open_wcstocts);
1527     _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs);
1528 #endif
1529
1530     _XlcAddUtf8Converters(lcd);
1531
1532     return lcd;
1533 }
1534
1535 #else
1536 typedef int dummy;
1537 #endif /* X_LOCALE */