diff options
Diffstat (limited to 'libX11/modules/lc/xlocale/lcSjis.c')
-rw-r--r-- | libX11/modules/lc/xlocale/lcSjis.c | 1614 |
1 files changed, 1614 insertions, 0 deletions
diff --git a/libX11/modules/lc/xlocale/lcSjis.c b/libX11/modules/lc/xlocale/lcSjis.c new file mode 100644 index 000000000..6adb2945d --- /dev/null +++ b/libX11/modules/lc/xlocale/lcSjis.c @@ -0,0 +1,1614 @@ +/* $Xorg: lcSjis.c,v 1.3 2000/08/17 19:45:19 cpqbld Exp $ */ +/**************************************************************** + + Copyright 1992, 1993 by FUJITSU LIMITED + Copyright 1993 by Fujitsu Open Systems Solutions, Inc. + Copyright 1994 by Sony Corporation + +Permission to use, copy, modify, distribute and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear +in supporting documentation, and that the name of FUJITSU LIMITED, +Fujitsu Open Systems Solutions, Inc. and Sony Corporation not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. +FUJITSU LIMITED, Fujitsu Open Systems Solutions, Inc. and +Sony Corporation make no representations about the suitability of +this software for any purpose. It is provided "as is" without +express or implied warranty. + +FUJITSU LIMITED, FUJITSU OPEN SYSTEMS SOLUTIONS, INC. AND SONY +CORPORATION DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL FUJITSU OPEN SYSTEMS SOLUTIONS, INC., FUJITSU LIMITED +AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + + Authors: Jeffrey Bloomfield (jeffb@ossi.com) + Shigeru Yamada (yamada@ossi.com) + Yoshiyuki Segawa (segawa@ossi.com) + Modifier:Makoto Wakamatsu Sony Corporation + makoto@sm.sony.co.jp + +*****************************************************************/ +/* $XFree86: xc/lib/X11/lcSjis.c,v 3.9 2002/04/10 16:20:06 tsi Exp $ */ + +/* + * A Japanese SJIS locale. + * Supports: all locales with codeset SJIS. + * How: Provides converters for SJIS. + * Platforms: Only those defining X_LOCALE (only Lynx, Linux-libc5, OS/2). + */ + +#ifdef X_LOCALE + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "Xlibint.h" +#include "XlcGeneric.h" + +#include <ctype.h> +#ifdef WIN32 +#define isascii __isascii +#endif + +#define CS0 codesets[0] /* Codeset 0 - 7-bit ASCII */ +#define CS1 codesets[1] /* Codeset 1 - Kanji */ +#define CS2 codesets[2] /* Codeset 2 - Half-Kana */ +#define CS3 codesets[3] /* Codeset 3 - User defined */ + +#define ascii (codeset->cs_num == 0) +#define kanji (codeset->cs_num == 1) +#define kana (codeset->cs_num == 2) +#define userdef (codeset->cs_num == 3) + +#define ASCII_CODESET 0 +#define KANJI_CODESET 1 +#define KANA_CODESET 2 +#define USERDEF_CODESET 3 +#define MAX_CODESETS 4 + +#define GR 0x80 /* begins right-side (non-ascii) region */ +#define GL 0x7f /* ends left-side (ascii) region */ + +#define isleftside(c) (((c) & GR) ? 0 : 1) +#define isrightside(c) (!isleftside(c)) + +typedef unsigned char Uchar; +typedef unsigned long Ulong; +typedef unsigned int Uint; + +/* Acceptable range for 2nd byte of SJIS multibyte char */ +#define VALID_MULTIBYTE(c) \ + ((0x40<=((Uchar)c) && ((Uchar)c)<=0x7e) \ + || (0x80<=((Uchar)c) && ((Uchar)c)<=0xfc)) + +#ifndef iskanji +#define iskanji(c) ((0x81<=((Uchar)c) && ((Uchar)c)<=0x9f) \ + || (0xe0<=((Uchar)c) && ((Uchar)c)<=0xef)) +#endif /* !iskanji */ + +#ifndef iskana +#define iskana(c) (0xa1<=((Uchar)c) && ((Uchar)c)<=0xdf) +#endif /* !iskana */ + +#define isuserdef(c) (0xf0<=((Uchar)c) && ((Uchar)c)<=0xfc) + +#define BIT8OFF(c) ((c) & GL) +#define BIT8ON(c) ((c) | GR) + + +static void jis_to_sjis (Uchar *p1, Uchar *p2); +static void sjis_to_jis (Uchar *p1, Uchar *p2); +static CodeSet wc_codeset (XLCd lcd, wchar_t wch); + + +/* + * Notes: + * 1. 16-bit widechar format is limited to 14 data bits. Since the 2nd byte + * of SJIS multibyte chars are in the ranges of 0x40 - 7E and 0x80 - 0xFC, + * SJIS cannot map directly into 16 bit widechar format within the confines + * of a single codeset. Therefore, for SJIS widechar conversion, SJIS Kanji + * is mapped into the JIS codeset. (The algorithms used in jis_to_sjis() + * and sjis_to_jis() are from Ken Lunde (lunde@mv.us.adobe.com) and are in + * the public domain.) + * 2. Defining FORCE_INDIRECT_CONVERTER (see _XlcEucLoader()) + * forces indirect (charset) conversions (e.g. wcstocs()<->cstombs()). + * 3. Using direct converters (e.g. mbstowcs()) decreases conversion + * times by 20-40% (depends on specific converter used). + */ + + +static int +sjis_mbstowcs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + + XLCd lcd = (XLCd)conv->state; + + int chr_len = 0; + int shift_mult = 0; + Uint chrcode = 0; + + Uchar ch, ch2; + Uint wc_encode = 0; + Uint wc_tmp = 0; + + Bool new_char; + + int firstbyte; + int length = 0; + int num_conv; + int unconv_num = 0; + + const char *inbufptr = *from; + wchar_t *outbufptr = (wchar_t *) *to; + wchar_t *outbuf_base = outbufptr; + + CodeSet *codesets = XLC_GENERIC(lcd, codeset_list); + int codeset_num = XLC_GENERIC(lcd, codeset_num); + Ulong wc_shift = XLC_GENERIC(lcd, wc_shift_bits); + + if (*from_left > *to_left) + *from_left = *to_left; + + for (new_char = True, firstbyte = True; *from_left > 0; (*from_left)--) { + + ch = *inbufptr++; + + if (firstbyte) { + if (ASCII_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + if (isascii(ch)) { + length = CS0->length; + *outbufptr++ = (wchar_t)ch; + continue; + } + else if (iskanji(ch)) { + if (KANJI_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + firstbyte = False; + length = CS1->length; + if (*from_left < length || *to_left < length) + return -1; + wc_encode = CS1->wc_encoding; + ch2 = *inbufptr; + sjis_to_jis(&ch, &ch2); + chrcode = ch; + } + else if (iskana(ch)) { + if (KANA_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + length = CS2->length; + wc_encode = CS2->wc_encoding; + chrcode = BIT8OFF(ch); + } + else if (isuserdef(ch)) { + if (USERDEF_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + firstbyte = False; + length = CS3->length; + if (*from_left < length || *to_left < length) + return -1; + wc_encode = CS3->wc_encoding; + ch2 = *inbufptr; + sjis_to_jis(&ch, &ch2); + chrcode = ch; + } + else /* unknown */ { + unconv_num++; + (*from_left)--; + continue; + } + } else { /* 2nd byte of multibyte char */ + if (!VALID_MULTIBYTE((Uchar) *(inbufptr-1))) { + unconv_num++; + firstbyte = True; + } + chrcode = ch2; + } + + if (new_char) { + chr_len = length; + shift_mult = length - 1; + new_char = False; + } + + chrcode <<= (wc_shift * shift_mult); + shift_mult--; + wc_tmp |= chrcode; + if (--chr_len == 0) { + wc_tmp |= wc_encode; + *outbufptr++ = wc_tmp; + + firstbyte = True; + new_char = True; + wc_tmp = (Uint)0; + } + + } /* end for */ + + *to = (XPointer)outbufptr; + + if ((num_conv = outbufptr - outbuf_base) > 0) + (*to_left) -= num_conv; + + return unconv_num; +} + + +#define byte1 (length == codeset->length - 1) +#define byte2 (byte1 == 0) + +static int +sjis_wcstombs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + const wchar_t *inbufptr = (const wchar_t *) *from; + XPointer outbufptr = *to; + XPointer outbuf_base = outbufptr; + wchar_t wch; + int length; + Uchar tmp; + Uchar t1, t2; + int num_conv; + int unconv_num = 0; + + XLCd lcd = (XLCd)conv->state; + CodeSet codeset; + Ulong wc_shift = XLC_GENERIC(lcd, wc_shift_bits); + + if (*from_left > *to_left) + *from_left = *to_left; + + for (; *from_left > 0 ; (*from_left)-- ) { + + wch = *inbufptr++; + + if (!(codeset = wc_codeset(lcd, wch))) { + unconv_num++; + (*from_left)--; + continue; + } + + length = codeset->length; + wch ^= (wchar_t)codeset->wc_encoding; + + do { + length--; + tmp = wch>>(wchar_t)( (Ulong)length * wc_shift); + + if (kana) + tmp = BIT8ON(tmp); + + else if (byte1 && (kanji || userdef)) { + t1 = BIT8OFF(tmp); + continue; + } + + else if (byte2 && (kanji || userdef)) { + t2 = BIT8OFF(tmp); + jis_to_sjis(&t1, &t2); + *outbufptr++ = (char)t1; + tmp = t2; + } + + *outbufptr++ = (char)tmp; + } while (length); + + } /* end for */ + + *to = (XPointer)outbufptr; + + if ((num_conv = (int)(outbufptr - outbuf_base)) > 0) + (*to_left) -= num_conv; + + return unconv_num; +} +#undef byte1 +#undef byte2 + +/* + * sjis<->jis conversion for widechar kanji (See Note at top of file) + */ +static void +sjis_to_jis( + Uchar *p1, + Uchar *p2) +{ + Uchar c1 = *p1; + Uchar c2 = *p2; + Uchar adjust = c2 < 0x9f; + Uchar rowOffset = c1 < 0xa0 ? 0x70 : 0xb0; + Uchar cellOffset = adjust ? (0x1f + (c2 > 0x7f)) : 0x7e; + + *p1 = ((c1 - rowOffset) << 1) - adjust; + *p2 -= cellOffset; +} + +static void +jis_to_sjis( + Uchar *p1, + Uchar *p2) +{ + Uchar c1 = *p1; + Uchar c2 = *p2; + Uchar rowOffset = c1 < 0x5f ? 0x70 : 0xb0; + Uchar cellOffset = c1 % 2 ? 0x1f + (c2 > 0x5f) : 0x7e; + + *p1 = ((Uchar)(c1 + 1) >> 1) + rowOffset; + *p2 = c2 + cellOffset; +} + +static CodeSet +wc_codeset( + XLCd lcd, + wchar_t wch) +{ + CodeSet *codesets = XLC_GENERIC(lcd, codeset_list); +#if !defined(__sony_news) || defined(SVR4) + int end = XLC_GENERIC(lcd, codeset_num); + Ulong widech = (Ulong)(wch & XLC_GENERIC(lcd, wc_encode_mask)); + + for (; --end >= 0; codesets++) + if ( widech == (*codesets)->wc_encoding ) + return *codesets; + + return NULL; +#else + if( iskanji(wch >> 8) ) + return( codesets[1] ); + if( iskana(wch & 0xff) ) + return( codesets[2] ); + return( codesets[0] ); +#endif +} + + +static int +sjis_mbtocs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + XLCd lcd = (XLCd)conv->state; + XlcCharSet charset = NULL; + int char_size = 0; + int unconv_num = 0; + const char *src = *from; + char *dst = *to; + CodeSet *codesets = XLC_GENERIC(lcd, codeset_list); + int codeset_num = XLC_GENERIC(lcd, codeset_num); + + if (iskanji(*src)) { + if (KANJI_CODESET >= codeset_num) + return -1; + charset = *CS1->charset_list; + char_size = charset->char_size; + + if (*from_left >= char_size && *to_left >= char_size) { + *dst++ = *src++; + *dst++ = *src++; + if (!VALID_MULTIBYTE((Uchar) *(src-1))) /* check 2nd byte */ + unconv_num++; + sjis_to_jis((Uchar *)(dst-2), (Uchar *)(dst-1)); + } else + return -1; + } + else if (isuserdef(*src)) { + if (USERDEF_CODESET >= codeset_num) + return -1; + charset = *CS3->charset_list; + char_size = charset->char_size; + + if (*from_left >= char_size && *to_left >= char_size) { + *dst++ = *src++; + *dst++ = *src++; + if (!VALID_MULTIBYTE((Uchar) *(src-1))) /* check 2nd byte */ + unconv_num++; + sjis_to_jis((Uchar *)(dst-2), (Uchar *)(dst-1)); + } else + return -1; + } + else if (isascii(*src)) { + if (ASCII_CODESET >= codeset_num) + return -1; + charset = *CS0->charset_list; + char_size = charset->char_size; + + if (*from_left >= char_size && *to_left >= char_size) + *dst++ = *src++; + else + return -1; + } + else if (iskana(*src)) { + if (KANA_CODESET >= codeset_num) + return -1; + charset = *CS2->charset_list; + char_size = charset->char_size; + + if (*from_left >= char_size && *to_left >= char_size) + *dst++ = *src++; + else + return -1; + } + else /* unknown */ + return -1; + + *from_left -= char_size; + *to_left -= char_size; + + *to = (XPointer) dst; + *from = (XPointer) src; + + if (num_args > 0) + *((XlcCharSet *) args[0]) = charset; + + return unconv_num; +} + + +static int +sjis_mbstocs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + const char *tmp_from; + char *tmp_to; + int tmp_from_left, tmp_to_left; + XlcCharSet charset, tmp_charset; + XPointer tmp_args[1]; + int unconv_num = 0, ret; + +/* Determine the charset of the segment and convert one character: */ + + tmp_args[0] = (XPointer) &charset; /* charset from sjis_mbtocs() */ + while + ((ret = sjis_mbtocs(conv, from, from_left, to, to_left, tmp_args, 1)) > 0) + unconv_num += ret; + if ( ret < 0 ) + return ret; + + tmp_from = *from; + tmp_from_left = *from_left; + tmp_to_left = *to_left; + tmp_to = *to; + +/* Convert remainder of the segment: */ + + tmp_args[0] = (XPointer) &tmp_charset; + while( (ret = sjis_mbtocs(conv, (XPointer *) &tmp_from, &tmp_from_left, + (XPointer *) &tmp_to, &tmp_to_left, tmp_args, 1)) >= 0 ) { + + if (ret > 0) { + unconv_num += ret; + continue; + } + + if (tmp_charset != charset) /* quit on end of segment */ + break; + + *from = (XPointer) tmp_from; + *from_left = tmp_from_left; + *to = (XPointer) tmp_to; + *to_left = tmp_to_left; + } + + if (num_args > 0) + *((XlcCharSet *) args[0]) = charset; + + return unconv_num; +} + +static int +sjis_wcstocs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + XLCd lcd = (XLCd) conv->state; + const wchar_t *wcptr = *((const wchar_t **)from); + char *bufptr = *((char **) to); + wchar_t wch; + char *tmpptr; + int length; + CodeSet codeset; + Ulong wc_encoding; + int buf_len = *to_left; + int wcstr_len = *from_left; + + if (!(codeset = wc_codeset(lcd, *wcptr))) + return -1; + + if (wcstr_len < buf_len / codeset->length) + buf_len = wcstr_len * codeset->length; + +#if !defined(__sony_news) || defined(SVR4) + wc_encoding = codeset->wc_encoding; + + for ( ; wcstr_len > 0 && buf_len > 0; wcptr++, wcstr_len--) { + wch = *wcptr; + + if ((wch & XLC_GENERIC(lcd, wc_encode_mask)) != wc_encoding) + break; + + length = codeset->length; + + buf_len -= length; + bufptr += length; + tmpptr = bufptr - 1; + + while (length--) { + *tmpptr-- = kana ? BIT8ON(wch) : BIT8OFF(wch); + wch >>= (wchar_t)XLC_GENERIC(lcd, wc_shift_bits); + } + } +#else + length = codeset->length; + for( ; wcstr_len > 0 && buf_len > 0; wcptr++, wcstr_len-- ) { + wch = *wcptr; + if( codeset != wc_codeset( lcd, wch ) ) + break; + + buf_len -= length; + if( length == 2 ) { + unsigned short code; + + code = sjis2jis( wch & 0xffff ); + *bufptr++ = code >> 8; + *bufptr++ = code & 0xff; + } + else + *bufptr++ = wch & 0xff; + } +#endif + + if (num_args > 0) + *((XlcCharSet *) args[0]) = *codeset->charset_list; + + *from_left -= wcptr - (wchar_t *) *from; + *from = (XPointer) wcptr; + + *to_left -= bufptr - *to; + *to = bufptr; + + return 0; +} + +static CodeSet +GetCodeSetFromCharSet( + XLCd lcd, + XlcCharSet charset) +{ + CodeSet *codeset = XLC_GENERIC(lcd, codeset_list); + XlcCharSet *charset_list; + int codeset_num, num_charsets; + + codeset_num = XLC_GENERIC(lcd, codeset_num); + + for ( ; codeset_num-- > 0; codeset++) { + num_charsets = (*codeset)->num_charsets; + charset_list = (*codeset)->charset_list; + + for ( ; num_charsets-- > 0; charset_list++) + if (*charset_list == charset) + return *codeset; + } + + return (CodeSet) NULL; +} + + +static int +sjis_cstombs( + XlcConv conv, + char **from, + int *from_left, + char **to, + int *to_left, + XPointer *args, + int num_args) +{ + XLCd lcd = (XLCd) conv->state; + const char *csptr = *from; + char *bufptr = *to; + int csstr_len = *from_left; + int buf_len = *to_left; + int length; + CodeSet codeset; + int cvt_length = 0; + + if (num_args < 1) + return -1; + + if (!(codeset = GetCodeSetFromCharSet(lcd, (XlcCharSet) args[0]))) + return -1; + + csstr_len /= codeset->length; + buf_len /= codeset->length; + if (csstr_len < buf_len) + buf_len = csstr_len; + + cvt_length += buf_len * codeset->length; + + if (bufptr) { + while (buf_len--) { + length = codeset->length; + while (length--) + *bufptr++ = codeset->length == 1 && codeset->side == XlcGR ? + BIT8ON(*csptr++) : BIT8OFF(*csptr++); + + if (codeset->length == 2) + jis_to_sjis((Uchar *)(bufptr-2), (Uchar *)(bufptr-1)); + } + } + + *from_left -= csptr - *from; + *from = (XPointer) csptr; + + if (bufptr) + *to += cvt_length; + *to_left -= cvt_length; + + + return 0; +} + +static int +sjis_cstowcs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + XLCd lcd = (XLCd) conv->state; + const char *csptr = (const char *) *from; + wchar_t *bufptr = (wchar_t *) *to; + wchar_t *toptr = (wchar_t *) *to; + int csstr_len = *from_left; + int buf_len = *to_left; + wchar_t wch; + int length; + Ulong wc_shift_bits = (int)XLC_GENERIC(lcd, wc_shift_bits); + CodeSet codeset; + + if (num_args < 1) + return -1; + + if (!(codeset = GetCodeSetFromCharSet(lcd, (XlcCharSet) args[0]))) + return -1; + + csstr_len /= codeset->length; + if (csstr_len < buf_len) + buf_len = csstr_len; + + *to_left -= buf_len; + + if (bufptr) { + + toptr += buf_len; + *to = (XPointer) toptr; + + while (buf_len--) { + wch = (wchar_t) BIT8OFF(*csptr); + csptr++; + + length = codeset->length - 1; + while (length--) { + wch = (wch << wc_shift_bits) | BIT8OFF(*csptr); + csptr++; + } + *bufptr++ = wch | codeset->wc_encoding; + } + } + + *from_left -= csptr - *from; + *from = (XPointer) csptr; + + return 0; +} + + +/* + * Stripped down Direct CT converters for SJIS + * + */ + +#define BADCHAR(min_ch, c) (BIT8OFF(c) < (char)min_ch && BIT8OFF(c) != 0x0 && \ + BIT8OFF(c) != '\t' && BIT8OFF(c) != '\n' && \ + BIT8OFF(c) != 0x1b) + +typedef struct _CTDataRec { + int side; + int length; + char *name; + Ulong wc_encoding; + char *ct_encoding; + int ct_encoding_len; + int set_size; + Uchar min_ch; + Uchar ct_type; +} CTDataRec, *CTData; + +typedef struct _StateRec { + CTData GL_charset; + CTData GR_charset; + CTData charset; +} StateRec, *State; + +#define CT_STD 0 +#define CT_NSTD 1 +#define CT_DIR 2 +#define CT_EXT0 3 +#define CT_EXT1 4 +#define CT_EXT2 5 +#define CT_VER 6 + +static CTDataRec ctdata[] = +{ + { XlcGL, 1, "ISO8859-1:GL", 0, "\033(B" , 3, 0, 0, CT_STD }, + { XlcGR, 1, "ISO8859-1:GR", 0, "\033-A" , 3, 0, 0, CT_STD }, + { XlcGL, 1, "JISX0201.1976-0:GL", 0, "\033(J" , 3, 0, 0, CT_STD }, + { XlcGR, 1, "JISX0201.1976-0:GR", 0, "\033)I" , 3, 0, 0, CT_STD }, + { XlcGL, 2, "JISX0208.1983-0:GL", 0, "\033$(B" , 4, 0, 0, CT_STD }, + { XlcGR, 2, "JISX0208.1983-0:GR", 0, "\033$)B" , 4, 0, 0, CT_STD }, + { XlcGL, 2, "JISX0212.1990-0:GL", 0, "\033$(D" , 4, 0, 0, CT_STD }, + { XlcGR, 2, "JISX0212.1990-0:GR", 0, "\033$)D" , 4, 0, 0, CT_STD }, + { XlcUnknown, 0, "Ignore-Ext-Status?", 0, "\033#" , 2, 0, 0, CT_VER }, + { XlcUnknown, 0, "NonStd-?-OctetChar", 0, "\033%/0" , 4, 0, 0, CT_NSTD }, + { XlcUnknown, 1, "NonStd-1-OctetChar", 0, "\033%/1" , 4, 0, 0, CT_NSTD }, + { XlcUnknown, 2, "NonStd-2-OctetChar", 0, "\033%/2" , 4, 0, 0, CT_NSTD }, + { XlcUnknown, 3, "NonStd-3-OctetChar", 0, "\033%/3" , 4, 0, 0, CT_NSTD }, + { XlcUnknown, 4, "NonStd-4-OctetChar", 0, "\033%/4" , 4, 0, 0, CT_NSTD }, + { XlcUnknown, 0, "Extension-2" , 0, "\033%/" , 3, 0, 0, CT_EXT2 }, + { XlcUnknown, 0, "Extension-0" , 0, "\033" , 1, 0, 0, CT_EXT0 }, + { XlcUnknown, 0, "Begin-L-to-R-Text", 0, "\2331]" , 3, 0, 0, CT_DIR }, + { XlcUnknown, 0, "Begin-R-to-L-Text", 0, "\2332]" , 3, 0, 0, CT_DIR }, + { XlcUnknown, 0, "End-Of-String", 0, "\233]" , 2, 0, 0, CT_DIR }, + { XlcUnknown, 0, "Extension-1" , 0, "\233" , 1, 0, 0, CT_EXT1 }, +}; + +/* Note on above table: sjis_ctstombs() and sjis_ctstowcs() parser depends on + * certain table entries occuring in decreasing string length-- + * 1. CT_EXT2 and CT_EXT0 entries must occur after CT_NSTD entries. + * 2. CT_DIR and CT_EXT1 entries must occur after CT_DIR entries. + */ + +static CTData ctdptr[sizeof(ctdata) / sizeof(CTDataRec)]; +static CTData ctd_endp = ctdata + ((sizeof(ctdata) / sizeof(CTDataRec))) - 1; + +#define Ascii 0 +#define Kanji 1 +#define Kana 2 +#define Userdef 3 + +/* + * initCTptr(): Set ctptr[] to point at ctdata[], indexed by codeset_num. + */ +static void +initCTptr( + XLCd lcd) +{ + int num_codesets = XLC_GENERIC(lcd, codeset_num); + int num_charsets; + int i, j; + CodeSet *codesets = XLC_GENERIC(lcd, codeset_list); + CodeSet codeset; + XlcCharSet charset; + CTData ctdp = ctdata; + + ctdptr[Ascii] = &ctdata[0]; /* failsafe */ + + for (i = 0; i < num_codesets; i++) { + + codeset = codesets[i]; + num_charsets = codeset->num_charsets; + + for (j = 0; j < num_charsets; j++) { + + charset = codeset->charset_list[j]; + + for (ctdp = ctdata; ctdp <= ctd_endp; ctdp++) + + if (! strcmp(ctdp->name, charset->name)) { + + ctdptr[codeset->cs_num] = ctdp; + + ctdptr[codeset->cs_num]->wc_encoding = codeset->wc_encoding; + + ctdptr[codeset->cs_num]->set_size = + charset->set_size; + + ctdptr[codeset->cs_num]->min_ch = + charset->set_size == 94 && + (ctdptr[codeset->cs_num]->length > 1 || + ctdptr[codeset->cs_num]->side == XlcGR) ? 0x21 : 0x20; + + break; + } + } + } +} + + +static int +sjis_mbstocts( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + int ct_len = *to_left; + int cs_num; + int clen; + int unconv_num = 0; + int num_conv; + const char *inbufptr = *from; + char *ctptr = *to; + XPointer ct_base = ctptr; + + StateRec ct_state; + CTData charset = NULL; + XLCd lcd = (XLCd) conv->state; + int codeset_num = XLC_GENERIC(lcd, codeset_num); + +/* Initial State: */ + + ct_state.GL_charset = ctdptr[Ascii]; + ct_state.GR_charset = NULL; + + if (*from_left > *to_left) + *from_left = *to_left; + + for (;*from_left > 0; (*from_left) -= charset->length) { + + if (iskanji(*inbufptr)) { + if (KANJI_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + cs_num = Kanji; + charset = ctdptr[Kanji]; + if (!VALID_MULTIBYTE((Uchar) *(inbufptr+1))) + unconv_num++; + } + else if (isuserdef(*inbufptr)) { + if (USERDEF_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + cs_num = Userdef; + charset = ctdptr[Userdef]; + if (!VALID_MULTIBYTE((Uchar) *(inbufptr+1))) + unconv_num++; + } + else if (isascii(*inbufptr)) { + if (ASCII_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + cs_num = Ascii; + charset = ctdptr[Ascii]; + } + else if (iskana(*inbufptr)) { + if (KANA_CODESET >= codeset_num) { + unconv_num++; + (*from_left)--; + continue; + } + cs_num = Kana; + charset = ctdptr[Kana]; + } + else { /* unknown */ + unconv_num++; + (*from_left)--; + continue; + } + + if ( (charset->side == XlcGR && charset != ct_state.GR_charset) || + (charset->side == XlcGL && charset != ct_state.GL_charset) ) { + + ct_len -= ctdptr[cs_num]->ct_encoding_len; + if (ct_len < 0) { + unconv_num++; + break; + } + + if (ctptr) { + strcpy(ctptr, ctdptr[cs_num]->ct_encoding); + ctptr += ctdptr[cs_num]->ct_encoding_len; + } + } + + clen = charset->length; + do { + *ctptr++ = *inbufptr++; + } while (--clen); + + if (charset->length >= 2) { + sjis_to_jis((Uchar *)(ctptr-2), (Uchar *)(ctptr-1)); + if (BADCHAR(charset->min_ch, *(ctptr-2)) || + BADCHAR(charset->min_ch, *(ctptr-1))) { + unconv_num++; + continue; + } + } + else + if (BADCHAR(charset->min_ch, *(ctptr-1))) { + unconv_num++; + continue; + } + + if (charset->side == XlcGR) + ct_state.GR_charset = charset; + else if (charset->side == XlcGL) + ct_state.GL_charset = charset; + + if (charset->side == XlcGR) { + clen = charset->length; + do { + (*(Uchar *)(ctptr-clen)) = BIT8ON(*(Uchar *)(ctptr-clen)); + } while (--clen); + } + } + + *to = (XPointer)ctptr; + + if ((num_conv = (int)(ctptr - ct_base)) > 0) + (*to_left) -= num_conv; + + return unconv_num; + +} + + +#define byte1 (length == codeset->length - 1) +#define byte2 (byte1 == 0) + +static int +sjis_wcstocts( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + int ct_len = *to_left; + const wchar_t *inbufptr = (const wchar_t *) *from; + char *ctptr = *to; + XPointer ct_base = ctptr; + wchar_t wch; + int length; + Uchar tmp; + Uchar t1 = 0; + int num_conv; + + StateRec ct_state; + XLCd lcd = (XLCd)conv->state; + CTData charset; + CodeSet codeset; + int unconv_num = 0; + Ulong wc_shift = XLC_GENERIC(lcd, wc_shift_bits); + +/* Initial State: */ + ct_state.GL_charset = ctdptr[0]; /* Codeset 0 */ + ct_state.GR_charset = NULL; + + if (*from_left > *to_left) + *from_left = *to_left; + + for (; *from_left > 0 ; (*from_left)-- ) { + + wch = *inbufptr++; + + if (!(codeset = wc_codeset(lcd, wch))) { + unconv_num++; + (*from_left)--; + continue; + } + + charset = ctdptr[codeset->cs_num]; + + length = codeset->length; + wch ^= (wchar_t)codeset->wc_encoding; + + if ( (charset->side == XlcGR && charset != ct_state.GR_charset) || + (charset->side == XlcGL && charset != ct_state.GL_charset) ) { + + ct_len -= ctdptr[codeset->cs_num]->ct_encoding_len; + if (ct_len < 0) { + unconv_num++; + break; + } + + if (ctptr) { + strcpy(ctptr, ctdptr[codeset->cs_num]->ct_encoding); + ctptr += ctdptr[codeset->cs_num]->ct_encoding_len; + } + + } + + if (charset->side == XlcGR) + ct_state.GR_charset = charset; + else if (charset->side == XlcGL) + ct_state.GL_charset = charset; + + do { + length--; + tmp = wch>>(wchar_t)( (Ulong)length * wc_shift); + + if (kana) { + if (BADCHAR(charset->min_ch, (char)tmp)) { + unconv_num++; + break; + } + *ctptr++ = (char)BIT8ON(tmp); + } + + else if (byte1 && (kanji || userdef)) { + t1 = tmp; + } + + else if (byte2 && (kanji || userdef)) { + if (BADCHAR(charset->min_ch, (char)t1) || + BADCHAR(charset->min_ch, (char)tmp)) { + unconv_num++; + break; + } + + *ctptr++ = (char)BIT8OFF(t1); + *ctptr++ = (char)BIT8OFF(tmp); + } + + else { + if (BADCHAR(charset->min_ch, (char)tmp)) { + unconv_num++; + break; + } + *ctptr++ = (char)tmp; + } + } while (length); + + } /* end for */ + + *to = (XPointer)ctptr; + + if ((num_conv = (int)(ctptr - ct_base)) > 0) + (*to_left) -= num_conv; + + return unconv_num; +} +#undef byte1 +#undef byte2 + +#define SKIP_I(str) while (*(str) >= 0x20 && *(str) <= 0x2f) (str)++; +#define SKIP_P(str) while (*(str) >= 0x30 && *(str) <= 0x3f) (str)++; + +static int +sjis_ctstombs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + const char *inbufptr = *from; + XPointer outbufptr = *to; + const char *inbuf_base; + XPointer outbuf_base = outbufptr; + int clen, length; + int unconv_num = 0; + int num_conv; + unsigned int ct_seglen = 0; + Uchar ct_type; + CTData ctdp = ctdata; /* default */ + CTData GL_ctdp = ctdp; /* GL ctdp save */ + CTData GR_ctdp = ctdp; /* GR ctdp save */ + + if (*from_left > *to_left) + *from_left = *to_left; + + for (length = ctdata[Ascii].length; *from_left > 0 ; (*from_left) -= length) + { + ct_type = CT_STD; + /* change GL/GR charset */ + if(ctdp->side == XlcGR && isleftside(*inbufptr)){ + /* select GL side */ + ctdp = GL_ctdp; + length = ctdp->length; + ct_type = ctdp->ct_type; + }else if(ctdp->side == XlcGL && isrightside(*inbufptr)){ + /* select GR side */ + ctdp = GR_ctdp; + length = ctdp->length; + ct_type = ctdp->ct_type; + } + if (*inbufptr == '\033' || *inbufptr == (char)'\233') { + + for (ctdp = ctdata; ctdp <= ctd_endp ; ctdp++) { + + if(!strncmp(inbufptr, ctdp->ct_encoding, ctdp->ct_encoding_len)) + { + inbufptr += ctdp->ct_encoding_len; + (*from_left) -= ctdp->ct_encoding_len; + if( ctdp->length ) { + length = ctdp->length; + if( *from_left < length ) { + *to = (XPointer)outbufptr; + *to_left -= outbufptr - outbuf_base; + return( unconv_num + *from_left ); + } + } + ct_type = ctdp->ct_type; + if(ctdp->side == XlcGL){ + GL_ctdp = ctdp; /* save GL ctdp */ + }else{ + GR_ctdp = ctdp; /* save GR ctdp */ + } + break; + } + } + if (ctdp > ctd_endp) /* failed to match CT sequence */ + unconv_num++; + } + +/* The following code insures that non-standard encodings, direction, extension, + * and version strings are ignored; subject to change in future. + */ + switch (ct_type) { + case CT_STD: + break; + case CT_EXT2: + inbufptr++; + (*from_left)--; + case CT_NSTD: + ct_seglen = (BIT8OFF(*inbufptr) << 7) + BIT8OFF(*(inbufptr+1)) + 2; + inbufptr += ct_seglen; + (*from_left) -= ct_seglen; + continue; + case CT_EXT0: + inbuf_base = inbufptr; + SKIP_I(inbufptr); + inbufptr++; + ct_seglen = (unsigned)(inbufptr - inbuf_base); + (*from_left) -= ct_seglen; + continue; + case CT_EXT1: + inbuf_base = inbufptr; + SKIP_P(inbufptr); + SKIP_I(inbufptr); + inbufptr++; + ct_seglen = (unsigned)(inbufptr - inbuf_base); + (*from_left) -= ct_seglen; + continue; + case CT_DIR: + continue; + case CT_VER: + inbufptr += 2; + (*from_left) -= 2; + continue; + } + + if (ctdp->side == XlcGL || isrightside (*inbufptr)) { + clen = length; + } else { + clen = 1; + *from_left += length - clen; + } + do { + Uchar mask = (length == 2) ? GL : -1; + *outbufptr++ = *inbufptr++ & mask; + } while (--clen); + + if (length >= 2) + jis_to_sjis((Uchar *)(outbufptr-2), (Uchar *)(outbufptr-1)); + } + + *to = (XPointer)outbufptr; + + if ((num_conv = (int)(outbufptr - outbuf_base)) > 0) + (*to_left) -= num_conv; + + return unconv_num; +} + + +static int +sjis_ctstowcs( + XlcConv conv, + XPointer *from, + int *from_left, + XPointer *to, + int *to_left, + XPointer *args, + int num_args) +{ + XLCd lcd = (XLCd)conv->state; + Ulong wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits); + const char *inbufptr = *from; + const char *inbuf_base; + wchar_t *outbufptr = (wchar_t *) *to; + wchar_t *outbuf_base = outbufptr; + int clen, length; + int num_conv; + int unconv_num = 0; + unsigned int ct_seglen = 0; + Uchar ct_type = 0; + int shift_mult; + wchar_t wc_tmp; + wchar_t wch; + Ulong wc_encoding; + CTData ctdp = ctdata; + CTData GL_ctdp = ctdp; /* GL ctdp save */ + CTData GR_ctdp = ctdp; /* GR ctdp save */ + + if (*from_left > *to_left) + *from_left = *to_left; + + for (length = ctdata[Ascii].length; *from_left > 0; (*from_left) -= length ) + { + ct_type = CT_STD; + /* change GL/GR charset */ + if(ctdp->side == XlcGR && isleftside(*inbufptr)){ + /* select GL side */ + ctdp = GL_ctdp; + length = ctdp->length; + ct_type = ctdp->ct_type; + }else if(ctdp->side == XlcGL && isrightside(*inbufptr)){ + /* select GR side */ + ctdp = GR_ctdp; + length = ctdp->length; + ct_type = ctdp->ct_type; + } + if (*inbufptr == '\033' || *inbufptr == (char)'\233') { + for (ctdp = ctdata; ctdp <= ctd_endp ; ctdp++) { + + if(!strncmp(inbufptr, ctdp->ct_encoding, ctdp->ct_encoding_len)) + { + inbufptr += ctdp->ct_encoding_len; + (*from_left) -= ctdp->ct_encoding_len; + if( ctdp->length ) { + length = ctdp->length; + if( *from_left < length ) { + *to = (XPointer)outbufptr; + *to_left -= outbufptr - outbuf_base; + return( unconv_num + *from_left ); + } + } + ct_type = ctdp->ct_type; + if(ctdp->side == XlcGL){ + GL_ctdp = ctdp; /* save GL ctdp */ + }else{ + GR_ctdp = ctdp; /* save GR ctdp */ + } + break; + } + } + if (ctdp > ctd_endp) /* failed to match CT sequence */ + unconv_num++; + } + +/* The following block of code insures that non-standard encodings, direction, + * extension, and version strings are ignored; subject to change in future. + */ + switch (ct_type) { + case CT_STD: + break; + case CT_EXT2: + inbufptr++; + (*from_left)--; + case CT_NSTD: + ct_seglen = (BIT8OFF(*inbufptr) << 7) + BIT8OFF(*(inbufptr+1)) + 2; + inbufptr += ct_seglen; + (*from_left) -= ct_seglen; + continue; + case CT_EXT0: + inbuf_base = inbufptr; + SKIP_I(inbufptr); + inbufptr++; + ct_seglen = (unsigned)(inbufptr - inbuf_base); + (*from_left) -= ct_seglen; + continue; + case CT_EXT1: + inbuf_base = inbufptr; + SKIP_P(inbufptr); + SKIP_I(inbufptr); + inbufptr++; + ct_seglen = (unsigned)(inbufptr - inbuf_base); + (*from_left) -= ct_seglen; + continue; + case CT_DIR: + continue; + case CT_VER: + inbufptr += 2; + (*from_left) -= 2; + continue; + } +#if !defined(__sony_news) || defined(SVR4) + if (ctdp->side == XlcGL || isrightside (*inbufptr)) { + clen = length; + wc_encoding = ctdp->wc_encoding; + } else { + clen = 1; + *from_left += length - clen; + wc_encoding = ctdptr[Ascii]->wc_encoding; + } + shift_mult = clen - 1; + wch = (wchar_t)0; + + do { + wc_tmp = BIT8OFF(*inbufptr++) << (wc_shift_bits * shift_mult); + wch |= wc_tmp; + shift_mult--; + } while (--clen); + *outbufptr++ = wch | wc_encoding; +#else + if( length == 1 ) + *outbufptr++ = (unsigned char)*inbufptr++; + else if( length == 2 ) { + unsigned short code; + code = (*inbufptr << 8) | *(inbufptr+1); + *outbufptr++ = jis2sjis( code ); + inbufptr += 2; + } +#endif + } + *to = (XPointer)outbufptr; + + if ((num_conv = (int)(outbufptr - outbuf_base)) > 0) + (*to_left) -= num_conv ; + + return unconv_num; + +} +#undef BADCHAR + +static void +close_converter( + XlcConv conv) +{ + Xfree((char *) conv); +} + + +static XlcConv +create_conv( + XLCd lcd, + XlcConvMethods methods) +{ + XlcConv conv; + + conv = (XlcConv) Xmalloc(sizeof(XlcConvRec)); + if (conv == NULL) + return (XlcConv) NULL; + + conv->methods = methods; + conv->state = (XPointer) lcd; + return conv; +} + + +enum { MBSTOCS, WCSTOCS, MBTOCS, CSTOMBS, CSTOWCS, MBSTOWCS, WCSTOMBS, + WCSTOCTS, MBSTOCTS, CTSTOMBS, CTSTOWCS }; + +static XlcConvMethodsRec conv_methods[] = { + {close_converter, sjis_mbstocs, NULL }, + {close_converter, sjis_wcstocs, NULL }, + {close_converter, sjis_mbtocs, NULL }, + {close_converter, sjis_cstombs, NULL }, + {close_converter, sjis_cstowcs, NULL }, + {close_converter, sjis_mbstowcs, NULL }, + {close_converter, sjis_wcstombs, NULL }, + {close_converter, sjis_wcstocts, NULL }, + {close_converter, sjis_mbstocts, NULL }, + {close_converter, sjis_ctstombs, NULL }, + {close_converter, sjis_ctstowcs, NULL }, +}; + + +static XlcConv +open_mbstocs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[MBSTOCS]); +} + +static XlcConv +open_wcstocs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[WCSTOCS]); +} + +static XlcConv +open_mbtocs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[MBTOCS]); +} + +static XlcConv +open_cstombs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[CSTOMBS]); +} + +static XlcConv +open_cstowcs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[CSTOWCS]); +} + +static XlcConv +open_mbstowcs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[MBSTOWCS]); +} + +static XlcConv +open_wcstombs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[WCSTOMBS]); +} + +static XlcConv +open_wcstocts( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[WCSTOCTS]); +} + +static XlcConv +open_mbstocts( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[MBSTOCTS]); +} + +static XlcConv +open_ctstombs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[CTSTOMBS]); +} + +static XlcConv +open_ctstowcs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_conv(from_lcd, &conv_methods[CTSTOWCS]); +} + +XLCd +_XlcSjisLoader( + const char *name) +{ + XLCd lcd; + + lcd = _XlcCreateLC(name, _XlcGenericMethods); + if (lcd == NULL) + return lcd; + + if (!XLC_PUBLIC_PART(lcd)->codeset || + (_XlcCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "SJIS"))) { + _XlcDestroyLC(lcd); + return (XLCd) NULL; + } + + initCTptr(lcd); + + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs); + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs); + _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs); + _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs); + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbtocs); + +#ifndef FORCE_INDIRECT_CONVERTER + _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte, open_ctstombs); + _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar, open_ctstowcs); + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCompoundText, open_mbstocts); + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs); + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCompoundText, open_wcstocts); + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs); +#endif + + _XlcAddUtf8Converters(lcd); + + return lcd; +} + +#else +typedef int dummy; +#endif /* X_LOCALE */ |