Initialize.c revision 0568f49b
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, (size_t) 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 NULL, 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 _XtString 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, (size_t) (len-1)); 324 dest[len-1] = '\0'; 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 } else 330 *dest = '\0'; 331 } 332#endif 333 return dest; 334} 335 336 337static String GetRootDirName( 338 _XtString 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 static char *ptr; 364 365 if (len <= 0 || dest == NULL) 366 return NULL; 367 368 if ((ptr = getenv("HOME"))) { 369 (void) strncpy (dest, ptr, (size_t)(len-1)); 370 dest[len-1] = '\0'; 371 } else { 372 struct passwd *pw; 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, (size_t)(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 char *dpy_defaults = XResourceManagerString(dpy); 429 430 if (dpy_defaults) { 431 XrmCombineDatabase(XrmGetStringDatabase(dpy_defaults), pdb, False); 432 } else { 433#ifdef __MINGW32__ 434 const char *slashDotXdefaults = "/Xdefaults"; 435#else 436 const char *slashDotXdefaults = "/.Xdefaults"; 437#endif 438 char filename[PATH_MAX]; 439 (void) GetRootDirName(filename, 440 PATH_MAX - (int)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 - (int)strlen (slashDotXdefaultsDash) - 1); 578 (void) strcat(filename, slashDotXdefaultsDash); 579 len = (int)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 XrmOptionDescRec *opt1, *dstP; 652 const XrmOptionDescRec *opt2; 653 int i1; 654 Cardinal i2; 655 int dst_len, order; 656 enum {Check, NotSorted, IsSorted} sort_order = Check; 657 658 *dst = table = (XrmOptionDescRec*) 659 __XtMalloc( (Cardinal)(sizeof(XrmOptionDescRec) * (num_src1 + num_src2) )); 660 661 (void) memmove(table, src1, sizeof(XrmOptionDescRec) * num_src1 ); 662 if (num_src2 == 0) { 663 *num_dst = num_src1; 664 return; 665 } 666 endP = &table[dst_len = (int)num_src1]; 667 for (opt2 = src2, i2= 0; i2 < num_src2; opt2++, i2++) { 668 XrmOptionDescRec *whereP; 669 Boolean found; 670 671 found = False; 672 whereP = endP-1; /* assume new option goes at the end */ 673 for (opt1 = table, i1 = 0; i1 < dst_len; opt1++, i1++) { 674 /* have to walk the entire new table so new list is ordered 675 (if src1 was ordered) */ 676 if (sort_order == Check && i1 > 0 677 && strcmp(opt1->option, (opt1-1)->option) < 0) 678 sort_order = NotSorted; 679 if ((order = strcmp(opt1->option, opt2->option)) == 0) { 680 /* same option names; just overwrite opt1 with opt2 */ 681 *opt1 = *opt2; 682 found = True; 683 break; 684 } 685 /* else */ 686 if (sort_order == IsSorted && order > 0) { 687 /* insert before opt1 to preserve order */ 688 /* shift rest of table forward to make room for new entry */ 689 for (dstP = endP++; dstP > opt1; dstP--) 690 *dstP = *(dstP-1); 691 *opt1 = *opt2; 692 dst_len++; 693 found = True; 694 break; 695 } 696 /* else */ 697 if (order < 0) 698 /* opt2 sorts after opt1, so remember this position */ 699 whereP = opt1; 700 } 701 if (sort_order == Check && i1 == dst_len) 702 sort_order = IsSorted; 703 if (!found) { 704 /* when we get here, whereP points to the last entry in the 705 destination that sorts before "opt2". Shift rest of table 706 forward and insert "opt2" after whereP. */ 707 whereP++; 708 for (dstP = endP++; dstP > whereP; dstP--) 709 *dstP = *(dstP-1); 710 *whereP = *opt2; 711 dst_len++; 712 } 713 } 714 *num_dst = (Cardinal)dst_len; 715} 716 717 718/* NOTE: name, class, and type must be permanent strings */ 719static Boolean _GetResource( 720 Display *dpy, 721 XrmSearchList list, 722 String name, 723 String class, 724 String type, 725 XrmValue* value) 726{ 727 XrmRepresentation db_type; 728 XrmValue db_value; 729 XrmName Qname = XrmPermStringToQuark(name); 730 XrmClass Qclass = XrmPermStringToQuark(class); 731 XrmRepresentation Qtype = XrmPermStringToQuark(type); 732 733 if (XrmQGetSearchResource(list, Qname, Qclass, &db_type, &db_value)) { 734 if (db_type == Qtype) { 735 if (Qtype == _XtQString) 736 *(String*)value->addr = db_value.addr; 737 else 738 (void) memmove(value->addr, db_value.addr, value->size ); 739 return True; 740 } else { 741 WidgetRec widget; /* hack, hack */ 742 memset( &widget, 0, sizeof(widget) ); 743 widget.core.self = &widget; 744 widget.core.widget_class = coreWidgetClass; 745 widget.core.screen = (Screen*)DefaultScreenOfDisplay(dpy); 746 XtInitializeWidgetClass(coreWidgetClass); 747 if (_XtConvert(&widget,db_type,&db_value,Qtype,value,NULL)) { 748 return True; 749 } 750 } 751 } 752 return False; 753} 754 755XrmDatabase _XtPreparseCommandLine( 756 XrmOptionDescRec *urlist, 757 Cardinal num_urs, 758 int argc, 759 _XtString *argv, 760 /* return */ 761 String *applName, 762 String *displayName, 763 String *language) 764{ 765 XrmDatabase db = NULL; 766 XrmOptionDescRec *options; 767 Cardinal num_options; 768 XrmName name_list[3]; 769 XrmName class_list[3]; 770 XrmRepresentation type; 771 XrmValue val; 772 _XtString *targv; 773 int targc = argc; 774 775 targv = (_XtString *) __XtMalloc((Cardinal)(sizeof(_XtString*) * (size_t)argc)); 776 (void) memmove(targv, argv, sizeof(char *) * (size_t) argc); 777 _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs, 778 &options, &num_options); 779 name_list[0] = class_list[0] = XrmPermStringToQuark("."); 780 name_list[2] = class_list[2] = NULLQUARK; 781 XrmParseCommand(&db, options, (int) num_options, ".", &targc, targv); 782 if (applName) { 783 name_list[1] = XrmPermStringToQuark("name"); 784 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 785 type == _XtQString) 786 *applName = val.addr; 787 } 788 if (displayName) { 789 name_list[1] = XrmPermStringToQuark("display"); 790 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 791 type == _XtQString) 792 *displayName = val.addr; 793 } 794 if (language) { 795 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 796 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 797 if (XrmQGetResource(db, name_list, class_list, &type, &val) && 798 type == _XtQString) 799 *language = val.addr; 800 } 801 802 XtFree((char *)targv); 803 XtFree((char *)options); 804 return db; 805} 806 807 808static void GetLanguage( 809 Display *dpy, 810 XtPerDisplay pd) 811{ 812 XrmRepresentation type; 813 XrmValue value; 814 XrmName name_list[3]; 815 XrmName class_list[3]; 816 817 LOCK_PROCESS; 818 if (! pd->language) { 819 name_list[0] = pd->name; 820 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 821 class_list[0] = pd->class; 822 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 823 name_list[2] = class_list[2] = NULLQUARK; 824 if (!pd->server_db) 825 CombineUserDefaults(dpy, &pd->server_db); 826 if (pd->server_db && 827 XrmQGetResource(pd->server_db,name_list,class_list, &type, &value) 828 && type == _XtQString) 829 pd->language = (char *) value.addr; 830 } 831 832 if (pd->appContext->langProcRec.proc) { 833 if (! pd->language) pd->language = ""; 834 pd->language = (*pd->appContext->langProcRec.proc) 835 (dpy, pd->language, pd->appContext->langProcRec.closure); 836 } 837 else if (! pd->language || pd->language[0] == '\0') /* R4 compatibility */ 838 pd->language = getenv("LANG"); 839 840 if (pd->language) pd->language = XtNewString(pd->language); 841 UNLOCK_PROCESS; 842} 843 844static void ProcessInternalConnection ( 845 XtPointer client_data, 846 int* fd, 847 XtInputId* id) 848{ 849 XProcessInternalConnection ((Display *) client_data, *fd); 850} 851 852static void ConnectionWatch ( 853 Display* dpy, 854 XPointer client_data, 855 int fd, 856 Bool opening, 857 XPointer* watch_data) 858{ 859 XtInputId* iptr; 860 XtAppContext app = XtDisplayToApplicationContext(dpy); 861 862 if (opening) { 863 iptr = (XtInputId *) __XtMalloc(sizeof(XtInputId)); 864 *iptr = XtAppAddInput(app, fd, (XtPointer) XtInputReadMask, 865 ProcessInternalConnection, client_data); 866 *watch_data = (XPointer) iptr; 867 } else { 868 iptr = (XtInputId *) *watch_data; 869 XtRemoveInput(*iptr); 870 (void) XtFree(*watch_data); 871 } 872} 873 874void _XtDisplayInitialize( 875 Display *dpy, 876 XtPerDisplay pd, 877 _Xconst char* name, 878 XrmOptionDescRec *urlist, 879 Cardinal num_urs, 880 int *argc, 881 char **argv) 882{ 883 Boolean tmp_bool; 884 XrmValue value; 885 XrmOptionDescRec *options; 886 Cardinal num_options; 887 XrmDatabase db; 888 XrmName name_list[2]; 889 XrmClass class_list[2]; 890 XrmHashTable* search_list; 891 int search_list_size = SEARCH_LIST_SIZE; 892 893 GetLanguage(dpy, pd); 894 895 /* Parse the command line and remove Xt arguments from argv */ 896 _MergeOptionTables( opTable, XtNumber(opTable), urlist, num_urs, 897 &options, &num_options ); 898 XrmParseCommand(&pd->cmd_db, options, (int) num_options, name, argc, argv); 899 900 db = XtScreenDatabase(DefaultScreenOfDisplay(dpy)); 901 902 if (!(search_list = (XrmHashTable*) 903 ALLOCATE_LOCAL( SEARCH_LIST_SIZE*sizeof(XrmHashTable)))) 904 _XtAllocError(NULL); 905 name_list[0] = pd->name; 906 class_list[0] = pd->class; 907 name_list[1] = NULLQUARK; 908 class_list[1] = NULLQUARK; 909 910 while (!XrmQGetSearchList(db, name_list, class_list, 911 search_list, search_list_size)) { 912 XrmHashTable* old = search_list; 913 Cardinal size = (Cardinal) ((size_t)(search_list_size *= 2)*sizeof(XrmHashTable)); 914 if (!(search_list = (XrmHashTable*)ALLOCATE_LOCAL(size))) 915 _XtAllocError(NULL); 916 (void) memmove((char*)search_list, (char*)old, (size>>1) ); 917 DEALLOCATE_LOCAL(old); 918 } 919 920 value.size = sizeof(tmp_bool); 921 value.addr = (XtPointer)&tmp_bool; 922 if (_GetResource(dpy, search_list, "synchronous", "Synchronous", 923 XtRBoolean, &value)) { 924 int i; 925 Display **dpyP = pd->appContext->list; 926 pd->appContext->sync = tmp_bool; 927 for (i = pd->appContext->count; i; dpyP++, i--) { 928 (void) XSynchronize(*dpyP, (Bool)tmp_bool); 929 } 930 } else { 931 (void) XSynchronize(dpy, (Bool)pd->appContext->sync); 932 } 933 934 if (_GetResource(dpy, search_list, "reverseVideo", "ReverseVideo", 935 XtRBoolean, &value) 936 && tmp_bool) { 937 pd->rv = True; 938 } 939 940 value.size = sizeof(pd->multi_click_time); 941 value.addr = (XtPointer)&pd->multi_click_time; 942 if (!_GetResource(dpy, search_list, 943 "multiClickTime", "MultiClickTime", 944 XtRInt, &value)) { 945 pd->multi_click_time = 200; 946 } 947 948 value.size = sizeof(pd->appContext->selectionTimeout); 949 value.addr = (XtPointer)&pd->appContext->selectionTimeout; 950 (void)_GetResource(dpy, search_list, 951 "selectionTimeout", "SelectionTimeout", 952 XtRInt, &value); 953 954#ifndef NO_IDENTIFY_WINDOWS 955 value.size = sizeof(pd->appContext->identify_windows); 956 value.addr = (XtPointer)&pd->appContext->identify_windows; 957 (void)_GetResource(dpy, search_list, 958 "xtIdentifyWindows", "XtDebug", 959 XtRBoolean, &value); 960#endif 961 962 XAddConnectionWatch(dpy, ConnectionWatch, (XPointer) dpy); 963 964 XtFree( (XtPointer)options ); 965 DEALLOCATE_LOCAL( search_list ); 966} 967 968/* Function Name: XtAppSetFallbackResources 969 * Description: Sets the fallback resource list that will be loaded 970 * at display initialization time. 971 * Arguments: app_context - the app context. 972 * specification_list - the resource specification list. 973 * Returns: none. 974 */ 975 976void 977XtAppSetFallbackResources( 978 XtAppContext app_context, 979 String *specification_list) 980{ 981 LOCK_APP(app_context); 982 app_context->fallback_resources = specification_list; 983 UNLOCK_APP(app_context); 984} 985 986 987Widget XtOpenApplication(XtAppContext *app_context_return, 988 _Xconst char *application_class, 989 XrmOptionDescRec *options, Cardinal num_options, 990 int *argc_in_out, _XtString *argv_in_out, 991 String *fallback_resources, WidgetClass widget_class, 992 ArgList args_in, Cardinal num_args_in) 993{ 994 XtAppContext app_con; 995 Display * dpy; 996 register int saved_argc = *argc_in_out; 997 Widget root; 998 Arg args[3], *merged_args; 999 Cardinal num = 0; 1000 1001 XtToolkitInitialize(); /* cannot be moved into _XtAppInit */ 1002 1003 dpy = _XtAppInit(&app_con, (String)application_class, options, num_options, 1004 argc_in_out, &argv_in_out, fallback_resources); 1005 1006 LOCK_APP(app_con); 1007 XtSetArg(args[num], XtNscreen, DefaultScreenOfDisplay(dpy)); num++; 1008 XtSetArg(args[num], XtNargc, saved_argc); num++; 1009 XtSetArg(args[num], XtNargv, argv_in_out); num++; 1010 1011 merged_args = XtMergeArgLists(args_in, num_args_in, args, num); 1012 num += num_args_in; 1013 1014 root = XtAppCreateShell(NULL, application_class, widget_class, dpy, 1015 merged_args, num); 1016 1017 if (app_context_return) 1018 *app_context_return = app_con; 1019 1020 XtFree((XtPointer)merged_args); 1021 XtFree((XtPointer)argv_in_out); 1022 UNLOCK_APP(app_con); 1023 return root; 1024} 1025 1026 1027Widget 1028XtAppInitialize( 1029 XtAppContext * app_context_return, 1030 _Xconst char* application_class, 1031 XrmOptionDescRec *options, 1032 Cardinal num_options, 1033 int *argc_in_out, 1034 _XtString *argv_in_out, 1035 String *fallback_resources, 1036 ArgList args_in, 1037 Cardinal num_args_in) 1038{ 1039 return XtOpenApplication(app_context_return, application_class, 1040 options, num_options, 1041 argc_in_out, argv_in_out, fallback_resources, 1042 applicationShellWidgetClass, 1043 args_in, num_args_in); 1044} 1045 1046 1047/*ARGSUSED*/ 1048Widget 1049XtInitialize( 1050 _Xconst _XtString name, 1051 _Xconst _XtString classname, 1052 XrmOptionDescRec *options, 1053 Cardinal num_options, 1054 int *argc, 1055 _XtString *argv) 1056{ 1057 Widget root; 1058 XtAppContext app_con; 1059 register ProcessContext process = _XtGetProcessContext(); 1060 1061 root = XtAppInitialize(&app_con, classname, options, num_options, 1062 argc, argv, NULL, NULL, (Cardinal) 0); 1063 1064 LOCK_PROCESS; 1065 process->defaultAppContext = app_con; 1066 UNLOCK_PROCESS; 1067 return root; 1068} 1069