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