lcDefConv.c revision 1ab64890
11ab64890Smrg/* $Xorg: lcDefConv.c,v 1.3 2000/08/17 19:45:17 cpqbld Exp $ */
21ab64890Smrg/*
31ab64890Smrg * Copyright 1992, 1993 by TOSHIBA Corp.
41ab64890Smrg *
51ab64890Smrg * Permission to use, copy, modify, and distribute this software and its
61ab64890Smrg * documentation for any purpose and without fee is hereby granted, provided
71ab64890Smrg * that the above copyright notice appear in all copies and that both that
81ab64890Smrg * copyright notice and this permission notice appear in supporting
91ab64890Smrg * documentation, and that the name of TOSHIBA not be used in advertising
101ab64890Smrg * or publicity pertaining to distribution of the software without specific,
111ab64890Smrg * written prior permission. TOSHIBA make no representations about the
121ab64890Smrg * suitability of this software for any purpose.  It is provided "as is"
131ab64890Smrg * without express or implied warranty.
141ab64890Smrg *
151ab64890Smrg * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
161ab64890Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
171ab64890Smrg * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
181ab64890Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
191ab64890Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
201ab64890Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
211ab64890Smrg * SOFTWARE.
221ab64890Smrg *
231ab64890Smrg * Author: Katsuhisa Yano	TOSHIBA Corp.
241ab64890Smrg *			   	mopi@osa.ilab.toshiba.co.jp
251ab64890Smrg */
261ab64890Smrg/*
271ab64890Smrg * 2000
281ab64890Smrg * Modifier: Ivan Pascal        The XFree86 Project
291ab64890Smrg */
301ab64890Smrg/* $XFree86: xc/lib/X11/lcDefConv.c,v 1.6 2001/01/17 19:41:53 dawes Exp $ */
311ab64890Smrg
321ab64890Smrg/*
331ab64890Smrg * The default locale loader.
341ab64890Smrg * Supports: one byte per char (iso8859 like) locales.
351ab64890Smrg * How: converts bytes to wide characters in a 1:1 manner.
361ab64890Smrg * Platforms: all systems.
371ab64890Smrg */
381ab64890Smrg
391ab64890Smrg#ifdef HAVE_CONFIG_H
401ab64890Smrg#include <config.h>
411ab64890Smrg#endif
421ab64890Smrg#include "Xlibint.h"
431ab64890Smrg#include "XlcGeneric.h"
441ab64890Smrg
451ab64890Smrg#ifndef MB_LEN_MAX
461ab64890Smrg#define MB_LEN_MAX 6
471ab64890Smrg#endif
481ab64890Smrg
491ab64890Smrg#if !defined(macII) && !defined(Lynx_22) && !defined(X_LOCALE)
501ab64890Smrg#define STDCVT
511ab64890Smrg#endif
521ab64890Smrg
531ab64890Smrg#define GR	0x80
541ab64890Smrg#define GL	0x7f
551ab64890Smrg
561ab64890Smrgtypedef struct _StateRec *State;
571ab64890Smrgtypedef struct _StateRec {
581ab64890Smrg    CodeSet     GL_codeset;
591ab64890Smrg    CodeSet     GR_codeset;
601ab64890Smrg    wchar_t     wc_mask;
611ab64890Smrg    wchar_t     wc_encode_mask;
621ab64890Smrg    Bool        (*MBtoWC) (State state, const char *ch, wchar_t *wc);
631ab64890Smrg    Bool        (*WCtoMB) (State state, wchar_t wc, char *ch);
641ab64890Smrg} StateRec;
651ab64890Smrg
661ab64890Smrgstatic
671ab64890SmrgBool MBtoWCdef(
681ab64890Smrg    State    state,
691ab64890Smrg    const char *ch,
701ab64890Smrg    wchar_t  *wc)
711ab64890Smrg{
721ab64890Smrg    wchar_t wc_encoding;
731ab64890Smrg    CodeSet codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset;
741ab64890Smrg    if (!codeset)
751ab64890Smrg	return False;
761ab64890Smrg    wc_encoding = codeset->wc_encoding;
771ab64890Smrg    *wc = ((wchar_t) *ch & state->wc_mask) | wc_encoding;
781ab64890Smrg    return True;
791ab64890Smrg}
801ab64890Smrg
811ab64890Smrg#ifdef STDCVT
821ab64890Smrgstatic
831ab64890SmrgBool MBtoWCstd(
841ab64890Smrg    State   state,
851ab64890Smrg    const char *ch,
861ab64890Smrg    wchar_t *wc)
871ab64890Smrg{
881ab64890Smrg    return (mbtowc(wc, ch, 1) == 1);
891ab64890Smrg}
901ab64890Smrg#endif
911ab64890Smrg
921ab64890Smrgstatic
931ab64890SmrgBool WCtoMBdef(
941ab64890Smrg    State   state,
951ab64890Smrg    wchar_t wc,
961ab64890Smrg    char    *ch)
971ab64890Smrg{
981ab64890Smrg    wchar_t wc_encoding = wc & state->wc_encode_mask;
991ab64890Smrg    CodeSet codeset;
1001ab64890Smrg
1011ab64890Smrg    codeset = state->GL_codeset;
1021ab64890Smrg    if (codeset && (wc_encoding == codeset->wc_encoding)) {
1031ab64890Smrg	*ch = wc & state->wc_mask;
1041ab64890Smrg	return True;
1051ab64890Smrg    }
1061ab64890Smrg    codeset = state->GR_codeset;
1071ab64890Smrg    if (codeset && (wc_encoding == codeset->wc_encoding)) {
1081ab64890Smrg	*ch = (wc & state->wc_mask) | GR;
1091ab64890Smrg	return True;
1101ab64890Smrg    }
1111ab64890Smrg    return False;
1121ab64890Smrg}
1131ab64890Smrg
1141ab64890Smrg#ifdef STDCVT
1151ab64890Smrgstatic
1161ab64890SmrgBool WCtoMBstd(
1171ab64890Smrg    State   state,
1181ab64890Smrg    wchar_t wc,
1191ab64890Smrg    char    *ch)
1201ab64890Smrg{
1211ab64890Smrg    return (wctomb(ch, wc) == 1);
1221ab64890Smrg}
1231ab64890Smrg#endif
1241ab64890Smrg
1251ab64890Smrgstatic
1261ab64890SmrgXlcCharSet get_charset(
1271ab64890Smrg    State  state,
1281ab64890Smrg    char   side)
1291ab64890Smrg{
1301ab64890Smrg    CodeSet codeset = side ? state->GR_codeset : state->GL_codeset;
1311ab64890Smrg    if (codeset) {
1321ab64890Smrg	int i;
1331ab64890Smrg	XlcCharSet charset;
1341ab64890Smrg	for (i = 0; i < codeset->num_charsets; i++) {
1351ab64890Smrg	    charset = codeset->charset_list[i];
1361ab64890Smrg	    if (*charset->ct_sequence != '\0')
1371ab64890Smrg		return charset;
1381ab64890Smrg	}
1391ab64890Smrg	return *(codeset->charset_list);
1401ab64890Smrg    }
1411ab64890Smrg    return (XlcCharSet) NULL;
1421ab64890Smrg}
1431ab64890Smrg
1441ab64890Smrgstatic int
1451ab64890Smrgdef_mbstowcs(
1461ab64890Smrg    XlcConv conv,
1471ab64890Smrg    XPointer *from,
1481ab64890Smrg    int *from_left,
1491ab64890Smrg    XPointer *to,
1501ab64890Smrg    int *to_left,
1511ab64890Smrg    XPointer *args,
1521ab64890Smrg    int num_args)
1531ab64890Smrg{
1541ab64890Smrg    const char *src = (const char *) *from;
1551ab64890Smrg    wchar_t *dst = (wchar_t *) * to;
1561ab64890Smrg    State state = (State) conv->state;
1571ab64890Smrg    int unconv = 0;
1581ab64890Smrg
1591ab64890Smrg    if (from == NULL || *from == NULL)
1601ab64890Smrg	return 0;
1611ab64890Smrg
1621ab64890Smrg    while (*from_left && *to_left) {
1631ab64890Smrg	(*from_left)--;
1641ab64890Smrg	if (state->MBtoWC (state, src++, dst)) {
1651ab64890Smrg	    dst++;
1661ab64890Smrg	    (*to_left)--;
1671ab64890Smrg	} else {
1681ab64890Smrg	    unconv++;
1691ab64890Smrg	}
1701ab64890Smrg    }
1711ab64890Smrg    *from = (XPointer) src;
1721ab64890Smrg    *to = (XPointer) dst;
1731ab64890Smrg    return unconv;
1741ab64890Smrg}
1751ab64890Smrg
1761ab64890Smrgstatic int
1771ab64890Smrgdef_wcstombs(
1781ab64890Smrg    XlcConv conv,
1791ab64890Smrg    XPointer *from,
1801ab64890Smrg    int *from_left,
1811ab64890Smrg    XPointer *to,
1821ab64890Smrg    int *to_left,
1831ab64890Smrg    XPointer *args,
1841ab64890Smrg    int num_args)
1851ab64890Smrg{
1861ab64890Smrg    const wchar_t *src = (const wchar_t *) * from;
1871ab64890Smrg    char  *dst = (char *) *to;
1881ab64890Smrg    State state = (State) conv->state;
1891ab64890Smrg    char ch[MB_LEN_MAX];
1901ab64890Smrg    int unconv = 0;
1911ab64890Smrg
1921ab64890Smrg    if (from == NULL || *from == NULL)
1931ab64890Smrg	return 0;
1941ab64890Smrg
1951ab64890Smrg    while (*from_left && *to_left) {
1961ab64890Smrg	(*from_left)--;
1971ab64890Smrg	if (state->WCtoMB (state, *src++, ch)) {
1981ab64890Smrg	    *dst++ = *ch;
1991ab64890Smrg	    (*to_left)--;
2001ab64890Smrg	} else {
2011ab64890Smrg	    unconv++;
2021ab64890Smrg	}
2031ab64890Smrg    }
2041ab64890Smrg    *from = (XPointer) src;
2051ab64890Smrg    *to = (XPointer) dst;
2061ab64890Smrg    return unconv;
2071ab64890Smrg}
2081ab64890Smrg
2091ab64890Smrgstatic int
2101ab64890Smrgmbstostr(
2111ab64890Smrg    XlcConv conv,
2121ab64890Smrg    XPointer *from,
2131ab64890Smrg    int *from_left,
2141ab64890Smrg    XPointer *to,
2151ab64890Smrg    int *to_left,
2161ab64890Smrg    XPointer *args,
2171ab64890Smrg    int num_args)
2181ab64890Smrg{
2191ab64890Smrg    const char *src = (const char *) *from;
2201ab64890Smrg    char *dst = (char *) *to;
2211ab64890Smrg    CodeSet codeset;
2221ab64890Smrg    State state = (State) conv->state;
2231ab64890Smrg    char ch;
2241ab64890Smrg    int unconv = 0;
2251ab64890Smrg
2261ab64890Smrg    if (from == NULL || *from == NULL)
2271ab64890Smrg	return 0;
2281ab64890Smrg
2291ab64890Smrg    while (*from_left && *to_left) {
2301ab64890Smrg	ch = *src++;
2311ab64890Smrg	(*from_left)--;
2321ab64890Smrg
2331ab64890Smrg	codeset = (ch & GR) ? state->GR_codeset : state->GL_codeset;
2341ab64890Smrg	if (codeset && codeset->string_encoding) {
2351ab64890Smrg	    *dst++ = ch;
2361ab64890Smrg	    (*to_left)--;
2371ab64890Smrg	} else {
2381ab64890Smrg	    unconv++;
2391ab64890Smrg	}
2401ab64890Smrg    }
2411ab64890Smrg    *from = (XPointer) src;
2421ab64890Smrg    *to = (XPointer) dst;
2431ab64890Smrg    return unconv;
2441ab64890Smrg}
2451ab64890Smrg
2461ab64890Smrgstatic int
2471ab64890Smrgwcstostr(
2481ab64890Smrg    XlcConv conv,
2491ab64890Smrg    XPointer *from,
2501ab64890Smrg    int *from_left,
2511ab64890Smrg    XPointer *to,
2521ab64890Smrg    int *to_left,
2531ab64890Smrg    XPointer *args,
2541ab64890Smrg    int num_args)
2551ab64890Smrg{
2561ab64890Smrg    const wchar_t *src = (const wchar_t *) *from;
2571ab64890Smrg    char *dst = (char *) *to;
2581ab64890Smrg    CodeSet codeset;
2591ab64890Smrg    State state = (State) conv->state;
2601ab64890Smrg    char ch[MB_LEN_MAX];
2611ab64890Smrg    int unconv = 0;
2621ab64890Smrg
2631ab64890Smrg    if (from == NULL || *from == NULL)
2641ab64890Smrg	return 0;
2651ab64890Smrg
2661ab64890Smrg    while (*from_left && *to_left) {
2671ab64890Smrg	(*from_left)--;
2681ab64890Smrg	if (state->WCtoMB (state, *src++, ch)) {
2691ab64890Smrg	    codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset;
2701ab64890Smrg	    if (codeset && codeset->string_encoding) {
2711ab64890Smrg		*dst++ = *ch;
2721ab64890Smrg		(*to_left)--;
2731ab64890Smrg	    } else {
2741ab64890Smrg		unconv++;
2751ab64890Smrg	    }
2761ab64890Smrg	} else {
2771ab64890Smrg	    unconv++;
2781ab64890Smrg	}
2791ab64890Smrg    }
2801ab64890Smrg    *from = (XPointer) src;
2811ab64890Smrg    *to = (XPointer) dst;
2821ab64890Smrg    return unconv;
2831ab64890Smrg}
2841ab64890Smrg
2851ab64890Smrgstatic int
2861ab64890Smrgmbstocs(
2871ab64890Smrg    XlcConv conv,
2881ab64890Smrg    XPointer *from,
2891ab64890Smrg    int *from_left,
2901ab64890Smrg    XPointer *to,
2911ab64890Smrg    int *to_left,
2921ab64890Smrg    XPointer *args,
2931ab64890Smrg    int num_args)
2941ab64890Smrg{
2951ab64890Smrg    const char *src = (const char *) *from;
2961ab64890Smrg    char *dst = (char *) *to;
2971ab64890Smrg    int length;
2981ab64890Smrg    State state = (State) conv->state;
2991ab64890Smrg    char cur_side;
3001ab64890Smrg    int unconv = 0;
3011ab64890Smrg
3021ab64890Smrg    if (from == NULL || *from == NULL)
3031ab64890Smrg	return 0;
3041ab64890Smrg
3051ab64890Smrg    length = min(*from_left, *to_left);
3061ab64890Smrg
3071ab64890Smrg    cur_side = *src & GR;
3081ab64890Smrg    while (length) {
3091ab64890Smrg	if ((char) (*src & GR) != cur_side)
3101ab64890Smrg	    break;
3111ab64890Smrg	*dst++ = *src++;
3121ab64890Smrg	length--;
3131ab64890Smrg    }
3141ab64890Smrg
3151ab64890Smrg    if (num_args > 0) {
3161ab64890Smrg	XlcCharSet      charset = get_charset(state, cur_side);
3171ab64890Smrg	if (charset) {
3181ab64890Smrg	    *((XlcCharSet *) args[0]) = charset;
3191ab64890Smrg	} else {
3201ab64890Smrg	    dst = *to;
3211ab64890Smrg	    unconv = -1;
3221ab64890Smrg	}
3231ab64890Smrg    }
3241ab64890Smrg    *from_left -= src - (char *) *from;
3251ab64890Smrg    *to_left -= dst - (char *) *to;
3261ab64890Smrg    *from = (XPointer) src;
3271ab64890Smrg    *to = (XPointer) dst;
3281ab64890Smrg    return unconv;
3291ab64890Smrg}
3301ab64890Smrg
3311ab64890Smrgstatic int
3321ab64890Smrgwcstocs(
3331ab64890Smrg    XlcConv conv,
3341ab64890Smrg    XPointer *from,
3351ab64890Smrg    int *from_left,
3361ab64890Smrg    XPointer *to,
3371ab64890Smrg    int *to_left,
3381ab64890Smrg    XPointer *args,
3391ab64890Smrg    int num_args)
3401ab64890Smrg{
3411ab64890Smrg    const wchar_t *src = (const wchar_t *) * from;
3421ab64890Smrg    char *dst = (char *) *to;
3431ab64890Smrg    State state = (State) conv->state;
3441ab64890Smrg    char cur_side = 0, ch[MB_LEN_MAX];
3451ab64890Smrg    int unconv = 0;
3461ab64890Smrg    Bool found = False;
3471ab64890Smrg
3481ab64890Smrg    if (from == NULL || *from == NULL)
3491ab64890Smrg	return 0;
3501ab64890Smrg
3511ab64890Smrg    while (*from_left) {
3521ab64890Smrg	if ((found = state->WCtoMB (state, *src, ch)))
3531ab64890Smrg	    break;
3541ab64890Smrg	unconv++;
3551ab64890Smrg	src++;
3561ab64890Smrg	(*from_left)--;
3571ab64890Smrg    }
3581ab64890Smrg
3591ab64890Smrg    if (found) {
3601ab64890Smrg	cur_side = *ch & GR;
3611ab64890Smrg	while (*from_left && *to_left) {
3621ab64890Smrg	    (*from_left)--;
3631ab64890Smrg	    if (state->WCtoMB (state, *src++, ch)) {
3641ab64890Smrg		if ((char) (*ch & GR) != cur_side) {
3651ab64890Smrg		    src--;
3661ab64890Smrg		    (*from_left)++;
3671ab64890Smrg		    break;
3681ab64890Smrg		} else {
3691ab64890Smrg		    *dst++ = *ch;
3701ab64890Smrg		    (*to_left)--;
3711ab64890Smrg		}
3721ab64890Smrg	    } else {
3731ab64890Smrg		unconv++;
3741ab64890Smrg	    }
3751ab64890Smrg	}
3761ab64890Smrg    } else {
3771ab64890Smrg	unconv++;
3781ab64890Smrg    }
3791ab64890Smrg
3801ab64890Smrg    if (num_args > 0) {
3811ab64890Smrg	XlcCharSet charset = get_charset(state, cur_side);
3821ab64890Smrg	if (charset) {
3831ab64890Smrg	    *((XlcCharSet *) args[0]) = charset;
3841ab64890Smrg	} else {
3851ab64890Smrg	    unconv = -1;
3861ab64890Smrg	}
3871ab64890Smrg    }
3881ab64890Smrg    *from = (XPointer) src;
3891ab64890Smrg    *to = (XPointer) dst;
3901ab64890Smrg    return unconv;
3911ab64890Smrg}
3921ab64890Smrg
3931ab64890Smrgstatic int
3941ab64890Smrgcstombs(
3951ab64890Smrg    XlcConv conv,
3961ab64890Smrg    XPointer *from,
3971ab64890Smrg    int *from_left,
3981ab64890Smrg    XPointer *to,
3991ab64890Smrg    int *to_left,
4001ab64890Smrg    XPointer *args,
4011ab64890Smrg    int num_args)
4021ab64890Smrg{
4031ab64890Smrg    const char *src = (const char *) *from;
4041ab64890Smrg    char *dst = (char *) *to;
4051ab64890Smrg    CodeSet codeset;
4061ab64890Smrg    XlcCharSet charset;
4071ab64890Smrg    State state = (State) conv->state;
4081ab64890Smrg    unsigned char cur_side = 0;
4091ab64890Smrg    int i;
4101ab64890Smrg    Bool found = False;
4111ab64890Smrg
4121ab64890Smrg    if (from == NULL || *from == NULL)
4131ab64890Smrg	return 0;
4141ab64890Smrg
4151ab64890Smrg    if (num_args > 0) {
4161ab64890Smrg	charset = (XlcCharSet) args[0];
4171ab64890Smrg	if (charset == NULL)
4181ab64890Smrg	    return -1;
4191ab64890Smrg    } else {
4201ab64890Smrg	return -1;
4211ab64890Smrg    }
4221ab64890Smrg
4231ab64890Smrg    if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) {
4241ab64890Smrg	codeset = state->GL_codeset;
4251ab64890Smrg	if (codeset) {
4261ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
4271ab64890Smrg		if (charset == codeset->charset_list[i]) {
4281ab64890Smrg		    found = True;
4291ab64890Smrg		    cur_side = 0;
4301ab64890Smrg		    break;
4311ab64890Smrg		}
4321ab64890Smrg	}
4331ab64890Smrg    }
4341ab64890Smrg    if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) {
4351ab64890Smrg	codeset = state->GR_codeset;
4361ab64890Smrg	if (codeset) {
4371ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
4381ab64890Smrg		if (charset == codeset->charset_list[i]) {
4391ab64890Smrg		    found = True;
4401ab64890Smrg		    cur_side = GR;
4411ab64890Smrg		    break;
4421ab64890Smrg		}
4431ab64890Smrg	}
4441ab64890Smrg    }
4451ab64890Smrg    if (found) {
4461ab64890Smrg	int length = min(*from_left, *to_left);
4471ab64890Smrg	while (length) {
4481ab64890Smrg	    *dst++ = *src++ | cur_side;
4491ab64890Smrg	    length--;
4501ab64890Smrg	}
4511ab64890Smrg    } else {
4521ab64890Smrg	return -1;
4531ab64890Smrg    }
4541ab64890Smrg
4551ab64890Smrg    *from_left -= src - (char *) *from;
4561ab64890Smrg    *to_left -= dst - (char *) *to;
4571ab64890Smrg    *from = (XPointer) src;
4581ab64890Smrg    *to = (XPointer) dst;
4591ab64890Smrg    return 0;
4601ab64890Smrg}
4611ab64890Smrg
4621ab64890Smrgstatic int
4631ab64890Smrgcstowcs(
4641ab64890Smrg    XlcConv conv,
4651ab64890Smrg    XPointer *from,
4661ab64890Smrg    int *from_left,
4671ab64890Smrg    XPointer *to,
4681ab64890Smrg    int *to_left,
4691ab64890Smrg    XPointer *args,
4701ab64890Smrg    int num_args)
4711ab64890Smrg{
4721ab64890Smrg    const char *src = (const char *) *from;
4731ab64890Smrg    wchar_t *dst = (wchar_t *) * to;
4741ab64890Smrg    CodeSet codeset;
4751ab64890Smrg    XlcCharSet charset;
4761ab64890Smrg    State state = (State) conv->state;
4771ab64890Smrg    Bool found = False;
4781ab64890Smrg    int i, unconv = 0;
4791ab64890Smrg    unsigned char cur_side = 0;
4801ab64890Smrg
4811ab64890Smrg    if (from == NULL || *from == NULL)
4821ab64890Smrg	return 0;
4831ab64890Smrg
4841ab64890Smrg    if (num_args > 0) {
4851ab64890Smrg	charset = (XlcCharSet) args[0];
4861ab64890Smrg	if (charset == NULL)
4871ab64890Smrg	    return -1;
4881ab64890Smrg    } else {
4891ab64890Smrg	return -1;
4901ab64890Smrg    }
4911ab64890Smrg
4921ab64890Smrg    if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) {
4931ab64890Smrg	codeset = state->GL_codeset;
4941ab64890Smrg	if (codeset) {
4951ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
4961ab64890Smrg		if (charset == codeset->charset_list[i]) {
4971ab64890Smrg		    found = True;
4981ab64890Smrg		    cur_side = 0;
4991ab64890Smrg		    break;
5001ab64890Smrg		}
5011ab64890Smrg	}
5021ab64890Smrg    }
5031ab64890Smrg    if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) {
5041ab64890Smrg	codeset = state->GR_codeset;
5051ab64890Smrg	if (codeset) {
5061ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
5071ab64890Smrg		if (charset == codeset->charset_list[i]) {
5081ab64890Smrg		    found = True;
5091ab64890Smrg		    cur_side = GR;
5101ab64890Smrg		    break;
5111ab64890Smrg		}
5121ab64890Smrg	}
5131ab64890Smrg    }
5141ab64890Smrg    if (found) {
5151ab64890Smrg	char ch;
5161ab64890Smrg	while (*from_left && *to_left) {
5171ab64890Smrg	    ch = *src++ | cur_side;
5181ab64890Smrg	    (*from_left)--;
5191ab64890Smrg	    if (state->MBtoWC (state, &ch, dst)) {
5201ab64890Smrg		dst++;
5211ab64890Smrg		(*to_left)--;
5221ab64890Smrg	    } else {
5231ab64890Smrg		unconv++;
5241ab64890Smrg	    }
5251ab64890Smrg	}
5261ab64890Smrg    } else {
5271ab64890Smrg	return -1;
5281ab64890Smrg    }
5291ab64890Smrg    *from = (XPointer) src;
5301ab64890Smrg    *to = (XPointer) dst;
5311ab64890Smrg    return unconv;
5321ab64890Smrg}
5331ab64890Smrg
5341ab64890Smrgstatic int
5351ab64890Smrgstrtombs(
5361ab64890Smrg    XlcConv conv,
5371ab64890Smrg    XPointer *from,
5381ab64890Smrg    int *from_left,
5391ab64890Smrg    XPointer *to,
5401ab64890Smrg    int *to_left,
5411ab64890Smrg    XPointer *args,
5421ab64890Smrg    int num_args)
5431ab64890Smrg{
5441ab64890Smrg    const char *src = (const char *) *from;
5451ab64890Smrg    char *dst = (char *) *to;
5461ab64890Smrg    int length;
5471ab64890Smrg
5481ab64890Smrg    if (from == NULL || *from == NULL)
5491ab64890Smrg	return 0;
5501ab64890Smrg
5511ab64890Smrg    length = min(*from_left, *to_left);
5521ab64890Smrg    while (length) {
5531ab64890Smrg	*dst++ = *src++;
5541ab64890Smrg	length--;
5551ab64890Smrg    }
5561ab64890Smrg
5571ab64890Smrg    *from_left -= src - (char *) *from;
5581ab64890Smrg    *to_left -= dst - (char *) *to;
5591ab64890Smrg    *from = (XPointer) src;
5601ab64890Smrg    *to = (XPointer) dst;
5611ab64890Smrg    return 0;
5621ab64890Smrg}
5631ab64890Smrg
5641ab64890Smrgstatic void
5651ab64890Smrgclose_converter(
5661ab64890Smrg    XlcConv conv)
5671ab64890Smrg{
5681ab64890Smrg    if (conv->state)
5691ab64890Smrg	Xfree((char *) conv->state);
5701ab64890Smrg
5711ab64890Smrg    Xfree((char *) conv);
5721ab64890Smrg}
5731ab64890Smrg
5741ab64890Smrgstatic XlcConv
5751ab64890Smrgcreate_conv(
5761ab64890Smrg    XLCd lcd,
5771ab64890Smrg    XlcConvMethods methods)
5781ab64890Smrg{
5791ab64890Smrg    XlcConv conv;
5801ab64890Smrg    State state;
5811ab64890Smrg
5821ab64890Smrg    conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
5831ab64890Smrg    if (conv == NULL)
5841ab64890Smrg	return (XlcConv) NULL;
5851ab64890Smrg
5861ab64890Smrg    state = (State) Xmalloc(sizeof(StateRec));
5871ab64890Smrg    if (state == NULL) {
5881ab64890Smrg	close_converter(conv);
5891ab64890Smrg	return (XlcConv) NULL;
5901ab64890Smrg    }
5911ab64890Smrg    state->GL_codeset = XLC_GENERIC(lcd, initial_state_GL);
5921ab64890Smrg    state->GR_codeset = XLC_GENERIC(lcd, initial_state_GR);
5931ab64890Smrg    state->wc_mask = (1 << XLC_GENERIC(lcd, wc_shift_bits)) - 1;
5941ab64890Smrg    state->wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask);
5951ab64890Smrg
5961ab64890Smrg#ifdef STDCVT
5971ab64890Smrg    if (XLC_GENERIC(lcd, use_stdc_env) == True)
5981ab64890Smrg	state->MBtoWC = &MBtoWCstd;
5991ab64890Smrg    else
6001ab64890Smrg#endif
6011ab64890Smrg	state->MBtoWC = &MBtoWCdef;
6021ab64890Smrg
6031ab64890Smrg#ifdef STDCVT
6041ab64890Smrg    if (XLC_GENERIC(lcd, use_stdc_env) == True)
6051ab64890Smrg	state->WCtoMB = &WCtoMBstd;
6061ab64890Smrg    else
6071ab64890Smrg#endif
6081ab64890Smrg	state->WCtoMB = &WCtoMBdef;
6091ab64890Smrg
6101ab64890Smrg    conv->methods = methods;
6111ab64890Smrg    conv->state = (XPointer) state;
6121ab64890Smrg
6131ab64890Smrg    return conv;
6141ab64890Smrg}
6151ab64890Smrg
6161ab64890Smrgstatic XlcConvMethodsRec mbstowcs_methods = {
6171ab64890Smrg    close_converter,
6181ab64890Smrg    def_mbstowcs,
6191ab64890Smrg    NULL
6201ab64890Smrg};
6211ab64890Smrg
6221ab64890Smrgstatic XlcConv
6231ab64890Smrgopen_mbstowcs(
6241ab64890Smrg    XLCd from_lcd,
6251ab64890Smrg    const char *from_type,
6261ab64890Smrg    XLCd to_lcd,
6271ab64890Smrg    const char *to_type)
6281ab64890Smrg{
6291ab64890Smrg    return create_conv(from_lcd, &mbstowcs_methods);
6301ab64890Smrg}
6311ab64890Smrg
6321ab64890Smrgstatic XlcConvMethodsRec mbstostr_methods = {
6331ab64890Smrg    close_converter,
6341ab64890Smrg    mbstostr,
6351ab64890Smrg    NULL
6361ab64890Smrg};
6371ab64890Smrg
6381ab64890Smrgstatic XlcConv
6391ab64890Smrgopen_mbstostr(
6401ab64890Smrg    XLCd from_lcd,
6411ab64890Smrg    const char *from_type,
6421ab64890Smrg    XLCd to_lcd,
6431ab64890Smrg    const char *to_type)
6441ab64890Smrg{
6451ab64890Smrg    return create_conv(from_lcd, &mbstostr_methods);
6461ab64890Smrg}
6471ab64890Smrg
6481ab64890Smrgstatic XlcConvMethodsRec mbstocs_methods = {
6491ab64890Smrg    close_converter,
6501ab64890Smrg    mbstocs,
6511ab64890Smrg    NULL
6521ab64890Smrg};
6531ab64890Smrg
6541ab64890Smrgstatic XlcConv
6551ab64890Smrgopen_mbstocs(
6561ab64890Smrg    XLCd from_lcd,
6571ab64890Smrg    const char *from_type,
6581ab64890Smrg    XLCd to_lcd,
6591ab64890Smrg    const char *to_type)
6601ab64890Smrg{
6611ab64890Smrg    return create_conv(from_lcd, &mbstocs_methods);
6621ab64890Smrg}
6631ab64890Smrg
6641ab64890Smrgstatic XlcConvMethodsRec wcstombs_methods = {
6651ab64890Smrg    close_converter,
6661ab64890Smrg    def_wcstombs,
6671ab64890Smrg    NULL
6681ab64890Smrg};
6691ab64890Smrg
6701ab64890Smrgstatic XlcConv
6711ab64890Smrgopen_wcstombs(
6721ab64890Smrg    XLCd from_lcd,
6731ab64890Smrg    const char *from_type,
6741ab64890Smrg    XLCd to_lcd,
6751ab64890Smrg    const char *to_type)
6761ab64890Smrg{
6771ab64890Smrg    return create_conv(from_lcd, &wcstombs_methods);
6781ab64890Smrg}
6791ab64890Smrg
6801ab64890Smrgstatic XlcConvMethodsRec wcstostr_methods = {
6811ab64890Smrg    close_converter,
6821ab64890Smrg    wcstostr,
6831ab64890Smrg    NULL
6841ab64890Smrg};
6851ab64890Smrg
6861ab64890Smrgstatic XlcConv
6871ab64890Smrgopen_wcstostr(
6881ab64890Smrg    XLCd from_lcd,
6891ab64890Smrg    const char *from_type,
6901ab64890Smrg    XLCd to_lcd,
6911ab64890Smrg    const char *to_type)
6921ab64890Smrg{
6931ab64890Smrg    return create_conv(from_lcd, &wcstostr_methods);
6941ab64890Smrg}
6951ab64890Smrg
6961ab64890Smrgstatic XlcConvMethodsRec wcstocs_methods = {
6971ab64890Smrg    close_converter,
6981ab64890Smrg    wcstocs,
6991ab64890Smrg    NULL
7001ab64890Smrg};
7011ab64890Smrg
7021ab64890Smrgstatic XlcConv
7031ab64890Smrgopen_wcstocs(
7041ab64890Smrg    XLCd from_lcd,
7051ab64890Smrg    const char *from_type,
7061ab64890Smrg    XLCd to_lcd,
7071ab64890Smrg    const char *to_type)
7081ab64890Smrg{
7091ab64890Smrg    return create_conv(from_lcd, &wcstocs_methods);
7101ab64890Smrg}
7111ab64890Smrg
7121ab64890Smrgstatic XlcConvMethodsRec strtombs_methods = {
7131ab64890Smrg    close_converter,
7141ab64890Smrg    strtombs,
7151ab64890Smrg    NULL
7161ab64890Smrg};
7171ab64890Smrg
7181ab64890Smrgstatic XlcConv
7191ab64890Smrgopen_strtombs(
7201ab64890Smrg    XLCd from_lcd,
7211ab64890Smrg    const char *from_type,
7221ab64890Smrg    XLCd to_lcd,
7231ab64890Smrg    const char *to_type)
7241ab64890Smrg{
7251ab64890Smrg    return create_conv(from_lcd, &strtombs_methods);
7261ab64890Smrg}
7271ab64890Smrg
7281ab64890Smrgstatic XlcConvMethodsRec cstombs_methods = {
7291ab64890Smrg    close_converter,
7301ab64890Smrg    cstombs,
7311ab64890Smrg    NULL
7321ab64890Smrg};
7331ab64890Smrg
7341ab64890Smrgstatic XlcConv
7351ab64890Smrgopen_cstombs(
7361ab64890Smrg    XLCd from_lcd,
7371ab64890Smrg    const char *from_type,
7381ab64890Smrg    XLCd to_lcd,
7391ab64890Smrg    const char *to_type)
7401ab64890Smrg{
7411ab64890Smrg    return create_conv(from_lcd, &cstombs_methods);
7421ab64890Smrg}
7431ab64890Smrg
7441ab64890Smrgstatic XlcConvMethodsRec cstowcs_methods = {
7451ab64890Smrg    close_converter,
7461ab64890Smrg    cstowcs,
7471ab64890Smrg    NULL
7481ab64890Smrg};
7491ab64890Smrg
7501ab64890Smrgstatic XlcConv
7511ab64890Smrgopen_cstowcs(
7521ab64890Smrg    XLCd from_lcd,
7531ab64890Smrg    const char *from_type,
7541ab64890Smrg    XLCd to_lcd,
7551ab64890Smrg    const char *to_type)
7561ab64890Smrg{
7571ab64890Smrg    return create_conv(from_lcd, &cstowcs_methods);
7581ab64890Smrg}
7591ab64890Smrg
7601ab64890SmrgXLCd
7611ab64890Smrg_XlcDefaultLoader(
7621ab64890Smrg    const char *name)
7631ab64890Smrg{
7641ab64890Smrg    XLCd lcd;
7651ab64890Smrg
7661ab64890Smrg    lcd = _XlcCreateLC(name, _XlcGenericMethods);
7671ab64890Smrg    if (lcd == NULL)
7681ab64890Smrg	return lcd;
7691ab64890Smrg
7701ab64890Smrg    if (XLC_PUBLIC(lcd, mb_cur_max) != 1){
7711ab64890Smrg        _XlcDestroyLC(lcd);
7721ab64890Smrg        return (XLCd) NULL;
7731ab64890Smrg    }
7741ab64890Smrg
7751ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs);
7761ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_mbstostr);
7771ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs);
7781ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbstocs);
7791ab64890Smrg
7801ab64890Smrg    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs);
7811ab64890Smrg    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr);
7821ab64890Smrg    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs);
7831ab64890Smrg
7841ab64890Smrg    _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtombs);
7851ab64890Smrg    _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_mbstowcs);
7861ab64890Smrg
7871ab64890Smrg    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs);
7881ab64890Smrg    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs);
7891ab64890Smrg
7901ab64890Smrg    _XlcAddUtf8Converters(lcd);
7911ab64890Smrg
7921ab64890Smrg    return lcd;
7931ab64890Smrg}
794