lcConv.c revision 1ab64890
11ab64890Smrg/* $Xorg: lcConv.c,v 1.4 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/* $XFree86: xc/lib/X11/lcConv.c,v 1.5 2000/12/04 18:49:26 dawes Exp $ */
271ab64890Smrg
281ab64890Smrg#ifdef HAVE_CONFIG_H
291ab64890Smrg#include <config.h>
301ab64890Smrg#endif
311ab64890Smrg#include "Xlibint.h"
321ab64890Smrg#include "XlcPubI.h"
331ab64890Smrg#include <stdio.h>
341ab64890Smrg
351ab64890Smrgtypedef struct _XlcConverterListRec {
361ab64890Smrg    XLCd from_lcd;
371ab64890Smrg    const char *from;
381ab64890Smrg    XrmQuark from_type;
391ab64890Smrg    XLCd to_lcd;
401ab64890Smrg    const char *to;
411ab64890Smrg    XrmQuark to_type;
421ab64890Smrg    XlcOpenConverterProc converter;
431ab64890Smrg    struct _XlcConverterListRec *next;
441ab64890Smrg} XlcConverterListRec, *XlcConverterList;
451ab64890Smrg
461ab64890Smrgstatic XlcConverterList conv_list = NULL;
471ab64890Smrg
481ab64890Smrgstatic void
491ab64890Smrgclose_converter(
501ab64890Smrg    XlcConv conv)
511ab64890Smrg{
521ab64890Smrg    (*conv->methods->close)(conv);
531ab64890Smrg}
541ab64890Smrg
551ab64890Smrgstatic XlcConv
561ab64890Smrgget_converter(
571ab64890Smrg    XLCd from_lcd,
581ab64890Smrg    XrmQuark from_type,
591ab64890Smrg    XLCd to_lcd,
601ab64890Smrg    XrmQuark to_type)
611ab64890Smrg{
621ab64890Smrg    XlcConverterList list, prev = NULL;
631ab64890Smrg
641ab64890Smrg    for (list = conv_list; list; list = list->next) {
651ab64890Smrg	if (list->from_lcd == from_lcd && list->to_lcd == to_lcd
661ab64890Smrg	    && list->from_type == from_type && list->to_type == to_type) {
671ab64890Smrg
681ab64890Smrg	    if (prev && prev != conv_list) {	/* XXX */
691ab64890Smrg		prev->next = list->next;
701ab64890Smrg		list->next = conv_list;
711ab64890Smrg		conv_list = list;
721ab64890Smrg	    }
731ab64890Smrg
741ab64890Smrg	    return (*list->converter)(from_lcd, list->from, to_lcd, list->to);
751ab64890Smrg	}
761ab64890Smrg
771ab64890Smrg	prev = list;
781ab64890Smrg    }
791ab64890Smrg
801ab64890Smrg    return (XlcConv) NULL;
811ab64890Smrg}
821ab64890Smrg
831ab64890SmrgBool
841ab64890Smrg_XlcSetConverter(
851ab64890Smrg    XLCd from_lcd,
861ab64890Smrg    const char *from,
871ab64890Smrg    XLCd to_lcd,
881ab64890Smrg    const char *to,
891ab64890Smrg    XlcOpenConverterProc converter)
901ab64890Smrg{
911ab64890Smrg    XlcConverterList list;
921ab64890Smrg    XrmQuark from_type, to_type;
931ab64890Smrg
941ab64890Smrg    from_type = XrmStringToQuark(from);
951ab64890Smrg    to_type = XrmStringToQuark(to);
961ab64890Smrg
971ab64890Smrg    for (list = conv_list; list; list = list->next) {
981ab64890Smrg	if (list->from_lcd == from_lcd && list->to_lcd == to_lcd
991ab64890Smrg	    && list->from_type == from_type && list->to_type == to_type) {
1001ab64890Smrg
1011ab64890Smrg	    list->converter = converter;
1021ab64890Smrg	    return True;
1031ab64890Smrg	}
1041ab64890Smrg    }
1051ab64890Smrg
1061ab64890Smrg    list = (XlcConverterList) Xmalloc(sizeof(XlcConverterListRec));
1071ab64890Smrg    if (list == NULL)
1081ab64890Smrg	return False;
1091ab64890Smrg
1101ab64890Smrg    list->from_lcd = from_lcd;
1111ab64890Smrg    list->from = from;
1121ab64890Smrg    list->from_type = from_type;
1131ab64890Smrg    list->to_lcd = to_lcd;
1141ab64890Smrg    list->to = to;
1151ab64890Smrg    list->to_type = to_type;
1161ab64890Smrg    list->converter = converter;
1171ab64890Smrg    list->next = conv_list;
1181ab64890Smrg    conv_list = list;
1191ab64890Smrg
1201ab64890Smrg    return True;
1211ab64890Smrg}
1221ab64890Smrg
1231ab64890Smrgtypedef struct _ConvRec {
1241ab64890Smrg    XlcConv from_conv;
1251ab64890Smrg    XlcConv to_conv;
1261ab64890Smrg} ConvRec, *Conv;
1271ab64890Smrg
1281ab64890Smrgstatic int
1291ab64890Smrgindirect_convert(
1301ab64890Smrg    XlcConv lc_conv,
1311ab64890Smrg    XPointer *from,
1321ab64890Smrg    int *from_left,
1331ab64890Smrg    XPointer *to,
1341ab64890Smrg    int *to_left,
1351ab64890Smrg    XPointer *args,
1361ab64890Smrg    int num_args)
1371ab64890Smrg{
1381ab64890Smrg    Conv conv = (Conv) lc_conv->state;
1391ab64890Smrg    XlcConv from_conv = conv->from_conv;
1401ab64890Smrg    XlcConv to_conv = conv->to_conv;
1411ab64890Smrg    XlcCharSet charset;
1421ab64890Smrg    char buf[BUFSIZ], *cs;
1431ab64890Smrg    XPointer tmp_args[1];
1441ab64890Smrg    int cs_left, ret, length, unconv_num = 0;
1451ab64890Smrg
1461ab64890Smrg    if (from == NULL || *from == NULL) {
1471ab64890Smrg	if (from_conv->methods->reset)
1481ab64890Smrg	    (*from_conv->methods->reset)(from_conv);
1491ab64890Smrg
1501ab64890Smrg	if (to_conv->methods->reset)
1511ab64890Smrg	    (*to_conv->methods->reset)(to_conv);
1521ab64890Smrg
1531ab64890Smrg	return 0;
1541ab64890Smrg    }
1551ab64890Smrg
1561ab64890Smrg    while (*from_left > 0) {
1571ab64890Smrg	cs = buf;
1581ab64890Smrg	cs_left = BUFSIZ;
1591ab64890Smrg	tmp_args[0] = (XPointer) &charset;
1601ab64890Smrg
1611ab64890Smrg	ret = (*from_conv->methods->convert)(from_conv, from, from_left, &cs,
1621ab64890Smrg					     &cs_left, tmp_args, 1);
1631ab64890Smrg	if (ret < 0)
1641ab64890Smrg	    break;
1651ab64890Smrg
1661ab64890Smrg	unconv_num += ret;
1671ab64890Smrg
1681ab64890Smrg	length = cs - buf;
1691ab64890Smrg	if (length > 0) {
1701ab64890Smrg	    cs_left = length;
1711ab64890Smrg	    cs = buf;
1721ab64890Smrg
1731ab64890Smrg	    tmp_args[0] = (XPointer) charset;
1741ab64890Smrg
1751ab64890Smrg	    ret = (*to_conv->methods->convert)(to_conv, &cs, &cs_left, to, to_left,
1761ab64890Smrg					       tmp_args, 1);
1771ab64890Smrg	    if (ret < 0) {
1781ab64890Smrg		unconv_num += length / (charset->char_size > 0 ? charset->char_size : 1);
1791ab64890Smrg		continue;
1801ab64890Smrg	    }
1811ab64890Smrg
1821ab64890Smrg	    unconv_num += ret;
1831ab64890Smrg
1841ab64890Smrg	    if (*to_left < 1)
1851ab64890Smrg		break;
1861ab64890Smrg	}
1871ab64890Smrg    }
1881ab64890Smrg
1891ab64890Smrg    return unconv_num;
1901ab64890Smrg}
1911ab64890Smrg
1921ab64890Smrgstatic void
1931ab64890Smrgclose_indirect_converter(
1941ab64890Smrg    XlcConv lc_conv)
1951ab64890Smrg{
1961ab64890Smrg    Conv conv = (Conv) lc_conv->state;
1971ab64890Smrg
1981ab64890Smrg    if (conv) {
1991ab64890Smrg	if (conv->from_conv)
2001ab64890Smrg	    close_converter(conv->from_conv);
2011ab64890Smrg	if (conv->to_conv)
2021ab64890Smrg	    close_converter(conv->to_conv);
2031ab64890Smrg
2041ab64890Smrg	Xfree((char *) conv);
2051ab64890Smrg    }
2061ab64890Smrg
2071ab64890Smrg    Xfree((char *) lc_conv);
2081ab64890Smrg}
2091ab64890Smrg
2101ab64890Smrgstatic void
2111ab64890Smrgreset_indirect_converter(
2121ab64890Smrg    XlcConv lc_conv)
2131ab64890Smrg{
2141ab64890Smrg    Conv conv = (Conv) lc_conv->state;
2151ab64890Smrg
2161ab64890Smrg    if (conv) {
2171ab64890Smrg	if (conv->from_conv && conv->from_conv->methods->reset)
2181ab64890Smrg	    (*conv->from_conv->methods->reset)(conv->from_conv);
2191ab64890Smrg	if (conv->to_conv && conv->to_conv->methods->reset)
2201ab64890Smrg	    (*conv->to_conv->methods->reset)(conv->to_conv);
2211ab64890Smrg    }
2221ab64890Smrg}
2231ab64890Smrg
2241ab64890Smrgstatic XlcConvMethodsRec conv_methods = {
2251ab64890Smrg    close_indirect_converter,
2261ab64890Smrg    indirect_convert,
2271ab64890Smrg    reset_indirect_converter
2281ab64890Smrg} ;
2291ab64890Smrg
2301ab64890Smrgstatic XlcConv
2311ab64890Smrgopen_indirect_converter(
2321ab64890Smrg    XLCd from_lcd,
2331ab64890Smrg    const char *from,
2341ab64890Smrg    XLCd to_lcd,
2351ab64890Smrg    const char *to)
2361ab64890Smrg{
2371ab64890Smrg    XlcConv lc_conv, from_conv, to_conv;
2381ab64890Smrg    Conv conv;
2391ab64890Smrg    XrmQuark from_type, to_type;
2401ab64890Smrg    static XrmQuark QChar, QCharSet, QCTCharSet = (XrmQuark) 0;
2411ab64890Smrg
2421ab64890Smrg    if (QCTCharSet == (XrmQuark) 0) {
2431ab64890Smrg	QCTCharSet = XrmStringToQuark(XlcNCTCharSet);
2441ab64890Smrg	QCharSet = XrmStringToQuark(XlcNCharSet);
2451ab64890Smrg	QChar = XrmStringToQuark(XlcNChar);
2461ab64890Smrg    }
2471ab64890Smrg
2481ab64890Smrg    from_type = XrmStringToQuark(from);
2491ab64890Smrg    to_type = XrmStringToQuark(to);
2501ab64890Smrg
2511ab64890Smrg    if (from_type == QCharSet || from_type == QChar || to_type == QCharSet ||
2521ab64890Smrg	to_type == QChar)
2531ab64890Smrg	return (XlcConv) NULL;
2541ab64890Smrg
2551ab64890Smrg    lc_conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
2561ab64890Smrg    if (lc_conv == NULL)
2571ab64890Smrg	return (XlcConv) NULL;
2581ab64890Smrg
2591ab64890Smrg    lc_conv->methods = &conv_methods;
2601ab64890Smrg
2611ab64890Smrg    lc_conv->state = (XPointer) Xcalloc(1, sizeof(ConvRec));
2621ab64890Smrg    if (lc_conv->state == NULL)
2631ab64890Smrg	goto err;
2641ab64890Smrg
2651ab64890Smrg    conv = (Conv) lc_conv->state;
2661ab64890Smrg
2671ab64890Smrg    from_conv = get_converter(from_lcd, from_type, from_lcd, QCTCharSet);
2681ab64890Smrg    if (from_conv == NULL)
2691ab64890Smrg	from_conv = get_converter(from_lcd, from_type, from_lcd, QCharSet);
2701ab64890Smrg    if (from_conv == NULL)
2711ab64890Smrg	from_conv = get_converter((XLCd)NULL, from_type, (XLCd)NULL, QCharSet);
2721ab64890Smrg    if (from_conv == NULL)
2731ab64890Smrg	from_conv = get_converter(from_lcd, from_type, from_lcd, QChar);
2741ab64890Smrg    if (from_conv == NULL)
2751ab64890Smrg	goto err;
2761ab64890Smrg    conv->from_conv = from_conv;
2771ab64890Smrg
2781ab64890Smrg    to_conv = get_converter(to_lcd, QCTCharSet, to_lcd, to_type);
2791ab64890Smrg    if (to_conv == NULL)
2801ab64890Smrg	to_conv = get_converter(to_lcd, QCharSet, to_lcd, to_type);
2811ab64890Smrg    if (to_conv == NULL)
2821ab64890Smrg	to_conv = get_converter((XLCd) NULL, QCharSet, (XLCd) NULL, to_type);
2831ab64890Smrg    if (to_conv == NULL)
2841ab64890Smrg	goto err;
2851ab64890Smrg    conv->to_conv = to_conv;
2861ab64890Smrg
2871ab64890Smrg    return lc_conv;
2881ab64890Smrg
2891ab64890Smrgerr:
2901ab64890Smrg    close_indirect_converter(lc_conv);
2911ab64890Smrg
2921ab64890Smrg    return (XlcConv) NULL;
2931ab64890Smrg}
2941ab64890Smrg
2951ab64890SmrgXlcConv
2961ab64890Smrg_XlcOpenConverter(
2971ab64890Smrg    XLCd from_lcd,
2981ab64890Smrg    const char *from,
2991ab64890Smrg    XLCd to_lcd,
3001ab64890Smrg    const char *to)
3011ab64890Smrg{
3021ab64890Smrg    XlcConv conv;
3031ab64890Smrg    XrmQuark from_type, to_type;
3041ab64890Smrg
3051ab64890Smrg    from_type = XrmStringToQuark(from);
3061ab64890Smrg    to_type = XrmStringToQuark(to);
3071ab64890Smrg
3081ab64890Smrg    if ((conv = get_converter(from_lcd, from_type, to_lcd, to_type)))
3091ab64890Smrg	return conv;
3101ab64890Smrg
3111ab64890Smrg    return open_indirect_converter(from_lcd, from, to_lcd, to);
3121ab64890Smrg}
3131ab64890Smrg
3141ab64890Smrgvoid
3151ab64890Smrg_XlcCloseConverter(
3161ab64890Smrg    XlcConv conv)
3171ab64890Smrg{
3181ab64890Smrg    close_converter(conv);
3191ab64890Smrg}
3201ab64890Smrg
3211ab64890Smrgint
3221ab64890Smrg_XlcConvert(
3231ab64890Smrg    XlcConv conv,
3241ab64890Smrg    XPointer *from,
3251ab64890Smrg    int *from_left,
3261ab64890Smrg    XPointer *to,
3271ab64890Smrg    int *to_left,
3281ab64890Smrg    XPointer *args,
3291ab64890Smrg    int num_args)
3301ab64890Smrg{
3311ab64890Smrg    return (*conv->methods->convert)(conv, from, from_left, to, to_left, args,
3321ab64890Smrg				     num_args);
3331ab64890Smrg}
3341ab64890Smrg
3351ab64890Smrgvoid
3361ab64890Smrg_XlcResetConverter(
3371ab64890Smrg    XlcConv conv)
3381ab64890Smrg{
3391ab64890Smrg    if (conv->methods->reset)
3401ab64890Smrg	(*conv->methods->reset)(conv);
3411ab64890Smrg}
342