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