Intrinsic.c revision 444c061a
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 = 0, 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 /* try the places set in the environment */ 877 drive = getenv ("_XBASEDRIVE"); 878#ifdef __UNIXOS2__ 879 if (!drive) 880 drive = getenv ("X11ROOT"); 881#endif 882 if (!drive) 883 drive = "C:"; 884 len = strlen (drive) + strlen (path); 885 bufp = XtStackAlloc (len + 1, buf); 886 strcpy (bufp, drive); 887 strcat (bufp, path); 888 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 889 XtStackFree (bufp, buf); 890 return 1; 891 } 892 893#ifndef __UNIXOS2__ 894 /* one last place to look */ 895 drive = getenv ("HOMEDRIVE"); 896 if (drive) { 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 907 /* does OS/2 (with or with gcc-emx) have getdrives()? */ 908 /* tried everywhere else, go fishing */ 909 drives = _getdrives (); 910#define C_DRIVE ('C' - 'A') 911#define Z_DRIVE ('Z' - 'A') 912 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 913 if ((1 << i) & drives) { 914 len = 2 + strlen (path); 915 bufp = XtStackAlloc (len + 1, buf); 916 *bufp = 'A' + i; 917 *(bufp + 1) = ':'; 918 *(bufp + 2) = '\0'; 919 strcat (bufp, path); 920 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 921 XtStackFree (bufp, buf); 922 return 1; 923 } 924 } 925 } 926#endif 927 return 0; 928} 929#endif 930 931static Boolean TestFile( 932 String path) 933{ 934#ifndef VMS 935 int ret = 0; 936 struct stat status; 937#if defined(WIN32) 938 char buf[MAX_PATH]; 939 char* bufp; 940 int len; 941 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 942 943 if (AccessFile (path, buf, MAX_PATH, &bufp)) 944 path = bufp; 945 946 (void) SetErrorMode (olderror); 947#endif 948 ret = (access(path, R_OK) == 0 && /* exists and is readable */ 949 stat(path, &status) == 0 && /* get the status */ 950#ifndef X_NOT_POSIX 951 S_ISDIR(status.st_mode) == 0); /* not a directory */ 952#else 953 (status.st_mode & S_IFMT) != S_IFDIR); /* not a directory */ 954#endif /* X_NOT_POSIX else */ 955#if defined(WIN32) 956 XtStackFree ((XtPointer)bufp, buf); 957#endif 958 return ret; 959#else /* VMS */ 960 return TRUE; /* Who knows what to do here? */ 961#endif /* VMS */ 962} 963 964/* return of TRUE = resolved string fit, FALSE = didn't fit. Not 965 null-terminated and not collapsed if it didn't fit */ 966 967static Boolean Resolve( 968 register _Xconst char *source, /* The source string */ 969 register int len, /* The length in bytes of *source */ 970 Substitution sub, /* Array of string values to substitute */ 971 Cardinal num, /* Number of substitution entries */ 972 char *buf, /* Where to put the resolved string; */ 973 char collapse) /* Character to collapse */ 974{ 975 register int bytesLeft = PATH_MAX; 976 register char* bp = buf; 977#ifndef DONT_COLLAPSE 978 Boolean atBeginning = TRUE; 979 Boolean prevIsCollapse = FALSE; 980 981#define PUT(ch) \ 982 { \ 983 if (--bytesLeft == 0) return FALSE; \ 984 if (prevIsCollapse) \ 985 if ((*bp = ch) != collapse) { \ 986 prevIsCollapse = FALSE; \ 987 bp++; \ 988 } \ 989 else bytesLeft++; \ 990 else if ((*bp++ = ch) == collapse && !atBeginning) \ 991 prevIsCollapse = TRUE; \ 992 } 993#else /* DONT_COLLAPSE */ 994 995#define PUT(ch) \ 996 { \ 997 if (--bytesLeft == 0) return FALSE; \ 998 *bp++ = ch; \ 999 } 1000#endif /* DONT_COLLAPSE */ 1001#define escape '%' 1002 1003 while (len--) { 1004#ifndef DONT_COLLAPSE 1005 if (*source == collapse) { 1006 PUT(*source); 1007 source++; 1008 continue; 1009 } 1010 else 1011#endif /* DONT_COLLAPSE */ 1012 if (*source != escape) { 1013 PUT(*source); 1014 } 1015 else { 1016 source++; 1017 if (len-- == 0) { 1018 PUT(escape); 1019 break; 1020 } 1021 1022 if (*source == ':' || *source == escape) 1023 PUT(*source) 1024 else { 1025 /* Match the character against the match array */ 1026 register Cardinal j; 1027 1028 for (j = 0; j < num && sub[j].match != *source; j++) {} 1029 1030 /* Substitute the substitution string */ 1031 1032 if (j >= num) PUT(*source) 1033 else if (sub[j].substitution != NULL) { 1034 char *sp = sub[j].substitution; 1035 while (*sp) { 1036 PUT(*sp); 1037 sp++; 1038 } 1039 } 1040 } 1041 } 1042 source++; 1043#ifndef DONT_COLLAPSE 1044 atBeginning = FALSE; 1045#endif /* DONT_COLLAPSE */ 1046 } 1047 PUT('\0'); 1048 1049 return TRUE; 1050#undef PUT 1051#undef escape 1052} 1053 1054 1055String XtFindFile( 1056 _Xconst char* path, 1057 Substitution substitutions, 1058 Cardinal num_substitutions, 1059 XtFilePredicate predicate) 1060{ 1061 char *buf, *buf1, *buf2, *colon; 1062 int len; 1063 Boolean firstTime = TRUE; 1064 1065 buf = buf1 = __XtMalloc((unsigned)PATH_MAX); 1066 buf2 = __XtMalloc((unsigned)PATH_MAX); 1067 1068 if (predicate == NULL) predicate = TestFile; 1069 1070 while (1) { 1071 colon = (String)path; 1072 /* skip leading colons */ 1073 while (*colon) { 1074 if (*colon != ':') break; 1075 colon++; 1076 path++; 1077 } 1078 /* now look for an un-escaped colon */ 1079 for ( ; *colon ; colon++) { 1080 if (*colon == '%' && *(path+1)) { 1081 colon++; /* bump it an extra time to skip %. */ 1082 continue; 1083 } 1084 if (*colon == ':') 1085#ifdef __UNIXOS2__ 1086 if (colon > (path+1)) 1087#endif 1088 break; 1089 } 1090 len = colon - path; 1091 if (Resolve(path, len, substitutions, num_substitutions, 1092 buf, '/')) { 1093 if (firstTime || strcmp(buf1,buf2) != 0) { 1094#ifdef __UNIXOS2__ 1095 { 1096 char *bufx = (char*)__XOS2RedirRoot(buf); 1097 strcpy(buf,bufx); 1098 } 1099#endif 1100#ifdef XNL_DEBUG 1101 printf("Testing file %s\n", buf); 1102#endif /* XNL_DEBUG */ 1103 /* Check out the file */ 1104 if ((*predicate) (buf)) { 1105 /* We've found it, return it */ 1106#ifdef XNL_DEBUG 1107 printf("File found.\n"); 1108#endif /* XNL_DEBUG */ 1109 if (buf == buf1) XtFree(buf2); 1110 else XtFree(buf1); 1111 return buf; 1112 } 1113 if (buf == buf1) 1114 buf = buf2; 1115 else 1116 buf = buf1; 1117 firstTime = FALSE; 1118 } 1119 } 1120 1121 /* Nope...any more paths? */ 1122 1123 if (*colon == '\0') break; 1124 path = colon+1; 1125 } 1126 1127 /* No file found */ 1128 1129 XtFree(buf1); 1130 XtFree(buf2); 1131 return NULL; 1132} 1133 1134 1135/* The implementation of this routine is operating system dependent */ 1136/* Should match the code in Xlib _XlcMapOSLocaleName */ 1137 1138static char *ExtractLocaleName( 1139 String lang) 1140{ 1141 1142#if defined(hpux) || defined(CSRG_BASED) || defined(sun) || defined(SVR4) || defined(sgi) || defined(__osf__) || defined(AIXV3) || defined(ultrix) || defined(WIN32) || defined(__UNIXOS2__) || defined (linux) 1143# ifdef hpux 1144/* 1145 * We need to discriminated between HPUX 9 and HPUX 10. The equivalent 1146 * code in Xlib in SetLocale.c does include locale.h via X11/Xlocale.h. 1147 */ 1148# include <locale.h> 1149# ifndef _LastCategory 1150 /* HPUX 9 and earlier */ 1151# define SKIPCOUNT 2 1152# define STARTCHAR ':' 1153# define ENDCHAR ';' 1154# else 1155 /* HPUX 10 */ 1156# define ENDCHAR ' ' 1157# endif 1158# else 1159# ifdef ultrix 1160# define SKIPCOUNT 2 1161# define STARTCHAR '\001' 1162# define ENDCHAR '\001' 1163# else 1164# if defined(WIN32) || defined(__UNIXOS2__) 1165# define SKIPCOUNT 1 1166# define STARTCHAR '=' 1167# define ENDCHAR ';' 1168# define WHITEFILL 1169# else 1170# if defined(__osf__) || (defined(AIXV3) && !defined(AIXV4)) 1171# define STARTCHAR ' ' 1172# define ENDCHAR ' ' 1173# else 1174# if defined(linux) 1175# define STARTSTR "LC_CTYPE=" 1176# define ENDCHAR ';' 1177# else 1178# if !defined(sun) || defined(SVR4) 1179# define STARTCHAR '/' 1180# define ENDCHAR '/' 1181# endif 1182# endif 1183# endif 1184# endif 1185# endif 1186# endif 1187 1188 char *start; 1189 char *end; 1190 int len; 1191# ifdef SKIPCOUNT 1192 int n; 1193# endif 1194 static char* buf = NULL; 1195 1196 start = lang; 1197# ifdef SKIPCOUNT 1198 for (n = SKIPCOUNT; 1199 --n >= 0 && start && (start = strchr (start, STARTCHAR)); 1200 start++) 1201 ; 1202 if (!start) 1203 start = lang; 1204# endif 1205# ifdef STARTCHAR 1206 if (start && (start = strchr (start, STARTCHAR))) 1207# elif defined (STARTSTR) 1208 if (start && (start = strstr (start,STARTSTR))) 1209# endif 1210 { 1211# ifdef STARTCHAR 1212 start++; 1213# elif defined (STARTSTR) 1214 start += strlen(STARTSTR); 1215# endif 1216 1217 if ((end = strchr (start, ENDCHAR))) { 1218 len = end - start; 1219 if (buf != NULL) XtFree (buf); 1220 buf = XtMalloc (len + 1); 1221 if (buf == NULL) return NULL; 1222 strncpy(buf, start, len); 1223 *(buf + len) = '\0'; 1224# ifdef WHITEFILL 1225 for (start = buf; start = strchr(start, ' '); ) 1226 *start++ = '-'; 1227# endif 1228 return buf; 1229 } else /* if no ENDCHAR is found we are at the end of the line */ 1230 return start; 1231 } 1232# ifdef WHITEFILL 1233 if (strchr(lang, ' ')) { 1234 if (buf != NULL) XtFree (buf); 1235 else buf = XtMalloc (strlen (lang) + 1); 1236 if (buf == NULL) return NULL; 1237 strcpy(buf, lang); 1238 for (start = buf; start = strchr(start, ' '); ) 1239 *start++ = '-'; 1240 return buf; 1241 } 1242# endif 1243# undef STARTCHAR 1244# undef ENDCHAR 1245# undef WHITEFILL 1246#endif 1247 1248 return lang; 1249} 1250 1251static void FillInLangSubs( 1252 Substitution subs, 1253 XtPerDisplay pd) 1254{ 1255 int len; 1256 char *string, *p1, *p2, *p3; 1257 char **rest; 1258 char *ch; 1259 1260 if (pd->language == NULL || 1261 (pd->language != NULL && pd->language[0] == '\0')) { 1262 subs[0].substitution = subs[1].substitution = 1263 subs[2].substitution = subs[3].substitution = NULL; 1264 return; 1265 } 1266 1267 string = ExtractLocaleName(pd->language); 1268 1269 if (string == NULL || 1270 (string != NULL && string[0] == '\0')) { 1271 subs[0].substitution = subs[1].substitution = 1272 subs[2].substitution = subs[3].substitution = NULL; 1273 return; 1274 } 1275 1276 len = strlen(string) + 1; 1277 subs[0].substitution = string; 1278 p1 = subs[1].substitution = __XtMalloc((Cardinal) 3*len); 1279 p2 = subs[2].substitution = subs[1].substitution + len; 1280 p3 = subs[3].substitution = subs[2].substitution + len; 1281 1282 /* Everything up to the first "_" goes into p1. From "_" to "." in 1283 p2. The rest in p3. If no delimiters, all goes into p1. We 1284 assume p1, p2, and p3 are large enough. */ 1285 1286 *p1 = *p2 = *p3 = '\0'; 1287 1288 ch = strchr(string, '_'); 1289 if (ch != NULL) { 1290 len = ch - string; 1291 (void) strncpy(p1, string, len); 1292 p1[len] = '\0'; 1293 string = ch + 1; 1294 rest = &p2; 1295 } else rest = &p1; 1296 1297 /* Rest points to where we put the first part */ 1298 1299 ch = strchr(string, '.'); 1300 if (ch != NULL) { 1301 len = ch - string; 1302 strncpy(*rest, string, len); 1303 (*rest)[len] = '\0'; 1304 (void) strcpy(p3, ch+1); 1305 } else (void) strcpy(*rest, string); 1306} 1307 1308/* 1309 * default path used if environment variable XFILESEARCHPATH 1310 * is not defined. Also substitued for %D. 1311 * The exact value should be documented in the implementation 1312 * notes for any Xt implementation. 1313 */ 1314static char *implementation_default_path(void) 1315{ 1316#if defined(WIN32) || defined(__UNIXOS2__) 1317 /* if you know how to pass % thru the compiler let me know */ 1318 static char xfilesearchpath[] = XFILESEARCHPATHDEFAULT; 1319 static Bool fixed; 1320 char *ch; 1321 1322 if (!fixed) { 1323 for (ch = xfilesearchpath; ch = strchr(ch, ';'); ch++) 1324 *ch = '%'; 1325 fixed = True; 1326 } 1327 return xfilesearchpath; 1328#else 1329 return XFILESEARCHPATHDEFAULT; 1330#endif 1331} 1332 1333 1334static SubstitutionRec defaultSubs[] = { 1335 {'N', NULL}, 1336 {'T', NULL}, 1337 {'S', NULL}, 1338 {'C', NULL}, 1339 {'L', NULL}, 1340 {'l', NULL}, 1341 {'t', NULL}, 1342 {'c', NULL} 1343}; 1344 1345 1346String XtResolvePathname( 1347 Display *dpy, 1348 _Xconst char* type, 1349 _Xconst char* filename, 1350 _Xconst char* suffix, 1351 _Xconst char* path, 1352 Substitution substitutions, 1353 Cardinal num_substitutions, 1354 XtFilePredicate predicate) 1355{ 1356 XtPerDisplay pd; 1357 static char *defaultPath = NULL; 1358 char *impl_default = implementation_default_path(); 1359 int idef_len = strlen(impl_default); 1360 char *massagedPath; 1361 int bytesAllocd, bytesLeft; 1362 char *ch, *result; 1363 Substitution merged_substitutions; 1364 XrmRepresentation db_type; 1365 XrmValue value; 1366 XrmName name_list[3]; 1367 XrmClass class_list[3]; 1368 Boolean pathMallocd = False; 1369 1370 LOCK_PROCESS; 1371 pd = _XtGetPerDisplay(dpy); 1372 if (path == NULL) { 1373#ifndef VMS 1374 if (defaultPath == NULL) { 1375 defaultPath = getenv("XFILESEARCHPATH"); 1376 if (defaultPath == NULL) 1377 defaultPath = impl_default; 1378 } 1379 path = defaultPath; 1380#else 1381 path = ""; /* NULL would kill us later */ 1382#endif /* VMS */ 1383 } 1384 1385 if (filename == NULL) { 1386 filename = XrmClassToString(pd->class); 1387 } 1388 1389 bytesAllocd = bytesLeft = 1000; 1390 massagedPath = ALLOCATE_LOCAL(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, 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+i)*sizeof(SubstitutionRec)); 1456 if (sub == NULL) _XtAllocError(NULL); 1457 for (def = defaultSubs; i--; sub++, def++) sub->match = def->match; 1458 for (i = num_substitutions; i--; ) *sub++ = *substitutions++; 1459 } 1460 merged_substitutions[0].substitution = (String)filename; 1461 merged_substitutions[1].substitution = (String)type; 1462 merged_substitutions[2].substitution = (String)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, ...) 1579{ 1580 va_list args; 1581 char *fmt; 1582 int i ; 1583 if (IsTattled(widget)) { 1584 va_start(args, widget); 1585 fmt = va_arg(args, char *); 1586 for (i=0; i<n_tab; i++) printf(" "); 1587 (void) vprintf(fmt, args); 1588 va_end(args); 1589 } 1590} 1591 1592#endif /* XT_GEO_TATTLER */ 1593 1594