733 lines
20 KiB
C
733 lines
20 KiB
C
|
/* $Xorg: imLcIm.c,v 1.3 2000/08/17 19:45:14 cpqbld Exp $ */
|
||
|
/******************************************************************
|
||
|
|
||
|
Copyright 1992, 1993, 1994 by FUJITSU LIMITED
|
||
|
Copyright 1993 by Digital Equipment Corporation
|
||
|
|
||
|
Permission to use, copy, modify, distribute, and sell this software
|
||
|
and its documentation for any purpose is hereby granted without fee,
|
||
|
provided that the above copyright notice appear in all copies and that
|
||
|
both that copyright notice and this permission notice appear in
|
||
|
supporting documentation, and that the name of FUJITSU LIMITED and
|
||
|
Digital Equipment Corporation not be used in advertising or publicity
|
||
|
pertaining to distribution of the software without specific, written
|
||
|
prior permission. FUJITSU LIMITED and Digital Equipment Corporation
|
||
|
makes no representations about the suitability of this software for
|
||
|
any purpose. It is provided "as is" without express or implied
|
||
|
warranty.
|
||
|
|
||
|
FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL
|
||
|
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
|
||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
||
|
FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
|
||
|
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||
|
THIS SOFTWARE.
|
||
|
|
||
|
Author: Takashi Fujiwara FUJITSU LIMITED
|
||
|
fujiwara@a80.tech.yk.fujitsu.co.jp
|
||
|
Modifier: Franky Ling Digital Equipment Corporation
|
||
|
frankyling@hgrd01.enet.dec.com
|
||
|
|
||
|
******************************************************************/
|
||
|
/* $XFree86: xc/lib/X11/imLcIm.c,v 1.12 2003/09/06 14:06:32 pascal Exp $ */
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include <config.h>
|
||
|
#endif
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <X11/Xmd.h>
|
||
|
#include <X11/Xatom.h>
|
||
|
#include <X11/Xos.h>
|
||
|
#include "Xlibint.h"
|
||
|
#include "Xlcint.h"
|
||
|
#include "XlcPublic.h"
|
||
|
#include "XlcPubI.h"
|
||
|
#include "Ximint.h"
|
||
|
#include <ctype.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#ifdef COMPOSECACHE
|
||
|
# include <sys/types.h>
|
||
|
# include <sys/stat.h>
|
||
|
# include <sys/mman.h>
|
||
|
# include <langinfo.h>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#ifdef COMPOSECACHE
|
||
|
|
||
|
/* include trailing '/' for cache directory, file prefix otherwise */
|
||
|
#define XIM_GLOBAL_CACHE_DIR "/var/cache/libx11/compose/"
|
||
|
#define XIM_HOME_CACHE_DIR "/.compose-cache/"
|
||
|
#define XIM_CACHE_MAGIC ('X' | 'i'<<8 | 'm'<<16 | 'C'<<24)
|
||
|
#define XIM_CACHE_VERSION 4
|
||
|
#define XIM_CACHE_TREE_ALIGNMENT 4
|
||
|
|
||
|
#define XIM_HASH_PRIME_1 13
|
||
|
#define XIM_HASH_PRIME_2 1234096939
|
||
|
|
||
|
typedef INT32 DTStructIndex;
|
||
|
struct _XimCacheStruct {
|
||
|
INT32 id;
|
||
|
INT32 version;
|
||
|
DTStructIndex tree;
|
||
|
DTStructIndex mb;
|
||
|
DTStructIndex wc;
|
||
|
DTStructIndex utf8;
|
||
|
DTStructIndex size;
|
||
|
DTIndex top;
|
||
|
DTIndex treeused;
|
||
|
DTCharIndex mbused;
|
||
|
DTCharIndex wcused;
|
||
|
DTCharIndex utf8used;
|
||
|
char fname[1];
|
||
|
/* char encoding[1] */
|
||
|
};
|
||
|
|
||
|
Private struct _XimCacheStruct* _XimCache_mmap = NULL;
|
||
|
Private DefTreeBase _XimCachedDefaultTreeBase;
|
||
|
Private int _XimCachedDefaultTreeRefcount = 0;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
Public Bool
|
||
|
_XimCheckIfLocalProcessing(im)
|
||
|
Xim im;
|
||
|
{
|
||
|
FILE *fp;
|
||
|
char *name;
|
||
|
|
||
|
if(strcmp(im->core.im_name, "") == 0) {
|
||
|
name = _XlcFileName(im->core.lcd, COMPOSE_FILE);
|
||
|
if (name != (char *)NULL) {
|
||
|
fp = _XFopenFile (name, "r");
|
||
|
Xfree(name);
|
||
|
if (fp != (FILE *)NULL) {
|
||
|
fclose(fp);
|
||
|
return(True);
|
||
|
}
|
||
|
}
|
||
|
return(False);
|
||
|
} else if(strcmp(im->core.im_name, "local") == 0 ||
|
||
|
strcmp(im->core.im_name, "none" ) == 0 ) {
|
||
|
return(True);
|
||
|
}
|
||
|
return(False);
|
||
|
}
|
||
|
|
||
|
Private void
|
||
|
XimFreeDefaultTree(
|
||
|
DefTreeBase *b)
|
||
|
{
|
||
|
if (!b) return;
|
||
|
if (b->tree == NULL) return;
|
||
|
#ifdef COMPOSECACHE
|
||
|
if (b->tree == _XimCachedDefaultTreeBase.tree) {
|
||
|
_XimCachedDefaultTreeRefcount--;
|
||
|
/* No deleting, it's a cache after all. */
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
Xfree (b->tree);
|
||
|
if (b->mb) Xfree (b->mb);
|
||
|
if (b->wc) Xfree (b->wc);
|
||
|
if (b->utf8) Xfree (b->utf8);
|
||
|
b->tree = NULL;
|
||
|
b->mb = NULL;
|
||
|
b->wc = NULL;
|
||
|
b->utf8 = NULL;
|
||
|
b->treeused = b->treesize = 0;
|
||
|
b->mbused = b->mbsize = 0;
|
||
|
b->wcused = b->wcsize = 0;
|
||
|
b->utf8used = b->utf8size = 0;
|
||
|
}
|
||
|
|
||
|
Public void
|
||
|
_XimLocalIMFree(
|
||
|
Xim im)
|
||
|
{
|
||
|
XimFreeDefaultTree(&im->private.local.base);
|
||
|
im->private.local.top = 0;
|
||
|
|
||
|
if(im->core.im_resources) {
|
||
|
Xfree(im->core.im_resources);
|
||
|
im->core.im_resources = NULL;
|
||
|
}
|
||
|
if(im->core.ic_resources) {
|
||
|
Xfree(im->core.ic_resources);
|
||
|
im->core.ic_resources = NULL;
|
||
|
}
|
||
|
if(im->core.im_values_list) {
|
||
|
Xfree(im->core.im_values_list);
|
||
|
im->core.im_values_list = NULL;
|
||
|
}
|
||
|
if(im->core.ic_values_list) {
|
||
|
Xfree(im->core.ic_values_list);
|
||
|
im->core.ic_values_list = NULL;
|
||
|
}
|
||
|
if(im->core.styles) {
|
||
|
Xfree(im->core.styles);
|
||
|
im->core.styles = NULL;
|
||
|
}
|
||
|
if(im->core.res_name) {
|
||
|
Xfree(im->core.res_name);
|
||
|
im->core.res_name = NULL;
|
||
|
}
|
||
|
if(im->core.res_class) {
|
||
|
Xfree(im->core.res_class);
|
||
|
im->core.res_class = NULL;
|
||
|
}
|
||
|
if(im->core.im_name) {
|
||
|
Xfree(im->core.im_name);
|
||
|
im->core.im_name = NULL;
|
||
|
}
|
||
|
if (im->private.local.ctom_conv) {
|
||
|
_XlcCloseConverter(im->private.local.ctom_conv);
|
||
|
im->private.local.ctom_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.ctow_conv) {
|
||
|
_XlcCloseConverter(im->private.local.ctow_conv);
|
||
|
im->private.local.ctow_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.ctoutf8_conv) {
|
||
|
_XlcCloseConverter(im->private.local.ctoutf8_conv);
|
||
|
im->private.local.ctoutf8_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.cstomb_conv) {
|
||
|
_XlcCloseConverter(im->private.local.cstomb_conv);
|
||
|
im->private.local.cstomb_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.cstowc_conv) {
|
||
|
_XlcCloseConverter(im->private.local.cstowc_conv);
|
||
|
im->private.local.cstowc_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.cstoutf8_conv) {
|
||
|
_XlcCloseConverter(im->private.local.cstoutf8_conv);
|
||
|
im->private.local.cstoutf8_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.ucstoc_conv) {
|
||
|
_XlcCloseConverter(im->private.local.ucstoc_conv);
|
||
|
im->private.local.ucstoc_conv = NULL;
|
||
|
}
|
||
|
if (im->private.local.ucstoutf8_conv) {
|
||
|
_XlcCloseConverter(im->private.local.ucstoutf8_conv);
|
||
|
im->private.local.ucstoutf8_conv = NULL;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Private Status
|
||
|
_XimLocalCloseIM(
|
||
|
XIM xim)
|
||
|
{
|
||
|
Xim im = (Xim)xim;
|
||
|
XIC ic;
|
||
|
XIC next;
|
||
|
|
||
|
ic = im->core.ic_chain;
|
||
|
im->core.ic_chain = NULL;
|
||
|
while (ic) {
|
||
|
(*ic->methods->destroy) (ic);
|
||
|
next = ic->core.next;
|
||
|
Xfree ((char *) ic);
|
||
|
ic = next;
|
||
|
}
|
||
|
_XimLocalIMFree(im);
|
||
|
_XimDestroyIMStructureList(im);
|
||
|
return(True);
|
||
|
}
|
||
|
|
||
|
Public char *
|
||
|
_XimLocalGetIMValues(
|
||
|
XIM xim,
|
||
|
XIMArg *values)
|
||
|
{
|
||
|
Xim im = (Xim)xim;
|
||
|
XimDefIMValues im_values;
|
||
|
|
||
|
_XimGetCurrentIMValues(im, &im_values);
|
||
|
return(_XimGetIMValueData(im, (XPointer)&im_values, values,
|
||
|
im->core.im_resources, im->core.im_num_resources));
|
||
|
}
|
||
|
|
||
|
Public char *
|
||
|
_XimLocalSetIMValues(
|
||
|
XIM xim,
|
||
|
XIMArg *values)
|
||
|
{
|
||
|
Xim im = (Xim)xim;
|
||
|
XimDefIMValues im_values;
|
||
|
char *name = (char *)NULL;
|
||
|
|
||
|
_XimGetCurrentIMValues(im, &im_values);
|
||
|
name = _XimSetIMValueData(im, (XPointer)&im_values, values,
|
||
|
im->core.im_resources, im->core.im_num_resources);
|
||
|
_XimSetCurrentIMValues(im, &im_values);
|
||
|
return(name);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef COMPOSECACHE
|
||
|
|
||
|
Private Bool
|
||
|
_XimReadCachedDefaultTree(
|
||
|
int fd_cache,
|
||
|
const char *name,
|
||
|
const char *encoding,
|
||
|
DTStructIndex size)
|
||
|
{
|
||
|
struct _XimCacheStruct* m;
|
||
|
int namelen = strlen (name) + 1;
|
||
|
int encodinglen = strlen (encoding) + 1;
|
||
|
|
||
|
m = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd_cache, 0);
|
||
|
if (m == NULL || m == MAP_FAILED)
|
||
|
return False;
|
||
|
assert (m->id == XIM_CACHE_MAGIC);
|
||
|
assert (m->version == XIM_CACHE_VERSION);
|
||
|
if (size != m->size ||
|
||
|
size < XOffsetOf (struct _XimCacheStruct, fname) + namelen + encodinglen) {
|
||
|
fprintf (stderr, "Ignoring broken XimCache %s [%s]\n", name, encoding);
|
||
|
munmap (m, size);
|
||
|
return False;
|
||
|
}
|
||
|
if (strncmp (name, m->fname, namelen) != 0) {
|
||
|
/* m->fname may *not* be terminated - but who cares here */
|
||
|
fprintf (stderr, "Filename hash clash - expected %s, got %s\n",
|
||
|
name, m->fname);
|
||
|
munmap (m, size);
|
||
|
return False;
|
||
|
}
|
||
|
if (strncmp (encoding, m->fname + namelen, encodinglen) != 0) {
|
||
|
/* m->fname+namelen may *not* be terminated - but who cares here */
|
||
|
fprintf (stderr, "Enoding hash clash - expected %s, got %s\n",
|
||
|
encoding, m->fname + namelen);
|
||
|
munmap (m, size);
|
||
|
return False;
|
||
|
}
|
||
|
_XimCache_mmap = m;
|
||
|
_XimCachedDefaultTreeBase.tree = (DefTree *) (((char *) m) + m->tree);
|
||
|
_XimCachedDefaultTreeBase.mb = (((char *) m) + m->mb);
|
||
|
_XimCachedDefaultTreeBase.wc = (wchar_t *) (((char *) m) + m->wc);
|
||
|
_XimCachedDefaultTreeBase.utf8 = (((char *) m) + m->utf8);
|
||
|
_XimCachedDefaultTreeBase.treeused = m->treeused;
|
||
|
_XimCachedDefaultTreeBase.mbused = m->mbused;
|
||
|
_XimCachedDefaultTreeBase.wcused = m->wcused;
|
||
|
_XimCachedDefaultTreeBase.utf8used = m->utf8used;
|
||
|
/* treesize etc. is ignored because only used during parsing */
|
||
|
_XimCachedDefaultTreeRefcount = 0;
|
||
|
/* fprintf (stderr, "read cached tree at %p: %s\n", (void *) m, name); */
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
Private unsigned int strToHash (
|
||
|
const char *name)
|
||
|
{
|
||
|
unsigned int hash = 0;
|
||
|
while (*name)
|
||
|
hash = hash * XIM_HASH_PRIME_1 + *(unsigned const char *)name++;
|
||
|
return hash % XIM_HASH_PRIME_2;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Returns read-only fd of cache file, -1 if none.
|
||
|
* Sets *res to cache filename if safe. Sets *size to file size of cache. */
|
||
|
Private int _XimCachedFileName (
|
||
|
const char *dir, const char *name,
|
||
|
const char *intname, const char *encoding,
|
||
|
uid_t uid, int isglobal, char **res, off_t *size)
|
||
|
{
|
||
|
struct stat st_name, st;
|
||
|
int fd;
|
||
|
unsigned int len, hash, hash2;
|
||
|
struct _XimCacheStruct *m;
|
||
|
/* There are some races here with 'dir', but we are either in our own home
|
||
|
* or the global cache dir, and not inside some public writable dir */
|
||
|
/* fprintf (stderr, "XimCachedFileName for dir %s name %s intname %s encoding %s uid %d\n", dir, name, intname, encoding, uid); */
|
||
|
if (stat (name, &st_name) == -1 || ! S_ISREG (st_name.st_mode)
|
||
|
|| stat (dir, &st) == -1 || ! S_ISDIR (st.st_mode) || st.st_uid != uid
|
||
|
|| (st.st_mode & 0022) != 0000) {
|
||
|
*res = NULL;
|
||
|
return -1;
|
||
|
}
|
||
|
len = strlen (dir);
|
||
|
hash = strToHash (intname);
|
||
|
hash2 = strToHash (encoding);
|
||
|
*res = Xmalloc (len + 1 + 27 + 1); /* Max VERSION 9999 */
|
||
|
|
||
|
if (len == 0 || dir [len-1] != '/')
|
||
|
sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(),
|
||
|
XIM_CACHE_VERSION, sizeof (DefTree), hash, hash2);
|
||
|
else
|
||
|
sprintf (*res, "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(),
|
||
|
XIM_CACHE_VERSION, sizeof (DefTree), hash, hash2);
|
||
|
|
||
|
/* fprintf (stderr, "-> %s\n", *res); */
|
||
|
if ( (fd = _XOpenFile (*res, O_RDONLY)) == -1)
|
||
|
return -1;
|
||
|
|
||
|
if (fstat (fd, &st) == -1) {
|
||
|
Xfree (*res);
|
||
|
*res = NULL;
|
||
|
close (fd);
|
||
|
return -1;
|
||
|
}
|
||
|
*size = st.st_size;
|
||
|
|
||
|
if (! S_ISREG (st.st_mode) || st.st_uid != uid
|
||
|
|| (st.st_mode & 0022) != 0000 || st.st_mtime <= st_name.st_mtime
|
||
|
|| (st.st_mtime < time (NULL) - 24*60*60 && ! isglobal)) {
|
||
|
|
||
|
close (fd);
|
||
|
if (unlink (*res) != 0) {
|
||
|
Xfree (*res);
|
||
|
*res = NULL; /* cache is not safe */
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
m = mmap (NULL, sizeof (struct _XimCacheStruct), PROT_READ, MAP_PRIVATE,
|
||
|
fd, 0);
|
||
|
if (m == NULL || m == MAP_FAILED) {
|
||
|
close (fd);
|
||
|
Xfree (*res);
|
||
|
*res = NULL;
|
||
|
return -1;
|
||
|
}
|
||
|
if (*size < sizeof (struct _XimCacheStruct) || m->id != XIM_CACHE_MAGIC) {
|
||
|
munmap (m, sizeof (struct _XimCacheStruct));
|
||
|
close (fd);
|
||
|
fprintf (stderr, "Ignoring broken XimCache %s\n", *res);
|
||
|
Xfree (*res);
|
||
|
*res = NULL;
|
||
|
return -1;
|
||
|
}
|
||
|
if (m->version != XIM_CACHE_VERSION) {
|
||
|
munmap (m, sizeof (struct _XimCacheStruct));
|
||
|
close (fd);
|
||
|
if (unlink (*res) != 0) {
|
||
|
Xfree (*res);
|
||
|
*res = NULL; /* cache is not safe */
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
munmap (m, sizeof (struct _XimCacheStruct));
|
||
|
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
|
||
|
Private Bool _XimLoadCache (
|
||
|
int fd,
|
||
|
const char *name,
|
||
|
const char *encoding,
|
||
|
off_t size,
|
||
|
Xim im)
|
||
|
{
|
||
|
if (_XimCache_mmap ||
|
||
|
_XimReadCachedDefaultTree (fd, name, encoding, size)) {
|
||
|
_XimCachedDefaultTreeRefcount++;
|
||
|
memcpy (&im->private.local.base, &_XimCachedDefaultTreeBase,
|
||
|
sizeof (_XimCachedDefaultTreeBase));
|
||
|
im->private.local.top = _XimCache_mmap->top;
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
return False;
|
||
|
}
|
||
|
|
||
|
|
||
|
Private void
|
||
|
_XimWriteCachedDefaultTree(
|
||
|
const char *name,
|
||
|
const char *encoding,
|
||
|
const char *cachename,
|
||
|
Xim im)
|
||
|
{
|
||
|
int fd;
|
||
|
FILE *fp;
|
||
|
struct _XimCacheStruct *m;
|
||
|
int msize = (XOffsetOf(struct _XimCacheStruct, fname)
|
||
|
+ strlen(name) + strlen(encoding) + 2
|
||
|
+ XIM_CACHE_TREE_ALIGNMENT-1) & -XIM_CACHE_TREE_ALIGNMENT;
|
||
|
DefTreeBase *b = &im->private.local.base;
|
||
|
|
||
|
if (! b->tree && ! (b->tree = Xmalloc (sizeof(DefTree))) )
|
||
|
return;
|
||
|
if (! b->mb && ! (b->mb = Xmalloc (1)) )
|
||
|
return;
|
||
|
if (! b->wc && ! (b->wc = Xmalloc (sizeof(wchar_t))) )
|
||
|
return;
|
||
|
if (! b->utf8 && ! (b->utf8 = Xmalloc (1)) )
|
||
|
return;
|
||
|
|
||
|
/* First entry is always unused */
|
||
|
memset (b->tree, 0, sizeof(DefTree));
|
||
|
b->mb[0] = 0;
|
||
|
b->wc[0] = 0;
|
||
|
b->utf8[0] = 0;
|
||
|
|
||
|
m = Xmalloc (msize);
|
||
|
memset (m, 0, msize);
|
||
|
m->id = XIM_CACHE_MAGIC;
|
||
|
m->version = XIM_CACHE_VERSION;
|
||
|
m->top = im->private.local.top;
|
||
|
m->treeused = b->treeused;
|
||
|
m->mbused = b->mbused;
|
||
|
m->wcused = b->wcused;
|
||
|
m->utf8used = b->utf8used;
|
||
|
/* Tree first, then wide chars, then the rest due to alignment */
|
||
|
m->tree = msize;
|
||
|
m->wc = msize + sizeof (DefTree) * m->treeused;
|
||
|
m->mb = m->wc + sizeof (wchar_t) * m->wcused;
|
||
|
m->utf8 = m->mb + m->mbused;
|
||
|
m->size = m->utf8 + m->utf8used;
|
||
|
strcpy (m->fname, name);
|
||
|
strcpy (m->fname+strlen(name)+1, encoding);
|
||
|
|
||
|
/* This STILL might be racy on NFS */
|
||
|
if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL,
|
||
|
0600)) < 0)
|
||
|
return;
|
||
|
if (! (fp = fdopen (fd, "wb")) ) {
|
||
|
close (fd);
|
||
|
return;
|
||
|
}
|
||
|
fwrite (m, msize, 1, fp);
|
||
|
fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp);
|
||
|
fwrite (im->private.local.base.wc, sizeof(wchar_t), m->wcused, fp);
|
||
|
fwrite (im->private.local.base.mb, 1, m->mbused, fp);
|
||
|
fwrite (im->private.local.base.utf8, 1, m->utf8used, fp);
|
||
|
if (fclose (fp) != 0)
|
||
|
unlink (cachename);
|
||
|
_XimCache_mmap = m;
|
||
|
memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base,
|
||
|
sizeof (_XimCachedDefaultTreeBase));
|
||
|
/* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
Private void
|
||
|
_XimCreateDefaultTree(
|
||
|
Xim im)
|
||
|
{
|
||
|
FILE *fp = NULL;
|
||
|
char *name, *tmpname = NULL, *intname;
|
||
|
char *cachename = NULL;
|
||
|
/* Should use getpwent() instead of $HOME (cross-platform?) */
|
||
|
char *home = getenv("HOME");
|
||
|
char *cachedir = NULL;
|
||
|
char *tmpcachedir = NULL;
|
||
|
int hl = home ? strlen (home) : 0;
|
||
|
#ifdef COMPOSECACHE
|
||
|
const char *encoding = nl_langinfo (CODESET);
|
||
|
uid_t euid = geteuid ();
|
||
|
gid_t egid = getegid ();
|
||
|
int cachefd = -1;
|
||
|
off_t size;
|
||
|
#endif
|
||
|
|
||
|
name = getenv("XCOMPOSEFILE");
|
||
|
if (name == (char *) NULL) {
|
||
|
if (home != (char *) NULL) {
|
||
|
tmpname = name = Xmalloc(hl + 10 + 1);
|
||
|
if (name != (char *) NULL) {
|
||
|
int fd;
|
||
|
strcpy(name, home);
|
||
|
strcpy(name + hl, "/.XCompose");
|
||
|
if ( (fd = _XOpenFile (name, O_RDONLY)) < 0) {
|
||
|
Xfree (name);
|
||
|
name = tmpname = NULL;
|
||
|
} else
|
||
|
close (fd);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (name == (char *) NULL) {
|
||
|
tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE);
|
||
|
}
|
||
|
intname = name;
|
||
|
|
||
|
#ifdef COMPOSECACHE
|
||
|
if (getuid () == euid && getgid () == egid && euid != 0) {
|
||
|
char *c;
|
||
|
/* Usage: XCOMPOSECACHE=<cachedir>[=<filename>]
|
||
|
* cachedir: directory of cache files
|
||
|
* filename: internally used name for cache file */
|
||
|
cachedir = getenv("XCOMPOSECACHE");
|
||
|
if (cachedir && (c = strchr (cachedir, '='))) {
|
||
|
tmpcachedir = strdup (cachedir);
|
||
|
intname = tmpcachedir + (c-cachedir) + 1;
|
||
|
tmpcachedir[c-cachedir] = '\0';
|
||
|
cachedir = tmpcachedir;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (! cachedir) {
|
||
|
cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR, name, intname,
|
||
|
encoding, 0, 1, &cachename, &size);
|
||
|
if (cachefd != -1) {
|
||
|
if (_XimLoadCache (cachefd, intname, encoding, size, im)) {
|
||
|
if (tmpcachedir)
|
||
|
Xfree (tmpcachedir);
|
||
|
if (tmpname)
|
||
|
Xfree (tmpname);
|
||
|
if (cachename)
|
||
|
Xfree (cachename);
|
||
|
close (cachefd);
|
||
|
return;
|
||
|
}
|
||
|
close (cachefd);
|
||
|
}
|
||
|
if (cachename)
|
||
|
Xfree (cachename);
|
||
|
cachename = NULL;
|
||
|
}
|
||
|
|
||
|
if (getuid () == euid && getgid () == egid && euid != 0 && home) {
|
||
|
|
||
|
if (! cachedir) {
|
||
|
tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1);
|
||
|
strcpy (cachedir, home);
|
||
|
strcat (cachedir, XIM_HOME_CACHE_DIR);
|
||
|
}
|
||
|
cachefd = _XimCachedFileName (cachedir, name, intname, encoding,
|
||
|
euid, 0, &cachename, &size);
|
||
|
if (cachefd != -1) {
|
||
|
if (_XimLoadCache (cachefd, intname, encoding, size, im)) {
|
||
|
if (tmpcachedir)
|
||
|
Xfree (tmpcachedir);
|
||
|
if (tmpname)
|
||
|
Xfree (tmpname);
|
||
|
if (cachename)
|
||
|
Xfree (cachename);
|
||
|
close (cachefd);
|
||
|
return;
|
||
|
}
|
||
|
close (cachefd);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (! (fp = _XFopenFile (name, "r"))) {
|
||
|
if (tmpcachedir)
|
||
|
Xfree (tmpcachedir);
|
||
|
if (tmpname)
|
||
|
Xfree (tmpname);
|
||
|
if (cachename)
|
||
|
Xfree (cachename);
|
||
|
return;
|
||
|
}
|
||
|
_XimParseStringFile(fp, im);
|
||
|
fclose(fp);
|
||
|
|
||
|
#ifdef COMPOSECACHE
|
||
|
if (cachename) {
|
||
|
assert (euid != 0);
|
||
|
_XimWriteCachedDefaultTree (intname, encoding, cachename, im);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (tmpcachedir)
|
||
|
Xfree (tmpcachedir);
|
||
|
if (tmpname)
|
||
|
Xfree (tmpname);
|
||
|
if (cachename)
|
||
|
Xfree (cachename);
|
||
|
}
|
||
|
|
||
|
Private XIMMethodsRec Xim_im_local_methods = {
|
||
|
_XimLocalCloseIM, /* close */
|
||
|
_XimLocalSetIMValues, /* set_values */
|
||
|
_XimLocalGetIMValues, /* get_values */
|
||
|
_XimLocalCreateIC, /* create_ic */
|
||
|
_XimLcctstombs, /* ctstombs */
|
||
|
_XimLcctstowcs, /* ctstowcs */
|
||
|
_XimLcctstoutf8 /* ctstoutf8 */
|
||
|
};
|
||
|
|
||
|
Public Bool
|
||
|
_XimLocalOpenIM(
|
||
|
Xim im)
|
||
|
{
|
||
|
XLCd lcd = im->core.lcd;
|
||
|
XlcConv conv;
|
||
|
XimDefIMValues im_values;
|
||
|
XimLocalPrivateRec* private = &im->private.local;
|
||
|
|
||
|
_XimInitialResourceInfo();
|
||
|
if(_XimSetIMResourceList(&im->core.im_resources,
|
||
|
&im->core.im_num_resources) == False) {
|
||
|
goto Open_Error;
|
||
|
}
|
||
|
if(_XimSetICResourceList(&im->core.ic_resources,
|
||
|
&im->core.ic_num_resources) == False) {
|
||
|
goto Open_Error;
|
||
|
}
|
||
|
|
||
|
_XimSetIMMode(im->core.im_resources, im->core.im_num_resources);
|
||
|
|
||
|
_XimGetCurrentIMValues(im, &im_values);
|
||
|
if(_XimSetLocalIMDefaults(im, (XPointer)&im_values,
|
||
|
im->core.im_resources, im->core.im_num_resources) == False) {
|
||
|
goto Open_Error;
|
||
|
}
|
||
|
_XimSetCurrentIMValues(im, &im_values);
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte)))
|
||
|
goto Open_Error;
|
||
|
private->ctom_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar)))
|
||
|
goto Open_Error;
|
||
|
private->ctow_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNUtf8String)))
|
||
|
goto Open_Error;
|
||
|
private->ctoutf8_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte)))
|
||
|
goto Open_Error;
|
||
|
private->cstomb_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar)))
|
||
|
goto Open_Error;
|
||
|
private->cstowc_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String)))
|
||
|
goto Open_Error;
|
||
|
private->cstoutf8_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar)))
|
||
|
goto Open_Error;
|
||
|
private->ucstoc_conv = conv;
|
||
|
|
||
|
if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String)))
|
||
|
goto Open_Error;
|
||
|
private->ucstoutf8_conv = conv;
|
||
|
|
||
|
private->base.treeused = 1;
|
||
|
private->base.mbused = 1;
|
||
|
private->base.wcused = 1;
|
||
|
private->base.utf8used = 1;
|
||
|
|
||
|
_XimCreateDefaultTree(im);
|
||
|
|
||
|
im->methods = &Xim_im_local_methods;
|
||
|
private->current_ic = (XIC)NULL;
|
||
|
|
||
|
return(True);
|
||
|
|
||
|
Open_Error :
|
||
|
_XimLocalIMFree(im);
|
||
|
return(False);
|
||
|
}
|