Initialize.c revision a3bd7f05
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1994, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in this Software without prior written authorization from The Open Group. 68 69*/ 70 71/* Make sure all wm properties can make it out of the resource manager */ 72 73#ifdef HAVE_CONFIG_H 74#include <config.h> 75#endif 76#include "IntrinsicI.h" 77#include "StringDefs.h" 78#include "CoreP.h" 79#include "ShellP.h" 80#include <stdio.h> 81#include <X11/Xlocale.h> 82#ifdef XTHREADS 83#include <X11/Xthreads.h> 84#endif 85#ifndef WIN32 86#define X_INCLUDE_PWD_H 87#define XOS_USE_XT_LOCKING 88#include <X11/Xos_r.h> 89#endif 90 91#include <stdlib.h> 92 93#if (defined(SUNSHLIB) || defined(AIXSHLIB)) && defined(SHAREDCODE) 94/* 95 * If used as a shared library, generate code under a different name so that 96 * the stub routines in sharedlib.c get loaded into the application binary. 97 */ 98#define XtToolkitInitialize _XtToolkitInitialize 99#define XtOpenApplication _XtOpenApplication 100#define XtAppInitialize _XtAppInitialize 101#define XtInitialize _XtInitialize 102#endif /* (SUNSHLIB || AIXSHLIB) && SHAREDCODE */ 103 104/* 105 * hpux 106 * Hand-patched versions of HP-UX prior to version 7.0 can usefully add 107 * -DUSE_UNAME in the appropriate config file to get long hostnames. 108 */ 109 110#ifdef USG 111#define USE_UNAME 112#endif 113 114#ifdef USE_UNAME 115#include <sys/utsname.h> 116#endif 117 118/* some unspecified magic number of expected search levels for Xrm */ 119#define SEARCH_LIST_SIZE 1000 120 121/* 122 This is a set of default records describing the command line arguments that 123 Xlib will parse and set into the resource data base. 124 125 This list is applied before the users list to enforce these defaults. This is 126 policy, which the toolkit avoids but I hate differing programs at this level. 127*/ 128 129/* *INDENT-OFF* */ 130static XrmOptionDescRec const opTable[] = { 131{"+rv", "*reverseVideo", XrmoptionNoArg, (XtPointer) "off"}, 132{"+synchronous", "*synchronous", XrmoptionNoArg, (XtPointer) "off"}, 133{"-background", "*background", XrmoptionSepArg, (XtPointer) NULL}, 134{"-bd", "*borderColor", XrmoptionSepArg, (XtPointer) NULL}, 135{"-bg", "*background", XrmoptionSepArg, (XtPointer) NULL}, 136{"-bordercolor", "*borderColor", XrmoptionSepArg, (XtPointer) NULL}, 137{"-borderwidth", ".borderWidth", XrmoptionSepArg, (XtPointer) NULL}, 138{"-bw", ".borderWidth", XrmoptionSepArg, (XtPointer) NULL}, 139{"-display", ".display", XrmoptionSepArg, (XtPointer) NULL}, 140{"-fg", "*foreground", XrmoptionSepArg, (XtPointer) NULL}, 141{"-fn", "*font", XrmoptionSepArg, (XtPointer) NULL}, 142{"-font", "*font", XrmoptionSepArg, (XtPointer) NULL}, 143{"-foreground", "*foreground", XrmoptionSepArg, (XtPointer) NULL}, 144{"-geometry", ".geometry", XrmoptionSepArg, (XtPointer) NULL}, 145{"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "on"}, 146{"-name", ".name", XrmoptionSepArg, (XtPointer) NULL}, 147{"-reverse", "*reverseVideo", XrmoptionNoArg, (XtPointer) "on"}, 148{"-rv", "*reverseVideo", XrmoptionNoArg, (XtPointer) "on"}, 149{"-selectionTimeout", ".selectionTimeout", XrmoptionSepArg, (XtPointer) NULL}, 150{"-synchronous", "*synchronous", XrmoptionNoArg, (XtPointer) "on"}, 151{"-title", ".title", XrmoptionSepArg, (XtPointer) NULL}, 152{"-xnllanguage", ".xnlLanguage", XrmoptionSepArg, (XtPointer) NULL}, 153{"-xrm", NULL, XrmoptionResArg, (XtPointer) NULL}, 154{"-xtsessionID", ".sessionID", XrmoptionSepArg, (XtPointer) NULL}, 155}; 156/* *INDENT-ON* */ 157 158/* 159 * GetHostname - emulates gethostname() on non-bsd systems. 160 */ 161 162static void 163GetHostname(char *buf, int maxlen) 164{ 165#ifdef USE_UNAME 166 int len; 167 struct utsname name; 168 169 if (maxlen <= 0 || buf == NULL) 170 return; 171 172 uname(&name); 173 len = strlen(name.nodename); 174 if (len >= maxlen) 175 len = maxlen; 176 (void) strncpy(buf, name.nodename, len - 1); 177 buf[len - 1] = '\0'; 178#else 179 if (maxlen <= 0 || buf == NULL) 180 return; 181 182 buf[0] = '\0'; 183 (void) gethostname(buf, (size_t) maxlen); 184 buf[maxlen - 1] = '\0'; 185#endif 186} 187 188#ifdef SUNSHLIB 189void 190_XtInherit(void) 191{ 192 extern void __XtInherit(); 193 194 __XtInherit(); 195} 196 197#define _XtInherit __XtInherit 198#endif 199 200#if defined (WIN32) || defined(__CYGWIN__) 201/* 202 * The Symbol _XtInherit is used in two different manners. 203 * First it could be used as a generic function and second 204 * as an absolute address reference, which will be used to 205 * check the initialisation process of several other libraries. 206 * Because of this the symbol must be accessable by all 207 * client dll's and applications. In unix environments 208 * this is no problem, because the used shared libraries 209 * format (elf) supports this immediatly. Under Windows 210 * this isn't true, because a functions address in a dll 211 * is different from the same function in another dll or 212 * applications, because the used Portable Executable 213 * File adds a code stub to each client to provide the 214 * exported symbol name. This stub uses an indirect 215 * pointer to get the original symbol address, which is 216 * then jumped to, like in this example: 217 * 218 * --- client --- --- dll ---- 219 * ... 220 * call foo 221 * 222 * foo: jmp (*_imp_foo) ----> foo: .... 223 * nop 224 * nop 225 * 226 * _imp_foo: .long <index of foo in dll export table, is 227 * set to the real address by the runtime linker> 228 * 229 * Now it is clear why the clients symbol foo isn't the same 230 * as in the dll and we can think about how to deal which 231 * this two above mentioned requirements, to export this 232 * symbol to all clients and to allow calling this symbol 233 * as a function. The solution I've used exports the 234 * symbol _XtInherit as data symbol, because global data 235 * symbols are exported to all clients. But how to deal 236 * with the second requirement, that this symbol should 237 * be used as function. The Trick is to build a little 238 * code stub in the data section in the exact manner as 239 * above explained. This is done with the assembler code 240 * below. 241 * 242 * Ralf Habacker 243 * 244 * References: 245 * msdn http://msdn.microsoft.com/msdnmag/issues/02/02/PE/PE.asp 246 * cygwin-xfree: http://www.cygwin.com/ml/cygwin-xfree/2003-10/msg00000.html 247 */ 248 249#ifdef __x86_64__ 250asm(".section .trampoline, \"dwx\" \n\ 251 .globl _XtInherit \n\ 252 _XtInherit: \n\ 253 jmp *_y(%rip) \n\ 254_y: .quad __XtInherit \n\ 255 .text \n"); 256#else 257asm(".data\n\ 258 .globl __XtInherit \n\ 259 __XtInherit: jmp *_y \n\ 260 _y: .long ___XtInherit \n\ 261 .text \n"); 262#endif 263 264#define _XtInherit __XtInherit 265#endif 266 267void 268_XtInherit(void) 269{ 270 XtErrorMsg("invalidProcedure", "inheritanceProc", XtCXtToolkitError, 271 "Unresolved inheritance operation", NULL, NULL); 272} 273 274void 275XtToolkitInitialize(void) 276{ 277 static Boolean initialized = False; 278 279 LOCK_PROCESS; 280 if (initialized) { 281 UNLOCK_PROCESS; 282 return; 283 } 284 initialized = True; 285 UNLOCK_PROCESS; 286 /* Resource management initialization */ 287 XrmInitialize(); 288 _XtResourceListInitialize(); 289 290 /* Other intrinsic intialization */ 291 _XtConvertInitialize(); 292 _XtEventInitialize(); 293 _XtTranslateInitialize(); 294 295 /* Some apps rely on old (broken) XtAppPeekEvent behavior */ 296 if (getenv("XTAPPPEEKEVENT_SKIPTIMER")) 297 XtAppPeekEvent_SkipTimer = True; 298 else 299 XtAppPeekEvent_SkipTimer = False; 300} 301 302String 303_XtGetUserName(_XtString dest, int len) 304{ 305#ifdef WIN32 306 String ptr = NULL; 307 308 if ((ptr = getenv("USERNAME"))) { 309 (void) strncpy(dest, ptr, len - 1); 310 dest[len - 1] = '\0'; 311 } 312 else 313 *dest = '\0'; 314#else 315#ifdef X_NEEDS_PWPARAMS 316 _Xgetpwparams pwparams; 317#endif 318 struct passwd *pw; 319 char *ptr; 320 321 if ((ptr = getenv("USER"))) { 322 (void) strncpy(dest, ptr, (size_t) (len - 1)); 323 dest[len - 1] = '\0'; 324 } 325 else { 326 if ((pw = _XGetpwuid(getuid(), pwparams)) != NULL) { 327 (void) strncpy(dest, pw->pw_name, (size_t) (len - 1)); 328 dest[len - 1] = '\0'; 329 } 330 else 331 *dest = '\0'; 332 } 333#endif 334 return dest; 335} 336 337static String 338GetRootDirName(_XtString dest, int len) 339{ 340#ifdef WIN32 341 register char *ptr1; 342 register char *ptr2 = NULL; 343 int len1 = 0, len2 = 0; 344 345 if (ptr1 = getenv("HOME")) { /* old, deprecated */ 346 len1 = strlen(ptr1); 347 } 348 else if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) { 349 len1 = strlen(ptr1); 350 len2 = strlen(ptr2); 351 } 352 else if (ptr2 = getenv("USERNAME")) { 353 len1 = strlen(ptr1 = "/users/"); 354 len2 = strlen(ptr2); 355 } 356 if ((len1 + len2 + 1) < len) 357 sprintf(dest, "%s%s", ptr1, (ptr2) ? ptr2 : ""); 358 else 359 *dest = '\0'; 360#else 361#ifdef X_NEEDS_PWPARAMS 362 _Xgetpwparams pwparams; 363#endif 364 static char *ptr; 365 366 if (len <= 0 || dest == NULL) 367 return NULL; 368 369 if ((ptr = getenv("HOME"))) { 370 (void) strncpy(dest, ptr, (size_t) (len - 1)); 371 dest[len - 1] = '\0'; 372 } 373 else { 374 struct passwd *pw; 375 376 if ((ptr = getenv("USER"))) 377 pw = _XGetpwnam(ptr, pwparams); 378 else 379 pw = _XGetpwuid(getuid(), pwparams); 380 if (pw != NULL) { 381 (void) strncpy(dest, pw->pw_dir, (size_t) (len - 1)); 382 dest[len - 1] = '\0'; 383 } 384 else 385 *dest = '\0'; 386 } 387#endif 388 return dest; 389} 390 391static void 392CombineAppUserDefaults(Display *dpy, XrmDatabase *pdb) 393{ 394 char *filename; 395 char *path = NULL; 396 Boolean deallocate = False; 397 398 if (!(path = getenv("XUSERFILESEARCHPATH"))) { 399#if !defined(WIN32) || !defined(__MINGW32__) 400 char *old_path; 401 char homedir[PATH_MAX]; 402 403 GetRootDirName(homedir, PATH_MAX); 404 if (!(old_path = getenv("XAPPLRESDIR"))) { 405 XtAsprintf(&path, 406 "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N", 407 homedir, homedir, homedir, homedir, homedir, homedir); 408 } 409 else { 410 XtAsprintf(&path, 411 "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N", 412 old_path, old_path, old_path, homedir, 413 old_path, old_path, old_path, homedir); 414 } 415 deallocate = True; 416#endif 417 } 418 419 filename = XtResolvePathname(dpy, NULL, NULL, NULL, path, NULL, 0, NULL); 420 if (filename) { 421 (void) XrmCombineFileDatabase(filename, pdb, False); 422 XtFree(filename); 423 } 424 425 if (deallocate) 426 XtFree(path); 427} 428 429static void 430CombineUserDefaults(Display *dpy, XrmDatabase *pdb) 431{ 432 char *dpy_defaults = XResourceManagerString(dpy); 433 434 if (dpy_defaults) { 435 XrmCombineDatabase(XrmGetStringDatabase(dpy_defaults), pdb, False); 436 } 437 else { 438#ifdef __MINGW32__ 439 const char *slashDotXdefaults = "/Xdefaults"; 440#else 441 const char *slashDotXdefaults = "/.Xdefaults"; 442#endif 443 char filename[PATH_MAX]; 444 445 (void) GetRootDirName(filename, 446 PATH_MAX - (int) strlen(slashDotXdefaults) - 1); 447 (void) strcat(filename, slashDotXdefaults); 448 (void) XrmCombineFileDatabase(filename, pdb, False); 449 } 450} 451 452static Bool 453StoreDBEntry(XrmDatabase *db _X_UNUSED, 454 XrmBindingList bindings, 455 XrmQuarkList quarks, 456 XrmRepresentation *type, 457 XrmValuePtr value, 458 XPointer data) 459{ 460 XrmQPutResource((XrmDatabase *) data, bindings, quarks, *type, value); 461 return False; 462} 463 464static XrmDatabase 465CopyDB(XrmDatabase db) 466{ 467 XrmDatabase copy = NULL; 468 XrmQuark empty = NULLQUARK; 469 470 XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels, 471 StoreDBEntry, (XPointer) ©); 472 return copy; 473} 474 475static String 476_XtDefaultLanguageProc(Display *dpy _X_UNUSED, 477 String xnl, 478 XtPointer closure _X_UNUSED) 479{ 480 if (!setlocale(LC_ALL, xnl)) 481 XtWarning("locale not supported by C library, locale unchanged"); 482 483 if (!XSupportsLocale()) { 484 XtWarning("locale not supported by Xlib, locale set to C"); 485 setlocale(LC_ALL, "C"); 486 } 487 if (!XSetLocaleModifiers("")) 488 XtWarning("X locale modifiers not supported, using default"); 489 490 return setlocale(LC_ALL, NULL); /* re-query in case overwritten */ 491} 492 493XtLanguageProc 494XtSetLanguageProc(XtAppContext app, XtLanguageProc proc, XtPointer closure) 495{ 496 XtLanguageProc old; 497 498 if (!proc) { 499 proc = _XtDefaultLanguageProc; 500 closure = NULL; 501 } 502 503 if (app) { 504 LOCK_APP(app); 505 LOCK_PROCESS; 506 /* set langProcRec only for this application context */ 507 old = app->langProcRec.proc; 508 app->langProcRec.proc = proc; 509 app->langProcRec.closure = closure; 510 UNLOCK_PROCESS; 511 UNLOCK_APP(app); 512 } 513 else { 514 /* set langProcRec for all application contexts */ 515 ProcessContext process; 516 517 LOCK_PROCESS; 518 process = _XtGetProcessContext(); 519 old = process->globalLangProcRec.proc; 520 process->globalLangProcRec.proc = proc; 521 process->globalLangProcRec.closure = closure; 522 app = process->appContextList; 523 while (app) { 524 app->langProcRec.proc = proc; 525 app->langProcRec.closure = closure; 526 app = app->next; 527 } 528 UNLOCK_PROCESS; 529 } 530 return (old ? old : _XtDefaultLanguageProc); 531} 532 533XrmDatabase 534XtScreenDatabase(Screen *screen) 535{ 536 int scrno; 537 Bool doing_def; 538 XrmDatabase db, olddb; 539 XtPerDisplay pd; 540 Status do_fallback; 541 char *scr_resources; 542 Display *dpy = DisplayOfScreen(screen); 543 544 DPY_TO_APPCON(dpy); 545 if (dpy == NULL) { 546 XtErrorMsg("nullDisplay", 547 "XtScreenDatabase", XtCXtToolkitError, 548 "XtScreenDatabase requires a non-NULL display", 549 NULL, NULL); 550 } 551 552 LOCK_APP(app); 553 LOCK_PROCESS; 554 if (screen == DefaultScreenOfDisplay(dpy)) { 555 scrno = DefaultScreen(dpy); 556 doing_def = True; 557 } 558 else { 559 scrno = XScreenNumberOfScreen(screen); 560 doing_def = False; 561 } 562 pd = _XtGetPerDisplay(dpy); 563 if ((db = pd->per_screen_db[scrno])) { 564 UNLOCK_PROCESS; 565 UNLOCK_APP(app); 566 return (doing_def ? XrmGetDatabase(dpy) : db); 567 } 568 scr_resources = XScreenResourceString(screen); 569 570 if (ScreenCount(dpy) == 1) { 571 db = pd->cmd_db; 572 pd->cmd_db = NULL; 573 } 574 else { 575 db = CopyDB(pd->cmd_db); 576 } 577 { /* Environment defaults */ 578 char filenamebuf[PATH_MAX]; 579 char *filename; 580 581 if (!(filename = getenv("XENVIRONMENT"))) { 582 int len; 583 584#ifdef __MINGW32__ 585 const char *slashDotXdefaultsDash = "/Xdefaults-"; 586#else 587 const char *slashDotXdefaultsDash = "/.Xdefaults-"; 588#endif 589 590 (void) GetRootDirName(filename = filenamebuf, 591 PATH_MAX - 592 (int) strlen(slashDotXdefaultsDash) - 1); 593 (void) strcat(filename, slashDotXdefaultsDash); 594 len = (int) strlen(filename); 595 GetHostname(filename + len, PATH_MAX - len); 596 } 597 (void) XrmCombineFileDatabase(filename, &db, False); 598 } 599 if (scr_resources) { /* Screen defaults */ 600 XrmCombineDatabase(XrmGetStringDatabase(scr_resources), &db, False); 601 XFree(scr_resources); 602 } 603 /* Server or host defaults */ 604 if (!pd->server_db) 605 CombineUserDefaults(dpy, &db); 606 else { 607 (void) XrmCombineDatabase(pd->server_db, &db, False); 608 pd->server_db = NULL; 609 } 610 611 if (!db) 612 db = XrmGetStringDatabase(""); 613 pd->per_screen_db[scrno] = db; 614 olddb = XrmGetDatabase(dpy); 615 /* set database now, for XtResolvePathname to use */ 616 XrmSetDatabase(dpy, db); 617 CombineAppUserDefaults(dpy, &db); 618 do_fallback = 1; 619 { /* System app-defaults */ 620 char *filename; 621 622 if ((filename = XtResolvePathname(dpy, "app-defaults", 623 NULL, NULL, NULL, NULL, 0, NULL))) { 624 do_fallback = !XrmCombineFileDatabase(filename, &db, False); 625 XtFree(filename); 626 } 627 } 628 /* now restore old database, if need be */ 629 if (!doing_def) 630 XrmSetDatabase(dpy, olddb); 631 if (do_fallback && pd->appContext->fallback_resources) { /* Fallback defaults */ 632 XrmDatabase fdb = NULL; 633 String *res; 634 635 for (res = pd->appContext->fallback_resources; *res; res++) 636 XrmPutLineResource(&fdb, *res); 637 (void) XrmCombineDatabase(fdb, &db, False); 638 } 639 UNLOCK_PROCESS; 640 UNLOCK_APP(app); 641 return db; 642} 643 644/* 645 * Merge two option tables, allowing the second to over-ride the first, 646 * so that ambiguous abbreviations can be noticed. The merge attempts 647 * to make the resulting table lexicographically sorted, but succeeds 648 * only if the first source table is sorted. Though it _is_ recommended 649 * (for optimizations later in XrmParseCommand), it is not required 650 * that either source table be sorted. 651 * 652 * Caller is responsible for freeing the returned option table. 653 */ 654 655static void 656_MergeOptionTables(const XrmOptionDescRec *src1, 657 Cardinal num_src1, 658 const XrmOptionDescRec *src2, 659 Cardinal num_src2, 660 XrmOptionDescRec **dst, 661 Cardinal *num_dst) 662{ 663 XrmOptionDescRec *table, *endP; 664 XrmOptionDescRec *opt1, *dstP; 665 const XrmOptionDescRec *opt2; 666 int i1; 667 Cardinal i2; 668 int dst_len, order; 669 enum { Check, NotSorted, IsSorted } sort_order = Check; 670 671 *dst = table = (XrmOptionDescRec *) 672 __XtMalloc((Cardinal) 673 (sizeof(XrmOptionDescRec) * (num_src1 + num_src2))); 674 675 (void) memmove(table, src1, sizeof(XrmOptionDescRec) * num_src1); 676 if (num_src2 == 0) { 677 *num_dst = num_src1; 678 return; 679 } 680 endP = &table[dst_len = (int) num_src1]; 681 for (opt2 = src2, i2 = 0; i2 < num_src2; opt2++, i2++) { 682 XrmOptionDescRec *whereP; 683 Boolean found; 684 685 found = False; 686 whereP = endP - 1; /* assume new option goes at the end */ 687 for (opt1 = table, i1 = 0; i1 < dst_len; opt1++, i1++) { 688 /* have to walk the entire new table so new list is ordered 689 (if src1 was ordered) */ 690 if (sort_order == Check && i1 > 0 691 && strcmp(opt1->option, (opt1 - 1)->option) < 0) 692 sort_order = NotSorted; 693 if ((order = strcmp(opt1->option, opt2->option)) == 0) { 694 /* same option names; just overwrite opt1 with opt2 */ 695 *opt1 = *opt2; 696 found = True; 697 break; 698 } 699 /* else */ 700 if (sort_order == IsSorted && order > 0) { 701 /* insert before opt1 to preserve order */ 702 /* shift rest of table forward to make room for new entry */ 703 for (dstP = endP++; dstP > opt1; dstP--) 704 *dstP = *(dstP - 1); 705 *opt1 = *opt2; 706 dst_len++; 707 found = True; 708 break; 709 } 710 /* else */ 711 if (order < 0) 712 /* opt2 sorts after opt1, so remember this position */ 713 whereP = opt1; 714 } 715 if (sort_order == Check && i1 == dst_len) 716 sort_order = IsSorted; 717 if (!found) { 718 /* when we get here, whereP points to the last entry in the 719 destination that sorts before "opt2". Shift rest of table 720 forward and insert "opt2" after whereP. */ 721 whereP++; 722 for (dstP = endP++; dstP > whereP; dstP--) 723 *dstP = *(dstP - 1); 724 *whereP = *opt2; 725 dst_len++; 726 } 727 } 728 *num_dst = (Cardinal) dst_len; 729} 730 731/* NOTE: name, class, and type must be permanent strings */ 732static Boolean 733_GetResource(Display *dpy, 734 XrmSearchList list, 735 String name, 736 String class, 737 String type, 738 XrmValue *value) 739{ 740 XrmRepresentation db_type; 741 XrmValue db_value; 742 XrmName Qname = XrmPermStringToQuark(name); 743 XrmClass Qclass = XrmPermStringToQuark(class); 744 XrmRepresentation Qtype = XrmPermStringToQuark(type); 745 746 if (XrmQGetSearchResource(list, Qname, Qclass, &db_type, &db_value)) { 747 if (db_type == Qtype) { 748 if (Qtype == _XtQString) 749 *(String *) value->addr = db_value.addr; 750 else 751 (void) memmove(value->addr, db_value.addr, value->size); 752 return True; 753 } 754 else { 755 WidgetRec widget; /* hack, hack */ 756 757 memset(&widget, 0, sizeof(widget)); 758 widget.core.self = &widget; 759 widget.core.widget_class = coreWidgetClass; 760 widget.core.screen = (Screen *) DefaultScreenOfDisplay(dpy); 761 XtInitializeWidgetClass(coreWidgetClass); 762 if (_XtConvert(&widget, db_type, &db_value, Qtype, value, NULL)) { 763 return True; 764 } 765 } 766 } 767 return False; 768} 769 770XrmDatabase 771_XtPreparseCommandLine(XrmOptionDescRec *urlist, 772 Cardinal num_urs, 773 int argc, 774 _XtString *argv, /* return */ 775 String *applName, 776 String *displayName, 777 String *language) 778{ 779 XrmDatabase db = NULL; 780 XrmOptionDescRec *options; 781 Cardinal num_options; 782 XrmName name_list[3]; 783 XrmName class_list[3]; 784 XrmRepresentation type; 785 XrmValue val; 786 _XtString *targv; 787 int targc = argc; 788 789 targv = (_XtString *) 790 __XtMalloc((Cardinal) (sizeof(_XtString *) * (size_t) argc)); 791 (void) memmove(targv, argv, sizeof(char *) * (size_t) argc); 792 _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs, 793 &options, &num_options); 794 name_list[0] = class_list[0] = XrmPermStringToQuark("."); 795 name_list[2] = class_list[2] = NULLQUARK; 796 XrmParseCommand(&db, options, (int) num_options, ".", &targc, targv); 797 if (applName) { 798 name_list[1] = XrmPermStringToQuark("name"); 799 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 800 type == _XtQString) 801 *applName = val.addr; 802 } 803 if (displayName) { 804 name_list[1] = XrmPermStringToQuark("display"); 805 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 806 type == _XtQString) 807 *displayName = val.addr; 808 } 809 if (language) { 810 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 811 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 812 if (XrmQGetResource(db, name_list, class_list, &type, &val) && 813 type == _XtQString) 814 *language = val.addr; 815 } 816 817 XtFree((char *) targv); 818 XtFree((char *) options); 819 return db; 820} 821 822static void 823GetLanguage(Display *dpy, XtPerDisplay pd) 824{ 825 XrmRepresentation type; 826 XrmValue value; 827 XrmName name_list[3]; 828 XrmName class_list[3]; 829 830 LOCK_PROCESS; 831 if (!pd->language) { 832 name_list[0] = pd->name; 833 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 834 class_list[0] = pd->class; 835 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 836 name_list[2] = class_list[2] = NULLQUARK; 837 if (!pd->server_db) 838 CombineUserDefaults(dpy, &pd->server_db); 839 if (pd->server_db && 840 XrmQGetResource(pd->server_db, name_list, class_list, &type, &value) 841 && type == _XtQString) 842 pd->language = (char *) value.addr; 843 } 844 845 if (pd->appContext->langProcRec.proc) { 846 if (!pd->language) 847 pd->language = ""; 848 pd->language = (*pd->appContext->langProcRec.proc) 849 (dpy, pd->language, pd->appContext->langProcRec.closure); 850 } 851 else if (!pd->language || pd->language[0] == '\0') /* R4 compatibility */ 852 pd->language = getenv("LANG"); 853 854 if (pd->language) 855 pd->language = XtNewString(pd->language); 856 UNLOCK_PROCESS; 857} 858 859static void 860ProcessInternalConnection(XtPointer client_data, 861 int *fd, 862 XtInputId *id _X_UNUSED) 863{ 864 XProcessInternalConnection((Display *) client_data, *fd); 865} 866 867static void 868ConnectionWatch(Display *dpy, 869 XPointer client_data, 870 int fd, 871 Bool opening, 872 XPointer *watch_data) 873{ 874 XtInputId *iptr; 875 XtAppContext app = XtDisplayToApplicationContext(dpy); 876 877 if (opening) { 878 iptr = (XtInputId *) __XtMalloc(sizeof(XtInputId)); 879 *iptr = XtAppAddInput(app, fd, (XtPointer) XtInputReadMask, 880 ProcessInternalConnection, client_data); 881 *watch_data = (XPointer) iptr; 882 } 883 else { 884 iptr = (XtInputId *) *watch_data; 885 XtRemoveInput(*iptr); 886 (void) XtFree(*watch_data); 887 } 888} 889 890void 891_XtDisplayInitialize(Display *dpy, 892 XtPerDisplay pd, 893 _Xconst char *name, 894 XrmOptionDescRec *urlist, 895 Cardinal num_urs, 896 int *argc, 897 char **argv) 898{ 899 Boolean tmp_bool; 900 XrmValue value; 901 XrmOptionDescRec *options; 902 Cardinal num_options; 903 XrmDatabase db; 904 XrmName name_list[2]; 905 XrmClass class_list[2]; 906 XrmHashTable *search_list; 907 int search_list_size = SEARCH_LIST_SIZE; 908 909 GetLanguage(dpy, pd); 910 911 /* Parse the command line and remove Xt arguments from argv */ 912 _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs, 913 &options, &num_options); 914 XrmParseCommand(&pd->cmd_db, options, (int) num_options, name, argc, argv); 915 916 db = XtScreenDatabase(DefaultScreenOfDisplay(dpy)); 917 918 if (!(search_list = (XrmHashTable *) 919 ALLOCATE_LOCAL(SEARCH_LIST_SIZE * sizeof(XrmHashTable)))) 920 _XtAllocError(NULL); 921 name_list[0] = pd->name; 922 class_list[0] = pd->class; 923 name_list[1] = NULLQUARK; 924 class_list[1] = NULLQUARK; 925 926 while (!XrmQGetSearchList(db, name_list, class_list, 927 search_list, search_list_size)) { 928 XrmHashTable *old = search_list; 929 Cardinal size = 930 (Cardinal) ((size_t) (search_list_size *= 2) * 931 sizeof(XrmHashTable)); 932 if (!(search_list = (XrmHashTable *) ALLOCATE_LOCAL(size))) 933 _XtAllocError(NULL); 934 (void) memmove((char *) search_list, (char *) old, (size >> 1)); 935 DEALLOCATE_LOCAL(old); 936 } 937 938 value.size = sizeof(tmp_bool); 939 value.addr = (XtPointer) &tmp_bool; 940 if (_GetResource(dpy, search_list, "synchronous", "Synchronous", 941 XtRBoolean, &value)) { 942 int i; 943 Display **dpyP = pd->appContext->list; 944 945 pd->appContext->sync = tmp_bool; 946 for (i = pd->appContext->count; i; dpyP++, i--) { 947 (void) XSynchronize(*dpyP, (Bool) tmp_bool); 948 } 949 } 950 else { 951 (void) XSynchronize(dpy, (Bool) pd->appContext->sync); 952 } 953 954 if (_GetResource(dpy, search_list, "reverseVideo", "ReverseVideo", 955 XtRBoolean, &value) 956 && tmp_bool) { 957 pd->rv = True; 958 } 959 960 value.size = sizeof(pd->multi_click_time); 961 value.addr = (XtPointer) &pd->multi_click_time; 962 if (!_GetResource(dpy, search_list, 963 "multiClickTime", "MultiClickTime", XtRInt, &value)) { 964 pd->multi_click_time = 200; 965 } 966 967 value.size = sizeof(pd->appContext->selectionTimeout); 968 value.addr = (XtPointer) &pd->appContext->selectionTimeout; 969 (void) _GetResource(dpy, search_list, 970 "selectionTimeout", "SelectionTimeout", XtRInt, &value); 971 972#ifndef NO_IDENTIFY_WINDOWS 973 value.size = sizeof(pd->appContext->identify_windows); 974 value.addr = (XtPointer) &pd->appContext->identify_windows; 975 (void) _GetResource(dpy, search_list, 976 "xtIdentifyWindows", "XtDebug", XtRBoolean, &value); 977#endif 978 979 XAddConnectionWatch(dpy, ConnectionWatch, (XPointer) dpy); 980 981 XtFree((XtPointer) options); 982 DEALLOCATE_LOCAL(search_list); 983} 984 985/* Function Name: XtAppSetFallbackResources 986 * Description: Sets the fallback resource list that will be loaded 987 * at display initialization time. 988 * Arguments: app_context - the app context. 989 * specification_list - the resource specification list. 990 * Returns: none. 991 */ 992 993void 994XtAppSetFallbackResources(XtAppContext app_context, String *specification_list) 995{ 996 LOCK_APP(app_context); 997 app_context->fallback_resources = specification_list; 998 UNLOCK_APP(app_context); 999} 1000 1001Widget 1002XtOpenApplication(XtAppContext *app_context_return, 1003 _Xconst char *application_class, 1004 XrmOptionDescRec *options, 1005 Cardinal num_options, 1006 int *argc_in_out, 1007 _XtString *argv_in_out, 1008 String *fallback_resources, 1009 WidgetClass widget_class, 1010 ArgList args_in, 1011 Cardinal num_args_in) 1012{ 1013 XtAppContext app_con; 1014 Display *dpy; 1015 register int saved_argc = *argc_in_out; 1016 Widget root; 1017 Arg args[3], *merged_args; 1018 Cardinal num = 0; 1019 1020 XtToolkitInitialize(); /* cannot be moved into _XtAppInit */ 1021 1022 dpy = _XtAppInit(&app_con, (String) application_class, options, num_options, 1023 argc_in_out, &argv_in_out, fallback_resources); 1024 1025 LOCK_APP(app_con); 1026 XtSetArg(args[num], XtNscreen, DefaultScreenOfDisplay(dpy)); 1027 num++; 1028 XtSetArg(args[num], XtNargc, saved_argc); 1029 num++; 1030 XtSetArg(args[num], XtNargv, argv_in_out); 1031 num++; 1032 1033 merged_args = XtMergeArgLists(args_in, num_args_in, args, num); 1034 num += num_args_in; 1035 1036 root = XtAppCreateShell(NULL, application_class, widget_class, dpy, 1037 merged_args, num); 1038 1039 if (app_context_return) 1040 *app_context_return = app_con; 1041 1042 XtFree((XtPointer) merged_args); 1043 XtFree((XtPointer) argv_in_out); 1044 UNLOCK_APP(app_con); 1045 return root; 1046} 1047 1048Widget 1049XtAppInitialize(XtAppContext *app_context_return, 1050 _Xconst char *application_class, 1051 XrmOptionDescRec *options, 1052 Cardinal num_options, 1053 int *argc_in_out, 1054 _XtString *argv_in_out, 1055 String *fallback_resources, 1056 ArgList args_in, 1057 Cardinal num_args_in) 1058{ 1059 return XtOpenApplication(app_context_return, application_class, 1060 options, num_options, 1061 argc_in_out, argv_in_out, fallback_resources, 1062 applicationShellWidgetClass, args_in, num_args_in); 1063} 1064 1065Widget 1066XtInitialize(_Xconst _XtString name _X_UNUSED, 1067 _Xconst _XtString classname, 1068 XrmOptionDescRec *options, 1069 Cardinal num_options, 1070 int *argc, 1071 _XtString *argv) 1072{ 1073 Widget root; 1074 XtAppContext app_con; 1075 register ProcessContext process = _XtGetProcessContext(); 1076 1077 root = XtAppInitialize(&app_con, classname, options, num_options, 1078 argc, argv, NULL, NULL, (Cardinal) 0); 1079 1080 LOCK_PROCESS; 1081 process->defaultAppContext = app_con; 1082 UNLOCK_PROCESS; 1083 return root; 1084} 1085