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