/* $Xorg: lcGenConv.c,v 1.5 2000/08/17 19:45:17 cpqbld Exp $ */ /* * Copyright 1992, 1993 by TOSHIBA Corp. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, 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 TOSHIBA not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. TOSHIBA make no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * TOSHIBA 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. * * Author: Katsuhisa Yano TOSHIBA Corp. * mopi@osa.ilab.toshiba.co.jp */ /* * (c) Copyright 1995 FUJITSU LIMITED * This is source code modified by FUJITSU LIMITED under the Joint * Development Agreement for the CDE/Motif PST. * * Modifier: Masayoshi Shimamura FUJITSU LIMITED * */ /* * 2000 * Modifier: Ivan Pascal The XFree86 Project */ /* $XFree86: xc/lib/X11/lcGenConv.c,v 3.27tsi Exp $ */ /* * A generic locale loader for all kinds of ISO-2022 based codesets. * Supports: all locales. * How: Provides generic converters for ISO-2022 based codesets. Extensible as * far as ISO-2022 is extensible: codesets can be given by name in the * stream. Overall distinction between GL (0x00..0x7f) and GR (0x80..0xff). * In every chunk between escape sequences, the number of bytes per * character (char_size) is constant. * Platforms: all systems. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "Xlibint.h" #include "XlcGeneric.h" #include <stdio.h> #if !defined(macII) && !defined(Lynx_22) && !defined(X_LOCALE) #define STDCVT #endif typedef struct _CTDataRec { char *name; char *encoding; /* Compound Text encoding */ } CTDataRec, *CTData; static CTDataRec directionality_data[] = { { "BEGIN_LEFT-TO-RIGHT_TEXT", "\2331]" }, { "BEGIN_RIGHT-TO-LEFT_TEXT", "\2332]" }, { "END_OF_STRING", "\233]" }, }; typedef struct _StateRec { XLCd lcd; /* CT state */ XlcCharSet charset; /* charset of current state */ XlcCharSet GL_charset; /* charset of initial state in GL */ XlcCharSet GR_charset; /* charset of initial state in GR */ /* MB shift state */ CodeSet GL_codeset; CodeSet GR_codeset; } StateRec, *State; #define GR 0x80 /* begins right-side (non-ascii) region */ #define GL 0x7f /* ends left-side (ascii) region */ #define ESC 0x1b #define CSI 0x9b #define STX 0x02 #define isrightside(c) ((c) & GR) #define isleftside(c) (!isrightside(c)) /* Forward declarations for local routines. */ static int mbstocts (XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args); static int ctstombs (XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args); static int cstombs (XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args); /* ------------------------------------------------------------------------- */ /* Misc */ /* ------------------------------------------------------------------------- */ static int compare( const char *src, const char *encoding, int length) { const char *start = src; while (length-- > 0) { if (*src++ != *encoding++) return 0; if (*encoding == '\0') return src - start; } return 0; } static unsigned long conv_to_dest( Conversion conv, unsigned long code) { int i; int conv_num = conv->conv_num; FontScope convlist = conv->convlist; for (i = 0; i < conv_num; i++) { if (convlist[i].start <= code && code <= convlist[i].end) { switch (convlist[i].shift_direction) { case '+': return(code + convlist[i].shift); case '-': return(code - convlist[i].shift); default: return(code); } } } return(code); } static unsigned long conv_to_source( Conversion conv, unsigned long code) { int i; int conv_num; FontScope convlist; unsigned long start_p; unsigned long start_m; unsigned long end_p; unsigned long end_m; if (!conv) return(code); conv_num = conv->conv_num; convlist = conv->convlist; for (i = 0; i < conv_num; i++) { switch (convlist[i].shift_direction) { case '+': start_p = convlist[i].start + convlist[i].shift; end_p = convlist[i].end + convlist[i].shift; if (start_p <= code && code <= end_p) return(code - convlist[i].shift); break; case '-': start_m = convlist[i].start - convlist[i].shift; end_m = convlist[i].end - convlist[i].shift; if (start_m <= code && code <= end_m) return(code + convlist[i].shift); break; default: continue; } } return(code); } static unsigned long mb_to_gi( unsigned long mb, CodeSet codeset) { int i; unsigned long mb_tmp, mask = 0; if (codeset->mbconv) { mb_tmp = conv_to_dest(codeset->mbconv, mb); if (mb_tmp != mb) return(mb_tmp); } if (codeset->side == XlcC0 || codeset->side == XlcGL || codeset->side == XlcC1 || codeset->side == XlcGR) { for (i = 0; i < codeset->length; i++) mask = (mask << 8) | GL; mb = mb & mask; } return(mb); } static unsigned long gi_to_mb( unsigned long glyph_index, CodeSet codeset) { int i; unsigned long mask = 0; if (codeset->side == XlcC1 || codeset->side == XlcGR) { for (i = 0; i < codeset->length; i++) mask = (mask << 8) | GR; glyph_index = glyph_index | mask; } if (codeset->mbconv) return( conv_to_source(codeset->mbconv, glyph_index) ); return(glyph_index); } static Bool gi_to_wc( XLCd lcd, unsigned long glyph_index, CodeSet codeset, wchar_t *wc) { unsigned char mask = 0; unsigned long wc_encoding = codeset->wc_encoding; int length = codeset->length; unsigned long wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits); mask = (1 << wc_shift_bits) - 1 ; for (*wc = 0, length--; length >= 0; length--) *wc = (*wc << wc_shift_bits) | ((glyph_index >> (length * 8 )) & mask); *wc = *wc | wc_encoding; return(True); } static Bool wc_to_gi( XLCd lcd, wchar_t wc, unsigned long *glyph_index, CodeSet *codeset) { int i; unsigned char mask = 0; unsigned long wc_encoding; unsigned long wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask); unsigned long wc_shift_bits = XLC_GENERIC(lcd, wc_shift_bits); int codeset_num = XLC_GENERIC(lcd, codeset_num); CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list); wc_encoding = wc & wc_encode_mask; for (*codeset = NULL, i = 0; i < codeset_num; i++) { if (wc_encoding == codeset_list[i]->wc_encoding) { *codeset = codeset_list[i]; break; } } if (*codeset == NULL) return(False); mask = (1 << wc_shift_bits) - 1 ; wc = wc & ~wc_encode_mask; for (*glyph_index = 0, i = (*codeset)->length - 1; i >= 0; i--) *glyph_index = (*glyph_index << 8) | ( ((unsigned long)wc >> (i * wc_shift_bits)) & mask ); return(True); } static CodeSet mb_parse_codeset( State state, int num, const char **inbufptr, int *from_left) { int len; int from_len = (*from_left) + 1; const char *src = (*inbufptr) - 1; ParseInfo *mb_parse_list = XLC_GENERIC(state->lcd, mb_parse_list); ParseInfo parse_info; CodeSet codeset; for (--num ; (parse_info = mb_parse_list[num]) != NULL; num++) { len = compare(src, parse_info->encoding, from_len); if (len > 0) { codeset = parse_info->codeset; if (parse_info->type == E_LSL) state->GL_codeset = codeset; else if (parse_info->type == E_LSR) state->GR_codeset = codeset; --len; *inbufptr += len; *from_left -= len; return codeset; } } return (CodeSet) NULL; } static CodeSet byteM_parse_codeset( XLCd lcd, const char *inbufptr) { unsigned char ch; CodeSet codeset; ByteInfoList byteM; ByteInfoListRec byteM_rec; ByteInfo byteinfo; ByteInfoRec byteinfo_rec; Bool hit = False; int i, j, k; int codeset_num = XLC_GENERIC(lcd, codeset_num); CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list); for (i = 0; i < codeset_num; i++) { codeset = codeset_list[i]; byteM = codeset->byteM; if (codeset->side != XlcNONE || byteM == NULL) continue; for (j = 0; j < codeset->length; j++) { ch = *((unsigned char *)(inbufptr + j)); byteM_rec = byteM[j]; byteinfo = byteM_rec.byteinfo; for (hit = False, k = 0; k < byteM_rec.byteinfo_num; k++) { byteinfo_rec = byteinfo[k]; if (byteinfo_rec.start <= ch && ch <= byteinfo_rec.end) { hit = True; break; } } if (!hit) break; } if (hit) return(codeset); } return(NULL); } #define GLGR_parse_codeset(ch) \ (isrightside(ch) ? (state->GR_codeset) : \ (state->GL_codeset) ) static XlcCharSet gi_parse_charset( unsigned long glyph_index, CodeSet codeset) { int i; XlcCharSet *charset_list = codeset->charset_list; int num_charsets = codeset->num_charsets; ExtdSegment ctextseg = codeset->ctextseg; XlcCharSet charset = NULL; int area_num; FontScope area; /* lockup ct sequence */ for (i = 0; i < num_charsets; i++) { charset = charset_list[i]; if (*charset->ct_sequence != '\0') break; } if (i >= num_charsets) return(NULL); if (charset->source != CSsrcStd) return (charset); if (!ctextseg) return(charset); area = ctextseg->area; area_num = ctextseg->area_num; for (i = 0; i < area_num; i++) { if (area[i].start <= glyph_index && glyph_index <= area[i].end) { charset = ctextseg->charset; if (*charset->ct_sequence == '\0') return(NULL); break; } } return(charset); } static Bool ct_parse_csi( const char *inbufptr, int *ctr_seq_len) { int i; int num = sizeof(directionality_data) / sizeof(directionality_data[0]); for (i = 0; i < num; i++) { if ( !(*ctr_seq_len = strlen(directionality_data[i].encoding)) ) continue; if ( strncmp(inbufptr, directionality_data[i].encoding, *ctr_seq_len) == 0) return(True); } return(False); } static int cmp_esc_sequence( const char *inbufptr, XlcCharSet charset) { int seq_len, name_len, total_len; unsigned char byte_m, byte_l; const char *ct_sequence = charset->ct_sequence; const char *encoding_name = charset->encoding_name; /* check esc sequence */ if ( !(seq_len = strlen(ct_sequence) ) ) return(0); if ( strncmp(inbufptr, ct_sequence, seq_len) != 0) return(0); /* Standard Character Set Encoding ? */ if (charset->source == CSsrcStd) return(seq_len); /* * Non-Standard Character Set Encoding * * +--- ---+-----+-----+-----+---- ----+-----+-----+------- ------+ * | ctseq | M | L | encoding name | STX | contents | * +--- ---+-----+-----+-----+---- ----+-----+-----+------- ------+ * 4bytes 1byte 1byte variable length 1byte variable length * | | * +----------------------------------------------+ * rest length = ((M - 128) * 128) + (L - 128) */ /* get length of encoding name */ inbufptr += seq_len; byte_m = *inbufptr++; byte_l = *inbufptr++; name_len = strlen(encoding_name); if (((byte_m - 128) * 128 + (byte_l - 128) - 1) < name_len) return(0); if ( _XlcNCompareISOLatin1(inbufptr, encoding_name, name_len) != 0 ) return(0); /* check STX (Start of Text) */ inbufptr = inbufptr + name_len; if ( *inbufptr != STX ) return(0); total_len = seq_len + name_len + 3; return(total_len); } static Bool ct_parse_charset( XLCd lcd, const char *inbufptr, XlcCharSet *charset, int *ctr_seq_len) { int i, j; ExtdSegment ctextseg; int num_charsets; XlcCharSet *charset_list; CodeSet codeset; int codeset_num = XLC_GENERIC(lcd, codeset_num); CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list); int segment_conv_num = XLC_GENERIC(lcd, segment_conv_num); SegConv segment_conv = XLC_GENERIC(lcd, segment_conv); /* get charset from XLC_XLOCALE by escape sequence */ for (i = 0; i < codeset_num; i++) { codeset = codeset_list[i]; num_charsets = codeset->num_charsets; charset_list = codeset->charset_list; ctextseg = codeset->ctextseg; for (j = 0; j < num_charsets; j++) { *charset = charset_list[j]; if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset))) return(True); } if (ctextseg) { *charset = ctextseg->charset; if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset))) return(True); } } /* get charset from XLC_SEGMENTCONVERSION by escape sequence */ if (!segment_conv) return(False); for (i = 0; i < segment_conv_num; i++) { *charset = segment_conv[i].source; if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset))) return(True); *charset = segment_conv[i].dest; if ((*ctr_seq_len = cmp_esc_sequence(inbufptr, *charset))) return(True); } return(False); } static Bool segment_conversion( XLCd lcd, XlcCharSet *charset, unsigned long *glyph_index) { int i; int segment_conv_num = XLC_GENERIC(lcd, segment_conv_num); SegConv segment_conv = XLC_GENERIC(lcd, segment_conv); FontScopeRec range; ConversionRec conv_rec; if (!segment_conv) return(True); for (i = 0; i < segment_conv_num; i++) { if (segment_conv[i].source == *charset) break; } if (i >= segment_conv_num) return(True); range = segment_conv[i].range; if (*glyph_index < range.start || range.end < *glyph_index) return(True); *charset = segment_conv[i].dest; conv_rec.conv_num = segment_conv[i].conv_num; conv_rec.convlist = segment_conv[i].conv; *glyph_index = conv_to_dest(&conv_rec, *glyph_index); return(True); } static CodeSet _XlcGetCodeSetFromName( XLCd lcd, const char *name) { int i, j; XlcCharSet charset; int num_charsets; XlcCharSet *charset_list; CodeSet codeset; int codeset_num = XLC_GENERIC(lcd, codeset_num); CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list); for (i = 0; i < codeset_num; i++) { codeset = codeset_list[i]; num_charsets = codeset->num_charsets; charset_list = codeset->charset_list; for (j = 0; j < num_charsets; j++) { charset = charset_list[j]; if (!strlen(charset->name)) continue; if ( strcmp(charset->name, name) == 0) return(codeset); } } return(NULL); } static Bool _XlcGetCodeSetFromCharSet( XLCd lcd, XlcCharSet charset, CodeSet *codeset, unsigned long *glyph_index) { int j, num; CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list); XlcCharSet *charset_list; int codeset_num, num_charsets; Conversion ctconv; unsigned long glyph_index_tmp = 0; ExtdSegment ctextseg; codeset_num = XLC_GENERIC(lcd, codeset_num); for (num = 0 ; num < codeset_num; num++) { *codeset = codeset_list[num]; ctconv = (*codeset)->ctconv; ctextseg = (*codeset)->ctextseg; num_charsets = (*codeset)->num_charsets; charset_list = (*codeset)->charset_list; glyph_index_tmp = conv_to_source(ctconv, *glyph_index); if (charset->source == CSsrcStd) { /* Standard Character Set Encoding */ if (glyph_index_tmp == *glyph_index) { for (j = 0; j < num_charsets; j++) { if (charset_list[j] == charset) { goto end_loop; } } } } else { /* Non-Standard Character Set Encoding */ for (j = 0; j < num_charsets; j++) { if (charset_list[j] == charset) { goto end_loop; } } if (glyph_index_tmp != *glyph_index) { if (ctextseg && ctextseg->charset == charset) { goto end_loop; } } } } end_loop: if (num < codeset_num) { *glyph_index = glyph_index_tmp; return(True); } return(False); } #define check_string_encoding(codeset) (codeset->string_encoding) static void output_ulong_value( char *outbufptr, unsigned long code, int length, XlcSide side) { int i; for (i = (length - 1) * 8; i >= 0; i -= 8) { *outbufptr = ( code >> i) & 0xff; if (side == XlcC0 || side == XlcGL) { *outbufptr = *outbufptr & GL; } else if (side == XlcC1 || side == XlcGR) { *outbufptr = *outbufptr | GR; } outbufptr++; } } /* -------------------------------------------------------------------------- */ /* Init */ /* -------------------------------------------------------------------------- */ static XlcCharSet default_GL_charset = 0; static XlcCharSet default_GR_charset = 0; static void init_state( XlcConv conv) { State state = (State) conv->state; /* for CT */ state->charset = NULL; state->GL_charset = default_GL_charset; state->GR_charset = default_GR_charset; /* for MB shift state */ state->GL_codeset = XLC_GENERIC(state->lcd, initial_state_GL); state->GR_codeset = XLC_GENERIC(state->lcd, initial_state_GR); } /* -------------------------------------------------------------------------- */ /* Convert */ /* -------------------------------------------------------------------------- */ static int mbstowcs_org( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned char ch; unsigned long mb = 0; wchar_t wc; int length = 0, len_left = 0; int unconv_num = 0; int num; CodeSet codeset = NULL; const char *inbufptr = *from; wchar_t *outbufptr = (wchar_t *) *to; int from_size = *from_left; unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table); if (from == NULL || *from == NULL) { _XlcResetConverter(conv); return( 0 ); } if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { if (outbufptr) {*outbufptr++ = L'\0';} (*to_left)--; /* error check */ if (len_left) { unconv_num += (length - len_left); len_left = 0; } continue; } /* same mb char data */ if (len_left) goto output_one_wc; /* next mb char data for single shift ? */ if (mb_parse_table && (num = mb_parse_table[ch]) ) { codeset = mb_parse_codeset(state, num, &inbufptr, from_left); if (codeset != NULL) { length = len_left = codeset->length; mb = 0; continue; } } /* next mb char data for byteM ? */ if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1)))) goto next_mb_char; /* next mb char data for GL or GR side ? */ if ((codeset = GLGR_parse_codeset(ch))) goto next_mb_char; /* can't find codeset for the ch */ unconv_num++; continue; next_mb_char: length = len_left = codeset->length; mb = 0; output_one_wc: mb = (mb << 8) | ch; /* 1 byte left shift */ len_left--; /* last of one mb char data */ if (!len_left) { gi_to_wc(lcd, mb_to_gi(mb, codeset), codeset, &wc); if (outbufptr) {*outbufptr++ = wc;} (*to_left)--; } } /* end of while */ /* error check on last char */ if (len_left) { inbufptr -= (length - len_left); (*from_left) += (length - len_left); unconv_num += (length - len_left); } *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int stdc_mbstowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { const char *src = *((const 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 int wcstombs_org( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; char *encoding; unsigned long mb, glyph_index; wchar_t wc; int length; int unconv_num = 0; CodeSet codeset; const wchar_t *inbufptr = (const wchar_t *) *from; char *outbufptr = *to; int from_size = *from_left; const char *default_string = XLC_PUBLIC(lcd, default_string); int defstr_len = strlen(default_string); if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { wc = *inbufptr++; (*from_left)--; /* null ? */ if (!wc) { if (outbufptr) {*outbufptr++ = '\0';} (*to_left)--; continue; } /* convert */ if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) { /* output default_string of XDefaultString() */ if (*to_left < defstr_len) break; if (outbufptr) { strncpy((char *)outbufptr, default_string, defstr_len); outbufptr += defstr_len; } (*to_left) -= defstr_len; unconv_num++; } else { mb = gi_to_mb(glyph_index, codeset); if (codeset->parse_info) { Bool need_shift = False; switch (codeset->parse_info->type) { case E_LSL : if (codeset != state->GL_codeset) { need_shift = True; state->GL_codeset = codeset; } break; case E_LSR : if (codeset != state->GR_codeset) { need_shift = True; state->GR_codeset = codeset; } break; /* case E_SS */ default: need_shift = True; } /* output shift sequence */ if (need_shift) { encoding = codeset->parse_info->encoding; length = strlen(encoding); if (*to_left < length) break; if (outbufptr) { strncpy((char *)outbufptr, encoding, length); outbufptr += length; } (*to_left) -= length; } } /* output characters */ length = codeset->length; if (*to_left < length) break; if (outbufptr) { output_ulong_value(outbufptr, mb, length, XlcNONE); outbufptr += length; } (*to_left) -= length; } } /* end of while */ *from = (XPointer) ((const wchar_t *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int stdc_wcstombs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { const wchar_t *src = *((const 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 int wcstocts( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned long glyph_index; wchar_t wc; int total_len, seq_len, name_len; int unconv_num = 0; Bool first_flag = True, standard_flag; XlcSide side; CodeSet codeset; XlcCharSet charset, old_charset = NULL; const char *ct_sequence; const wchar_t *inbufptr = (const wchar_t *) *from; char *outbufptr = *to; int from_size = *from_left; char *ext_seg_len = NULL; if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { wc = *inbufptr++; (*from_left)--; /* null ? */ if (!wc) { if (outbufptr) {*outbufptr++ = '\0';} (*to_left)--; continue; } /* convert */ if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) { unconv_num++; continue; } /* parse charset */ if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) { unconv_num++; continue; } /* Standard Character Set Encoding ? */ standard_flag = charset->source == CSsrcStd ? True : False; /* * Non-Standard Character Set Encoding * * +-----+-----+-----+-----+-----+-----+-----+---- ----+-----+-----+ * | esc sequence | M | L | encoding name | STX | * +-----+-----+-----+-----+-----+-----+-----+---- ----+-----+-----+ * 4bytes 1byte 1byte variable length 1byte * | | * +-----------------------------------------+ * name length = ((M - 128) * 128) + (L - 128) */ /* make encoding data */ ct_sequence = charset->ct_sequence; side = charset->side; seq_len = strlen(ct_sequence); if (standard_flag) { name_len = 0; total_len = seq_len; } else { name_len = strlen(charset->encoding_name) + 1; total_len = seq_len + name_len + 2; } /* output escape sequence of CT */ if ( (charset != old_charset) && !(first_flag && charset->string_encoding) ){ if ( (ext_seg_len != NULL) && outbufptr) { int i = (outbufptr - ext_seg_len) - 2; *ext_seg_len++ = i / 128 + 128; *ext_seg_len = i % 128 + 128; ext_seg_len = NULL; } if (*to_left < total_len + 1) { unconv_num++; break; } if (outbufptr) { strcpy((char *)outbufptr, ct_sequence); outbufptr += seq_len; if (!standard_flag) { const char *i = charset->encoding_name; ext_seg_len = outbufptr; outbufptr += 2; for (; *i ; i++) *outbufptr++ = ((*i >= 'A') && (*i <= 'Z')) ? *i - 'A' + 'a' : *i; *outbufptr++ = STX; } } (*to_left) -= total_len; first_flag = False; old_charset = charset; } /* output glyph index */ if (codeset->ctconv) glyph_index = conv_to_dest(codeset->ctconv, glyph_index); if (*to_left < charset->char_size) { unconv_num++; break; } if (outbufptr) { output_ulong_value(outbufptr, glyph_index, charset->char_size, side); outbufptr += charset->char_size; } (*to_left) -= charset->char_size; } /* end of while */ if ( (ext_seg_len != NULL) && outbufptr) { int i = (outbufptr - ext_seg_len) - 2; *ext_seg_len++ = i / 128 + 128; *ext_seg_len = i % 128 + 128; } *from = (XPointer) ((const wchar_t *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int stdc_wcstocts( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX); char *buf_ptr1 = buf; int buf_left1 = (*from_left) * MB_CUR_MAX; char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = stdc_wcstombs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = buf_ptr1 - buf_ptr2; unconv_num2 = mbstocts(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int ctstowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned char ch; unsigned long glyph_index = 0; wchar_t wc; int ctr_seq_len = 0, gi_len_left = 0, gi_len = 0; int unconv_num = 0; CodeSet codeset = NULL; XlcCharSet charset_tmp; const char *inbufptr = *from; wchar_t *outbufptr = (wchar_t *) *to; int from_size = *from_left; _XlcResetConverter(conv); /* ??? */ if (from == NULL || *from == NULL) { _XlcResetConverter(conv); return( 0 ); } if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { if (outbufptr) {*outbufptr++ = L'\0';} (*to_left)--; /* error check */ if (gi_len_left) { unconv_num += (gi_len - gi_len_left); gi_len_left = 0; } continue; } /* same glyph_index data */ if (gi_len_left) goto output_one_wc; /* control sequence ? */ if (ch == CSI) { if ( !ct_parse_csi(inbufptr - 1, &ctr_seq_len) ) goto skip_the_seg; if (*from_left + 1 < ctr_seq_len) { inbufptr--; (*from_left)++; unconv_num += *from_left; break; } /* skip the control sequence */ inbufptr += (ctr_seq_len - 1); *from_left -= (ctr_seq_len - 1); continue; } /* escape sequence ? */ if (ch == ESC) { if ( !ct_parse_charset(lcd, inbufptr - 1, &state->charset, &ctr_seq_len) ) goto skip_the_seg; if (state->charset->side == XlcC0 || state->charset->side == XlcGL) { state->GL_charset = state->charset; } else if (state->charset->side == XlcC1 || state->charset->side == XlcGR) { state->GR_charset = state->charset; } else if (state->charset->side == XlcGLGR) { state->GL_charset = state->charset; state->GR_charset = state->charset; } if (*from_left + 1 < ctr_seq_len) { inbufptr--; (*from_left)++; unconv_num += *from_left; break; } /* skip the escape sequence */ inbufptr += (ctr_seq_len - 1); *from_left -= (ctr_seq_len - 1); continue; } /* check current state */ if (isleftside(ch)) state->charset = state->GL_charset; else state->charset = state->GR_charset; gi_len = gi_len_left = state->charset->char_size; glyph_index = 0; output_one_wc: if (state->charset->side == XlcC1 || state->charset->side == XlcGR) glyph_index = (glyph_index << 8) | (ch & GL); else glyph_index = (glyph_index << 8) | ch; gi_len_left--; /* last of one glyph_index data */ if (!gi_len_left) { /* segment conversion */ charset_tmp = state->charset; segment_conversion(lcd, &charset_tmp, &glyph_index); /* get codeset */ if ( !_XlcGetCodeSetFromCharSet(lcd, charset_tmp, &codeset, &glyph_index) ) { unconv_num += gi_len; continue; } /* convert glyph index to wicd char */ gi_to_wc(lcd, glyph_index, codeset, &wc); if (outbufptr) {*outbufptr++ = wc;} (*to_left)--; } continue; skip_the_seg: /* skip until next escape or control sequence */ while ( *from_left ) { ch = *inbufptr++; (*from_left)--; unconv_num++; if (ch == ESC || ch == CSI) { inbufptr--; (*from_left)++; unconv_num--; break; } } if ( !(*from_left) ) break; } /* end of while */ /* error check on last char */ if (gi_len_left) { inbufptr -= (gi_len - gi_len_left); (*from_left) += (gi_len - gi_len_left); unconv_num += (gi_len - gi_len_left); } *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int cstowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned char ch; unsigned long glyph_index = 0; wchar_t wc; int gi_len_left = 0, gi_len = 0; int unconv_num = 0; CodeSet codeset = NULL; XlcCharSet charset, charset_tmp; const char *inbufptr = *from; wchar_t *outbufptr = (wchar_t *) *to; int from_size = *from_left; if (from == NULL || *from == NULL) { return( 0 ); } charset = (XlcCharSet) args[0]; while (*from_left && *to_left) { if (!gi_len_left) { gi_len_left = gi_len = charset->char_size; glyph_index = 0; } ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { if (outbufptr) {*outbufptr++ = L'\0';} (*to_left)--; /* error check */ if (gi_len_left) { unconv_num += (gi_len - gi_len_left); gi_len_left = 0; } continue; } if (charset->side == XlcC1 || charset->side == XlcGR) glyph_index = (glyph_index << 8) | (ch & GL); else glyph_index = (glyph_index << 8) | ch; gi_len_left--; /* last of one glyph_index data */ if (!gi_len_left) { /* segment conversion */ charset_tmp = charset; segment_conversion(lcd, &charset_tmp, &glyph_index); /* get codeset */ if ( !_XlcGetCodeSetFromCharSet(lcd, charset_tmp, &codeset, &glyph_index) ) { unconv_num += gi_len; continue; } /* convert glyph index to wicd char */ gi_to_wc(lcd, glyph_index, codeset, &wc); if (outbufptr) {*outbufptr++ = wc;} (*to_left)--; } } /* end of while */ /* error check on last char */ if (gi_len_left) { inbufptr -= (gi_len - gi_len_left); (*from_left) += (gi_len - gi_len_left); unconv_num += (gi_len - gi_len_left); } *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int stdc_ctstowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX); char *buf_ptr1 = buf; int buf_left1 = (*from_left) * MB_CUR_MAX; char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = ctstombs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = buf_ptr1 - buf_ptr2; unconv_num2 = stdc_mbstowcs(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int stdc_cstowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX); char *buf_ptr1 = buf; int buf_left1 = (*from_left) * MB_CUR_MAX; char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = cstombs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = buf_ptr1 - buf_ptr2; unconv_num2 = stdc_mbstowcs(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int mbstocts( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t)); char *buf_ptr1 = buf; int buf_left1 = (*from_left); char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = mbstowcs_org(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t); unconv_num2 += wcstocts(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int mbstostr( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned char ch; unsigned long mb = 0; int length = 0, len_left = 0; int unconv_num = 0; int num; CodeSet codeset = NULL; const char *inbufptr = *from; char *outbufptr = *to; int from_size = *from_left; unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table); if (from == NULL || *from == NULL) { _XlcResetConverter(conv); return( 0 ); } if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { if (outbufptr) {*outbufptr++ = '\0';} (*to_left)--; /* error check */ if (len_left) { unconv_num += (length - len_left); len_left = 0; } continue; } /* same mb char data */ if (len_left) goto output_one_mb; /* next mb char data for single shift ? */ if (mb_parse_table && (num = mb_parse_table[ch]) ) { codeset = mb_parse_codeset(state, num, &inbufptr, from_left); if (codeset != NULL) { length = len_left = codeset->length; mb = 0; continue; } } /* next char data : byteM ? */ if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1)))) goto next_mb_char; /* next char data : GL or GR side ? */ if ((codeset = GLGR_parse_codeset(ch))) goto next_mb_char; /* can't find codeset for the ch */ unconv_num++; continue; next_mb_char: length = len_left = codeset->length; mb = 0; output_one_mb: mb = (mb << 8) | ch; /* 1 byte left shift */ len_left--; /* last of one mb char data */ if (!len_left) { if (check_string_encoding(codeset)) { if (outbufptr) {*outbufptr++ = mb & 0xff;} (*to_left)--; } else { unconv_num++; } } } /* end of while */ /* error check on last char */ if (len_left) { inbufptr -= (length - len_left); (*from_left) += (length - len_left); unconv_num += (length - len_left); } *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int mbtocs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned char ch; unsigned long mb = 0; unsigned long glyph_index; int length = 0, len_left = 0, char_len; int unconv_num = 0; int num; XlcSide side; CodeSet codeset = NULL; XlcCharSet charset = NULL; const char *inbufptr = *from; char *outbufptr = *to; int from_size = *from_left; unsigned char *mb_parse_table = XLC_GENERIC(lcd, mb_parse_table); if (from == NULL || *from == NULL) { _XlcResetConverter(conv); return( 0 ); } if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { unconv_num = 1; if (len_left) unconv_num += (length - len_left); break; } /* same mb char data */ if (len_left) goto output; /* next mb char data for single shift ? */ if (mb_parse_table && (num = mb_parse_table[ch]) ) { codeset = mb_parse_codeset(state, num, &inbufptr, from_left); if (codeset != NULL) { length = len_left = codeset->length; mb = 0; continue; } } /* next mb char data for byteM ? */ if ((codeset = byteM_parse_codeset(lcd, (inbufptr - 1)))) goto next_mb_char; /* next mb char data for GL or GR side ? */ if ((codeset = GLGR_parse_codeset(ch))) goto next_mb_char; /* can't find codeset for the ch */ unconv_num = 1; break; next_mb_char: length = len_left = codeset->length; mb = 0; output: mb = (mb << 8) | ch; /* 1 byte left shift */ len_left--; /* last of one mb char data */ if (!len_left) { glyph_index = mb_to_gi(mb, codeset); if (!(charset = gi_parse_charset(glyph_index, codeset))) { unconv_num = length; break; } char_len = charset->char_size; side = charset->side; /* output glyph index */ if (codeset->ctconv) glyph_index = conv_to_dest(codeset->ctconv, glyph_index); if (*to_left < char_len) { unconv_num = length; break; } if (outbufptr) { output_ulong_value(outbufptr, glyph_index, char_len, side); outbufptr += char_len; } (*to_left) -= char_len; break; } } /* end of while */ /* error end */ if (unconv_num) { *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return -1; } /* nomal end */ *from = (XPointer) inbufptr; *to = (XPointer) outbufptr; if (num_args > 0) *((XlcCharSet *) args[0]) = charset; return 0; } static int mbstocs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { int ret; XlcCharSet charset_old, charset = NULL; XPointer tmp_args[1]; const char *inbufptr; int in_left; char *outbufptr; int out_left; tmp_args[0] = (XPointer) &charset; ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1); charset_old = charset; while ( ret == 0 && *from_left && *to_left) { inbufptr = *from; in_left = *from_left; outbufptr = *to; out_left = *to_left; ret = mbtocs(conv, from, from_left, to, to_left, tmp_args, 1); if (charset_old != charset) { *from = (XPointer) inbufptr; *from_left = in_left; *to = (XPointer) outbufptr; *to_left = out_left; break; } } if (num_args > 0) *((XlcCharSet *) args[0]) = charset_old; /* error end */ if (ret != 0) return( -1 ); return(0); } static int wcstostr( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; char *encoding; unsigned long mb, glyph_index; wchar_t wc; int length; int unconv_num = 0; CodeSet codeset; const wchar_t *inbufptr = (const wchar_t *) *from; char *outbufptr = *to; int from_size = *from_left; const char *default_string = XLC_PUBLIC(lcd, default_string); int defstr_len = strlen(default_string); if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { wc = *inbufptr++; (*from_left)--; /* null ? */ if (!wc) { if (outbufptr) {*outbufptr++ = '\0';} (*to_left)--; continue; } /* convert */ if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) { /* output default_string of XDefaultString() */ if (*to_left < defstr_len) break; if (outbufptr) { strncpy((char *)outbufptr, default_string, defstr_len); outbufptr += defstr_len; } (*to_left) -= defstr_len; unconv_num++; } else { mb = gi_to_mb(glyph_index, codeset); if (check_string_encoding(codeset)) { if (codeset->parse_info) { Bool need_shift = False; switch (codeset->parse_info->type) { case E_LSL : if (codeset != state->GL_codeset) { need_shift = True; state->GL_codeset = codeset; } break; case E_LSR : if (codeset != state->GR_codeset) { need_shift = True; state->GR_codeset = codeset; } break; /* case E_SS */ default: need_shift = True; } /* output shift sequence */ if (need_shift) { encoding = codeset->parse_info->encoding; length = strlen(encoding); if (*to_left < length) break; if (outbufptr) { strncpy((char *)outbufptr, encoding, length); outbufptr += length; } (*to_left) -= length; } } /* output characters */ length = codeset->length; if (*to_left < length) break; if (outbufptr) { output_ulong_value(outbufptr, mb, length, XlcNONE); outbufptr += length; } (*to_left) -= length; } else { unconv_num++; } } } /* end of while */ *from = (XPointer) ((const wchar_t *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int stdc_wcstostr( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX); char *buf_ptr1 = buf; int buf_left1 = (*from_left) * MB_CUR_MAX; char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = stdc_wcstombs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = buf_ptr1 - buf_ptr2; unconv_num2 = mbstostr(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int wctocs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; wchar_t wc; unsigned long glyph_index; int char_len; int unconv_num = 0; XlcSide side; CodeSet codeset; XlcCharSet charset = NULL; const wchar_t *inbufptr = (const wchar_t *) *from; char *outbufptr = *to; int from_size = *from_left; if (*from_left > *to_left) *from_left = *to_left; if (*from_left && *to_left) { wc = *inbufptr++; (*from_left)--; /* null ? */ if (!wc) { unconv_num = 1; goto end; } /* convert */ if ( !wc_to_gi(lcd, wc, &glyph_index, &codeset) ) { unconv_num = 1; goto end; } if ( !(charset = gi_parse_charset(glyph_index, codeset)) ) { unconv_num = 1; goto end; } char_len = charset->char_size; side = charset->side; /* output glyph index */ if (codeset->ctconv) glyph_index = conv_to_dest(codeset->ctconv, glyph_index); if (*to_left < char_len) { unconv_num++; goto end; } if (outbufptr) { output_ulong_value(outbufptr, glyph_index, char_len, side); outbufptr += char_len; } (*to_left) -= char_len; } end: /* error end */ if (unconv_num) { *from = (XPointer) ((const wchar_t *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return -1; } /* nomal end */ *from = (XPointer) inbufptr; *to = (XPointer) outbufptr; if (num_args > 0) *((XlcCharSet *) args[0]) = charset; return 0; } static int stdc_wctocs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { const wchar_t *src = *((const wchar_t **) from); wchar_t wch; XPointer tmp_from, save_from = *from; char tmp[32]; int length, ret, src_left = *from_left; int from_size = *from_left; if (src_left > 0 && *to_left > 0) { if ((wch = *src)) { length = wctomb(tmp, wch); } else { goto end; } if (length < 0) goto end; tmp_from = (XPointer) tmp; ret = mbtocs(conv, &tmp_from, &length, to, to_left, args, num_args); if (ret < 0) goto end; src++; src_left--; } end: /* error end */ if (save_from == (XPointer) src) { *from = (XPointer) ((const wchar_t *) *from + from_size); *from_left = 0; return -1; } /* nomal end */ *from = (XPointer) src; *from_left = src_left; return 0; } static int wcstocs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { int ret; XlcCharSet charset_old, charset = NULL; XPointer tmp_args[1]; const wchar_t *inbufptr; int in_left; XPointer outbufptr; int out_left; tmp_args[0] = (XPointer) &charset; ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1); charset_old = charset; while ( ret == 0 && *from_left && *to_left) { inbufptr = (const wchar_t *) *from; in_left = *from_left; outbufptr = *to; out_left = *to_left; ret = wctocs(conv, from, from_left, to, to_left, tmp_args, 1); if (charset_old != charset) { *from = (XPointer) inbufptr; *from_left = in_left; *to = (XPointer) outbufptr; *to_left = out_left; break; } } if (num_args > 0) *((XlcCharSet *) args[0]) = charset_old; /* error end */ if (ret != 0) return( -1 ); return(0); } #ifdef STDCVT static int stdc_wcstocs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { int ret; XlcCharSet charset_old, charset = NULL; XPointer tmp_args[1]; const wchar_t *inbufptr; int in_left; XPointer outbufptr; int out_left; tmp_args[0] = (XPointer) &charset; ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1); charset_old = charset; while ( ret == 0 && *from_left && *to_left ) { inbufptr = (const wchar_t *) *from; in_left = *from_left; outbufptr = *to; out_left = *to_left; ret = stdc_wctocs(conv, from, from_left, to, to_left, tmp_args, 1); if (charset_old != charset) { *from = (XPointer) inbufptr; *from_left = in_left; *to = (XPointer) outbufptr; *to_left = out_left; break; } } if (num_args > 0) *((XlcCharSet *) args[0]) = charset_old; /* error end */ if (ret != 0) return( -1 ); return(0); } #endif static int ctstombs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t)); char *buf_ptr1 = buf; int buf_left1 = (*from_left); char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = ctstowcs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t); unconv_num2 += wcstombs_org(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int cstombs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * sizeof(wchar_t)); char *buf_ptr1 = buf; int buf_left1 = (*from_left); char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = cstowcs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = (buf_ptr1 - buf_ptr2) / sizeof(wchar_t); unconv_num2 += wcstombs_org(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } static int strtombs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; char *encoding; unsigned long mb, glyph_index; unsigned char ch; int length; int unconv_num = 0; CodeSet codeset; const char *inbufptr = *from; char *outbufptr = *to; int from_size = *from_left; if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { if (outbufptr) {*outbufptr++ = '\0';} (*to_left)--; continue; } /* convert */ if (isleftside(ch)) { glyph_index = ch; codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL"); } else { glyph_index = ch & GL; codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR"); } if (!codeset) { unconv_num++; continue; } mb = gi_to_mb(glyph_index, codeset); if (codeset->parse_info) { Bool need_shift = False; switch (codeset->parse_info->type) { case E_LSL : if (codeset != state->GL_codeset) { need_shift = True; state->GL_codeset = codeset; } break; case E_LSR : if (codeset != state->GR_codeset) { need_shift = True; state->GR_codeset = codeset; } break; /* case E_SS */ default: need_shift = True; } /* output shift sequence */ if (need_shift) { encoding = codeset->parse_info->encoding; length = strlen(encoding); if (*to_left < length) break; if (outbufptr) { strncpy((char *)outbufptr, encoding, length); outbufptr += length; } (*to_left) -= length; } } /* output characters */ length = codeset->length; if (*to_left < length) break; if (outbufptr) { output_ulong_value(outbufptr, mb, length, XlcNONE); outbufptr += length; } (*to_left) -= length; } /* end of while */ *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int strtowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { State state = (State) conv->state; XLCd lcd = state->lcd; unsigned char ch; unsigned long glyph_index; wchar_t wc; int unconv_num = 0; CodeSet codeset; const char *inbufptr = *from; wchar_t *outbufptr = (wchar_t *)*to; int from_size = *from_left; if (*from_left > *to_left) *from_left = *to_left; while (*from_left && *to_left) { ch = *inbufptr++; (*from_left)--; /* null ? */ if (!ch) { if (outbufptr) {*outbufptr++ = L'\0';} (*to_left)--; continue; } /* convert */ if (isleftside(ch)) { glyph_index = ch; codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GL"); } else { glyph_index = ch & GL; codeset = _XlcGetCodeSetFromName(lcd, "ISO8859-1:GR"); } if (!codeset) { unconv_num++; continue; } gi_to_wc(lcd, glyph_index, codeset, &wc); if (outbufptr) {*outbufptr++ = wc;} (*to_left)--; } /* end of while */ *from = (XPointer) ((const char *) *from + from_size); *from_left = 0; *to = (XPointer) outbufptr; return unconv_num; } static int stdc_strtowcs( XlcConv conv, XPointer *from, int *from_left, XPointer *to, int *to_left, XPointer *args, int num_args) { XPointer buf = Xmalloc((*from_left) * MB_CUR_MAX); char *buf_ptr1 = buf; int buf_left1 = (*from_left) * MB_CUR_MAX; char *buf_ptr2 = buf_ptr1; int buf_left2; int unconv_num1 = 0, unconv_num2 = 0; unconv_num1 = strtombs(conv, from, from_left, &buf_ptr1, &buf_left1, args, num_args); if (unconv_num1 < 0) goto ret; buf_left2 = buf_ptr1 - buf_ptr2; unconv_num2 = stdc_mbstowcs(conv, &buf_ptr2, &buf_left2, to, to_left, args, num_args); if (unconv_num2 < 0) goto ret; ret: if (buf) Xfree((char *)buf); return (unconv_num1 + unconv_num2); } /* -------------------------------------------------------------------------- */ /* Close */ /* -------------------------------------------------------------------------- */ static void close_converter( XlcConv conv) { if (conv->state) { Xfree((char *) conv->state); } if (conv->methods) { Xfree((char *) conv->methods); } Xfree((char *) conv); } /* -------------------------------------------------------------------------- */ /* Open */ /* -------------------------------------------------------------------------- */ static XlcConv create_conv( XLCd lcd, XlcConvMethods methods) { XlcConv conv; State state; conv = (XlcConv) Xmalloc(sizeof(XlcConvRec)); if (conv == NULL) return (XlcConv) NULL; conv->methods = (XlcConvMethods) Xmalloc(sizeof(XlcConvMethodsRec)); if (conv->methods == NULL) goto err; *conv->methods = *methods; conv->methods->reset = init_state; conv->state = (XPointer) Xmalloc(sizeof(StateRec)); if (conv->state == NULL) goto err; bzero((char *) conv->state, sizeof(StateRec)); state = (State) conv->state; state->lcd = lcd; _XlcResetConverter(conv); return conv; err: close_converter(conv); return (XlcConv) NULL; } static XlcConvMethodsRec mbstocts_methods = { close_converter, mbstocts, NULL }; static XlcConv open_mbstocts( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &mbstocts_methods); } static XlcConvMethodsRec mbstostr_methods = { close_converter, mbstostr, NULL }; static XlcConv open_mbstostr( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &mbstostr_methods); } static XlcConvMethodsRec mbstocs_methods = { close_converter, mbstocs, NULL }; static XlcConv open_mbstocs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &mbstocs_methods); } static XlcConvMethodsRec mbtocs_methods = { close_converter, mbtocs, NULL }; static XlcConv open_mbtocs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &mbtocs_methods); } static XlcConvMethodsRec ctstombs_methods = { close_converter, ctstombs, NULL }; static XlcConv open_ctstombs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &ctstombs_methods); } static XlcConvMethodsRec cstombs_methods = { close_converter, cstombs, NULL }; static XlcConv open_cstombs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &cstombs_methods); } static XlcConvMethodsRec strtombs_methods = { close_converter, strtombs, NULL }; static XlcConv open_strtombs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &strtombs_methods); } #ifdef STDCVT static XlcConvMethodsRec stdc_mbstowcs_methods = { close_converter, stdc_mbstowcs, NULL }; static XlcConv open_stdc_mbstowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_mbstowcs_methods); } static XlcConvMethodsRec stdc_wcstombs_methods = { close_converter, stdc_wcstombs, NULL }; static XlcConv open_stdc_wcstombs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_wcstombs_methods); } static XlcConvMethodsRec stdc_wcstocts_methods = { close_converter, stdc_wcstocts, NULL }; static XlcConv open_stdc_wcstocts( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_wcstocts_methods); } static XlcConvMethodsRec stdc_wcstostr_methods = { close_converter, stdc_wcstostr, NULL }; static XlcConv open_stdc_wcstostr( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_wcstostr_methods); } static XlcConvMethodsRec stdc_wcstocs_methods = { close_converter, stdc_wcstocs, NULL }; static XlcConv open_stdc_wcstocs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_wcstocs_methods); } static XlcConvMethodsRec stdc_wctocs_methods = { close_converter, stdc_wctocs, NULL }; static XlcConv open_stdc_wctocs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_wctocs_methods); } static XlcConvMethodsRec stdc_ctstowcs_methods = { close_converter, stdc_ctstowcs, NULL }; static XlcConv open_stdc_ctstowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_ctstowcs_methods); } static XlcConvMethodsRec stdc_cstowcs_methods = { close_converter, stdc_cstowcs, NULL }; static XlcConv open_stdc_cstowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_cstowcs_methods); } static XlcConvMethodsRec stdc_strtowcs_methods = { close_converter, stdc_strtowcs, NULL }; static XlcConv open_stdc_strtowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &stdc_strtowcs_methods); } #endif /* STDCVT */ static XlcConvMethodsRec mbstowcs_methods = { close_converter, mbstowcs_org, NULL }; static XlcConv open_mbstowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &mbstowcs_methods); } static XlcConvMethodsRec wcstombs_methods = { close_converter, wcstombs_org, NULL }; static XlcConv open_wcstombs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &wcstombs_methods); } static XlcConvMethodsRec wcstocts_methods = { close_converter, wcstocts, NULL }; static XlcConv open_wcstocts( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &wcstocts_methods); } static XlcConvMethodsRec wcstostr_methods = { close_converter, wcstostr, NULL }; static XlcConv open_wcstostr( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &wcstostr_methods); } static XlcConvMethodsRec wcstocs_methods = { close_converter, wcstocs, NULL }; static XlcConv open_wcstocs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &wcstocs_methods); } static XlcConvMethodsRec wctocs_methods = { close_converter, wctocs, NULL }; static XlcConv open_wctocs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &wctocs_methods); } static XlcConvMethodsRec ctstowcs_methods = { close_converter, ctstowcs, NULL }; static XlcConv open_ctstowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &ctstowcs_methods); } static XlcConvMethodsRec cstowcs_methods = { close_converter, cstowcs, NULL }; static XlcConv open_cstowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &cstowcs_methods); } static XlcConvMethodsRec strtowcs_methods = { close_converter, strtowcs, NULL }; static XlcConv open_strtowcs( XLCd from_lcd, const char *from_type, XLCd to_lcd, const char *to_type) { return create_conv(from_lcd, &strtowcs_methods); } /* -------------------------------------------------------------------------- */ /* Loader */ /* -------------------------------------------------------------------------- */ XLCd _XlcGenericLoader( const char *name) { XLCd lcd; #ifdef STDCVT XLCdGenericPart *gen; #endif lcd = _XlcCreateLC(name, _XlcGenericMethods); if (lcd == NULL) return lcd; default_GL_charset = _XlcGetCharSet("ISO8859-1:GL"); default_GR_charset = _XlcGetCharSet("ISO8859-1:GR"); _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCompoundText, open_mbstocts); _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_mbstostr); _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs); _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbtocs); _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte, open_ctstombs); _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtombs); _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs); #ifdef STDCVT gen = XLC_GENERIC_PART(lcd); if (gen->use_stdc_env != True) { #endif _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCompoundText, open_wcstocts); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNChar, open_wctocs); _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar, open_ctstowcs); _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_strtowcs); _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs); #ifdef STDCVT } #endif #ifdef STDCVT if (gen->use_stdc_env == True) { _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_stdc_mbstowcs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_stdc_wcstombs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCompoundText, open_stdc_wcstocts); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_stdc_wcstostr); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_stdc_wcstocs); _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNChar, open_stdc_wctocs); _XlcSetConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar, open_stdc_ctstowcs); _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_stdc_strtowcs); _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_stdc_cstowcs); } #endif _XlcAddUtf8Converters(lcd); return lcd; }