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