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