/* * Motif * * Copyright (c) 1987-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA * */ /************************************************************ * INCLUDE FILES *************************************************************/ #include #include #include #include "XmI.h" /************************************************************ * TYPEDEFS AND DEFINES *************************************************************/ #define SUPERCLASS (&xmHierarchyClassRec) #define DEF_INDENT_SPACE 30 #define MOVE_TIME 200 typedef struct { int x; int y; } LadderPoint; /************************************************************ * MACROS *************************************************************/ /************************************************************ * GLOBAL DECLARATIONS *************************************************************/ /************************************************************ * STATIC FUNCTION DECLARATIONS *************************************************************/ static void ClassInitialize(); static void Resize(Widget), ClassPartInitialize(WidgetClass); static void Redisplay(Widget, XEvent *, Region); static void Initialize(Widget, Widget, ArgList, Cardinal *); static void Destroy(Widget widget); static void ConstraintInitialize(Widget, Widget, ArgList, Cardinal *); static void ConstraintDestroy(Widget); static void ToggleNodeState(Widget, XtPointer, XtPointer); static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *, XtWidgetGeometry *); static Boolean ConstraintSetValues(Widget, Widget, Widget, ArgList, Cardinal*); static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal*); static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *, XtWidgetGeometry *); /************************ * Actions and callbacks. ************************/ /********************* * Internal Routines. *********************/ static Bool CheckExpose(Display *, XEvent *, char *); static OutlineConstraints GetNodeInfo(Widget); static int CalcMaxWidth(Widget); static void ChangeManaged(Widget); static void RequestNewSize(Widget), CalcLocations(Widget, Boolean); static void GetNodeDimensions(Widget, OutlineConstraints, Cardinal, Cardinal *); static void GetNodeHeightAndWidth(Widget, OutlineConstraints, Cardinal, Boolean, Cardinal *); static void GetDesiredSize(Widget, Dimension*, Dimension*, Dimension *, Dimension *, Boolean, Boolean); static void LayoutChildren(Widget, Widget); static Boolean LocInRect(XRectangle *, Widget, Position, Position); static Boolean WidgetInRect(XRectangle *, Widget); static Boolean CheckWidget(XRectangle *, OutlineConstraints); static void ProcessChildQueue(XmOutlineWidget, XRectangle *); static void MoveNode(XmOutlineWidget, OutlineConstraints, Position, Position, Position, Position, Boolean); static void ProcessNode(OutlineConstraints); static Boolean MoveNodesTimer(XtPointer); static void UnmapNode(XmOutlineWidget ow, OutlineConstraints node); static void UnmapAllExtraNodes(Widget w, HierarchyConstraints node); static void NegotiateNodeWidth(Widget w, OutlineConstraints node); static void RedrawOutlineLines(Widget, XRectangle *); static void DrawOutlineLine(Widget, XRectangle *, OutlineConstraints); static void _CalcNodeMidPoint( OutlineConstraints node, Widget w, LadderPoint *ret_point ); static void _OutlineDrawLine(Widget w, XRectangle *rect, OutlineConstraints parent, OutlineConstraints child, LadderPoint from_ladder_point, LadderPoint *to_ladder_point ); static void CreateGC(XmOutlineWidget ow); /************************************************************ * STATIC DECLARATIONS *************************************************************/ static XtResource resources[] = { { XmNindentSpace, XmCIndentSpace, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmOutlineRec, outline.indent_space), XmRImmediate, (XtPointer)DEF_INDENT_SPACE }, { XmNconstrainWidth, XmCConstrainWidth, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmOutlineRec, outline.constrain_width), XmRImmediate, (XtPointer)False }, { XmNconnectNodes, XmCBoolean, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmOutlineRec, outline.connect_nodes), XmRImmediate, (XtPointer)False } }; static XmSyntheticResource get_resources[] = { { XmNindentSpace, sizeof(Dimension), XtOffsetOf(XmOutlineRec, outline.indent_space), XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels } }; XmOutlineClassRec xmOutlineClassRec = { { /* core fields */ /* superclass */ ((WidgetClass) SUPERCLASS), /* class_name */ "XmOutline", /* widget_size */ sizeof(XmOutlineRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ (XtResource*)resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMultiple, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ (XtGeometryHandler) QueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ GeometryManager, /* change_managed */ ChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL, }, { /* constraint_class fields */ /* resource list */ NULL, /* num resources */ 0, /* constraint size */ sizeof(XmOutlineConstraintRec), /* init proc */ ConstraintInitialize, /* destroy proc */ ConstraintDestroy, /* set values proc */ ConstraintSetValues, /* extension */ NULL, }, { /* manager_class fields */ /* default translations */ XtInheritTranslations, /* syn_resources */ get_resources, /* num_syn_resources */ XtNumber(get_resources), /* syn_cont_resources */ NULL, /* num_syn_cont_resources */ 0, /* parent_process */ NULL, /* extension */ NULL, }, { /* Hierarchy fields */ XtInheritChangeNodeState, /* The function for changing the node state. */ XtInheritMapNode, /* Maps a given node. */ XtInheritUnmapNode, /* Unmaps a given node. */ UnmapAllExtraNodes, /* Unmaps all extra nodes. */ XtInheritBuildNodeTable, /* Builds up the node table. */ XtInheritResetOpenCloseButton, /* Resets the the o/c button. */ ToggleNodeState, /* Called to toggle the state of node. */ NULL, /* extension */ }, { /* Outline fields */ CalcMaxWidth, /* calculates the max width of the outline. */ CalcLocations, /* calculates were children will be placed. */ NULL /* extension */ } }; WidgetClass xmOutlineWidgetClass = (WidgetClass) &xmOutlineClassRec; /************************************************************ * STATIC CODE *************************************************************/ /* Function Name: ClassInitialize * Description: Initializes class-specific data (offsets) * Arguments: none * Returns: nothing */ static void ClassInitialize() { /* do nothing */ } /* Function Name: ClassPartInitialize * Description: handles inheritance of class functions. * Arguments: class - the widget class of this widget. * Returns: none. */ static void ClassPartInitialize(WidgetClass class) { XmOutlineWidgetClass wc = (XmOutlineWidgetClass) class; XmOutlineWidgetClass superC; _XmProcessLock(); superC = (XmOutlineWidgetClass) wc->core_class.superclass; /* * We don't need to check for NULL super since we'll get to The functions * defined by the Outline class eventually. */ if (wc->outline_class.calc_max_width == XtInheritCalcMaxWidth) wc->outline_class.calc_max_width= superC->outline_class.calc_max_width; if (wc->outline_class.calc_locations == XtInheritCalcLocations) wc->outline_class.calc_locations= superC->outline_class.calc_locations; _XmProcessUnlock(); } /* Function Name: Initialize * Description: Called to initialize information specific * to this widget. * Arguments: req - what was originally requested. * set - what will be created (our superclassed have * already mucked with this) * args, num_args - The arguments passed to * the creation call. * Returns: none. */ /*ARGSUSED*/ static void Initialize(Widget req, Widget set, ArgList args, Cardinal * num_args) { XmOutlineWidget ow = (XmOutlineWidget) set; XmHierarchy_top_node(ow) = ((HierarchyConstraints) XtRealloc((XtPointer) XmHierarchy_top_node(ow), sizeof(OutlineConstraintRec))); XmOutline_top_node_of_display(ow) = NULL; XmOutline_max_width(ow) = 0; XmOutline_max_widget_width(ow) = 0; XmOutline_ul_point(ow).x = ow->core.width; XmOutline_ul_point(ow).y = ow->core.height; XmOutline_lr_point(ow).x = 0; XmOutline_lr_point(ow).y = 0; XmOutline_child_op_list(ow) = _XmListInit(); CreateGC(ow); } static void CreateGC(XmOutlineWidget ow) { XGCValues values; values.foreground = ow->manager.foreground; XmOutline_draw_gc(ow) = XtGetGC((Widget)ow, GCForeground, &values); } /* Function Name: Destroy * Description: Destroys all data allocated by the widget * Arguments: w - the widget. * Returns: none. */ static void Destroy(Widget widget) { XmOutlineWidget ow = (XmOutlineWidget) widget; _XmListFree(XmOutline_child_op_list(ow)); XtReleaseGC(widget,XmOutline_draw_gc(ow)); } /* Function Name: Resize * Description: Called when this widget has been resized. * Arguments: w - Extended List Widget to resize. * Returns: none. */ static void Resize(Widget w) { XmOutlineWidget ow = (XmOutlineWidget) w; if (XmHierarchy_refigure_mode(ow)) { if(XmOutline_constrain_width(ow)) CalcLocations(w, False); LayoutChildren(w, NULL); if (XtIsRealized((Widget)ow)) { XClearArea(XtDisplay(ow), XtWindow(ow), 0, 0, ow->core.width, ow->core.height, True); } } } /* Function Name: Redisplay * Description: This function deals with any pending moves/maps/unmaps * in the queue before redisplay * Arguments: w - the Outline widget. * event - event that caused the exposure. * region - the region containing all the exposures. * Returns: none */ typedef struct _RedispInfo { Window window; Boolean found; } RedispInfo; /* ARGSUSED */ static void Redisplay(Widget w, XEvent * event, Region region) { XmOutlineWidget ow = (XmOutlineWidget) w; XEvent junk; RedispInfo info; int lrx, lry; /* local variables for lower left corner. */ XmDropSiteStartUpdate(w); /* * Make sure that there are not more expose events pending in the queue */ info.window = XtWindow(w); info.found = False; XCheckIfEvent(XtDisplay(w), &junk, CheckExpose, (char *) &info); /* * Compute the maximum bounding rectangle for all expose events * that have yet to be processed. */ if (event->xexpose.x < XmOutline_ul_point(ow).x) XmOutline_ul_point(ow).x = event->xexpose.x; if (event->xexpose.y < XmOutline_ul_point(ow).y) XmOutline_ul_point(ow).y = event->xexpose.y; lrx = event->xexpose.x + event->xexpose.width; lry = event->xexpose.y + event->xexpose.height; if (lrx > XmOutline_lr_point(ow).x) XmOutline_lr_point(ow).x = lrx; if (lry > XmOutline_lr_point(ow).y) XmOutline_lr_point(ow).y = lry; if (!info.found) { /* No more expose events waiting - process these. */ XRectangle rect; rect.x = XmOutline_ul_point(ow).x; rect.y = XmOutline_ul_point(ow).y; rect.width = XmOutline_lr_point(ow).x - XmOutline_ul_point(ow).x; rect.height = XmOutline_lr_point(ow).y - XmOutline_ul_point(ow).y; ProcessChildQueue((XmOutlineWidget) w, &rect); if (XmOutline_connect_nodes(w)) RedrawOutlineLines(w,&rect); /* * Reset upper right and lower left points. */ XmOutline_ul_point(ow).x = w->core.width; XmOutline_ul_point(ow).y = w->core.height; XmOutline_lr_point(ow).x = XmOutline_lr_point(ow).y = 0; } XmDropSiteEndUpdate(w); } /* Function Name: CheckExpose * Description: Checks to see if there is an expose event on the queue. * Arguments: disp - the X Display. * event - the event to check for. * info_ptr - a pointer to the redispInfo. * Returns: Always False. */ /* ARGSUSED */ static Bool CheckExpose(Display *disp, XEvent *event, char *info_ptr) { RedispInfo *info = (RedispInfo *) info_ptr; if (info->found || event->xany.type != Expose) return(False); if (event->xexpose.window == info->window) info->found = True; return(False); } /* Function Name: QueryGeometry * Description: Called when my parent wants to know what size * I would like to be. * Arguments: w - the drt widget. * indended - constriants imposed by the parent. * preferred - what I would like. * Returns: See Xt Manual. */ static XtGeometryResult QueryGeometry(Widget w,XtWidgetGeometry *intended, XtWidgetGeometry *preferred) { Dimension *width_intended = NULL; Dimension *height_intended = NULL; if(!(intended->request_mode & XtCWQueryOnly)) { if(intended->request_mode & CWWidth) width_intended = &(intended->width); if(intended->request_mode & CWHeight) height_intended = &(intended->height); } GetDesiredSize(w, width_intended, height_intended, &(preferred->width), &(preferred->height), True, False); preferred->request_mode = CWWidth | CWHeight; return(_XmHWQuery(w, intended, preferred)); } /* Function Name: SetValues * Description: Called a resources is changed. * Arguments: current - the current (old) widget values. * request - before superclassed have changed things. * set - what will acutally be the new values. * args, num_args - the arguments in the list. * Returns: none */ /* ARGSUSED */ static Boolean SetValues(Widget current, Widget request, Widget set, ArgList args, Cardinal * num_args) { XmOutlineWidget c_outline = (XmOutlineWidget) current; XmOutlineWidget outline = (XmOutlineWidget) set; Boolean layout = False; Boolean retval = False; if ((XmHierarchy_v_margin(c_outline) != XmHierarchy_v_margin(outline)) || (XmHierarchy_h_margin(c_outline) != XmHierarchy_h_margin(outline))) { layout = True; } if (XmOutline_indent_space(c_outline) != XmOutline_indent_space(outline)) { layout = True; } if (XmOutline_constrain_width(c_outline) != XmOutline_constrain_width(outline)) { layout = True; } if (XmHierarchy_refigure_mode(c_outline) != XmHierarchy_refigure_mode(outline)) layout = XmHierarchy_refigure_mode(outline); if (XmOutline_connect_nodes(c_outline) != XmOutline_connect_nodes(outline)) retval = True; if (layout) { XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(set); XmOutlineCalcLocationProc calc_locations; _XmProcessLock() calc_locations = oc->outline_class.calc_locations; _XmProcessUnlock() (*calc_locations)(set, True); LayoutChildren(set, NULL); retval = True; } if (c_outline->manager.foreground != outline->manager.foreground) { XtReleaseGC(current,XmOutline_draw_gc(c_outline)); CreateGC(outline); retval = True; } return(retval); } /************************************************************ * * Composite Widget class procedures. * ************************************************************/ /* Function Name: ChangeManaged * Description: When a management change has occured... * Arguments: w - the icon box widget. * Returns: none. */ static void ChangeManaged(Widget w) { XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(w); XmOutlineWidget ow = (XmOutlineWidget) w; if (XmHierarchy_refigure_mode(ow)) { XmOutlineCalcLocationProc calc_locations; _XmProcessLock() calc_locations = oc->outline_class.calc_locations; _XmProcessUnlock() (*calc_locations)(w, True); LayoutChildren(w, NULL); if (XtIsRealized((Widget)ow)) { XClearArea(XtDisplay(ow), XtWindow(ow), 0, 0, ow->core.width, ow->core.height, True); } } XmeNavigChangeManaged(w); /* for Motif navigation */ } /* Function Name: GeometryManager * Description: handles requests from children for a size change. * Arguments: child - the child to change. * request - the geometry that the child wants. * return - what we will allow if this is an almost. * Returns: status. */ /*ARGSUSED*/ static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry * request, XtWidgetGeometry * result) { XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(XtParent(w)); XmOutlineWidget ow = (XmOutlineWidget)(XtParent(w)); result->request_mode = 0; /* if nothing we're interested in, say No */ if (!(request->request_mode & (CWWidth | CWHeight | CWBorderWidth))) return(XtGeometryNo); if((XmOutline_constrain_width(ow)) && (request->request_mode & CWWidth) && (request->width > w->core.width)) { result->request_mode = CWWidth; result->width = w->core.width; return XtGeometryAlmost; } /* else we have something that we're interested in. Do we also have ** something that we're not granting? If so, say that we'll grant the ** stuff that we're interested in but not the other items */ if (request->request_mode & (CWX | CWY | CWStackMode | CWSibling)) { result->request_mode = request->request_mode & (CWWidth | CWHeight | CWBorderWidth); result->width = request->width; result->height = request->height; result->border_width = request->border_width; return(XtGeometryAlmost); } if (!(request->request_mode & CWWidth)) { request->width = w->core.width; result->request_mode |= CWWidth; } if (!(request->request_mode & CWBorderWidth)) { request->border_width = w->core.border_width; result->request_mode |= CWBorderWidth; } if (!(request->request_mode & CWHeight)) { request->height = w->core.height; result->request_mode |= CWHeight; } *result = *request; if (request->request_mode & XtCWQueryOnly) return(XtGeometryYes); /* * Correct for stupid children */ if(result->width <= 0) result->width = 1; if(result->height <= 0) result->height = 1; /* * A real allowed request, make the change. */ _XmResizeWidget(w, result->width, result->height, result->border_width); if (XmHierarchy_refigure_mode(ow)) { XmOutlineCalcLocationProc calc_locations; _XmProcessLock() calc_locations = oc->outline_class.calc_locations; _XmProcessUnlock() (*calc_locations)(XtParent(w), True); LayoutChildren(XtParent(w), w); if (XtIsRealized((Widget)ow)) { XClearArea(XtDisplay(ow), XtWindow(ow), 0, 0, ow->core.width, ow->core.height, True); } } return(XtGeometryYes); } /************************************************************ * * Constraint widget class procedures. * ************************************************************/ /* Function Name: ConstraintInitialize * Description: Called when a childs constriaints need initializing. * Arguments: req - the widget being requested. * set - what this will become. * args, num_args - the argument list. * Returns: none. */ /*ARGSUSED*/ static void ConstraintInitialize(Widget req, Widget set, ArgList args, Cardinal * num_args) { XmOutlineC_widget_x(set->core.constraints) = XmOutlineC_open_close_x(set->core.constraints) = 0; } /* Function Name: ConstraintSetValues * Description: Called a constraint is changed on my children. * Arguments: current - the current (old) widget values. * request - before superclassed have changed things. * set - what will acutally be the new values. * args, num_args - the arguments in the list. * Returns: none */ /*ARGSUSED*/ static Boolean ConstraintSetValues(Widget current, Widget request, Widget set, ArgList args, Cardinal * num_args) { Widget ow = XtParent(set); OutlineConstraints set_node = GetNodeInfo(set); OutlineConstraints old_node = GetNodeInfo(current); Boolean insert_change = False, redisplay = False; int i; for (i = 0; i < *num_args; i++) if (streq(args[i].name, XmNinsertBefore)) { insert_change = True; break; } /* * Nothing below here needs to be done before we are realized. */ if (!XtIsRealized(set)) return(False); if ((XmHierarchyC_parent(set_node) != XmHierarchyC_parent(old_node)) || (XmHierarchyC_state(set_node) != XmHierarchyC_state(old_node)) || (insert_change)) { /* * Other operations have already been performed by my superclass. */ if (XmHierarchy_refigure_mode((XmOutlineWidget)ow)) { CalcLocations(ow, True); LayoutChildren(ow, NULL); redisplay = True; } /* * Since Layout children has (possibily) moved this widget * to a new location. The current state of the widget * must be updated so that neither the intrinsics nor * any sub-classes of this widget attempt to move it * to the new location, since it is already there. */ current->core.x = set->core.x; current->core.y = set->core.y; } if (XtIsRealized(ow) && redisplay && (XmHierarchy_refigure_mode((XmOutlineWidget)ow))) { XClearArea(XtDisplay(ow), XtWindow(ow), 0, 0, ow->core.width, ow->core.height, True); } return(False); } /* Function Name: ConstraintDestroy * Description: Destroys all data allocated by the constraint * record. * Arguments: w - the widget. * Returns: none. * * Removes the destroyed children from the list of children that still * need to be moved. */ static void ConstraintDestroy(Widget w) { OutlineConstraints node = GetNodeInfo(w); XmListElem *elem, *next; XmOutlineWidget ow; if (XmHierarchyC_state(node) == XmNotInHierarchy) return; ow = (XmOutlineWidget) XtParent(w); elem = XmListFirst(XmOutline_child_op_list(ow)); while(elem != NULL) { OutlineConstraints info = (OutlineConstraints) XmListElemData(elem); next = XmListElemNext(elem); if (XmHierarchyC_widget(info) == w) { /* * Each widget will only be in the list once. */ _XmListRemove(XmOutline_child_op_list(ow), elem); break; } elem = next; } } /************************************************************ * * Hierarchy Widget class proceedures. * ************************************************************/ /* Function Name: ToggleNodeState * Description: Toggles the open/close state of a toggle button. * Arguments: w - the command button that activated this. * node_ptr - a pointer to the node info. * call_data - UNUSED. * Returns: none. */ /*ARGSUSED*/ static void ToggleNodeState(Widget w, XtPointer node_ptr, XtPointer call_data) { Widget ow = XtParent(w); XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(ow); { XtCallbackProc toggle_node_state; _XmProcessLock() toggle_node_state = SUPERCLASS->hierarchy_class.toggle_node_state; _XmProcessUnlock() (*toggle_node_state)(w, node_ptr, call_data); } { XmOutlineCalcLocationProc calc_locations; _XmProcessLock() calc_locations = oc->outline_class.calc_locations; _XmProcessUnlock() (*calc_locations)(ow, True); } LayoutChildren(ow, NULL); /* * Could check for a size change and abort if we really wanted * to be clever. */ if (XtIsRealized(ow)) { XClearArea(XtDisplay(ow), XtWindow(ow), 0, 0, ow->core.width, ow->core.height, True); } } /************************************************************ * * Outline widget class proceedures. * ************************************************************/ /************************************************************ * * Actions and Callbacks. * ************************************************************/ /************************************************************ * * Internal routines. * ************************************************************/ /* Function Name: CalcLocations * Description: Calculates the location of each widget in the outline. * Arguments: w - the outline widget. * allow_resize - allow shell to resize? * Returns: none. */ static void CalcLocations(Widget w, Boolean allow_resize) { Cardinal outline_depth, current_index; XmOutlineWidget ow = (XmOutlineWidget) w; OutlineConstraints node; XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(w); register int i; unsigned int num_nodes; if (!XmHierarchy_refigure_mode(ow)) return; XmOutline_max_widget_width(ow) = 0; /* reset max_width. */ /* * Reset each node to be hidden; */ for( i = 0; i < ow->composite.num_children; ++i ) { node = GetNodeInfo(ow->composite.children[i]); XmHierarchyC_status(node) |= IS_COMPRESSED; } num_nodes = 0; outline_depth = 0; GetNodeDimensions(w, (OutlineConstraints) XmHierarchy_top_node(ow), outline_depth, &num_nodes); { XmOutlineMaxWidthProc calc_max_width; _XmProcessLock(); calc_max_width = oc->outline_class.calc_max_width; _XmProcessUnlock() XmOutline_max_width(ow) = (*calc_max_width)(w); } XmHierarchy_num_nodes(ow) = num_nodes; current_index = 0; { XmHierarchyBuildTableProc build_node_table; _XmProcessLock(); build_node_table = oc->hierarchy_class.build_node_table; _XmProcessUnlock(); (*build_node_table)(w, XmHierarchy_top_node(ow), ¤t_index); } if (num_nodes != 0) { XmOutline_top_node_of_display(ow) = (OutlineConstraints) XmHierarchy_node_table(ow)[0]; } else XmOutline_top_node_of_display(ow) = NULL; if (allow_resize) RequestNewSize(w); } /* Function Name: GetNodeDimensions Description: Calls GetNodeHeightAndWidth, but first resets maximum Arguments: w - outline widget node - the starting node depth - outline depth num_nodes - like num_nuts... hahaha Returns: none */ static void GetNodeDimensions(Widget w, OutlineConstraints node, Cardinal depth, Cardinal *num) { XmOutlineWidget ow = (XmOutlineWidget) w; XmOutline_max_widget_width(ow) = 2 * XmHierarchy_h_margin(ow); GetNodeHeightAndWidth(w, node, depth, TRUE, num); } /* Function Name: RequestNewSize * Description: Asks our parent for a new size. * Arguments: w - the data request outline widget. * Returns: none. */ static void RequestNewSize(Widget w) { Dimension width, height, rwidth, rheight; XtGeometryResult ret_val; GetDesiredSize(w, NULL, NULL, &width, &height, False, True); /* * It is just barely possible that our height or width could go to * zero. If this happens then do no request a new size because the * X server will generate a protocol error. It is best to just * stay where we are. */ if ((width == 0) || (height == 0)) return; ret_val = XtMakeResizeRequest(w, width, height, &rwidth, &rheight); while (ret_val == XtGeometryAlmost) { Dimension fwidth, fheight; /* Final values */ if(XmOutline_constrain_width(w)) { GetDesiredSize(w, &rwidth, &rheight, &fwidth, &fheight, False, True); ret_val = XtMakeResizeRequest(w, fwidth, fheight, &rwidth, &rheight); } else { ret_val = XtMakeResizeRequest(w, rwidth, rheight, NULL, NULL); } } } /* Function Name: GetDesiredSize * Description: Returns the desired size of the outline widget. * Arguments: w - the outline widget. * width - the intended width * height - the intended height * width_ret - the desired width. * height_ret - the desired height. * recalc - recalculate the new size if row height unset? * allow_resize - allow the outline to attempt a resize? * Returns: none. */ static void GetDesiredSize(Widget w, Dimension *width, Dimension *height, Dimension *width_ret, Dimension *height_ret, Boolean recalc, Boolean allow_resize) { XmOutlineWidget ow = (XmOutlineWidget) w; register int i, num, temp_height; OutlineConstraints * node; XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(w); if (recalc) { if(XmOutline_constrain_width(w)) { Dimension tmp_width, tmp_height; tmp_height = w->core.height; tmp_width = w->core.width; if(width) w->core.width = *width; if(height) w->core.height = *height; { XmOutlineCalcLocationProc calc_locations; _XmProcessLock(); calc_locations = oc->outline_class.calc_locations; _XmProcessUnlock(); (*calc_locations)(w, allow_resize); } if(width) w->core.width = tmp_width; if(height) w->core.height = tmp_height; } else { { XmOutlineCalcLocationProc calc_locations; _XmProcessLock(); calc_locations = oc->outline_class.calc_locations; _XmProcessUnlock(); (*calc_locations)(w, allow_resize); } } } if(XmOutline_constrain_width(ow) && width) { *width_ret = *width; } else { *width_ret = XmOutline_max_width(ow); } temp_height = 0; node = (OutlineConstraints *) XmHierarchy_node_table(ow); num = XmHierarchy_num_nodes(ow); for (i = 0; i < num; i++, node++) temp_height += XmOutlineC_height(*node) + XmHierarchy_v_margin(ow); *height_ret = temp_height + XmHierarchy_v_margin(ow); } /* Function Name: LayoutChildren * Description: all the fun stuff for positioning the children is here. * Arguments: w - the outline widget. * assign_child - The child to assign values to rather * than _XiMove. * Returns: none. */ static void LayoutChildren(Widget w, Widget assign_child) { XmOutlineWidget ow = (XmOutlineWidget) w; XmOutlineWidgetClass oc = (XmOutlineWidgetClass) XtClass(w); register OutlineConstraints disp_top = XmOutline_top_node_of_display(ow); register HierarchyConstraints * node_table = XmHierarchy_node_table(ow); register Cardinal num_nodes = XmHierarchy_num_nodes(ow); register Position cur_y; register int cur_node, v_margin; int oc_x = 0, oc_y = 0; Boolean register_workproc = True; if (!XmHierarchy_refigure_mode(ow)) return; XmDropSiteStartUpdate(w); /* * Remove the old list, replace it with the new one. */ if (XmListFirst(XmOutline_child_op_list(ow)) != NULL) { if( XmHierarchy_work_proc_id(ow) != (XtWorkProcId) NULL ) { XtRemoveWorkProc(XmHierarchy_work_proc_id(ow)); XmHierarchy_work_proc_id(ow) = (XtWorkProcId) NULL; } _XmListFree(XmOutline_child_op_list(ow)); XmOutline_child_op_list(ow) = _XmListInit(); register_workproc = False; } /* * Unmap all nodes that no longer are visible. */ { XmHierarchyExtraNodeProc unmap_all_extra_nodes; _XmProcessLock(); unmap_all_extra_nodes = oc->hierarchy_class.unmap_all_extra_nodes; _XmProcessUnlock(); (*unmap_all_extra_nodes)(w, XmHierarchy_top_node(ow)); } /* * Find the first node to be displayed, and unmap all nodes that would be * above that one. */ for (cur_node = 0; cur_node < num_nodes; cur_node++, node_table++) { if (*node_table == (HierarchyConstraints) disp_top) break; UnmapNode(ow, (OutlineConstraints) *node_table); } cur_y = (Position) (v_margin = XmHierarchy_v_margin(ow)); while ( ((int)cur_node < (int)num_nodes) && (XmOutline_connect_nodes(ow) || ((int)cur_y < (int)ow->core.height) ) ) { register Widget w; OutlineConstraints node = (OutlineConstraints) *node_table; if (XmHierarchyC_open_close_button(node) != NULL) { Position offset; Widget w; w = XmHierarchyC_open_close_button(node); offset = (XmOutlineC_height(node) - (w->core.height + 2 * w->core.border_width)); oc_x = XmOutlineC_open_close_x(node); oc_y = cur_y + offset/2; } w = XmHierarchyC_widget(node); if (assign_child == w) { w->core.x = XmOutlineC_widget_x(node); w->core.y = cur_y; } MoveNode(ow, node, XmOutlineC_widget_x(node), cur_y, oc_x, oc_y, True); cur_y += XmOutlineC_height(node) + v_margin; cur_node++; node_table++; } /* * We have used all the window, unmap all other nodes. */ while(cur_node < num_nodes) { UnmapNode(ow, (OutlineConstraints) *node_table); cur_node++; node_table++; } if (register_workproc) { XmHierarchy_work_proc_id(ow) = XtAppAddWorkProc(XtWidgetToApplicationContext(w), MoveNodesTimer, (XtPointer) w); } XmDropSiteEndUpdate(w); } /* Function Name: GetNodeHeightAndWidth * Description: Gets the size of each node. * Arguments: w - the drt widget. * node - the node to get the height and width of. * outline_depth - depth of the outline at this node. * recurse - recurse all subnodes?. * IN/OUT num - number of nodes. * Returns: none */ static void GetNodeHeightAndWidth(Widget w, OutlineConstraints node, Cardinal outline_depth, Boolean recurse, Cardinal * num) { XmOutlineWidget ow = (XmOutlineWidget) w; register int i; XtWidgetGeometry geom_pref; if ((node == NULL) || ((XmHierarchyC_widget(node) != NULL) && !XtIsManaged(XmHierarchyC_widget(node)))) { return; } if (XmHierarchyC_state(node) != XmHidden) { Arg args[5]; Cardinal num_args; Dimension width, open_height, node_height, width2, border_width; if (XmHierarchyC_open_close_button(node) != NULL) { num_args = 0; XtSetArg(args[num_args], XmNwidth, &width); num_args++; XtSetArg(args[num_args], XmNheight, &open_height); num_args++; XtSetArg(args[num_args], XmNborderWidth, &border_width);num_args++; XtGetValues(XmHierarchyC_open_close_button(node), args, num_args); border_width *= 2; width += border_width; open_height += border_width; } else { width = 0; open_height = 0; } num_args = 0; /* XtSetArg(args[num_args], XmNwidth, &width2); num_args++; */ /* XtSetArg(args[num_args], XmNheight, &node_height); num_args++; */ XtSetArg(args[num_args], XmNborderWidth, &border_width); num_args++; XtGetValues(XmHierarchyC_widget(node), args, num_args); XtQueryGeometry(XmHierarchyC_widget(node), NULL, &geom_pref); width2 = geom_pref.width; node_height = geom_pref.height; border_width *= 2; width2 += border_width; node_height += border_width; /* * indent_level = outline_depth; */ XmOutlineC_open_close_x(node) = ((outline_depth *XmOutline_indent_space(ow)) + XmHierarchy_h_margin(ow)); if (XmHierarchyC_open_close_button(node) == NULL) XmOutlineC_widget_x(node) = XmOutlineC_open_close_x(node); else XmOutlineC_widget_x(node) = (XmOutlineC_open_close_x(node) + width + XmHierarchy_h_margin(ow)); width2 += XmOutlineC_widget_x(node) + XmHierarchy_h_margin(ow); if ( width2 > XmOutline_max_widget_width(ow) ) XmOutline_max_widget_width(ow) = width2; /* * Now, if we are set to constrain our childrens' widths, we need * to do a geometry negotiation and reset the width to whatever we * decide. */ if(XmOutline_constrain_width(w)) { NegotiateNodeWidth(w, node); num_args = 0; XtSetArg(args[num_args], XmNheight, &node_height); num_args++; XtGetValues(XmHierarchyC_widget(node), args, num_args); } XmOutlineC_height(node) = MAX(node_height, open_height); (*num)++; } if (!recurse || (XmHierarchyC_state(node) == XmClosed)) return; /* * Hidden nodes don't count as another level down the outline. */ if (XmHierarchyC_state(node) != XmHidden) outline_depth++; for (i = 0; i < XmHierarchyC_num_children(node); i++) { GetNodeHeightAndWidth(w, (OutlineConstraints) XmHierarchyC_children(node)[i], outline_depth, TRUE, num); } if (XmHierarchyC_state(node) != XmHidden) outline_depth--; } /* Function Name: GetNodeInfo * Description: Gets the node info associated with this widget. * Arguments: w - the widget. * Returns: the node info about this widget. */ static OutlineConstraints GetNodeInfo(Widget w) { return((OutlineConstraints) w->core.constraints); } /* Function Name: CalcMaxWidth * Description: Calculates the maximum width of the outline. * Arguments: w - the outline. * Returns: The max width the outline would like to be. */ static int CalcMaxWidth(Widget w) { return XmOutline_max_widget_width(w) + 2 * XmHierarchy_h_margin(w); } /************************************************************ * * Code for handling the node queue. * ************************************************************/ /* Function Name: UnmapAllExtraNodes * Description: Correctly unmaps each node in the hierarchy that is * currently compressed out. * Arguments: w - the ow. * node - node to work one. * Returns: none */ static void UnmapAllExtraNodes(Widget w, HierarchyConstraints node) { register int i, num; register HierarchyConstraints * ptr; if ((XmHierarchyC_status(node) & IS_COMPRESSED) && (XmHierarchyC_status(node) & IS_MAPPED)) { UnmapNode((XmOutlineWidget) w, (OutlineConstraints) node); } ptr = XmHierarchyC_children(node); for (num = XmHierarchyC_num_children(node), i = 0; i < num; i++, ptr++) UnmapAllExtraNodes(w, *ptr); } /* Function Name: MoveNode * Description: This function adds a widget to the movment queue * but does not move it until it becomes visible. * Arguments: ow - the outline widget. * node - the node to move. * x, y - the X and Y location. * oc_x, oc_y - the X and Y location of the open close button. * map - map this child? * Returns: none. */ static void MoveNode(XmOutlineWidget ow, OutlineConstraints node, Position x, Position y, Position oc_x, Position oc_y, Boolean map) { XmOutlineC_new_x(node) = x; XmOutlineC_new_y(node) = y; XmOutlineC_oc_new_x(node) = oc_x; XmOutlineC_oc_new_y(node) = oc_y; XmOutlineC_map(node) = map; XmOutlineC_move(node) = True; XmOutlineC_unmap(node) = False; _XmListAddBefore(XmOutline_child_op_list(ow), NULL, (XtPointer) node); } /* Function Name: UnmapNode * Description: This function adds a widget to the movment queue * telling it to be unmapped. * Arguments: ow - the outline widget. * node - the node to move. * Returns: none. */ static void UnmapNode(XmOutlineWidget ow, OutlineConstraints node) { XmOutlineC_map(node) = False; XmOutlineC_move(node) = False; XmOutlineC_unmap(node) = True; _XmListAddBefore(XmOutline_child_op_list(ow), NULL, (XtPointer) node); } /* Function Name: ProcessChildQueue * Description: Processes the child queue. * Arguments: ow - the outline widget. * vis - the visible rect. * Returns: none. */ static void ProcessChildQueue(XmOutlineWidget ow, XRectangle *vis) { XmListElem *elem, *next; elem = XmListFirst(XmOutline_child_op_list(ow)); while(elem != NULL) { OutlineConstraints info = (OutlineConstraints) XmListElemData(elem); next = XmListElemNext(elem); if (CheckWidget(vis, info)) _XmListRemove(XmOutline_child_op_list(ow), elem); elem = next; } } /* Function Name: CheckWidget * Description: This function checks a widget to see if it * needs to be operated on. * Arguments: visible - visible rect. * info - the child op info. * Returns: True if operation complete. * * NOTES: A widget will need to be operated on if it is mapped an will show * on the screen, or if the new location is on the screen. */ static Boolean CheckWidget(XRectangle * visible, OutlineConstraints node) { if (( ((XmHierarchyC_status(node) & IS_MAPPED) || XmOutlineC_map(node)) && ( WidgetInRect(visible, XmHierarchyC_open_close_button(node)) || WidgetInRect(visible, XmHierarchyC_parent(node)) || WidgetInRect(visible, XmHierarchyC_widget(node)) ) ) || LocInRect(visible, XmHierarchyC_open_close_button(node), XmOutlineC_oc_new_x(node), XmOutlineC_oc_new_y(node)) || LocInRect(visible, XmHierarchyC_widget(node), XmOutlineC_new_x(node), XmOutlineC_new_y(node)) ) { ProcessNode(node); return(True); } return(False); } /* Function Name: ProcessNode * Description: Processes the request made of this outline node. * Arguments: node - the Outline node to process. * Returns: none. */ static void ProcessNode(OutlineConstraints node) { XmOutlineWidgetClass tc; Widget w = XmHierarchyC_widget(node); if (w == NULL) return; tc = (XmOutlineWidgetClass) XtClass(XtParent(w)); if (XmOutlineC_move(node)) { _XmMoveWidget(XmHierarchyC_widget(node), XmOutlineC_new_x(node), XmOutlineC_new_y(node)); if (XmHierarchyC_open_close_button(node) != NULL) _XmMoveWidget(XmHierarchyC_open_close_button(node), XmOutlineC_oc_new_x(node), XmOutlineC_oc_new_y(node)); XmOutlineC_move(node) = False; } if (XmOutlineC_map(node)) { { XmHierarchyNodeProc map_node; _XmProcessLock(); map_node = tc->hierarchy_class.map_node _XmProcessUnlock(); (*map_node)((HierarchyConstraints) node); } XmOutlineC_map(node) = False; } if (XmOutlineC_unmap(node)) { { XmHierarchyNodeProc unmap_node; _XmProcessLock(); unmap_node = tc->hierarchy_class.unmap_node _XmProcessUnlock(); (*unmap_node)((HierarchyConstraints) node); } XmOutlineC_unmap(node) = False; } } /* Function Name: WidgetInRect * Description: Checks to see if widget is in the rect specified. * Arguments: rect - the rect to check. * w - the widget to check. * Returns: True if the widget is in the regien specified. */ static Boolean WidgetInRect(XRectangle *rect, Widget w) { if (w == NULL) return(False); return(LocInRect(rect, w, w->core.x, w->core.y)); } /* Function Name: LocInRect * Description: Checks to see if widget is in the rect specified. * given new X and Y locations. * Arguments: rect - the rectangle to check. * w - the widget to check. * x, y - the new x and y locations. * Returns: True if the widget is in the regien specified. */ static Boolean LocInRect(XRectangle *rect, Widget w, Position x, Position y) { register int x1, x2; register int y1, y2; if (w == NULL) return(False); x1 = x + w->core.width; y1 = y + w->core.height; x2 = rect->x + rect->width; y2 = rect->y + rect->height; return (!((x > x2) || (y > y2) || (x1 < rect->x) || (y1 < rect->y))); } /* Function Name: MoveNodesTimer * Description: processes one node from the movement queue. * Arguments: data - A Pointer to the outline widget. * id - th ext interval id. * Returns: none */ /* ARGSUSED */ static Boolean MoveNodesTimer(XtPointer data) { XmOutlineWidget ow = (XmOutlineWidget) data; XmListElem *elem = XmListFirst(XmOutline_child_op_list(ow)); if (elem != NULL) { OutlineConstraints node = (OutlineConstraints) XmListElemData(elem); ProcessNode(node); _XmListRemove(XmOutline_child_op_list(ow), elem); return (False); } XmHierarchy_work_proc_id(ow) = (XtWorkProcId) NULL; return (True); } /* Function Name: NegotiateNodeWidth * Description: Does a geometry negoation with the child * specified by node with the intent of fitting * the child within the existing width of the * Outline widget. * Arguments: w - The XmOutline widget * node - The constraint record for the child in * question * Returns: The width negotiated */ static void NegotiateNodeWidth(Widget w, OutlineConstraints node) { Dimension width_avail; XtWidgetGeometry geom_asked, geom_agreed; XtGeometryResult result; Dimension curr_width, curr_height; width_avail = w->core.width - XmOutlineC_widget_x(node); curr_width = XmHierarchyC_widget(node)->core.width; curr_height = XmHierarchyC_widget(node)->core.height; geom_asked.request_mode = XtCWQueryOnly; result = XtQueryGeometry(XmHierarchyC_widget(node), &geom_asked, &geom_agreed); if(geom_agreed.width < 1) geom_agreed.width = 1; if(geom_agreed.height < 1) geom_agreed.height = 1; if(geom_agreed.width <= width_avail) { /* * If it's the right size already, just return */ if(curr_width == geom_agreed.width && curr_height == geom_agreed.height) { return; } else { _XmResizeWidget(XmHierarchyC_widget(node), geom_agreed.width, geom_agreed.height, geom_agreed.border_width); return; } } /* * Otherwise tell the widget to size itself to the right width and * see what we get */ geom_asked.request_mode = CWWidth; geom_asked.width = width_avail; result = XtQueryGeometry(XmHierarchyC_widget(node), &geom_asked, &geom_agreed); if(geom_agreed.width < 1) geom_agreed.width = 1; if(geom_agreed.height < 1) geom_agreed.height = 1; if(result == XtGeometryYes) { _XmResizeWidget(XmHierarchyC_widget(node), width_avail, geom_agreed.height, geom_agreed.border_width); return; } else if(result == XtGeometryAlmost) { /* * See if it lied and set the width correctly anyway */ if(geom_agreed.width <= width_avail) { _XmResizeWidget(XmHierarchyC_widget(node), geom_agreed.width, geom_agreed.height, geom_agreed.border_width); return; } } /* * If we get here, the sucker tried to deny the request, so just * clip the thing. Thbbbt! */ _XmResizeWidget(XmHierarchyC_widget(node), width_avail, geom_agreed.height, geom_agreed.border_width); } /* drawing on expose; taken from XmTree in horizontal mode with ** ladder drawing ** Note: it looks not so good when indentSpace is very small */ static void RedrawOutlineLines(Widget w, XRectangle * rect) { XmOutlineWidget ow = (XmOutlineWidget) w; if (XtIsRealized(w)) /* && has children */ DrawOutlineLine(w, rect, (OutlineConstraints) XmHierarchy_top_node(ow)); } static void DrawOutlineLine(Widget w, XRectangle *rect, OutlineConstraints node) { OutlineConstraints from_node = node; if (XmHierarchyC_widget(node) != NULL && !XtIsManaged(XmHierarchyC_widget(node))) return; /* * Hunt up the list until we find a non-hidden parent to be the from * node. */ while ((XmHierarchyC_parent(from_node) != NULL) && (XmHierarchyC_state(from_node) == XmHidden)) { from_node = GetNodeInfo(XmHierarchyC_parent(from_node)); } { OutlineConstraints * kids; register int i, num_kids; Boolean anyKidManaged = False; /* CR03730 Support Case 22066 */ LadderPoint from_node_point, kid_point; LadderPoint last_kid_point; XmOutlineWidget ow = (XmOutlineWidget)w; num_kids = XmHierarchyC_num_children(node); kids = (OutlineConstraints *) XmHierarchyC_children(node); /* * This only executes if the root is hidden. */ if (XmHierarchyC_state(from_node) == XmHidden) { for (i = 0; i < num_kids; i++, kids++) DrawOutlineLine(w, rect, *kids); /* recurse to descendants. */ return; } if (XmHierarchyC_state(from_node) == XmClosed) return; _CalcNodeMidPoint( from_node, w, &from_node_point ); for (i = 0; i < num_kids; i++, kids++) { if (XtIsManaged(XmHierarchyC_widget((*kids)))) { anyKidManaged = True; /* CR03730 Support Case 22066 */ if (XmHierarchyC_state((*kids)) != XmHidden) { _OutlineDrawLine(w, rect, from_node, *kids, from_node_point, &kid_point); /* set up the points to draw ladder lines */ last_kid_point.x = kid_point.x; last_kid_point.y = kid_point.y; } DrawOutlineLine(w, rect, *kids); /* recurse to descendants. */ } } /* Draw extra ladder lines if necessary. */ if (num_kids > 0 && anyKidManaged) { /* CR03730 Support Case 22066 anyKidManaged added to prevent draw needless (x & y are not initialized if no kid managed) line */ XDrawLine(XtDisplay(w), XtWindow(w), XmOutline_draw_gc(ow), from_node_point.x, from_node_point.y, from_node_point.x, last_kid_point.y ); } } } static void _CalcNodeMidPoint( OutlineConstraints node, Widget w, LadderPoint *ret_point ) { if (!XmHierarchyC_widget(node)) return; { XmOutlineWidget ow = (XmOutlineWidget)w; Widget which; int value; if (XmHierarchyC_open_close_button(node)) value = (int)XtWidth(which=XmHierarchyC_open_close_button(node)); else { value = (int)XmOutline_indent_space(ow); which = XmHierarchyC_widget(node); } ret_point->x = XmOutlineC_open_close_x(node) + value/2; ret_point->y = XtY(which)+XtHeight(which); /* plus possible pad */ } } static void _OutlineDrawLine(Widget w, XRectangle *rect, OutlineConstraints parent, OutlineConstraints child, LadderPoint from_ladder_point, LadderPoint *to_ladder_point ) { GC gc; XmOutlineWidget ow = (XmOutlineWidget) w; register int x2, y2; register int rx2, ry2, cx1, cx2, cy1, cy2; /* * (from_ladder_point.x, from_ladder_point.y) are the coordinates * of the parent's midpoint * (x2, y2) are the coordinates of the child midpoint * * We will end up drawing a partial ladder line from * (cx1, cy1) to (cx2, cy2) * * (rx2, ry2) are the coordinates of the lower right of clip rectangle */ /* * Must always do the first node since it is what draws the root * of the ladder. */ if (child != (OutlineConstraints) XmHierarchyC_children(parent)[0] && (!(XmHierarchyC_status(child) & IS_MAPPED) || (XmHierarchyC_status(child) & IS_COMPRESSED))) { return; } gc = XmOutline_draw_gc(ow); x2 = XmOutlineC_open_close_x(child); y2 = XtY(XmHierarchyC_widget(child)) + XtHeight(XmHierarchyC_widget(child))/2; cx1 = MIN(from_ladder_point.x, x2); cx2 = MAX(from_ladder_point.x, x2); cy1 = MIN(from_ladder_point.y, y2); cy2 = MAX(from_ladder_point.y, y2); cy1 = cy2 = y2; rx2 = rect->x + rect->width; ry2 = rect->y + rect->height; /* * Not very pretty, only checks to see if the rect containing the * line is partially within the exposed rectangle. */ if (!((cx1 > rx2) || (cy1 > ry2) || (cx2 < rect->x) || (cy2 < rect->y))) XDrawLine(XtDisplay(w), XtWindow(w), gc, cx1, cy1, cx2, cy2); /* This is sent back because the ladder lines get connected later */ to_ladder_point->x = cx1; to_ladder_point->y = cy1; } /************************************************************ * * Public functions. * ************************************************************/ /* Function Name: XmCreateOutline * Description: Creation Routine for UIL and ADA. * Arguments: parent - the parent widget. * name - the name of the widget. * args, num_args - the number and list of args. * Returns: The created widget. */ Widget XmCreateOutline(Widget parent, String name, ArgList args, Cardinal num_args) { return(XtCreateWidget(name, xmOutlineWidgetClass, parent, args, num_args)); }