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
47ebe525bcSmrg#ifndef 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{
1520f8248bfSmrg    const char *src;
1530f8248bfSmrg    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
1600f8248bfSmrg    src = (const char *) *from;
1610f8248bfSmrg
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{
1860f8248bfSmrg    const wchar_t *src;
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
1950f8248bfSmrg    src = (const wchar_t *) *from;
1960f8248bfSmrg
1971ab64890Smrg    while (*from_left && *to_left) {
1981ab64890Smrg	(*from_left)--;
1991ab64890Smrg	if (state->WCtoMB (state, *src++, ch)) {
2001ab64890Smrg	    *dst++ = *ch;
2011ab64890Smrg	    (*to_left)--;
2021ab64890Smrg	} else {
2031ab64890Smrg	    unconv++;
2041ab64890Smrg	}
2051ab64890Smrg    }
2061ab64890Smrg    *from = (XPointer) src;
2071ab64890Smrg    *to = (XPointer) dst;
2081ab64890Smrg    return unconv;
2091ab64890Smrg}
2101ab64890Smrg
2111ab64890Smrgstatic int
2121ab64890Smrgmbstostr(
2131ab64890Smrg    XlcConv conv,
2141ab64890Smrg    XPointer *from,
2151ab64890Smrg    int *from_left,
2161ab64890Smrg    XPointer *to,
2171ab64890Smrg    int *to_left,
2181ab64890Smrg    XPointer *args,
2191ab64890Smrg    int num_args)
2201ab64890Smrg{
2210f8248bfSmrg    const char *src;
2221ab64890Smrg    char *dst = (char *) *to;
2231ab64890Smrg    CodeSet codeset;
2241ab64890Smrg    State state = (State) conv->state;
2251ab64890Smrg    char ch;
2261ab64890Smrg    int unconv = 0;
2271ab64890Smrg
2281ab64890Smrg    if (from == NULL || *from == NULL)
2291ab64890Smrg	return 0;
2301ab64890Smrg
2310f8248bfSmrg    src = (const char *) *from;
2320f8248bfSmrg
2331ab64890Smrg    while (*from_left && *to_left) {
2341ab64890Smrg	ch = *src++;
2351ab64890Smrg	(*from_left)--;
2361ab64890Smrg
2371ab64890Smrg	codeset = (ch & GR) ? state->GR_codeset : state->GL_codeset;
2381ab64890Smrg	if (codeset && codeset->string_encoding) {
2391ab64890Smrg	    *dst++ = ch;
2401ab64890Smrg	    (*to_left)--;
2411ab64890Smrg	} else {
2421ab64890Smrg	    unconv++;
2431ab64890Smrg	}
2441ab64890Smrg    }
2451ab64890Smrg    *from = (XPointer) src;
2461ab64890Smrg    *to = (XPointer) dst;
2471ab64890Smrg    return unconv;
2481ab64890Smrg}
2491ab64890Smrg
2501ab64890Smrgstatic int
2511ab64890Smrgwcstostr(
2521ab64890Smrg    XlcConv conv,
2531ab64890Smrg    XPointer *from,
2541ab64890Smrg    int *from_left,
2551ab64890Smrg    XPointer *to,
2561ab64890Smrg    int *to_left,
2571ab64890Smrg    XPointer *args,
2581ab64890Smrg    int num_args)
2591ab64890Smrg{
2600f8248bfSmrg    const wchar_t *src;
2611ab64890Smrg    char *dst = (char *) *to;
2621ab64890Smrg    CodeSet codeset;
2631ab64890Smrg    State state = (State) conv->state;
2641ab64890Smrg    char ch[MB_LEN_MAX];
2651ab64890Smrg    int unconv = 0;
2661ab64890Smrg
2671ab64890Smrg    if (from == NULL || *from == NULL)
2681ab64890Smrg	return 0;
2691ab64890Smrg
2700f8248bfSmrg    src = (const wchar_t *) *from;
2710f8248bfSmrg
2721ab64890Smrg    while (*from_left && *to_left) {
2731ab64890Smrg	(*from_left)--;
2741ab64890Smrg	if (state->WCtoMB (state, *src++, ch)) {
2751ab64890Smrg	    codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset;
2761ab64890Smrg	    if (codeset && codeset->string_encoding) {
2771ab64890Smrg		*dst++ = *ch;
2781ab64890Smrg		(*to_left)--;
2791ab64890Smrg	    } else {
2801ab64890Smrg		unconv++;
2811ab64890Smrg	    }
2821ab64890Smrg	} else {
2831ab64890Smrg	    unconv++;
2841ab64890Smrg	}
2851ab64890Smrg    }
2861ab64890Smrg    *from = (XPointer) src;
2871ab64890Smrg    *to = (XPointer) dst;
2881ab64890Smrg    return unconv;
2891ab64890Smrg}
2901ab64890Smrg
2911ab64890Smrgstatic int
2921ab64890Smrgmbstocs(
2931ab64890Smrg    XlcConv conv,
2941ab64890Smrg    XPointer *from,
2951ab64890Smrg    int *from_left,
2961ab64890Smrg    XPointer *to,
2971ab64890Smrg    int *to_left,
2981ab64890Smrg    XPointer *args,
2991ab64890Smrg    int num_args)
3001ab64890Smrg{
3010f8248bfSmrg    const char *src;
3021ab64890Smrg    char *dst = (char *) *to;
3031ab64890Smrg    int length;
3041ab64890Smrg    State state = (State) conv->state;
3051ab64890Smrg    char cur_side;
3061ab64890Smrg    int unconv = 0;
3071ab64890Smrg
3081ab64890Smrg    if (from == NULL || *from == NULL)
3091ab64890Smrg	return 0;
3101ab64890Smrg
3110f8248bfSmrg    src = (const char *) *from;
3121ab64890Smrg    length = min(*from_left, *to_left);
3131ab64890Smrg
3141ab64890Smrg    cur_side = *src & GR;
3151ab64890Smrg    while (length) {
3161ab64890Smrg	if ((char) (*src & GR) != cur_side)
3171ab64890Smrg	    break;
3181ab64890Smrg	*dst++ = *src++;
3191ab64890Smrg	length--;
3201ab64890Smrg    }
3211ab64890Smrg
3221ab64890Smrg    if (num_args > 0) {
3231ab64890Smrg	XlcCharSet      charset = get_charset(state, cur_side);
3241ab64890Smrg	if (charset) {
3251ab64890Smrg	    *((XlcCharSet *) args[0]) = charset;
3261ab64890Smrg	} else {
3271ab64890Smrg	    dst = *to;
3281ab64890Smrg	    unconv = -1;
3291ab64890Smrg	}
3301ab64890Smrg    }
3311ab64890Smrg    *from_left -= src - (char *) *from;
3321ab64890Smrg    *to_left -= dst - (char *) *to;
3331ab64890Smrg    *from = (XPointer) src;
3341ab64890Smrg    *to = (XPointer) dst;
3351ab64890Smrg    return unconv;
3361ab64890Smrg}
3371ab64890Smrg
3381ab64890Smrgstatic int
3391ab64890Smrgwcstocs(
3401ab64890Smrg    XlcConv conv,
3411ab64890Smrg    XPointer *from,
3421ab64890Smrg    int *from_left,
3431ab64890Smrg    XPointer *to,
3441ab64890Smrg    int *to_left,
3451ab64890Smrg    XPointer *args,
3461ab64890Smrg    int num_args)
3471ab64890Smrg{
3480f8248bfSmrg    const wchar_t *src;
3491ab64890Smrg    char *dst = (char *) *to;
3501ab64890Smrg    State state = (State) conv->state;
3511ab64890Smrg    char cur_side = 0, ch[MB_LEN_MAX];
3521ab64890Smrg    int unconv = 0;
3531ab64890Smrg    Bool found = False;
3541ab64890Smrg
3551ab64890Smrg    if (from == NULL || *from == NULL)
3561ab64890Smrg	return 0;
3571ab64890Smrg
3580f8248bfSmrg    src = (const wchar_t *) *from;
3590f8248bfSmrg
3601ab64890Smrg    while (*from_left) {
3611ab64890Smrg	if ((found = state->WCtoMB (state, *src, ch)))
3621ab64890Smrg	    break;
3631ab64890Smrg	unconv++;
3641ab64890Smrg	src++;
3651ab64890Smrg	(*from_left)--;
3661ab64890Smrg    }
3671ab64890Smrg
3681ab64890Smrg    if (found) {
3691ab64890Smrg	cur_side = *ch & GR;
3701ab64890Smrg	while (*from_left && *to_left) {
3711ab64890Smrg	    (*from_left)--;
3721ab64890Smrg	    if (state->WCtoMB (state, *src++, ch)) {
3731ab64890Smrg		if ((char) (*ch & GR) != cur_side) {
3741ab64890Smrg		    src--;
3751ab64890Smrg		    (*from_left)++;
3761ab64890Smrg		    break;
3771ab64890Smrg		} else {
3781ab64890Smrg		    *dst++ = *ch;
3791ab64890Smrg		    (*to_left)--;
3801ab64890Smrg		}
3811ab64890Smrg	    } else {
3821ab64890Smrg		unconv++;
3831ab64890Smrg	    }
3841ab64890Smrg	}
3851ab64890Smrg    } else {
3861ab64890Smrg	unconv++;
3871ab64890Smrg    }
3881ab64890Smrg
3891ab64890Smrg    if (num_args > 0) {
3901ab64890Smrg	XlcCharSet charset = get_charset(state, cur_side);
3911ab64890Smrg	if (charset) {
3921ab64890Smrg	    *((XlcCharSet *) args[0]) = charset;
3931ab64890Smrg	} else {
3941ab64890Smrg	    unconv = -1;
3951ab64890Smrg	}
3961ab64890Smrg    }
3971ab64890Smrg    *from = (XPointer) src;
3981ab64890Smrg    *to = (XPointer) dst;
3991ab64890Smrg    return unconv;
4001ab64890Smrg}
4011ab64890Smrg
4021ab64890Smrgstatic int
4031ab64890Smrgcstombs(
4041ab64890Smrg    XlcConv conv,
4051ab64890Smrg    XPointer *from,
4061ab64890Smrg    int *from_left,
4071ab64890Smrg    XPointer *to,
4081ab64890Smrg    int *to_left,
4091ab64890Smrg    XPointer *args,
4101ab64890Smrg    int num_args)
4111ab64890Smrg{
4120f8248bfSmrg    const char *src;
4131ab64890Smrg    char *dst = (char *) *to;
4141ab64890Smrg    CodeSet codeset;
4151ab64890Smrg    XlcCharSet charset;
4161ab64890Smrg    State state = (State) conv->state;
4171ab64890Smrg    unsigned char cur_side = 0;
4181ab64890Smrg    int i;
4191ab64890Smrg    Bool found = False;
4201ab64890Smrg
4211ab64890Smrg    if (from == NULL || *from == NULL)
4221ab64890Smrg	return 0;
4231ab64890Smrg
4240f8248bfSmrg    src = (const char *) *from;
4250f8248bfSmrg
4261ab64890Smrg    if (num_args > 0) {
4271ab64890Smrg	charset = (XlcCharSet) args[0];
4281ab64890Smrg	if (charset == NULL)
4291ab64890Smrg	    return -1;
4301ab64890Smrg    } else {
4311ab64890Smrg	return -1;
4321ab64890Smrg    }
4331ab64890Smrg
4341ab64890Smrg    if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) {
4351ab64890Smrg	codeset = state->GL_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 = 0;
4411ab64890Smrg		    break;
4421ab64890Smrg		}
4431ab64890Smrg	}
4441ab64890Smrg    }
4451ab64890Smrg    if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) {
4461ab64890Smrg	codeset = state->GR_codeset;
4471ab64890Smrg	if (codeset) {
4481ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
4491ab64890Smrg		if (charset == codeset->charset_list[i]) {
4501ab64890Smrg		    found = True;
4511ab64890Smrg		    cur_side = GR;
4521ab64890Smrg		    break;
4531ab64890Smrg		}
4541ab64890Smrg	}
4551ab64890Smrg    }
4561ab64890Smrg    if (found) {
4571ab64890Smrg	int length = min(*from_left, *to_left);
4581ab64890Smrg	while (length) {
4591ab64890Smrg	    *dst++ = *src++ | cur_side;
4601ab64890Smrg	    length--;
4611ab64890Smrg	}
4621ab64890Smrg    } else {
4631ab64890Smrg	return -1;
4641ab64890Smrg    }
4651ab64890Smrg
4661ab64890Smrg    *from_left -= src - (char *) *from;
4671ab64890Smrg    *to_left -= dst - (char *) *to;
4681ab64890Smrg    *from = (XPointer) src;
4691ab64890Smrg    *to = (XPointer) dst;
4701ab64890Smrg    return 0;
4711ab64890Smrg}
4721ab64890Smrg
4731ab64890Smrgstatic int
4741ab64890Smrgcstowcs(
4751ab64890Smrg    XlcConv conv,
4761ab64890Smrg    XPointer *from,
4771ab64890Smrg    int *from_left,
4781ab64890Smrg    XPointer *to,
4791ab64890Smrg    int *to_left,
4801ab64890Smrg    XPointer *args,
4811ab64890Smrg    int num_args)
4821ab64890Smrg{
4830f8248bfSmrg    const char *src;
4840f8248bfSmrg    wchar_t *dst = (wchar_t *) *to;
4851ab64890Smrg    CodeSet codeset;
4861ab64890Smrg    XlcCharSet charset;
4871ab64890Smrg    State state = (State) conv->state;
4881ab64890Smrg    Bool found = False;
4891ab64890Smrg    int i, unconv = 0;
4901ab64890Smrg    unsigned char cur_side = 0;
4911ab64890Smrg
4921ab64890Smrg    if (from == NULL || *from == NULL)
4931ab64890Smrg	return 0;
4941ab64890Smrg
4950f8248bfSmrg    src = (const char *) *from;
4960f8248bfSmrg
4971ab64890Smrg    if (num_args > 0) {
4981ab64890Smrg	charset = (XlcCharSet) args[0];
4991ab64890Smrg	if (charset == NULL)
5001ab64890Smrg	    return -1;
5011ab64890Smrg    } else {
5021ab64890Smrg	return -1;
5031ab64890Smrg    }
5041ab64890Smrg
5051ab64890Smrg    if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) {
5061ab64890Smrg	codeset = state->GL_codeset;
5071ab64890Smrg	if (codeset) {
5081ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
5091ab64890Smrg		if (charset == codeset->charset_list[i]) {
5101ab64890Smrg		    found = True;
5111ab64890Smrg		    cur_side = 0;
5121ab64890Smrg		    break;
5131ab64890Smrg		}
5141ab64890Smrg	}
5151ab64890Smrg    }
5161ab64890Smrg    if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) {
5171ab64890Smrg	codeset = state->GR_codeset;
5181ab64890Smrg	if (codeset) {
5191ab64890Smrg	    for (i = 0; i < codeset->num_charsets; i++)
5201ab64890Smrg		if (charset == codeset->charset_list[i]) {
5211ab64890Smrg		    found = True;
5221ab64890Smrg		    cur_side = GR;
5231ab64890Smrg		    break;
5241ab64890Smrg		}
5251ab64890Smrg	}
5261ab64890Smrg    }
5271ab64890Smrg    if (found) {
5281ab64890Smrg	char ch;
5291ab64890Smrg	while (*from_left && *to_left) {
5301ab64890Smrg	    ch = *src++ | cur_side;
5311ab64890Smrg	    (*from_left)--;
5321ab64890Smrg	    if (state->MBtoWC (state, &ch, dst)) {
5331ab64890Smrg		dst++;
5341ab64890Smrg		(*to_left)--;
5351ab64890Smrg	    } else {
5361ab64890Smrg		unconv++;
5371ab64890Smrg	    }
5381ab64890Smrg	}
5391ab64890Smrg    } else {
5401ab64890Smrg	return -1;
5411ab64890Smrg    }
5421ab64890Smrg    *from = (XPointer) src;
5431ab64890Smrg    *to = (XPointer) dst;
5441ab64890Smrg    return unconv;
5451ab64890Smrg}
5461ab64890Smrg
5471ab64890Smrgstatic int
5481ab64890Smrgstrtombs(
5491ab64890Smrg    XlcConv conv,
5501ab64890Smrg    XPointer *from,
5511ab64890Smrg    int *from_left,
5521ab64890Smrg    XPointer *to,
5531ab64890Smrg    int *to_left,
5541ab64890Smrg    XPointer *args,
5551ab64890Smrg    int num_args)
5561ab64890Smrg{
5570f8248bfSmrg    const char *src;
5581ab64890Smrg    char *dst = (char *) *to;
5591ab64890Smrg    int length;
5601ab64890Smrg
5611ab64890Smrg    if (from == NULL || *from == NULL)
5621ab64890Smrg	return 0;
5631ab64890Smrg
5640f8248bfSmrg    src = (const char *) *from;
5651ab64890Smrg    length = min(*from_left, *to_left);
5661ab64890Smrg    while (length) {
5671ab64890Smrg	*dst++ = *src++;
5681ab64890Smrg	length--;
5691ab64890Smrg    }
5701ab64890Smrg
5711ab64890Smrg    *from_left -= src - (char *) *from;
5721ab64890Smrg    *to_left -= dst - (char *) *to;
5731ab64890Smrg    *from = (XPointer) src;
5741ab64890Smrg    *to = (XPointer) dst;
5751ab64890Smrg    return 0;
5761ab64890Smrg}
5771ab64890Smrg
5781ab64890Smrgstatic void
5791ab64890Smrgclose_converter(
5801ab64890Smrg    XlcConv conv)
5811ab64890Smrg{
5821ab64890Smrg
5830f8248bfSmrg    Xfree(conv->state);
584818534a1Smrg    Xfree(conv);
5851ab64890Smrg}
5861ab64890Smrg
5871ab64890Smrgstatic XlcConv
5881ab64890Smrgcreate_conv(
5891ab64890Smrg    XLCd lcd,
5901ab64890Smrg    XlcConvMethods methods)
5911ab64890Smrg{
5921ab64890Smrg    XlcConv conv;
5931ab64890Smrg    State state;
5941ab64890Smrg
595818534a1Smrg    conv = Xcalloc(1, sizeof(XlcConvRec));
5961ab64890Smrg    if (conv == NULL)
5971ab64890Smrg	return (XlcConv) NULL;
5981ab64890Smrg
599818534a1Smrg    state = Xmalloc(sizeof(StateRec));
6001ab64890Smrg    if (state == NULL) {
6011ab64890Smrg	close_converter(conv);
6021ab64890Smrg	return (XlcConv) NULL;
6031ab64890Smrg    }
6041ab64890Smrg    state->GL_codeset = XLC_GENERIC(lcd, initial_state_GL);
6051ab64890Smrg    state->GR_codeset = XLC_GENERIC(lcd, initial_state_GR);
6061ab64890Smrg    state->wc_mask = (1 << XLC_GENERIC(lcd, wc_shift_bits)) - 1;
6071ab64890Smrg    state->wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask);
6081ab64890Smrg
6091ab64890Smrg#ifdef STDCVT
6101ab64890Smrg    if (XLC_GENERIC(lcd, use_stdc_env) == True)
6111ab64890Smrg	state->MBtoWC = &MBtoWCstd;
6121ab64890Smrg    else
6131ab64890Smrg#endif
6141ab64890Smrg	state->MBtoWC = &MBtoWCdef;
6151ab64890Smrg
6161ab64890Smrg#ifdef STDCVT
6171ab64890Smrg    if (XLC_GENERIC(lcd, use_stdc_env) == True)
6181ab64890Smrg	state->WCtoMB = &WCtoMBstd;
6191ab64890Smrg    else
6201ab64890Smrg#endif
6211ab64890Smrg	state->WCtoMB = &WCtoMBdef;
6221ab64890Smrg
6231ab64890Smrg    conv->methods = methods;
6241ab64890Smrg    conv->state = (XPointer) state;
6251ab64890Smrg
6261ab64890Smrg    return conv;
6271ab64890Smrg}
6281ab64890Smrg
6291ab64890Smrgstatic XlcConvMethodsRec mbstowcs_methods = {
6301ab64890Smrg    close_converter,
6311ab64890Smrg    def_mbstowcs,
6321ab64890Smrg    NULL
6331ab64890Smrg};
6341ab64890Smrg
6351ab64890Smrgstatic XlcConv
6361ab64890Smrgopen_mbstowcs(
6371ab64890Smrg    XLCd from_lcd,
6381ab64890Smrg    const char *from_type,
6391ab64890Smrg    XLCd to_lcd,
6401ab64890Smrg    const char *to_type)
6411ab64890Smrg{
6421ab64890Smrg    return create_conv(from_lcd, &mbstowcs_methods);
6431ab64890Smrg}
6441ab64890Smrg
6451ab64890Smrgstatic XlcConvMethodsRec mbstostr_methods = {
6461ab64890Smrg    close_converter,
6471ab64890Smrg    mbstostr,
6481ab64890Smrg    NULL
6491ab64890Smrg};
6501ab64890Smrg
6511ab64890Smrgstatic XlcConv
6521ab64890Smrgopen_mbstostr(
6531ab64890Smrg    XLCd from_lcd,
6541ab64890Smrg    const char *from_type,
6551ab64890Smrg    XLCd to_lcd,
6561ab64890Smrg    const char *to_type)
6571ab64890Smrg{
6581ab64890Smrg    return create_conv(from_lcd, &mbstostr_methods);
6591ab64890Smrg}
6601ab64890Smrg
6611ab64890Smrgstatic XlcConvMethodsRec mbstocs_methods = {
6621ab64890Smrg    close_converter,
6631ab64890Smrg    mbstocs,
6641ab64890Smrg    NULL
6651ab64890Smrg};
6661ab64890Smrg
6671ab64890Smrgstatic XlcConv
6681ab64890Smrgopen_mbstocs(
6691ab64890Smrg    XLCd from_lcd,
6701ab64890Smrg    const char *from_type,
6711ab64890Smrg    XLCd to_lcd,
6721ab64890Smrg    const char *to_type)
6731ab64890Smrg{
6741ab64890Smrg    return create_conv(from_lcd, &mbstocs_methods);
6751ab64890Smrg}
6761ab64890Smrg
6771ab64890Smrgstatic XlcConvMethodsRec wcstombs_methods = {
6781ab64890Smrg    close_converter,
6791ab64890Smrg    def_wcstombs,
6801ab64890Smrg    NULL
6811ab64890Smrg};
6821ab64890Smrg
6831ab64890Smrgstatic XlcConv
6841ab64890Smrgopen_wcstombs(
6851ab64890Smrg    XLCd from_lcd,
6861ab64890Smrg    const char *from_type,
6871ab64890Smrg    XLCd to_lcd,
6881ab64890Smrg    const char *to_type)
6891ab64890Smrg{
6901ab64890Smrg    return create_conv(from_lcd, &wcstombs_methods);
6911ab64890Smrg}
6921ab64890Smrg
6931ab64890Smrgstatic XlcConvMethodsRec wcstostr_methods = {
6941ab64890Smrg    close_converter,
6951ab64890Smrg    wcstostr,
6961ab64890Smrg    NULL
6971ab64890Smrg};
6981ab64890Smrg
6991ab64890Smrgstatic XlcConv
7001ab64890Smrgopen_wcstostr(
7011ab64890Smrg    XLCd from_lcd,
7021ab64890Smrg    const char *from_type,
7031ab64890Smrg    XLCd to_lcd,
7041ab64890Smrg    const char *to_type)
7051ab64890Smrg{
7061ab64890Smrg    return create_conv(from_lcd, &wcstostr_methods);
7071ab64890Smrg}
7081ab64890Smrg
7091ab64890Smrgstatic XlcConvMethodsRec wcstocs_methods = {
7101ab64890Smrg    close_converter,
7111ab64890Smrg    wcstocs,
7121ab64890Smrg    NULL
7131ab64890Smrg};
7141ab64890Smrg
7151ab64890Smrgstatic XlcConv
7161ab64890Smrgopen_wcstocs(
7171ab64890Smrg    XLCd from_lcd,
7181ab64890Smrg    const char *from_type,
7191ab64890Smrg    XLCd to_lcd,
7201ab64890Smrg    const char *to_type)
7211ab64890Smrg{
7221ab64890Smrg    return create_conv(from_lcd, &wcstocs_methods);
7231ab64890Smrg}
7241ab64890Smrg
7251ab64890Smrgstatic XlcConvMethodsRec strtombs_methods = {
7261ab64890Smrg    close_converter,
7271ab64890Smrg    strtombs,
7281ab64890Smrg    NULL
7291ab64890Smrg};
7301ab64890Smrg
7311ab64890Smrgstatic XlcConv
7321ab64890Smrgopen_strtombs(
7331ab64890Smrg    XLCd from_lcd,
7341ab64890Smrg    const char *from_type,
7351ab64890Smrg    XLCd to_lcd,
7361ab64890Smrg    const char *to_type)
7371ab64890Smrg{
7381ab64890Smrg    return create_conv(from_lcd, &strtombs_methods);
7391ab64890Smrg}
7401ab64890Smrg
7411ab64890Smrgstatic XlcConvMethodsRec cstombs_methods = {
7421ab64890Smrg    close_converter,
7431ab64890Smrg    cstombs,
7441ab64890Smrg    NULL
7451ab64890Smrg};
7461ab64890Smrg
7471ab64890Smrgstatic XlcConv
7481ab64890Smrgopen_cstombs(
7491ab64890Smrg    XLCd from_lcd,
7501ab64890Smrg    const char *from_type,
7511ab64890Smrg    XLCd to_lcd,
7521ab64890Smrg    const char *to_type)
7531ab64890Smrg{
7541ab64890Smrg    return create_conv(from_lcd, &cstombs_methods);
7551ab64890Smrg}
7561ab64890Smrg
7571ab64890Smrgstatic XlcConvMethodsRec cstowcs_methods = {
7581ab64890Smrg    close_converter,
7591ab64890Smrg    cstowcs,
7601ab64890Smrg    NULL
7611ab64890Smrg};
7621ab64890Smrg
7631ab64890Smrgstatic XlcConv
7641ab64890Smrgopen_cstowcs(
7651ab64890Smrg    XLCd from_lcd,
7661ab64890Smrg    const char *from_type,
7671ab64890Smrg    XLCd to_lcd,
7681ab64890Smrg    const char *to_type)
7691ab64890Smrg{
7701ab64890Smrg    return create_conv(from_lcd, &cstowcs_methods);
7711ab64890Smrg}
7721ab64890Smrg
7731ab64890SmrgXLCd
7741ab64890Smrg_XlcDefaultLoader(
7751ab64890Smrg    const char *name)
7761ab64890Smrg{
7771ab64890Smrg    XLCd lcd;
7781ab64890Smrg
7791ab64890Smrg    lcd = _XlcCreateLC(name, _XlcGenericMethods);
7801ab64890Smrg    if (lcd == NULL)
7811ab64890Smrg	return lcd;
7821ab64890Smrg
7831ab64890Smrg    if (XLC_PUBLIC(lcd, mb_cur_max) != 1){
7841ab64890Smrg        _XlcDestroyLC(lcd);
7851ab64890Smrg        return (XLCd) NULL;
7861ab64890Smrg    }
7871ab64890Smrg
7881ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs);
7891ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_mbstostr);
7901ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs);
7911ab64890Smrg    _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbstocs);
7921ab64890Smrg
7931ab64890Smrg    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs);
7941ab64890Smrg    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr);
7951ab64890Smrg    _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs);
7961ab64890Smrg
7971ab64890Smrg    _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtombs);
7981ab64890Smrg    _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_mbstowcs);
7991ab64890Smrg
8001ab64890Smrg    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs);
8011ab64890Smrg    _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs);
8021ab64890Smrg
8031ab64890Smrg    _XlcAddUtf8Converters(lcd);
8041ab64890Smrg
8051ab64890Smrg    return lcd;
8061ab64890Smrg}
807