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