Intrinsic.c revision 1477040f
1/* $Xorg: Intrinsic.c,v 1.4 2001/02/09 02:03:55 xorgcvs Exp $ */ 2 3/*********************************************************** 4Copyright 1993 Sun Microsystems, Inc. All rights reserved. 5 6Permission is hereby granted, free of charge, to any person obtaining a 7copy of this software and associated documentation files (the "Software"), 8to deal in the Software without restriction, including without limitation 9the rights to use, copy, modify, merge, publish, distribute, sublicense, 10and/or sell copies of the Software, and to permit persons to whom the 11Software is furnished to do so, subject to the following conditions: 12 13The above copyright notice and this permission notice (including the next 14paragraph) shall be included in all copies or substantial portions of the 15Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23DEALINGS IN THE SOFTWARE. 24 25Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Digital not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45******************************************************************/ 46/* $XFree86: xc/lib/Xt/Intrinsic.c,v 3.22 2003/01/12 03:55:46 tsi Exp $ */ 47 48/* 49 50Copyright 1987, 1988, 1994, 1998 The Open Group 51 52Permission to use, copy, modify, distribute, and sell this software and its 53documentation for any purpose is hereby granted without fee, provided that 54the above copyright notice appear in all copies and that both that 55copyright notice and this permission notice appear in supporting 56documentation. 57 58The above copyright notice and this permission notice shall be included in 59all copies or substantial portions of the Software. 60 61THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 65AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 66CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 67 68Except as contained in this notice, the name of The Open Group shall not be 69used in advertising or otherwise to promote the sale, use or other dealings 70in this Software without prior written authorization from The Open Group. 71 72*/ 73 74#define INTRINSIC_C 75 76#ifdef HAVE_CONFIG_H 77#include <config.h> 78#endif 79#include "IntrinsicI.h" 80#include "VarargsI.h" /* for geoTattler */ 81#ifndef NO_IDENTIFY_WINDOWS 82#include <X11/Xatom.h> 83#endif 84#ifndef VMS 85#include <sys/stat.h> 86#endif /* VMS */ 87 88#include <stdlib.h> 89 90String XtCXtToolkitError = "XtToolkitError"; 91 92Boolean XtIsSubclass( 93 Widget widget, 94 WidgetClass widgetClass) 95{ 96 register WidgetClass w; 97 Boolean retval = FALSE; 98 WIDGET_TO_APPCON(widget); 99 100 LOCK_APP(app); 101 LOCK_PROCESS; 102 for (w = widget->core.widget_class; w != NULL; w = w->core_class.superclass) 103 if (w == widgetClass) { 104 retval = TRUE; 105 break; 106 } 107 UNLOCK_PROCESS; 108 UNLOCK_APP(app); 109 return retval; 110} /* XtIsSubclass */ 111 112 113Boolean _XtCheckSubclassFlag( 114 Widget object, 115 _XtXtEnum flag) 116{ 117 Boolean retval; 118 119 LOCK_PROCESS; 120 if (object->core.widget_class->core_class.class_inited & flag) 121 retval = TRUE; 122 else 123 retval = FALSE; 124 UNLOCK_PROCESS; 125 return retval; 126} /*_XtVerifySubclass */ 127 128 129Boolean _XtIsSubclassOf( 130 Widget object, 131 WidgetClass widgetClass, 132 WidgetClass superClass, 133 _XtXtEnum flag) 134{ 135 LOCK_PROCESS; 136 if (!(object->core.widget_class->core_class.class_inited & flag)) { 137 UNLOCK_PROCESS; 138 return False; 139 } else { 140 register WidgetClass c = object->core.widget_class; 141 while (c != superClass) { 142 if (c == widgetClass) { 143 UNLOCK_PROCESS; 144 return True; 145 } 146 c = c->core_class.superclass; 147 } 148 UNLOCK_PROCESS; 149 return False; 150 } 151} /*_XtIsSubclassOf */ 152 153 154XtPointer XtGetClassExtension( 155 WidgetClass object_class, 156 Cardinal byte_offset, 157 XrmQuark type, 158 long version, 159 Cardinal record_size) 160{ 161 ObjectClassExtension ext; 162 LOCK_PROCESS; 163 164 ext = *(ObjectClassExtension *)((char *)object_class + byte_offset); 165 while (ext && (ext->record_type != type || ext->version < version 166 || ext->record_size < record_size)) { 167 ext = (ObjectClassExtension) ext->next_extension; 168 } 169 170 UNLOCK_PROCESS; 171 return (XtPointer) ext; 172} 173 174 175static void ComputeWindowAttributes( 176 Widget widget, 177 XtValueMask *value_mask, 178 XSetWindowAttributes *values) 179{ 180 XtExposeProc expose; 181 182 *value_mask = CWEventMask | CWColormap; 183 (*values).event_mask = XtBuildEventMask(widget); 184 (*values).colormap = widget->core.colormap; 185 if (widget->core.background_pixmap != XtUnspecifiedPixmap) { 186 *value_mask |= CWBackPixmap; 187 (*values).background_pixmap = widget->core.background_pixmap; 188 } else { 189 *value_mask |= CWBackPixel; 190 (*values).background_pixel = widget->core.background_pixel; 191 } 192 if (widget->core.border_pixmap != XtUnspecifiedPixmap) { 193 *value_mask |= CWBorderPixmap; 194 (*values).border_pixmap = widget->core.border_pixmap; 195 } else { 196 *value_mask |= CWBorderPixel; 197 (*values).border_pixel = widget->core.border_pixel; 198 } 199 LOCK_PROCESS; 200 expose = widget->core.widget_class->core_class.expose; 201 UNLOCK_PROCESS; 202 if (expose == (XtExposeProc) NULL) { 203 /* Try to avoid redisplay upon resize by making bit_gravity the same 204 as the default win_gravity */ 205 *value_mask |= CWBitGravity; 206 (*values).bit_gravity = NorthWestGravity; 207 } 208} /* ComputeWindowAttributes */ 209 210static void CallChangeManaged( 211 register Widget widget) 212{ 213 register Cardinal i; 214 XtWidgetProc change_managed; 215 register WidgetList children; 216 int managed_children = 0; 217 218 register CompositePtr cpPtr; 219 register CompositePartPtr clPtr; 220 221 if (XtIsComposite (widget)) { 222 cpPtr = (CompositePtr)&((CompositeWidget) widget)->composite; 223 clPtr = (CompositePartPtr)&((CompositeWidgetClass) 224 widget->core.widget_class)->composite_class; 225 } else return; 226 227 children = cpPtr->children; 228 LOCK_PROCESS; 229 change_managed = clPtr->change_managed; 230 UNLOCK_PROCESS; 231 232 /* CallChangeManaged for all children */ 233 for (i = cpPtr->num_children; i != 0; --i) { 234 CallChangeManaged (children[i-1]); 235 if (XtIsManaged(children[i-1])) managed_children++; 236 } 237 238 if (change_managed != NULL && managed_children != 0) { 239 CALLGEOTAT(_XtGeoTrace(widget,"Call \"%s\"[%d,%d]'s changemanaged\n", 240 XtName(widget), 241 widget->core.width, widget->core.height)); 242 (*change_managed) (widget); 243 } 244} /* CallChangeManaged */ 245 246 247static void MapChildren( 248 CompositePart *cwp) 249{ 250 Cardinal i; 251 WidgetList children; 252 register Widget child; 253 254 children = cwp->children; 255 for (i = 0; i < cwp->num_children; i++) { 256 child = children[i]; 257 if (XtIsWidget (child)){ 258 if (child->core.managed && child->core.mapped_when_managed) { 259 XtMapWidget (children[i]); 260 } 261 } 262 } 263} /* MapChildren */ 264 265 266static Boolean ShouldMapAllChildren( 267 CompositePart *cwp) 268{ 269 Cardinal i; 270 WidgetList children; 271 register Widget child; 272 273 children = cwp->children; 274 for (i = 0; i < cwp->num_children; i++) { 275 child = children[i]; 276 if (XtIsWidget(child)) { 277 if (XtIsRealized(child) && (! (child->core.managed 278 && child->core.mapped_when_managed))){ 279 return False; 280 } 281 } 282 } 283 284 return True; 285} /* ShouldMapAllChildren */ 286 287 288static void RealizeWidget( 289 Widget widget) 290{ 291 XtValueMask value_mask; 292 XSetWindowAttributes values; 293 XtRealizeProc realize; 294 Window window; 295 Display* display; 296 String class_name; 297 Widget hookobj; 298 299 if (!XtIsWidget(widget) || XtIsRealized(widget)) return; 300 display = XtDisplay(widget); 301 _XtInstallTranslations(widget); 302 303 ComputeWindowAttributes (widget, &value_mask, &values); 304 LOCK_PROCESS; 305 realize = widget->core.widget_class->core_class.realize; 306 class_name = widget->core.widget_class->core_class.class_name; 307 UNLOCK_PROCESS; 308 if (realize == NULL) 309 XtAppErrorMsg(XtWidgetToApplicationContext(widget), 310 "invalidProcedure","realizeProc",XtCXtToolkitError, 311 "No realize class procedure defined", 312 (String *)NULL, (Cardinal *)NULL); 313 else { 314 CALLGEOTAT(_XtGeoTrace(widget,"Call \"%s\"[%d,%d]'s realize proc\n", 315 XtName(widget), 316 widget->core.width, widget->core.height)); 317 (*realize) (widget, &value_mask, &values); 318 } 319 window = XtWindow(widget); 320 hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 321 if (XtHasCallbacks(hookobj,XtNchangeHook) == XtCallbackHasSome) { 322 XtChangeHookDataRec call_data; 323 324 call_data.type = XtHrealizeWidget; 325 call_data.widget = widget; 326 XtCallCallbackList(hookobj, 327 ((HookObject)hookobj)->hooks.changehook_callbacks, 328 (XtPointer)&call_data); 329 } 330#ifndef NO_IDENTIFY_WINDOWS 331 if (_XtGetPerDisplay(display)->appContext->identify_windows) { 332 int len_nm, len_cl; 333 char *s; 334 335 len_nm = widget->core.name ? strlen(widget->core.name) : 0; 336 len_cl = strlen(class_name); 337 s = __XtMalloc((unsigned) (len_nm + len_cl + 2)); 338 s[0] = '\0'; 339 if (len_nm) 340 strcpy(s, widget->core.name); 341 strcpy(s + len_nm + 1, class_name); 342 XChangeProperty(display, window, 343 XInternAtom(display, "_MIT_OBJ_CLASS", 344 False), 345 XA_STRING, 8, PropModeReplace, (unsigned char *) s, 346 len_nm + len_cl + 2); 347 XtFree(s); 348 } 349#endif 350#ifdef notdef 351 _XtRegisterAsyncHandlers(widget); 352#endif 353 /* (re)register any grabs extant in the translations */ 354 _XtRegisterGrabs(widget); 355 /* reregister any grabs added with XtGrab{Button,Key} */ 356 _XtRegisterPassiveGrabs(widget); 357 XtRegisterDrawable (display, window, widget); 358 _XtExtensionSelect(widget); 359 360 if (XtIsComposite (widget)) { 361 Cardinal i; 362 CompositePart *cwp = &(((CompositeWidget)widget)->composite); 363 WidgetList children = cwp->children; 364 /* Realize all children */ 365 for (i = cwp->num_children; i != 0; --i) { 366 RealizeWidget (children[i-1]); 367 } 368 /* Map children that are managed and mapped_when_managed */ 369 370 if (cwp->num_children != 0) { 371 if (ShouldMapAllChildren(cwp)) { 372 XMapSubwindows (display, window); 373 } else { 374 MapChildren(cwp); 375 } 376 } 377 } 378 379 /* If this is the application's popup shell, map it */ 380 if (widget->core.parent == NULL && widget->core.mapped_when_managed) { 381 XtMapWidget (widget); 382 } 383} /* RealizeWidget */ 384 385void XtRealizeWidget ( 386 Widget widget) 387{ 388 WIDGET_TO_APPCON(widget); 389 390 LOCK_APP(app); 391 if (XtIsRealized (widget)) { 392 UNLOCK_APP(app); 393 return; 394 } 395 CallChangeManaged(widget); 396 RealizeWidget(widget); 397 UNLOCK_APP(app); 398} /* XtRealizeWidget */ 399 400 401static void UnrealizeWidget( 402 Widget widget) 403{ 404 CompositeWidget cw; 405 Cardinal i; 406 WidgetList children; 407 408 if (!XtIsWidget(widget) || !XtIsRealized(widget)) return; 409 410 /* If this is the application's popup shell, unmap it? */ 411 /* no, the window is being destroyed */ 412 413 /* Recurse on children */ 414 if (XtIsComposite (widget)) { 415 cw = (CompositeWidget) widget; 416 children = cw->composite.children; 417 /* Unrealize all children */ 418 for (i = cw->composite.num_children; i != 0; --i) { 419 UnrealizeWidget (children[i-1]); 420 } 421 /* Unmap children that are managed and mapped_when_managed? */ 422 /* No, it's ok to be managed and unrealized as long as your parent */ 423 /* is unrealized. XtUnrealize widget makes sure the "top" widget */ 424 /* is unmanaged, we can ignore all descendents */ 425 } 426 427 if (XtHasCallbacks(widget, XtNunrealizeCallback) == XtCallbackHasSome) 428 XtCallCallbacks(widget, XtNunrealizeCallback, NULL); 429 430 /* Unregister window */ 431 XtUnregisterDrawable(XtDisplay(widget), XtWindow(widget)); 432 433 /* Remove Event Handlers */ 434 /* remove grabs. Happens automatically when window is destroyed. */ 435 436 /* Destroy X Window, done at outer level with one request */ 437 widget->core.window = None; 438 439 /* Removing the event handler here saves having to keep track if 440 * the translation table is changed while the widget is unrealized. 441 */ 442 _XtRemoveTranslations(widget); 443} /* UnrealizeWidget */ 444 445 446void XtUnrealizeWidget ( 447 Widget widget) 448{ 449 Window window; 450 Widget hookobj; 451 WIDGET_TO_APPCON(widget); 452 453 LOCK_APP(app); 454 window = XtWindow(widget); 455 if (! XtIsRealized (widget)) { 456 UNLOCK_APP(app); 457 return; 458 } 459 if (widget->core.managed && widget->core.parent != NULL) 460 XtUnmanageChild(widget); 461 UnrealizeWidget(widget); 462 if (window != None) 463 XDestroyWindow(XtDisplay(widget), window); 464 hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 465 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 466 XtChangeHookDataRec call_data; 467 468 call_data.type = XtHunrealizeWidget; 469 call_data.widget = widget; 470 XtCallCallbackList(hookobj, 471 ((HookObject)hookobj)->hooks.changehook_callbacks, 472 (XtPointer)&call_data); 473 } 474 UNLOCK_APP(app); 475} /* XtUnrealizeWidget */ 476 477 478void XtCreateWindow( 479 Widget widget, 480 unsigned int window_class, 481 Visual *visual, 482 XtValueMask value_mask, 483 XSetWindowAttributes *attributes) 484{ 485 XtAppContext app = XtWidgetToApplicationContext(widget); 486 487 LOCK_APP(app); 488 if (widget->core.window == None) { 489 if (widget->core.width == 0 || widget->core.height == 0) { 490 Cardinal count = 1; 491 XtAppErrorMsg(app, 492 "invalidDimension", "xtCreateWindow", XtCXtToolkitError, 493 "Widget %s has zero width and/or height", 494 &widget->core.name, &count); 495 } 496 widget->core.window = 497 XCreateWindow ( 498 XtDisplay (widget), 499 (widget->core.parent ? 500 widget->core.parent->core.window : 501 widget->core.screen->root), 502 (int)widget->core.x, (int)widget->core.y, 503 (unsigned)widget->core.width, (unsigned)widget->core.height, 504 (unsigned)widget->core.border_width, (int) widget->core.depth, 505 window_class, visual, value_mask, attributes); 506 } 507 UNLOCK_APP(app); 508} /* XtCreateWindow */ 509 510 511/* ---------------- XtNameToWidget ----------------- */ 512 513static Widget NameListToWidget( 514 Widget root, 515 XrmNameList names, 516 XrmBindingList bindings, 517 int in_depth, int *out_depth, int *found_depth); 518 519typedef Widget (*NameMatchProc)(XrmNameList, 520 XrmBindingList, 521 WidgetList, Cardinal, int, int *, int *); 522 523static Widget MatchExactChildren( 524 XrmNameList names, 525 XrmBindingList bindings, 526 register WidgetList children, 527 register Cardinal num, 528 int in_depth, int *out_depth, int *found_depth) 529{ 530 register Cardinal i; 531 register XrmName name = *names; 532 Widget w, result = NULL; 533 int d, min = 10000; 534 535 for (i = 0; i < num; i++) { 536 if (name == children[i]->core.xrm_name) { 537 w = NameListToWidget(children[i], &names[1], &bindings[1], 538 in_depth+1, &d, found_depth); 539 if (w != NULL && d < min) {result = w; min = d;} 540 } 541 } 542 *out_depth = min; 543 return result; 544} 545 546static Widget MatchWildChildren( 547 XrmNameList names, 548 XrmBindingList bindings, 549 register WidgetList children, 550 register Cardinal num, 551 int in_depth, int *out_depth, int *found_depth) 552{ 553 register Cardinal i; 554 Widget w, result = NULL; 555 int d, min = 10000; 556 557 for (i = 0; i < num; i++) { 558 w = NameListToWidget(children[i], names, bindings, 559 in_depth+1, &d, found_depth); 560 if (w != NULL && d < min) {result = w; min = d;} 561 } 562 *out_depth = min; 563 return result; 564} 565 566static Widget SearchChildren( 567 Widget root, 568 XrmNameList names, 569 XrmBindingList bindings, 570 NameMatchProc matchproc, 571 int in_depth, int *out_depth, int *found_depth) 572{ 573 Widget w1 = NULL, w2; 574 int d1, d2; 575 576 if (XtIsComposite(root)) { 577 w1 = (*matchproc)(names, bindings, 578 ((CompositeWidget) root)->composite.children, 579 ((CompositeWidget) root)->composite.num_children, 580 in_depth, &d1, found_depth); 581 } else d1 = 10000; 582 w2 = (*matchproc)(names, bindings, root->core.popup_list, 583 root->core.num_popups, in_depth, &d2, found_depth); 584 *out_depth = (d1 < d2 ? d1 : d2); 585 return (d1 < d2 ? w1 : w2); 586} 587 588static Widget NameListToWidget( 589 register Widget root, 590 XrmNameList names, 591 XrmBindingList bindings, 592 int in_depth, int *out_depth, int *found_depth) 593{ 594 Widget w1, w2; 595 int d1, d2; 596 597 if (in_depth >= *found_depth) { 598 *out_depth = 10000; 599 return NULL; 600 } 601 602 if (names[0] == NULLQUARK) { 603 *out_depth = *found_depth = in_depth; 604 return root; 605 } 606 607 if (! XtIsWidget(root)) { 608 *out_depth = 10000; 609 return NULL; 610 } 611 612 if (*bindings == XrmBindTightly) { 613 return SearchChildren(root, names, bindings, MatchExactChildren, 614 in_depth, out_depth, found_depth); 615 616 } else { /* XrmBindLoosely */ 617 w1 = SearchChildren(root, names, bindings, MatchExactChildren, 618 in_depth, &d1, found_depth); 619 w2 = SearchChildren(root, names, bindings, MatchWildChildren, 620 in_depth, &d2, found_depth); 621 *out_depth = (d1 < d2 ? d1 : d2); 622 return (d1 < d2 ? w1 : w2); 623 } 624} /* NameListToWidget */ 625 626Widget XtNameToWidget( 627 Widget root, 628 _Xconst char* name) 629{ 630 XrmName *names; 631 XrmBinding *bindings; 632 int len, depth, found = 10000; 633 Widget result; 634 WIDGET_TO_APPCON(root); 635 636 len = strlen(name); 637 if (len == 0) return NULL; 638 639 LOCK_APP(app); 640 names = (XrmName *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmName)); 641 bindings = (XrmBinding *) 642 ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmBinding)); 643 if (names == NULL || bindings == NULL) _XtAllocError(NULL); 644 645 XrmStringToBindingQuarkList(name, bindings, names); 646 if (names[0] == NULLQUARK) { 647 DEALLOCATE_LOCAL((char *) bindings); 648 DEALLOCATE_LOCAL((char *) names); 649 UNLOCK_APP(app); 650 return NULL; 651 } 652 653 result = NameListToWidget(root, names, bindings, 0, &depth, &found); 654 655 DEALLOCATE_LOCAL((char *) bindings); 656 DEALLOCATE_LOCAL((char *) names); 657 UNLOCK_APP(app); 658 return result; 659} /* XtNameToWidget */ 660 661/* Define user versions of intrinsics macros */ 662 663#undef XtDisplayOfObject 664Display *XtDisplayOfObject( 665 Widget object) 666{ 667 /* Attempts to LockApp() here will generate endless recursive loops */ 668 if (XtIsSubclass(object, hookObjectClass)) 669 return DisplayOfScreen(((HookObject)object)->hooks.screen); 670 return XtDisplay(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); 671} 672 673#undef XtDisplay 674Display *XtDisplay( 675 Widget widget) 676{ 677 /* Attempts to LockApp() here will generate endless recursive loops */ 678 return DisplayOfScreen(widget->core.screen); 679} 680 681#undef XtScreenOfObject 682Screen *XtScreenOfObject( 683 Widget object) 684{ 685 /* Attempts to LockApp() here will generate endless recursive loops */ 686 if (XtIsSubclass(object, hookObjectClass)) 687 return ((HookObject)object)->hooks.screen; 688 return XtScreen(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); 689} 690 691#undef XtScreen 692Screen *XtScreen( 693 Widget widget) 694{ 695 /* Attempts to LockApp() here will generate endless recursive loops */ 696 return widget->core.screen; 697} 698 699#undef XtWindowOfObject 700Window XtWindowOfObject( 701 Widget object) 702{ 703 return XtWindow(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); 704} 705 706 707#undef XtWindow 708Window XtWindow( 709 Widget widget) 710{ 711 return widget->core.window; 712} 713 714#undef XtSuperclass 715WidgetClass XtSuperclass( 716 Widget widget) 717{ 718 WidgetClass retval; 719 720 LOCK_PROCESS; 721 retval = XtClass(widget)->core_class.superclass; 722 UNLOCK_PROCESS; 723 return retval; 724} 725 726#undef XtClass 727WidgetClass XtClass( 728 Widget widget) 729{ 730 WidgetClass retval; 731 732 LOCK_PROCESS; 733 retval = widget->core.widget_class; 734 UNLOCK_PROCESS; 735 return retval; 736} 737 738#undef XtIsManaged 739Boolean XtIsManaged( 740 Widget object) 741{ 742 Boolean retval; 743 WIDGET_TO_APPCON(object); 744 745 LOCK_APP(app); 746 if (XtIsRectObj(object)) 747 retval = object->core.managed; 748 else 749 retval = False; 750 UNLOCK_APP(app); 751 return retval; 752} 753 754#undef XtIsRealized 755Boolean XtIsRealized ( 756 Widget object) 757{ 758 Boolean retval; 759 WIDGET_TO_APPCON(object); 760 761 LOCK_APP(app); 762 retval = XtWindowOfObject(object) != None; 763 UNLOCK_APP(app); 764 return retval; 765} /* XtIsRealized */ 766 767#undef XtIsSensitive 768Boolean XtIsSensitive( 769 Widget object) 770{ 771 Boolean retval; 772 WIDGET_TO_APPCON(object); 773 774 LOCK_APP(app); 775 if (XtIsRectObj(object)) 776 retval = object->core.sensitive && object->core.ancestor_sensitive; 777 else 778 retval = False; 779 UNLOCK_APP(app); 780 return retval; 781} 782 783/* 784 * Internal routine; must be called only after XtIsWidget returns false 785 */ 786Widget _XtWindowedAncestor( 787 register Widget object) 788{ 789 Widget obj = object; 790 for (object = XtParent(object); object && !XtIsWidget(object);) 791 object = XtParent(object); 792 793 if (object == NULL) { 794 String params = XtName(obj); 795 Cardinal num_params = 1; 796 XtErrorMsg("noWidgetAncestor", "windowedAncestor", XtCXtToolkitError, 797 "Object \"%s\" does not have windowed ancestor", 798 ¶ms, &num_params); 799 } 800 801 return object; 802} 803 804#undef XtParent 805Widget XtParent( 806 Widget widget) 807{ 808 /* Attempts to LockApp() here will generate endless recursive loops */ 809 return widget->core.parent; 810} 811 812#undef XtName 813String XtName( 814 Widget object) 815{ 816 /* Attempts to LockApp() here will generate endless recursive loops */ 817 return XrmQuarkToString(object->core.xrm_name); 818} 819 820 821Boolean XtIsObject( 822 Widget object) 823{ 824 WidgetClass wc; 825 String class_name; 826 827 /* perform basic sanity checks */ 828 if (object->core.self != object || object->core.xrm_name == NULLQUARK) 829 return False; 830 831 LOCK_PROCESS; 832 wc = object->core.widget_class; 833 if (wc->core_class.class_name == NULL || 834 wc->core_class.xrm_class == NULLQUARK || 835 (class_name = XrmClassToString(wc->core_class.xrm_class)) == NULL || 836 strcmp(wc->core_class.class_name, class_name) != 0) { 837 UNLOCK_PROCESS; 838 return False; 839 } 840 UNLOCK_PROCESS; 841 842 if (XtIsWidget(object)) { 843 if (object->core.name == NULL || 844 (class_name = XrmNameToString(object->core.xrm_name)) == NULL || 845 strcmp(object->core.name, class_name) != 0) 846 return False; 847 } 848 return True; 849} 850 851#if defined(WIN32) 852static int access_file ( 853 char* path, 854 char* pathbuf, 855 int len_pathbuf, 856 char** pathret) 857{ 858 if (access (path, F_OK) == 0) { 859 if (strlen (path) < len_pathbuf) 860 *pathret = pathbuf; 861 else 862 *pathret = XtMalloc (strlen (path)); 863 if (*pathret) { 864 strcpy (*pathret, path); 865 return 1; 866 } 867 } 868 return 0; 869} 870 871static int AccessFile ( 872 char* path, 873 char* pathbuf, 874 int len_pathbuf, 875 char** pathret) 876{ 877 unsigned long drives; 878 int i, len; 879 char* drive; 880 char buf[MAX_PATH]; 881 char* bufp; 882 883 /* just try the "raw" name first and see if it works */ 884 if (access_file (path, pathbuf, len_pathbuf, pathret)) 885 return 1; 886 887#if defined(WIN32) && defined(__MINGW32__) 888 /* don't try others */ 889 return 0; 890#endif 891 892 /* try the places set in the environment */ 893 drive = getenv ("_XBASEDRIVE"); 894#ifdef __UNIXOS2__ 895 if (!drive) 896 drive = getenv ("X11ROOT"); 897#endif 898 if (!drive) 899 drive = "C:"; 900 len = strlen (drive) + strlen (path); 901 bufp = XtStackAlloc (len + 1, buf); 902 strcpy (bufp, drive); 903 strcat (bufp, path); 904 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 905 XtStackFree (bufp, buf); 906 return 1; 907 } 908 909#ifndef __UNIXOS2__ 910 /* one last place to look */ 911 drive = getenv ("HOMEDRIVE"); 912 if (drive) { 913 len = strlen (drive) + strlen (path); 914 bufp = XtStackAlloc (len + 1, buf); 915 strcpy (bufp, drive); 916 strcat (bufp, path); 917 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 918 XtStackFree (bufp, buf); 919 return 1; 920 } 921 } 922 923 /* does OS/2 (with or with gcc-emx) have getdrives()? */ 924 /* tried everywhere else, go fishing */ 925 drives = _getdrives (); 926#define C_DRIVE ('C' - 'A') 927#define Z_DRIVE ('Z' - 'A') 928 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 929 if ((1 << i) & drives) { 930 len = 2 + strlen (path); 931 bufp = XtStackAlloc (len + 1, buf); 932 *bufp = 'A' + i; 933 *(bufp + 1) = ':'; 934 *(bufp + 2) = '\0'; 935 strcat (bufp, path); 936 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 937 XtStackFree (bufp, buf); 938 return 1; 939 } 940 } 941 } 942#endif 943 return 0; 944} 945#endif 946 947static Boolean TestFile( 948 String path) 949{ 950#ifndef VMS 951 int ret = 0; 952 struct stat status; 953#if defined(WIN32) 954 char buf[MAX_PATH]; 955 char* bufp; 956 int len; 957 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 958 959 if (AccessFile (path, buf, MAX_PATH, &bufp)) 960 path = bufp; 961 962 (void) SetErrorMode (olderror); 963#endif 964 ret = (access(path, R_OK) == 0 && /* exists and is readable */ 965 stat(path, &status) == 0 && /* get the status */ 966#ifndef X_NOT_POSIX 967 S_ISDIR(status.st_mode) == 0); /* not a directory */ 968#else 969 (status.st_mode & S_IFMT) != S_IFDIR); /* not a directory */ 970#endif /* X_NOT_POSIX else */ 971 return ret; 972#else /* VMS */ 973 return TRUE; /* Who knows what to do here? */ 974#endif /* VMS */ 975} 976 977/* return of TRUE = resolved string fit, FALSE = didn't fit. Not 978 null-terminated and not collapsed if it didn't fit */ 979 980static Boolean Resolve( 981 register _Xconst char *source, /* The source string */ 982 register int len, /* The length in bytes of *source */ 983 Substitution sub, /* Array of string values to substitute */ 984 Cardinal num, /* Number of substitution entries */ 985 char *buf, /* Where to put the resolved string; */ 986 char collapse) /* Character to collapse */ 987{ 988 register int bytesLeft = PATH_MAX; 989 register char* bp = buf; 990#ifndef DONT_COLLAPSE 991 Boolean atBeginning = TRUE; 992 Boolean prevIsCollapse = FALSE; 993 994#define PUT(ch) \ 995 { \ 996 if (--bytesLeft == 0) return FALSE; \ 997 if (prevIsCollapse) \ 998 if ((*bp = ch) != collapse) { \ 999 prevIsCollapse = FALSE; \ 1000 bp++; \ 1001 } \ 1002 else bytesLeft++; \ 1003 else if ((*bp++ = ch) == collapse && !atBeginning) \ 1004 prevIsCollapse = TRUE; \ 1005 } 1006#else /* DONT_COLLAPSE */ 1007 1008#define PUT(ch) \ 1009 { \ 1010 if (--bytesLeft == 0) return FALSE; \ 1011 *bp++ = ch; \ 1012 } 1013#endif /* DONT_COLLAPSE */ 1014#define escape '%' 1015 1016 while (len--) { 1017#ifndef DONT_COLLAPSE 1018 if (*source == collapse) { 1019 PUT(*source); 1020 source++; 1021 continue; 1022 } 1023 else 1024#endif /* DONT_COLLAPSE */ 1025 if (*source != escape) { 1026 PUT(*source); 1027 } 1028 else { 1029 source++; 1030 if (len-- == 0) { 1031 PUT(escape); 1032 break; 1033 } 1034 1035 if (*source == ':' || *source == escape) 1036 PUT(*source) 1037 else { 1038 /* Match the character against the match array */ 1039 register Cardinal j; 1040 1041 for (j = 0; j < num && sub[j].match != *source; j++) {} 1042 1043 /* Substitute the substitution string */ 1044 1045 if (j >= num) PUT(*source) 1046 else if (sub[j].substitution != NULL) { 1047 char *sp = sub[j].substitution; 1048 while (*sp) { 1049 PUT(*sp); 1050 sp++; 1051 } 1052 } 1053 } 1054 } 1055 source++; 1056#ifndef DONT_COLLAPSE 1057 atBeginning = FALSE; 1058#endif /* DONT_COLLAPSE */ 1059 } 1060 PUT('\0'); 1061 1062 return TRUE; 1063#undef PUT 1064#undef escape 1065} 1066 1067 1068String XtFindFile( 1069 _Xconst char* path, 1070 Substitution substitutions, 1071 Cardinal num_substitutions, 1072 XtFilePredicate predicate) 1073{ 1074 char *buf, *buf1, *buf2, *colon; 1075 int len; 1076 Boolean firstTime = TRUE; 1077 1078 buf = buf1 = __XtMalloc((unsigned)PATH_MAX); 1079 buf2 = __XtMalloc((unsigned)PATH_MAX); 1080 1081 if (predicate == NULL) predicate = TestFile; 1082 1083 while (1) { 1084 colon = (String)path; 1085 /* skip leading colons */ 1086 while (*colon) { 1087 if (*colon != ':') break; 1088 colon++; 1089 path++; 1090 } 1091 /* now look for an un-escaped colon */ 1092 for ( ; *colon ; colon++) { 1093 if (*colon == '%' && *(path+1)) { 1094 colon++; /* bump it an extra time to skip %. */ 1095 continue; 1096 } 1097 if (*colon == ':') 1098#ifdef __UNIXOS2__ 1099 if (colon > (path+1)) 1100#endif 1101 break; 1102 } 1103 len = colon - path; 1104 if (Resolve(path, len, substitutions, num_substitutions, 1105 buf, '/')) { 1106 if (firstTime || strcmp(buf1,buf2) != 0) { 1107#ifdef __UNIXOS2__ 1108 { 1109 char *bufx = (char*)__XOS2RedirRoot(buf); 1110 strcpy(buf,bufx); 1111 } 1112#endif 1113#ifdef XNL_DEBUG 1114 printf("Testing file %s\n", buf); 1115#endif /* XNL_DEBUG */ 1116 /* Check out the file */ 1117 if ((*predicate) (buf)) { 1118 /* We've found it, return it */ 1119#ifdef XNL_DEBUG 1120 printf("File found.\n"); 1121#endif /* XNL_DEBUG */ 1122 if (buf == buf1) XtFree(buf2); 1123 else XtFree(buf1); 1124 return buf; 1125 } 1126 if (buf == buf1) 1127 buf = buf2; 1128 else 1129 buf = buf1; 1130 firstTime = FALSE; 1131 } 1132 } 1133 1134 /* Nope...any more paths? */ 1135 1136 if (*colon == '\0') break; 1137 path = colon+1; 1138 } 1139 1140 /* No file found */ 1141 1142 XtFree(buf1); 1143 XtFree(buf2); 1144 return NULL; 1145} 1146 1147 1148/* The implementation of this routine is operating system dependent */ 1149/* Should match the code in Xlib _XlcMapOSLocaleName */ 1150 1151static char *ExtractLocaleName( 1152 String lang) 1153{ 1154 1155#if defined(hpux) || defined(CSRG_BASED) || defined(sun) || defined(SVR4) || defined(sgi) || defined(__osf__) || defined(AIXV3) || defined(ultrix) || defined(WIN32) || defined(__UNIXOS2__) || defined (linux) 1156# ifdef hpux 1157/* 1158 * We need to discriminated between HPUX 9 and HPUX 10. The equivalent 1159 * code in Xlib in SetLocale.c does include locale.h via X11/Xlocale.h. 1160 */ 1161# include <locale.h> 1162# ifndef _LastCategory 1163 /* HPUX 9 and earlier */ 1164# define SKIPCOUNT 2 1165# define STARTCHAR ':' 1166# define ENDCHAR ';' 1167# else 1168 /* HPUX 10 */ 1169# define ENDCHAR ' ' 1170# endif 1171# else 1172# ifdef ultrix 1173# define SKIPCOUNT 2 1174# define STARTCHAR '\001' 1175# define ENDCHAR '\001' 1176# else 1177# if defined(WIN32) || defined(__UNIXOS2__) 1178# define SKIPCOUNT 1 1179# define STARTCHAR '=' 1180# define ENDCHAR ';' 1181# define WHITEFILL 1182# else 1183# if defined(__osf__) || (defined(AIXV3) && !defined(AIXV4)) 1184# define STARTCHAR ' ' 1185# define ENDCHAR ' ' 1186# else 1187# if defined(linux) 1188# define STARTSTR "LC_CTYPE=" 1189# define ENDCHAR ';' 1190# else 1191# if !defined(sun) || defined(SVR4) 1192# define STARTCHAR '/' 1193# define ENDCHAR '/' 1194# endif 1195# endif 1196# endif 1197# endif 1198# endif 1199# endif 1200 1201 char *start; 1202 char *end; 1203 int len; 1204# ifdef SKIPCOUNT 1205 int n; 1206# endif 1207 static char* buf = NULL; 1208 1209 start = lang; 1210# ifdef SKIPCOUNT 1211 for (n = SKIPCOUNT; 1212 --n >= 0 && start && (start = strchr (start, STARTCHAR)); 1213 start++) 1214 ; 1215 if (!start) 1216 start = lang; 1217# endif 1218# ifdef STARTCHAR 1219 if (start && (start = strchr (start, STARTCHAR))) 1220# elif defined (STARTSTR) 1221 if (start && (start = strstr (start,STARTSTR))) 1222# endif 1223 { 1224# ifdef STARTCHAR 1225 start++; 1226# elif defined (STARTSTR) 1227 start += strlen(STARTSTR); 1228# endif 1229 1230 if ((end = strchr (start, ENDCHAR))) { 1231 len = end - start; 1232 if (buf != NULL) XtFree (buf); 1233 buf = XtMalloc (len + 1); 1234 if (buf == NULL) return NULL; 1235 strncpy(buf, start, len); 1236 *(buf + len) = '\0'; 1237# ifdef WHITEFILL 1238 for (start = buf; start = strchr(start, ' '); ) 1239 *start++ = '-'; 1240# endif 1241 return buf; 1242 } else /* if no ENDCHAR is found we are at the end of the line */ 1243 return start; 1244 } 1245# ifdef WHITEFILL 1246 if (strchr(lang, ' ')) { 1247 if (buf != NULL) XtFree (buf); 1248 else buf = XtMalloc (strlen (lang) + 1); 1249 if (buf == NULL) return NULL; 1250 strcpy(buf, lang); 1251 for (start = buf; start = strchr(start, ' '); ) 1252 *start++ = '-'; 1253 return buf; 1254 } 1255# endif 1256# undef STARTCHAR 1257# undef ENDCHAR 1258# undef WHITEFILL 1259#endif 1260 1261 return lang; 1262} 1263 1264static void FillInLangSubs( 1265 Substitution subs, 1266 XtPerDisplay pd) 1267{ 1268 int len; 1269 char *string, *p1, *p2, *p3; 1270 char **rest; 1271 char *ch; 1272 1273 if (pd->language == NULL || 1274 (pd->language != NULL && pd->language[0] == '\0')) { 1275 subs[0].substitution = subs[1].substitution = 1276 subs[2].substitution = subs[3].substitution = NULL; 1277 return; 1278 } 1279 1280 string = ExtractLocaleName(pd->language); 1281 1282 if (string == NULL || 1283 (string != NULL && string[0] == '\0')) { 1284 subs[0].substitution = subs[1].substitution = 1285 subs[2].substitution = subs[3].substitution = NULL; 1286 return; 1287 } 1288 1289 len = strlen(string) + 1; 1290 subs[0].substitution = string; 1291 p1 = subs[1].substitution = __XtMalloc((Cardinal) 3*len); 1292 p2 = subs[2].substitution = subs[1].substitution + len; 1293 p3 = subs[3].substitution = subs[2].substitution + len; 1294 1295 /* Everything up to the first "_" goes into p1. From "_" to "." in 1296 p2. The rest in p3. If no delimiters, all goes into p1. We 1297 assume p1, p2, and p3 are large enough. */ 1298 1299 *p1 = *p2 = *p3 = '\0'; 1300 1301 ch = strchr(string, '_'); 1302 if (ch != NULL) { 1303 len = ch - string; 1304 (void) strncpy(p1, string, len); 1305 p1[len] = '\0'; 1306 string = ch + 1; 1307 rest = &p2; 1308 } else rest = &p1; 1309 1310 /* Rest points to where we put the first part */ 1311 1312 ch = strchr(string, '.'); 1313 if (ch != NULL) { 1314 len = ch - string; 1315 strncpy(*rest, string, len); 1316 (*rest)[len] = '\0'; 1317 (void) strcpy(p3, ch+1); 1318 } else (void) strcpy(*rest, string); 1319} 1320 1321/* 1322 * default path used if environment variable XFILESEARCHPATH 1323 * is not defined. Also substitued for %D. 1324 * The exact value should be documented in the implementation 1325 * notes for any Xt implementation. 1326 */ 1327static char *implementation_default_path(void) 1328{ 1329#if defined(WIN32) 1330 static char xfilesearchpath[] = ""; 1331 1332 return xfilesearchpath; 1333#elif defined(__UNIXOS2__) 1334 /* if you know how to pass % thru the compiler let me know */ 1335 static char xfilesearchpath[] = XFILESEARCHPATHDEFAULT; 1336 static Bool fixed; 1337 char *ch; 1338 1339 if (!fixed) { 1340 for (ch = xfilesearchpath; ch = strchr(ch, ';'); ch++) 1341 *ch = '%'; 1342 fixed = True; 1343 } 1344 return xfilesearchpath; 1345#else 1346 return XFILESEARCHPATHDEFAULT; 1347#endif 1348} 1349 1350 1351static SubstitutionRec defaultSubs[] = { 1352 {'N', NULL}, 1353 {'T', NULL}, 1354 {'S', NULL}, 1355 {'C', NULL}, 1356 {'L', NULL}, 1357 {'l', NULL}, 1358 {'t', NULL}, 1359 {'c', NULL} 1360}; 1361 1362 1363String XtResolvePathname( 1364 Display *dpy, 1365 _Xconst char* type, 1366 _Xconst char* filename, 1367 _Xconst char* suffix, 1368 _Xconst char* path, 1369 Substitution substitutions, 1370 Cardinal num_substitutions, 1371 XtFilePredicate predicate) 1372{ 1373 XtPerDisplay pd; 1374 static char *defaultPath = NULL; 1375 char *impl_default = implementation_default_path(); 1376 int idef_len = strlen(impl_default); 1377 char *massagedPath; 1378 int bytesAllocd, bytesLeft; 1379 char *ch, *result; 1380 Substitution merged_substitutions; 1381 XrmRepresentation db_type; 1382 XrmValue value; 1383 XrmName name_list[3]; 1384 XrmClass class_list[3]; 1385 Boolean pathMallocd = False; 1386 1387 LOCK_PROCESS; 1388 pd = _XtGetPerDisplay(dpy); 1389 if (path == NULL) { 1390#ifndef VMS 1391 if (defaultPath == NULL) { 1392 defaultPath = getenv("XFILESEARCHPATH"); 1393 if (defaultPath == NULL) 1394 defaultPath = impl_default; 1395 } 1396 path = defaultPath; 1397#endif /* VMS */ 1398 } 1399 1400 if (path == NULL) 1401 path = ""; /* NULL would kill us later */ 1402 1403 if (filename == NULL) { 1404 filename = XrmClassToString(pd->class); 1405 } 1406 1407 bytesAllocd = bytesLeft = 1000; 1408 massagedPath = ALLOCATE_LOCAL(bytesAllocd); 1409 if (massagedPath == NULL) _XtAllocError(NULL); 1410 1411 if (path[0] == ':') { 1412 strcpy(massagedPath, "%N%S"); 1413 ch = &massagedPath[4]; 1414 bytesLeft -= 4; 1415 } else ch = massagedPath; 1416 1417 /* Insert %N%S between adjacent colons 1418 * and default path for %D. 1419 * Default path should not have any adjacent colons of its own. 1420 */ 1421 1422 while (*path != '\0') { 1423 if (bytesLeft < idef_len) { 1424 int bytesUsed = bytesAllocd - bytesLeft; 1425 char *new; 1426 bytesAllocd +=1000; 1427 new = __XtMalloc((Cardinal) bytesAllocd); 1428 strncpy( new, massagedPath, bytesUsed ); 1429 ch = new + bytesUsed; 1430 if (pathMallocd) 1431 XtFree(massagedPath); 1432 else 1433 DEALLOCATE_LOCAL(massagedPath); 1434 pathMallocd = True; 1435 massagedPath = new; 1436 bytesLeft = bytesAllocd - bytesUsed; 1437 } 1438 if (*path == '%' && *(path+1) == ':') { 1439 *ch++ = '%'; 1440 *ch++ = ':'; 1441 path += 2; 1442 bytesLeft -= 2; 1443 continue; 1444 } 1445 if (*path == ':' && *(path+1) == ':') { 1446 strcpy(ch, ":%N%S:"); 1447 ch += 6; 1448 bytesLeft -= 6; 1449 while (*path == ':') path++; 1450 continue; 1451 } 1452 if (*path == '%' && *(path+1) == 'D') { 1453 strcpy(ch, impl_default); 1454 ch += idef_len; 1455 bytesLeft -= idef_len; 1456 path += 2; 1457 continue; 1458 } 1459 *ch++ = *path++; 1460 bytesLeft--; 1461 } 1462 *ch = '\0'; 1463#ifdef XNL_DEBUG 1464 printf("Massaged path: %s\n", massagedPath); 1465#endif /* XNL_DEBUG */ 1466 1467 if (num_substitutions == 0) 1468 merged_substitutions = defaultSubs; 1469 else { 1470 int i = XtNumber(defaultSubs); 1471 Substitution sub, def; 1472 merged_substitutions = sub = (Substitution) 1473 ALLOCATE_LOCAL((unsigned)(num_substitutions+i)*sizeof(SubstitutionRec)); 1474 if (sub == NULL) _XtAllocError(NULL); 1475 for (def = defaultSubs; i--; sub++, def++) sub->match = def->match; 1476 for (i = num_substitutions; i--; ) *sub++ = *substitutions++; 1477 } 1478 merged_substitutions[0].substitution = (String)filename; 1479 merged_substitutions[1].substitution = (String)type; 1480 merged_substitutions[2].substitution = (String)suffix; 1481 name_list[0] = pd->name; 1482 name_list[1] = XrmPermStringToQuark("customization"); 1483 name_list[2] = NULLQUARK; 1484 class_list[0] = pd->class; 1485 class_list[1] = XrmPermStringToQuark("Customization"); 1486 class_list[2] = NULLQUARK; 1487 if (XrmQGetResource(XrmGetDatabase(dpy), name_list, class_list, 1488 &db_type, &value) && 1489 db_type == _XtQString) 1490 merged_substitutions[3].substitution = (char *)value.addr; 1491 else 1492 merged_substitutions[3].substitution = NULL; 1493 FillInLangSubs(&merged_substitutions[4], pd); 1494 1495 result = XtFindFile(massagedPath, merged_substitutions, 1496 num_substitutions + XtNumber(defaultSubs), 1497 predicate); 1498 1499 if (merged_substitutions[5].substitution != NULL) 1500 XtFree( (XtPointer)merged_substitutions[5].substitution ); 1501 1502 if (merged_substitutions != defaultSubs) 1503 DEALLOCATE_LOCAL(merged_substitutions); 1504 1505 if (pathMallocd) 1506 XtFree(massagedPath); 1507 else 1508 DEALLOCATE_LOCAL(massagedPath); 1509 1510 UNLOCK_PROCESS; 1511 return result; 1512} 1513 1514 1515Boolean XtCallAcceptFocus( 1516 Widget widget, 1517 Time *time) 1518{ 1519 XtAcceptFocusProc ac; 1520 Boolean retval; 1521 WIDGET_TO_APPCON(widget); 1522 1523 LOCK_APP(app); 1524 LOCK_PROCESS; 1525 ac = XtClass(widget)->core_class.accept_focus; 1526 UNLOCK_PROCESS; 1527 1528 if (ac != NULL) 1529 retval = (*ac) (widget, time); 1530 else 1531 retval = FALSE; 1532 UNLOCK_APP(app); 1533 return retval; 1534} 1535 1536#ifdef XT_GEO_TATTLER 1537/************************************************************************** 1538 GeoTattler: This is used to debug Geometry management in Xt. 1539 1540 It uses a pseudo resource XtNgeotattler. 1541 1542 E.G. if those lines are found in the resource database: 1543 1544 myapp*draw.XmScale.geoTattler: ON 1545 *XmScrollBar.geoTattler:ON 1546 *XmRowColumn.exit_button.geoTattler:ON 1547 1548 then: 1549 1550 all the XmScale children of the widget named draw, 1551 all the XmScrollBars, 1552 the widget named exit_button in any XmRowColumn 1553 1554 will return True to the function IsTattled(), and will generate 1555 outlined trace to stdout. 1556 1557*************************************************************************/ 1558 1559#define XtNgeoTattler "geoTattler" 1560#define XtCGeoTattler "GeoTattler" 1561 1562typedef struct { Boolean geo_tattler ;} GeoDataRec ; 1563 1564static XtResource geo_resources[] = { 1565 { XtNgeoTattler, XtCGeoTattler, XtRBoolean, sizeof(Boolean), 1566 XtOffsetOf(GeoDataRec, geo_tattler), 1567 XtRImmediate, (XtPointer) False } 1568}; 1569 1570/************************************************************************ 1571 This function uses XtGetSubresources to find out if a widget 1572 needs to be geo-spied by the caller. */ 1573static Boolean IsTattled (Widget widget) 1574{ 1575 GeoDataRec geo_data ; 1576 1577 XtGetSubresources(widget, (XtPointer)&geo_data, 1578 (String)NULL, (String)NULL, 1579 geo_resources, XtNumber(geo_resources), 1580 NULL, 0); 1581 1582 return geo_data.geo_tattler; 1583 1584} /* IsTattled */ 1585 1586static int n_tab = 0 ; /* not MT for now */ 1587 1588void 1589_XtGeoTab (int direction) /* +1 or -1 */ 1590{ 1591 n_tab += direction ; 1592} 1593 1594 1595void 1596_XtGeoTrace (Widget widget, ...) 1597{ 1598 va_list args; 1599 char *fmt; 1600 int i ; 1601 if (IsTattled(widget)) { 1602 va_start(args, widget); 1603 fmt = va_arg(args, char *); 1604 for (i=0; i<n_tab; i++) printf(" "); 1605 (void) vprintf(fmt, args); 1606 va_end(args); 1607 } 1608} 1609 1610#endif /* XT_GEO_TATTLER */ 1611 1612