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