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