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