11ab64890Smrg/*
21ab64890Smrg * Copyright 1992, 1993 by TOSHIBA Corp.
31ab64890Smrg *
41ab64890Smrg * Permission to use, copy, modify, and distribute this software and its
51ab64890Smrg * documentation for any purpose and without fee is hereby granted, provided
61ab64890Smrg * that the above copyright notice appear in all copies and that both that
71ab64890Smrg * copyright notice and this permission notice appear in supporting
81ab64890Smrg * documentation, and that the name of TOSHIBA not be used in advertising
91ab64890Smrg * or publicity pertaining to distribution of the software without specific,
101ab64890Smrg * written prior permission. TOSHIBA make no representations about the
111ab64890Smrg * suitability of this software for any purpose.  It is provided "as is"
121ab64890Smrg * without express or implied warranty.
131ab64890Smrg *
141ab64890Smrg * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
151ab64890Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
161ab64890Smrg * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
171ab64890Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
181ab64890Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
191ab64890Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
201ab64890Smrg * SOFTWARE.
211ab64890Smrg *
221ab64890Smrg * Author: Katsuhisa Yano	TOSHIBA Corp.
231ab64890Smrg *			   	mopi@osa.ilab.toshiba.co.jp
241ab64890Smrg */
251ab64890Smrg
261ab64890Smrg#ifdef HAVE_CONFIG_H
271ab64890Smrg#include <config.h>
281ab64890Smrg#endif
291ab64890Smrg#include "Xlibint.h"
301ab64890Smrg#include "XlcPubI.h"
311ab64890Smrg#include <X11/Xutil.h>
321ab64890Smrg#include <X11/Xatom.h>
33258a0ebeSmrg#include "reallocarray.h"
341ab64890Smrg
351ab64890Smrgstatic XPointer *
361ab64890Smrgalloc_list(
371ab64890Smrg    Bool is_wide_char,
381ab64890Smrg    int count,
391ab64890Smrg    int nitems)
401ab64890Smrg{
411ab64890Smrg    if (is_wide_char) {
421ab64890Smrg	wchar_t **wstr_list;
431ab64890Smrg
44258a0ebeSmrg	wstr_list = Xmallocarray(count, sizeof(wchar_t *));
451ab64890Smrg	if (wstr_list == NULL)
461ab64890Smrg	    return (XPointer *) NULL;
471ab64890Smrg
48258a0ebeSmrg	*wstr_list = Xmallocarray(nitems, sizeof(wchar_t));
491ab64890Smrg	if (*wstr_list == NULL) {
501ab64890Smrg	    Xfree(wstr_list);
511ab64890Smrg	    return (XPointer *) NULL;
521ab64890Smrg	}
531ab64890Smrg
541ab64890Smrg	return (XPointer *) wstr_list;
551ab64890Smrg    } else {
561ab64890Smrg	char **str_list;
571ab64890Smrg
58258a0ebeSmrg	str_list = Xmallocarray(count, sizeof(char *));
591ab64890Smrg	if (str_list == NULL)
601ab64890Smrg	    return (XPointer *) NULL;
611ab64890Smrg
62818534a1Smrg	*str_list = Xmalloc(nitems);
631ab64890Smrg	if (*str_list == NULL) {
641ab64890Smrg	    Xfree(str_list);
651ab64890Smrg	    return (XPointer *) NULL;
661ab64890Smrg	}
671ab64890Smrg
681ab64890Smrg	return (XPointer *) str_list;
691ab64890Smrg    }
701ab64890Smrg}
711ab64890Smrg
721ab64890Smrgstatic void
731ab64890Smrgcopy_list(
741ab64890Smrg    Bool is_wide_char,
751ab64890Smrg    XPointer text,
761ab64890Smrg    XPointer *list,
771ab64890Smrg    int count)
781ab64890Smrg{
791ab64890Smrg    int length;
801ab64890Smrg
811ab64890Smrg    if (is_wide_char) {
821ab64890Smrg	wchar_t *wc_text, *wstr, **wstr_list;
8361b2299dSmrg
841ab64890Smrg	wc_text = (wchar_t *) text;
851ab64890Smrg	wstr_list = (wchar_t **) list;
861ab64890Smrg
871ab64890Smrg	for (wstr = *wstr_list; count > 0; count--, wstr_list++) {
881ab64890Smrg	    _Xwcscpy(wstr, wc_text);
891ab64890Smrg	    *wstr_list = wstr;
901ab64890Smrg	    length = _Xwcslen(wstr) + 1;
911ab64890Smrg	    wstr += length;
921ab64890Smrg	    wc_text += length;
931ab64890Smrg	}
941ab64890Smrg    } else {
951ab64890Smrg	char *mb_text, *str, **str_list;
9661b2299dSmrg
971ab64890Smrg	mb_text = (char *) text;
981ab64890Smrg	str_list = (char **) list;
991ab64890Smrg
1001ab64890Smrg	for (str = *str_list; count > 0; count--, str_list++) {
1011ab64890Smrg	    strcpy(str, mb_text);
1021ab64890Smrg	    *str_list = str;
1039c019ec5Smaya	    length = (int) strlen(str) + 1;
1041ab64890Smrg	    str += length;
1051ab64890Smrg	    mb_text += length;
1061ab64890Smrg	}
1071ab64890Smrg    }
1081ab64890Smrg}
1091ab64890Smrg
1101ab64890Smrgstatic int
1111ab64890Smrg_XTextPropertyToTextList(
1121ab64890Smrg    XLCd lcd,
1131ab64890Smrg    Display *dpy,
1141ab64890Smrg    const XTextProperty *text_prop,
1151ab64890Smrg    const char *to_type,
1161ab64890Smrg    XPointer **list_ret,
1171ab64890Smrg    int *count_ret)
1181ab64890Smrg{
1191ab64890Smrg    XlcConv conv = NULL;
1201ab64890Smrg    const char *from_type;
1211ab64890Smrg    XPointer from, to, buf;
1221ab64890Smrg    char *str_ptr, *last_ptr;
1231ab64890Smrg    Atom encoding;
1241ab64890Smrg    int from_left, to_left, buf_len, ret, len;
1251ab64890Smrg    int unconv_num, nitems = text_prop->nitems;
1261ab64890Smrg    Bool is_wide_char = False, do_strcpy = False;
1271ab64890Smrg
1281ab64890Smrg    if (strcmp(XlcNWideChar, to_type) == 0)
1291ab64890Smrg	is_wide_char = True;
1301ab64890Smrg
1311ab64890Smrg    if (nitems <= 0) {
1321ab64890Smrg	*list_ret = NULL;
1331ab64890Smrg	*count_ret = 0;
1341ab64890Smrg	return Success;
1351ab64890Smrg    }
1361ab64890Smrg
1371ab64890Smrg    if (text_prop->format != 8)
1381ab64890Smrg	return XConverterNotFound;
1391ab64890Smrg
1401ab64890Smrg    encoding = text_prop->encoding;
1411ab64890Smrg    if (encoding == XA_STRING)
1421ab64890Smrg	from_type = XlcNString;
1431ab64890Smrg    else if (encoding == XInternAtom(dpy, "UTF8_STRING", False))
1441ab64890Smrg	from_type = XlcNUtf8String;
1451ab64890Smrg    else if (encoding == XInternAtom(dpy, "COMPOUND_TEXT", False))
1461ab64890Smrg	from_type = XlcNCompoundText;
1471ab64890Smrg    else if (encoding == XInternAtom(dpy, XLC_PUBLIC(lcd, encoding_name), False))
1481ab64890Smrg	from_type = XlcNMultiByte;
1491ab64890Smrg    else
1501ab64890Smrg	return XConverterNotFound;
1511ab64890Smrg
1521ab64890Smrg    if (is_wide_char) {
1532d67cb4fSmrg	buf_len = (text_prop->nitems + 1) * sizeof(wchar_t);
1541ab64890Smrg    } else {
1551ab64890Smrg	if (strcmp(to_type, XlcNUtf8String) == 0)
1561ab64890Smrg	    buf_len = text_prop->nitems * 6 + 1;
1571ab64890Smrg	else
1581ab64890Smrg	    buf_len = text_prop->nitems * XLC_PUBLIC(lcd, mb_cur_max) + 1;
1591ab64890Smrg    }
160818534a1Smrg    buf = Xmalloc(buf_len);
1611ab64890Smrg    if (buf == NULL)
1621ab64890Smrg	return XNoMemory;
1631ab64890Smrg    to = buf;
1641ab64890Smrg    to_left = buf_len;
1651ab64890Smrg
1661ab64890Smrg    /* can be XlcNMultiByte to XlcNMultiByte,
1671ab64890Smrg       or XlcNUtf8String to XlcNUtf8String */
1681ab64890Smrg    if (!strcmp(from_type, to_type)) {
1691ab64890Smrg        do_strcpy = True;
1701ab64890Smrg    } else {
1711ab64890Smrg        conv = _XlcOpenConverter(lcd, from_type, lcd, to_type);
1721ab64890Smrg        if (conv == NULL) {
1731ab64890Smrg	    Xfree(buf);
1741ab64890Smrg	    return XConverterNotFound;
1751ab64890Smrg        }
1761ab64890Smrg    }
1771ab64890Smrg
1781ab64890Smrg    last_ptr = str_ptr = (char *) text_prop->value;
1791ab64890Smrg    unconv_num = *count_ret = 0;
1801ab64890Smrg
1811ab64890Smrg    while (1) {
1821ab64890Smrg	if (nitems == 0 || *str_ptr == 0) {
1831ab64890Smrg	    from = (XPointer) last_ptr;
1841ab64890Smrg	    from_left = str_ptr - last_ptr;
1851ab64890Smrg	    last_ptr = str_ptr;
1861ab64890Smrg
1871ab64890Smrg            if (do_strcpy) {
1881ab64890Smrg            	len = min(from_left, to_left);
1899c019ec5Smaya                strncpy(to, from, (size_t) len);
1901ab64890Smrg                from += len;
1911ab64890Smrg                to += len;
1921ab64890Smrg                from_left -= len;
1931ab64890Smrg                to_left -= len;
1941ab64890Smrg                ret = 0;
1951ab64890Smrg            } else {
1961ab64890Smrg	        ret = _XlcConvert(conv, &from, &from_left, &to, &to_left, NULL, 0);
1971ab64890Smrg            }
1981ab64890Smrg
1991ab64890Smrg	    if (ret < 0)
2001ab64890Smrg		continue;
2011ab64890Smrg
2021ab64890Smrg	    unconv_num += ret;
2031ab64890Smrg	    (*count_ret)++;
2041ab64890Smrg
2051ab64890Smrg	    if (nitems == 0)
2061ab64890Smrg		break;
2071ab64890Smrg 	    last_ptr = ++str_ptr;
2081ab64890Smrg	    if (is_wide_char) {
2091ab64890Smrg		*((wchar_t *)to) = (wchar_t) 0;
2101ab64890Smrg		to += sizeof(wchar_t);
2111ab64890Smrg		to_left -= sizeof(wchar_t);
2121ab64890Smrg	    } else {
2131ab64890Smrg		*((char *)to) = '\0';
2141ab64890Smrg		to++;
2151ab64890Smrg		to_left--;
2161ab64890Smrg	    }
2171ab64890Smrg	    if (! do_strcpy)
2181ab64890Smrg	        _XlcResetConverter(conv);
2191ab64890Smrg	} else
2201ab64890Smrg	    str_ptr++;
2211ab64890Smrg
2221ab64890Smrg	nitems--;
2231ab64890Smrg    }
2241ab64890Smrg
2251ab64890Smrg    if (! do_strcpy)
2261ab64890Smrg        _XlcCloseConverter(conv);
2271ab64890Smrg
2281ab64890Smrg    if (is_wide_char) {
2291ab64890Smrg	*((wchar_t *) to) = (wchar_t) 0;
2301ab64890Smrg	to_left -= sizeof(wchar_t);
2311ab64890Smrg    } else {
2321ab64890Smrg	*((char *) to) = '\0';
2331ab64890Smrg	to_left--;
2341ab64890Smrg    }
2351ab64890Smrg
2361ab64890Smrg    *list_ret = alloc_list(is_wide_char, *count_ret, buf_len - to_left);
2371ab64890Smrg    if (*list_ret)
2381ab64890Smrg	copy_list(is_wide_char, buf, *list_ret, *count_ret);
2391ab64890Smrg
2401ab64890Smrg    Xfree(buf);
2411ab64890Smrg
2421ab64890Smrg    return unconv_num;
2431ab64890Smrg}
2441ab64890Smrg
2451ab64890Smrgint
2461ab64890Smrg_XmbTextPropertyToTextList(
2471ab64890Smrg    XLCd lcd,
2481ab64890Smrg    Display *dpy,
2491ab64890Smrg    const XTextProperty *text_prop,
2501ab64890Smrg    char ***list_ret,
2511ab64890Smrg    int *count_ret)
2521ab64890Smrg{
2531ab64890Smrg    return _XTextPropertyToTextList(lcd, dpy, text_prop, XlcNMultiByte,
2541ab64890Smrg				    (XPointer **) list_ret, count_ret);
2551ab64890Smrg}
2561ab64890Smrg
2571ab64890Smrgint
2581ab64890Smrg_XwcTextPropertyToTextList(
2591ab64890Smrg    XLCd lcd,
2601ab64890Smrg    Display *dpy,
2611ab64890Smrg    const XTextProperty *text_prop,
2621ab64890Smrg    wchar_t ***list_ret,
2631ab64890Smrg    int *count_ret)
2641ab64890Smrg{
2651ab64890Smrg    return _XTextPropertyToTextList(lcd, dpy, text_prop, XlcNWideChar,
2661ab64890Smrg				    (XPointer **) list_ret, count_ret);
2671ab64890Smrg}
2681ab64890Smrg
2691ab64890Smrgint
2701ab64890Smrg_Xutf8TextPropertyToTextList(
2711ab64890Smrg    XLCd lcd,
2721ab64890Smrg    Display *dpy,
2731ab64890Smrg    const XTextProperty *text_prop,
2741ab64890Smrg    char ***list_ret,
2751ab64890Smrg    int *count_ret)
2761ab64890Smrg{
2771ab64890Smrg    return _XTextPropertyToTextList(lcd, dpy, text_prop, XlcNUtf8String,
2781ab64890Smrg				    (XPointer **) list_ret, count_ret);
2791ab64890Smrg}
2801ab64890Smrg
2811ab64890Smrgvoid
2821ab64890Smrg_XwcFreeStringList(
2831ab64890Smrg    XLCd lcd,
2841ab64890Smrg    wchar_t **list)
2851ab64890Smrg{
2861ab64890Smrg    if (list) {
2870f8248bfSmrg        Xfree(*list);
2881ab64890Smrg        Xfree(list);
2891ab64890Smrg    }
2901ab64890Smrg}
291