imLcIm.c revision 1ab64890
11ab64890Smrg/* $Xorg: imLcIm.c,v 1.3 2000/08/17 19:45:14 cpqbld Exp $ */ 21ab64890Smrg/****************************************************************** 31ab64890Smrg 41ab64890Smrg Copyright 1992, 1993, 1994 by FUJITSU LIMITED 51ab64890Smrg Copyright 1993 by Digital Equipment Corporation 61ab64890Smrg 71ab64890SmrgPermission to use, copy, modify, distribute, and sell this software 81ab64890Smrgand its documentation for any purpose is hereby granted without fee, 91ab64890Smrgprovided that the above copyright notice appear in all copies and that 101ab64890Smrgboth that copyright notice and this permission notice appear in 111ab64890Smrgsupporting documentation, and that the name of FUJITSU LIMITED and 121ab64890SmrgDigital Equipment Corporation not be used in advertising or publicity 131ab64890Smrgpertaining to distribution of the software without specific, written 141ab64890Smrgprior permission. FUJITSU LIMITED and Digital Equipment Corporation 151ab64890Smrgmakes no representations about the suitability of this software for 161ab64890Smrgany purpose. It is provided "as is" without express or implied 171ab64890Smrgwarranty. 181ab64890Smrg 191ab64890SmrgFUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL 201ab64890SmrgWARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED 211ab64890SmrgWARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 221ab64890SmrgFUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR 231ab64890SmrgANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 241ab64890SmrgWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 251ab64890SmrgIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 261ab64890SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 271ab64890SmrgTHIS SOFTWARE. 281ab64890Smrg 291ab64890Smrg Author: Takashi Fujiwara FUJITSU LIMITED 301ab64890Smrg fujiwara@a80.tech.yk.fujitsu.co.jp 311ab64890Smrg Modifier: Franky Ling Digital Equipment Corporation 321ab64890Smrg frankyling@hgrd01.enet.dec.com 331ab64890Smrg 341ab64890Smrg******************************************************************/ 351ab64890Smrg/* $XFree86: xc/lib/X11/imLcIm.c,v 1.12 2003/09/06 14:06:32 pascal Exp $ */ 361ab64890Smrg 371ab64890Smrg#ifdef HAVE_CONFIG_H 381ab64890Smrg#include <config.h> 391ab64890Smrg#endif 401ab64890Smrg#include <stdio.h> 411ab64890Smrg 421ab64890Smrg#include <X11/Xmd.h> 431ab64890Smrg#include <X11/Xatom.h> 441ab64890Smrg#include <X11/Xos.h> 451ab64890Smrg#include "Xlibint.h" 461ab64890Smrg#include "Xlcint.h" 471ab64890Smrg#include "XlcPublic.h" 481ab64890Smrg#include "XlcPubI.h" 491ab64890Smrg#include "Ximint.h" 501ab64890Smrg#include <ctype.h> 511ab64890Smrg#include <assert.h> 521ab64890Smrg 531ab64890Smrg#ifdef COMPOSECACHE 541ab64890Smrg# include <sys/types.h> 551ab64890Smrg# include <sys/stat.h> 561ab64890Smrg# include <sys/mman.h> 571ab64890Smrg# include <langinfo.h> 581ab64890Smrg#endif 591ab64890Smrg 601ab64890Smrg 611ab64890Smrg#ifdef COMPOSECACHE 621ab64890Smrg 631ab64890Smrg/* include trailing '/' for cache directory, file prefix otherwise */ 641ab64890Smrg#define XIM_GLOBAL_CACHE_DIR "/var/cache/libx11/compose/" 651ab64890Smrg#define XIM_HOME_CACHE_DIR "/.compose-cache/" 661ab64890Smrg#define XIM_CACHE_MAGIC ('X' | 'i'<<8 | 'm'<<16 | 'C'<<24) 671ab64890Smrg#define XIM_CACHE_VERSION 4 681ab64890Smrg#define XIM_CACHE_TREE_ALIGNMENT 4 691ab64890Smrg 701ab64890Smrg#define XIM_HASH_PRIME_1 13 711ab64890Smrg#define XIM_HASH_PRIME_2 1234096939 721ab64890Smrg 731ab64890Smrgtypedef INT32 DTStructIndex; 741ab64890Smrgstruct _XimCacheStruct { 751ab64890Smrg INT32 id; 761ab64890Smrg INT32 version; 771ab64890Smrg DTStructIndex tree; 781ab64890Smrg DTStructIndex mb; 791ab64890Smrg DTStructIndex wc; 801ab64890Smrg DTStructIndex utf8; 811ab64890Smrg DTStructIndex size; 821ab64890Smrg DTIndex top; 831ab64890Smrg DTIndex treeused; 841ab64890Smrg DTCharIndex mbused; 851ab64890Smrg DTCharIndex wcused; 861ab64890Smrg DTCharIndex utf8used; 871ab64890Smrg char fname[1]; 881ab64890Smrg /* char encoding[1] */ 891ab64890Smrg}; 901ab64890Smrg 911ab64890SmrgPrivate struct _XimCacheStruct* _XimCache_mmap = NULL; 921ab64890SmrgPrivate DefTreeBase _XimCachedDefaultTreeBase; 931ab64890SmrgPrivate int _XimCachedDefaultTreeRefcount = 0; 941ab64890Smrg 951ab64890Smrg#endif 961ab64890Smrg 971ab64890Smrg 981ab64890SmrgPublic Bool 991ab64890Smrg_XimCheckIfLocalProcessing(im) 1001ab64890Smrg Xim im; 1011ab64890Smrg{ 1021ab64890Smrg FILE *fp; 1031ab64890Smrg char *name; 1041ab64890Smrg 1051ab64890Smrg if(strcmp(im->core.im_name, "") == 0) { 1061ab64890Smrg name = _XlcFileName(im->core.lcd, COMPOSE_FILE); 1071ab64890Smrg if (name != (char *)NULL) { 1081ab64890Smrg fp = _XFopenFile (name, "r"); 1091ab64890Smrg Xfree(name); 1101ab64890Smrg if (fp != (FILE *)NULL) { 1111ab64890Smrg fclose(fp); 1121ab64890Smrg return(True); 1131ab64890Smrg } 1141ab64890Smrg } 1151ab64890Smrg return(False); 1161ab64890Smrg } else if(strcmp(im->core.im_name, "local") == 0 || 1171ab64890Smrg strcmp(im->core.im_name, "none" ) == 0 ) { 1181ab64890Smrg return(True); 1191ab64890Smrg } 1201ab64890Smrg return(False); 1211ab64890Smrg} 1221ab64890Smrg 1231ab64890SmrgPrivate void 1241ab64890SmrgXimFreeDefaultTree( 1251ab64890Smrg DefTreeBase *b) 1261ab64890Smrg{ 1271ab64890Smrg if (!b) return; 1281ab64890Smrg if (b->tree == NULL) return; 1291ab64890Smrg#ifdef COMPOSECACHE 1301ab64890Smrg if (b->tree == _XimCachedDefaultTreeBase.tree) { 1311ab64890Smrg _XimCachedDefaultTreeRefcount--; 1321ab64890Smrg /* No deleting, it's a cache after all. */ 1331ab64890Smrg return; 1341ab64890Smrg } 1351ab64890Smrg#endif 1361ab64890Smrg Xfree (b->tree); 1371ab64890Smrg if (b->mb) Xfree (b->mb); 1381ab64890Smrg if (b->wc) Xfree (b->wc); 1391ab64890Smrg if (b->utf8) Xfree (b->utf8); 1401ab64890Smrg b->tree = NULL; 1411ab64890Smrg b->mb = NULL; 1421ab64890Smrg b->wc = NULL; 1431ab64890Smrg b->utf8 = NULL; 1441ab64890Smrg b->treeused = b->treesize = 0; 1451ab64890Smrg b->mbused = b->mbsize = 0; 1461ab64890Smrg b->wcused = b->wcsize = 0; 1471ab64890Smrg b->utf8used = b->utf8size = 0; 1481ab64890Smrg} 1491ab64890Smrg 1501ab64890SmrgPublic void 1511ab64890Smrg_XimLocalIMFree( 1521ab64890Smrg Xim im) 1531ab64890Smrg{ 1541ab64890Smrg XimFreeDefaultTree(&im->private.local.base); 1551ab64890Smrg im->private.local.top = 0; 1561ab64890Smrg 1571ab64890Smrg if(im->core.im_resources) { 1581ab64890Smrg Xfree(im->core.im_resources); 1591ab64890Smrg im->core.im_resources = NULL; 1601ab64890Smrg } 1611ab64890Smrg if(im->core.ic_resources) { 1621ab64890Smrg Xfree(im->core.ic_resources); 1631ab64890Smrg im->core.ic_resources = NULL; 1641ab64890Smrg } 1651ab64890Smrg if(im->core.im_values_list) { 1661ab64890Smrg Xfree(im->core.im_values_list); 1671ab64890Smrg im->core.im_values_list = NULL; 1681ab64890Smrg } 1691ab64890Smrg if(im->core.ic_values_list) { 1701ab64890Smrg Xfree(im->core.ic_values_list); 1711ab64890Smrg im->core.ic_values_list = NULL; 1721ab64890Smrg } 1731ab64890Smrg if(im->core.styles) { 1741ab64890Smrg Xfree(im->core.styles); 1751ab64890Smrg im->core.styles = NULL; 1761ab64890Smrg } 1771ab64890Smrg if(im->core.res_name) { 1781ab64890Smrg Xfree(im->core.res_name); 1791ab64890Smrg im->core.res_name = NULL; 1801ab64890Smrg } 1811ab64890Smrg if(im->core.res_class) { 1821ab64890Smrg Xfree(im->core.res_class); 1831ab64890Smrg im->core.res_class = NULL; 1841ab64890Smrg } 1851ab64890Smrg if(im->core.im_name) { 1861ab64890Smrg Xfree(im->core.im_name); 1871ab64890Smrg im->core.im_name = NULL; 1881ab64890Smrg } 1891ab64890Smrg if (im->private.local.ctom_conv) { 1901ab64890Smrg _XlcCloseConverter(im->private.local.ctom_conv); 1911ab64890Smrg im->private.local.ctom_conv = NULL; 1921ab64890Smrg } 1931ab64890Smrg if (im->private.local.ctow_conv) { 1941ab64890Smrg _XlcCloseConverter(im->private.local.ctow_conv); 1951ab64890Smrg im->private.local.ctow_conv = NULL; 1961ab64890Smrg } 1971ab64890Smrg if (im->private.local.ctoutf8_conv) { 1981ab64890Smrg _XlcCloseConverter(im->private.local.ctoutf8_conv); 1991ab64890Smrg im->private.local.ctoutf8_conv = NULL; 2001ab64890Smrg } 2011ab64890Smrg if (im->private.local.cstomb_conv) { 2021ab64890Smrg _XlcCloseConverter(im->private.local.cstomb_conv); 2031ab64890Smrg im->private.local.cstomb_conv = NULL; 2041ab64890Smrg } 2051ab64890Smrg if (im->private.local.cstowc_conv) { 2061ab64890Smrg _XlcCloseConverter(im->private.local.cstowc_conv); 2071ab64890Smrg im->private.local.cstowc_conv = NULL; 2081ab64890Smrg } 2091ab64890Smrg if (im->private.local.cstoutf8_conv) { 2101ab64890Smrg _XlcCloseConverter(im->private.local.cstoutf8_conv); 2111ab64890Smrg im->private.local.cstoutf8_conv = NULL; 2121ab64890Smrg } 2131ab64890Smrg if (im->private.local.ucstoc_conv) { 2141ab64890Smrg _XlcCloseConverter(im->private.local.ucstoc_conv); 2151ab64890Smrg im->private.local.ucstoc_conv = NULL; 2161ab64890Smrg } 2171ab64890Smrg if (im->private.local.ucstoutf8_conv) { 2181ab64890Smrg _XlcCloseConverter(im->private.local.ucstoutf8_conv); 2191ab64890Smrg im->private.local.ucstoutf8_conv = NULL; 2201ab64890Smrg } 2211ab64890Smrg return; 2221ab64890Smrg} 2231ab64890Smrg 2241ab64890SmrgPrivate Status 2251ab64890Smrg_XimLocalCloseIM( 2261ab64890Smrg XIM xim) 2271ab64890Smrg{ 2281ab64890Smrg Xim im = (Xim)xim; 2291ab64890Smrg XIC ic; 2301ab64890Smrg XIC next; 2311ab64890Smrg 2321ab64890Smrg ic = im->core.ic_chain; 2331ab64890Smrg im->core.ic_chain = NULL; 2341ab64890Smrg while (ic) { 2351ab64890Smrg (*ic->methods->destroy) (ic); 2361ab64890Smrg next = ic->core.next; 2371ab64890Smrg Xfree ((char *) ic); 2381ab64890Smrg ic = next; 2391ab64890Smrg } 2401ab64890Smrg _XimLocalIMFree(im); 2411ab64890Smrg _XimDestroyIMStructureList(im); 2421ab64890Smrg return(True); 2431ab64890Smrg} 2441ab64890Smrg 2451ab64890SmrgPublic char * 2461ab64890Smrg_XimLocalGetIMValues( 2471ab64890Smrg XIM xim, 2481ab64890Smrg XIMArg *values) 2491ab64890Smrg{ 2501ab64890Smrg Xim im = (Xim)xim; 2511ab64890Smrg XimDefIMValues im_values; 2521ab64890Smrg 2531ab64890Smrg _XimGetCurrentIMValues(im, &im_values); 2541ab64890Smrg return(_XimGetIMValueData(im, (XPointer)&im_values, values, 2551ab64890Smrg im->core.im_resources, im->core.im_num_resources)); 2561ab64890Smrg} 2571ab64890Smrg 2581ab64890SmrgPublic char * 2591ab64890Smrg_XimLocalSetIMValues( 2601ab64890Smrg XIM xim, 2611ab64890Smrg XIMArg *values) 2621ab64890Smrg{ 2631ab64890Smrg Xim im = (Xim)xim; 2641ab64890Smrg XimDefIMValues im_values; 2651ab64890Smrg char *name = (char *)NULL; 2661ab64890Smrg 2671ab64890Smrg _XimGetCurrentIMValues(im, &im_values); 2681ab64890Smrg name = _XimSetIMValueData(im, (XPointer)&im_values, values, 2691ab64890Smrg im->core.im_resources, im->core.im_num_resources); 2701ab64890Smrg _XimSetCurrentIMValues(im, &im_values); 2711ab64890Smrg return(name); 2721ab64890Smrg} 2731ab64890Smrg 2741ab64890Smrg 2751ab64890Smrg#ifdef COMPOSECACHE 2761ab64890Smrg 2771ab64890SmrgPrivate Bool 2781ab64890Smrg_XimReadCachedDefaultTree( 2791ab64890Smrg int fd_cache, 2801ab64890Smrg const char *name, 2811ab64890Smrg const char *encoding, 2821ab64890Smrg DTStructIndex size) 2831ab64890Smrg{ 2841ab64890Smrg struct _XimCacheStruct* m; 2851ab64890Smrg int namelen = strlen (name) + 1; 2861ab64890Smrg int encodinglen = strlen (encoding) + 1; 2871ab64890Smrg 2881ab64890Smrg m = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd_cache, 0); 2891ab64890Smrg if (m == NULL || m == MAP_FAILED) 2901ab64890Smrg return False; 2911ab64890Smrg assert (m->id == XIM_CACHE_MAGIC); 2921ab64890Smrg assert (m->version == XIM_CACHE_VERSION); 2931ab64890Smrg if (size != m->size || 2941ab64890Smrg size < XOffsetOf (struct _XimCacheStruct, fname) + namelen + encodinglen) { 2951ab64890Smrg fprintf (stderr, "Ignoring broken XimCache %s [%s]\n", name, encoding); 2961ab64890Smrg munmap (m, size); 2971ab64890Smrg return False; 2981ab64890Smrg } 2991ab64890Smrg if (strncmp (name, m->fname, namelen) != 0) { 3001ab64890Smrg /* m->fname may *not* be terminated - but who cares here */ 3011ab64890Smrg fprintf (stderr, "Filename hash clash - expected %s, got %s\n", 3021ab64890Smrg name, m->fname); 3031ab64890Smrg munmap (m, size); 3041ab64890Smrg return False; 3051ab64890Smrg } 3061ab64890Smrg if (strncmp (encoding, m->fname + namelen, encodinglen) != 0) { 3071ab64890Smrg /* m->fname+namelen may *not* be terminated - but who cares here */ 3081ab64890Smrg fprintf (stderr, "Enoding hash clash - expected %s, got %s\n", 3091ab64890Smrg encoding, m->fname + namelen); 3101ab64890Smrg munmap (m, size); 3111ab64890Smrg return False; 3121ab64890Smrg } 3131ab64890Smrg _XimCache_mmap = m; 3141ab64890Smrg _XimCachedDefaultTreeBase.tree = (DefTree *) (((char *) m) + m->tree); 3151ab64890Smrg _XimCachedDefaultTreeBase.mb = (((char *) m) + m->mb); 3161ab64890Smrg _XimCachedDefaultTreeBase.wc = (wchar_t *) (((char *) m) + m->wc); 3171ab64890Smrg _XimCachedDefaultTreeBase.utf8 = (((char *) m) + m->utf8); 3181ab64890Smrg _XimCachedDefaultTreeBase.treeused = m->treeused; 3191ab64890Smrg _XimCachedDefaultTreeBase.mbused = m->mbused; 3201ab64890Smrg _XimCachedDefaultTreeBase.wcused = m->wcused; 3211ab64890Smrg _XimCachedDefaultTreeBase.utf8used = m->utf8used; 3221ab64890Smrg /* treesize etc. is ignored because only used during parsing */ 3231ab64890Smrg _XimCachedDefaultTreeRefcount = 0; 3241ab64890Smrg/* fprintf (stderr, "read cached tree at %p: %s\n", (void *) m, name); */ 3251ab64890Smrg return True; 3261ab64890Smrg} 3271ab64890Smrg 3281ab64890SmrgPrivate unsigned int strToHash ( 3291ab64890Smrg const char *name) 3301ab64890Smrg{ 3311ab64890Smrg unsigned int hash = 0; 3321ab64890Smrg while (*name) 3331ab64890Smrg hash = hash * XIM_HASH_PRIME_1 + *(unsigned const char *)name++; 3341ab64890Smrg return hash % XIM_HASH_PRIME_2; 3351ab64890Smrg} 3361ab64890Smrg 3371ab64890Smrg 3381ab64890Smrg/* Returns read-only fd of cache file, -1 if none. 3391ab64890Smrg * Sets *res to cache filename if safe. Sets *size to file size of cache. */ 3401ab64890SmrgPrivate int _XimCachedFileName ( 3411ab64890Smrg const char *dir, const char *name, 3421ab64890Smrg const char *intname, const char *encoding, 3431ab64890Smrg uid_t uid, int isglobal, char **res, off_t *size) 3441ab64890Smrg{ 3451ab64890Smrg struct stat st_name, st; 3461ab64890Smrg int fd; 3471ab64890Smrg unsigned int len, hash, hash2; 3481ab64890Smrg struct _XimCacheStruct *m; 3491ab64890Smrg /* There are some races here with 'dir', but we are either in our own home 3501ab64890Smrg * or the global cache dir, and not inside some public writable dir */ 3511ab64890Smrg/* fprintf (stderr, "XimCachedFileName for dir %s name %s intname %s encoding %s uid %d\n", dir, name, intname, encoding, uid); */ 3521ab64890Smrg if (stat (name, &st_name) == -1 || ! S_ISREG (st_name.st_mode) 3531ab64890Smrg || stat (dir, &st) == -1 || ! S_ISDIR (st.st_mode) || st.st_uid != uid 3541ab64890Smrg || (st.st_mode & 0022) != 0000) { 3551ab64890Smrg *res = NULL; 3561ab64890Smrg return -1; 3571ab64890Smrg } 3581ab64890Smrg len = strlen (dir); 3591ab64890Smrg hash = strToHash (intname); 3601ab64890Smrg hash2 = strToHash (encoding); 3611ab64890Smrg *res = Xmalloc (len + 1 + 27 + 1); /* Max VERSION 9999 */ 3621ab64890Smrg 3631ab64890Smrg if (len == 0 || dir [len-1] != '/') 3641ab64890Smrg sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), 3651ab64890Smrg XIM_CACHE_VERSION, sizeof (DefTree), hash, hash2); 3661ab64890Smrg else 3671ab64890Smrg sprintf (*res, "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), 3681ab64890Smrg XIM_CACHE_VERSION, sizeof (DefTree), hash, hash2); 3691ab64890Smrg 3701ab64890Smrg/* fprintf (stderr, "-> %s\n", *res); */ 3711ab64890Smrg if ( (fd = _XOpenFile (*res, O_RDONLY)) == -1) 3721ab64890Smrg return -1; 3731ab64890Smrg 3741ab64890Smrg if (fstat (fd, &st) == -1) { 3751ab64890Smrg Xfree (*res); 3761ab64890Smrg *res = NULL; 3771ab64890Smrg close (fd); 3781ab64890Smrg return -1; 3791ab64890Smrg } 3801ab64890Smrg *size = st.st_size; 3811ab64890Smrg 3821ab64890Smrg if (! S_ISREG (st.st_mode) || st.st_uid != uid 3831ab64890Smrg || (st.st_mode & 0022) != 0000 || st.st_mtime <= st_name.st_mtime 3841ab64890Smrg || (st.st_mtime < time (NULL) - 24*60*60 && ! isglobal)) { 3851ab64890Smrg 3861ab64890Smrg close (fd); 3871ab64890Smrg if (unlink (*res) != 0) { 3881ab64890Smrg Xfree (*res); 3891ab64890Smrg *res = NULL; /* cache is not safe */ 3901ab64890Smrg } 3911ab64890Smrg return -1; 3921ab64890Smrg } 3931ab64890Smrg 3941ab64890Smrg m = mmap (NULL, sizeof (struct _XimCacheStruct), PROT_READ, MAP_PRIVATE, 3951ab64890Smrg fd, 0); 3961ab64890Smrg if (m == NULL || m == MAP_FAILED) { 3971ab64890Smrg close (fd); 3981ab64890Smrg Xfree (*res); 3991ab64890Smrg *res = NULL; 4001ab64890Smrg return -1; 4011ab64890Smrg } 4021ab64890Smrg if (*size < sizeof (struct _XimCacheStruct) || m->id != XIM_CACHE_MAGIC) { 4031ab64890Smrg munmap (m, sizeof (struct _XimCacheStruct)); 4041ab64890Smrg close (fd); 4051ab64890Smrg fprintf (stderr, "Ignoring broken XimCache %s\n", *res); 4061ab64890Smrg Xfree (*res); 4071ab64890Smrg *res = NULL; 4081ab64890Smrg return -1; 4091ab64890Smrg } 4101ab64890Smrg if (m->version != XIM_CACHE_VERSION) { 4111ab64890Smrg munmap (m, sizeof (struct _XimCacheStruct)); 4121ab64890Smrg close (fd); 4131ab64890Smrg if (unlink (*res) != 0) { 4141ab64890Smrg Xfree (*res); 4151ab64890Smrg *res = NULL; /* cache is not safe */ 4161ab64890Smrg } 4171ab64890Smrg return -1; 4181ab64890Smrg } 4191ab64890Smrg munmap (m, sizeof (struct _XimCacheStruct)); 4201ab64890Smrg 4211ab64890Smrg return fd; 4221ab64890Smrg} 4231ab64890Smrg 4241ab64890Smrg 4251ab64890SmrgPrivate Bool _XimLoadCache ( 4261ab64890Smrg int fd, 4271ab64890Smrg const char *name, 4281ab64890Smrg const char *encoding, 4291ab64890Smrg off_t size, 4301ab64890Smrg Xim im) 4311ab64890Smrg{ 4321ab64890Smrg if (_XimCache_mmap || 4331ab64890Smrg _XimReadCachedDefaultTree (fd, name, encoding, size)) { 4341ab64890Smrg _XimCachedDefaultTreeRefcount++; 4351ab64890Smrg memcpy (&im->private.local.base, &_XimCachedDefaultTreeBase, 4361ab64890Smrg sizeof (_XimCachedDefaultTreeBase)); 4371ab64890Smrg im->private.local.top = _XimCache_mmap->top; 4381ab64890Smrg return True; 4391ab64890Smrg } 4401ab64890Smrg 4411ab64890Smrg return False; 4421ab64890Smrg} 4431ab64890Smrg 4441ab64890Smrg 4451ab64890SmrgPrivate void 4461ab64890Smrg_XimWriteCachedDefaultTree( 4471ab64890Smrg const char *name, 4481ab64890Smrg const char *encoding, 4491ab64890Smrg const char *cachename, 4501ab64890Smrg Xim im) 4511ab64890Smrg{ 4521ab64890Smrg int fd; 4531ab64890Smrg FILE *fp; 4541ab64890Smrg struct _XimCacheStruct *m; 4551ab64890Smrg int msize = (XOffsetOf(struct _XimCacheStruct, fname) 4561ab64890Smrg + strlen(name) + strlen(encoding) + 2 4571ab64890Smrg + XIM_CACHE_TREE_ALIGNMENT-1) & -XIM_CACHE_TREE_ALIGNMENT; 4581ab64890Smrg DefTreeBase *b = &im->private.local.base; 4591ab64890Smrg 4601ab64890Smrg if (! b->tree && ! (b->tree = Xmalloc (sizeof(DefTree))) ) 4611ab64890Smrg return; 4621ab64890Smrg if (! b->mb && ! (b->mb = Xmalloc (1)) ) 4631ab64890Smrg return; 4641ab64890Smrg if (! b->wc && ! (b->wc = Xmalloc (sizeof(wchar_t))) ) 4651ab64890Smrg return; 4661ab64890Smrg if (! b->utf8 && ! (b->utf8 = Xmalloc (1)) ) 4671ab64890Smrg return; 4681ab64890Smrg 4691ab64890Smrg /* First entry is always unused */ 4701ab64890Smrg memset (b->tree, 0, sizeof(DefTree)); 4711ab64890Smrg b->mb[0] = 0; 4721ab64890Smrg b->wc[0] = 0; 4731ab64890Smrg b->utf8[0] = 0; 4741ab64890Smrg 4751ab64890Smrg m = Xmalloc (msize); 4761ab64890Smrg memset (m, 0, msize); 4771ab64890Smrg m->id = XIM_CACHE_MAGIC; 4781ab64890Smrg m->version = XIM_CACHE_VERSION; 4791ab64890Smrg m->top = im->private.local.top; 4801ab64890Smrg m->treeused = b->treeused; 4811ab64890Smrg m->mbused = b->mbused; 4821ab64890Smrg m->wcused = b->wcused; 4831ab64890Smrg m->utf8used = b->utf8used; 4841ab64890Smrg /* Tree first, then wide chars, then the rest due to alignment */ 4851ab64890Smrg m->tree = msize; 4861ab64890Smrg m->wc = msize + sizeof (DefTree) * m->treeused; 4871ab64890Smrg m->mb = m->wc + sizeof (wchar_t) * m->wcused; 4881ab64890Smrg m->utf8 = m->mb + m->mbused; 4891ab64890Smrg m->size = m->utf8 + m->utf8used; 4901ab64890Smrg strcpy (m->fname, name); 4911ab64890Smrg strcpy (m->fname+strlen(name)+1, encoding); 4921ab64890Smrg 4931ab64890Smrg /* This STILL might be racy on NFS */ 4941ab64890Smrg if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL, 4951ab64890Smrg 0600)) < 0) 4961ab64890Smrg return; 4971ab64890Smrg if (! (fp = fdopen (fd, "wb")) ) { 4981ab64890Smrg close (fd); 4991ab64890Smrg return; 5001ab64890Smrg } 5011ab64890Smrg fwrite (m, msize, 1, fp); 5021ab64890Smrg fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp); 5031ab64890Smrg fwrite (im->private.local.base.wc, sizeof(wchar_t), m->wcused, fp); 5041ab64890Smrg fwrite (im->private.local.base.mb, 1, m->mbused, fp); 5051ab64890Smrg fwrite (im->private.local.base.utf8, 1, m->utf8used, fp); 5061ab64890Smrg if (fclose (fp) != 0) 5071ab64890Smrg unlink (cachename); 5081ab64890Smrg _XimCache_mmap = m; 5091ab64890Smrg memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base, 5101ab64890Smrg sizeof (_XimCachedDefaultTreeBase)); 5111ab64890Smrg/* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */ 5121ab64890Smrg} 5131ab64890Smrg 5141ab64890Smrg#endif 5151ab64890Smrg 5161ab64890Smrg 5171ab64890SmrgPrivate void 5181ab64890Smrg_XimCreateDefaultTree( 5191ab64890Smrg Xim im) 5201ab64890Smrg{ 5211ab64890Smrg FILE *fp = NULL; 5221ab64890Smrg char *name, *tmpname = NULL, *intname; 5231ab64890Smrg char *cachename = NULL; 5241ab64890Smrg /* Should use getpwent() instead of $HOME (cross-platform?) */ 5251ab64890Smrg char *home = getenv("HOME"); 5261ab64890Smrg char *cachedir = NULL; 5271ab64890Smrg char *tmpcachedir = NULL; 5281ab64890Smrg int hl = home ? strlen (home) : 0; 5291ab64890Smrg#ifdef COMPOSECACHE 5301ab64890Smrg const char *encoding = nl_langinfo (CODESET); 5311ab64890Smrg uid_t euid = geteuid (); 5321ab64890Smrg gid_t egid = getegid (); 5331ab64890Smrg int cachefd = -1; 5341ab64890Smrg off_t size; 5351ab64890Smrg#endif 5361ab64890Smrg 5371ab64890Smrg name = getenv("XCOMPOSEFILE"); 5381ab64890Smrg if (name == (char *) NULL) { 5391ab64890Smrg if (home != (char *) NULL) { 5401ab64890Smrg tmpname = name = Xmalloc(hl + 10 + 1); 5411ab64890Smrg if (name != (char *) NULL) { 5421ab64890Smrg int fd; 5431ab64890Smrg strcpy(name, home); 5441ab64890Smrg strcpy(name + hl, "/.XCompose"); 5451ab64890Smrg if ( (fd = _XOpenFile (name, O_RDONLY)) < 0) { 5461ab64890Smrg Xfree (name); 5471ab64890Smrg name = tmpname = NULL; 5481ab64890Smrg } else 5491ab64890Smrg close (fd); 5501ab64890Smrg } 5511ab64890Smrg } 5521ab64890Smrg } 5531ab64890Smrg 5541ab64890Smrg if (name == (char *) NULL) { 5551ab64890Smrg tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE); 5561ab64890Smrg } 5571ab64890Smrg intname = name; 5581ab64890Smrg 5591ab64890Smrg#ifdef COMPOSECACHE 5601ab64890Smrg if (getuid () == euid && getgid () == egid && euid != 0) { 5611ab64890Smrg char *c; 5621ab64890Smrg /* Usage: XCOMPOSECACHE=<cachedir>[=<filename>] 5631ab64890Smrg * cachedir: directory of cache files 5641ab64890Smrg * filename: internally used name for cache file */ 5651ab64890Smrg cachedir = getenv("XCOMPOSECACHE"); 5661ab64890Smrg if (cachedir && (c = strchr (cachedir, '='))) { 5671ab64890Smrg tmpcachedir = strdup (cachedir); 5681ab64890Smrg intname = tmpcachedir + (c-cachedir) + 1; 5691ab64890Smrg tmpcachedir[c-cachedir] = '\0'; 5701ab64890Smrg cachedir = tmpcachedir; 5711ab64890Smrg } 5721ab64890Smrg } 5731ab64890Smrg 5741ab64890Smrg if (! cachedir) { 5751ab64890Smrg cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR, name, intname, 5761ab64890Smrg encoding, 0, 1, &cachename, &size); 5771ab64890Smrg if (cachefd != -1) { 5781ab64890Smrg if (_XimLoadCache (cachefd, intname, encoding, size, im)) { 5791ab64890Smrg if (tmpcachedir) 5801ab64890Smrg Xfree (tmpcachedir); 5811ab64890Smrg if (tmpname) 5821ab64890Smrg Xfree (tmpname); 5831ab64890Smrg if (cachename) 5841ab64890Smrg Xfree (cachename); 5851ab64890Smrg close (cachefd); 5861ab64890Smrg return; 5871ab64890Smrg } 5881ab64890Smrg close (cachefd); 5891ab64890Smrg } 5901ab64890Smrg if (cachename) 5911ab64890Smrg Xfree (cachename); 5921ab64890Smrg cachename = NULL; 5931ab64890Smrg } 5941ab64890Smrg 5951ab64890Smrg if (getuid () == euid && getgid () == egid && euid != 0 && home) { 5961ab64890Smrg 5971ab64890Smrg if (! cachedir) { 5981ab64890Smrg tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1); 5991ab64890Smrg strcpy (cachedir, home); 6001ab64890Smrg strcat (cachedir, XIM_HOME_CACHE_DIR); 6011ab64890Smrg } 6021ab64890Smrg cachefd = _XimCachedFileName (cachedir, name, intname, encoding, 6031ab64890Smrg euid, 0, &cachename, &size); 6041ab64890Smrg if (cachefd != -1) { 6051ab64890Smrg if (_XimLoadCache (cachefd, intname, encoding, size, im)) { 6061ab64890Smrg if (tmpcachedir) 6071ab64890Smrg Xfree (tmpcachedir); 6081ab64890Smrg if (tmpname) 6091ab64890Smrg Xfree (tmpname); 6101ab64890Smrg if (cachename) 6111ab64890Smrg Xfree (cachename); 6121ab64890Smrg close (cachefd); 6131ab64890Smrg return; 6141ab64890Smrg } 6151ab64890Smrg close (cachefd); 6161ab64890Smrg } 6171ab64890Smrg } 6181ab64890Smrg#endif 6191ab64890Smrg 6201ab64890Smrg if (! (fp = _XFopenFile (name, "r"))) { 6211ab64890Smrg if (tmpcachedir) 6221ab64890Smrg Xfree (tmpcachedir); 6231ab64890Smrg if (tmpname) 6241ab64890Smrg Xfree (tmpname); 6251ab64890Smrg if (cachename) 6261ab64890Smrg Xfree (cachename); 6271ab64890Smrg return; 6281ab64890Smrg } 6291ab64890Smrg _XimParseStringFile(fp, im); 6301ab64890Smrg fclose(fp); 6311ab64890Smrg 6321ab64890Smrg#ifdef COMPOSECACHE 6331ab64890Smrg if (cachename) { 6341ab64890Smrg assert (euid != 0); 6351ab64890Smrg _XimWriteCachedDefaultTree (intname, encoding, cachename, im); 6361ab64890Smrg } 6371ab64890Smrg#endif 6381ab64890Smrg 6391ab64890Smrg if (tmpcachedir) 6401ab64890Smrg Xfree (tmpcachedir); 6411ab64890Smrg if (tmpname) 6421ab64890Smrg Xfree (tmpname); 6431ab64890Smrg if (cachename) 6441ab64890Smrg Xfree (cachename); 6451ab64890Smrg} 6461ab64890Smrg 6471ab64890SmrgPrivate XIMMethodsRec Xim_im_local_methods = { 6481ab64890Smrg _XimLocalCloseIM, /* close */ 6491ab64890Smrg _XimLocalSetIMValues, /* set_values */ 6501ab64890Smrg _XimLocalGetIMValues, /* get_values */ 6511ab64890Smrg _XimLocalCreateIC, /* create_ic */ 6521ab64890Smrg _XimLcctstombs, /* ctstombs */ 6531ab64890Smrg _XimLcctstowcs, /* ctstowcs */ 6541ab64890Smrg _XimLcctstoutf8 /* ctstoutf8 */ 6551ab64890Smrg}; 6561ab64890Smrg 6571ab64890SmrgPublic Bool 6581ab64890Smrg_XimLocalOpenIM( 6591ab64890Smrg Xim im) 6601ab64890Smrg{ 6611ab64890Smrg XLCd lcd = im->core.lcd; 6621ab64890Smrg XlcConv conv; 6631ab64890Smrg XimDefIMValues im_values; 6641ab64890Smrg XimLocalPrivateRec* private = &im->private.local; 6651ab64890Smrg 6661ab64890Smrg _XimInitialResourceInfo(); 6671ab64890Smrg if(_XimSetIMResourceList(&im->core.im_resources, 6681ab64890Smrg &im->core.im_num_resources) == False) { 6691ab64890Smrg goto Open_Error; 6701ab64890Smrg } 6711ab64890Smrg if(_XimSetICResourceList(&im->core.ic_resources, 6721ab64890Smrg &im->core.ic_num_resources) == False) { 6731ab64890Smrg goto Open_Error; 6741ab64890Smrg } 6751ab64890Smrg 6761ab64890Smrg _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); 6771ab64890Smrg 6781ab64890Smrg _XimGetCurrentIMValues(im, &im_values); 6791ab64890Smrg if(_XimSetLocalIMDefaults(im, (XPointer)&im_values, 6801ab64890Smrg im->core.im_resources, im->core.im_num_resources) == False) { 6811ab64890Smrg goto Open_Error; 6821ab64890Smrg } 6831ab64890Smrg _XimSetCurrentIMValues(im, &im_values); 6841ab64890Smrg 6851ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte))) 6861ab64890Smrg goto Open_Error; 6871ab64890Smrg private->ctom_conv = conv; 6881ab64890Smrg 6891ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar))) 6901ab64890Smrg goto Open_Error; 6911ab64890Smrg private->ctow_conv = conv; 6921ab64890Smrg 6931ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNUtf8String))) 6941ab64890Smrg goto Open_Error; 6951ab64890Smrg private->ctoutf8_conv = conv; 6961ab64890Smrg 6971ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) 6981ab64890Smrg goto Open_Error; 6991ab64890Smrg private->cstomb_conv = conv; 7001ab64890Smrg 7011ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) 7021ab64890Smrg goto Open_Error; 7031ab64890Smrg private->cstowc_conv = conv; 7041ab64890Smrg 7051ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) 7061ab64890Smrg goto Open_Error; 7071ab64890Smrg private->cstoutf8_conv = conv; 7081ab64890Smrg 7091ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) 7101ab64890Smrg goto Open_Error; 7111ab64890Smrg private->ucstoc_conv = conv; 7121ab64890Smrg 7131ab64890Smrg if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) 7141ab64890Smrg goto Open_Error; 7151ab64890Smrg private->ucstoutf8_conv = conv; 7161ab64890Smrg 7171ab64890Smrg private->base.treeused = 1; 7181ab64890Smrg private->base.mbused = 1; 7191ab64890Smrg private->base.wcused = 1; 7201ab64890Smrg private->base.utf8used = 1; 7211ab64890Smrg 7221ab64890Smrg _XimCreateDefaultTree(im); 7231ab64890Smrg 7241ab64890Smrg im->methods = &Xim_im_local_methods; 7251ab64890Smrg private->current_ic = (XIC)NULL; 7261ab64890Smrg 7271ab64890Smrg return(True); 7281ab64890Smrg 7291ab64890SmrgOpen_Error : 7301ab64890Smrg _XimLocalIMFree(im); 7311ab64890Smrg return(False); 7321ab64890Smrg} 733