Initialize.c revision 9e7bcd65
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 248asm (".data\n\ 249 .globl __XtInherit \n\ 250 __XtInherit: jmp *_y \n\ 251 _y: .long ___XtInherit \n\ 252 .text \n"); 253 254#define _XtInherit __XtInherit 255#endif 256 257 258void _XtInherit(void) 259{ 260 XtErrorMsg("invalidProcedure","inheritanceProc",XtCXtToolkitError, 261 "Unresolved inheritance operation", 262 (String *)NULL, (Cardinal *)NULL); 263} 264 265 266void XtToolkitInitialize(void) 267{ 268 static Boolean initialized = False; 269 270 LOCK_PROCESS; 271 if (initialized) { 272 UNLOCK_PROCESS; 273 return; 274 } 275 initialized = True; 276 UNLOCK_PROCESS; 277 /* Resource management initialization */ 278 XrmInitialize(); 279 _XtResourceListInitialize(); 280 281 /* Other intrinsic intialization */ 282 _XtConvertInitialize(); 283 _XtEventInitialize(); 284 _XtTranslateInitialize(); 285 286 /* Some apps rely on old (broken) XtAppPeekEvent behavior */ 287 if(getenv("XTAPPPEEKEVENT_SKIPTIMER")) 288 XtAppPeekEvent_SkipTimer = True; 289 else 290 XtAppPeekEvent_SkipTimer = False; 291} 292 293 294String _XtGetUserName( 295 String dest, 296 int len) 297{ 298#ifdef WIN32 299 String ptr = NULL; 300 301 if ((ptr = getenv("USERNAME"))) { 302 (void) strncpy (dest, ptr, len-1); 303 dest[len-1] = '\0'; 304 } else 305 *dest = '\0'; 306#else 307#ifdef X_NEEDS_PWPARAMS 308 _Xgetpwparams pwparams; 309#endif 310 struct passwd *pw; 311 char* ptr; 312 313 if ((ptr = getenv("USER"))) { 314 (void) strncpy (dest, ptr, len-1); 315 dest[len-1] = '\0'; 316 } else { 317 if ((pw = _XGetpwuid(getuid(),pwparams)) != NULL) { 318 (void) strncpy (dest, pw->pw_name, len-1); 319 dest[len-1] = '\0'; 320 } else 321 *dest = '\0'; 322 } 323#endif 324 return dest; 325} 326 327 328static String GetRootDirName( 329 String dest, 330 int len) 331{ 332#ifdef WIN32 333 register char *ptr1; 334 register char *ptr2 = NULL; 335 int len1 = 0, len2 = 0; 336 337 if (ptr1 = getenv("HOME")) { /* old, deprecated */ 338 len1 = strlen (ptr1); 339 } else if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) { 340 len1 = strlen (ptr1); 341 len2 = strlen (ptr2); 342 } else if (ptr2 = getenv("USERNAME")) { 343 len1 = strlen (ptr1 = "/users/"); 344 len2 = strlen (ptr2); 345 } 346 if ((len1 + len2 + 1) < len) 347 sprintf (dest, "%s%s", ptr1, (ptr2) ? ptr2 : ""); 348 else 349 *dest = '\0'; 350#else 351#ifdef X_NEEDS_PWPARAMS 352 _Xgetpwparams pwparams; 353#endif 354 struct passwd *pw; 355 static char *ptr; 356 357 if (len <= 0 || dest == NULL) 358 return NULL; 359 360 if ((ptr = getenv("HOME"))) { 361 (void) strncpy (dest, ptr, len-1); 362 dest[len-1] = '\0'; 363 } else { 364 if ((ptr = getenv("USER"))) 365 pw = _XGetpwnam(ptr,pwparams); 366 else 367 pw = _XGetpwuid(getuid(),pwparams); 368 if (pw != NULL) { 369 (void) strncpy (dest, pw->pw_dir, len-1); 370 dest[len-1] = '\0'; 371 } else 372 *dest = '\0'; 373 } 374#endif 375 return dest; 376} 377 378static void CombineAppUserDefaults( 379 Display *dpy, 380 XrmDatabase *pdb) 381{ 382 char* filename; 383 char* path = NULL; 384 Boolean deallocate = False; 385 386 if (!(path = getenv("XUSERFILESEARCHPATH"))) { 387#if !defined(WIN32) || !defined(__MINGW32__) 388 char *old_path; 389 char homedir[PATH_MAX]; 390 GetRootDirName(homedir, PATH_MAX); 391 if (!(old_path = getenv("XAPPLRESDIR"))) { 392 XtAsprintf(&path, 393 "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N", 394 homedir, homedir, homedir, homedir, homedir, homedir); 395 } else { 396 XtAsprintf(&path, 397 "%s/%%L/%%N%%C:%s/%%l/%%N%%C:%s/%%N%%C:%s/%%N%%C:%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N", 398 old_path, old_path, old_path, homedir, 399 old_path, old_path, old_path, homedir); 400 } 401 deallocate = True; 402#endif 403 } 404 405 filename = XtResolvePathname(dpy, NULL, NULL, NULL, path, NULL, 0, NULL); 406 if (filename) { 407 (void)XrmCombineFileDatabase(filename, pdb, False); 408 XtFree(filename); 409 } 410 411 if (deallocate) 412 XtFree(path); 413} 414 415static void CombineUserDefaults( 416 Display *dpy, 417 XrmDatabase *pdb) 418{ 419#ifdef __MINGW32__ 420 const char *slashDotXdefaults = "/Xdefaults"; 421#else 422 const char *slashDotXdefaults = "/.Xdefaults"; 423#endif 424 char *dpy_defaults = XResourceManagerString(dpy); 425 426 if (dpy_defaults) { 427 XrmCombineDatabase(XrmGetStringDatabase(dpy_defaults), pdb, False); 428 } else { 429 char filename[PATH_MAX]; 430 (void) GetRootDirName(filename, 431 PATH_MAX - strlen (slashDotXdefaults) - 1); 432 (void) strcat(filename, slashDotXdefaults); 433 (void)XrmCombineFileDatabase(filename, pdb, False); 434 } 435} 436 437/*ARGSUSED*/ 438static Bool StoreDBEntry( 439 XrmDatabase *db, 440 XrmBindingList bindings, 441 XrmQuarkList quarks, 442 XrmRepresentation *type, 443 XrmValuePtr value, 444 XPointer data) 445{ 446 XrmQPutResource((XrmDatabase *)data, bindings, quarks, *type, value); 447 return False; 448} 449 450static XrmDatabase CopyDB(XrmDatabase db) 451{ 452 XrmDatabase copy = NULL; 453 XrmQuark empty = NULLQUARK; 454 455 XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels, 456 StoreDBEntry, (XPointer)©); 457 return copy; 458} 459 460/*ARGSUSED*/ 461static String _XtDefaultLanguageProc( 462 Display *dpy, /* unused */ 463 String xnl, 464 XtPointer closure) /* unused */ 465{ 466 if (! setlocale(LC_ALL, xnl)) 467 XtWarning("locale not supported by C library, locale unchanged"); 468 469 if (! XSupportsLocale()) { 470 XtWarning("locale not supported by Xlib, locale set to C"); 471 setlocale(LC_ALL, "C"); 472 } 473 if (! XSetLocaleModifiers("")) 474 XtWarning("X locale modifiers not supported, using default"); 475 476 return setlocale(LC_ALL, NULL); /* re-query in case overwritten */ 477} 478 479XtLanguageProc XtSetLanguageProc( 480 XtAppContext app, 481 XtLanguageProc proc, 482 XtPointer closure) 483{ 484 XtLanguageProc old; 485 486 if (!proc) { 487 proc = _XtDefaultLanguageProc; 488 closure = NULL; 489 } 490 491 if (app) { 492 LOCK_APP(app); 493 LOCK_PROCESS; 494 /* set langProcRec only for this application context */ 495 old = app->langProcRec.proc; 496 app->langProcRec.proc = proc; 497 app->langProcRec.closure = closure; 498 UNLOCK_PROCESS; 499 UNLOCK_APP(app); 500 } else { 501 /* set langProcRec for all application contexts */ 502 ProcessContext process; 503 504 LOCK_PROCESS; 505 process = _XtGetProcessContext(); 506 old = process->globalLangProcRec.proc; 507 process->globalLangProcRec.proc = proc; 508 process->globalLangProcRec.closure = closure; 509 app = process->appContextList; 510 while (app) { 511 app->langProcRec.proc = proc; 512 app->langProcRec.closure = closure; 513 app = app->next; 514 } 515 UNLOCK_PROCESS; 516 } 517 return (old ? old : _XtDefaultLanguageProc); 518} 519 520XrmDatabase XtScreenDatabase( 521 Screen *screen) 522{ 523 int scrno; 524 Bool doing_def; 525 XrmDatabase db, olddb; 526 XtPerDisplay pd; 527 Status do_fallback; 528 char *scr_resources; 529 Display *dpy = DisplayOfScreen(screen); 530 DPY_TO_APPCON(dpy); 531 532 LOCK_APP(app); 533 LOCK_PROCESS; 534 if (screen == DefaultScreenOfDisplay(dpy)) { 535 scrno = DefaultScreen(dpy); 536 doing_def = True; 537 } else { 538 scrno = XScreenNumberOfScreen(screen); 539 doing_def = False; 540 } 541 pd = _XtGetPerDisplay(dpy); 542 if ((db = pd->per_screen_db[scrno])) { 543 UNLOCK_PROCESS; 544 UNLOCK_APP(app); 545 return (doing_def ? XrmGetDatabase(dpy) : db); 546 } 547 scr_resources = XScreenResourceString(screen); 548 549 if (ScreenCount(dpy) == 1) { 550 db = pd->cmd_db; 551 pd->cmd_db = NULL; 552 } else { 553 db = CopyDB(pd->cmd_db); 554 } 555 { /* Environment defaults */ 556 char filenamebuf[PATH_MAX]; 557 char *filename; 558 559 if (!(filename = getenv("XENVIRONMENT"))) { 560 int len; 561#ifdef __MINGW32__ 562 const char *slashDotXdefaultsDash = "/Xdefaults-"; 563#else 564 const char *slashDotXdefaultsDash = "/.Xdefaults-"; 565#endif 566 567 (void) GetRootDirName(filename = filenamebuf, 568 PATH_MAX - strlen (slashDotXdefaultsDash) - 1); 569 (void) strcat(filename, slashDotXdefaultsDash); 570 len = strlen(filename); 571 GetHostname (filename+len, PATH_MAX-len); 572 } 573 (void)XrmCombineFileDatabase(filename, &db, False); 574 } 575 if (scr_resources) 576 { /* Screen defaults */ 577 XrmCombineDatabase(XrmGetStringDatabase(scr_resources), &db, False); 578 XFree(scr_resources); 579 } 580 /* Server or host defaults */ 581 if (!pd->server_db) 582 CombineUserDefaults(dpy, &db); 583 else { 584 (void) XrmCombineDatabase(pd->server_db, &db, False); 585 pd->server_db = NULL; 586 } 587 588 if (!db) 589 db = XrmGetStringDatabase(""); 590 pd->per_screen_db[scrno] = db; 591 olddb = XrmGetDatabase(dpy); 592 /* set database now, for XtResolvePathname to use */ 593 XrmSetDatabase(dpy, db); 594 CombineAppUserDefaults(dpy, &db); 595 do_fallback = 1; 596 { /* System app-defaults */ 597 char *filename; 598 599 if ((filename = XtResolvePathname(dpy, "app-defaults", 600 NULL, NULL, NULL, NULL, 0, NULL))) { 601 do_fallback = !XrmCombineFileDatabase(filename, &db, False); 602 XtFree(filename); 603 } 604 } 605 /* now restore old database, if need be */ 606 if (!doing_def) 607 XrmSetDatabase(dpy, olddb); 608 if (do_fallback && pd->appContext->fallback_resources) 609 { /* Fallback defaults */ 610 XrmDatabase fdb = NULL; 611 String *res; 612 613 for (res = pd->appContext->fallback_resources; *res; res++) 614 XrmPutLineResource(&fdb, *res); 615 (void)XrmCombineDatabase(fdb, &db, False); 616 } 617 UNLOCK_PROCESS; 618 UNLOCK_APP(app); 619 return db; 620} 621 622/* 623 * Merge two option tables, allowing the second to over-ride the first, 624 * so that ambiguous abbreviations can be noticed. The merge attempts 625 * to make the resulting table lexicographically sorted, but succeeds 626 * only if the first source table is sorted. Though it _is_ recommended 627 * (for optimizations later in XrmParseCommand), it is not required 628 * that either source table be sorted. 629 * 630 * Caller is responsible for freeing the returned option table. 631 */ 632 633static void _MergeOptionTables( 634 const XrmOptionDescRec *src1, 635 Cardinal num_src1, 636 const XrmOptionDescRec *src2, 637 Cardinal num_src2, 638 XrmOptionDescRec **dst, 639 Cardinal *num_dst) 640{ 641 XrmOptionDescRec *table, *endP; 642 register XrmOptionDescRec *opt1, *whereP, *dstP; 643 register const XrmOptionDescRec *opt2; 644 int i1; 645 Cardinal i2; 646 int dst_len, order; 647 Boolean found; 648 enum {Check, NotSorted, IsSorted} sort_order = Check; 649 650 *dst = table = (XrmOptionDescRec*) 651 __XtMalloc( sizeof(XrmOptionDescRec) * (num_src1 + num_src2) ); 652 653 (void) memmove(table, src1, sizeof(XrmOptionDescRec) * num_src1 ); 654 if (num_src2 == 0) { 655 *num_dst = num_src1; 656 return; 657 } 658 endP = &table[dst_len = num_src1]; 659 for (opt2 = src2, i2= 0; i2 < num_src2; opt2++, i2++) { 660 found = False; 661 whereP = endP-1; /* assume new option goes at the end */ 662 for (opt1 = table, i1 = 0; i1 < dst_len; opt1++, i1++) { 663 /* have to walk the entire new table so new list is ordered 664 (if src1 was ordered) */ 665 if (sort_order == Check && i1 > 0 666 && strcmp(opt1->option, (opt1-1)->option) < 0) 667 sort_order = NotSorted; 668 if ((order = strcmp(opt1->option, opt2->option)) == 0) { 669 /* same option names; just overwrite opt1 with opt2 */ 670 *opt1 = *opt2; 671 found = True; 672 break; 673 } 674 /* else */ 675 if (sort_order == IsSorted && order > 0) { 676 /* insert before opt1 to preserve order */ 677 /* shift rest of table forward to make room for new entry */ 678 for (dstP = endP++; dstP > opt1; dstP--) 679 *dstP = *(dstP-1); 680 *opt1 = *opt2; 681 dst_len++; 682 found = True; 683 break; 684 } 685 /* else */ 686 if (order < 0) 687 /* opt2 sorts after opt1, so remember this position */ 688 whereP = opt1; 689 } 690 if (sort_order == Check && i1 == dst_len) 691 sort_order = IsSorted; 692 if (!found) { 693 /* when we get here, whereP points to the last entry in the 694 destination that sorts before "opt2". Shift rest of table 695 forward and insert "opt2" after whereP. */ 696 whereP++; 697 for (dstP = endP++; dstP > whereP; dstP--) 698 *dstP = *(dstP-1); 699 *whereP = *opt2; 700 dst_len++; 701 } 702 } 703 *num_dst = dst_len; 704} 705 706 707/* NOTE: name, class, and type must be permanent strings */ 708static Boolean _GetResource( 709 Display *dpy, 710 XrmSearchList list, 711 String name, 712 String class, 713 String type, 714 XrmValue* value) 715{ 716 XrmRepresentation db_type; 717 XrmValue db_value; 718 XrmName Qname = XrmPermStringToQuark(name); 719 XrmClass Qclass = XrmPermStringToQuark(class); 720 XrmRepresentation Qtype = XrmPermStringToQuark(type); 721 722 if (XrmQGetSearchResource(list, Qname, Qclass, &db_type, &db_value)) { 723 if (db_type == Qtype) { 724 if (Qtype == _XtQString) 725 *(String*)value->addr = db_value.addr; 726 else 727 (void) memmove(value->addr, db_value.addr, value->size ); 728 return True; 729 } else { 730 WidgetRec widget; /* hack, hack */ 731 bzero( &widget, sizeof(widget) ); 732 widget.core.self = &widget; 733 widget.core.widget_class = coreWidgetClass; 734 widget.core.screen = (Screen*)DefaultScreenOfDisplay(dpy); 735 XtInitializeWidgetClass(coreWidgetClass); 736 if (_XtConvert(&widget,db_type,&db_value,Qtype,value,NULL)) { 737 return True; 738 } 739 } 740 } 741 return False; 742} 743 744XrmDatabase _XtPreparseCommandLine( 745 XrmOptionDescRec *urlist, 746 Cardinal num_urs, 747 int argc, 748 String *argv, 749 /* return */ 750 String *applName, 751 String *displayName, 752 String *language) 753{ 754 XrmDatabase db = NULL; 755 XrmOptionDescRec *options; 756 Cardinal num_options; 757 XrmName name_list[3]; 758 XrmName class_list[3]; 759 XrmRepresentation type; 760 XrmValue val; 761 String *targv; 762 int targc = argc; 763 764 targv = (String *) __XtMalloc(sizeof(char *) * argc); 765 (void) memmove(targv, argv, sizeof(char *) * argc); 766 _MergeOptionTables(opTable, XtNumber(opTable), urlist, num_urs, 767 &options, &num_options); 768 name_list[0] = class_list[0] = XrmPermStringToQuark("."); 769 name_list[2] = class_list[2] = NULLQUARK; 770 XrmParseCommand(&db, options, num_options, ".", &targc, targv); 771 if (applName) { 772 name_list[1] = XrmPermStringToQuark("name"); 773 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 774 type == _XtQString) 775 *applName = val.addr; 776 } 777 if (displayName) { 778 name_list[1] = XrmPermStringToQuark("display"); 779 if (XrmQGetResource(db, name_list, name_list, &type, &val) && 780 type == _XtQString) 781 *displayName = val.addr; 782 } 783 if (language) { 784 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 785 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 786 if (XrmQGetResource(db, name_list, class_list, &type, &val) && 787 type == _XtQString) 788 *language = val.addr; 789 } 790 791 XtFree((char *)targv); 792 XtFree((char *)options); 793 return db; 794} 795 796 797static void GetLanguage( 798 Display *dpy, 799 XtPerDisplay pd) 800{ 801 XrmRepresentation type; 802 XrmValue value; 803 XrmName name_list[3]; 804 XrmName class_list[3]; 805 806 LOCK_PROCESS; 807 if (! pd->language) { 808 name_list[0] = pd->name; 809 name_list[1] = XrmPermStringToQuark("xnlLanguage"); 810 class_list[0] = pd->class; 811 class_list[1] = XrmPermStringToQuark("XnlLanguage"); 812 name_list[2] = class_list[2] = NULLQUARK; 813 if (!pd->server_db) 814 CombineUserDefaults(dpy, &pd->server_db); 815 if (pd->server_db && 816 XrmQGetResource(pd->server_db,name_list,class_list, &type, &value) 817 && type == _XtQString) 818 pd->language = (char *) value.addr; 819 } 820 821 if (pd->appContext->langProcRec.proc) { 822 if (! pd->language) pd->language = ""; 823 pd->language = (*pd->appContext->langProcRec.proc) 824 (dpy, pd->language, pd->appContext->langProcRec.closure); 825 } 826 else if (! pd->language || pd->language[0] == '\0') /* R4 compatibility */ 827 pd->language = getenv("LANG"); 828 829 if (pd->language) pd->language = XtNewString(pd->language); 830 UNLOCK_PROCESS; 831} 832 833static void ProcessInternalConnection ( 834 XtPointer client_data, 835 int* fd, 836 XtInputId* id) 837{ 838 XProcessInternalConnection ((Display *) client_data, *fd); 839} 840 841static void ConnectionWatch ( 842 Display* dpy, 843 XPointer client_data, 844 int fd, 845 Bool opening, 846 XPointer* watch_data) 847{ 848 XtInputId* iptr; 849 XtAppContext app = XtDisplayToApplicationContext(dpy); 850 851 if (opening) { 852 iptr = (XtInputId *) __XtMalloc(sizeof(XtInputId)); 853 *iptr = XtAppAddInput(app, fd, (XtPointer) XtInputReadMask, 854 ProcessInternalConnection, client_data); 855 *watch_data = (XPointer) iptr; 856 } else { 857 iptr = (XtInputId *) *watch_data; 858 XtRemoveInput(*iptr); 859 (void) XtFree(*watch_data); 860 } 861} 862 863void _XtDisplayInitialize( 864 Display *dpy, 865 XtPerDisplay pd, 866 _Xconst char* name, 867 XrmOptionDescRec *urlist, 868 Cardinal num_urs, 869 int *argc, 870 char **argv) 871{ 872 Boolean tmp_bool; 873 XrmValue value; 874 XrmOptionDescRec *options; 875 Cardinal num_options; 876 XrmDatabase db; 877 XrmName name_list[2]; 878 XrmClass class_list[2]; 879 XrmHashTable* search_list; 880 int search_list_size = SEARCH_LIST_SIZE; 881 882 GetLanguage(dpy, pd); 883 884 /* Parse the command line and remove Xt arguments from argv */ 885 _MergeOptionTables( opTable, XtNumber(opTable), urlist, num_urs, 886 &options, &num_options ); 887 XrmParseCommand(&pd->cmd_db, options, num_options, name, argc, argv); 888 889 db = XtScreenDatabase(DefaultScreenOfDisplay(dpy)); 890 891 if (!(search_list = (XrmHashTable*) 892 ALLOCATE_LOCAL( SEARCH_LIST_SIZE*sizeof(XrmHashTable)))) 893 _XtAllocError(NULL); 894 name_list[0] = pd->name; 895 class_list[0] = pd->class; 896 name_list[1] = NULLQUARK; 897 class_list[1] = NULLQUARK; 898 899 while (!XrmQGetSearchList(db, name_list, class_list, 900 search_list, search_list_size)) { 901 XrmHashTable* old = search_list; 902 Cardinal size = (search_list_size*=2)*sizeof(XrmHashTable); 903 if (!(search_list = (XrmHashTable*)ALLOCATE_LOCAL(size))) 904 _XtAllocError(NULL); 905 (void) memmove((char*)search_list, (char*)old, (size>>1) ); 906 DEALLOCATE_LOCAL(old); 907 } 908 909 value.size = sizeof(tmp_bool); 910 value.addr = (XtPointer)&tmp_bool; 911 if (_GetResource(dpy, search_list, "synchronous", "Synchronous", 912 XtRBoolean, &value)) { 913 int i; 914 Display **dpyP = pd->appContext->list; 915 pd->appContext->sync = tmp_bool; 916 for (i = pd->appContext->count; i; dpyP++, i--) { 917 (void) XSynchronize(*dpyP, (Bool)tmp_bool); 918 } 919 } else { 920 (void) XSynchronize(dpy, (Bool)pd->appContext->sync); 921 } 922 923 if (_GetResource(dpy, search_list, "reverseVideo", "ReverseVideo", 924 XtRBoolean, &value) 925 && tmp_bool) { 926 pd->rv = True; 927 } 928 929 value.size = sizeof(pd->multi_click_time); 930 value.addr = (XtPointer)&pd->multi_click_time; 931 if (!_GetResource(dpy, search_list, 932 "multiClickTime", "MultiClickTime", 933 XtRInt, &value)) { 934 pd->multi_click_time = 200; 935 } 936 937 value.size = sizeof(pd->appContext->selectionTimeout); 938 value.addr = (XtPointer)&pd->appContext->selectionTimeout; 939 (void)_GetResource(dpy, search_list, 940 "selectionTimeout", "SelectionTimeout", 941 XtRInt, &value); 942 943#ifndef NO_IDENTIFY_WINDOWS 944 value.size = sizeof(pd->appContext->identify_windows); 945 value.addr = (XtPointer)&pd->appContext->identify_windows; 946 (void)_GetResource(dpy, search_list, 947 "xtIdentifyWindows", "XtDebug", 948 XtRBoolean, &value); 949#endif 950 951 XAddConnectionWatch(dpy, ConnectionWatch, (XPointer) dpy); 952 953 XtFree( (XtPointer)options ); 954 DEALLOCATE_LOCAL( search_list ); 955} 956 957/* Function Name: XtAppSetFallbackResources 958 * Description: Sets the fallback resource list that will be loaded 959 * at display initialization time. 960 * Arguments: app_context - the app context. 961 * specification_list - the resource specification list. 962 * Returns: none. 963 */ 964 965void 966XtAppSetFallbackResources( 967 XtAppContext app_context, 968 String *specification_list) 969{ 970 LOCK_APP(app_context); 971 app_context->fallback_resources = specification_list; 972 UNLOCK_APP(app_context); 973} 974 975 976Widget XtOpenApplication(XtAppContext *app_context_return, 977 _Xconst char *application_class, 978 XrmOptionDescRec *options, Cardinal num_options, 979 int *argc_in_out, String *argv_in_out, 980 String *fallback_resources, WidgetClass widget_class, 981 ArgList args_in, Cardinal num_args_in) 982{ 983 XtAppContext app_con; 984 Display * dpy; 985 register int saved_argc = *argc_in_out; 986 Widget root; 987 Arg args[3], *merged_args; 988 Cardinal num = 0; 989 990 XtToolkitInitialize(); /* cannot be moved into _XtAppInit */ 991 992 dpy = _XtAppInit(&app_con, (String)application_class, options, num_options, 993 argc_in_out, &argv_in_out, fallback_resources); 994 995 LOCK_APP(app_con); 996 XtSetArg(args[num], XtNscreen, DefaultScreenOfDisplay(dpy)); num++; 997 XtSetArg(args[num], XtNargc, saved_argc); num++; 998 XtSetArg(args[num], XtNargv, argv_in_out); num++; 999 1000 merged_args = XtMergeArgLists(args_in, num_args_in, args, num); 1001 num += num_args_in; 1002 1003 root = XtAppCreateShell(NULL, application_class, widget_class, dpy, 1004 merged_args, num); 1005 1006 if (app_context_return) 1007 *app_context_return = app_con; 1008 1009 XtFree((XtPointer)merged_args); 1010 XtFree((XtPointer)argv_in_out); 1011 UNLOCK_APP(app_con); 1012 return root; 1013} 1014 1015 1016Widget 1017XtAppInitialize( 1018 XtAppContext * app_context_return, 1019 _Xconst char* application_class, 1020 XrmOptionDescRec *options, 1021 Cardinal num_options, 1022 int *argc_in_out, 1023 String *argv_in_out, 1024 String *fallback_resources, 1025 ArgList args_in, 1026 Cardinal num_args_in) 1027{ 1028 return XtOpenApplication(app_context_return, application_class, 1029 options, num_options, 1030 argc_in_out, argv_in_out, fallback_resources, 1031 applicationShellWidgetClass, 1032 args_in, num_args_in); 1033} 1034 1035 1036/*ARGSUSED*/ 1037Widget 1038XtInitialize( 1039 _Xconst char* name, 1040 _Xconst char* classname, 1041 XrmOptionDescRec *options, 1042 Cardinal num_options, 1043 int *argc, 1044 String *argv) 1045{ 1046 Widget root; 1047 XtAppContext app_con; 1048 register ProcessContext process = _XtGetProcessContext(); 1049 1050 root = XtAppInitialize(&app_con, classname, options, num_options, 1051 argc, argv, NULL, NULL, (Cardinal) 0); 1052 1053 LOCK_PROCESS; 1054 process->defaultAppContext = app_con; 1055 UNLOCK_PROCESS; 1056 return root; 1057} 1058