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