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 <stdio.h> 32d4a3aaf4Smrg#include "locking.h" 33d4a3aaf4Smrg 34d4a3aaf4Smrg#ifdef XTHREADS 35d4a3aaf4SmrgLockInfoPtr _conv_lock; 36d4a3aaf4Smrg#endif 371ab64890Smrg 381ab64890Smrgtypedef struct _XlcConverterListRec { 391ab64890Smrg XLCd from_lcd; 401ab64890Smrg const char *from; 411ab64890Smrg XrmQuark from_type; 421ab64890Smrg XLCd to_lcd; 431ab64890Smrg const char *to; 441ab64890Smrg XrmQuark to_type; 451ab64890Smrg XlcOpenConverterProc converter; 461ab64890Smrg struct _XlcConverterListRec *next; 471ab64890Smrg} XlcConverterListRec, *XlcConverterList; 481ab64890Smrg 491ab64890Smrgstatic XlcConverterList conv_list = NULL; 501ab64890Smrg 511ab64890Smrgstatic void 521ab64890Smrgclose_converter( 531ab64890Smrg XlcConv conv) 541ab64890Smrg{ 551ab64890Smrg (*conv->methods->close)(conv); 561ab64890Smrg} 571ab64890Smrg 581ab64890Smrgstatic XlcConv 591ab64890Smrgget_converter( 601ab64890Smrg XLCd from_lcd, 611ab64890Smrg XrmQuark from_type, 621ab64890Smrg XLCd to_lcd, 631ab64890Smrg XrmQuark to_type) 641ab64890Smrg{ 651ab64890Smrg XlcConverterList list, prev = NULL; 66d4a3aaf4Smrg XlcConv conv = NULL; 67d4a3aaf4Smrg 68d4a3aaf4Smrg _XLockMutex(_conv_lock); 691ab64890Smrg 701ab64890Smrg for (list = conv_list; list; list = list->next) { 7161b2299dSmrg if (list->from_lcd == from_lcd && list->to_lcd == to_lcd 721ab64890Smrg && list->from_type == from_type && list->to_type == to_type) { 731ab64890Smrg 741ab64890Smrg if (prev && prev != conv_list) { /* XXX */ 751ab64890Smrg prev->next = list->next; 761ab64890Smrg list->next = conv_list; 771ab64890Smrg conv_list = list; 781ab64890Smrg } 791ab64890Smrg 80d4a3aaf4Smrg conv = (*list->converter)(from_lcd, list->from, to_lcd, list->to); 81d4a3aaf4Smrg break; 821ab64890Smrg } 831ab64890Smrg 841ab64890Smrg prev = list; 851ab64890Smrg } 861ab64890Smrg 87d4a3aaf4Smrg _XUnlockMutex(_conv_lock); 88d4a3aaf4Smrg 89d4a3aaf4Smrg return conv; 901ab64890Smrg} 911ab64890Smrg 921ab64890SmrgBool 931ab64890Smrg_XlcSetConverter( 941ab64890Smrg XLCd from_lcd, 951ab64890Smrg const char *from, 961ab64890Smrg XLCd to_lcd, 971ab64890Smrg const char *to, 981ab64890Smrg XlcOpenConverterProc converter) 991ab64890Smrg{ 1001ab64890Smrg XlcConverterList list; 1011ab64890Smrg XrmQuark from_type, to_type; 1021ab64890Smrg 1031ab64890Smrg from_type = XrmStringToQuark(from); 1041ab64890Smrg to_type = XrmStringToQuark(to); 1051ab64890Smrg 106d4a3aaf4Smrg _XLockMutex(_conv_lock); 107d4a3aaf4Smrg 1081ab64890Smrg for (list = conv_list; list; list = list->next) { 10961b2299dSmrg if (list->from_lcd == from_lcd && list->to_lcd == to_lcd 1101ab64890Smrg && list->from_type == from_type && list->to_type == to_type) { 1111ab64890Smrg 1121ab64890Smrg list->converter = converter; 113d4a3aaf4Smrg goto ret; 1141ab64890Smrg } 1151ab64890Smrg } 1161ab64890Smrg 117818534a1Smrg list = Xmalloc(sizeof(XlcConverterListRec)); 1181ab64890Smrg if (list == NULL) 119d4a3aaf4Smrg goto ret; 1201ab64890Smrg 1211ab64890Smrg list->from_lcd = from_lcd; 1221ab64890Smrg list->from = from; 1231ab64890Smrg list->from_type = from_type; 1241ab64890Smrg list->to_lcd = to_lcd; 1251ab64890Smrg list->to = to; 1261ab64890Smrg list->to_type = to_type; 1271ab64890Smrg list->converter = converter; 1281ab64890Smrg list->next = conv_list; 1291ab64890Smrg conv_list = list; 1301ab64890Smrg 131d4a3aaf4Smrgret: 132d4a3aaf4Smrg _XUnlockMutex(_conv_lock); 133d4a3aaf4Smrg return list != NULL; 1341ab64890Smrg} 1351ab64890Smrg 1361ab64890Smrgtypedef struct _ConvRec { 1371ab64890Smrg XlcConv from_conv; 1381ab64890Smrg XlcConv to_conv; 1391ab64890Smrg} ConvRec, *Conv; 1401ab64890Smrg 1411ab64890Smrgstatic int 1421ab64890Smrgindirect_convert( 1431ab64890Smrg XlcConv lc_conv, 1441ab64890Smrg XPointer *from, 1451ab64890Smrg int *from_left, 1461ab64890Smrg XPointer *to, 1471ab64890Smrg int *to_left, 1481ab64890Smrg XPointer *args, 1491ab64890Smrg int num_args) 1501ab64890Smrg{ 1511ab64890Smrg Conv conv = (Conv) lc_conv->state; 1521ab64890Smrg XlcConv from_conv = conv->from_conv; 1531ab64890Smrg XlcConv to_conv = conv->to_conv; 1541ab64890Smrg XlcCharSet charset; 1551ab64890Smrg char buf[BUFSIZ], *cs; 1561ab64890Smrg XPointer tmp_args[1]; 1571ab64890Smrg int cs_left, ret, length, unconv_num = 0; 1581ab64890Smrg 1591ab64890Smrg if (from == NULL || *from == NULL) { 1601ab64890Smrg if (from_conv->methods->reset) 1611ab64890Smrg (*from_conv->methods->reset)(from_conv); 1621ab64890Smrg 1631ab64890Smrg if (to_conv->methods->reset) 1641ab64890Smrg (*to_conv->methods->reset)(to_conv); 1651ab64890Smrg 1661ab64890Smrg return 0; 1671ab64890Smrg } 1681ab64890Smrg 1691ab64890Smrg while (*from_left > 0) { 1701ab64890Smrg cs = buf; 1711ab64890Smrg cs_left = BUFSIZ; 1721ab64890Smrg tmp_args[0] = (XPointer) &charset; 1731ab64890Smrg 1741ab64890Smrg ret = (*from_conv->methods->convert)(from_conv, from, from_left, &cs, 1751ab64890Smrg &cs_left, tmp_args, 1); 1761ab64890Smrg if (ret < 0) 1771ab64890Smrg break; 1781ab64890Smrg 1791ab64890Smrg unconv_num += ret; 1801ab64890Smrg 1811ab64890Smrg length = cs - buf; 1821ab64890Smrg if (length > 0) { 1831ab64890Smrg cs_left = length; 1841ab64890Smrg cs = buf; 1851ab64890Smrg 1861ab64890Smrg tmp_args[0] = (XPointer) charset; 1871ab64890Smrg 1881ab64890Smrg ret = (*to_conv->methods->convert)(to_conv, &cs, &cs_left, to, to_left, 1891ab64890Smrg tmp_args, 1); 1901ab64890Smrg if (ret < 0) { 1911ab64890Smrg unconv_num += length / (charset->char_size > 0 ? charset->char_size : 1); 1921ab64890Smrg continue; 1931ab64890Smrg } 1941ab64890Smrg 1951ab64890Smrg unconv_num += ret; 1961ab64890Smrg 1971ab64890Smrg if (*to_left < 1) 1981ab64890Smrg break; 1991ab64890Smrg } 2001ab64890Smrg } 2011ab64890Smrg 2021ab64890Smrg return unconv_num; 2031ab64890Smrg} 2041ab64890Smrg 2051ab64890Smrgstatic void 2061ab64890Smrgclose_indirect_converter( 2071ab64890Smrg XlcConv lc_conv) 2081ab64890Smrg{ 2091ab64890Smrg Conv conv = (Conv) lc_conv->state; 2101ab64890Smrg 2111ab64890Smrg if (conv) { 2121ab64890Smrg if (conv->from_conv) 2131ab64890Smrg close_converter(conv->from_conv); 2141ab64890Smrg if (conv->to_conv) 2151ab64890Smrg close_converter(conv->to_conv); 2161ab64890Smrg 217818534a1Smrg Xfree(conv); 2181ab64890Smrg } 2191ab64890Smrg 220818534a1Smrg Xfree(lc_conv); 2211ab64890Smrg} 2221ab64890Smrg 2231ab64890Smrgstatic void 2241ab64890Smrgreset_indirect_converter( 2251ab64890Smrg XlcConv lc_conv) 2261ab64890Smrg{ 2271ab64890Smrg Conv conv = (Conv) lc_conv->state; 2281ab64890Smrg 2291ab64890Smrg if (conv) { 2301ab64890Smrg if (conv->from_conv && conv->from_conv->methods->reset) 2311ab64890Smrg (*conv->from_conv->methods->reset)(conv->from_conv); 2321ab64890Smrg if (conv->to_conv && conv->to_conv->methods->reset) 2331ab64890Smrg (*conv->to_conv->methods->reset)(conv->to_conv); 2341ab64890Smrg } 2351ab64890Smrg} 2361ab64890Smrg 2371ab64890Smrgstatic XlcConvMethodsRec conv_methods = { 2381ab64890Smrg close_indirect_converter, 2391ab64890Smrg indirect_convert, 2401ab64890Smrg reset_indirect_converter 2411ab64890Smrg} ; 2421ab64890Smrg 2431ab64890Smrgstatic XlcConv 2441ab64890Smrgopen_indirect_converter( 2451ab64890Smrg XLCd from_lcd, 2461ab64890Smrg const char *from, 2471ab64890Smrg XLCd to_lcd, 2481ab64890Smrg const char *to) 2491ab64890Smrg{ 2501ab64890Smrg XlcConv lc_conv, from_conv, to_conv; 2511ab64890Smrg Conv conv; 2521ab64890Smrg XrmQuark from_type, to_type; 2531ab64890Smrg static XrmQuark QChar, QCharSet, QCTCharSet = (XrmQuark) 0; 2541ab64890Smrg 2551ab64890Smrg if (QCTCharSet == (XrmQuark) 0) { 2561ab64890Smrg QCTCharSet = XrmStringToQuark(XlcNCTCharSet); 2571ab64890Smrg QCharSet = XrmStringToQuark(XlcNCharSet); 2581ab64890Smrg QChar = XrmStringToQuark(XlcNChar); 2591ab64890Smrg } 2601ab64890Smrg 2611ab64890Smrg from_type = XrmStringToQuark(from); 2621ab64890Smrg to_type = XrmStringToQuark(to); 2631ab64890Smrg 2641ab64890Smrg if (from_type == QCharSet || from_type == QChar || to_type == QCharSet || 2651ab64890Smrg to_type == QChar) 2661ab64890Smrg return (XlcConv) NULL; 2671ab64890Smrg 268818534a1Smrg lc_conv = Xmalloc(sizeof(XlcConvRec)); 2691ab64890Smrg if (lc_conv == NULL) 2701ab64890Smrg return (XlcConv) NULL; 2711ab64890Smrg 2721ab64890Smrg lc_conv->methods = &conv_methods; 2731ab64890Smrg 274818534a1Smrg lc_conv->state = Xcalloc(1, sizeof(ConvRec)); 2751ab64890Smrg if (lc_conv->state == NULL) 2761ab64890Smrg goto err; 2771ab64890Smrg 2781ab64890Smrg conv = (Conv) lc_conv->state; 2791ab64890Smrg 2801ab64890Smrg from_conv = get_converter(from_lcd, from_type, from_lcd, QCTCharSet); 2811ab64890Smrg if (from_conv == NULL) 2821ab64890Smrg from_conv = get_converter(from_lcd, from_type, from_lcd, QCharSet); 2831ab64890Smrg if (from_conv == NULL) 2841ab64890Smrg from_conv = get_converter((XLCd)NULL, from_type, (XLCd)NULL, QCharSet); 2851ab64890Smrg if (from_conv == NULL) 2861ab64890Smrg from_conv = get_converter(from_lcd, from_type, from_lcd, QChar); 2871ab64890Smrg if (from_conv == NULL) 2881ab64890Smrg goto err; 2891ab64890Smrg conv->from_conv = from_conv; 2901ab64890Smrg 2911ab64890Smrg to_conv = get_converter(to_lcd, QCTCharSet, to_lcd, to_type); 2921ab64890Smrg if (to_conv == NULL) 2931ab64890Smrg to_conv = get_converter(to_lcd, QCharSet, to_lcd, to_type); 2941ab64890Smrg if (to_conv == NULL) 2951ab64890Smrg to_conv = get_converter((XLCd) NULL, QCharSet, (XLCd) NULL, to_type); 2961ab64890Smrg if (to_conv == NULL) 2971ab64890Smrg goto err; 2981ab64890Smrg conv->to_conv = to_conv; 2991ab64890Smrg 3001ab64890Smrg return lc_conv; 3011ab64890Smrg 3021ab64890Smrgerr: 3031ab64890Smrg close_indirect_converter(lc_conv); 3041ab64890Smrg 3051ab64890Smrg return (XlcConv) NULL; 3061ab64890Smrg} 3071ab64890Smrg 3081ab64890SmrgXlcConv 3091ab64890Smrg_XlcOpenConverter( 3101ab64890Smrg XLCd from_lcd, 3111ab64890Smrg const char *from, 3121ab64890Smrg XLCd to_lcd, 3131ab64890Smrg const char *to) 3141ab64890Smrg{ 3151ab64890Smrg XlcConv conv; 3161ab64890Smrg XrmQuark from_type, to_type; 3171ab64890Smrg 3181ab64890Smrg from_type = XrmStringToQuark(from); 3191ab64890Smrg to_type = XrmStringToQuark(to); 3201ab64890Smrg 3211ab64890Smrg if ((conv = get_converter(from_lcd, from_type, to_lcd, to_type))) 3221ab64890Smrg return conv; 3231ab64890Smrg 3241ab64890Smrg return open_indirect_converter(from_lcd, from, to_lcd, to); 3251ab64890Smrg} 3261ab64890Smrg 3271ab64890Smrgvoid 3281ab64890Smrg_XlcCloseConverter( 3291ab64890Smrg XlcConv conv) 3301ab64890Smrg{ 3311ab64890Smrg close_converter(conv); 3321ab64890Smrg} 3331ab64890Smrg 3341ab64890Smrgint 3351ab64890Smrg_XlcConvert( 3361ab64890Smrg XlcConv conv, 3371ab64890Smrg XPointer *from, 3381ab64890Smrg int *from_left, 3391ab64890Smrg XPointer *to, 3401ab64890Smrg int *to_left, 3411ab64890Smrg XPointer *args, 3421ab64890Smrg int num_args) 3431ab64890Smrg{ 3441ab64890Smrg return (*conv->methods->convert)(conv, from, from_left, to, to_left, args, 3451ab64890Smrg num_args); 3461ab64890Smrg} 3471ab64890Smrg 3481ab64890Smrgvoid 3491ab64890Smrg_XlcResetConverter( 3501ab64890Smrg XlcConv conv) 3511ab64890Smrg{ 3521ab64890Smrg if (conv->methods->reset) 3531ab64890Smrg (*conv->methods->reset)(conv); 3541ab64890Smrg} 355