static XlcConv create_tocs_conv( XLCd lcd, XlcConvMethods methods) { XlcConv conv; CodeSet *codeset_list; int codeset_num; int charset_num; int i, j, k; Utf8Conv *preferred; lazy_init_all_charsets(); codeset_list = XLC_GENERIC(lcd, codeset_list); codeset_num = XLC_GENERIC(lcd, codeset_num); charset_num = 0; for (i = 0; i < codeset_num; i++) charset_num += codeset_list[i]->num_charsets; if (charset_num > all_charsets_count-1) charset_num = all_charsets_count-1; conv = (XlcConv) Xmalloc(sizeof(XlcConvRec) + (charset_num + 1) * sizeof(Utf8Conv)); if (conv == (XlcConv) NULL) return (XlcConv) NULL; preferred = (Utf8Conv *) ((char *) conv + sizeof(XlcConvRec)); /* Loop through all codesets mentioned in the locale. */ charset_num = 0; for (i = 0; i < codeset_num; i++) { XlcCharSet *charsets = codeset_list[i]->charset_list; int num_charsets = codeset_list[i]->num_charsets; for (j = 0; j < num_charsets; j++) { const char *name = charsets[j]->encoding_name; /* If it wasn't already encountered... */ for (k = charset_num-1; k >= 0; k--) if (!strcmp(preferred[k]->name, name)) break; if (k < 0) { /* Look it up in all_charsets[]. */ for (k = 0; k < all_charsets_count-1; k++) if (!strcmp(all_charsets[k].name, name)) { /* Add it to the preferred set. */ preferred[charset_num++] = &all_charsets[k]; break; } } } } preferred[charset_num] = (Utf8Conv) NULL; conv->methods = methods; conv->state = (XPointer) preferred; return conv; }
static int wcstocs( 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; const wchar_t *wcptr; char *bufptr; wchar_t wch; char *tmpptr; int length; CodeSet codeset; unsigned long wc_encoding; int wcstr_len, buf_len; if (from == NULL || *from == NULL) return 0; wcptr = *((const wchar_t **) from); bufptr = *((char **) to); wcstr_len = *from_left; buf_len = *to_left; codeset = wc_parse_codeset(lcd, wcptr); if (codeset == NULL) return -1; wc_encoding = codeset->wc_encoding; if (wcstr_len < buf_len / codeset->length) buf_len = wcstr_len * codeset->length; 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; if ((*codeset->charset_list)->side == XlcGL) { while (length--) { *tmpptr-- = (unsigned char) (wch & 0x7f); wch >>= (wchar_t)XLC_GENERIC(lcd, wc_shift_bits); } } else if ((*codeset->charset_list)->side == XlcGR) { while (length--) { *tmpptr-- = (unsigned char) (wch | 0x80); wch >>= (wchar_t)XLC_GENERIC(lcd, wc_shift_bits); } } else { while (length--) {
static CodeSet wc_parse_codeset( XLCd lcd, const wchar_t *wcstr) { CodeSet *codeset; unsigned long wc_encoding; int num; wc_encoding = *wcstr & XLC_GENERIC(lcd, wc_encode_mask); num = XLC_GENERIC(lcd, codeset_num); codeset = XLC_GENERIC(lcd, codeset_list); while (num-- > 0) { if (wc_encoding == (*codeset)->wc_encoding) return *codeset; codeset++; } return NULL; }
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; const char *src; char *dst; unsigned char *mb_parse_table; ParseInfo *parse_list, parse_info; XlcCharSet charset; int length, number, encoding_len = 0; int i; src = *((const char **) from); dst = *((char **) to); mb_parse_table = XLC_GENERIC(lcd, mb_parse_table); if (mb_parse_table != NULL) { number = mb_parse_table[(unsigned char) *src]; if (number > 0) { parse_list = XLC_GENERIC(lcd, mb_parse_list) + number - 1; for ( ; (parse_info = *parse_list) != NULL; parse_list++) { encoding_len = compare(src, parse_info->encoding, *from_left); if (encoding_len > 0) { switch (parse_info->type) { case E_SS: src += encoding_len; charset = *parse_info->codeset->charset_list; goto found; case E_LSL: case E_LSR: src += encoding_len; charset = *parse_info->codeset->charset_list; if (parse_info->type == E_LSL) state->GL_charset = charset; else state->GR_charset = charset; length = 0; goto end; case E_GL: charset = state->GL_charset; goto found; case E_GR: charset = state->GR_charset; goto found; default: break; } } } } } if ((*src & 0x80) && state->GR_charset) charset = state->GR_charset; else charset = state->GL_charset; found: if (charset == NULL || (num_args == 2 && (XlcCharSet) args[1] != charset)) return -1; length = charset->char_size; if (length > *from_left - encoding_len) return -1; if (dst) { if (length > *to_left) return -1; if (charset->side == XlcGL) { for (i = 0; i < length; i++) *dst++ = *src++ & 0x7f; } else if (charset->side == XlcGR) { for (i = 0; i < length; i++) *dst++ = *src++ | 0x80; } else { for (i = 0; i < length; i++) *dst++ = *src++; } *to = (XPointer) dst; *to_left -= length; } end: *from = (XPointer) src; *from_left -= encoding_len + length; state->charset = charset; if (num_args == 1) *((XlcCharSet *) args[0]) = charset; return 0; }