home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / l / libxtgeo.zip / libgeo17 / Xt / Intrinsic.c < prev    next >
C/C++ Source or Header  |  1992-10-06  |  29KB  |  1,125 lines

  1. /* $XConsortium: Intrinsic.c,v 1.172 92/04/15 19:15:24 rws Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  5. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  6.  
  7.                         All Rights Reserved
  8.  
  9. Permission to use, copy, modify, and distribute this software and its 
  10. documentation for any purpose and without fee is hereby granted, 
  11. provided that the above copyright notice appear in all copies and that
  12. both that copyright notice and this permission notice appear in 
  13. supporting documentation, and that the names of Digital or MIT not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.  
  16.  
  17. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  19. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. #define INTRINSIC_C
  28.  
  29. #include "IntrinsicI.h"
  30. #include "StringDefs.h"
  31. #ifndef NO_IDENTIFY_WINDOWS
  32. #include <X11/Xatom.h>
  33. #endif
  34. #ifndef VMS
  35. #include <sys/stat.h>
  36. #endif /* VMS */
  37.  
  38. #ifndef X_NOT_STDC_ENV
  39. #include <stdlib.h>
  40. #else
  41. extern char *getenv();
  42. #endif
  43.  
  44. String XtCXtToolkitError = "XtToolkitError";
  45.  
  46. Boolean XtIsSubclass(widget, widgetClass)
  47.     Widget    widget;
  48.     WidgetClass widgetClass;
  49. {
  50.     register WidgetClass w;
  51.  
  52.     for (w = widget->core.widget_class; w != NULL; w = w->core_class.superclass)
  53.     if (w == widgetClass) return (TRUE);
  54.     return (FALSE);
  55. } /* XtIsSubclass */
  56.  
  57.  
  58. #if NeedFunctionPrototypes
  59. Boolean _XtCheckSubclassFlag(
  60.     Widget object,
  61.     _XtXtEnum flag
  62.     )
  63. #else
  64. Boolean _XtCheckSubclassFlag(object, flag)
  65.     Widget object;
  66.     XtEnum flag;
  67. #endif
  68. {
  69.     if (object->core.widget_class->core_class.class_inited & flag)
  70.     return True;
  71.     else
  72.     return False;
  73.  
  74. } /*_XtVerifySubclass */
  75.  
  76.  
  77. #if NeedFunctionPrototypes
  78. Boolean _XtIsSubclassOf(
  79.     Widget object,
  80.     WidgetClass widgetClass,
  81.     WidgetClass superClass,
  82.     _XtXtEnum flag
  83.     )
  84. #else
  85. Boolean _XtIsSubclassOf(object, widgetClass, superClass, flag)
  86.     Widget object;
  87.     WidgetClass widgetClass, superClass;
  88.     XtEnum flag;
  89. #endif
  90. {
  91.     if (!(object->core.widget_class->core_class.class_inited & flag))
  92.     return False;
  93.     else {
  94.     register WidgetClass c = object->core.widget_class;
  95.     while (c != superClass) {
  96.         if (c == widgetClass)
  97.         return True;
  98.         c = c->core_class.superclass;
  99.     }
  100.     return False;
  101.     }
  102. } /*_XtIsSubclassOf */
  103.  
  104.  
  105. static void ComputeWindowAttributes(widget,value_mask,values)
  106.     Widget         widget;
  107.     XtValueMask         *value_mask;
  108.     XSetWindowAttributes *values;
  109. {
  110.     *value_mask = CWEventMask | CWColormap;
  111.     (*values).event_mask = XtBuildEventMask(widget);
  112.     (*values).colormap = widget->core.colormap;
  113.     if (widget->core.background_pixmap != XtUnspecifiedPixmap) {
  114.     *value_mask |= CWBackPixmap;
  115.     (*values).background_pixmap = widget->core.background_pixmap;
  116.     } else {
  117.     *value_mask |= CWBackPixel;
  118.     (*values).background_pixel = widget->core.background_pixel;
  119.     }
  120.     if (widget->core.border_pixmap != XtUnspecifiedPixmap) {
  121.     *value_mask |= CWBorderPixmap;
  122.     (*values).border_pixmap = widget->core.border_pixmap;
  123.     } else {
  124.     *value_mask |= CWBorderPixel;
  125.     (*values).border_pixel = widget->core.border_pixel;
  126.     }
  127.     if (widget->core.widget_class->core_class.expose == (XtExposeProc) NULL) {
  128.     /* Try to avoid redisplay upon resize by making bit_gravity the same
  129.        as the default win_gravity */
  130.     *value_mask |= CWBitGravity;
  131.     (*values).bit_gravity = NorthWestGravity;
  132.     }
  133. } /* ComputeWindowAttributes */
  134.  
  135. static void CallChangeManaged(widget)
  136.     register Widget        widget;
  137. {
  138.     register Cardinal        i;
  139.     XtWidgetProc        change_managed;
  140.     register WidgetList        children;
  141.     int                managed_children = 0;
  142.  
  143.     register CompositePtr cpPtr;
  144.     register CompositePartPtr clPtr;
  145.    
  146.     if (XtIsComposite (widget)) {
  147.     cpPtr = (CompositePtr)&((CompositeWidget) widget)->composite;
  148.         clPtr = (CompositePartPtr)&((CompositeWidgetClass)
  149.                    widget->core.widget_class)->composite_class;
  150.     } else return;
  151.  
  152.     children = cpPtr->children;
  153.     change_managed = clPtr->change_managed;
  154.  
  155.     /* CallChangeManaged for all children */
  156.     for (i = cpPtr->num_children; i != 0; --i) {
  157.     CallChangeManaged (children[i-1]);
  158.     if (XtIsManaged(children[i-1])) managed_children++;
  159.     }
  160.  
  161.     if (change_managed != NULL && managed_children != 0) {
  162.     (*change_managed) (widget);
  163.     }
  164. } /* CallChangeManaged */
  165.  
  166.  
  167. static void MapChildren(cwp)
  168.     CompositePart *cwp;
  169. {
  170.     Cardinal i;
  171.     WidgetList children;
  172.     register Widget child;
  173.  
  174.     children = cwp->children;
  175.     for (i = 0; i <  cwp->num_children; i++) {
  176.     child = children[i];
  177.     if (XtIsWidget (child)){
  178.         if (child->core.managed && child->core.mapped_when_managed) {
  179.         XtMapWidget (children[i]);
  180.         }
  181.     }
  182.     }
  183. } /* MapChildren */
  184.  
  185.  
  186. static Boolean ShouldMapAllChildren(cwp)
  187.     CompositePart *cwp;
  188. {
  189.     Cardinal i;
  190.     WidgetList children;
  191.     register Widget child;
  192.  
  193.     children = cwp->children;
  194.     for (i = 0; i < cwp->num_children; i++) {
  195.     child = children[i];
  196.     if (XtIsWidget(child)) {
  197.         if (XtIsRealized(child) && (! (child->core.managed 
  198.                       && child->core.mapped_when_managed))){
  199.             return False;
  200.         }
  201.     }
  202.     }
  203.  
  204.     return True;
  205. } /* ShouldMapAllChildren */
  206.  
  207.  
  208. static void RealizeWidget(widget)
  209.     register Widget        widget;
  210. {
  211.     XtValueMask            value_mask;
  212.     XSetWindowAttributes    values;
  213.     XtRealizeProc        realize;
  214.     Window            window;
  215.  
  216.     if (!XtIsWidget(widget) || XtIsRealized(widget)) return;
  217.  
  218.     _XtInstallTranslations(widget);
  219.  
  220.     ComputeWindowAttributes (widget, &value_mask, &values);
  221.     realize = widget->core.widget_class->core_class.realize;
  222.     if (realize == NULL)
  223.     XtAppErrorMsg(XtWidgetToApplicationContext(widget),
  224.               "invalidProcedure","realizeProc",XtCXtToolkitError,
  225.               "No realize class procedure defined",
  226.               (String *)NULL, (Cardinal *)NULL);
  227.     else (*realize) (widget, &value_mask, &values);
  228.     window = XtWindow(widget);
  229. #ifndef NO_IDENTIFY_WINDOWS
  230.     if (_XtGetPerDisplay(XtDisplay(widget))->appContext->identify_windows) {
  231.     int len_nm, len_cl;
  232.     char *s;
  233.  
  234.     len_nm = widget->core.name ? strlen(widget->core.name) : 0;
  235.     len_cl = strlen(widget->core.widget_class->core_class.class_name);
  236.     s = XtMalloc((unsigned) (len_nm + len_cl + 2));
  237.     s[0] = '\0';
  238.     if (len_nm)
  239.         strcpy(s, widget->core.name);
  240.     strcpy(s + len_nm + 1,
  241.            widget->core.widget_class->core_class.class_name);
  242.     XChangeProperty(XtDisplay(widget), window,
  243.             XInternAtom(XtDisplay(widget), "_MIT_OBJ_CLASS",
  244.                     False),
  245.             XA_STRING, 8, PropModeReplace, (unsigned char *) s, 
  246.             len_nm + len_cl + 2);
  247.     XtFree(s);
  248.     }
  249. #endif
  250. #ifdef notdef
  251.     _XtRegisterAsyncHandlers(widget);
  252. #endif
  253.     _XtRegisterGrabs(widget);
  254.     _XtRegisterWindow (window, widget);
  255.  
  256.     if (XtIsComposite (widget)) {
  257.     register Cardinal        i;
  258.     register CompositePart *cwp = &(((CompositeWidget)widget)->composite);
  259.     register WidgetList children = cwp->children;
  260.     /* Realize all children */
  261.     for (i = cwp->num_children; i != 0; --i) {
  262.         RealizeWidget (children[i-1]);
  263.     }
  264.     /* Map children that are managed and mapped_when_managed */
  265.  
  266.     if (cwp->num_children != 0) {
  267.         if (ShouldMapAllChildren(cwp)) {
  268.         XMapSubwindows (XtDisplay(widget), window);
  269.         } else {
  270.         MapChildren(cwp);
  271.         }
  272.     }
  273.     }
  274.  
  275.     /* If this is the application's popup shell, map it */
  276.     if (widget->core.parent == NULL && widget->core.mapped_when_managed) {
  277.     XtMapWidget (widget);
  278.     }
  279. } /* RealizeWidget */
  280.  
  281. void XtRealizeWidget (widget)
  282.     register Widget        widget;
  283. {
  284.     if (XtIsRealized (widget)) return;
  285.  
  286.     CallChangeManaged(widget);
  287.     RealizeWidget(widget);
  288. } /* XtRealizeWidget */
  289.  
  290.  
  291. static void UnrealizeWidget(widget)
  292.     register Widget        widget;
  293. {
  294.     register CompositeWidget    cw;
  295.     register Cardinal        i;
  296.     register WidgetList        children;
  297.  
  298.     if (!XtIsWidget(widget) || !XtIsRealized(widget)) return;
  299.  
  300.     /* If this is the application's popup shell, unmap it? */
  301.     /* no, the window is being destroyed */
  302.  
  303.     /* Recurse on children */
  304.     if (XtIsComposite (widget)) {
  305.     cw = (CompositeWidget) widget;
  306.     children = cw->composite.children;
  307.     /* Unrealize all children */
  308.     for (i = cw->composite.num_children; i != 0; --i) {
  309.         UnrealizeWidget (children[i-1]);
  310.     }
  311.     /* Unmap children that are managed and mapped_when_managed? */
  312.     /* No, it's ok to be managed and unrealized as long as your parent */
  313.     /* is unrealized. XtUnrealize widget makes sure the "top" widget */
  314.     /* is unmanaged, we can ignore all descendents */
  315.     }
  316.  
  317.     if (XtHasCallbacks(widget, XtNunrealizeCallback) == XtCallbackHasSome)
  318.     XtCallCallbacks(widget, XtNunrealizeCallback, NULL);
  319.  
  320.     /* Unregister window */
  321.     _XtUnregisterWindow(XtWindow(widget), widget);
  322.  
  323.     /* Remove Event Handlers */
  324.     /* remove grabs. Happens automatically when window is destroyed. */
  325.  
  326.     /* Destroy X Window, done at outer level with one request */
  327.     widget->core.window = None;
  328.  
  329.     /* Removing the event handler here saves having to keep track if
  330.      * the translation table is changed while the widget is unrealized.
  331.      */
  332.     _XtRemoveTranslations(widget);
  333. } /* UnrealizeWidget */
  334.  
  335.  
  336. void XtUnrealizeWidget (widget)
  337.     register Widget        widget;
  338. {
  339.     Window window = XtWindow(widget);
  340.  
  341.     if (! XtIsRealized (widget)) return;
  342.  
  343.     if (widget->core.parent != NULL) XtUnmanageChild(widget);
  344.  
  345.     UnrealizeWidget(widget);
  346.  
  347.     if (window != None) XDestroyWindow(XtDisplay(widget), window);
  348. } /* XtUnrealizeWidget */
  349.  
  350.  
  351. void XtCreateWindow(widget, window_class, visual, value_mask, attributes)
  352.     Widget         widget;
  353.     unsigned int     window_class;
  354.     Visual         *visual;
  355.     XtValueMask         value_mask;
  356.     XSetWindowAttributes *attributes;
  357. {
  358.     if (widget->core.window == None) {
  359.     if (widget->core.width == 0 || widget->core.height == 0) {
  360.         Cardinal count = 1;
  361.         XtAppErrorMsg(XtWidgetToApplicationContext(widget),
  362.                "invalidDimension", "xtCreateWindow", XtCXtToolkitError,
  363.                "Widget %s has zero width and/or height",
  364.                &widget->core.name, &count);
  365.     }
  366.     widget->core.window =
  367.         XCreateWindow (
  368.         XtDisplay (widget),
  369.         (widget->core.parent ?
  370.             widget->core.parent->core.window :
  371.             widget->core.screen->root),
  372.         (int)widget->core.x, (int)widget->core.y,
  373.         (unsigned)widget->core.width, (unsigned)widget->core.height,
  374.         (unsigned)widget->core.border_width, (int) widget->core.depth,
  375.         window_class, visual, value_mask, attributes);
  376.     }
  377. } /* XtCreateWindow */
  378.  
  379.  
  380. /* ---------------- XtNameToWidget ----------------- */
  381.  
  382. static Widget NameListToWidget();
  383.  
  384. typedef Widget (*NameMatchProc)();
  385.  
  386. static Widget MatchExactChildren(names, bindings, children, num,
  387.     in_depth, out_depth, found_depth)
  388.     XrmNameList     names;
  389.     XrmBindingList  bindings;
  390.     register WidgetList children;
  391.     register int num;
  392.     int in_depth, *out_depth, *found_depth;
  393. {
  394.     register Cardinal   i;
  395.     register XrmName    name = *names;
  396.     Widget w, result = NULL;
  397.     int d, min = 10000;
  398.  
  399.     for (i = 0; i < num; i++) {
  400.     if (name == children[i]->core.xrm_name) {
  401.         w = NameListToWidget(children[i], &names[1], &bindings[1],
  402.             in_depth+1, &d, found_depth);
  403.         if (w != NULL && d < min) {result = w; min = d;}
  404.     }
  405.     }
  406.     *out_depth = min;
  407.     return result;
  408. }
  409.  
  410. static Widget MatchWildChildren(names, bindings, children, num,
  411.     in_depth, out_depth, found_depth)
  412.     XrmNameList     names;
  413.     XrmBindingList  bindings;
  414.     register WidgetList children;
  415.     register int num;
  416.     int in_depth, *out_depth, *found_depth;
  417. {
  418.     register Cardinal   i;
  419.     Widget w, result = NULL;
  420.     int d, min = 10000;
  421.  
  422.     for (i = 0; i < num; i++) {
  423.     w = NameListToWidget(children[i], names, bindings,
  424.         in_depth+1, &d, found_depth);
  425.     if (w != NULL && d < min) {result = w; min = d;}
  426.     }
  427.     *out_depth = min;
  428.     return result;
  429. }
  430.  
  431. static Widget SearchChildren(root, names, bindings, matchproc,
  432.     in_depth, out_depth, found_depth)
  433.     Widget root;
  434.     XrmNameList     names;
  435.     XrmBindingList  bindings;
  436.     NameMatchProc matchproc;
  437.     int in_depth, *out_depth, *found_depth;
  438. {
  439.     Widget w1, w2;
  440.     int d1, d2;
  441.  
  442.     if (XtIsComposite(root)) {
  443.     w1 = (*matchproc)(names, bindings,
  444.         ((CompositeWidget) root)->composite.children,
  445.         ((CompositeWidget) root)->composite.num_children,
  446.         in_depth, &d1, found_depth);
  447.     } else d1 = 10000;
  448.     w2 = (*matchproc)(names, bindings, root->core.popup_list,
  449.         root->core.num_popups, in_depth, &d2, found_depth);
  450.     *out_depth = (d1 < d2 ? d1 : d2);
  451.     return (d1 < d2 ? w1 : w2);
  452. }
  453.  
  454. static Widget NameListToWidget(root, names, bindings,
  455.     in_depth, out_depth, found_depth)
  456.     register Widget root;
  457.     XrmNameList     names;
  458.     XrmBindingList  bindings;
  459.     int in_depth, *out_depth, *found_depth;
  460. {
  461.     Widget w1, w2;
  462.     int d1, d2;
  463.  
  464.     if (in_depth >= *found_depth) {
  465.     *out_depth = 10000;
  466.     return NULL;
  467.     }
  468.  
  469.     if (names[0] == NULLQUARK) {
  470.     *out_depth = *found_depth = in_depth;
  471.     return root;
  472.     }
  473.  
  474.     if (! XtIsWidget(root)) {
  475.     *out_depth = 10000;
  476.     return NULL;
  477.     }
  478.  
  479.     if (*bindings == XrmBindTightly) {
  480.     return SearchChildren(root, names, bindings, MatchExactChildren,
  481.         in_depth, out_depth, found_depth);
  482.  
  483.     } else {    /* XrmBindLoosely */
  484.     w1 = SearchChildren(root, names, bindings, MatchExactChildren,
  485.         in_depth, &d1, found_depth);
  486.     w2 = SearchChildren(root, names, bindings, MatchWildChildren,
  487.         in_depth, &d2, found_depth);
  488.     *out_depth = (d1 < d2 ? d1 : d2);
  489.     return (d1 < d2 ? w1 : w2);
  490.     }
  491. } /* NameListToWidget */
  492.  
  493. #if NeedFunctionPrototypes
  494. Widget XtNameToWidget(
  495.     Widget root,
  496.     _Xconst char* name
  497.     )
  498. #else
  499. Widget XtNameToWidget(root, name)
  500.     Widget root;
  501.     String name;
  502. #endif
  503. {
  504.     XrmName *names;
  505.     XrmBinding *bindings;
  506.     int len, depth, found = 10000;
  507.     Widget result;
  508.  
  509.     len = strlen(name);
  510.     if (len == 0) return NULL;
  511.  
  512.     names = (XrmName *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmName));
  513.     bindings = (XrmBinding *)
  514.     ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmBinding));
  515.     if (names == NULL || bindings == NULL) _XtAllocError(NULL);
  516.  
  517.     XrmStringToBindingQuarkList(name, bindings, names);
  518.     if (names[0] == NULLQUARK) {
  519.     DEALLOCATE_LOCAL((char *) bindings);
  520.     DEALLOCATE_LOCAL((char *) names);
  521.     return NULL;
  522.     }
  523.  
  524.     result = NameListToWidget(root, names, bindings, 0, &depth, &found);
  525.  
  526.     DEALLOCATE_LOCAL((char *) bindings);
  527.     DEALLOCATE_LOCAL((char *) names);
  528.     return result;
  529. } /* XtNameToWidget */
  530.  
  531. /* Define user versions of intrinsics macros */
  532.  
  533. #undef XtDisplayOfObject
  534. Display *XtDisplayOfObject(object)
  535.      Widget object;
  536. {
  537.     return XtDisplay(XtIsWidget(object) ? object : _XtWindowedAncestor(object));
  538. }
  539.  
  540. #undef XtDisplay
  541. Display *XtDisplay(widget)
  542.     Widget widget;
  543. {
  544.     return DisplayOfScreen(widget->core.screen);
  545. }
  546.  
  547. #undef XtScreenOfObject
  548. Screen *XtScreenOfObject(object)
  549.      Widget object;
  550. {
  551.     return XtScreen(XtIsWidget(object) ? object : _XtWindowedAncestor(object));
  552. }
  553.  
  554. #undef XtScreen
  555. Screen *XtScreen(widget)
  556.     Widget widget;
  557. {
  558.     return widget->core.screen;
  559. }
  560.  
  561. #undef XtWindowOfObject
  562. Window XtWindowOfObject(object)
  563.      Widget object;
  564. {
  565.     return XtWindow(XtIsWidget(object) ? object : _XtWindowedAncestor(object));
  566. }
  567.  
  568.  
  569. #undef XtWindow
  570. Window XtWindow(widget)
  571.     Widget widget;
  572. {
  573.     return widget->core.window;
  574. }
  575.  
  576. #undef XtSuperclass
  577. WidgetClass XtSuperclass(widget)
  578.     Widget widget;
  579. {
  580.     return XtClass(widget)->core_class.superclass;
  581. }
  582.  
  583. #undef XtClass
  584. WidgetClass XtClass(widget)
  585.     Widget widget;
  586. {
  587.     return widget->core.widget_class;
  588. }
  589.  
  590. #undef XtIsManaged
  591. Boolean XtIsManaged(object)
  592.     Widget object;
  593. {
  594.     if (XtIsRectObj(object))
  595.     return object->core.managed;
  596.     else
  597.     return False;
  598. }
  599.  
  600. #undef XtIsRealized
  601. Boolean XtIsRealized (object)
  602.     Widget   object;
  603. {
  604.     return XtWindowOfObject(object) != None;
  605. } /* XtIsRealized */
  606.  
  607. #undef XtIsSensitive
  608. Boolean XtIsSensitive(object)
  609.     Widget    object;
  610. {
  611.     if (XtIsRectObj(object))
  612.     return object->core.sensitive && object->core.ancestor_sensitive;
  613.     else
  614.     return False;
  615. }
  616.  
  617. /*
  618.  * Internal routine; must be called only after XtIsWidget returns false
  619.  */
  620. Widget _XtWindowedAncestor(object)
  621.     register Widget object;
  622. {
  623.     Widget obj = object;
  624.     for (object = XtParent(object); object && !XtIsWidget(object);)
  625.     object = XtParent(object);
  626.  
  627.     if (object == NULL) {
  628.     String params = XtName(obj);
  629.     Cardinal num_params = 1;
  630.     XtErrorMsg("noWidgetAncestor", "windowedAncestor", XtCXtToolkitError,
  631.            "Object \"%s\" does not have windowed ancestor",
  632.            ¶ms, &num_params);
  633.     }
  634.  
  635.     return object;
  636. }
  637.  
  638. #undef XtParent
  639. Widget XtParent(widget)
  640.     Widget widget;
  641. {
  642.     return widget->core.parent;
  643. }
  644.  
  645. #undef XtName
  646. String XtName(object)
  647.      Widget object;
  648. {
  649.     return XrmQuarkToString(object->core.xrm_name);
  650. }
  651.  
  652.  
  653. Boolean XtIsObject(object)
  654.     Widget object;
  655. {
  656.     WidgetClass wc;
  657.     String class_name;
  658.  
  659.     /* perform basic sanity checks */
  660.     if (object->core.self != object || object->core.xrm_name == NULLQUARK)
  661.     return False;
  662.  
  663.     wc = object->core.widget_class;
  664.     if (wc->core_class.class_name == NULL ||
  665.     wc->core_class.xrm_class == NULLQUARK ||
  666.     (class_name = XrmClassToString(wc->core_class.xrm_class)) == NULL ||
  667.     strcmp(wc->core_class.class_name, class_name) != 0)
  668.         return False;
  669.  
  670.     if (XtIsWidget(object)) {
  671.     if (object->core.name == NULL ||
  672.         (class_name = XrmNameToString(object->core.xrm_name)) == NULL ||
  673.         strcmp(object->core.name, class_name) != 0)
  674.         return False;
  675.     }
  676.     return True;
  677. }
  678.  
  679.  
  680. static Boolean TestFile(path)
  681.     String path;
  682. {
  683. #ifdef VMS
  684.     return TRUE;    /* Who knows what to do here? */
  685. #else
  686.     struct stat status;
  687.  
  688.     return (access(path, R_OK) == 0 &&        /* exists and is readable */
  689.         stat(path, &status) == 0 &&        /* get the status */
  690. #ifndef X_NOT_POSIX
  691.         S_ISDIR(status.st_mode) == 0);    /* not a directory */
  692. #else
  693.         (status.st_mode & S_IFDIR) == 0);    /* not a directory */
  694. #endif /* X_NOT_POSIX else */
  695. #endif /* VMS */
  696. }
  697.  
  698. /* return of TRUE = resolved string fit, FALSE = didn't fit.  Not
  699.    null-terminated and not collapsed if it didn't fit */
  700.  
  701. static Boolean Resolve(source, len, sub, num, buf, collapse)
  702.     register char *source;    /* The source string */
  703.     register int len;        /* The length in bytes of *source */
  704.     Substitution sub;    /* Array of string values to substitute */
  705.     Cardinal num;    /* Number of substitution entries */
  706.     char *buf;        /* Where to put the resolved string; */
  707.     char collapse;    /* Character to collapse */
  708. {
  709.     register int bytesLeft = PATH_MAX;
  710.     register char* bp = buf;
  711. #ifndef DONT_COLLAPSE
  712.     Boolean atBeginning = TRUE;
  713.     Boolean prevIsCollapse = FALSE;
  714.  
  715. #define PUT(ch) \
  716.     { \
  717.     if (--bytesLeft == 0) return FALSE; \
  718.         if (prevIsCollapse) \
  719.         if ((*bp = ch) != collapse) { \
  720.         prevIsCollapse = FALSE; \
  721.         bp++; \
  722.         } \
  723.         else bytesLeft++; \
  724.         else if ((*bp++ = ch) == collapse && !atBeginning) \
  725.         prevIsCollapse = TRUE; \
  726.     }
  727. #else /* DONT_COLLAPSE */
  728.  
  729. #define PUT(ch) \
  730.     { \
  731.     if (--bytesLeft == 0) return FALSE; \
  732.     *bp++ = ch; \
  733.     }
  734. #endif /* DONT_COLLAPSE */
  735. #define escape '%'
  736.  
  737.     while (len--) {
  738. #ifndef DONT_COLLAPSE
  739.     if (*source == collapse) {
  740.         PUT(*source);
  741.         source++;
  742.         continue;
  743.     }
  744.     else
  745. #endif /* DONT_COLLAPSE */
  746.         if (*source != escape) {
  747.         PUT(*source);
  748.     }
  749.     else {
  750.         source++;
  751.         if (len-- == 0) {
  752.         PUT(escape);
  753.         break;
  754.         }
  755.  
  756.         if (*source == ':' || *source == escape)
  757.         PUT(*source)
  758.         else {
  759.         /* Match the character against the match array */
  760.         register int j;
  761.  
  762.         for (j = 0; j < num && sub[j].match != *source; j++) {}
  763.  
  764.         /* Substitute the substitution string */
  765.  
  766.         if (j >= num) PUT(*source)
  767.         else if (sub[j].substitution != NULL) {
  768.             char *sp = sub[j].substitution;
  769.             while (*sp) {
  770.             PUT(*sp);
  771.             sp++;
  772.             }
  773.         }
  774.         }
  775.     }
  776.     source++;
  777. #ifndef DONT_COLLAPSE
  778.     atBeginning = FALSE;
  779. #endif /* DONT_COLLAPSE */
  780.     }
  781.     PUT('\0');
  782.  
  783.     return TRUE;
  784. #undef PUT
  785. #undef escape
  786. }
  787.  
  788.  
  789. #if NeedFunctionPrototypes
  790. String XtFindFile(
  791.     _Xconst char* path,
  792.     Substitution substitutions,
  793.     Cardinal num_substitutions,
  794.     XtFilePredicate predicate
  795.     )
  796. #else
  797. String XtFindFile(path, substitutions, num_substitutions, predicate)
  798.     String path;
  799.     Substitution substitutions;
  800.     Cardinal num_substitutions;
  801.     XtFilePredicate predicate;
  802. #endif
  803. {
  804.     char *buf, *buf1, *buf2, *colon, *start;
  805.     int len;
  806.     Boolean firstTime = TRUE;
  807.  
  808.     buf = buf1 = XtMalloc((unsigned)PATH_MAX);
  809.     buf2 = XtMalloc((unsigned)PATH_MAX);
  810.  
  811.     if (predicate == NULL) predicate = TestFile;
  812.  
  813.     while (1) {
  814.     start = (String)path;
  815.     while (1) {
  816.         colon = index(start, ':');
  817.         if (colon == NULL) break;
  818.         if (colon == path) {start++; path++; continue; }
  819.         if (*(colon-1) != '%') break;
  820.         start = colon+1;
  821.     }
  822.     if (colon != NULL)
  823.         len = colon - path;
  824.     else
  825.         len = strlen(path);
  826.     if (Resolve(path, len, substitutions, num_substitutions,
  827.             buf, '/')) {
  828.         if (firstTime || strcmp(buf1,buf2) != 0) {
  829. #ifdef XNL_DEBUG
  830.         printf("Testing file %s\n", buf);
  831. #endif /* XNL_DEBUG */
  832.  
  833.         /* Check out the file */
  834.         if ((*predicate) (buf)) {
  835.             /* We've found it, return it */
  836. #ifdef XNL_DEBUG
  837.             printf("File found.\n");
  838. #endif /* XNL_DEBUG */
  839.             if (buf == buf1) XtFree(buf2);
  840.             else XtFree(buf1);
  841.             return buf;
  842.         }
  843.         if (buf == buf1)
  844.             buf = buf2;
  845.         else
  846.             buf = buf1;
  847.         firstTime = FALSE;
  848.         }
  849.     }
  850.  
  851.     /* Nope...any more paths? */
  852.  
  853.     if (colon == NULL) break;
  854.     path = colon+1;
  855.     }
  856.  
  857.     /* No file found */
  858.  
  859.     XtFree(buf1);
  860.     XtFree(buf2);
  861.     return NULL;
  862. }
  863.  
  864.  
  865. /* The implementation of this routine is operating system dependent */
  866.  
  867. static char *ExtractLocaleName(lang)
  868.     String    lang;
  869. {
  870.  
  871. #ifdef hpux     /* hpux-specific parsing of the locale string */
  872. #define MAXLOCALE       64      /* buffer size of locale name */
  873.  
  874.     char           *start;
  875.     char           *end;
  876.     int             len;
  877.     static char     buf[MAXLOCALE];
  878.  
  879.     /*  If lang has a substring ":<category>;", extract <category>
  880.      *  from the first such occurrence as the locale name.
  881.      */
  882.  
  883.     start = lang;
  884.     if (start = strchr (lang, ':')) {
  885.         start++;
  886.         if (end = strchr (start, ';')) {
  887.             len = end - start;
  888.             strncpy(buf, start, len);
  889.             *(buf + len) = '\0';
  890.             lang = buf;
  891.       }
  892.     }
  893. #endif    /* hpux */
  894.  
  895.     /*  If result is "C", return NULL instead. */
  896.  
  897.     if (strcmp(lang, "C"))
  898.         return lang;
  899.     else
  900.       return NULL;
  901. }
  902.  
  903. static void FillInLangSubs(subs, pd)
  904.     Substitution subs;
  905.     XtPerDisplay pd;
  906. {
  907.     int len;
  908.     char *string, *p1, *p2, *p3;
  909.     char **rest;
  910.     char *ch;
  911.  
  912.     if (pd->language == NULL || pd->language[0] == '\0') {
  913.     subs[0].substitution = subs[1].substitution =
  914.         subs[2].substitution = subs[3].substitution = NULL;
  915.     return;
  916.     }
  917.  
  918.     string = ExtractLocaleName(pd->language);
  919.  
  920.     if (string == NULL || string[0] == '\0') {
  921.     subs[0].substitution = subs[1].substitution =
  922.         subs[2].substitution = subs[3].substitution = NULL;
  923.     return;
  924.     }
  925.  
  926.     len = strlen(string) + 1;
  927.     subs[0].substitution = string;
  928.     p1 = subs[1].substitution = XtMalloc((Cardinal) 3*len);
  929.     p2 = subs[2].substitution = subs[1].substitution + len;
  930.     p3 = subs[3].substitution = subs[2].substitution + len;
  931.  
  932.     /* Everything up to the first "_" goes into p1.  From "_" to "." in
  933.        p2.  The rest in p3.  If no delimiters, all goes into p1.  We
  934.        assume p1, p2, and p3 are large enough. */
  935.  
  936.     *p1 = *p2 = *p3 = '\0';
  937.  
  938.     ch = index(string, '_');
  939.     if (ch != NULL) {
  940.     len = ch - string;
  941.     (void) strncpy(p1, string, len);
  942.     p1[len] = '\0';
  943.     string = ch + 1;
  944.     rest = &p2;
  945.     } else rest = &p1;
  946.  
  947.     /* Rest points to where we put the first part */
  948.  
  949.     ch = index(string, '.');
  950.     if (ch != NULL) {
  951.     len = ch - string;
  952.     strncpy(*rest, string, len);
  953.     (*rest)[len] = '\0';
  954.     (void) strcpy(p3, ch+1);
  955.     } else (void) strcpy(*rest, string);
  956. }
  957.  
  958. static SubstitutionRec defaultSubs[] = {
  959.     {'N', NULL},
  960.     {'T', NULL},
  961.     {'S', NULL},
  962.     {'C', NULL},
  963.     {'L', NULL},
  964.     {'l', NULL}, 
  965.     {'t', NULL},
  966.     {'c', NULL}
  967. };
  968.  
  969.  
  970. #if NeedFunctionPrototypes
  971. String XtResolvePathname(
  972.     Display *dpy,
  973.     _Xconst char* type,
  974.     _Xconst char* filename,
  975.     _Xconst char* suffix,
  976.     _Xconst char* path,
  977.     Substitution substitutions,
  978.     Cardinal num_substitutions,
  979.     XtFilePredicate predicate
  980.     )
  981. #else
  982. String XtResolvePathname(dpy, type, filename, suffix, path, substitutions,
  983.              num_substitutions, predicate)
  984.     Display *dpy;
  985.     String type, filename, suffix, path;
  986.     Substitution substitutions;
  987.     Cardinal num_substitutions;
  988.     XtFilePredicate predicate;
  989. #endif
  990. {
  991.     XtPerDisplay pd = _XtGetPerDisplay(dpy);
  992.     static char *defaultPath = NULL;
  993.     char *massagedPath;
  994.     int bytesAllocd, bytesLeft;
  995.     char *ch, *result;
  996.     Substitution merged_substitutions;
  997.     XrmRepresentation db_type;
  998.     XrmValue value;
  999.     XrmName name_list[3];
  1000.     XrmClass class_list[3];
  1001.     Boolean pathMallocd = False;
  1002.  
  1003.     if (path == NULL) {
  1004. #ifndef VMS
  1005.     if (defaultPath == NULL) {
  1006.         defaultPath = getenv("XFILESEARCHPATH");
  1007.         if (defaultPath == NULL) defaultPath = XFILESEARCHPATHDEFAULT;
  1008.     }
  1009.     path = defaultPath;
  1010. #else
  1011.     path = "";    /* NULL would kill us later */
  1012. #endif /* VMS */
  1013.     }    
  1014.  
  1015.     if (filename == NULL) {
  1016.     filename = XrmClassToString(pd->class);
  1017.     }
  1018.  
  1019.     bytesAllocd = bytesLeft = 1000;
  1020.     massagedPath = ALLOCATE_LOCAL(bytesAllocd);
  1021.     if (massagedPath == NULL) _XtAllocError(NULL);
  1022.  
  1023.     if (path[0] == ':') {
  1024.     strcpy(massagedPath, "%N%S");
  1025.     ch = &massagedPath[4];
  1026.     bytesLeft -= 4;
  1027.     } else ch = massagedPath;
  1028.  
  1029.     /* Insert %N%S between adjacent colons */
  1030.  
  1031.     while (*path != '\0') {
  1032.     if (bytesLeft < 8) {
  1033.         int bytesUsed = bytesAllocd - bytesLeft;
  1034.         char *new;
  1035.         bytesAllocd +=1000;
  1036.         new = XtMalloc((Cardinal) bytesAllocd);
  1037.         strncpy( new, massagedPath, bytesUsed );
  1038.         ch = new + bytesUsed;
  1039.         if (pathMallocd)
  1040.         XtFree(massagedPath);
  1041.         else
  1042.         DEALLOCATE_LOCAL(massagedPath);
  1043.         pathMallocd = True;
  1044.         massagedPath = new;
  1045.         bytesLeft = bytesAllocd - bytesUsed;
  1046.     }
  1047.     if (*path == '%' && *(path+1) == ':') {
  1048.         *ch++ = '%';
  1049.         *ch++ = ':';
  1050.         path += 2;
  1051.         bytesLeft -= 2;
  1052.         continue;
  1053.     }
  1054.     if (*path == ':' && *(path+1) == ':') {
  1055.         strcpy(ch, ":%N%S:");
  1056.         ch += 6;
  1057.         bytesLeft -= 6;
  1058.         while (*path == ':') path++;
  1059.         continue;
  1060.     }
  1061.     *ch++ = *path++;
  1062.     bytesLeft--;
  1063.     }
  1064.     *ch = '\0';
  1065. #ifdef XNL_DEBUG
  1066.     printf("Massaged path: %s\n", massagedPath);
  1067. #endif /* XNL_DEBUG */
  1068.  
  1069.     if (num_substitutions == 0)
  1070.     merged_substitutions = defaultSubs;
  1071.     else {
  1072.     int i = XtNumber(defaultSubs);
  1073.     Substitution sub, def;
  1074.     merged_substitutions = sub = (Substitution)
  1075.         ALLOCATE_LOCAL((unsigned)(num_substitutions+i)*sizeof(SubstitutionRec));
  1076.     if (sub == NULL) _XtAllocError(NULL);
  1077.     for (def = defaultSubs; i--; sub++, def++) sub->match = def->match;
  1078.     for (i = num_substitutions; i--; ) *sub++ = *substitutions++;
  1079.     }
  1080.     merged_substitutions[0].substitution = (String)filename;
  1081.     merged_substitutions[1].substitution = (String)type;
  1082.     merged_substitutions[2].substitution = (String)suffix;
  1083.     name_list[0] = pd->name;
  1084.     name_list[1] = XrmPermStringToQuark("customization");
  1085.     name_list[2] = NULLQUARK;
  1086.     class_list[0] = pd->class;
  1087.     class_list[1] = XrmPermStringToQuark("Customization");
  1088.     class_list[2] = NULLQUARK;
  1089.     if (XrmQGetResource(XrmGetDatabase(dpy), name_list, class_list,
  1090.             &db_type, &value) &&
  1091.     db_type == _XtQString)
  1092.     merged_substitutions[3].substitution = (char *)value.addr;
  1093.     else
  1094.     merged_substitutions[3].substitution = NULL;
  1095.     FillInLangSubs(&merged_substitutions[4], pd);
  1096.  
  1097.     result = XtFindFile(massagedPath, merged_substitutions,
  1098.             num_substitutions + XtNumber(defaultSubs),
  1099.             predicate);
  1100.  
  1101.     if (merged_substitutions[5].substitution != NULL)
  1102.     XtFree( (XtPointer)merged_substitutions[5].substitution );
  1103.  
  1104.     if (merged_substitutions != defaultSubs) 
  1105.     DEALLOCATE_LOCAL(merged_substitutions);
  1106.  
  1107.     if (pathMallocd)
  1108.     XtFree(massagedPath);
  1109.     else
  1110.     DEALLOCATE_LOCAL(massagedPath);
  1111.  
  1112.     return result;
  1113. }
  1114.  
  1115.  
  1116. Boolean XtCallAcceptFocus(widget, time)
  1117.     Widget widget;
  1118.     Time *time;
  1119. {
  1120.     XtAcceptFocusProc ac = XtClass(widget)->core_class.accept_focus;
  1121.  
  1122.     if (ac != NULL) return (*ac) (widget, time);
  1123.     else return FALSE;
  1124. }
  1125.