Initialize.c revision 339a7c43
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 129static XrmOptionDescRec const opTable[] = { 130{"+rv", "*reverseVideo", XrmoptionNoArg, (XtPointer) "off"}, 131{"+synchronous","*synchronous", XrmoptionNoArg, (XtPointer) "off"}, 132{"-background", "*background", XrmoptionSepArg, (XtPointer) NULL}, 133{"-bd", "*borderColor", XrmoptionSepArg, (XtPointer) NULL}, 134{"-bg", "*background", XrmoptionSepArg, (XtPointer) NULL}, 135{"-bordercolor","*borderColor", XrmoptionSepArg, (XtPointer) NULL}, 136{"-borderwidth",".borderWidth", XrmoptionSepArg, (XtPointer) NULL}, 137{"-bw", ".borderWidth", XrmoptionSepArg, (XtPointer) NULL}, 138{"-display", ".display", XrmoptionSepArg, (XtPointer) NULL}, 139{"-fg", "*foreground", XrmoptionSepArg, (XtPointer) NULL}, 140{"-fn", "*font", XrmoptionSepArg, (XtPointer) NULL}, 141{"-font", "*font", XrmoptionSepArg, (XtPointer) NULL}, 142{"-foreground", "*foreground", XrmoptionSepArg, (XtPointer) NULL}, 143{"-geometry", ".geometry", XrmoptionSepArg, (XtPointer) NULL}, 144{"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "on"}, 145{"-name", ".name", XrmoptionSepArg, (XtPointer) NULL}, 146{"-reverse", "*reverseVideo", XrmoptionNoArg, (XtPointer) "on"}, 147{"-rv", "*reverseVideo", XrmoptionNoArg, (XtPointer) "on"}, 148{"-selectionTimeout", 149 ".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 157 158/* 159 * GetHostname - emulates gethostname() on non-bsd systems. 160 */ 161 162static void GetHostname ( 163 char *buf, 164 int maxlen) 165{ 166#ifdef USE_UNAME 167 int len; 168 struct utsname name; 169 170 if (maxlen <= 0 || buf == NULL) 171 return; 172 173 uname (&name); 174 len = strlen (name.nodename); 175 if (len >= maxlen) 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, maxlen); 184 buf [maxlen - 1] = '\0'; 185#endif 186} 187 188 189#ifdef SUNSHLIB 190void _XtInherit(void) 191{ 192 extern void __XtInherit(); 193 __XtInherit(); 194} 195#define _XtInherit __XtInherit 196#endif 197 198 199#if defined (WIN32) || defined(__CYGWIN__) 200/* 201 * The Symbol _XtInherit is used in two different manners. 202 * First it could be used as a generic function and second 203 * as an absolute address reference, which will be used to 204 * check the initialisation process of several other libraries. 205 * Because of this the symbol must be accessable by all 206 * client dll's and applications. In unix environments 207 * this is no problem, because the used shared libraries 208 * format (elf) supports this immediatly. Under Windows 209 * this isn't true, because a functions address in a dll 210 * is different from the same function in another dll or 211 * applications, because the used Portable Executable 212 * File adds a code stub to each client to provide the 213 * exported symbol name. This stub uses an indirect 214 * pointer to get the original symbol address, which is 215 * then jumped to, like in this example: 216 * 217 * --- client --- --- dll ---- 218 * ... 219 * call foo 220 * 221 * foo: jmp (*_imp_foo) ----> foo: .... 222 * nop 223 * nop 224 * 225 * _imp_foo: .long <index of foo in dll export table, is 226 * set to the real address by the runtime linker> 227 * 228 * Now it is clear why the clients symbol foo isn't the same 229 * as in the dll and we can think about how to deal which 230 * this two above mentioned requirements, to export this 231 * symbol to all clients and to allow calling this symbol 232 * as a function. The solution I've used exports the 233 * symbol _XtInherit as data symbol, because global data 234 * symbols are exported to all clients. But how to deal 235 * with the second requirement, that this symbol should 236 * be used as function. The Trick is to build a little 237 * code stub in the data section in the exact manner as 238 * above explained. This is done with the assembler code 239 * below. 240 * 241 * Ralf Habacker 242 * 243 * References: 244 * msdn http://msdn.microsoft.com/msdnmag/issues/02/02/PE/PE.asp 245 * cygwin-xfree: http://www.cygwin.com/ml/cygwin-xfree/2003-10/msg00000.html 246 */ 247 248#ifdef __x86_64__ 249asm (".section .trampoline, \"dwx\" \n\ 250 .globl _XtInherit \n\ 251 _XtInherit: \n\ 252 jmp *_y(%rip) \n\ 253_y: .quad __XtInherit \n\ 254 .text \n"); 255#else 256asm (".data\n\ 257 .globl __XtInherit \n\ 258 __XtInherit: jmp *_y \n\ 259 _y: .long ___XtInherit \n\ 260 .text \n"); 261#endif 262 263#define _XtInherit __XtInherit 264#endif 265 266 267void _XtInherit(void) 268{ 269 XtErrorMsg("invalidProcedure","inheritanceProc",XtCXtToolkitError, 270 "Unresolved inheritance operation", 271 (String *)NULL, (Cardinal *)NULL); 272} 273 274 275void XtToolkitInitialize(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 302 303String _XtGetUserName( 304 String dest, 305 int len) 306{ 307#ifdef WIN32 308 String ptr = NULL; 309 310 if ((ptr = getenv("USERNAME"))) { 311 (void) strncpy (dest, ptr, len-1); 312 dest[len-1] = '\0'; 313 } else 314 *dest = '\0'; 315#else 316#ifdef X_NEEDS_PWPARAMS 317 _Xgetpwparams pwparams; 318#endif 319 struct passwd *pw; 320 char* ptr; 321 322 if ((ptr = getenv("USER"))) { 323 (void) strncpy (dest, ptr, len-1); 324 dest[len-1] = '\0'; 325 } else { 326 if ((pw = _XGetpwuid(getuid(),pwparams)) != NULL) { 327 (void) strncpy (dest, pw->pw_name, len-1); 328 dest[len-1] = '\0'; 329 } else 330 *dest = '\0'; 331 } 332#endif 333 return dest; 334} 335 336 337static String GetRootDirName( 338 String dest, 339 int len) 340{ 341#ifdef WIN32 342 register char *ptr1; 343 register char *ptr2 = NULL; 344 int len1 = 0, len2 = 0; 345 346 if (ptr1 = getenv("HOME")) { /* old, deprecated */ 347 len1 = strlen (ptr1); 348 } else if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) { 349 len1 = strlen (ptr1); 350 len2 = strlen (ptr2); 351 } else if (ptr2 = getenv("USERNAME")) { 352 len1 = strlen (ptr1 = "/users/"); 353 len2 = strlen (ptr2); 354 } 355 if ((len1 + len2 + 1) < len) 356 sprintf (dest, "%s%s", ptr1, (ptr2) ? ptr2 : ""); 357 else 358 *dest = '\0'; 359#else 360#ifdef X_NEEDS_PWPARAMS 361 _Xgetpwparams pwparams; 362#endif 363 struct passwd *pw; 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, len-1); 371 dest[len-1] = '\0'; 372 } else { 373 if ((ptr = getenv("USER"))) 374 pw = _XGetpwnam(ptr,pwparams); 375 else 376 pw = _XGetpwuid(getuid(),pwparams); 377 if (pw != NULL) { 378 (void) strncpy (dest, pw->pw_dir, len-1); 379 dest[len-1] = '\0'; 380 } else 381 *dest = '\0'; 382 } 383#endif 384 return dest; 385} 386 387static void CombineAppUserDefaults( 388 Display *dpy, 389 XrmDatabase *pdb) 390{ 391 char* filename; 392 char* path = NULL; 393 Boolean deallocate = False; 394 395 if (!(path = getenv("XUSERFILESEARCHPATH"))) { 396#if !defined(WIN32) || !defined(__MINGW32__) 397 char *old_path; 398 char homedir[PATH_MAX]; 399 GetRootDirName(homedir, PATH_MAX); 400 if (!(old_path = getenv("XAPPLRESDIR"))) { 401 XtAsprintf(&path, 402 "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N", 403 homedir, homedir, homedir, homedir, homedir, homedir); 404 } else { 405 XtAsprintf(&path, 406 "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N", 407 old_path, old_path, old_path, homedir, 408 old_path, old_path, old_path, homedir); 409 } 410 deallocate = True; 411#endif 412 } 413 414 filename = XtResolvePathname(dpy, NULL, NULL, NULL, path, NULL, 0, NULL); 415 if (filename) { 416 (void)XrmCombineFileDatabase(filename, pdb, False); 417 XtFree(filename); 418 } 419 420 if (deallocate) 421 XtFree(path); 422} 423 424static void CombineUserDefaults( 425 Display *dpy, 426 XrmDatabase *pdb) 427{ 428#ifdef __MINGW32__ 429 const char *slashDotXdefaults = "/Xdefaults"; 430#else 431 const char *slashDotXdefaults = "/.Xdefaults"; 432#endif 433 char *dpy_defaults = XResourceManagerString(dpy); 434 435 if (dpy_defaults) { 436 XrmCombineDatabase(XrmGetStringDatabase(dpy_defaults), pdb, False); 437 } else { 438 char filename[PATH_MAX]; 439 (void) GetRootDirName(filename, 440 PATH_MAX - strlen (slashDotXdefaults) - 1); 441 (void) strcat(filename, slashDotXdefaults); 442 (void)XrmCombineFileDatabase(filename, pdb, False); 443 } 444} 445 446/*ARGSUSED*/ 447static Bool StoreDBEntry( 448 XrmDatabase *db, 449 XrmBindingList bindings, 450 XrmQuarkList quarks, 451 XrmRepresentation *type, 452 XrmValuePtr value, 453 XPointer data) 454{ 455 XrmQPutResource((XrmDatabase *)data, bindings, quarks, *type, value); 456 return False; 457} 458 459static XrmDatabase CopyDB(XrmDatabase db) 460{ 461 XrmDatabase copy = NULL; 462 XrmQuark empty = NULLQUARK; 463 464 XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels, 465 StoreDBEntry, (XPointer)©); 466 return copy; 467} 468 469/*ARGSUSED*/ 470static String _XtDefaultLanguageProc( 471 Display *dpy, /* unused */ 472 String xnl, 473 XtPointer closure) /* unused */ 474{ 475 if (! setlocale(LC_ALL, xnl)) 476 XtWarning("locale not supported by C library, locale unchanged"); 477 478 if (! XSupportsLocale()) { 479 XtWarning("locale not supported by Xlib, locale set to C"); 480 setlocale(LC_ALL, "C"); 481 } 482 if (! XSetLocaleModifiers("")) 483 XtWarning("X locale modifiers not supported, using default"); 484 485 return setlocale(LC_ALL, NULL); /* re-query in case overwritten */ 486} 487 488XtLanguageProc XtSetLanguageProc( 489 XtAppContext app, 490 XtLanguageProc proc, 491 XtPointer closure) 492{ 493 XtLanguageProc old; 494 495 if (!proc) { 496 proc = _XtDefaultLanguageProc; 497 closure = NULL; 498 } 499 500 if (app) { 501 LOCK_APP(app); 502 LOCK_PROCESS; 503 /* set langProcRec only for this application context */ 504 old = app->langProcRec.proc; 505 app->langProcRec.proc = proc; 506 app->langProcRec.closure = closure; 507 UNLOCK_PROCESS; 508 UNLOCK_APP(app); 509 } else { 510 /* set langProcRec for all application contexts */ 511 ProcessContext process; 512 513 LOCK_PROCESS; 514 process = _XtGetProcessContext(); 515 old = process->globalLangProcRec.proc; 516 process->globalLangProcRec.proc = proc; 517 process->globalLangProcRec.closure = closure; 518 app = process->appContextList; 519 while (app) { 520 app->langProcRec.proc = proc; 521 app->langProcRec.closure = closure; 522 app = app->next; 523 } 524 UNLOCK_PROCESS; 525 } 526 return (old ? old : _XtDefaultLanguageProc); 527} 528 529XrmDatabase XtScreenDatabase( 530 Screen *screen) 531{ 532 int scrno; 533 Bool doing_def; 534 XrmDatabase db, olddb; 535 XtPerDisplay pd; 536 Status do_fallback; 537 char *scr_resources; 538 Display *dpy = DisplayOfScreen(screen); 539 DPY_TO_APPCON(dpy); 540 541 LOCK_APP(app); 542 LOCK_PROCESS; 543 if (screen == DefaultScreenOfDisplay(dpy)) { 544 scrno = DefaultScreen(dpy); 545 doing_def = True; 546 } else { 547 scrno = XScreenNumberOfScreen(screen); 548 doing_def = False; 549 } 550 pd = _XtGetPerDisplay(dpy); 551 if ((db = pd->per_screen_db[scrno])) { 552 UNLOCK_PROCESS; 553 UNLOCK_APP(app); 554 return (doing_def ? XrmGetDatabase(dpy) : db); 555 } 556 scr_resources = XScreenResourceString(screen); 557 558 if (ScreenCount(dpy) == 1) { 559 db = pd->cmd_db; 560 pd->cmd_db = NULL; 561 } else { 562 db = CopyDB(pd->cmd_db); 563 } 564 { /* Environment defaults */ 565 char filenamebuf[PATH_MAX]; 566 char *filename; 567 568 if (!(filename = getenv("XENVIRONMENT"))) { 569 int len; 570#ifdef __MINGW32__ 571 const char *slashDotXdefaultsDash = "/Xdefaults-"; 572#else 573 const char *slashDotXdefaultsDash = "/.Xdefaults-"; 574#endif 575 576 (void) GetRootDirName(filename = filenamebuf, 577 PATH_MAX - strlen (slashDotXdefaultsDash) - 1); 578 (void) strcat(filename, slashDotXdefaultsDash); 579 len = strlen(filename); 580 GetHostname (filename+len, PATH_MAX-len); 581 } 582 (void)XrmCombineFileDatabase(filename, &db, False); 583 } 584 if (scr_resources) 585 { /* Screen defaults */ 586 XrmCombineDatabase(XrmGetStringDatabase(scr_resources), &db, False); 587 XFree(scr_resources); 588 } 589 /* Server or host defaults */ 590 if (!pd->server_db) 591 CombineUserDefaults(dpy, &db); 592 else { 593 (void) XrmCombineDatabase(pd->server_db, &db, False); 594 pd->server_db = NULL; 595 } 596 597 if (!db) 598 db = XrmGetStringDatabase(""); 599 pd->per_screen_db[scrno] = db; 600 olddb = XrmGetDatabase(dpy); 601 /* set database now, for XtResolvePathname to use */ 602 XrmSetDatabase(dpy, db); 603 CombineAppUserDefaults(dpy, &db); 604 do_fallback = 1; 605 { /* System app-defaults */ 606 char *filename; 607 608 if ((filename = XtResolvePathname(dpy, "app-defaults", 609 NULL, NULL, NULL, NULL, 0, NULL))) { 610 do_fallback = !XrmCombineFileDatabase(filename, &db, False); 611 XtFree(filename); 612 } 613 } 614 /* now restore old database, if need be */ 615 if (!doing_def) 616 XrmSetDatabase(dpy, olddb); 617 if (do_fallback && pd->appContext->fallback_resources) 618 { /* Fallback defaults */ 619 XrmDatabase fdb = NULL; 620 String *res; 621 622 for (res = pd->appContext->fallback_resources; *res; res++) 623 XrmPutLineResource(&fdb, *res); 624 (void)XrmCombineDatabase(fdb, &db, False); 625 } 626 UNLOCK_PROCESS; 627 UNLOCK_APP(app); 628 return db; 629} 630 631/* 632 * Merge two option tables, allowing the second to over-ride the first, 633 * so that ambiguous abbreviations can be noticed. The merge attempts 634 * to make the resulting table lexicographically sorted, but succeeds 635 * only if the first source table is sorted. Though it _is_ recommended 636 * (for optimizations later in XrmParseCommand), it is not required 637 * that either source table be sorted. 638 * 639 * Caller is responsible for freeing the returned option table. 640 */ 641 642static void _MergeOptionTables( 643 const XrmOptionDescRec *src1, 644 Cardinal num_src1, 645 const XrmOptionDescRec *src2, 646 Cardinal num_src2, 647 XrmOptionDescRec **dst, 648 Cardinal *num_dst) 649{ 650 XrmOptionDescRec *table, *endP; 651 register XrmOptionDescRec *opt1, *whereP, *dstP; 652 register const XrmOptionDescRec *opt2; 653 int i1; 654 Cardinal i2; 655 int dst_len, order; 656 Boolean found; 657 enum {Check, NotSorted, IsSorted} sort_order = Check; 658 659 *dst = table = (XrmOptionDescRec*) 660 __XtMalloc( sizeof(XrmOptionDescRec) * (num_src1 + num_src2) ); 661 662 (void) memmove(table, src1, sizeof(XrmOptionDescRec) * num_src1 ); 663 if (num_src2 == 0) { 664 *num_dst = num_src1; 665 return; 666 } 667 endP = &table[dst_len = num_src1]; 668 for (opt2 = src2, i2= 0; i2 < num_src2; opt2++, i2++) { 669 found = False; 670 whereP = endP-1; /* assume new option goes at the end */ 671 for (opt1 = table, i1 = 0; i1 < dst_len; opt1++, i1++) { 672 /* have to walk the entire new table so new list is ordered 673 (if src1 was ordered) */ 674 if (sort_order == Check && i1 > 0 675 && strcmp(opt1->option, (opt1-1)->option) < 0) 676 sort_order = NotSorted; 677 if ((order = strcmp(opt1->option, opt2->option)) == 0) { 678 /* same option names; just overwrite opt1 with opt2 */ 679 *opt1 = *opt2; 680 found = True; 681 break; 682 } 683 /* else */ 684 if (sort_order == IsSorted && order > 0) { 685 /* insert before opt1 to preserve order */ 686 /* shift rest of table forward to make room for new entry */ 687 for (dstP = endP++; dstP > opt1; dstP--) 688 *dstP = *(dstP-1); 689 *opt1 = *opt2; 690 dst_len++; 691 found = True; 692 break; 693 } 694 /* else */ 695 if (order < 0) 696 /* opt2 sorts after opt1, so remember this position */ 697 whereP = opt1; 698 } 699 if (sort_order == Check && i1 == dst_len) 700 sort_order = IsSorted; 701 if (!found) { 702 /* when we get here, whereP points to the last entry in the 703 destination that sorts before "opt2". Shift rest of table 704 forward and insert "opt2" after whereP. */ 705 whereP++; 706 for (dstP = endP++; dstP > whereP; dstP--) 707 *dstP = *(dstP-1); 708 *whereP = *opt2; 709 dst_len++; 710 } 711 } 712 *num_dst = dst_len; 713} 714 715 716/* NOTE: name, class, and type must be permanent strings */ 717static Boolean _GetResource( 718 Display *dpy, 719 XrmSearchList list, 720 String name, 721 String class, 722 String type, 723 XrmValue* value) 724{ 725 XrmRepresentation db_type; 726 XrmValue db_value; 727 XrmName Qname = XrmPermStringToQuark(name); 728 XrmClass Qclass = XrmPermStringToQuark(class); 729 XrmRepresentation Qtype = XrmPermStringToQuark(type); 730 731 if (XrmQGetSearchResource(list, Qname, Qclass, &db_type, &db_value)) { 732 if (db_type == Qtype) { 733 if (Qtype == _XtQString) 734 *(String*)value->addr = db_value.addr; 735 else 736 (void) memmove(value->addr, db_value.addr, value->size ); 737 return True; 738 } else { 739 WidgetRec widget; /* hack, hack */ 740 bzero( &widget, sizeof(widget) ); 741 widget.core.self = &widget; 742 widget.core.widget_class = coreWidgetClass; 743 widget.core.screen = (Screen*)DefaultScreenOfDisplay(dpy); 744 XtInitializeWidgetClass(coreWidgetClass); 745 if (_XtConvert(&widget,db_type,&db_value,Qtype,value,NULL)) { 746 return True; 747 } 748 } 749 } 750 return False; 751} 752 753XrmDatabase _XtPreparseCommandLine( 754 XrmOptionDescRec *urlist, 755 Cardinal num_urs, 756 int argc, 757 String *argv, 758 /* return */ 759 String *applName, 760 String *displayName, 761 String *language) 762{ 763 XrmDatabase db = NULL; 764 XrmOptionDescRec *options; 765 Cardinal num_options; 766 XrmName name_list[3]; 767 XrmName class_list[3]; 768 XrmRepresentation type; 769 XrmValue val; 770 String *targv; 771 int targc = argc; 772 773 targv = (String *) __XtMalloc(sizeof(char *) * argc); 774 (void) memmove(targv, argv, sizeof(char *) * argc); 775 _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs, 776 &options, &num_options); 777 name_list[0] = class_list[0] = XrmPermStringToQuark("."); 778 name_list[2] = class_list[2] = NULLQUARK; 779 XrmParseCommand(&db, options, num_options, ".", &targc, targv); 780 if (applName) { 781 name_list[1] = XrmPermStringToQuark("name"); 782 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 783 type == _XtQString) 784 *applName = val.addr; 785 } 786 if (displayName) { 787 name_list[1] = XrmPermStringToQuark("display"); 788 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 789 type == _XtQString) 790 *displayName = val.addr; 791 } 792 if (language) { 793 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 794 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 795 if (XrmQGetResource(db, name_list, class_list, &type, &val) && 796 type == _XtQString) 797 *language = val.addr; 798 } 799 800 XtFree((char *)targv); 801 XtFree((char *)options); 802 return db; 803} 804 805 806static void GetLanguage( 807 Display *dpy, 808 XtPerDisplay pd) 809{ 810 XrmRepresentation type; 811 XrmValue value; 812 XrmName name_list[3]; 813 XrmName class_list[3]; 814 815 LOCK_PROCESS; 816 if (! pd->language) { 817 name_list[0] = pd->name; 818 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 819 class_list[0] = pd->class; 820 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 821 name_list[2] = class_list[2] = NULLQUARK; 822 if (!pd->server_db) 823 CombineUserDefaults(dpy, &pd->server_db); 824 if (pd->server_db && 825 XrmQGetResource(pd->server_db,name_list,class_list, &type, &value) 826 && type == _XtQString) 827 pd->language = (char *) value.addr; 828 } 829 830 if (pd->appContext->langProcRec.proc) { 831 if (! pd->language) pd->language = ""; 832 pd->language = (*pd->appContext->langProcRec.proc) 833 (dpy, pd->language, pd->appContext->langProcRec.closure); 834 } 835 else if (! pd->language || pd->language[0] == '\0') /* R4 compatibility */ 836 pd->language = getenv("LANG"); 837 838 if (pd->language) pd->language = XtNewString(pd->language); 839 UNLOCK_PROCESS; 840} 841 842static void ProcessInternalConnection ( 843 XtPointer client_data, 844 int* fd, 845 XtInputId* id) 846{ 847 XProcessInternalConnection ((Display *) client_data, *fd); 848} 849 850static void ConnectionWatch ( 851 Display* dpy, 852 XPointer client_data, 853 int fd, 854 Bool opening, 855 XPointer* watch_data) 856{ 857 XtInputId* iptr; 858 XtAppContext app = XtDisplayToApplicationContext(dpy); 859 860 if (opening) { 861 iptr = (XtInputId *) __XtMalloc(sizeof(XtInputId)); 862 *iptr = XtAppAddInput(app, fd, (XtPointer) XtInputReadMask, 863 ProcessInternalConnection, client_data); 864 *watch_data = (XPointer) iptr; 865 } else { 866 iptr = (XtInputId *) *watch_data; 867 XtRemoveInput(*iptr); 868 (void) XtFree(*watch_data); 869 } 870} 871 872void _XtDisplayInitialize( 873 Display *dpy, 874 XtPerDisplay pd, 875 _Xconst char* name, 876 XrmOptionDescRec *urlist, 877 Cardinal num_urs, 878 int *argc, 879 char **argv) 880{ 881 Boolean tmp_bool; 882 XrmValue value; 883 XrmOptionDescRec *options; 884 Cardinal num_options; 885 XrmDatabase db; 886 XrmName name_list[2]; 887 XrmClass class_list[2]; 888 XrmHashTable* search_list; 889 int search_list_size = SEARCH_LIST_SIZE; 890 891 GetLanguage(dpy, pd); 892 893 /* Parse the command line and remove Xt arguments from argv */ 894 _MergeOptionTables( opTable, XtNumber(opTable), urlist, num_urs, 895 &options, &num_options ); 896 XrmParseCommand(&pd->cmd_db, options, num_options, name, argc, argv); 897 898 db = XtScreenDatabase(DefaultScreenOfDisplay(dpy)); 899 900 if (!(search_list = (XrmHashTable*) 901 ALLOCATE_LOCAL( SEARCH_LIST_SIZE*sizeof(XrmHashTable)))) 902 _XtAllocError(NULL); 903 name_list[0] = pd->name; 904 class_list[0] = pd->class; 905 name_list[1] = NULLQUARK; 906 class_list[1] = NULLQUARK; 907 908 while (!XrmQGetSearchList(db, name_list, class_list, 909 search_list, search_list_size)) { 910 XrmHashTable* old = search_list; 911 Cardinal size = (search_list_size*=2)*sizeof(XrmHashTable); 912 if (!(search_list = (XrmHashTable*)ALLOCATE_LOCAL(size))) 913 _XtAllocError(NULL); 914 (void) memmove((char*)search_list, (char*)old, (size>>1) ); 915 DEALLOCATE_LOCAL(old); 916 } 917 918 value.size = sizeof(tmp_bool); 919 value.addr = (XtPointer)&tmp_bool; 920 if (_GetResource(dpy, search_list, "synchronous", "Synchronous", 921 XtRBoolean, &value)) { 922 int i; 923 Display **dpyP = pd->appContext->list; 924 pd->appContext->sync = tmp_bool; 925 for (i = pd->appContext->count; i; dpyP++, i--) { 926 (void) XSynchronize(*dpyP, (Bool)tmp_bool); 927 } 928 } else { 929 (void) XSynchronize(dpy, (Bool)pd->appContext->sync); 930 } 931 932 if (_GetResource(dpy, search_list, "reverseVideo", "ReverseVideo", 933 XtRBoolean, &value) 934 && tmp_bool) { 935 pd->rv = True; 936 } 937 938 value.size = sizeof(pd->multi_click_time); 939 value.addr = (XtPointer)&pd->multi_click_time; 940 if (!_GetResource(dpy, search_list, 941 "multiClickTime", "MultiClickTime", 942 XtRInt, &value)) { 943 pd->multi_click_time = 200; 944 } 945 946 value.size = sizeof(pd->appContext->selectionTimeout); 947 value.addr = (XtPointer)&pd->appContext->selectionTimeout; 948 (void)_GetResource(dpy, search_list, 949 "selectionTimeout", "SelectionTimeout", 950 XtRInt, &value); 951 952#ifndef NO_IDENTIFY_WINDOWS 953 value.size = sizeof(pd->appContext->identify_windows); 954 value.addr = (XtPointer)&pd->appContext->identify_windows; 955 (void)_GetResource(dpy, search_list, 956 "xtIdentifyWindows", "XtDebug", 957 XtRBoolean, &value); 958#endif 959 960 XAddConnectionWatch(dpy, ConnectionWatch, (XPointer) dpy); 961 962 XtFree( (XtPointer)options ); 963 DEALLOCATE_LOCAL( search_list ); 964} 965 966/* Function Name: XtAppSetFallbackResources 967 * Description: Sets the fallback resource list that will be loaded 968 * at display initialization time. 969 * Arguments: app_context - the app context. 970 * specification_list - the resource specification list. 971 * Returns: none. 972 */ 973 974void 975XtAppSetFallbackResources( 976 XtAppContext app_context, 977 String *specification_list) 978{ 979 LOCK_APP(app_context); 980 app_context->fallback_resources = specification_list; 981 UNLOCK_APP(app_context); 982} 983 984 985Widget XtOpenApplication(XtAppContext *app_context_return, 986 _Xconst char *application_class, 987 XrmOptionDescRec *options, Cardinal num_options, 988 int *argc_in_out, String *argv_in_out, 989 String *fallback_resources, WidgetClass widget_class, 990 ArgList args_in, Cardinal num_args_in) 991{ 992 XtAppContext app_con; 993 Display * dpy; 994 register int saved_argc = *argc_in_out; 995 Widget root; 996 Arg args[3], *merged_args; 997 Cardinal num = 0; 998 999 XtToolkitInitialize(); /* cannot be moved into _XtAppInit */ 1000 1001 dpy = _XtAppInit(&app_con, (String)application_class, options, num_options, 1002 argc_in_out, &argv_in_out, fallback_resources); 1003 1004 LOCK_APP(app_con); 1005 XtSetArg(args[num], XtNscreen, DefaultScreenOfDisplay(dpy)); num++; 1006 XtSetArg(args[num], XtNargc, saved_argc); num++; 1007 XtSetArg(args[num], XtNargv, argv_in_out); num++; 1008 1009 merged_args = XtMergeArgLists(args_in, num_args_in, args, num); 1010 num += num_args_in; 1011 1012 root = XtAppCreateShell(NULL, application_class, widget_class, dpy, 1013 merged_args, num); 1014 1015 if (app_context_return) 1016 *app_context_return = app_con; 1017 1018 XtFree((XtPointer)merged_args); 1019 XtFree((XtPointer)argv_in_out); 1020 UNLOCK_APP(app_con); 1021 return root; 1022} 1023 1024 1025Widget 1026XtAppInitialize( 1027 XtAppContext * app_context_return, 1028 _Xconst char* application_class, 1029 XrmOptionDescRec *options, 1030 Cardinal num_options, 1031 int *argc_in_out, 1032 String *argv_in_out, 1033 String *fallback_resources, 1034 ArgList args_in, 1035 Cardinal num_args_in) 1036{ 1037 return XtOpenApplication(app_context_return, application_class, 1038 options, num_options, 1039 argc_in_out, argv_in_out, fallback_resources, 1040 applicationShellWidgetClass, 1041 args_in, num_args_in); 1042} 1043 1044 1045/*ARGSUSED*/ 1046Widget 1047XtInitialize( 1048 _Xconst char* name, 1049 _Xconst char* classname, 1050 XrmOptionDescRec *options, 1051 Cardinal num_options, 1052 int *argc, 1053 String *argv) 1054{ 1055 Widget root; 1056 XtAppContext app_con; 1057 register ProcessContext process = _XtGetProcessContext(); 1058 1059 root = XtAppInitialize(&app_con, classname, options, num_options, 1060 argc, argv, NULL, NULL, (Cardinal) 0); 1061 1062 LOCK_PROCESS; 1063 process->defaultAppContext = app_con; 1064 UNLOCK_PROCESS; 1065 return root; 1066} 1067