lcPrTxt.c revision 0f8248bf
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 */
25
26#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
29#include "Xlibint.h"
30#include "XlcPubI.h"
31#include <X11/Xutil.h>
32#include <X11/Xatom.h>
33
34static XPointer *
35alloc_list(
36    Bool is_wide_char,
37    int count,
38    int nitems)
39{
40    if (is_wide_char) {
41	wchar_t **wstr_list;
42
43	wstr_list = Xmalloc(count * sizeof(wchar_t *));
44	if (wstr_list == NULL)
45	    return (XPointer *) NULL;
46
47	*wstr_list = Xmalloc(nitems * sizeof(wchar_t));
48	if (*wstr_list == NULL) {
49	    Xfree(wstr_list);
50	    return (XPointer *) NULL;
51	}
52
53	return (XPointer *) wstr_list;
54    } else {
55	char **str_list;
56
57	str_list = Xmalloc(count * sizeof(char *));
58	if (str_list == NULL)
59	    return (XPointer *) NULL;
60
61	*str_list = Xmalloc(nitems);
62	if (*str_list == NULL) {
63	    Xfree(str_list);
64	    return (XPointer *) NULL;
65	}
66
67	return (XPointer *) str_list;
68    }
69}
70
71static void
72copy_list(
73    Bool is_wide_char,
74    XPointer text,
75    XPointer *list,
76    int count)
77{
78    int length;
79
80    if (is_wide_char) {
81	wchar_t *wc_text, *wstr, **wstr_list;
82
83	wc_text = (wchar_t *) text;
84	wstr_list = (wchar_t **) list;
85
86	for (wstr = *wstr_list; count > 0; count--, wstr_list++) {
87	    _Xwcscpy(wstr, wc_text);
88	    *wstr_list = wstr;
89	    length = _Xwcslen(wstr) + 1;
90	    wstr += length;
91	    wc_text += length;
92	}
93    } else {
94	char *mb_text, *str, **str_list;
95
96	mb_text = (char *) text;
97	str_list = (char **) list;
98
99	for (str = *str_list; count > 0; count--, str_list++) {
100	    strcpy(str, mb_text);
101	    *str_list = str;
102	    length = strlen(str) + 1;
103	    str += length;
104	    mb_text += length;
105	}
106    }
107}
108
109static int
110_XTextPropertyToTextList(
111    XLCd lcd,
112    Display *dpy,
113    const XTextProperty *text_prop,
114    const char *to_type,
115    XPointer **list_ret,
116    int *count_ret)
117{
118    XlcConv conv = NULL;
119    const char *from_type;
120    XPointer from, to, buf;
121    char *str_ptr, *last_ptr;
122    Atom encoding;
123    int from_left, to_left, buf_len, ret, len;
124    int unconv_num, nitems = text_prop->nitems;
125    Bool is_wide_char = False, do_strcpy = False;
126
127    if (strcmp(XlcNWideChar, to_type) == 0)
128	is_wide_char = True;
129
130    if (nitems <= 0) {
131	*list_ret = NULL;
132	*count_ret = 0;
133	return Success;
134    }
135
136    if (text_prop->format != 8)
137	return XConverterNotFound;
138
139    encoding = text_prop->encoding;
140    if (encoding == XA_STRING)
141	from_type = XlcNString;
142    else if (encoding == XInternAtom(dpy, "UTF8_STRING", False))
143	from_type = XlcNUtf8String;
144    else if (encoding == XInternAtom(dpy, "COMPOUND_TEXT", False))
145	from_type = XlcNCompoundText;
146    else if (encoding == XInternAtom(dpy, XLC_PUBLIC(lcd, encoding_name), False))
147	from_type = XlcNMultiByte;
148    else
149	return XConverterNotFound;
150
151    if (is_wide_char) {
152	buf_len = (text_prop->nitems + 1) * sizeof(wchar_t);;
153    } else {
154	if (strcmp(to_type, XlcNUtf8String) == 0)
155	    buf_len = text_prop->nitems * 6 + 1;
156	else
157	    buf_len = text_prop->nitems * XLC_PUBLIC(lcd, mb_cur_max) + 1;
158    }
159    buf = Xmalloc(buf_len);
160    if (buf == NULL)
161	return XNoMemory;
162    to = buf;
163    to_left = buf_len;
164
165    /* can be XlcNMultiByte to XlcNMultiByte,
166       or XlcNUtf8String to XlcNUtf8String */
167    if (!strcmp(from_type, to_type)) {
168        do_strcpy = True;
169    } else {
170        conv = _XlcOpenConverter(lcd, from_type, lcd, to_type);
171        if (conv == NULL) {
172	    Xfree(buf);
173	    return XConverterNotFound;
174        }
175    }
176
177    last_ptr = str_ptr = (char *) text_prop->value;
178    unconv_num = *count_ret = 0;
179
180    while (1) {
181	if (nitems == 0 || *str_ptr == 0) {
182	    from = (XPointer) last_ptr;
183	    from_left = str_ptr - last_ptr;
184	    last_ptr = str_ptr;
185
186            if (do_strcpy) {
187            	len = min(from_left, to_left);
188                strncpy(to, from, len);
189                from += len;
190                to += len;
191                from_left -= len;
192                to_left -= len;
193                ret = 0;
194            } else {
195	        ret = _XlcConvert(conv, &from, &from_left, &to, &to_left, NULL, 0);
196            }
197
198	    if (ret < 0)
199		continue;
200
201	    unconv_num += ret;
202	    (*count_ret)++;
203
204	    if (nitems == 0)
205		break;
206 	    last_ptr = ++str_ptr;
207	    if (is_wide_char) {
208		*((wchar_t *)to) = (wchar_t) 0;
209		to += sizeof(wchar_t);
210		to_left -= sizeof(wchar_t);
211	    } else {
212		*((char *)to) = '\0';
213		to++;
214		to_left--;
215	    }
216	    if (! do_strcpy)
217	        _XlcResetConverter(conv);
218	} else
219	    str_ptr++;
220
221	nitems--;
222    }
223
224    if (! do_strcpy)
225        _XlcCloseConverter(conv);
226
227    if (is_wide_char) {
228	*((wchar_t *) to) = (wchar_t) 0;
229	to_left -= sizeof(wchar_t);
230    } else {
231	*((char *) to) = '\0';
232	to_left--;
233    }
234
235    *list_ret = alloc_list(is_wide_char, *count_ret, buf_len - to_left);
236    if (*list_ret)
237	copy_list(is_wide_char, buf, *list_ret, *count_ret);
238
239    Xfree(buf);
240
241    return unconv_num;
242}
243
244int
245_XmbTextPropertyToTextList(
246    XLCd lcd,
247    Display *dpy,
248    const XTextProperty *text_prop,
249    char ***list_ret,
250    int *count_ret)
251{
252    return _XTextPropertyToTextList(lcd, dpy, text_prop, XlcNMultiByte,
253				    (XPointer **) list_ret, count_ret);
254}
255
256int
257_XwcTextPropertyToTextList(
258    XLCd lcd,
259    Display *dpy,
260    const XTextProperty *text_prop,
261    wchar_t ***list_ret,
262    int *count_ret)
263{
264    return _XTextPropertyToTextList(lcd, dpy, text_prop, XlcNWideChar,
265				    (XPointer **) list_ret, count_ret);
266}
267
268int
269_Xutf8TextPropertyToTextList(
270    XLCd lcd,
271    Display *dpy,
272    const XTextProperty *text_prop,
273    char ***list_ret,
274    int *count_ret)
275{
276    return _XTextPropertyToTextList(lcd, dpy, text_prop, XlcNUtf8String,
277				    (XPointer **) list_ret, count_ret);
278}
279
280void
281_XwcFreeStringList(
282    XLCd lcd,
283    wchar_t **list)
284{
285    if (list) {
286        Xfree(*list);
287        Xfree(list);
288    }
289}
290