lcConv.c revision 1ab64890
1/* $Xorg: lcConv.c,v 1.4 2000/08/17 19:45:17 cpqbld Exp $ */
2/*
3 * Copyright 1992, 1993 by TOSHIBA Corp.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation for any purpose and without fee is hereby granted, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of TOSHIBA not be used in advertising
10 * or publicity pertaining to distribution of the software without specific,
11 * written prior permission. TOSHIBA make no representations about the
12 * suitability of this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 *
15 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 * SOFTWARE.
22 *
23 * Author: Katsuhisa Yano	TOSHIBA Corp.
24 *			   	mopi@osa.ilab.toshiba.co.jp
25 */
26/* $XFree86: xc/lib/X11/lcConv.c,v 1.5 2000/12/04 18:49:26 dawes Exp $ */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "Xlibint.h"
32#include "XlcPubI.h"
33#include <stdio.h>
34
35typedef struct _XlcConverterListRec {
36    XLCd from_lcd;
37    const char *from;
38    XrmQuark from_type;
39    XLCd to_lcd;
40    const char *to;
41    XrmQuark to_type;
42    XlcOpenConverterProc converter;
43    struct _XlcConverterListRec *next;
44} XlcConverterListRec, *XlcConverterList;
45
46static XlcConverterList conv_list = NULL;
47
48static void
49close_converter(
50    XlcConv conv)
51{
52    (*conv->methods->close)(conv);
53}
54
55static XlcConv
56get_converter(
57    XLCd from_lcd,
58    XrmQuark from_type,
59    XLCd to_lcd,
60    XrmQuark to_type)
61{
62    XlcConverterList list, prev = NULL;
63
64    for (list = conv_list; list; list = list->next) {
65	if (list->from_lcd == from_lcd && list->to_lcd == to_lcd
66	    && list->from_type == from_type && list->to_type == to_type) {
67
68	    if (prev && prev != conv_list) {	/* XXX */
69		prev->next = list->next;
70		list->next = conv_list;
71		conv_list = list;
72	    }
73
74	    return (*list->converter)(from_lcd, list->from, to_lcd, list->to);
75	}
76
77	prev = list;
78    }
79
80    return (XlcConv) NULL;
81}
82
83Bool
84_XlcSetConverter(
85    XLCd from_lcd,
86    const char *from,
87    XLCd to_lcd,
88    const char *to,
89    XlcOpenConverterProc converter)
90{
91    XlcConverterList list;
92    XrmQuark from_type, to_type;
93
94    from_type = XrmStringToQuark(from);
95    to_type = XrmStringToQuark(to);
96
97    for (list = conv_list; list; list = list->next) {
98	if (list->from_lcd == from_lcd && list->to_lcd == to_lcd
99	    && list->from_type == from_type && list->to_type == to_type) {
100
101	    list->converter = converter;
102	    return True;
103	}
104    }
105
106    list = (XlcConverterList) Xmalloc(sizeof(XlcConverterListRec));
107    if (list == NULL)
108	return False;
109
110    list->from_lcd = from_lcd;
111    list->from = from;
112    list->from_type = from_type;
113    list->to_lcd = to_lcd;
114    list->to = to;
115    list->to_type = to_type;
116    list->converter = converter;
117    list->next = conv_list;
118    conv_list = list;
119
120    return True;
121}
122
123typedef struct _ConvRec {
124    XlcConv from_conv;
125    XlcConv to_conv;
126} ConvRec, *Conv;
127
128static int
129indirect_convert(
130    XlcConv lc_conv,
131    XPointer *from,
132    int *from_left,
133    XPointer *to,
134    int *to_left,
135    XPointer *args,
136    int num_args)
137{
138    Conv conv = (Conv) lc_conv->state;
139    XlcConv from_conv = conv->from_conv;
140    XlcConv to_conv = conv->to_conv;
141    XlcCharSet charset;
142    char buf[BUFSIZ], *cs;
143    XPointer tmp_args[1];
144    int cs_left, ret, length, unconv_num = 0;
145
146    if (from == NULL || *from == NULL) {
147	if (from_conv->methods->reset)
148	    (*from_conv->methods->reset)(from_conv);
149
150	if (to_conv->methods->reset)
151	    (*to_conv->methods->reset)(to_conv);
152
153	return 0;
154    }
155
156    while (*from_left > 0) {
157	cs = buf;
158	cs_left = BUFSIZ;
159	tmp_args[0] = (XPointer) &charset;
160
161	ret = (*from_conv->methods->convert)(from_conv, from, from_left, &cs,
162					     &cs_left, tmp_args, 1);
163	if (ret < 0)
164	    break;
165
166	unconv_num += ret;
167
168	length = cs - buf;
169	if (length > 0) {
170	    cs_left = length;
171	    cs = buf;
172
173	    tmp_args[0] = (XPointer) charset;
174
175	    ret = (*to_conv->methods->convert)(to_conv, &cs, &cs_left, to, to_left,
176					       tmp_args, 1);
177	    if (ret < 0) {
178		unconv_num += length / (charset->char_size > 0 ? charset->char_size : 1);
179		continue;
180	    }
181
182	    unconv_num += ret;
183
184	    if (*to_left < 1)
185		break;
186	}
187    }
188
189    return unconv_num;
190}
191
192static void
193close_indirect_converter(
194    XlcConv lc_conv)
195{
196    Conv conv = (Conv) lc_conv->state;
197
198    if (conv) {
199	if (conv->from_conv)
200	    close_converter(conv->from_conv);
201	if (conv->to_conv)
202	    close_converter(conv->to_conv);
203
204	Xfree((char *) conv);
205    }
206
207    Xfree((char *) lc_conv);
208}
209
210static void
211reset_indirect_converter(
212    XlcConv lc_conv)
213{
214    Conv conv = (Conv) lc_conv->state;
215
216    if (conv) {
217	if (conv->from_conv && conv->from_conv->methods->reset)
218	    (*conv->from_conv->methods->reset)(conv->from_conv);
219	if (conv->to_conv && conv->to_conv->methods->reset)
220	    (*conv->to_conv->methods->reset)(conv->to_conv);
221    }
222}
223
224static XlcConvMethodsRec conv_methods = {
225    close_indirect_converter,
226    indirect_convert,
227    reset_indirect_converter
228} ;
229
230static XlcConv
231open_indirect_converter(
232    XLCd from_lcd,
233    const char *from,
234    XLCd to_lcd,
235    const char *to)
236{
237    XlcConv lc_conv, from_conv, to_conv;
238    Conv conv;
239    XrmQuark from_type, to_type;
240    static XrmQuark QChar, QCharSet, QCTCharSet = (XrmQuark) 0;
241
242    if (QCTCharSet == (XrmQuark) 0) {
243	QCTCharSet = XrmStringToQuark(XlcNCTCharSet);
244	QCharSet = XrmStringToQuark(XlcNCharSet);
245	QChar = XrmStringToQuark(XlcNChar);
246    }
247
248    from_type = XrmStringToQuark(from);
249    to_type = XrmStringToQuark(to);
250
251    if (from_type == QCharSet || from_type == QChar || to_type == QCharSet ||
252	to_type == QChar)
253	return (XlcConv) NULL;
254
255    lc_conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
256    if (lc_conv == NULL)
257	return (XlcConv) NULL;
258
259    lc_conv->methods = &conv_methods;
260
261    lc_conv->state = (XPointer) Xcalloc(1, sizeof(ConvRec));
262    if (lc_conv->state == NULL)
263	goto err;
264
265    conv = (Conv) lc_conv->state;
266
267    from_conv = get_converter(from_lcd, from_type, from_lcd, QCTCharSet);
268    if (from_conv == NULL)
269	from_conv = get_converter(from_lcd, from_type, from_lcd, QCharSet);
270    if (from_conv == NULL)
271	from_conv = get_converter((XLCd)NULL, from_type, (XLCd)NULL, QCharSet);
272    if (from_conv == NULL)
273	from_conv = get_converter(from_lcd, from_type, from_lcd, QChar);
274    if (from_conv == NULL)
275	goto err;
276    conv->from_conv = from_conv;
277
278    to_conv = get_converter(to_lcd, QCTCharSet, to_lcd, to_type);
279    if (to_conv == NULL)
280	to_conv = get_converter(to_lcd, QCharSet, to_lcd, to_type);
281    if (to_conv == NULL)
282	to_conv = get_converter((XLCd) NULL, QCharSet, (XLCd) NULL, to_type);
283    if (to_conv == NULL)
284	goto err;
285    conv->to_conv = to_conv;
286
287    return lc_conv;
288
289err:
290    close_indirect_converter(lc_conv);
291
292    return (XlcConv) NULL;
293}
294
295XlcConv
296_XlcOpenConverter(
297    XLCd from_lcd,
298    const char *from,
299    XLCd to_lcd,
300    const char *to)
301{
302    XlcConv conv;
303    XrmQuark from_type, to_type;
304
305    from_type = XrmStringToQuark(from);
306    to_type = XrmStringToQuark(to);
307
308    if ((conv = get_converter(from_lcd, from_type, to_lcd, to_type)))
309	return conv;
310
311    return open_indirect_converter(from_lcd, from, to_lcd, to);
312}
313
314void
315_XlcCloseConverter(
316    XlcConv conv)
317{
318    close_converter(conv);
319}
320
321int
322_XlcConvert(
323    XlcConv conv,
324    XPointer *from,
325    int *from_left,
326    XPointer *to,
327    int *to_left,
328    XPointer *args,
329    int num_args)
330{
331    return (*conv->methods->convert)(conv, from, from_left, to, to_left, args,
332				     num_args);
333}
334
335void
336_XlcResetConverter(
337    XlcConv conv)
338{
339    if (conv->methods->reset)
340	(*conv->methods->reset)(conv);
341}
342