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