lcConv.c revision 818534a1
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 <stdio.h> 32 33typedef struct _XlcConverterListRec { 34 XLCd from_lcd; 35 const char *from; 36 XrmQuark from_type; 37 XLCd to_lcd; 38 const char *to; 39 XrmQuark to_type; 40 XlcOpenConverterProc converter; 41 struct _XlcConverterListRec *next; 42} XlcConverterListRec, *XlcConverterList; 43 44static XlcConverterList conv_list = NULL; 45 46static void 47close_converter( 48 XlcConv conv) 49{ 50 (*conv->methods->close)(conv); 51} 52 53static XlcConv 54get_converter( 55 XLCd from_lcd, 56 XrmQuark from_type, 57 XLCd to_lcd, 58 XrmQuark to_type) 59{ 60 XlcConverterList list, prev = NULL; 61 62 for (list = conv_list; list; list = list->next) { 63 if (list->from_lcd == from_lcd && list->to_lcd == to_lcd 64 && list->from_type == from_type && list->to_type == to_type) { 65 66 if (prev && prev != conv_list) { /* XXX */ 67 prev->next = list->next; 68 list->next = conv_list; 69 conv_list = list; 70 } 71 72 return (*list->converter)(from_lcd, list->from, to_lcd, list->to); 73 } 74 75 prev = list; 76 } 77 78 return (XlcConv) NULL; 79} 80 81Bool 82_XlcSetConverter( 83 XLCd from_lcd, 84 const char *from, 85 XLCd to_lcd, 86 const char *to, 87 XlcOpenConverterProc converter) 88{ 89 XlcConverterList list; 90 XrmQuark from_type, to_type; 91 92 from_type = XrmStringToQuark(from); 93 to_type = XrmStringToQuark(to); 94 95 for (list = conv_list; list; list = list->next) { 96 if (list->from_lcd == from_lcd && list->to_lcd == to_lcd 97 && list->from_type == from_type && list->to_type == to_type) { 98 99 list->converter = converter; 100 return True; 101 } 102 } 103 104 list = Xmalloc(sizeof(XlcConverterListRec)); 105 if (list == NULL) 106 return False; 107 108 list->from_lcd = from_lcd; 109 list->from = from; 110 list->from_type = from_type; 111 list->to_lcd = to_lcd; 112 list->to = to; 113 list->to_type = to_type; 114 list->converter = converter; 115 list->next = conv_list; 116 conv_list = list; 117 118 return True; 119} 120 121typedef struct _ConvRec { 122 XlcConv from_conv; 123 XlcConv to_conv; 124} ConvRec, *Conv; 125 126static int 127indirect_convert( 128 XlcConv lc_conv, 129 XPointer *from, 130 int *from_left, 131 XPointer *to, 132 int *to_left, 133 XPointer *args, 134 int num_args) 135{ 136 Conv conv = (Conv) lc_conv->state; 137 XlcConv from_conv = conv->from_conv; 138 XlcConv to_conv = conv->to_conv; 139 XlcCharSet charset; 140 char buf[BUFSIZ], *cs; 141 XPointer tmp_args[1]; 142 int cs_left, ret, length, unconv_num = 0; 143 144 if (from == NULL || *from == NULL) { 145 if (from_conv->methods->reset) 146 (*from_conv->methods->reset)(from_conv); 147 148 if (to_conv->methods->reset) 149 (*to_conv->methods->reset)(to_conv); 150 151 return 0; 152 } 153 154 while (*from_left > 0) { 155 cs = buf; 156 cs_left = BUFSIZ; 157 tmp_args[0] = (XPointer) &charset; 158 159 ret = (*from_conv->methods->convert)(from_conv, from, from_left, &cs, 160 &cs_left, tmp_args, 1); 161 if (ret < 0) 162 break; 163 164 unconv_num += ret; 165 166 length = cs - buf; 167 if (length > 0) { 168 cs_left = length; 169 cs = buf; 170 171 tmp_args[0] = (XPointer) charset; 172 173 ret = (*to_conv->methods->convert)(to_conv, &cs, &cs_left, to, to_left, 174 tmp_args, 1); 175 if (ret < 0) { 176 unconv_num += length / (charset->char_size > 0 ? charset->char_size : 1); 177 continue; 178 } 179 180 unconv_num += ret; 181 182 if (*to_left < 1) 183 break; 184 } 185 } 186 187 return unconv_num; 188} 189 190static void 191close_indirect_converter( 192 XlcConv lc_conv) 193{ 194 Conv conv = (Conv) lc_conv->state; 195 196 if (conv) { 197 if (conv->from_conv) 198 close_converter(conv->from_conv); 199 if (conv->to_conv) 200 close_converter(conv->to_conv); 201 202 Xfree(conv); 203 } 204 205 Xfree(lc_conv); 206} 207 208static void 209reset_indirect_converter( 210 XlcConv lc_conv) 211{ 212 Conv conv = (Conv) lc_conv->state; 213 214 if (conv) { 215 if (conv->from_conv && conv->from_conv->methods->reset) 216 (*conv->from_conv->methods->reset)(conv->from_conv); 217 if (conv->to_conv && conv->to_conv->methods->reset) 218 (*conv->to_conv->methods->reset)(conv->to_conv); 219 } 220} 221 222static XlcConvMethodsRec conv_methods = { 223 close_indirect_converter, 224 indirect_convert, 225 reset_indirect_converter 226} ; 227 228static XlcConv 229open_indirect_converter( 230 XLCd from_lcd, 231 const char *from, 232 XLCd to_lcd, 233 const char *to) 234{ 235 XlcConv lc_conv, from_conv, to_conv; 236 Conv conv; 237 XrmQuark from_type, to_type; 238 static XrmQuark QChar, QCharSet, QCTCharSet = (XrmQuark) 0; 239 240 if (QCTCharSet == (XrmQuark) 0) { 241 QCTCharSet = XrmStringToQuark(XlcNCTCharSet); 242 QCharSet = XrmStringToQuark(XlcNCharSet); 243 QChar = XrmStringToQuark(XlcNChar); 244 } 245 246 from_type = XrmStringToQuark(from); 247 to_type = XrmStringToQuark(to); 248 249 if (from_type == QCharSet || from_type == QChar || to_type == QCharSet || 250 to_type == QChar) 251 return (XlcConv) NULL; 252 253 lc_conv = Xmalloc(sizeof(XlcConvRec)); 254 if (lc_conv == NULL) 255 return (XlcConv) NULL; 256 257 lc_conv->methods = &conv_methods; 258 259 lc_conv->state = Xcalloc(1, sizeof(ConvRec)); 260 if (lc_conv->state == NULL) 261 goto err; 262 263 conv = (Conv) lc_conv->state; 264 265 from_conv = get_converter(from_lcd, from_type, from_lcd, QCTCharSet); 266 if (from_conv == NULL) 267 from_conv = get_converter(from_lcd, from_type, from_lcd, QCharSet); 268 if (from_conv == NULL) 269 from_conv = get_converter((XLCd)NULL, from_type, (XLCd)NULL, QCharSet); 270 if (from_conv == NULL) 271 from_conv = get_converter(from_lcd, from_type, from_lcd, QChar); 272 if (from_conv == NULL) 273 goto err; 274 conv->from_conv = from_conv; 275 276 to_conv = get_converter(to_lcd, QCTCharSet, to_lcd, to_type); 277 if (to_conv == NULL) 278 to_conv = get_converter(to_lcd, QCharSet, to_lcd, to_type); 279 if (to_conv == NULL) 280 to_conv = get_converter((XLCd) NULL, QCharSet, (XLCd) NULL, to_type); 281 if (to_conv == NULL) 282 goto err; 283 conv->to_conv = to_conv; 284 285 return lc_conv; 286 287err: 288 close_indirect_converter(lc_conv); 289 290 return (XlcConv) NULL; 291} 292 293XlcConv 294_XlcOpenConverter( 295 XLCd from_lcd, 296 const char *from, 297 XLCd to_lcd, 298 const char *to) 299{ 300 XlcConv conv; 301 XrmQuark from_type, to_type; 302 303 from_type = XrmStringToQuark(from); 304 to_type = XrmStringToQuark(to); 305 306 if ((conv = get_converter(from_lcd, from_type, to_lcd, to_type))) 307 return conv; 308 309 return open_indirect_converter(from_lcd, from, to_lcd, to); 310} 311 312void 313_XlcCloseConverter( 314 XlcConv conv) 315{ 316 close_converter(conv); 317} 318 319int 320_XlcConvert( 321 XlcConv conv, 322 XPointer *from, 323 int *from_left, 324 XPointer *to, 325 int *to_left, 326 XPointer *args, 327 int num_args) 328{ 329 return (*conv->methods->convert)(conv, from, from_left, to, to_left, args, 330 num_args); 331} 332 333void 334_XlcResetConverter( 335 XlcConv conv) 336{ 337 if (conv->methods->reset) 338 (*conv->methods->reset)(conv); 339} 340