imConv.c revision 3b4ba46c
1/******************************************************************
2
3              Copyright 1991, 1992 by Fuji Xerox Co.,Ltd.
4	      Copyright 1993, 1994 by FUJITSU LIMITED
5
6Permission to use, copy, modify, distribute, and sell this software
7and its documentation for any purpose is hereby granted without fee,
8provided that the above copyright notice appear in all copies and
9that both that copyright notice and this permission notice appear
10in supporting documentation, and that the name of Fuji Xerox Co.,Ltd.
11, and that the name of FUJITSU LIMITED not be used in advertising or
12publicity pertaining to distribution of the software without specific,
13 written prior permission.
14Fuji Xerox Co.,Ltd. , and FUJITSU LIMITED makes no representations about
15the suitability of this software for any purpose.
16It is provided "as is" without express or implied warranty.
17
18FUJI XEROX CO.,LTD. AND FUJITSU LIMITED DISCLAIMS ALL WARRANTIES WITH
19REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
20MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FUJI XEROX CO.,LTD.
21AND FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT
22OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
25THE USE OR PERFORMANCE OF THIS SOFTWARE.
26
27  Author:   Kazunori Nishihara, Fuji Xerox Co.,Ltd.
28                                kaz@ssdev.ksp.fujixerox.co.jp
29  Modifier: Takashi Fujiwara    FUJITSU LIMITED
30                                fujiwara@a80.tech.yk.fujitsu.co.jp
31
32******************************************************************/
33/* 2000 Modifier: Ivan Pascal	The XFree86 Project.
34 */
35
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39#include <stdio.h>
40#include "Xlibint.h"
41#include "Xlcint.h"
42#include "Ximint.h"
43#include "XlcPubI.h"
44
45#ifdef XKB
46/*
47 * rather than just call _XLookupString (i.e. the pre-XKB XLookupString)
48 * do this because with XKB the event may have some funky modifiers that
49 * _XLookupString doesn't grok.
50 */
51#include "XKBlib.h"
52#define	XLOOKUPSTRING lookup_string
53#else
54#define	XLOOKUPSTRING XLookupString
55#endif
56
57typedef unsigned int ucs4_t;
58
59typedef int (*ucstocsConvProc)(
60    XPointer,
61    unsigned char *,
62    ucs4_t,
63    int
64);
65
66struct SubstRec {
67    const char encoding_name[8];
68    const char charset_name[12];
69};
70
71static const struct SubstRec SubstTable[] = {
72    {"STRING", "ISO8859-1"},
73    {"TIS620", "TIS620-0"},
74    {"UTF-8",  "ISO10646-1"}
75};
76#define num_substitute (sizeof SubstTable / sizeof SubstTable[0])
77
78/*
79 * Given the name of a charset, returns the pointer to convertors
80 * from UCS char to specified charset char.
81 * This converter is needed for _XimGetCharCode subroutine.
82 */
83XPointer
84_XimGetLocaleCode (
85    _Xconst char*	encoding_name)
86{
87    XPointer cvt = _Utf8GetConvByName(encoding_name);
88    if (!cvt && encoding_name) {
89       int i;
90       for (i = 0; i < num_substitute; i++)
91           if (!strcmp(encoding_name, SubstTable[i].encoding_name))
92               return _Utf8GetConvByName(SubstTable[i].charset_name);
93    }
94    return cvt;
95}
96
97/*
98 * Returns the locale dependent representation of a keysym.
99 * The locale's encoding is passed in form of pointer to UCS converter.
100 * The resulting multi-byte sequence is placed starting at buf (a buffer
101 * with nbytes bytes, nbytes should be >= 8) and is NUL terminated.
102 * Returns the length of the resulting multi-byte sequence, excluding the
103 * terminating NUL byte. Return 0 if the keysym is not representable in the
104 * locale
105 */
106/*ARGSUSED*/
107int
108_XimGetCharCode (
109    XPointer            ucs_conv,
110    KeySym 		keysym,
111    unsigned char*	buf,
112    int 		nbytes)
113{
114    int count = 0;
115    ucstocsConvProc cvt = (ucstocsConvProc) ucs_conv;
116    ucs4_t ucs4;
117
118    if (keysym < 0x80) {
119        buf[0] = (char) keysym;
120        count = 1;
121    } else if (cvt) {
122        ucs4 = KeySymToUcs4(keysym);
123        if (ucs4)
124            count = (*cvt)((XPointer)NULL, buf, ucs4, nbytes);
125    }
126
127    if (count < 0)
128       	count = 0;
129    if (count>nbytes)
130        return nbytes;
131    if (count<nbytes)
132        buf[count]= '\0';
133    return count;
134}
135
136#ifdef XKB
137static int lookup_string(
138    XKeyEvent*		event,
139    char*		buffer,
140    int			nbytes,
141    KeySym*		keysym,
142    XComposeStatus*	status)
143{
144    int ret;
145    unsigned ctrls = XkbGetXlibControls (event->display);
146    XkbSetXlibControls (event->display,
147			XkbLC_ForceLatin1Lookup, XkbLC_ForceLatin1Lookup);
148    ret = XLookupString(event, (char *)buffer, nbytes, keysym, status);
149    XkbSetXlibControls (event->display,
150			XkbLC_ForceLatin1Lookup, ctrls);
151    return ret;
152}
153#endif
154
155#define BUF_SIZE (20)
156
157int
158_XimLookupMBText(
159    Xic			 ic,
160    XKeyEvent*		event,
161    char*		buffer,
162    int			nbytes,
163    KeySym*		keysym,
164    XComposeStatus*	status)
165{
166    int count;
167    KeySym symbol;
168    Status	dummy;
169    Xim	im = (Xim)ic->core.im;
170    XimCommonPrivateRec* private = &im->private.common;
171    unsigned char look[BUF_SIZE];
172    ucs4_t ucs4;
173
174    /* force a latin-1 lookup for compatibility */
175    count = XLOOKUPSTRING(event, (char *)buffer, nbytes, &symbol, status);
176    if (keysym != NULL) *keysym = symbol;
177    if ((nbytes == 0) || (symbol == NoSymbol)) return count;
178
179    if (count > 1) {
180	if ((unsigned)count >= sizeof(look))
181	    return 0;
182	memcpy(look, (char *)buffer,count);
183	look[count] = '\0';
184	if ((count = im->methods->ctstombs(ic->core.im,
185				(char*) look, count,
186				buffer, nbytes, &dummy)) < 0) {
187	    count = 0;
188	}
189    } else if ((count == 0) ||
190	       (count == 1 && (symbol > 0x7f && symbol < 0xff00))) {
191
192        XPointer from = (XPointer) &ucs4;
193        XPointer to =   (XPointer) look;
194        int from_len = 1;
195        int to_len = BUF_SIZE;
196        XPointer args[1];
197        XlcCharSet charset;
198        args[0] = (XPointer) &charset;
199        ucs4 = (ucs4_t) KeySymToUcs4(symbol);
200        if (!ucs4)
201            return 0;
202
203	if (_XlcConvert(private->ucstoc_conv,
204                        &from, &from_len, &to, &to_len,
205                        args, 1 ) != 0) {
206	    count = 0;
207	} else {
208            from = (XPointer) look;
209            to =   (XPointer) buffer;
210            from_len = BUF_SIZE - to_len;
211            to_len = nbytes;
212            args[0] = (XPointer) charset;
213	    if (_XlcConvert(private->cstomb_conv,
214                            &from, &from_len, &to, &to_len,
215			    args, 1 ) != 0) {
216		count = 0;
217	    } else {
218                count = nbytes - to_len;
219	    }
220	}
221    }
222    /* FIXME:
223     * we should make sure that if the character is a Latin1 character
224     * and it's on the right side, and we're in a non-Latin1 locale
225     * that this is a valid Latin1 character for this locale.
226     */
227    return count;
228}
229
230int
231_XimLookupWCText(
232    Xic			 ic,
233    XKeyEvent*		event,
234    wchar_t*		buffer,
235    int			nbytes,
236    KeySym*		keysym,
237    XComposeStatus*	status)
238{
239    int count;
240    KeySym symbol;
241    Status	dummy;
242    Xim	im = (Xim)ic->core.im;
243    XimCommonPrivateRec* private = &im->private.common;
244    unsigned char look[BUF_SIZE];
245    ucs4_t ucs4;
246
247    /* force a latin-1 lookup for compatibility */
248    count = XLOOKUPSTRING(event, (char *)look, nbytes, &symbol, status);
249    if (keysym != NULL) *keysym = symbol;
250    if ((nbytes == 0) || (symbol == NoSymbol)) return count;
251
252    if (count > 1) {
253	if ((count = im->methods->ctstowcs(ic->core.im,
254				(char*) look, count,
255				buffer, nbytes, &dummy)) < 0) {
256	    count = 0;
257	}
258    } else if ((count == 0) ||
259	       (count == 1 && (symbol > 0x7f && symbol < 0xff00))) {
260
261        XPointer from = (XPointer) &ucs4;
262        XPointer to =   (XPointer) look;
263        int from_len = 1;
264        int to_len = BUF_SIZE;
265        XPointer args[1];
266        XlcCharSet charset;
267        args[0] = (XPointer) &charset;
268        ucs4 = (ucs4_t) KeySymToUcs4(symbol);
269        if (!ucs4)
270            return 0;
271
272	if (_XlcConvert(private->ucstoc_conv,
273                        &from, &from_len, &to, &to_len,
274                        args, 1 ) != 0) {
275	    count = 0;
276	} else {
277            from = (XPointer) look;
278            to =   (XPointer) buffer;
279            from_len = BUF_SIZE - to_len;
280            to_len = nbytes;
281            args[0] = (XPointer) charset;
282
283	    if (_XlcConvert(private->cstowc_conv,
284                            &from, &from_len, &to, &to_len,
285			    args, 1 ) != 0) {
286		count = 0;
287	    } else {
288                count = nbytes - to_len;
289	    }
290	}
291    } else
292	/* FIXME:
293	 * we should make sure that if the character is a Latin1 character
294	 * and it's on the right side, and we're in a non-Latin1 locale
295	 * that this is a valid Latin1 character for this locale.
296	 */
297	buffer[0] = look[0];
298
299    return count;
300}
301
302int
303_XimLookupUTF8Text(
304    Xic			 ic,
305    XKeyEvent*		event,
306    char*		buffer,
307    int			nbytes,
308    KeySym*		keysym,
309    XComposeStatus*	status)
310{
311    int count;
312    KeySym symbol;
313    Status	dummy;
314    Xim	im = (Xim)ic->core.im;
315    XimCommonPrivateRec* private = &im->private.common;
316    unsigned char look[BUF_SIZE];
317    ucs4_t ucs4;
318
319    /* force a latin-1 lookup for compatibility */
320    count = XLOOKUPSTRING(event, (char *)buffer, nbytes, &symbol, status);
321    if (keysym != NULL) *keysym = symbol;
322    if ((nbytes == 0) || (symbol == NoSymbol)) return count;
323
324    if (count > 1) {
325	if ((unsigned)count >= sizeof(look))
326	    return 0;
327	memcpy(look, (char *)buffer,count);
328	look[count] = '\0';
329	if ((count = im->methods->ctstoutf8(ic->core.im,
330				(char*) look, count,
331				buffer, nbytes, &dummy)) < 0) {
332	    count = 0;
333	}
334    } else if ((count == 0) ||
335	       (count == 1 && (symbol > 0x7f && symbol < 0xff00))) {
336
337        XPointer from = (XPointer) &ucs4;
338        int from_len = 1;
339        XPointer to = (XPointer) buffer;
340        int to_len = nbytes;
341
342        ucs4 = (ucs4_t) KeySymToUcs4(symbol);
343        if (!ucs4)
344            return 0;
345
346	if (_XlcConvert(private->ucstoutf8_conv,
347                        &from, &from_len, &to, &to_len,
348                        NULL, 0) != 0) {
349	    count = 0;
350	} else {
351            count = nbytes - to_len;
352	}
353    }
354    /* FIXME:
355     * we should make sure that if the character is a Latin1 character
356     * and it's on the right side, and we're in a non-Latin1 locale
357     * that this is a valid Latin1 character for this locale.
358     */
359    return count;
360}
361