imLcIm.c revision 6cc2b21f
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 Xfree(m); 494 return; 495 } 496 if (! (fp = fdopen (fd, "wb")) ) { 497 close (fd); 498 Xfree(m); 499 return; 500 } 501 fwrite (m, msize, 1, fp); 502 fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp); 503 fwrite (im->private.local.base.wc, sizeof(wchar_t), m->wcused, fp); 504 fwrite (im->private.local.base.mb, 1, m->mbused, fp); 505 fwrite (im->private.local.base.utf8, 1, m->utf8used, fp); 506 if (fclose (fp) != 0) 507 unlink (cachename); 508 _XimCache_mmap = m; 509 memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base, 510 sizeof (_XimCachedDefaultTreeBase)); 511/* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */ 512} 513 514#endif 515 516 517Private void 518_XimCreateDefaultTree( 519 Xim im) 520{ 521 FILE *fp = NULL; 522 char *name, *tmpname = NULL, *intname; 523 char *cachename = NULL; 524 /* Should use getpwent() instead of $HOME (cross-platform?) */ 525 char *home = getenv("HOME"); 526 char *cachedir = NULL; 527 char *tmpcachedir = NULL; 528 int hl = home ? strlen (home) : 0; 529#ifdef COMPOSECACHE 530 const char *encoding = nl_langinfo (CODESET); 531 uid_t euid = geteuid (); 532 gid_t egid = getegid (); 533 int cachefd = -1; 534 off_t size; 535#endif 536 537 name = getenv("XCOMPOSEFILE"); 538 if (name == (char *) NULL) { 539 if (home != (char *) NULL) { 540 tmpname = name = Xmalloc(hl + 10 + 1); 541 if (name != (char *) NULL) { 542 int fd; 543 strcpy(name, home); 544 strcpy(name + hl, "/.XCompose"); 545 if ( (fd = _XOpenFile (name, O_RDONLY)) < 0) { 546 Xfree (name); 547 name = tmpname = NULL; 548 } else 549 close (fd); 550 } 551 } 552 } 553 554 if (name == (char *) NULL) { 555 tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE); 556 } 557 intname = name; 558 559#ifdef COMPOSECACHE 560 if (getuid () == euid && getgid () == egid && euid != 0) { 561 char *c; 562 /* Usage: XCOMPOSECACHE=<cachedir>[=<filename>] 563 * cachedir: directory of cache files 564 * filename: internally used name for cache file */ 565 cachedir = getenv("XCOMPOSECACHE"); 566 if (cachedir && (c = strchr (cachedir, '='))) { 567 tmpcachedir = strdup (cachedir); 568 intname = tmpcachedir + (c-cachedir) + 1; 569 tmpcachedir[c-cachedir] = '\0'; 570 cachedir = tmpcachedir; 571 } 572 } 573 574 if (! cachedir) { 575 cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR, name, intname, 576 encoding, 0, 1, &cachename, &size); 577 if (cachefd != -1) { 578 if (_XimLoadCache (cachefd, intname, encoding, size, im)) { 579 if (tmpcachedir) 580 Xfree (tmpcachedir); 581 if (tmpname) 582 Xfree (tmpname); 583 if (cachename) 584 Xfree (cachename); 585 close (cachefd); 586 return; 587 } 588 close (cachefd); 589 } 590 if (cachename) 591 Xfree (cachename); 592 cachename = NULL; 593 } 594 595 if (getuid () == euid && getgid () == egid && euid != 0 && home) { 596 597 if (! cachedir) { 598 tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1); 599 strcpy (cachedir, home); 600 strcat (cachedir, XIM_HOME_CACHE_DIR); 601 } 602 cachefd = _XimCachedFileName (cachedir, name, intname, encoding, 603 euid, 0, &cachename, &size); 604 if (cachefd != -1) { 605 if (_XimLoadCache (cachefd, intname, encoding, size, im)) { 606 if (tmpcachedir) 607 Xfree (tmpcachedir); 608 if (tmpname) 609 Xfree (tmpname); 610 if (cachename) 611 Xfree (cachename); 612 close (cachefd); 613 return; 614 } 615 close (cachefd); 616 } 617 } 618#endif 619 620 if (! (fp = _XFopenFile (name, "r"))) { 621 if (tmpcachedir) 622 Xfree (tmpcachedir); 623 if (tmpname) 624 Xfree (tmpname); 625 if (cachename) 626 Xfree (cachename); 627 return; 628 } 629 _XimParseStringFile(fp, im); 630 fclose(fp); 631 632#ifdef COMPOSECACHE 633 if (cachename) { 634 assert (euid != 0); 635 _XimWriteCachedDefaultTree (intname, encoding, cachename, im); 636 } 637#endif 638 639 if (tmpcachedir) 640 Xfree (tmpcachedir); 641 if (tmpname) 642 Xfree (tmpname); 643 if (cachename) 644 Xfree (cachename); 645} 646 647Private XIMMethodsRec Xim_im_local_methods = { 648 _XimLocalCloseIM, /* close */ 649 _XimLocalSetIMValues, /* set_values */ 650 _XimLocalGetIMValues, /* get_values */ 651 _XimLocalCreateIC, /* create_ic */ 652 _XimLcctstombs, /* ctstombs */ 653 _XimLcctstowcs, /* ctstowcs */ 654 _XimLcctstoutf8 /* ctstoutf8 */ 655}; 656 657Public Bool 658_XimLocalOpenIM( 659 Xim im) 660{ 661 XLCd lcd = im->core.lcd; 662 XlcConv conv; 663 XimDefIMValues im_values; 664 XimLocalPrivateRec* private = &im->private.local; 665 666 _XimInitialResourceInfo(); 667 if(_XimSetIMResourceList(&im->core.im_resources, 668 &im->core.im_num_resources) == False) { 669 goto Open_Error; 670 } 671 if(_XimSetICResourceList(&im->core.ic_resources, 672 &im->core.ic_num_resources) == False) { 673 goto Open_Error; 674 } 675 676 _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); 677 678 _XimGetCurrentIMValues(im, &im_values); 679 if(_XimSetLocalIMDefaults(im, (XPointer)&im_values, 680 im->core.im_resources, im->core.im_num_resources) == False) { 681 goto Open_Error; 682 } 683 _XimSetCurrentIMValues(im, &im_values); 684 685 if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte))) 686 goto Open_Error; 687 private->ctom_conv = conv; 688 689 if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar))) 690 goto Open_Error; 691 private->ctow_conv = conv; 692 693 if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNUtf8String))) 694 goto Open_Error; 695 private->ctoutf8_conv = conv; 696 697 if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) 698 goto Open_Error; 699 private->cstomb_conv = conv; 700 701 if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) 702 goto Open_Error; 703 private->cstowc_conv = conv; 704 705 if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) 706 goto Open_Error; 707 private->cstoutf8_conv = conv; 708 709 if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) 710 goto Open_Error; 711 private->ucstoc_conv = conv; 712 713 if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) 714 goto Open_Error; 715 private->ucstoutf8_conv = conv; 716 717 private->base.treeused = 1; 718 private->base.mbused = 1; 719 private->base.wcused = 1; 720 private->base.utf8used = 1; 721 722 _XimCreateDefaultTree(im); 723 724 im->methods = &Xim_im_local_methods; 725 private->current_ic = (XIC)NULL; 726 727 return(True); 728 729Open_Error : 730 _XimLocalIMFree(im); 731 return(False); 732} 733