1/*
2 * Copyright 1992, 1993 by TOSHIBA Corp.
3 *
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of TOSHIBA not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission. TOSHIBA make no representations about the
11 * suitability of this software for any purpose.  It is provided "as is"
12 * without express or implied warranty.
13 *
14 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 * SOFTWARE.
21 *
22 * Author: Katsuhisa Yano	TOSHIBA Corp.
23 *			   	mopi@osa.ilab.toshiba.co.jp
24 * Bug fixes: Bruno Haible	XFree86 Inc.
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include "Xlibint.h"
31#include "XlcPubI.h"
32#include <stdio.h>
33
34/*
35 * Default implementation of methods for Xrm parsing.
36 */
37
38/* ======================= Unibyte implementation ======================= */
39
40/* Only for efficiency, to speed up things. */
41
42/* This implementation must keep the locale, for lcname. */
43typedef struct _UbStateRec {
44    XLCd	lcd;
45} UbStateRec, *UbState;
46
47/* Sets the state to the initial state.
48   Initiates a sequence of calls to mbchar. */
49static void
50ub_mbinit(
51    XPointer state)
52{
53}
54
55/* Transforms one multibyte character, and return a 'char' in the same
56   parsing class. Returns the number of consumed bytes in *lenp. */
57static char
58ub_mbchar(
59    XPointer state,
60    const char *str,
61    int	*lenp)
62{
63    *lenp = 1;
64    return *str;
65}
66
67/* Terminates a sequence of calls to mbchar. */
68static void
69ub_mbfinish(
70    XPointer state)
71{
72}
73
74/* Returns the name of the state's locale, as a static string. */
75static const char *
76ub_lcname(
77    XPointer state)
78{
79    return ((UbState) state)->lcd->core->name;
80}
81
82/* Frees the state, which was allocated by _XrmDefaultInitParseInfo. */
83static void
84ub_destroy(
85    XPointer state)
86{
87    _XCloseLC(((UbState) state)->lcd);
88    Xfree(state);
89}
90
91static const XrmMethodsRec ub_methods = {
92    ub_mbinit,
93    ub_mbchar,
94    ub_mbfinish,
95    ub_lcname,
96    ub_destroy
97};
98
99/* ======================= Multibyte implementation ======================= */
100
101/* This implementation uses an XlcConv from XlcNMultiByte to XlcNWideChar. */
102typedef struct _MbStateRec {
103    XLCd	lcd;
104    XlcConv	conv;
105} MbStateRec, *MbState;
106
107/* Sets the state to the initial state.
108   Initiates a sequence of calls to mbchar. */
109static void
110mb_mbinit(
111    XPointer state)
112{
113    _XlcResetConverter(((MbState) state)->conv);
114}
115
116/* Transforms one multibyte character, and return a 'char' in the same
117   parsing class. Returns the number of consumed bytes in *lenp. */
118static char
119mb_mbchar(
120    XPointer state,
121    const char *str,
122    int	*lenp)
123{
124    XlcConv conv = ((MbState) state)->conv;
125    const char *from;
126    wchar_t *to, wc;
127    int cur_max, i, from_left, to_left, ret;
128
129    cur_max = XLC_PUBLIC(((MbState) state)->lcd, mb_cur_max);
130
131    from = str;
132    /* Determine from_left. Avoid overrun error which could occur if
133       from_left > strlen(str). */
134    from_left = cur_max;
135    for (i = 0; i < cur_max; i++)
136	if (str[i] == '\0') {
137	    from_left = i;
138	    break;
139	}
140    *lenp = from_left;
141
142    to = &wc;
143    to_left = 1;
144
145    ret = _XlcConvert(conv, (XPointer *) &from, &from_left,
146		      (XPointer *) &to, &to_left, NULL, 0);
147    *lenp -= from_left;
148
149    if (ret < 0 || to_left > 0) {
150	/* Invalid or incomplete multibyte character seen. */
151	*lenp = 1;
152	return 0x7f;
153    }
154    /* Return a 'char' equivalent to wc. */
155    return (wc >= 0 && wc <= 0x7f ? wc : 0x7f);
156}
157
158/* Terminates a sequence of calls to mbchar. */
159static void
160mb_mbfinish(
161    XPointer state)
162{
163}
164
165/* Returns the name of the state's locale, as a static string. */
166static const char *
167mb_lcname(
168    XPointer state)
169{
170    return ((MbState) state)->lcd->core->name;
171}
172
173/* Frees the state, which was allocated by _XrmDefaultInitParseInfo. */
174static void
175mb_destroy(
176    XPointer state)
177{
178    _XlcCloseConverter(((MbState) state)->conv);
179    _XCloseLC(((MbState) state)->lcd);
180    Xfree(state);
181}
182
183static const XrmMethodsRec mb_methods = {
184    mb_mbinit,
185    mb_mbchar,
186    mb_mbfinish,
187    mb_lcname,
188    mb_destroy
189};
190
191/* ======================= Exported function ======================= */
192
193XrmMethods
194_XrmDefaultInitParseInfo(
195    XLCd lcd,
196    XPointer *rm_state)
197{
198    if (XLC_PUBLIC(lcd, mb_cur_max) == 1) {
199	/* Unibyte case. */
200	UbState state = Xmalloc(sizeof(UbStateRec));
201	if (state == NULL)
202	    return (XrmMethods) NULL;
203
204	state->lcd = lcd;
205
206	*rm_state = (XPointer) state;
207	return &ub_methods;
208    } else {
209	/* Multibyte case. */
210	MbState state = Xmalloc(sizeof(MbStateRec));
211	if (state == NULL)
212	    return (XrmMethods) NULL;
213
214	state->lcd = lcd;
215	state->conv = _XlcOpenConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar);
216	if (state->conv == NULL) {
217	    Xfree(state);
218	    return (XrmMethods) NULL;
219	}
220
221	*rm_state = (XPointer) state;
222	return &mb_methods;
223    }
224}
225