Home | History | Annotate | Line # | Download | only in ximcp
      1 /******************************************************************
      2 
      3           Copyright 1992, 1993, 1994 by FUJITSU LIMITED
      4           Copyright 1993 by Digital Equipment Corporation
      5 
      6 Permission to use, copy, modify, distribute, and sell this software
      7 and its documentation for any purpose is hereby granted without fee,
      8 provided that the above copyright notice appear in all copies and that
      9 both that copyright notice and this permission notice appear in
     10 supporting documentation, and that the name of FUJITSU LIMITED and
     11 Digital Equipment Corporation not be used in advertising or publicity
     12 pertaining to distribution of the software without specific, written
     13 prior permission.  FUJITSU LIMITED and Digital Equipment Corporation
     14 makes no representations about the suitability of this software for
     15 any purpose.  It is provided "as is" without express or implied
     16 warranty.
     17 
     18 FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL
     19 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
     20 WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     21 FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
     22 ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     23 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
     24 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
     26 THIS SOFTWARE.
     27 
     28   Author:    Takashi Fujiwara     FUJITSU LIMITED
     29                                	  fujiwara (at) a80.tech.yk.fujitsu.co.jp
     30   Modifier:  Franky Ling          Digital Equipment Corporation
     31 	                          frankyling (at) hgrd01.enet.dec.com
     32 
     33 ******************************************************************/
     34 
     35 #ifdef HAVE_CONFIG_H
     36 #include <config.h>
     37 #endif
     38 #include <stdio.h>
     39 
     40 #include <X11/Xmd.h>
     41 #include <X11/Xatom.h>
     42 #include <X11/Xos.h>
     43 #include "Xlibint.h"
     44 #include "Xlcint.h"
     45 #include "XlcPublic.h"
     46 #include "XlcPubI.h"
     47 #include "Ximint.h"
     48 #include <ctype.h>
     49 #include <assert.h>
     50 
     51 #ifdef COMPOSECACHE
     52 #  include <sys/types.h>
     53 #  include <sys/stat.h>
     54 #  include <sys/mman.h>
     55 #  include <langinfo.h>
     56 #endif
     57 
     58 
     59 #ifdef COMPOSECACHE
     60 
     61 /* include trailing '/' for cache directory, file prefix otherwise */
     62 #define XIM_GLOBAL_CACHE_DIR "/var/cache/libx11/compose/"
     63 #define XIM_HOME_CACHE_DIR   "/.compose-cache/"
     64 #define XIM_CACHE_MAGIC      ('X' | 'i'<<8 | 'm'<<16 | 'C'<<24)
     65 #define XIM_CACHE_VERSION    4
     66 #define XIM_CACHE_TREE_ALIGNMENT 4
     67 
     68 #define XIM_HASH_PRIME_1 13
     69 #define XIM_HASH_PRIME_2 1234096939
     70 
     71 typedef INT32 DTStructIndex;
     72 struct _XimCacheStruct {
     73     INT32           id;
     74     INT32           version;
     75     DTStructIndex   tree;
     76     DTStructIndex   mb;
     77     DTStructIndex   wc;
     78     DTStructIndex   utf8;
     79     DTStructIndex   size;
     80     DTIndex         top;
     81     DTIndex         treeused;
     82     DTCharIndex     mbused;
     83     DTCharIndex     wcused;
     84     DTCharIndex     utf8used;
     85     char            fname[];
     86     /* char encoding[] */
     87 };
     88 
     89 static struct  _XimCacheStruct* _XimCache_mmap = NULL;
     90 static DefTreeBase _XimCachedDefaultTreeBase;
     91 static int     _XimCachedDefaultTreeRefcount = 0;
     92 
     93 #endif
     94 
     95 
     96 Bool
     97 _XimCheckIfLocalProcessing(Xim im)
     98 {
     99     FILE        *fp;
    100     char        *name;
    101 
    102     if(strcmp(im->core.im_name, "") == 0) {
    103 	name = _XlcFileName(im->core.lcd, COMPOSE_FILE);
    104 	if (name != (char *)NULL) {
    105 	    fp = _XFopenFile (name, "r");
    106 	    Xfree(name);
    107 	    if (fp != (FILE *)NULL) {
    108 		fclose(fp);
    109 		return(True);
    110 	    }
    111 	}
    112 	return(False);
    113     } else if(strcmp(im->core.im_name, "local") == 0 ||
    114 	      strcmp(im->core.im_name, "none" ) == 0 ) {
    115 	return(True);
    116     }
    117     return(False);
    118 }
    119 
    120 static void
    121 XimFreeDefaultTree(
    122     DefTreeBase *b)
    123 {
    124     if (!b) return;
    125     if (b->tree == NULL) return;
    126 #ifdef COMPOSECACHE
    127     if (b->tree == _XimCachedDefaultTreeBase.tree) {
    128         _XimCachedDefaultTreeRefcount--;
    129         /* No deleting, it's a cache after all. */
    130         return;
    131     }
    132 #endif
    133     Xfree (b->tree);
    134     b->tree = NULL;
    135     Xfree (b->mb);
    136     b->mb   = NULL;
    137     Xfree (b->wc);
    138     b->wc   = NULL;
    139     Xfree (b->utf8);
    140     b->utf8 = NULL;
    141 
    142     b->treeused = b->treesize = 0;
    143     b->mbused   = b->mbsize   = 0;
    144     b->wcused   = b->wcsize   = 0;
    145     b->utf8used = b->utf8size = 0;
    146 }
    147 
    148 void
    149 _XimLocalIMFree(
    150     Xim		im)
    151 {
    152     XimFreeDefaultTree(&im->private.local.base);
    153     im->private.local.top = 0;
    154 
    155     Xfree(im->core.im_resources);
    156     im->core.im_resources = NULL;
    157 
    158     Xfree(im->core.ic_resources);
    159     im->core.ic_resources = NULL;
    160 
    161     Xfree(im->core.im_values_list);
    162     im->core.im_values_list = NULL;
    163 
    164     Xfree(im->core.ic_values_list);
    165     im->core.ic_values_list = NULL;
    166 
    167     Xfree(im->core.styles);
    168     im->core.styles = NULL;
    169 
    170     Xfree(im->core.res_name);
    171     im->core.res_name = NULL;
    172 
    173     Xfree(im->core.res_class);
    174     im->core.res_class = NULL;
    175 
    176     Xfree(im->core.im_name);
    177     im->core.im_name = NULL;
    178 
    179     if (im->private.local.ctom_conv) {
    180 	_XlcCloseConverter(im->private.local.ctom_conv);
    181         im->private.local.ctom_conv = NULL;
    182     }
    183     if (im->private.local.ctow_conv) {
    184 	_XlcCloseConverter(im->private.local.ctow_conv);
    185 	im->private.local.ctow_conv = NULL;
    186     }
    187     if (im->private.local.ctoutf8_conv) {
    188 	_XlcCloseConverter(im->private.local.ctoutf8_conv);
    189 	im->private.local.ctoutf8_conv = NULL;
    190     }
    191     if (im->private.local.cstomb_conv) {
    192 	_XlcCloseConverter(im->private.local.cstomb_conv);
    193         im->private.local.cstomb_conv = NULL;
    194     }
    195     if (im->private.local.cstowc_conv) {
    196 	_XlcCloseConverter(im->private.local.cstowc_conv);
    197 	im->private.local.cstowc_conv = NULL;
    198     }
    199     if (im->private.local.cstoutf8_conv) {
    200 	_XlcCloseConverter(im->private.local.cstoutf8_conv);
    201 	im->private.local.cstoutf8_conv = NULL;
    202     }
    203     if (im->private.local.ucstoc_conv) {
    204 	_XlcCloseConverter(im->private.local.ucstoc_conv);
    205 	im->private.local.ucstoc_conv = NULL;
    206     }
    207     if (im->private.local.ucstoutf8_conv) {
    208 	_XlcCloseConverter(im->private.local.ucstoutf8_conv);
    209 	im->private.local.ucstoutf8_conv = NULL;
    210     }
    211     return;
    212 }
    213 
    214 static Status
    215 _XimLocalCloseIM(
    216     XIM		xim)
    217 {
    218     Xim		im = (Xim)xim;
    219     XIC		ic;
    220     XIC		next;
    221 
    222     ic = im->core.ic_chain;
    223     im->core.ic_chain = NULL;
    224     while (ic) {
    225 	(*ic->methods->destroy) (ic);
    226 	next = ic->core.next;
    227 	Xfree (ic);
    228 	ic = next;
    229     }
    230     _XimLocalIMFree(im);
    231     _XimDestroyIMStructureList(im);
    232     return(True);
    233 }
    234 
    235 char *
    236 _XimLocalGetIMValues(
    237     XIM			 xim,
    238     XIMArg		*values)
    239 {
    240     Xim			 im = (Xim)xim;
    241     XimDefIMValues	 im_values;
    242 
    243     _XimGetCurrentIMValues(im, &im_values);
    244     return(_XimGetIMValueData(im, (XPointer)&im_values, values,
    245 			im->core.im_resources, im->core.im_num_resources));
    246 }
    247 
    248 char *
    249 _XimLocalSetIMValues(
    250     XIM			 xim,
    251     XIMArg		*values)
    252 {
    253     Xim			 im = (Xim)xim;
    254     XimDefIMValues	 im_values;
    255     char		*name = (char *)NULL;
    256 
    257     _XimGetCurrentIMValues(im, &im_values);
    258     name = _XimSetIMValueData(im, (XPointer)&im_values, values,
    259 		im->core.im_resources, im->core.im_num_resources);
    260     _XimSetCurrentIMValues(im, &im_values);
    261     return(name);
    262 }
    263 
    264 
    265 #ifdef COMPOSECACHE
    266 
    267 static Bool
    268 _XimReadCachedDefaultTree(
    269     int          fd_cache,
    270     const char  *name,
    271     const char  *encoding,
    272     DTStructIndex size)
    273 {
    274     struct _XimCacheStruct* m;
    275     int namelen = strlen (name) + 1;
    276     int encodinglen = strlen (encoding) + 1;
    277 
    278     m = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd_cache, 0);
    279     if (m == NULL || m == MAP_FAILED)
    280         return False;
    281     assert (m->id == XIM_CACHE_MAGIC);
    282     assert (m->version == XIM_CACHE_VERSION);
    283     if (size != m->size ||
    284 	size < sizeof (struct _XimCacheStruct) + namelen + encodinglen) {
    285 	fprintf (stderr, "Ignoring broken XimCache %s [%s]\n", name, encoding);
    286         munmap (m, size);
    287         return False;
    288     }
    289     if (strncmp (name, m->fname, namelen) != 0) {
    290 	/* m->fname may *not* be terminated - but who cares here */
    291 	fprintf (stderr, "Filename hash clash - expected %s, got %s\n",
    292 		 name, m->fname);
    293         munmap (m, size);
    294         return False;
    295     }
    296     if (strncmp (encoding, m->fname + namelen, encodinglen) != 0) {
    297 	/* m->fname+namelen may *not* be terminated - but who cares here */
    298 	fprintf (stderr, "Enoding hash clash - expected %s, got %s\n",
    299 		 encoding, m->fname + namelen);
    300         munmap (m, size);
    301         return False;
    302     }
    303     _XimCache_mmap    = m;
    304     _XimCachedDefaultTreeBase.tree = (DefTree *) (((char *) m) + m->tree);
    305     _XimCachedDefaultTreeBase.mb   =             (((char *) m) + m->mb);
    306     _XimCachedDefaultTreeBase.wc   = (wchar_t *) (((char *) m) + m->wc);
    307     _XimCachedDefaultTreeBase.utf8 =             (((char *) m) + m->utf8);
    308     _XimCachedDefaultTreeBase.treeused = m->treeused;
    309     _XimCachedDefaultTreeBase.mbused   = m->mbused;
    310     _XimCachedDefaultTreeBase.wcused   = m->wcused;
    311     _XimCachedDefaultTreeBase.utf8used = m->utf8used;
    312     /* treesize etc. is ignored because only used during parsing */
    313     _XimCachedDefaultTreeRefcount = 0;
    314 /* fprintf (stderr, "read cached tree at %p: %s\n", (void *) m, name); */
    315     return True;
    316 }
    317 
    318 static unsigned int strToHash (
    319     const char *name)
    320 {
    321     unsigned int hash = 0;
    322     while (*name)
    323 	hash = hash * XIM_HASH_PRIME_1 + *(unsigned const char *)name++;
    324     return hash % XIM_HASH_PRIME_2;
    325 }
    326 
    327 
    328 /* Returns read-only fd of cache file, -1 if none.
    329  * Sets *res to cache filename if safe. Sets *size to file size of cache. */
    330 static int _XimCachedFileName (
    331     const char *dir, const char *name,
    332     const char *intname, const char *encoding,
    333     uid_t uid, int isglobal, char **res, off_t *size)
    334 {
    335     struct stat st_name, st;
    336     int    fd;
    337     unsigned int len, hash, hash2;
    338     struct _XimCacheStruct *m;
    339     /* There are some races here with 'dir', but we are either in our own home
    340      * or the global cache dir, and not inside some public writable dir */
    341 /* fprintf (stderr, "XimCachedFileName for dir %s name %s intname %s encoding %s uid %d\n", dir, name, intname, encoding, uid); */
    342     if (stat (name, &st_name) == -1 || ! S_ISREG (st_name.st_mode)
    343        || stat (dir, &st) == -1 || ! S_ISDIR (st.st_mode) || st.st_uid != uid
    344        || (st.st_mode & 0022) != 0000) {
    345        *res = NULL;
    346        return -1;
    347     }
    348     len   = strlen (dir);
    349     hash  = strToHash (intname);
    350     hash2 = strToHash (encoding);
    351     *res  = Xmalloc (len + 1 + 27 + 1);  /* Max VERSION 9999 */
    352 
    353     if (len == 0 || dir [len-1] != '/')
    354        sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(),
    355 		XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2);
    356     else
    357        sprintf (*res, "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(),
    358 		XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2);
    359 
    360 /* fprintf (stderr, "-> %s\n", *res); */
    361     if ( (fd = _XOpenFile (*res, O_RDONLY)) == -1)
    362        return -1;
    363 
    364     if (fstat (fd, &st) == -1) {
    365        Xfree (*res);
    366        *res = NULL;
    367        close (fd);
    368        return -1;
    369     }
    370     *size = st.st_size;
    371 
    372     if (! S_ISREG (st.st_mode) || st.st_uid != uid
    373        || (st.st_mode & 0022) != 0000 || st.st_mtime <= st_name.st_mtime
    374        || (st.st_mtime < time (NULL) - 24*60*60 && ! isglobal)) {
    375 
    376        close (fd);
    377        if (unlink (*res) != 0) {
    378            Xfree (*res);
    379            *res = NULL;                /* cache is not safe */
    380        }
    381        return -1;
    382     }
    383 
    384     m = mmap (NULL, sizeof (struct _XimCacheStruct), PROT_READ, MAP_PRIVATE,
    385 	      fd, 0);
    386     if (m == NULL || m == MAP_FAILED) {
    387 	close (fd);
    388 	Xfree (*res);
    389 	*res = NULL;
    390         return -1;
    391     }
    392     if (*size < sizeof (struct _XimCacheStruct) || m->id != XIM_CACHE_MAGIC) {
    393 	munmap (m, sizeof (struct _XimCacheStruct));
    394 	close (fd);
    395 	fprintf (stderr, "Ignoring broken XimCache %s\n", *res);
    396 	Xfree (*res);
    397 	*res = NULL;
    398         return -1;
    399     }
    400     if (m->version != XIM_CACHE_VERSION) {
    401 	munmap (m, sizeof (struct _XimCacheStruct));
    402 	close (fd);
    403 	if (unlink (*res) != 0) {
    404 	    Xfree (*res);
    405 	    *res = NULL;                /* cache is not safe */
    406 	}
    407 	return -1;
    408     }
    409     munmap (m, sizeof (struct _XimCacheStruct));
    410 
    411     return fd;
    412 }
    413 
    414 
    415 static Bool _XimLoadCache (
    416     int         fd,
    417     const char *name,
    418     const char *encoding,
    419     off_t       size,
    420     Xim         im)
    421 {
    422     if (_XimCache_mmap ||
    423        _XimReadCachedDefaultTree (fd, name, encoding, size)) {
    424        _XimCachedDefaultTreeRefcount++;
    425        memcpy (&im->private.local.base, &_XimCachedDefaultTreeBase,
    426 	       sizeof (_XimCachedDefaultTreeBase));
    427        im->private.local.top = _XimCache_mmap->top;
    428        return True;
    429     }
    430 
    431     return False;
    432 }
    433 
    434 
    435 static void
    436 _XimWriteCachedDefaultTree(
    437     const char *name,
    438     const char *encoding,
    439     const char *cachename,
    440     Xim                im)
    441 {
    442     int   fd;
    443     FILE *fp;
    444     struct _XimCacheStruct *m;
    445     int   msize = (sizeof(struct _XimCacheStruct)
    446 		   + strlen(name) + strlen(encoding) + 2
    447 		   + XIM_CACHE_TREE_ALIGNMENT-1) & -XIM_CACHE_TREE_ALIGNMENT;
    448     DefTreeBase *b = &im->private.local.base;
    449 
    450     if (! b->tree && ! (b->tree = Xcalloc (1, sizeof(DefTree))) )
    451 	return;
    452     if (! b->mb   && ! (b->mb   = Xmalloc (1)) )
    453 	return;
    454     if (! b->wc   && ! (b->wc   = Xmalloc (sizeof(wchar_t))) )
    455 	return;
    456     if (! b->utf8 && ! (b->utf8 = Xmalloc (1)) )
    457 	return;
    458 
    459     /* First entry is always unused */
    460     b->mb[0]   = 0;
    461     b->wc[0]   = 0;
    462     b->utf8[0] = 0;
    463 
    464     m = Xcalloc (1, msize);
    465     m->id       = XIM_CACHE_MAGIC;
    466     m->version  = XIM_CACHE_VERSION;
    467     m->top      = im->private.local.top;
    468     m->treeused = b->treeused;
    469     m->mbused   = b->mbused;
    470     m->wcused   = b->wcused;
    471     m->utf8used = b->utf8used;
    472     /* Tree first, then wide chars, then the rest due to alignment */
    473     m->tree     = msize;
    474     m->wc       = msize   + sizeof (DefTree) * m->treeused;
    475     m->mb       = m->wc   + sizeof (wchar_t) * m->wcused;
    476     m->utf8     = m->mb   +                    m->mbused;
    477     m->size     = m->utf8 +                    m->utf8used;
    478     strcpy (m->fname, name);
    479     strcpy (m->fname+strlen(name)+1, encoding);
    480 
    481     /* This STILL might be racy on NFS */
    482     if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL,
    483 			       0600)) < 0) {
    484        Xfree(m);
    485        return;
    486     }
    487     if (! (fp = fdopen (fd, "wb")) ) {
    488        close (fd);
    489        Xfree(m);
    490        return;
    491     }
    492     fwrite (m, msize, 1, fp);
    493     fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp);
    494     fwrite (im->private.local.base.wc,   sizeof(wchar_t), m->wcused,   fp);
    495     fwrite (im->private.local.base.mb,   1,               m->mbused,   fp);
    496     fwrite (im->private.local.base.utf8, 1,               m->utf8used, fp);
    497     if (fclose (fp) != 0)
    498 	unlink (cachename);
    499     _XimCache_mmap = m;
    500     memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base,
    501 	    sizeof (_XimCachedDefaultTreeBase));
    502 /* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */
    503 }
    504 
    505 #endif
    506 
    507 
    508 static void
    509 _XimCreateDefaultTree(
    510     Xim		im)
    511 {
    512     FILE *fp = NULL;
    513     char *name, *tmpname = NULL, *intname;
    514     char *cachename = NULL;
    515     /* Should use getpwent() instead of $HOME (cross-platform?) */
    516     char *home = getenv("HOME");
    517     char *cachedir = NULL;
    518     char *tmpcachedir = NULL;
    519     int   hl = home ? strlen (home) : 0;
    520 #ifdef COMPOSECACHE
    521     const char *encoding = nl_langinfo (CODESET);
    522     uid_t euid = geteuid ();
    523     gid_t egid = getegid ();
    524     int   cachefd = -1;
    525     off_t size;
    526 #endif
    527 
    528     name = getenv("XCOMPOSEFILE");
    529     if (name == (char *) NULL) {
    530     	if (home != (char *) NULL) {
    531             tmpname = name = Xmalloc(hl + 10 + 1);
    532             if (name != (char *) NULL) {
    533 		int fd;
    534             	strcpy(name, home);
    535             	strcpy(name + hl, "/.XCompose");
    536 		if ( (fd = _XOpenFile (name, O_RDONLY)) < 0) {
    537 		    Xfree (name);
    538 		    name = tmpname = NULL;
    539 		} else
    540 		    close (fd);
    541             }
    542         }
    543     }
    544 
    545     if (name == (char *) NULL) {
    546         tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE);
    547     }
    548     intname = name;
    549 
    550 #ifdef COMPOSECACHE
    551     if (getuid () == euid && getgid () == egid && euid != 0) {
    552 	char *c;
    553 	/* Usage: XCOMPOSECACHE=<cachedir>[=<filename>]
    554 	 * cachedir: directory of cache files
    555 	 * filename: internally used name for cache file */
    556         cachedir = getenv("XCOMPOSECACHE");
    557 	if (cachedir && (c = strchr (cachedir, '='))) {
    558 	    tmpcachedir = strdup (cachedir);
    559 	    intname = tmpcachedir + (c-cachedir) + 1;
    560 	    tmpcachedir[c-cachedir] = '\0';
    561 	    cachedir = tmpcachedir;
    562 	}
    563     }
    564 
    565     if (! cachedir) {
    566 	cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR, name, intname,
    567 				      encoding, 0, 1, &cachename, &size);
    568 	if (cachefd != -1) {
    569 	    if (_XimLoadCache (cachefd, intname, encoding, size, im)) {
    570 	        Xfree (tmpcachedir);
    571 		Xfree (tmpname);
    572 		Xfree (cachename);
    573 		close (cachefd);
    574 		return;
    575 	    }
    576 	    close (cachefd);
    577 	}
    578 	Xfree (cachename);
    579 	cachename = NULL;
    580     }
    581 
    582     if (getuid () == euid && getgid () == egid && euid != 0 && home) {
    583 
    584 	if (! cachedir) {
    585 	    tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1);
    586 	    strcpy (cachedir, home);
    587 	    strcat (cachedir, XIM_HOME_CACHE_DIR);
    588 	}
    589 	cachefd = _XimCachedFileName (cachedir, name, intname, encoding,
    590 				      euid, 0, &cachename, &size);
    591 	if (cachefd != -1) {
    592 	    if (_XimLoadCache (cachefd, intname, encoding, size, im)) {
    593 	        Xfree (tmpcachedir);
    594 		Xfree (tmpname);
    595 		Xfree (cachename);
    596 		close (cachefd);
    597 		return;
    598 	    }
    599 	    close (cachefd);
    600 	}
    601     }
    602 #endif
    603 
    604     if (! (fp = _XFopenFile (name, "r"))) {
    605 	Xfree (tmpcachedir);
    606 	Xfree (tmpname);
    607 	Xfree (cachename);
    608         return;
    609     }
    610     _XimParseStringFile(fp, im);
    611     fclose(fp);
    612 
    613 #ifdef COMPOSECACHE
    614     if (cachename) {
    615 	assert (euid != 0);
    616 	_XimWriteCachedDefaultTree (intname, encoding, cachename, im);
    617     }
    618 #endif
    619 
    620     Xfree (tmpcachedir);
    621     Xfree (tmpname);
    622     Xfree (cachename);
    623 }
    624 
    625 static XIMMethodsRec      Xim_im_local_methods = {
    626     _XimLocalCloseIM,           /* close */
    627     _XimLocalSetIMValues,       /* set_values */
    628     _XimLocalGetIMValues,       /* get_values */
    629     _XimLocalCreateIC,          /* create_ic */
    630     _XimLcctstombs,		/* ctstombs */
    631     _XimLcctstowcs,		/* ctstowcs */
    632     _XimLcctstoutf8		/* ctstoutf8 */
    633 };
    634 
    635 Bool
    636 _XimLocalOpenIM(
    637     Xim			 im)
    638 {
    639     XLCd		 lcd = im->core.lcd;
    640     XlcConv		 conv;
    641     XimDefIMValues	 im_values;
    642     XimLocalPrivateRec*  private = &im->private.local;
    643 
    644     _XimInitialResourceInfo();
    645     if(_XimSetIMResourceList(&im->core.im_resources,
    646 		 		&im->core.im_num_resources) == False) {
    647 	goto Open_Error;
    648     }
    649     if(_XimSetICResourceList(&im->core.ic_resources,
    650 				&im->core.ic_num_resources) == False) {
    651 	goto Open_Error;
    652     }
    653 
    654     _XimSetIMMode(im->core.im_resources, im->core.im_num_resources);
    655 
    656     _XimGetCurrentIMValues(im, &im_values);
    657     if(_XimSetLocalIMDefaults(im, (XPointer)&im_values,
    658 		im->core.im_resources, im->core.im_num_resources) == False) {
    659 	goto Open_Error;
    660     }
    661     _XimSetCurrentIMValues(im, &im_values);
    662 
    663     if (!(conv = _XlcOpenConverter(lcd,	XlcNCompoundText, lcd, XlcNMultiByte)))
    664 	goto Open_Error;
    665     private->ctom_conv = conv;
    666 
    667     if (!(conv = _XlcOpenConverter(lcd,	XlcNCompoundText, lcd, XlcNWideChar)))
    668 	goto Open_Error;
    669     private->ctow_conv = conv;
    670 
    671     if (!(conv = _XlcOpenConverter(lcd,	XlcNCompoundText, lcd, XlcNUtf8String)))
    672 	goto Open_Error;
    673     private->ctoutf8_conv = conv;
    674 
    675     if (!(conv = _XlcOpenConverter(lcd,	XlcNCharSet, lcd, XlcNMultiByte)))
    676 	goto Open_Error;
    677     private->cstomb_conv = conv;
    678 
    679     if (!(conv = _XlcOpenConverter(lcd,	XlcNCharSet, lcd, XlcNWideChar)))
    680 	goto Open_Error;
    681     private->cstowc_conv = conv;
    682 
    683     if (!(conv = _XlcOpenConverter(lcd,	XlcNCharSet, lcd, XlcNUtf8String)))
    684 	goto Open_Error;
    685     private->cstoutf8_conv = conv;
    686 
    687     if (!(conv = _XlcOpenConverter(lcd,	XlcNUcsChar, lcd, XlcNChar)))
    688 	goto Open_Error;
    689     private->ucstoc_conv = conv;
    690 
    691     if (!(conv = _XlcOpenConverter(lcd,	XlcNUcsChar, lcd, XlcNUtf8String)))
    692 	goto Open_Error;
    693     private->ucstoutf8_conv = conv;
    694 
    695     private->base.treeused = 1;
    696     private->base.mbused   = 1;
    697     private->base.wcused   = 1;
    698     private->base.utf8used = 1;
    699 
    700     _XimCreateDefaultTree(im);
    701 
    702     im->methods = &Xim_im_local_methods;
    703     private->current_ic = (XIC)NULL;
    704 
    705     return(True);
    706 
    707 Open_Error :
    708     _XimLocalIMFree(im);
    709     return(False);
    710 }
    711