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