#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]
#define CS1 codesets[1]
#define CS2 codesets[2]
#define CS3 codesets[3]
#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
#define GL 0x7f
#define isleftside(c) (((c) & GR) ? 0 : 1)
#define isrightside(c) (!isleftside(c))
typedef unsigned char Uchar;
typedef unsigned long Ulong;
typedef unsigned int Uint;
#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
#ifndef iskana
#define iskana(c) (0xa1<=((Uchar)c) && ((Uchar)c)<=0xdf)
#endif
#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);
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 {
unconv_num++;
(*from_left)--;
continue;
}
} else {
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;
}
}
*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);
}
*to = (XPointer)outbufptr;
if ((num_conv = (int)(outbufptr - outbuf_base)) > 0)
(*to_left) -= num_conv;
return unconv_num;
}
#undef byte1
#undef byte2
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)))
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)))
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
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;
tmp_args[0] = (XPointer) &charset;
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;
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)
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;
}
#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 },
};
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
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];
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);
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 {
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);
ct_state.GL_charset = ctdptr[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);
}
*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;
CTData GL_ctdp = ctdp;
CTData GR_ctdp = ctdp;
if (*from_left > *to_left)
*from_left = *to_left;
for (length = ctdata[Ascii].length; *from_left > 0 ; (*from_left) -= length)
{
ct_type = CT_STD;
if(ctdp->side == XlcGR && isleftside(*inbufptr)){
ctdp = GL_ctdp;
length = ctdp->length;
ct_type = ctdp->ct_type;
}else if(ctdp->side == XlcGL && isrightside(*inbufptr)){
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;
}else{
GR_ctdp = ctdp;
}
break;
}
}
if (ctdp > ctd_endp)
unconv_num++;
}
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;
CTData GR_ctdp = ctdp;
if (*from_left > *to_left)
*from_left = *to_left;
for (length = ctdata[Ascii].length; *from_left > 0; (*from_left) -= length )
{
ct_type = CT_STD;
if(ctdp->side == XlcGR && isleftside(*inbufptr)){
ctdp = GL_ctdp;
length = ctdp->length;
ct_type = ctdp->ct_type;
}else if(ctdp->side == XlcGL && isrightside(*inbufptr)){
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;
}else{
GR_ctdp = ctdp;
}
break;
}
}
if (ctdp > ctd_endp)
unconv_num++;
}
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