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#ifdef HAVE_CONFIG_H 72#include <config.h> 73#endif 74#include "IntrinsicI.h" 75#include "VarargsI.h" 76#include "Shell.h" 77#include "ShellP.h" 78#include "StringDefs.h" 79#include <stdio.h> 80 81static XrmClass QBoolean, QString, QCallProc, QImmediate; 82static XrmName QinitialResourcesPersistent, QInitialResourcesPersistent; 83static XrmClass QTranslations, QTranslationTable; 84static XrmName Qtranslations, QbaseTranslations; 85static XrmName Qscreen; 86static XrmClass QScreen; 87 88void 89_XtCopyFromParent(Widget widget, int offset, XrmValue *value) 90{ 91 if (widget->core.parent == NULL) { 92 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 93 "invalidParent", "xtCopyFromParent", XtCXtToolkitError, 94 "CopyFromParent must have non-NULL parent", NULL, NULL); 95 value->addr = NULL; 96 return; 97 } 98 value->addr = (XPointer) (((char *) widget->core.parent) + offset); 99} /* _XtCopyFromParent */ 100 101void 102_XtCopyFromArg(XtArgVal src, char *dst, register unsigned int size) 103{ 104 if (size > sizeof(XtArgVal)) 105 (void) memmove((char *) dst, (char *) src, (size_t) size); 106 else { 107 union { 108 long longval; 109#ifdef LONG64 110 int intval; 111#endif 112 short shortval; 113 char charval; 114 char *charptr; 115 XtPointer ptr; 116 } u; 117 char *p = (char *) &u; 118 119 if (size == sizeof(long)) 120 u.longval = (long) src; 121#ifdef LONG64 122 else if (size == sizeof(int)) 123 u.intval = (int) src; 124#endif 125 else if (size == sizeof(short)) 126 u.shortval = (short) src; 127 else if (size == sizeof(char)) 128 u.charval = (char) src; 129 else if (size == sizeof(XtPointer)) 130 u.ptr = (XtPointer) src; 131 else if (size == sizeof(char *)) 132 u.charptr = (char *) src; 133 else 134 p = (char *) &src; 135 136 (void) memcpy(dst, p, (size_t) size); 137 } 138} /* _XtCopyFromArg */ 139 140void 141_XtCopyToArg(char *src, XtArgVal *dst, register unsigned int size) 142{ 143 if (!*dst) { 144#ifdef GETVALUES_BUG 145 /* old GetValues semantics (storing directly into arglists) are bad, 146 * but preserve for compatibility as long as arglist contains NULL. 147 */ 148 union { 149 long longval; 150#ifdef LONG64 151 int intval; 152#endif 153 short shortval; 154 char charval; 155 char *charptr; 156 XtPointer ptr; 157 } u; 158 159 if (size <= sizeof(XtArgVal)) { 160 (void) memcpy(&u, src, (size_t) size); 161 if (size == sizeof(long)) 162 *dst = (XtArgVal) u.longval; 163#ifdef LONG64 164 else if (size == sizeof(int)) 165 *dst = (XtArgVal) u.intval; 166#endif 167 else if (size == sizeof(short)) 168 *dst = (XtArgVal) u.shortval; 169 else if (size == sizeof(char)) 170 *dst = (XtArgVal) u.charval; 171 else if (size == sizeof(char *)) 172 *dst = (XtArgVal) u.charptr; 173 else if (size == sizeof(XtPointer)) 174 *dst = (XtArgVal) u.ptr; 175 else 176 (void) memmove((char *) dst, (char *) src, (size_t) size); 177 } 178 else 179 (void) memmove((char *) dst, (char *) src, (size_t) size); 180#else 181 XtErrorMsg("invalidGetValues", "xtGetValues", XtCXtToolkitError, 182 "NULL ArgVal in XtGetValues", NULL, NULL); 183#endif 184 } 185 else { 186 /* proper GetValues semantics: argval is pointer to destination */ 187 (void) memmove((char *) *dst, (char *) src, (size_t) size); 188 } 189} /* _XtCopyToArg */ 190 191static void 192CopyToArg(char *src, XtArgVal *dst, register unsigned int size) 193{ 194 if (!*dst) { 195 /* old GetValues semantics (storing directly into arglists) are bad, 196 * but preserve for compatibility as long as arglist contains NULL. 197 */ 198 union { 199 long longval; 200#ifdef LONG64 201 int intval; 202#endif 203 short shortval; 204 char charval; 205 char *charptr; 206 XtPointer ptr; 207 } u; 208 209 if (size <= sizeof(XtArgVal)) { 210 (void) memcpy(&u, src, (size_t) size); 211 if (size == sizeof(long)) 212 *dst = (XtArgVal) u.longval; 213#ifdef LONG64 214 else if (size == sizeof(int)) 215 *dst = (XtArgVal) u.intval; 216#endif 217 else if (size == sizeof(short)) 218 *dst = (XtArgVal) u.shortval; 219 else if (size == sizeof(char)) 220 *dst = (XtArgVal) u.charval; 221 else if (size == sizeof(char *)) 222 *dst = (XtArgVal) u.charptr; 223 else if (size == sizeof(XtPointer)) 224 *dst = (XtArgVal) u.ptr; 225 else 226 (void) memmove((char *) dst, (char *) src, (size_t) size); 227 } 228 else 229 (void) memmove((char *) dst, (char *) src, (size_t) size); 230 } 231 else { 232 /* proper GetValues semantics: argval is pointer to destination */ 233 (void) memmove((char *) *dst, (char *) src, (size_t) size); 234 } 235} /* CopyToArg */ 236 237static Cardinal 238CountTreeDepth(Widget w) 239{ 240 Cardinal count; 241 242 for (count = 1; w != NULL; w = (Widget) w->core.parent) 243 count++; 244 245 return count; 246} 247 248static void 249GetNamesAndClasses(register Widget w, 250 register XrmNameList names, 251 register XrmClassList classes) 252{ 253 register Cardinal length, j; 254 register XrmQuark t; 255 WidgetClass class; 256 257 /* Return null-terminated quark arrays, with length the number of 258 quarks (not including NULL) */ 259 260 LOCK_PROCESS; 261 for (length = 0; w != NULL; w = (Widget) w->core.parent) { 262 names[length] = w->core.xrm_name; 263 class = XtClass(w); 264 /* KLUDGE KLUDGE KLUDGE KLUDGE */ 265 if (w->core.parent == NULL && XtIsApplicationShell(w)) { 266 classes[length] = 267 ((ApplicationShellWidget) w)->application.xrm_class; 268 } 269 else 270 classes[length] = class->core_class.xrm_class; 271 length++; 272 } 273 UNLOCK_PROCESS; 274 /* They're in backwards order, flop them around */ 275 for (j = 0; j < length / 2; j++) { 276 t = names[j]; 277 names[j] = names[length - j - 1]; 278 names[length - j - 1] = t; 279 t = classes[j]; 280 classes[j] = classes[length - j - 1]; 281 classes[length - j - 1] = t; 282 } 283 names[length] = NULLQUARK; 284 classes[length] = NULLQUARK; 285} /* GetNamesAndClasses */ 286 287/* Spiffy fast compiled form of resource list. */ 288/* XtResourceLists are compiled in-place into XrmResourceLists */ 289/* All atoms are replaced by quarks, and offsets are -offset-1 to */ 290/* indicate that this list has been compiled already */ 291 292void 293_XtCompileResourceList(register XtResourceList resources, 294 Cardinal num_resources) 295{ 296 register Cardinal count; 297 298#define xrmres ((XrmResourceList) resources) 299#define PSToQ XrmPermStringToQuark 300 301 for (count = 0; count < num_resources; resources++, count++) { 302 xrmres->xrm_name = PSToQ(resources->resource_name); 303 xrmres->xrm_class = PSToQ(resources->resource_class); 304 xrmres->xrm_type = PSToQ(resources->resource_type); 305 xrmres->xrm_offset = (int) 306 (-(int) resources->resource_offset - 1); 307 xrmres->xrm_default_type = PSToQ(resources->default_type); 308 } 309#undef PSToQ 310#undef xrmres 311} /* _XtCompileResourceList */ 312 313/* Like _XtCompileResourceList, but strings are not permanent */ 314static void 315XrmCompileResourceListEphem(register XtResourceList resources, 316 Cardinal num_resources) 317{ 318 register Cardinal count; 319 320#define xrmres ((XrmResourceList) resources) 321 322 for (count = 0; count < num_resources; resources++, count++) { 323 xrmres->xrm_name = StringToName(resources->resource_name); 324 xrmres->xrm_class = StringToClass(resources->resource_class); 325 xrmres->xrm_type = StringToQuark(resources->resource_type); 326 xrmres->xrm_offset = (int) 327 (-(int) resources->resource_offset - 1); 328 xrmres->xrm_default_type = StringToQuark(resources->default_type); 329 } 330#undef xrmres 331} /* XrmCompileResourceListEphem */ 332 333static void 334BadSize(Cardinal size, XrmQuark name) 335{ 336 String params[2]; 337 Cardinal num_params = 2; 338 339 params[0] = (String) (XtIntPtr) size; 340 params[1] = XrmQuarkToString(name); 341 XtWarningMsg("invalidSizeOverride", "xtDependencies", XtCXtToolkitError, 342 "Representation size %d must match superclass's to override %s", 343 params, &num_params); 344} /* BadType */ 345 346/* 347 * Create a new resource list, with the class resources following the 348 * superclass's resources. If a resource in the class list overrides 349 * a superclass resource, then just replace the superclass entry in place. 350 * 351 * At the same time, add a level of indirection to the XtResourceList to 352 * create and XrmResourceList. 353 */ 354void 355_XtDependencies(XtResourceList *class_resp, /* VAR */ 356 Cardinal *class_num_resp, /* VAR */ 357 XrmResourceList *super_res, 358 Cardinal super_num_res, 359 Cardinal super_widget_size) 360{ 361 register XrmResourceList *new_res; 362 Cardinal new_num_res; 363 XrmResourceList class_res = (XrmResourceList) *class_resp; 364 Cardinal class_num_res = *class_num_resp; 365 register Cardinal i, j; 366 Cardinal new_next; 367 368 if (class_num_res == 0) { 369 /* Just point to superclass resource list */ 370 *class_resp = (XtResourceList) super_res; 371 *class_num_resp = super_num_res; 372 return; 373 } 374 375 /* Allocate and initialize new_res with superclass resource pointers */ 376 new_num_res = super_num_res + class_num_res; 377 new_res = XtMallocArray(new_num_res, (Cardinal) sizeof(XrmResourceList)); 378 if (super_num_res > 0) 379 memcpy(new_res, super_res, super_num_res * sizeof(XrmResourceList)); 380 381 /* Put pointers to class resource entries into new_res */ 382 new_next = super_num_res; 383 for (i = 0; i < class_num_res; i++) { 384 if ((Cardinal) (-class_res[i].xrm_offset - 1) < super_widget_size) { 385 /* Probably an override of superclass resources--look for overlap */ 386 for (j = 0; j < super_num_res; j++) { 387 if (class_res[i].xrm_offset == new_res[j]->xrm_offset) { 388 /* Spec is silent on what fields subclass can override. 389 * The only two of real concern are type & size. 390 * Although allowing type to be over-ridden introduces 391 * the possibility of errors, it's at present the only 392 * reasonable way to allow a subclass to force a private 393 * converter to be invoked for a subset of fields. 394 */ 395 /* We do insist that size be identical to superclass */ 396 if (class_res[i].xrm_size != new_res[j]->xrm_size) { 397 BadSize(class_res[i].xrm_size, 398 (XrmQuark) class_res[i].xrm_name); 399 class_res[i].xrm_size = new_res[j]->xrm_size; 400 } 401 new_res[j] = &(class_res[i]); 402 new_num_res--; 403 goto NextResource; 404 } 405 } /* for j */ 406 } 407 /* Not an overlap, add an entry to new_res */ 408 new_res[new_next++] = &(class_res[i]); 409 NextResource:; 410 } /* for i */ 411 412 /* Okay, stuff new resources back into class record */ 413 *class_resp = (XtResourceList) new_res; 414 *class_num_resp = new_num_res; 415} /* _XtDependencies */ 416 417void 418_XtResourceDependencies(WidgetClass wc) 419{ 420 WidgetClass sc; 421 422 sc = wc->core_class.superclass; 423 if (sc == NULL) { 424 _XtDependencies(&(wc->core_class.resources), 425 &(wc->core_class.num_resources), 426 (XrmResourceList *) NULL, (unsigned) 0, (unsigned) 0); 427 } 428 else { 429 _XtDependencies(&(wc->core_class.resources), 430 &(wc->core_class.num_resources), 431 (XrmResourceList *) sc->core_class.resources, 432 sc->core_class.num_resources, 433 sc->core_class.widget_size); 434 } 435} /* _XtResourceDependencies */ 436 437void 438_XtConstraintResDependencies(ConstraintWidgetClass wc) 439{ 440 if (wc == (ConstraintWidgetClass) constraintWidgetClass) { 441 _XtDependencies(&(wc->constraint_class.resources), 442 &(wc->constraint_class.num_resources), 443 (XrmResourceList *) NULL, (unsigned) 0, (unsigned) 0); 444 } 445 else { 446 ConstraintWidgetClass sc; 447 448 sc = (ConstraintWidgetClass) wc->core_class.superclass; 449 _XtDependencies(&(wc->constraint_class.resources), 450 &(wc->constraint_class.num_resources), 451 (XrmResourceList *) sc->constraint_class.resources, 452 sc->constraint_class.num_resources, 453 sc->constraint_class.constraint_size); 454 } 455} /* _XtConstraintResDependencies */ 456 457XrmResourceList * 458_XtCreateIndirectionTable(XtResourceList resources, Cardinal num_resources) 459{ 460 register Cardinal idx; 461 XrmResourceList *table; 462 463 table = XtMallocArray(num_resources, (Cardinal) sizeof(XrmResourceList)); 464 for (idx = 0; idx < num_resources; idx++) 465 table[idx] = (XrmResourceList) (&(resources[idx])); 466 return table; 467} 468 469static XtCacheRef * 470GetResources(Widget widget, /* Widget resources are associated with */ 471 char *base, /* Base address of memory to write to */ 472 XrmNameList names, /* Full inheritance name of widget */ 473 XrmClassList classes, /* Full inheritance class of widget */ 474 XrmResourceList *table, /* The list of resources required. */ 475 unsigned num_resources, /* number of items in resource list */ 476 XrmQuarkList quark_args, /* Arg names quarkified */ 477 ArgList args, /* ArgList to override resources */ 478 unsigned num_args, /* number of items in arg list */ 479 XtTypedArgList typed_args, /* Typed arg list to override resources */ 480 Cardinal *pNumTypedArgs, /* number of items in typed arg list */ 481 Boolean tm_hack) /* do baseTranslations */ 482{ 483/* 484 * assert: *pNumTypedArgs == 0 if num_args > 0 485 * assert: num_args == 0 if *pNumTypedArgs > 0 486 */ 487#define SEARCHLISTLEN 100 488#define MAXRESOURCES 400 489 490 XrmValue value; 491 XrmQuark rawType; 492 XrmValue convValue; 493 XrmHashTable stackSearchList[SEARCHLISTLEN]; 494 XrmHashTable *searchList = stackSearchList; 495 unsigned int searchListSize = SEARCHLISTLEN; 496 Boolean found[MAXRESOURCES]; 497 int typed[MAXRESOURCES]; 498 XtCacheRef cache_ref[MAXRESOURCES]; 499 XtCacheRef *cache_ptr, *cache_base; 500 Boolean persistent_resources = True; 501 Boolean found_persistence = False; 502 int num_typed_args = (int) *pNumTypedArgs; 503 XrmDatabase db; 504 Boolean do_tm_hack = False; 505 506 if ((args == NULL) && (num_args != 0)) { 507 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 508 "invalidArgCount", "getResources", XtCXtToolkitError, 509 "argument count > 0 on NULL argument list", NULL, NULL); 510 num_args = 0; 511 } 512 if (num_resources == 0) { 513 return NULL; 514 } 515 else if (num_resources >= MAXRESOURCES) { 516 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 517 "invalidResourceCount", "getResources", 518 XtCXtToolkitError, "too many resources", NULL, NULL); 519 return NULL; 520 } 521 else if (table == NULL) { 522 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 523 "invalidResourceCount", "getResources", 524 XtCXtToolkitError, 525 "resource count > 0 on NULL resource list", NULL, NULL); 526 return NULL; 527 } 528 529 /* Mark each resource as not found on arg list */ 530 memset((void *) found, 0, (size_t) (num_resources * sizeof(Boolean))); 531 memset((void *) typed, 0, (size_t) (num_resources * sizeof(int))); 532 533 /* Copy the args into the resources, mark each as found */ 534 { 535 register ArgList arg; 536 register XtTypedArgList typed_arg; 537 register XrmName argName; 538 register Cardinal j; 539 register int i; 540 register XrmResourceList rx; 541 register XrmResourceList *res; 542 543 for (arg = args, i = 0; (Cardinal) i < num_args; i++, arg++) { 544 argName = quark_args[i]; 545 if (argName == QinitialResourcesPersistent) { 546 persistent_resources = (Boolean) arg->value; 547 found_persistence = True; 548 continue; 549 } 550 for (j = 0, res = table; j < num_resources; j++, res++) { 551 rx = *res; 552 if (argName == rx->xrm_name) { 553 _XtCopyFromArg(arg->value, 554 base - rx->xrm_offset - 1, rx->xrm_size); 555 found[j] = TRUE; 556 break; 557 } 558 } 559 } 560 for (typed_arg = typed_args, i = 0; i < num_typed_args; 561 i++, typed_arg++) { 562 register XrmRepresentation argType; 563 564 argName = quark_args[i]; 565 argType = (typed_arg->type == NULL) ? NULLQUARK 566 : XrmStringToRepresentation(typed_arg->type); 567 if (argName == QinitialResourcesPersistent) { 568 persistent_resources = (Boolean) typed_arg->value; 569 found_persistence = True; 570 break; 571 } 572 for (j = 0, res = table; j < num_resources; j++, res++) { 573 rx = *res; 574 if (argName == rx->xrm_name) { 575 if (argType != NULLQUARK && argType != rx->xrm_type) { 576 typed[j] = i + 1; 577 } 578 else { 579 _XtCopyFromArg(typed_arg->value, 580 base - rx->xrm_offset - 1, rx->xrm_size); 581 } 582 found[j] = TRUE; 583 break; 584 } 585 } 586 } 587 } 588 589 /* Ask resource manager for a list of database levels that we can 590 do a single-level search on each resource */ 591 592 db = XtScreenDatabase(XtScreenOfObject(widget)); 593 while (!XrmQGetSearchList(db, names, classes, 594 searchList, (int) searchListSize)) { 595 if (searchList == stackSearchList) 596 searchList = NULL; 597 searchListSize *= 2; 598 searchList = XtReallocArray(searchList, searchListSize, 599 (Cardinal) sizeof(XrmHashTable)); 600 } 601 602 if (persistent_resources) 603 cache_base = NULL; 604 else 605 cache_base = cache_ref; 606 /* geez, this is an ugly mess */ 607 if (XtIsShell(widget)) { 608 register XrmResourceList *res; 609 register Cardinal j; 610 Screen *oldscreen = widget->core.screen; 611 612 /* look up screen resource first, since real rdb depends on it */ 613 for (res = table, j = 0; j < num_resources; j++, res++) { 614 if ((*res)->xrm_name != Qscreen) 615 continue; 616 if (typed[j]) { 617 register XtTypedArg *arg = typed_args + typed[j] - 1; 618 XrmQuark from_type; 619 XrmValue from_val, to_val; 620 621 from_type = StringToQuark(arg->type); 622 from_val.size = (Cardinal) arg->size; 623 if ((from_type == QString) || 624 ((unsigned) arg->size > sizeof(XtArgVal))) 625 from_val.addr = (XPointer) arg->value; 626 else 627 from_val.addr = (XPointer) &arg->value; 628 to_val.size = sizeof(Screen *); 629 to_val.addr = (XPointer) &widget->core.screen; 630 found[j] = _XtConvert(widget, from_type, &from_val, 631 QScreen, &to_val, cache_base); 632 if (cache_base && *cache_base) 633 cache_base++; 634 } 635 if (!found[j]) { 636 if (XrmQGetSearchResource(searchList, Qscreen, QScreen, 637 &rawType, &value)) { 638 if (rawType != QScreen) { 639 convValue.size = sizeof(Screen *); 640 convValue.addr = (XPointer) &widget->core.screen; 641 (void) _XtConvert(widget, rawType, &value, 642 QScreen, &convValue, cache_base); 643 if (cache_base && *cache_base) 644 cache_base++; 645 } 646 else { 647 widget->core.screen = *((Screen **) value.addr); 648 } 649 } 650 } 651 break; 652 } 653 /* now get the database to use for the rest of the resources */ 654 if (widget->core.screen != oldscreen) { 655 db = XtScreenDatabase(widget->core.screen); 656 while (!XrmQGetSearchList(db, names, classes, 657 searchList, (int) searchListSize)) { 658 if (searchList == stackSearchList) 659 searchList = NULL; 660 searchList = (XrmHashTable *) XtRealloc((char *) searchList, 661 (Cardinal) (sizeof 662 (XrmHashTable) 663 * 664 (searchListSize 665 *= 2))); 666 } 667 } 668 } 669 670 /* go to the resource manager for those resources not found yet */ 671 /* if it's not in the resource database use the default value */ 672 673 { 674 register XrmResourceList rx; 675 register XrmResourceList *res; 676 register Cardinal j; 677 register XrmRepresentation xrm_type; 678 register XrmRepresentation xrm_default_type; 679 char char_val; 680 short short_val; 681 int int_val; 682 long long_val; 683 char *char_ptr; 684 685 if (!found_persistence) { 686 if (XrmQGetSearchResource(searchList, QinitialResourcesPersistent, 687 QInitialResourcesPersistent, &rawType, 688 &value)) { 689 if (rawType != QBoolean) { 690 convValue.size = sizeof(Boolean); 691 convValue.addr = (XPointer) &persistent_resources; 692 (void) _XtConvert(widget, rawType, &value, QBoolean, 693 &convValue, NULL); 694 } 695 else 696 persistent_resources = *(Boolean *) value.addr; 697 } 698 } 699 if (persistent_resources) 700 cache_ptr = NULL; 701 else if (cache_base) 702 cache_ptr = cache_base; 703 else 704 cache_ptr = cache_ref; 705 706 for (res = table, j = 0; j < num_resources; j++, res++) { 707 rx = *res; 708 xrm_type = (XrmRepresentation) rx->xrm_type; 709 if (typed[j]) { 710 register XtTypedArg *arg = typed_args + typed[j] - 1; 711 712 /* 713 * This resource value has been specified as a typed arg and 714 * has to be converted. Typed arg conversions are done here 715 * to correctly interpose them with normal resource conversions. 716 */ 717 XrmQuark from_type; 718 XrmValue from_val, to_val; 719 Boolean converted; 720 721 from_type = StringToQuark(arg->type); 722 from_val.size = (Cardinal) arg->size; 723 if ((from_type == QString) || 724 ((unsigned) arg->size > sizeof(XtArgVal))) 725 from_val.addr = (XPointer) arg->value; 726 else 727 from_val.addr = (XPointer) &arg->value; 728 to_val.size = rx->xrm_size; 729 to_val.addr = base - rx->xrm_offset - 1; 730 converted = _XtConvert(widget, from_type, &from_val, 731 xrm_type, &to_val, cache_ptr); 732 if (converted) { 733 734 /* Copy the converted value back into the typed argument. 735 * normally the data should be <= sizeof(XtArgVal) and 736 * is stored directly into the 'value' field .... BUT 737 * if the resource size is greater than sizeof(XtArgVal) 738 * then we dynamically alloc a block of store to hold the 739 * data and zap a copy in there !!! .... freeing it later 740 * the size field in the typed arg is negated to indicate 741 * that the store pointed to by the value field is 742 * dynamic ....... 743 * "freeing" happens in the case of _XtCreate after the 744 * CallInitialize ..... other clients of GetResources 745 * using typed args should be aware of the need to free 746 * this store ..... 747 */ 748 749 if (rx->xrm_size > sizeof(XtArgVal)) { 750 arg->value = 751 (XtArgVal) (void *) __XtMalloc(rx->xrm_size); 752 arg->size = -(arg->size); 753 } 754 else { /* will fit - copy directly into value field */ 755 arg->value = (XtArgVal) NULL; 756 } 757 CopyToArg((char *) (base - rx->xrm_offset - 1), 758 &arg->value, rx->xrm_size); 759 760 } 761 else { 762 /* Conversion failed. Get default value. */ 763 found[j] = False; 764 } 765 766 if (cache_ptr && *cache_ptr) 767 cache_ptr++; 768 } 769 770 if (!found[j]) { 771 Boolean already_copied = False; 772 Boolean have_value = False; 773 774 if (XrmQGetSearchResource(searchList, 775 (XrmName) rx->xrm_name, 776 (XrmClass) rx->xrm_class, &rawType, 777 &value)) { 778 if (rawType != xrm_type) { 779 convValue.size = rx->xrm_size; 780 convValue.addr = (XPointer) (base - rx->xrm_offset - 1); 781 already_copied = have_value = 782 _XtConvert(widget, rawType, &value, 783 xrm_type, &convValue, cache_ptr); 784 if (cache_ptr && *cache_ptr) 785 cache_ptr++; 786 } 787 else 788 have_value = True; 789 if (have_value && rx->xrm_name == Qtranslations) 790 do_tm_hack = True; 791 } 792 LOCK_PROCESS; 793 if (!have_value && ((rx->xrm_default_type == QImmediate) 794 || (rx->xrm_default_type == xrm_type) 795 || (rx->xrm_default_addr != NULL))) { 796 /* Convert default value to proper type */ 797 xrm_default_type = (XrmRepresentation) rx->xrm_default_type; 798 if (xrm_default_type == QCallProc) { 799 (*(XtResourceDefaultProc) (rx->xrm_default_addr)) 800 (widget, -(rx->xrm_offset + 1), &value); 801 802 } 803 else if (xrm_default_type == QImmediate) { 804 /* XtRImmediate == XtRString for type XtRString */ 805 if (xrm_type == QString) { 806 value.addr = rx->xrm_default_addr; 807 } 808 else if (rx->xrm_size == sizeof(int)) { 809 int_val = (int) (long) rx->xrm_default_addr; 810 value.addr = (XPointer) &int_val; 811 } 812 else if (rx->xrm_size == sizeof(short)) { 813 short_val = (short) (long) rx->xrm_default_addr; 814 value.addr = (XPointer) &short_val; 815 } 816 else if (rx->xrm_size == sizeof(char)) { 817 char_val = (char) (long) rx->xrm_default_addr; 818 value.addr = (XPointer) &char_val; 819 } 820 else if (rx->xrm_size == sizeof(long)) { 821 long_val = (long) rx->xrm_default_addr; 822 value.addr = (XPointer) &long_val; 823 } 824 else if (rx->xrm_size == sizeof(char *)) { 825 char_ptr = (char *) rx->xrm_default_addr; 826 value.addr = (XPointer) &char_ptr; 827 } 828 else { 829 value.addr = (XPointer) &(rx->xrm_default_addr); 830 } 831 } 832 else if (xrm_default_type == xrm_type) { 833 value.addr = rx->xrm_default_addr; 834 } 835 else { 836 value.addr = rx->xrm_default_addr; 837 if (xrm_default_type == QString) { 838 value.size = 839 (unsigned) strlen((char *) value.addr) + 1; 840 } 841 else { 842 value.size = sizeof(XtPointer); 843 } 844 convValue.size = rx->xrm_size; 845 convValue.addr = (XPointer) (base - rx->xrm_offset - 1); 846 already_copied = 847 _XtConvert(widget, xrm_default_type, &value, 848 xrm_type, &convValue, cache_ptr); 849 if (!already_copied) 850 value.addr = NULL; 851 if (cache_ptr && *cache_ptr) 852 cache_ptr++; 853 } 854 } 855 if (!already_copied) { 856 if (xrm_type == QString) { 857 *((String *) (base - rx->xrm_offset - 1)) = value.addr; 858 } 859 else { 860 if (value.addr != NULL) { 861 XtMemmove(base - rx->xrm_offset - 1, 862 value.addr, rx->xrm_size); 863 } 864 else { 865 /* didn't get value, initialize to NULL... */ 866 XtBZero(base - rx->xrm_offset - 1, rx->xrm_size); 867 } 868 } 869 } 870 UNLOCK_PROCESS; 871 } 872 } 873 for (res = table, j = 0; j < num_resources; j++, res++) { 874 if (!found[j] && typed[j]) { 875 /* 876 * This resource value was specified as a typed arg. 877 * However, the default value is being used here since 878 * type type conversion failed, so we compress the list. 879 */ 880 register XtTypedArg *arg = typed_args + typed[j] - 1; 881 register int i; 882 883 for (i = num_typed_args - typed[j]; i > 0; i--, arg++) { 884 *arg = *(arg + 1); 885 } 886 num_typed_args--; 887 } 888 } 889 if (tm_hack) 890 widget->core.tm.current_state = NULL; 891 if (tm_hack && 892 (!widget->core.tm.translations || 893 (do_tm_hack && 894 widget->core.tm.translations->operation != XtTableReplace)) && 895 XrmQGetSearchResource(searchList, QbaseTranslations, 896 QTranslations, &rawType, &value)) { 897 if (rawType != QTranslationTable) { 898 convValue.size = sizeof(XtTranslations); 899 convValue.addr = (XPointer) &widget->core.tm.current_state; 900 (void) _XtConvert(widget, rawType, &value, 901 QTranslationTable, &convValue, cache_ptr); 902 if (cache_ptr && *cache_ptr) 903 cache_ptr++; 904 } 905 else { 906 /* value.addr can be NULL see: !already_copied */ 907 if (value.addr) 908 *((XtTranslations *) &widget->core.tm.current_state) = 909 *((XtTranslations *) value.addr); 910 } 911 } 912 } 913 if ((Cardinal) num_typed_args != *pNumTypedArgs) 914 *pNumTypedArgs = (Cardinal) num_typed_args; 915 if (searchList != stackSearchList) 916 XtFree((char *) searchList); 917 if (!cache_ptr) 918 cache_ptr = cache_base; 919 if (cache_ptr && cache_ptr != cache_ref) { 920 int cache_ref_size = (int) (cache_ptr - cache_ref); 921 XtCacheRef *refs = XtMallocArray((Cardinal) cache_ref_size + 1, 922 (Cardinal) sizeof(XtCacheRef)); 923 924 (void) memcpy(refs, cache_ref, 925 sizeof(XtCacheRef) * (size_t) cache_ref_size); 926 refs[cache_ref_size] = NULL; 927 return refs; 928 } 929 return (XtCacheRef *) NULL; 930} 931 932static void 933CacheArgs(ArgList args, 934 Cardinal num_args, 935 XtTypedArgList typed_args, 936 Cardinal num_typed_args, 937 XrmQuarkList quark_cache, 938 Cardinal num_quarks, 939 XrmQuarkList *pQuarks) /* RETURN */ 940{ 941 register XrmQuarkList quarks; 942 register Cardinal i; 943 register Cardinal count; 944 945 count = (args != NULL) ? num_args : num_typed_args; 946 947 if (num_quarks < count) { 948 quarks = XtMallocArray(count, (Cardinal) sizeof(XrmQuark)); 949 } 950 else { 951 quarks = quark_cache; 952 } 953 *pQuarks = quarks; 954 955 if (args != NULL) { 956 for (i = count; i; i--) 957 *quarks++ = StringToQuark((args++)->name); 958 } 959 else { 960 for (i = count; i; i--) 961 *quarks++ = StringToQuark((typed_args++)->name); 962 } 963} 964 965#define FreeCache(cache, pointer) \ 966 if (cache != pointer) XtFree((char *)pointer) 967 968XtCacheRef * 969_XtGetResources(register Widget w, 970 ArgList args, 971 Cardinal num_args, 972 XtTypedArgList typed_args, 973 Cardinal *num_typed_args) 974{ 975 XrmName *names, names_s[50]; 976 XrmClass *classes, classes_s[50]; 977 XrmQuark quark_cache[100]; 978 XrmQuarkList quark_args; 979 WidgetClass wc; 980 XtCacheRef *cache_refs = NULL; 981 Cardinal count; 982 983 wc = XtClass(w); 984 985 count = CountTreeDepth(w); 986 names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s); 987 classes = (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s); 988 if (names == NULL || classes == NULL) { 989 _XtAllocError(NULL); 990 } 991 else { 992 993 /* Get names, classes for widget and ancestors */ 994 GetNamesAndClasses(w, names, classes); 995 996 /* Compile arg list into quarks */ 997 CacheArgs(args, num_args, typed_args, *num_typed_args, quark_cache, 998 XtNumber(quark_cache), &quark_args); 999 1000 /* Get normal resources */ 1001 LOCK_PROCESS; 1002 cache_refs = GetResources(w, (char *) w, names, classes, 1003 (XrmResourceList *) wc->core_class.resources, 1004 wc->core_class.num_resources, quark_args, 1005 args, num_args, typed_args, num_typed_args, 1006 XtIsWidget(w)); 1007 1008 if (w->core.constraints != NULL) { 1009 ConstraintWidgetClass cwc; 1010 XtCacheRef *cache_refs_core; 1011 1012 cwc = (ConstraintWidgetClass) XtClass(w->core.parent); 1013 cache_refs_core = 1014 GetResources(w, (char *) w->core.constraints, names, classes, 1015 (XrmResourceList *) cwc->constraint_class. 1016 resources, cwc->constraint_class.num_resources, 1017 quark_args, args, num_args, typed_args, 1018 num_typed_args, False); 1019 XtFree((char *) cache_refs_core); 1020 } 1021 FreeCache(quark_cache, quark_args); 1022 UNLOCK_PROCESS; 1023 XtStackFree((XtPointer) names, names_s); 1024 XtStackFree((XtPointer) classes, classes_s); 1025 } 1026 return cache_refs; 1027} /* _XtGetResources */ 1028 1029void 1030_XtGetSubresources(Widget w, /* Widget "parent" of subobject */ 1031 XtPointer base, /* Base address to write to */ 1032 const char *name, /* name of subobject */ 1033 const char *class, /* class of subobject */ 1034 XtResourceList resources, /* resource list for subobject */ 1035 Cardinal num_resources, 1036 ArgList args, /* arg list to override resources */ 1037 Cardinal num_args, 1038 XtTypedArgList typed_args, 1039 Cardinal num_typed_args) 1040{ 1041 XrmName *names, names_s[50]; 1042 XrmClass *classes, classes_s[50]; 1043 XrmQuark quark_cache[100]; 1044 XrmQuarkList quark_args; 1045 Cardinal count, ntyped_args = num_typed_args; 1046 XtCacheRef *Resrc = NULL; 1047 1048 WIDGET_TO_APPCON(w); 1049 1050 if (num_resources == 0) 1051 return; 1052 1053 LOCK_APP(app); 1054 count = CountTreeDepth(w); 1055 count++; /* make sure there's enough room for name and class */ 1056 names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s); 1057 classes = (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s); 1058 if (names == NULL || classes == NULL) { 1059 _XtAllocError(NULL); 1060 } 1061 else { 1062 XrmResourceList *table; 1063 1064 /* Get full name, class of subobject */ 1065 GetNamesAndClasses(w, names, classes); 1066 count -= 2; 1067 names[count] = StringToName(name); 1068 classes[count] = StringToClass(class); 1069 count++; 1070 names[count] = NULLQUARK; 1071 classes[count] = NULLQUARK; 1072 1073 /* Compile arg list into quarks */ 1074 CacheArgs(args, num_args, typed_args, num_typed_args, 1075 quark_cache, XtNumber(quark_cache), &quark_args); 1076 1077 /* Compile resource list if needed */ 1078 if (((int) resources->resource_offset) >= 0) { 1079 XrmCompileResourceListEphem(resources, num_resources); 1080 } 1081 table = _XtCreateIndirectionTable(resources, num_resources); 1082 Resrc = 1083 GetResources(w, (char *) base, names, classes, table, num_resources, 1084 quark_args, args, num_args, typed_args, &ntyped_args, 1085 False); 1086 FreeCache(quark_cache, quark_args); 1087 XtFree((char *) table); 1088 XtFree((char *) Resrc); 1089 XtStackFree((XtPointer) names, names_s); 1090 XtStackFree((XtPointer) classes, classes_s); 1091 UNLOCK_APP(app); 1092 } 1093} 1094 1095void 1096XtGetSubresources(Widget w, /* Widget "parent" of subobject */ 1097 XtPointer base, /* Base address to write to */ 1098 _Xconst char *name, /* name of subobject */ 1099 _Xconst char *class, /* class of subobject */ 1100 XtResourceList resources, /* resource list for subobject */ 1101 Cardinal num_resources, 1102 ArgList args, /* arg list to override resources */ 1103 Cardinal num_args) 1104{ 1105 _XtGetSubresources(w, base, name, class, resources, num_resources, args, 1106 num_args, NULL, 0); 1107} 1108 1109void 1110_XtGetApplicationResources(Widget w, /* Application shell widget */ 1111 XtPointer base, /* Base address to write to */ 1112 XtResourceList resources, /* resource list for subobject */ 1113 Cardinal num_resources, 1114 ArgList args, /* arg list to override resources */ 1115 Cardinal num_args, 1116 XtTypedArgList typed_args, 1117 Cardinal num_typed_args) 1118{ 1119 XrmName *names, names_s[50]; 1120 XrmClass *classes, classes_s[50]; 1121 XrmQuark quark_cache[100]; 1122 XrmQuarkList quark_args; 1123 XrmResourceList *table; 1124 Cardinal ntyped_args = num_typed_args; 1125 1126#ifdef XTHREADS 1127 XtAppContext app; 1128#endif 1129 XtCacheRef *Resrc = NULL; 1130 1131 if (num_resources == 0) 1132 return; 1133 1134#ifdef XTHREADS 1135 if (w == NULL) 1136 app = _XtDefaultAppContext(); 1137 else 1138 app = XtWidgetToApplicationContext(w); 1139#endif 1140 1141 LOCK_APP(app); 1142 /* Get full name, class of application */ 1143 if (w == NULL) { 1144 /* hack for R2 compatibility */ 1145 XtPerDisplay pd = _XtGetPerDisplay(_XtDefaultAppContext()->list[0]); 1146 1147 names = (XrmName *) XtStackAlloc(2 * sizeof(XrmName), names_s); 1148 classes = (XrmClass *) XtStackAlloc(2 * sizeof(XrmClass), classes_s); 1149 if (names == NULL || classes == NULL) { 1150 _XtAllocError(NULL); 1151 } 1152 else { 1153 names[0] = pd->name; 1154 names[1] = NULLQUARK; 1155 classes[0] = pd->class; 1156 classes[1] = NULLQUARK; 1157 } 1158 } 1159 else { 1160 Cardinal count = CountTreeDepth(w); 1161 1162 names = (XrmName *) XtStackAlloc(count * sizeof(XrmName), names_s); 1163 classes = 1164 (XrmClass *) XtStackAlloc(count * sizeof(XrmClass), classes_s); 1165 if (names == NULL || classes == NULL) { 1166 _XtAllocError(NULL); 1167 } 1168 else { 1169 GetNamesAndClasses(w, names, classes); 1170 } 1171 } 1172 1173 /* Compile arg list into quarks */ 1174 CacheArgs(args, num_args, typed_args, num_typed_args, quark_cache, 1175 XtNumber(quark_cache), &quark_args); 1176 /* Compile resource list if needed */ 1177 if (((int) resources->resource_offset) >= 0) { 1178 XrmCompileResourceListEphem(resources, num_resources); 1179 } 1180 table = _XtCreateIndirectionTable(resources, num_resources); 1181 1182 Resrc = GetResources(w, (char *) base, names, classes, table, num_resources, 1183 quark_args, args, num_args, 1184 typed_args, &ntyped_args, False); 1185 FreeCache(quark_cache, quark_args); 1186 XtFree((char *) table); 1187 XtFree((char *) Resrc); 1188 if (w != NULL) { 1189 XtStackFree((XtPointer) names, names_s); 1190 XtStackFree((XtPointer) classes, classes_s); 1191 } 1192 UNLOCK_APP(app); 1193} 1194 1195void 1196XtGetApplicationResources(Widget w, /* Application shell widget */ 1197 XtPointer base, /* Base address to write to */ 1198 XtResourceList resources, /* resource list for subobject */ 1199 Cardinal num_resources, 1200 ArgList args, /* arg list to override resources */ 1201 Cardinal num_args) 1202{ 1203 _XtGetApplicationResources(w, base, resources, num_resources, args, 1204 num_args, NULL, 0); 1205} 1206 1207static Boolean initialized = FALSE; 1208 1209void 1210_XtResourceListInitialize(void) 1211{ 1212 LOCK_PROCESS; 1213 if (initialized) { 1214 XtWarningMsg("initializationError", "xtInitialize", XtCXtToolkitError, 1215 "Initializing Resource Lists twice", NULL, NULL); 1216 UNLOCK_PROCESS; 1217 return; 1218 } 1219 initialized = TRUE; 1220 UNLOCK_PROCESS; 1221 1222 QBoolean = XrmPermStringToQuark(XtCBoolean); 1223 QString = XrmPermStringToQuark(XtCString); 1224 QCallProc = XrmPermStringToQuark(XtRCallProc); 1225 QImmediate = XrmPermStringToQuark(XtRImmediate); 1226 QinitialResourcesPersistent = 1227 XrmPermStringToQuark(XtNinitialResourcesPersistent); 1228 QInitialResourcesPersistent = 1229 XrmPermStringToQuark(XtCInitialResourcesPersistent); 1230 Qtranslations = XrmPermStringToQuark(XtNtranslations); 1231 QbaseTranslations = XrmPermStringToQuark("baseTranslations"); 1232 QTranslations = XrmPermStringToQuark(XtCTranslations); 1233 QTranslationTable = XrmPermStringToQuark(XtRTranslationTable); 1234 Qscreen = XrmPermStringToQuark(XtNscreen); 1235 QScreen = XrmPermStringToQuark(XtCScreen); 1236} 1237