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