diff -urN libX11-1.0.3.orig/modules/lc/Utf8/lcUTF8Load.c libX11-1.0.3/modules/lc/Utf8/lcUTF8Load.c --- libX11-1.0.3.orig/modules/lc/Utf8/lcUTF8Load.c 2006-06-23 06:22:22.000000000 +0900 +++ libX11-1.0.3/modules/lc/Utf8/lcUTF8Load.c 2006-12-07 14:22:54.000000000 +0900 @@ -50,15 +50,22 @@ if (lcd == (XLCd) NULL) return lcd; - /* The official IANA name for UTF-8 is "UTF-8" in upper case with a dash. */ - if (!XLC_PUBLIC_PART(lcd)->codeset || - (_XlcCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "UTF-8"))) { - _XlcDestroyLC(lcd); - return (XLCd) NULL; + /* The official IANA name for UTF-8 is "UTF-8" in upper case with a dash. */ if (!XLC_PUBLIC_PART(lcd)->codeset) { + _XlcDestroyLC(lcd); + return (XLCd) NULL; } - _XlcAddUtf8LocaleConverters(lcd); - _XlcAddUtf8Converters(lcd); + /* This loader only supports "UTF-8" and "GB18030" codeset */ + if (!_XlcCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "GB18030")) { + _XlcAddGB18030LocaleConverters(lcd); + _XlcAddUtf8Converters(lcd); + } else if (!_XlcCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "UTF-8")) { + _XlcAddUtf8LocaleConverters(lcd); + _XlcAddUtf8Converters(lcd); + } else { + _XlcDestroyLC(lcd); + return (XLCd) NULL; + } return lcd; } diff -urN libX11-1.0.3.orig/src/xlibi18n/lcUTF8.c libX11-1.0.3/src/xlibi18n/lcUTF8.c --- libX11-1.0.3.orig/src/xlibi18n/lcUTF8.c 2006-06-23 06:22:23.000000000 +0900 +++ libX11-1.0.3/src/xlibi18n/lcUTF8.c 2006-12-07 03:52:32.000000000 +0900 @@ -1842,3 +1842,614 @@ _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNFontCharSet, open_utf8tofcs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNFontCharSet, open_wcstofcs); } + +/* ========================== iconv Stuff ================================ */ + +/* from XlcNCharSet to XlcNMultiByte */ + +static int +iconv_cstombs(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + XlcCharSet charset; + char *name; + Utf8Conv convptr; + int i; + unsigned char const *src; + unsigned char const *srcend; + unsigned char *dst; + unsigned char *dstend; + int unconv_num; + + if (from == NULL || *from == NULL) + return 0; + + if (num_args < 1) + return -1; + + charset = (XlcCharSet) args[0]; + name = charset->encoding_name; + /* not charset->name because the latter has a ":GL"/":GR" suffix */ + + for (convptr = all_charsets, i = all_charsets_count-1; i > 0; convptr++, i--) + if (!strcmp(convptr->name, name)) + break; + if (i == 0) + return -1; + + src = (unsigned char const *) *from; + srcend = src + *from_left; + dst = (unsigned char *) *to; + dstend = dst + *to_left; + unconv_num = 0; + + while (src < srcend) { + ucs4_t wc; + int consumed; + int count; + + consumed = convptr->cstowc(conv, &wc, src, srcend-src); + if (consumed == RET_ILSEQ) + return -1; + if (consumed == RET_TOOFEW(0)) + break; + + /* Use stdc iconv to convert widechar -> multibyte */ + + count = wctomb(dst, wc); + if (count == 0) + break; + if (count == -1) { + count = wctomb(dst, BAD_WCHAR); + if (count == 0) + break; + unconv_num++; + } + src += consumed; + dst += count; + } + + *from = (XPointer) src; + *from_left = srcend - src; + *to = (XPointer) dst; + *to_left = dstend - dst; + + return unconv_num; + +} + +static XlcConvMethodsRec iconv_cstombs_methods = { + close_converter, + iconv_cstombs, + NULL +}; + +static XlcConv +open_iconv_cstombs(from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + lazy_init_all_charsets(); + return create_conv(from_lcd, &iconv_cstombs_methods); +} + +static int +iconv_mbstocs(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + Utf8Conv *preferred_charsets; + XlcCharSet last_charset = NULL; + unsigned char const *src; + unsigned char const *srcend; + unsigned char *dst; + unsigned char *dstend; + int unconv_num; + + if (from == NULL || *from == NULL) + return 0; + + preferred_charsets = (Utf8Conv *) conv->state; + src = (unsigned char const *) *from; + srcend = src + *from_left; + dst = (unsigned char *) *to; + dstend = dst + *to_left; + unconv_num = 0; + + while (src < srcend && dst < dstend) { + Utf8Conv chosen_charset = NULL; + XlcSide chosen_side = XlcNONE; + wchar_t wc; + int consumed; + int count; + + /* Uses stdc iconv to convert multibyte -> widechar */ + + consumed = mbtowc(&wc, src, srcend-src); + if (consumed == 0) + break; + if (consumed == -1) { + src++; + unconv_num++; + continue; + } + + count = charset_wctocs(preferred_charsets, &chosen_charset, &chosen_side, conv, dst, wc, dstend-dst); + + if (count == RET_TOOSMALL) + break; + if (count == RET_ILSEQ) { + src += consumed; + unconv_num++; + continue; + } + + if (last_charset == NULL) { + last_charset = + _XlcGetCharSetWithSide(chosen_charset->name, chosen_side); + if (last_charset == NULL) { + src += consumed; + unconv_num++; + continue; + } + } else { + if (!(last_charset->xrm_encoding_name == chosen_charset->xrm_name + && (last_charset->side == XlcGLGR + || last_charset->side == chosen_side))) + break; + } + src += consumed; + dst += count; + } + + if (last_charset == NULL) + return -1; + + *from = (XPointer) src; + *from_left = srcend - src; + *to = (XPointer) dst; + *to_left = dstend - dst; + + if (num_args >= 1) + *((XlcCharSet *)args[0]) = last_charset; + + return unconv_num; +} + +static XlcConvMethodsRec iconv_mbstocs_methods = { + close_tocs_converter, + iconv_mbstocs, + NULL +}; + +static XlcConv +open_iconv_mbstocs(from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + return create_tocs_conv(from_lcd, &iconv_mbstocs_methods); +} + +/* from XlcNMultiByte to XlcNChar */ + +static int +iconv_mbtocs(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + Utf8Conv *preferred_charsets; + XlcCharSet last_charset = NULL; + unsigned char const *src; + unsigned char const *srcend; + unsigned char *dst; + unsigned char *dstend; + int unconv_num; + + if (from == NULL || *from == NULL) + return 0; + + preferred_charsets = (Utf8Conv *) conv->state; + src = (unsigned char const *) *from; + srcend = src + *from_left; + dst = (unsigned char *) *to; + dstend = dst + *to_left; + unconv_num = 0; + + while (src < srcend && dst < dstend) { + Utf8Conv chosen_charset = NULL; + XlcSide chosen_side = XlcNONE; + wchar_t wc; + int consumed; + int count; + + /* Uses stdc iconv to convert multibyte -> widechar */ + + consumed = mbtowc(&wc, src, srcend-src); + if (consumed == 0) + break; + if (consumed == -1) { + src++; + unconv_num++; + continue; + } + + count = charset_wctocs(preferred_charsets, &chosen_charset, &chosen_side, conv, dst, wc, dstend-dst); + if (count == RET_TOOSMALL) + break; + if (count == RET_ILSEQ) { + src += consumed; + unconv_num++; + continue; + } + + if (last_charset == NULL) { + last_charset = + _XlcGetCharSetWithSide(chosen_charset->name, chosen_side); + if (last_charset == NULL) { + src += consumed; + unconv_num++; + continue; + } + } else { + if (!(last_charset->xrm_encoding_name == chosen_charset->xrm_name + && (last_charset->side == XlcGLGR + || last_charset->side == chosen_side))) + break; + } + src += consumed; + dst += count; + } + + if (last_charset == NULL) + return -1; + + *from = (XPointer) src; + *from_left = srcend - src; + *to = (XPointer) dst; + *to_left = dstend - dst; + + if (num_args >= 1) + *((XlcCharSet *)args[0]) = last_charset; + + return unconv_num; +} + +static XlcConvMethodsRec iconv_mbtocs_methods = { + close_tocs_converter, + iconv_mbtocs, + NULL +}; + +static XlcConv +open_iconv_mbtocs (from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + return create_tocs_conv(from_lcd, &iconv_mbtocs_methods ); +} + +/* from XlcNMultiByte to XlcNString */ + +static int +iconv_mbstostr(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + unsigned char const *src; + unsigned char const *srcend; + unsigned char *dst; + unsigned char *dstend; + int unconv_num; + + if (from == NULL || *from == NULL) + return 0; + + src = (unsigned char const *) *from; + srcend = src + *from_left; + dst = (unsigned char *) *to; + dstend = dst + *to_left; + unconv_num = 0; + + while (src < srcend) { + unsigned char c; + wchar_t wc; + int consumed; + + /* Uses stdc iconv to convert multibyte -> widechar */ + + consumed = mbtowc(&wc, src, srcend-src); + if (consumed == 0) + break; + if (dst == dstend) + break; + if (consumed == -1) { + consumed = 1; + c = BAD_CHAR; + unconv_num++; + } else { + if ((wc & ~(wchar_t)0xff) != 0) { + c = BAD_CHAR; + unconv_num++; + } else + c = (unsigned char) wc; + } + *dst++ = c; + src += consumed; + } + + *from = (XPointer) src; + *from_left = srcend - src; + *to = (XPointer) dst; + *to_left = dstend - dst; + + return unconv_num; +} + +static XlcConvMethodsRec iconv_mbstostr_methods = { + close_converter, + iconv_mbstostr, + NULL +}; + +static XlcConv +open_iconv_mbstostr(from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + return create_conv(from_lcd, &iconv_mbstostr_methods); +} + +/* from XlcNString to XlcNMultiByte */ +static int +iconv_strtombs(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + unsigned char const *src; + unsigned char const *srcend; + unsigned char *dst; + unsigned char *dstend; + + if (from == NULL || *from == NULL) + return 0; + + src = (unsigned char const *) *from; + srcend = src + *from_left; + dst = (unsigned char *) *to; + dstend = dst + *to_left; + + while (src < srcend) { + int count = wctomb(dst, *src); + if (count < 0) + break; + dst += count; + src++; + } + + *from = (XPointer) src; + *from_left = srcend - src; + *to = (XPointer) dst; + *to_left = dstend - dst; + + return 0; +} + +static XlcConvMethodsRec iconv_strtombs_methods= { + close_converter, + iconv_strtombs, + NULL +}; + +static XlcConv +open_iconv_strtombs(from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + return create_conv(from_lcd, &iconv_strtombs_methods); +} + +/***************************************************************************/ +/* Part II: An iconv locale loader. + * + *Here we can assume that "multi-byte" is iconv and that `wchar_t' is Unicode. + */ + +/* from XlcNMultiByte to XlcNWideChar */ +static int +iconv_mbstowcs(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + char *src = *((char **) from); + wchar_t *dst = *((wchar_t **) to); + int src_left = *from_left; + int dst_left = *to_left; + int length, unconv_num = 0; + + while (src_left > 0 && dst_left > 0) { + length = mbtowc(dst, src, src_left); + + if (length > 0) { + src += length; + src_left -= length; + if (dst) + dst++; + dst_left--; + } else if (length < 0) { + src++; + src_left--; + unconv_num++; + } else { + /* null ? */ + src++; + src_left--; + if (dst) + *dst++ = L'\0'; + dst_left--; + } + } + + *from = (XPointer) src; + if (dst) + *to = (XPointer) dst; + *from_left = src_left; + *to_left = dst_left; + + return unconv_num; +} + +static XlcConvMethodsRec iconv_mbstowcs_methods = { + close_converter, + iconv_mbstowcs, + NULL +} ; + +static XlcConv +open_iconv_mbstowcs(from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + return create_conv(from_lcd, &iconv_mbstowcs_methods); +} + +static int +iconv_wcstombs(conv, from, from_left, to, to_left, args, num_args) + XlcConv conv; + XPointer *from; + int *from_left; + XPointer *to; + int *to_left; + XPointer *args; + int num_args; +{ + wchar_t *src = *((wchar_t **) from); + char *dst = *((char **) to); + int src_left = *from_left; + int dst_left = *to_left; + int length, unconv_num = 0; + + while (src_left > 0 && dst_left >= MB_CUR_MAX) { + length = wctomb(dst, *src); /* XXX */ + + if (length > 0) { + src++; + src_left--; + if (dst) + dst += length; + dst_left -= length; + } else if (length < 0) { + src++; + src_left--; + unconv_num++; + } + } + + *from = (XPointer) src; + if (dst) + *to = (XPointer) dst; + *from_left = src_left; + *to_left = dst_left; + + return unconv_num; +} + +static XlcConvMethodsRec iconv_wcstombs_methods = { + close_converter, + iconv_wcstombs, + NULL +} ; + +static XlcConv +open_iconv_wcstombs(from_lcd, from_type, to_lcd, to_type) + XLCd from_lcd; + char *from_type; + XLCd to_lcd; + char *to_type; +{ + return create_conv(from_lcd, &iconv_wcstombs_methods); +} + +static XlcConv +open_iconv_mbstofcs( + XLCd from_lcd, + const char *from_type, + XLCd to_lcd, + const char *to_type) +{ + return create_tofontcs_conv(from_lcd, &iconv_mbstocs_methods); +} + +void +_XlcAddGB18030LocaleConverters( + XLCd lcd) +{ + + /* Register elementary converters. */ + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_iconv_mbstowcs); + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_iconv_wcstombs); + + /* Register converters for XlcNCharSet. This implicitly provides + * converters from and to XlcNCompoundText. */ + + _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_iconv_cstombs); + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_iconv_mbstocs); + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_iconv_mbtocs); + _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_iconv_strtombs); + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_iconv_mbstostr); + + /* Register converters for XlcNFontCharSet */ + _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNFontCharSet, open_iconv_mbstofcs); + + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr); + _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_strtowcs); + _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs); + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs); + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNChar, open_wcstocs1); + + /* Register converters for XlcNFontCharSet */ + _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNFontCharSet, open_wcstofcs); +} +