Intrinsic.c revision 0568f49b
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#ifdef WIN32 85#include <direct.h> /* for _getdrives() */ 86#endif 87 88#include <stdio.h> 89#include <stdlib.h> 90 91String XtCXtToolkitError = "XtToolkitError"; 92 93Boolean XtIsSubclass( 94 Widget widget, 95 WidgetClass myWidgetClass) 96{ 97 register WidgetClass w; 98 Boolean retval = FALSE; 99 WIDGET_TO_APPCON(widget); 100 101 LOCK_APP(app); 102 LOCK_PROCESS; 103 for (w = widget->core.widget_class; w != NULL; w = w->core_class.superclass) 104 if (w == myWidgetClass) { 105 retval = TRUE; 106 break; 107 } 108 UNLOCK_PROCESS; 109 UNLOCK_APP(app); 110 return retval; 111} /* XtIsSubclass */ 112 113 114Boolean _XtCheckSubclassFlag( 115 Widget object, 116 _XtXtEnum flag) 117{ 118 Boolean retval; 119 120 LOCK_PROCESS; 121 if (object->core.widget_class->core_class.class_inited & flag) 122 retval = TRUE; 123 else 124 retval = FALSE; 125 UNLOCK_PROCESS; 126 return retval; 127} /*_XtVerifySubclass */ 128 129 130Boolean _XtIsSubclassOf( 131 Widget object, 132 WidgetClass myWidgetClass, 133 WidgetClass superClass, 134 _XtXtEnum flag) 135{ 136 LOCK_PROCESS; 137 if (!(object->core.widget_class->core_class.class_inited & flag)) { 138 UNLOCK_PROCESS; 139 return False; 140 } else { 141 register WidgetClass c = object->core.widget_class; 142 while (c != superClass) { 143 if (c == myWidgetClass) { 144 UNLOCK_PROCESS; 145 return True; 146 } 147 c = c->core_class.superclass; 148 } 149 UNLOCK_PROCESS; 150 return False; 151 } 152} /*_XtIsSubclassOf */ 153 154 155XtPointer XtGetClassExtension( 156 WidgetClass object_class, 157 Cardinal byte_offset, 158 XrmQuark type, 159 long version, 160 Cardinal record_size) 161{ 162 ObjectClassExtension ext; 163 LOCK_PROCESS; 164 165 ext = *(ObjectClassExtension *)((char *)object_class + byte_offset); 166 while (ext && (ext->record_type != type || ext->version < version 167 || ext->record_size < record_size)) { 168 ext = (ObjectClassExtension) ext->next_extension; 169 } 170 171 UNLOCK_PROCESS; 172 return (XtPointer) ext; 173} 174 175 176static void ComputeWindowAttributes( 177 Widget widget, 178 XtValueMask *value_mask, 179 XSetWindowAttributes *values) 180{ 181 XtExposeProc expose; 182 183 *value_mask = CWEventMask | CWColormap; 184 (*values).event_mask = (long) XtBuildEventMask(widget); 185 (*values).colormap = widget->core.colormap; 186 if (widget->core.background_pixmap != XtUnspecifiedPixmap) { 187 *value_mask |= CWBackPixmap; 188 (*values).background_pixmap = widget->core.background_pixmap; 189 } else { 190 *value_mask |= CWBackPixel; 191 (*values).background_pixel = widget->core.background_pixel; 192 } 193 if (widget->core.border_pixmap != XtUnspecifiedPixmap) { 194 *value_mask |= CWBorderPixmap; 195 (*values).border_pixmap = widget->core.border_pixmap; 196 } else { 197 *value_mask |= CWBorderPixel; 198 (*values).border_pixel = widget->core.border_pixel; 199 } 200 LOCK_PROCESS; 201 expose = widget->core.widget_class->core_class.expose; 202 UNLOCK_PROCESS; 203 if (expose == (XtExposeProc) NULL) { 204 /* Try to avoid redisplay upon resize by making bit_gravity the same 205 as the default win_gravity */ 206 *value_mask |= CWBitGravity; 207 (*values).bit_gravity = NorthWestGravity; 208 } 209} /* ComputeWindowAttributes */ 210 211static void CallChangeManaged( 212 register Widget widget) 213{ 214 register Cardinal i; 215 XtWidgetProc change_managed; 216 register WidgetList children; 217 int managed_children = 0; 218 219 register CompositePtr cpPtr; 220 register CompositePartPtr clPtr; 221 222 if (XtIsComposite (widget)) { 223 cpPtr = (CompositePtr)&((CompositeWidget) widget)->composite; 224 clPtr = (CompositePartPtr)&((CompositeWidgetClass) 225 widget->core.widget_class)->composite_class; 226 } else return; 227 228 children = cpPtr->children; 229 LOCK_PROCESS; 230 change_managed = clPtr->change_managed; 231 UNLOCK_PROCESS; 232 233 /* CallChangeManaged for all children */ 234 for (i = cpPtr->num_children; i != 0; --i) { 235 CallChangeManaged (children[i-1]); 236 if (XtIsManaged(children[i-1])) managed_children++; 237 } 238 239 if (change_managed != NULL && managed_children != 0) { 240 CALLGEOTAT(_XtGeoTrace(widget,"Call \"%s\"[%d,%d]'s changemanaged\n", 241 XtName(widget), 242 widget->core.width, widget->core.height)); 243 (*change_managed) (widget); 244 } 245} /* CallChangeManaged */ 246 247 248static void MapChildren( 249 CompositePart *cwp) 250{ 251 Cardinal i; 252 WidgetList children; 253 254 children = cwp->children; 255 for (i = 0; i < cwp->num_children; i++) { 256 Widget 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 272 children = cwp->children; 273 for (i = 0; i < cwp->num_children; i++) { 274 Widget child = children[i]; 275 if (XtIsWidget(child)) { 276 if (XtIsRealized(child) && (! (child->core.managed 277 && child->core.mapped_when_managed))){ 278 return False; 279 } 280 } 281 } 282 283 return True; 284} /* ShouldMapAllChildren */ 285 286 287static void RealizeWidget( 288 Widget widget) 289{ 290 XtValueMask value_mask; 291 XSetWindowAttributes values; 292 XtRealizeProc realize; 293 Window window; 294 Display* display; 295 String class_name; 296 Widget hookobj; 297 298 if (!XtIsWidget(widget) || XtIsRealized(widget)) return; 299 display = XtDisplay(widget); 300 _XtInstallTranslations(widget); 301 302 ComputeWindowAttributes (widget, &value_mask, &values); 303 LOCK_PROCESS; 304 realize = widget->core.widget_class->core_class.realize; 305 class_name = widget->core.widget_class->core_class.class_name; 306 UNLOCK_PROCESS; 307 if (realize == NULL) 308 XtAppErrorMsg(XtWidgetToApplicationContext(widget), 309 "invalidProcedure","realizeProc",XtCXtToolkitError, 310 "No realize class procedure defined", 311 NULL, NULL); 312 else { 313 CALLGEOTAT(_XtGeoTrace(widget,"Call \"%s\"[%d,%d]'s realize proc\n", 314 XtName(widget), 315 widget->core.width, widget->core.height)); 316 (*realize) (widget, &value_mask, &values); 317 } 318 window = XtWindow(widget); 319 hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget)); 320 if (XtHasCallbacks(hookobj,XtNchangeHook) == XtCallbackHasSome) { 321 XtChangeHookDataRec call_data; 322 323 call_data.type = XtHrealizeWidget; 324 call_data.widget = widget; 325 XtCallCallbackList(hookobj, 326 ((HookObject)hookobj)->hooks.changehook_callbacks, 327 (XtPointer)&call_data); 328 } 329#ifndef NO_IDENTIFY_WINDOWS 330 if (_XtGetPerDisplay(display)->appContext->identify_windows) { 331 int len_nm, len_cl; 332 char *s; 333 334 len_nm = widget->core.name ? (int) strlen(widget->core.name) : 0; 335 len_cl = (int) strlen(class_name); 336 s = __XtMalloc((unsigned) (len_nm + len_cl + 2)); 337 s[0] = '\0'; 338 if (len_nm) 339 strcpy(s, widget->core.name); 340 strcpy(s + len_nm + 1, class_name); 341 XChangeProperty(display, window, 342 XInternAtom(display, "_MIT_OBJ_CLASS", 343 False), 344 XA_STRING, 8, PropModeReplace, (unsigned char *) s, 345 len_nm + len_cl + 2); 346 XtFree(s); 347 } 348#endif 349#ifdef notdef 350 _XtRegisterAsyncHandlers(widget); 351#endif 352 /* (re)register any grabs extant in the translations */ 353 _XtRegisterGrabs(widget); 354 /* reregister any grabs added with XtGrab{Button,Key} */ 355 _XtRegisterPassiveGrabs(widget); 356 XtRegisterDrawable (display, window, widget); 357 _XtExtensionSelect(widget); 358 359 if (XtIsComposite (widget)) { 360 Cardinal i; 361 CompositePart *cwp = &(((CompositeWidget)widget)->composite); 362 WidgetList children = cwp->children; 363 /* Realize all children */ 364 for (i = cwp->num_children; i != 0; --i) { 365 RealizeWidget (children[i-1]); 366 } 367 /* Map children that are managed and mapped_when_managed */ 368 369 if (cwp->num_children != 0) { 370 if (ShouldMapAllChildren(cwp)) { 371 XMapSubwindows (display, window); 372 } else { 373 MapChildren(cwp); 374 } 375 } 376 } 377 378 /* If this is the application's popup shell, map it */ 379 if (widget->core.parent == NULL && widget->core.mapped_when_managed) { 380 XtMapWidget (widget); 381 } 382} /* RealizeWidget */ 383 384void XtRealizeWidget ( 385 Widget widget) 386{ 387 WIDGET_TO_APPCON(widget); 388 389 LOCK_APP(app); 390 if (XtIsRealized (widget)) { 391 UNLOCK_APP(app); 392 return; 393 } 394 CallChangeManaged(widget); 395 RealizeWidget(widget); 396 UNLOCK_APP(app); 397} /* XtRealizeWidget */ 398 399 400static void UnrealizeWidget( 401 Widget widget) 402{ 403 CompositeWidget cw; 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 Cardinal i; 413 WidgetList children; 414 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 int d1, d2; 595 596 if (in_depth >= *found_depth) { 597 *out_depth = 10000; 598 return NULL; 599 } 600 601 if (names[0] == NULLQUARK) { 602 *out_depth = *found_depth = in_depth; 603 return root; 604 } 605 606 if (! XtIsWidget(root)) { 607 *out_depth = 10000; 608 return NULL; 609 } 610 611 if (*bindings == XrmBindTightly) { 612 return SearchChildren(root, names, bindings, MatchExactChildren, 613 in_depth, out_depth, found_depth); 614 615 } else { /* XrmBindLoosely */ 616 Widget w1, w2; 617 618 w1 = SearchChildren(root, names, bindings, MatchExactChildren, 619 in_depth, &d1, found_depth); 620 w2 = SearchChildren(root, names, bindings, MatchWildChildren, 621 in_depth, &d2, found_depth); 622 *out_depth = (d1 < d2 ? d1 : d2); 623 return (d1 < d2 ? w1 : w2); 624 } 625} /* NameListToWidget */ 626 627Widget XtNameToWidget( 628 Widget root, 629 _Xconst char* name) 630{ 631 XrmName *names; 632 XrmBinding *bindings; 633 int len, depth, found = 10000; 634 Widget result; 635 WIDGET_TO_APPCON(root); 636 637 len = (int) strlen(name); 638 if (len == 0) return NULL; 639 640 LOCK_APP(app); 641 names = (XrmName *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmName)); 642 bindings = (XrmBinding *) 643 ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmBinding)); 644 if (names == NULL || bindings == NULL) _XtAllocError(NULL); 645 646 XrmStringToBindingQuarkList(name, bindings, names); 647 if (names[0] == NULLQUARK) { 648 DEALLOCATE_LOCAL((char *) bindings); 649 DEALLOCATE_LOCAL((char *) names); 650 UNLOCK_APP(app); 651 return NULL; 652 } 653 654 result = NameListToWidget(root, names, bindings, 0, &depth, &found); 655 656 DEALLOCATE_LOCAL((char *) bindings); 657 DEALLOCATE_LOCAL((char *) names); 658 UNLOCK_APP(app); 659 return result; 660} /* XtNameToWidget */ 661 662/* Define user versions of intrinsics macros */ 663 664#undef XtDisplayOfObject 665Display *XtDisplayOfObject( 666 Widget object) 667{ 668 /* Attempts to LockApp() here will generate endless recursive loops */ 669 if (XtIsSubclass(object, hookObjectClass)) 670 return DisplayOfScreen(((HookObject)object)->hooks.screen); 671 return XtDisplay(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); 672} 673 674#undef XtDisplay 675Display *XtDisplay( 676 Widget widget) 677{ 678 /* Attempts to LockApp() here will generate endless recursive loops */ 679 return DisplayOfScreen(widget->core.screen); 680} 681 682#undef XtScreenOfObject 683Screen *XtScreenOfObject( 684 Widget object) 685{ 686 /* Attempts to LockApp() here will generate endless recursive loops */ 687 if (XtIsSubclass(object, hookObjectClass)) 688 return ((HookObject)object)->hooks.screen; 689 return XtScreen(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); 690} 691 692#undef XtScreen 693Screen *XtScreen( 694 Widget widget) 695{ 696 /* Attempts to LockApp() here will generate endless recursive loops */ 697 return widget->core.screen; 698} 699 700#undef XtWindowOfObject 701Window XtWindowOfObject( 702 Widget object) 703{ 704 return XtWindow(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); 705} 706 707 708#undef XtWindow 709Window XtWindow( 710 Widget widget) 711{ 712 return widget->core.window; 713} 714 715#undef XtSuperclass 716WidgetClass XtSuperclass( 717 Widget widget) 718{ 719 WidgetClass retval; 720 721 LOCK_PROCESS; 722 retval = XtClass(widget)->core_class.superclass; 723 UNLOCK_PROCESS; 724 return retval; 725} 726 727#undef XtClass 728WidgetClass XtClass( 729 Widget widget) 730{ 731 WidgetClass retval; 732 733 LOCK_PROCESS; 734 retval = widget->core.widget_class; 735 UNLOCK_PROCESS; 736 return retval; 737} 738 739#undef XtIsManaged 740Boolean XtIsManaged( 741 Widget object) 742{ 743 Boolean retval; 744 WIDGET_TO_APPCON(object); 745 746 LOCK_APP(app); 747 if (XtIsRectObj(object)) 748 retval = object->core.managed; 749 else 750 retval = False; 751 UNLOCK_APP(app); 752 return retval; 753} 754 755#undef XtIsRealized 756Boolean XtIsRealized ( 757 Widget object) 758{ 759 Boolean retval; 760 WIDGET_TO_APPCON(object); 761 762 LOCK_APP(app); 763 retval = XtWindowOfObject(object) != None; 764 UNLOCK_APP(app); 765 return retval; 766} /* XtIsRealized */ 767 768#undef XtIsSensitive 769Boolean XtIsSensitive( 770 Widget object) 771{ 772 Boolean retval; 773 WIDGET_TO_APPCON(object); 774 775 LOCK_APP(app); 776 if (XtIsRectObj(object)) 777 retval = object->core.sensitive && object->core.ancestor_sensitive; 778 else 779 retval = False; 780 UNLOCK_APP(app); 781 return retval; 782} 783 784/* 785 * Internal routine; must be called only after XtIsWidget returns false 786 */ 787Widget _XtWindowedAncestor( 788 register Widget object) 789{ 790 Widget obj = object; 791 for (object = XtParent(object); object && !XtIsWidget(object);) 792 object = XtParent(object); 793 794 if (object == NULL) { 795 String params = XtName(obj); 796 Cardinal num_params = 1; 797 XtErrorMsg("noWidgetAncestor", "windowedAncestor", XtCXtToolkitError, 798 "Object \"%s\" does not have windowed ancestor", 799 ¶ms, &num_params); 800 } 801 802 return object; 803} 804 805#undef XtParent 806Widget XtParent( 807 Widget widget) 808{ 809 /* Attempts to LockApp() here will generate endless recursive loops */ 810 return widget->core.parent; 811} 812 813#undef XtName 814String XtName( 815 Widget object) 816{ 817 /* Attempts to LockApp() here will generate endless recursive loops */ 818 return XrmQuarkToString(object->core.xrm_name); 819} 820 821 822Boolean XtIsObject( 823 Widget object) 824{ 825 WidgetClass wc; 826 String class_name; 827 828 /* perform basic sanity checks */ 829 if (object->core.self != object || object->core.xrm_name == NULLQUARK) 830 return False; 831 832 LOCK_PROCESS; 833 wc = object->core.widget_class; 834 if (wc->core_class.class_name == NULL || 835 wc->core_class.xrm_class == NULLQUARK || 836 (class_name = XrmClassToString(wc->core_class.xrm_class)) == NULL || 837 strcmp(wc->core_class.class_name, class_name) != 0) { 838 UNLOCK_PROCESS; 839 return False; 840 } 841 UNLOCK_PROCESS; 842 843 if (XtIsWidget(object)) { 844 if (object->core.name == NULL || 845 (class_name = XrmNameToString(object->core.xrm_name)) == NULL || 846 strcmp(object->core.name, class_name) != 0) 847 return False; 848 } 849 return True; 850} 851 852#if defined(WIN32) 853static int access_file ( 854 char* path, 855 char* pathbuf, 856 int len_pathbuf, 857 char** pathret) 858{ 859 if (access (path, F_OK) == 0) { 860 if (strlen (path) < len_pathbuf) 861 *pathret = pathbuf; 862 else 863 *pathret = XtMalloc (strlen (path)); 864 if (*pathret) { 865 strcpy (*pathret, path); 866 return 1; 867 } 868 } 869 return 0; 870} 871 872static int AccessFile ( 873 char* path, 874 char* pathbuf, 875 int len_pathbuf, 876 char** pathret) 877{ 878 unsigned long drives; 879 int i, len; 880 char* drive; 881 char buf[MAX_PATH]; 882 char* bufp; 883 884 /* just try the "raw" name first and see if it works */ 885 if (access_file (path, pathbuf, len_pathbuf, pathret)) 886 return 1; 887 888#if defined(WIN32) && defined(__MINGW32__) 889 /* don't try others */ 890 return 0; 891#endif 892 893 /* try the places set in the environment */ 894 drive = getenv ("_XBASEDRIVE"); 895 if (!drive) 896 drive = "C:"; 897 len = strlen (drive) + strlen (path); 898 bufp = XtStackAlloc (len + 1, buf); 899 strcpy (bufp, drive); 900 strcat (bufp, path); 901 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 902 XtStackFree (bufp, buf); 903 return 1; 904 } 905 906 /* one last place to look */ 907 drive = getenv ("HOMEDRIVE"); 908 if (drive) { 909 len = strlen (drive) + strlen (path); 910 bufp = XtStackAlloc (len + 1, buf); 911 strcpy (bufp, drive); 912 strcat (bufp, path); 913 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 914 XtStackFree (bufp, buf); 915 return 1; 916 } 917 } 918 919 /* does OS/2 (with or with gcc-emx) have getdrives()? */ 920 /* tried everywhere else, go fishing */ 921 drives = _getdrives (); 922#define C_DRIVE ('C' - 'A') 923#define Z_DRIVE ('Z' - 'A') 924 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 925 if ((1 << i) & drives) { 926 len = 2 + strlen (path); 927 bufp = XtStackAlloc (len + 1, buf); 928 *bufp = 'A' + i; 929 *(bufp + 1) = ':'; 930 *(bufp + 2) = '\0'; 931 strcat (bufp, path); 932 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 933 XtStackFree (bufp, buf); 934 return 1; 935 } 936 } 937 } 938 return 0; 939} 940#endif 941 942static Boolean TestFile( 943 String path) 944{ 945#ifndef VMS 946 int ret = 0; 947 struct stat status; 948#if defined(WIN32) 949 char buf[MAX_PATH]; 950 char* bufp; 951 int len; 952 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 953 954 if (AccessFile (path, buf, MAX_PATH, &bufp)) 955 path = bufp; 956 957 (void) SetErrorMode (olderror); 958#endif 959 ret = (access(path, R_OK) == 0 && /* exists and is readable */ 960 stat(path, &status) == 0 && /* get the status */ 961#ifndef X_NOT_POSIX 962 S_ISDIR(status.st_mode) == 0); /* not a directory */ 963#else 964 (status.st_mode & S_IFMT) != S_IFDIR); /* not a directory */ 965#endif /* X_NOT_POSIX else */ 966 return (Boolean) ret; 967#else /* VMS */ 968 return TRUE; /* Who knows what to do here? */ 969#endif /* VMS */ 970} 971 972/* return of TRUE = resolved string fit, FALSE = didn't fit. Not 973 null-terminated and not collapsed if it didn't fit */ 974 975static Boolean Resolve( 976 register _Xconst char *source, /* The source string */ 977 register int len, /* The length in bytes of *source */ 978 Substitution sub, /* Array of string values to substitute */ 979 Cardinal num, /* Number of substitution entries */ 980 char *buf, /* Where to put the resolved string; */ 981 char collapse) /* Character to collapse */ 982{ 983 register int bytesLeft = PATH_MAX; 984 register char* bp = buf; 985#ifndef DONT_COLLAPSE 986 Boolean atBeginning = TRUE; 987 Boolean prevIsCollapse = FALSE; 988 989#define PUT(ch) \ 990 { \ 991 if (--bytesLeft == 0) return FALSE; \ 992 if (prevIsCollapse) \ 993 if ((*bp = ch) != collapse) { \ 994 prevIsCollapse = FALSE; \ 995 bp++; \ 996 } \ 997 else bytesLeft++; \ 998 else if ((*bp++ = ch) == collapse && !atBeginning) \ 999 prevIsCollapse = TRUE; \ 1000 } 1001#else /* DONT_COLLAPSE */ 1002 1003#define PUT(ch) \ 1004 { \ 1005 if (--bytesLeft == 0) return FALSE; \ 1006 *bp++ = ch; \ 1007 } 1008#endif /* DONT_COLLAPSE */ 1009#define escape '%' 1010 1011 while (len--) { 1012#ifndef DONT_COLLAPSE 1013 if (*source == collapse) { 1014 PUT(*source); 1015 source++; 1016 continue; 1017 } 1018 else 1019#endif /* DONT_COLLAPSE */ 1020 if (*source != escape) { 1021 PUT(*source); 1022 } 1023 else { 1024 source++; 1025 if (len-- == 0) { 1026 PUT(escape); 1027 break; 1028 } 1029 1030 if (*source == ':' || *source == escape) 1031 PUT(*source) 1032 else { 1033 /* Match the character against the match array */ 1034 register Cardinal j; 1035 1036 for (j = 0; j < num && sub[j].match != *source; j++) {} 1037 1038 /* Substitute the substitution string */ 1039 1040 if (j >= num) PUT(*source) 1041 else if (sub[j].substitution != NULL) { 1042 char *sp = sub[j].substitution; 1043 while (*sp) { 1044 PUT(*sp); 1045 sp++; 1046 } 1047 } 1048 } 1049 } 1050 source++; 1051#ifndef DONT_COLLAPSE 1052 atBeginning = FALSE; 1053#endif /* DONT_COLLAPSE */ 1054 } 1055 PUT('\0'); 1056 1057 return TRUE; 1058#undef PUT 1059#undef escape 1060} 1061 1062 1063_XtString XtFindFile( 1064 _Xconst _XtString path, 1065 Substitution substitutions, 1066 Cardinal num_substitutions, 1067 XtFilePredicate predicate) 1068{ 1069 char *buf, *buf1, *buf2; 1070 _Xconst _XtString colon; 1071 int len; 1072 Boolean firstTime = TRUE; 1073 1074 buf1 = __XtMalloc((unsigned)PATH_MAX); 1075 buf2 = __XtMalloc((unsigned)PATH_MAX); 1076 buf = buf1; 1077 1078 if (predicate == NULL) predicate = TestFile; 1079 1080 while (1) { 1081 colon = path; 1082 /* skip leading colons */ 1083 while (*colon) { 1084 if (*colon != ':') break; 1085 colon++; 1086 path++; 1087 } 1088 /* now look for an un-escaped colon */ 1089 for ( ; *colon ; colon++) { 1090 if (*colon == '%' && *(path+1)) { 1091 colon++; /* bump it an extra time to skip %. */ 1092 continue; 1093 } 1094 if (*colon == ':') 1095 break; 1096 } 1097 len = (int) (colon - path); 1098 if (Resolve(path, len, substitutions, num_substitutions, 1099 buf, '/')) { 1100 if (firstTime || strcmp(buf1,buf2) != 0) { 1101#ifdef XNL_DEBUG 1102 printf("Testing file %s\n", buf); 1103#endif /* XNL_DEBUG */ 1104 /* Check out the file */ 1105 if ((*predicate) (buf)) { 1106 /* We've found it, return it */ 1107#ifdef XNL_DEBUG 1108 printf("File found.\n"); 1109#endif /* XNL_DEBUG */ 1110 if (buf == buf1) { 1111 XtFree(buf2); 1112 return buf1; 1113 } 1114 XtFree(buf1); 1115 return buf2; 1116 } 1117 if (buf == buf1) 1118 buf = buf2; 1119 else 1120 buf = buf1; 1121 firstTime = FALSE; 1122 } 1123 } 1124 1125 /* Nope...any more paths? */ 1126 1127 if (*colon == '\0') break; 1128 path = colon+1; 1129 } 1130 1131 /* No file found */ 1132 1133 XtFree(buf1); 1134 XtFree(buf2); 1135 return NULL; 1136} 1137 1138 1139/* The implementation of this routine is operating system dependent */ 1140/* Should match the code in Xlib _XlcMapOSLocaleName */ 1141 1142static String ExtractLocaleName( 1143 String lang) 1144{ 1145 1146#if defined(hpux) || defined(CSRG_BASED) || defined(sun) || defined(SVR4) || defined(sgi) || defined(__osf__) || defined(AIXV3) || defined(ultrix) || defined(WIN32) || defined (linux) 1147# ifdef hpux 1148/* 1149 * We need to discriminated between HPUX 9 and HPUX 10. The equivalent 1150 * code in Xlib in SetLocale.c does include locale.h via X11/Xlocale.h. 1151 */ 1152# include <locale.h> 1153# ifndef _LastCategory 1154 /* HPUX 9 and earlier */ 1155# define SKIPCOUNT 2 1156# define STARTCHAR ':' 1157# define ENDCHAR ';' 1158# else 1159 /* HPUX 10 */ 1160# define ENDCHAR ' ' 1161# endif 1162# else 1163# ifdef ultrix 1164# define SKIPCOUNT 2 1165# define STARTCHAR '\001' 1166# define ENDCHAR '\001' 1167# else 1168# ifdef WIN32 1169# define SKIPCOUNT 1 1170# define STARTCHAR '=' 1171# define ENDCHAR ';' 1172# define WHITEFILL 1173# else 1174# if defined(__osf__) || (defined(AIXV3) && !defined(AIXV4)) 1175# define STARTCHAR ' ' 1176# define ENDCHAR ' ' 1177# else 1178# if defined(linux) 1179# define STARTSTR "LC_CTYPE=" 1180# define ENDCHAR ';' 1181# else 1182# if !defined(sun) || defined(SVR4) 1183# define STARTCHAR '/' 1184# define ENDCHAR '/' 1185# endif 1186# endif 1187# endif 1188# endif 1189# endif 1190# endif 1191 1192 String start; 1193 String end; 1194 int len; 1195# ifdef SKIPCOUNT 1196 int n; 1197# endif 1198 static char* buf = NULL; 1199# ifdef WHITEFILL 1200 char *temp; 1201# endif 1202 1203 start = lang; 1204# ifdef SKIPCOUNT 1205 for (n = SKIPCOUNT; 1206 --n >= 0 && start && (start = strchr (start, STARTCHAR)); 1207 start++) 1208 ; 1209 if (!start) 1210 start = lang; 1211# endif 1212# ifdef STARTCHAR 1213 if (start && (start = strchr (start, STARTCHAR))) 1214# elif defined (STARTSTR) 1215 if (start && (start = strstr (start,STARTSTR))) 1216# endif 1217 { 1218# ifdef STARTCHAR 1219 start++; 1220# elif defined (STARTSTR) 1221 start += strlen(STARTSTR); 1222# endif 1223 1224 if ((end = strchr (start, ENDCHAR))) { 1225 len = (int) (end - start); 1226 XtFree (buf); 1227 buf = XtMalloc ((Cardinal)(len + 1)); 1228 if (buf == NULL) return NULL; 1229 strncpy(buf, start, (size_t) len); 1230 *(buf + len) = '\0'; 1231# ifdef WHITEFILL 1232 for (temp = buf; (temp = strchr(temp, ' ')) != NULL; ) 1233 *temp++ = '-'; 1234# endif 1235 return buf; 1236 } else /* if no ENDCHAR is found we are at the end of the line */ 1237 return start; 1238 } 1239# ifdef WHITEFILL 1240 if (strchr(lang, ' ')) { 1241 XtFree (buf); 1242 buf = strdup (lang); 1243 if (buf == NULL) return NULL; 1244 for (temp = buf; (temp = strchr(temp, ' ')) != NULL; ) 1245 *temp++ = '-'; 1246 return buf; 1247 } 1248# endif 1249# undef STARTCHAR 1250# undef ENDCHAR 1251# undef WHITEFILL 1252#endif 1253 1254 return lang; 1255} 1256 1257static void FillInLangSubs( 1258 Substitution subs, 1259 XtPerDisplay pd) 1260{ 1261 int len; 1262 String string; 1263 char *p1, *p2, *p3; 1264 char **rest; 1265 char *ch; 1266 1267 if (pd->language == NULL || 1268 (pd->language != NULL && pd->language[0] == '\0')) { 1269 subs[0].substitution = subs[1].substitution = 1270 subs[2].substitution = subs[3].substitution = NULL; 1271 return; 1272 } 1273 1274 string = ExtractLocaleName(pd->language); 1275 1276 if (string == NULL || 1277 (string != NULL && string[0] == '\0')) { 1278 subs[0].substitution = subs[1].substitution = 1279 subs[2].substitution = subs[3].substitution = NULL; 1280 return; 1281 } 1282 1283 len = (int) strlen(string) + 1; 1284 subs[0].substitution = (_XtString) string; 1285 p1 = subs[1].substitution = __XtMalloc((Cardinal) (3*len)); 1286 p2 = subs[2].substitution = subs[1].substitution + len; 1287 p3 = subs[3].substitution = subs[2].substitution + len; 1288 1289 /* Everything up to the first "_" goes into p1. From "_" to "." in 1290 p2. The rest in p3. If no delimiters, all goes into p1. We 1291 assume p1, p2, and p3 are large enough. */ 1292 1293 *p1 = *p2 = *p3 = '\0'; 1294 1295 ch = strchr(string, '_'); 1296 if (ch != NULL) { 1297 len = (int) (ch - string); 1298 (void) strncpy(p1, string, (size_t) len); 1299 p1[len] = '\0'; 1300 string = ch + 1; 1301 rest = &p2; 1302 } else rest = &p1; 1303 1304 /* Rest points to where we put the first part */ 1305 1306 ch = strchr(string, '.'); 1307 if (ch != NULL) { 1308 len = (int) (ch - string); 1309 strncpy(*rest, string, (size_t) len); 1310 (*rest)[len] = '\0'; 1311 (void) strcpy(p3, ch+1); 1312 } else (void) strcpy(*rest, string); 1313} 1314 1315/* 1316 * default path used if environment variable XFILESEARCHPATH 1317 * is not defined. Also substitued for %D. 1318 * The exact value should be documented in the implementation 1319 * notes for any Xt implementation. 1320 */ 1321static const char *implementation_default_path(void) 1322{ 1323#if defined(WIN32) 1324 static char xfilesearchpath[] = ""; 1325 1326 return xfilesearchpath; 1327#else 1328 return XFILESEARCHPATHDEFAULT; 1329#endif 1330} 1331 1332 1333static SubstitutionRec defaultSubs[] = { 1334 {'N', NULL}, 1335 {'T', NULL}, 1336 {'S', NULL}, 1337 {'C', NULL}, 1338 {'L', NULL}, 1339 {'l', NULL}, 1340 {'t', NULL}, 1341 {'c', NULL} 1342}; 1343 1344 1345_XtString XtResolvePathname( 1346 Display *dpy, 1347 _Xconst char* type, 1348 _Xconst char* filename, 1349 _Xconst char* suffix, 1350 _Xconst char* path, 1351 Substitution substitutions, 1352 Cardinal num_substitutions, 1353 XtFilePredicate predicate) 1354{ 1355 XtPerDisplay pd; 1356 static const char *defaultPath = NULL; 1357 const char *impl_default = implementation_default_path(); 1358 int idef_len = (int) strlen(impl_default); 1359 char *massagedPath; 1360 int bytesAllocd, bytesLeft; 1361 char *ch, *result; 1362 Substitution merged_substitutions; 1363 XrmRepresentation db_type; 1364 XrmValue value; 1365 XrmName name_list[3]; 1366 XrmClass class_list[3]; 1367 Boolean pathMallocd = False; 1368 1369 LOCK_PROCESS; 1370 pd = _XtGetPerDisplay(dpy); 1371 if (path == NULL) { 1372#ifndef VMS 1373 if (defaultPath == NULL) { 1374 defaultPath = getenv("XFILESEARCHPATH"); 1375 if (defaultPath == NULL) 1376 defaultPath = impl_default; 1377 } 1378 path = defaultPath; 1379#endif /* VMS */ 1380 } 1381 1382 if (path == NULL) 1383 path = ""; /* NULL would kill us later */ 1384 1385 if (filename == NULL) { 1386 filename = XrmClassToString(pd->class); 1387 } 1388 1389 bytesAllocd = bytesLeft = 1000; 1390 massagedPath = ALLOCATE_LOCAL((size_t)bytesAllocd); 1391 if (massagedPath == NULL) _XtAllocError(NULL); 1392 1393 if (path[0] == ':') { 1394 strcpy(massagedPath, "%N%S"); 1395 ch = &massagedPath[4]; 1396 bytesLeft -= 4; 1397 } else ch = massagedPath; 1398 1399 /* Insert %N%S between adjacent colons 1400 * and default path for %D. 1401 * Default path should not have any adjacent colons of its own. 1402 */ 1403 1404 while (*path != '\0') { 1405 if (bytesLeft < idef_len) { 1406 int bytesUsed = bytesAllocd - bytesLeft; 1407 char *new; 1408 bytesAllocd +=1000; 1409 new = __XtMalloc((Cardinal) bytesAllocd); 1410 strncpy( new, massagedPath, (size_t) bytesUsed ); 1411 ch = new + bytesUsed; 1412 if (pathMallocd) 1413 XtFree(massagedPath); 1414 else 1415 DEALLOCATE_LOCAL(massagedPath); 1416 pathMallocd = True; 1417 massagedPath = new; 1418 bytesLeft = bytesAllocd - bytesUsed; 1419 } 1420 if (*path == '%' && *(path+1) == ':') { 1421 *ch++ = '%'; 1422 *ch++ = ':'; 1423 path += 2; 1424 bytesLeft -= 2; 1425 continue; 1426 } 1427 if (*path == ':' && *(path+1) == ':') { 1428 strcpy(ch, ":%N%S:"); 1429 ch += 6; 1430 bytesLeft -= 6; 1431 while (*path == ':') path++; 1432 continue; 1433 } 1434 if (*path == '%' && *(path+1) == 'D') { 1435 strcpy(ch, impl_default); 1436 ch += idef_len; 1437 bytesLeft -= idef_len; 1438 path += 2; 1439 continue; 1440 } 1441 *ch++ = *path++; 1442 bytesLeft--; 1443 } 1444 *ch = '\0'; 1445#ifdef XNL_DEBUG 1446 printf("Massaged path: %s\n", massagedPath); 1447#endif /* XNL_DEBUG */ 1448 1449 if (num_substitutions == 0) 1450 merged_substitutions = defaultSubs; 1451 else { 1452 int i = XtNumber(defaultSubs); 1453 Substitution sub, def; 1454 merged_substitutions = sub = (Substitution) 1455 ALLOCATE_LOCAL((unsigned)(num_substitutions+(Cardinal)i)*sizeof(SubstitutionRec)); 1456 if (sub == NULL) _XtAllocError(NULL); 1457 for (def = defaultSubs; i--; sub++, def++) sub->match = def->match; 1458 for (i = (int) num_substitutions; i--; ) *sub++ = *substitutions++; 1459 } 1460 merged_substitutions[0].substitution = (_XtString)filename; 1461 merged_substitutions[1].substitution = (_XtString)type; 1462 merged_substitutions[2].substitution = (_XtString)suffix; 1463 name_list[0] = pd->name; 1464 name_list[1] = XrmPermStringToQuark("customization"); 1465 name_list[2] = NULLQUARK; 1466 class_list[0] = pd->class; 1467 class_list[1] = XrmPermStringToQuark("Customization"); 1468 class_list[2] = NULLQUARK; 1469 if (XrmQGetResource(XrmGetDatabase(dpy), name_list, class_list, 1470 &db_type, &value) && 1471 db_type == _XtQString) 1472 merged_substitutions[3].substitution = (char *)value.addr; 1473 else 1474 merged_substitutions[3].substitution = NULL; 1475 FillInLangSubs(&merged_substitutions[4], pd); 1476 1477 result = XtFindFile(massagedPath, merged_substitutions, 1478 num_substitutions + XtNumber(defaultSubs), 1479 predicate); 1480 1481 if (merged_substitutions[5].substitution != NULL) 1482 XtFree( (XtPointer)merged_substitutions[5].substitution ); 1483 1484 if (merged_substitutions != defaultSubs) 1485 DEALLOCATE_LOCAL(merged_substitutions); 1486 1487 if (pathMallocd) 1488 XtFree(massagedPath); 1489 else 1490 DEALLOCATE_LOCAL(massagedPath); 1491 1492 UNLOCK_PROCESS; 1493 return result; 1494} 1495 1496 1497Boolean XtCallAcceptFocus( 1498 Widget widget, 1499 Time *time) 1500{ 1501 XtAcceptFocusProc ac; 1502 Boolean retval; 1503 WIDGET_TO_APPCON(widget); 1504 1505 LOCK_APP(app); 1506 LOCK_PROCESS; 1507 ac = XtClass(widget)->core_class.accept_focus; 1508 UNLOCK_PROCESS; 1509 1510 if (ac != NULL) 1511 retval = (*ac) (widget, time); 1512 else 1513 retval = FALSE; 1514 UNLOCK_APP(app); 1515 return retval; 1516} 1517 1518#ifdef XT_GEO_TATTLER 1519/************************************************************************** 1520 GeoTattler: This is used to debug Geometry management in Xt. 1521 1522 It uses a pseudo resource XtNgeotattler. 1523 1524 E.G. if those lines are found in the resource database: 1525 1526 myapp*draw.XmScale.geoTattler: ON 1527 *XmScrollBar.geoTattler:ON 1528 *XmRowColumn.exit_button.geoTattler:ON 1529 1530 then: 1531 1532 all the XmScale children of the widget named draw, 1533 all the XmScrollBars, 1534 the widget named exit_button in any XmRowColumn 1535 1536 will return True to the function IsTattled(), and will generate 1537 outlined trace to stdout. 1538 1539*************************************************************************/ 1540 1541#define XtNgeoTattler "geoTattler" 1542#define XtCGeoTattler "GeoTattler" 1543 1544typedef struct { Boolean geo_tattler ;} GeoDataRec ; 1545 1546static XtResource geo_resources[] = { 1547 { XtNgeoTattler, XtCGeoTattler, XtRBoolean, sizeof(Boolean), 1548 XtOffsetOf(GeoDataRec, geo_tattler), 1549 XtRImmediate, (XtPointer) False } 1550}; 1551 1552/************************************************************************ 1553 This function uses XtGetSubresources to find out if a widget 1554 needs to be geo-spied by the caller. */ 1555static Boolean IsTattled (Widget widget) 1556{ 1557 GeoDataRec geo_data ; 1558 1559 XtGetSubresources(widget, (XtPointer)&geo_data, 1560 (String)NULL, (String)NULL, 1561 geo_resources, XtNumber(geo_resources), 1562 NULL, 0); 1563 1564 return geo_data.geo_tattler; 1565 1566} /* IsTattled */ 1567 1568static int n_tab = 0 ; /* not MT for now */ 1569 1570void 1571_XtGeoTab (int direction) /* +1 or -1 */ 1572{ 1573 n_tab += direction ; 1574} 1575 1576 1577void 1578_XtGeoTrace (Widget widget, const char *fmt, ...) 1579{ 1580 if (IsTattled(widget)) { 1581 va_list args; 1582 int i ; 1583 1584 va_start(args, fmt); 1585 for (i=0; i<n_tab; i++) printf(" "); 1586 (void) vprintf(fmt, args); 1587 va_end(args); 1588 } 1589} 1590 1591#endif /* XT_GEO_TATTLER */ 1592 1593