lcConv.c revision 1ab64890
1/* $Xorg: lcConv.c,v 1.4 2000/08/17 19:45:17 cpqbld Exp $ */ 2/* 3 * Copyright 1992, 1993 by TOSHIBA Corp. 4 * 5 * Permission to use, copy, modify, and distribute this software and its 6 * documentation for any purpose and without fee is hereby granted, provided 7 * that the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of TOSHIBA not be used in advertising 10 * or publicity pertaining to distribution of the software without specific, 11 * written prior permission. TOSHIBA make no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * without express or implied warranty. 14 * 15 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 16 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 17 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 18 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 19 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 20 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 21 * SOFTWARE. 22 * 23 * Author: Katsuhisa Yano TOSHIBA Corp. 24 * mopi@osa.ilab.toshiba.co.jp 25 */ 26/* $XFree86: xc/lib/X11/lcConv.c,v 1.5 2000/12/04 18:49:26 dawes Exp $ */ 27 28#ifdef HAVE_CONFIG_H 29#include <config.h> 30#endif 31#include "Xlibint.h" 32#include "XlcPubI.h" 33#include <stdio.h> 34 35typedef struct _XlcConverterListRec { 36 XLCd from_lcd; 37 const char *from; 38 XrmQuark from_type; 39 XLCd to_lcd; 40 const char *to; 41 XrmQuark to_type; 42 XlcOpenConverterProc converter; 43 struct _XlcConverterListRec *next; 44} XlcConverterListRec, *XlcConverterList; 45 46static XlcConverterList conv_list = NULL; 47 48static void 49close_converter( 50 XlcConv conv) 51{ 52 (*conv->methods->close)(conv); 53} 54 55static XlcConv 56get_converter( 57 XLCd from_lcd, 58 XrmQuark from_type, 59 XLCd to_lcd, 60 XrmQuark to_type) 61{ 62 XlcConverterList list, prev = NULL; 63 64 for (list = conv_list; list; list = list->next) { 65 if (list->from_lcd == from_lcd && list->to_lcd == to_lcd 66 && list->from_type == from_type && list->to_type == to_type) { 67 68 if (prev && prev != conv_list) { /* XXX */ 69 prev->next = list->next; 70 list->next = conv_list; 71 conv_list = list; 72 } 73 74 return (*list->converter)(from_lcd, list->from, to_lcd, list->to); 75 } 76 77 prev = list; 78 } 79 80 return (XlcConv) NULL; 81} 82 83Bool 84_XlcSetConverter( 85 XLCd from_lcd, 86 const char *from, 87 XLCd to_lcd, 88 const char *to, 89 XlcOpenConverterProc converter) 90{ 91 XlcConverterList list; 92 XrmQuark from_type, to_type; 93 94 from_type = XrmStringToQuark(from); 95 to_type = XrmStringToQuark(to); 96 97 for (list = conv_list; list; list = list->next) { 98 if (list->from_lcd == from_lcd && list->to_lcd == to_lcd 99 && list->from_type == from_type && list->to_type == to_type) { 100 101 list->converter = converter; 102 return True; 103 } 104 } 105 106 list = (XlcConverterList) Xmalloc(sizeof(XlcConverterListRec)); 107 if (list == NULL) 108 return False; 109 110 list->from_lcd = from_lcd; 111 list->from = from; 112 list->from_type = from_type; 113 list->to_lcd = to_lcd; 114 list->to = to; 115 list->to_type = to_type; 116 list->converter = converter; 117 list->next = conv_list; 118 conv_list = list; 119 120 return True; 121} 122 123typedef struct _ConvRec { 124 XlcConv from_conv; 125 XlcConv to_conv; 126} ConvRec, *Conv; 127 128static int 129indirect_convert( 130 XlcConv lc_conv, 131 XPointer *from, 132 int *from_left, 133 XPointer *to, 134 int *to_left, 135 XPointer *args, 136 int num_args) 137{ 138 Conv conv = (Conv) lc_conv->state; 139 XlcConv from_conv = conv->from_conv; 140 XlcConv to_conv = conv->to_conv; 141 XlcCharSet charset; 142 char buf[BUFSIZ], *cs; 143 XPointer tmp_args[1]; 144 int cs_left, ret, length, unconv_num = 0; 145 146 if (from == NULL || *from == NULL) { 147 if (from_conv->methods->reset) 148 (*from_conv->methods->reset)(from_conv); 149 150 if (to_conv->methods->reset) 151 (*to_conv->methods->reset)(to_conv); 152 153 return 0; 154 } 155 156 while (*from_left > 0) { 157 cs = buf; 158 cs_left = BUFSIZ; 159 tmp_args[0] = (XPointer) &charset; 160 161 ret = (*from_conv->methods->convert)(from_conv, from, from_left, &cs, 162 &cs_left, tmp_args, 1); 163 if (ret < 0) 164 break; 165 166 unconv_num += ret; 167 168 length = cs - buf; 169 if (length > 0) { 170 cs_left = length; 171 cs = buf; 172 173 tmp_args[0] = (XPointer) charset; 174 175 ret = (*to_conv->methods->convert)(to_conv, &cs, &cs_left, to, to_left, 176 tmp_args, 1); 177 if (ret < 0) { 178 unconv_num += length / (charset->char_size > 0 ? charset->char_size : 1); 179 continue; 180 } 181 182 unconv_num += ret; 183 184 if (*to_left < 1) 185 break; 186 } 187 } 188 189 return unconv_num; 190} 191 192static void 193close_indirect_converter( 194 XlcConv lc_conv) 195{ 196 Conv conv = (Conv) lc_conv->state; 197 198 if (conv) { 199 if (conv->from_conv) 200 close_converter(conv->from_conv); 201 if (conv->to_conv) 202 close_converter(conv->to_conv); 203 204 Xfree((char *) conv); 205 } 206 207 Xfree((char *) lc_conv); 208} 209 210static void 211reset_indirect_converter( 212 XlcConv lc_conv) 213{ 214 Conv conv = (Conv) lc_conv->state; 215 216 if (conv) { 217 if (conv->from_conv && conv->from_conv->methods->reset) 218 (*conv->from_conv->methods->reset)(conv->from_conv); 219 if (conv->to_conv && conv->to_conv->methods->reset) 220 (*conv->to_conv->methods->reset)(conv->to_conv); 221 } 222} 223 224static XlcConvMethodsRec conv_methods = { 225 close_indirect_converter, 226 indirect_convert, 227 reset_indirect_converter 228} ; 229 230static XlcConv 231open_indirect_converter( 232 XLCd from_lcd, 233 const char *from, 234 XLCd to_lcd, 235 const char *to) 236{ 237 XlcConv lc_conv, from_conv, to_conv; 238 Conv conv; 239 XrmQuark from_type, to_type; 240 static XrmQuark QChar, QCharSet, QCTCharSet = (XrmQuark) 0; 241 242 if (QCTCharSet == (XrmQuark) 0) { 243 QCTCharSet = XrmStringToQuark(XlcNCTCharSet); 244 QCharSet = XrmStringToQuark(XlcNCharSet); 245 QChar = XrmStringToQuark(XlcNChar); 246 } 247 248 from_type = XrmStringToQuark(from); 249 to_type = XrmStringToQuark(to); 250 251 if (from_type == QCharSet || from_type == QChar || to_type == QCharSet || 252 to_type == QChar) 253 return (XlcConv) NULL; 254 255 lc_conv = (XlcConv) Xmalloc(sizeof(XlcConvRec)); 256 if (lc_conv == NULL) 257 return (XlcConv) NULL; 258 259 lc_conv->methods = &conv_methods; 260 261 lc_conv->state = (XPointer) Xcalloc(1, sizeof(ConvRec)); 262 if (lc_conv->state == NULL) 263 goto err; 264 265 conv = (Conv) lc_conv->state; 266 267 from_conv = get_converter(from_lcd, from_type, from_lcd, QCTCharSet); 268 if (from_conv == NULL) 269 from_conv = get_converter(from_lcd, from_type, from_lcd, QCharSet); 270 if (from_conv == NULL) 271 from_conv = get_converter((XLCd)NULL, from_type, (XLCd)NULL, QCharSet); 272 if (from_conv == NULL) 273 from_conv = get_converter(from_lcd, from_type, from_lcd, QChar); 274 if (from_conv == NULL) 275 goto err; 276 conv->from_conv = from_conv; 277 278 to_conv = get_converter(to_lcd, QCTCharSet, to_lcd, to_type); 279 if (to_conv == NULL) 280 to_conv = get_converter(to_lcd, QCharSet, to_lcd, to_type); 281 if (to_conv == NULL) 282 to_conv = get_converter((XLCd) NULL, QCharSet, (XLCd) NULL, to_type); 283 if (to_conv == NULL) 284 goto err; 285 conv->to_conv = to_conv; 286 287 return lc_conv; 288 289err: 290 close_indirect_converter(lc_conv); 291 292 return (XlcConv) NULL; 293} 294 295XlcConv 296_XlcOpenConverter( 297 XLCd from_lcd, 298 const char *from, 299 XLCd to_lcd, 300 const char *to) 301{ 302 XlcConv conv; 303 XrmQuark from_type, to_type; 304 305 from_type = XrmStringToQuark(from); 306 to_type = XrmStringToQuark(to); 307 308 if ((conv = get_converter(from_lcd, from_type, to_lcd, to_type))) 309 return conv; 310 311 return open_indirect_converter(from_lcd, from, to_lcd, to); 312} 313 314void 315_XlcCloseConverter( 316 XlcConv conv) 317{ 318 close_converter(conv); 319} 320 321int 322_XlcConvert( 323 XlcConv conv, 324 XPointer *from, 325 int *from_left, 326 XPointer *to, 327 int *to_left, 328 XPointer *args, 329 int num_args) 330{ 331 return (*conv->methods->convert)(conv, from, from_left, to, to_left, args, 332 num_args); 333} 334 335void 336_XlcResetConverter( 337 XlcConv conv) 338{ 339 if (conv->methods->reset) 340 (*conv->methods->reset)(conv); 341} 342