/* $TOG: Container.c /main/35 1999/07/29 09:16:07 mgreess $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ /* * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC. * ALL RIGHTS RESERVED */ #ifndef X_NOT_STDC_ENV #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ColorI.h" #include "GadgetUtiI.h" #include "GeoUtilsI.h" #include "IconGI.h" #include "RepTypeI.h" #include "TransferI.h" #include "TraversalI.h" #include "XmI.h" #include "CareVisualTI.h" #include "MessagesI.h" #include "ClipWindTI.h" #include /* for bzero et al */ #define ZERO_DIM 0 #define DEFAULT_INDENTATION 40 #define NO_CELL -1 #define OBNAME "OutlineButton" #define HEADERNAME "Header" #define DANAME "HeaderDA" #define INVALID_COUNT 32767 #define INVALID_DIMENSION 32767 #define MOTION_THRESHOLD 3 /* Make this nicely divisible by 2 */ #define DRAG_STATE_SIZE 14 #define WRONGPARAMS _XmMMsgContainer_0000 #define MESSAGE1 _XmMMsgContainer_0001 enum { ANY_FIT, EXACT_FIT, FORCE}; /* Useful macros */ #define _LEFT 0 #define _RIGHT 1 #define _UP 2 #define _DOWN 3 #define _FIRST 4 #define _LAST 5 #define _COLLAPSE 2 #define _EXPAND 3 #define _IN "In" #define _OUT "Out" #define _ENTER "Enter" #define _LEAVE "Leave" #define _LINK 0 #define _MOVE 1 #define _COPY 2 #define defaultTranslations _XmContainer_defaultTranslations #define traversalTranslations _XmContainer_traversalTranslations /******** Static Function Declarations ********/ static void GetDetailHeader( Widget wid, int offset, XtArgVal *value); static void GetDetailHeaderCount( Widget wid, int offset, XtArgVal *value); static void GetOutlineColumnWidth( Widget wid, int offset, XtArgVal *value); static void ClassPartInitialize( WidgetClass wc); static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args); static void Destroy( Widget wid); static void Resize( Widget wid); static void Redisplay( Widget wid, XEvent *event, Region region); static Boolean SetValues( Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args); static void GetSize( Widget wid, Dimension * pwidth, Dimension * pheight); static XtGeometryResult QueryGeometry( Widget wid, XtWidgetGeometry *intended, XtWidgetGeometry *desired); static XtGeometryResult GeometryManager( Widget instigator, XtWidgetGeometry *desired, XtWidgetGeometry *allowed); static void ChangeManaged( Widget wid); static void ChangeManagedOutlineDetail( Widget wid); static void ChangeManagedSpatial( Widget wid); static Boolean RequestSpatialGrowth( Widget wid, Widget cwid); static void ConstraintInitialize( Widget rcwid, Widget ncwid, ArgList args, Cardinal *num_args); static void ConstraintDestroy( Widget cwid); static Boolean ConstraintSetValues( Widget ccwid, Widget rcwid, Widget ncwid, ArgList args, Cardinal *num_args); static Widget ObjectAtPoint( Widget wid, Position x, Position y); static Boolean TestFitItem( Widget wid, Widget cwid, Position x, Position y); static Boolean PlaceItem( Widget wid, Widget cwid, unsigned char fit_type); static Boolean RemoveItem( Widget wid, Widget cwid); static void GetSpatialSize( Widget wid, Dimension * pwidth, Dimension * pheight); static void GetSpatialSizeCellAdjustment( Widget wid, int *width_in_cells, int *height_in_cells, ContainerCwidCellInfo cwid_info, int cwid_info_count); static void PlaceItemNone( Widget wid, Widget cwid, unsigned char fit_type); static void PlaceItemGridCells( Widget wid, Widget cwid, unsigned char fit_type); static int GetCellFromCoord( Widget wid, Position x, Position y); static XPoint * GetCoordFromCell( Widget wid, int cell_idx, XPoint *point); static void PlaceItemReset( Widget wid); static void PlaceCwid( Widget cwid, Position x, Position y); static XPoint * SnapCwid( Widget cwid, Position x, Position y, XPoint *point); static void HideCwid( Widget cwid); static void ContainerNoop( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerHandleBtn1Down( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerHandleBtn1Motion( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerHandleBtn1Up( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerHandleBtn2Down( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerHandleBtn2Motion( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerHandleBtn2Up( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerBeginSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerButtonMotion( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerEndSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerBeginToggle( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerEndToggle( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerBeginExtend( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerEndExtend( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerStartTransfer( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerEndTransfer( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerPrimaryCopy( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerPrimaryLink( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerPrimaryMove( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerCancel( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerExtend( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerMoveCursor( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerExtendCursor( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerToggleMode( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerSelectAll( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerDeselectAll( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerActivate( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerExpandOrCollapse( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void ContainerConvertProc( Widget wid, XtPointer closure, XmConvertCallbackStruct *cs); static void ContainerDestinationProc( Widget wid, XtPointer closure, XmDestinationCallbackStruct *cs); static void ContainerDestPrehookProc( Widget wid, XtPointer closure, XmDestinationCallbackStruct *cs); static void ContGetValues( Widget wid, XmContainerData contData); static unsigned char GetVisualEmphasis( Widget cwid); static void SetVisualEmphasis( Widget cwid, unsigned char emphasis); static unsigned char GetViewType( Widget cwid); static void SetViewType( Widget cwid, unsigned char viewtype); static Dimension GetIconWidth( Widget cwid); static Cardinal GetDefaultDetailCount( Widget wid); static XmTabList SetDynamicTabList( Widget wid); static XmTabList GetDumbTabList( int tab_size, Cardinal asked_num_tab); static Dimension GetDynFirstColWidth( Widget wid); static void ResizeIconWidths( Widget wid); static void Layout( Widget wid); static void RequestOutlineDetail( Widget wid, XtWidgetGeometry * geo_desired); static void LayoutOutlineDetail( Widget wid); static void LayoutSpatial( Widget wid, Boolean growth_req_allowed, CwidNode stop_node); static void SetCellSizes( Widget wid); static void SetLargeCellSizes( Widget wid); static void SetSmallCellSizes( Widget wid); static void SizeOutlineButton( Widget wid); static void UpdateGCs( Widget wid); static void CreateIconHeader( Widget wid); static Widget GetRealIconHeader( Widget wid); static void UpdateIconHeader( Widget wid, Boolean count_only); static void ChangeView( Widget wid, unsigned char view); static CwidNode NewNode( Widget cwid); static void InsertNode( CwidNode node); static void SeverNode( CwidNode node); static void DeleteNode( Widget cwid); static CwidNode GetFirstNode( XmContainerWidget cw); static CwidNode GetNextNode( CwidNode start_item); static Boolean NodeIsActive( CwidNode node); static CwidNode GetNextUpLevelNode( CwidNode start_item); static void StartSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params); static Boolean ProcessButtonMotion( Widget wid, XEvent *event, String *params, Cardinal *num_params); static Boolean SelectAllCwids( Widget wid); static Boolean DeselectAllCwids( Widget wid); static Boolean MarkCwid( Widget cwid, Boolean visual_only); static Boolean UnmarkCwidVisual( Widget cwid); static void SetMarkedCwids( Widget wid); static Boolean ResetMarkedCwids( Widget wid); static Boolean MarkCwidsInRange( Widget wid, Widget cwid1, Widget cwid2, Boolean visual_only); static Boolean MarkCwidsInMarquee( Widget wid, Boolean find_anchor, Boolean visual_only); static Boolean InMarquee( Widget cwid); static void RecalcMarquee( Widget wid, Widget cwid, Position x, Position y); static void DrawMarquee( Widget wid); static void KBSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void SetLocationCursor( Widget cwid); static void CalcNextLocationCursor( Widget wid, String direction); static Widget RedirectTraversal( Widget old_focus, Widget new_focus, unsigned int focus_policy, XmTraversalDirection direction, unsigned int pass) ; static CwidNode GetLastTraversableChild( CwidNode node); static CwidNode GetPrevTraversableSibling( CwidNode node); static CwidNode GetPrevTraversableUplevel( CwidNode node); static CwidNode GetNextTraversableChild( CwidNode node); static CwidNode GetNextTraversableSibling( CwidNode node); static CwidNode GetNextTraversableUplevel( CwidNode node); static CwidNode GetNextTraversable( CwidNode node); static Widget GetLastTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap); static Widget GetFirstTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap); static Widget GetNextTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap); static Widget GetPrevTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap); static void MakeOutlineButton( Widget cwid); static void ChangeOutlineButtons( Widget wid); static void ExpandCwid( Widget cwid); static void CollapseCwid( Widget cwid); static void CallActionCB( Widget cwid, XEvent *event); static void CallSelectCB( Widget wid, XEvent *event, unsigned char auto_selection_type); static WidgetList GetSelectedCwids( Widget wid); static void GetSelectedItems( Widget wid, int offset, XtArgVal *value); static int CompareInts( XmConst void *p1, XmConst void *p2); static int Isqrt( int n); static void GainPrimary( Widget wid, Time timestamp); static void ConvertRefuse( Widget wid, XtPointer closure, XmConvertCallbackStruct * cs); static void DragStart( XtPointer data, XtIntervalId * id); static void OutlineButtonCallback( Widget pbwid, XtPointer client_data, XtPointer call_data); static void OutlineButtonAction( Widget cwid, unsigned char new_state, XEvent *event); static void MoveItemCallback( Widget wid, XtPointer client_data, XtPointer call_data); static void DropDoneCallback( Widget wid, XtPointer client_data, XtPointer call_data); static void FreeLocationData( Widget wid, XtEnum op, XmTransferDoneCallbackStruct*); static Boolean SetupDrag( Widget wid, XEvent *event, String *params, Cardinal *num_params); static void CheckSetRenderTable( Widget wid, int offset, XrmValue *value); static void DefaultCollapsedPixmap( Widget wid, int offset, XrmValue * value); static void EnterHandler( Widget wid, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch); static void LeaveHandler( Widget wid, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch); static void ScrollProc( XtPointer closure, XtIntervalId* id); static void ContainerResetDepths (XmContainerConstraint c); static Boolean ContainerIsDescendant (Widget containerChild, Widget newEntryParent); static void ContainerResequenceNodes(XmContainerWidget cw, Widget entryParent); /******** End Static Function Declarations ********/ static XtActionsRec actionsList[] = { {"ContainerBeginSelect", (XtActionProc) ContainerBeginSelect}, {"ContainerButtonMotion", (XtActionProc) ContainerButtonMotion}, {"ContainerEndSelect", (XtActionProc) ContainerEndSelect}, {"ContainerBeginToggle", (XtActionProc) ContainerBeginToggle}, {"ContainerEndToggle", (XtActionProc) ContainerEndToggle}, {"ContainerBeginExtend", (XtActionProc) ContainerBeginExtend}, {"ContainerEndExtend", (XtActionProc) ContainerEndExtend}, {"ContainerStartTransfer", (XtActionProc) ContainerStartTransfer}, {"ContainerEndTransfer", (XtActionProc) ContainerEndTransfer}, {"ContainerPrimaryCopy", (XtActionProc) ContainerPrimaryCopy}, {"ContainerPrimaryLink", (XtActionProc) ContainerPrimaryLink}, {"ContainerPrimaryMove", (XtActionProc) ContainerPrimaryMove}, {"ContainerCancel", (XtActionProc) ContainerCancel}, {"ContainerSelect", (XtActionProc) ContainerSelect}, {"ContainerExtend", (XtActionProc) ContainerExtend}, {"ContainerMoveCursor", (XtActionProc) ContainerMoveCursor}, {"ContainerExtendCursor", (XtActionProc) ContainerExtendCursor}, {"ContainerToggleMode", (XtActionProc) ContainerToggleMode}, {"ContainerSelectAll", (XtActionProc) ContainerSelectAll}, {"ContainerDeselectAll", (XtActionProc) ContainerDeselectAll}, {"ContainerActivate", (XtActionProc) ContainerActivate}, {"ContainerExpandOrCollapse", (XtActionProc) ContainerExpandOrCollapse}, {"ContainerNoop", (XtActionProc) ContainerNoop}, {"ContainerHandleBtn1Down", (XtActionProc) ContainerHandleBtn1Down}, {"ContainerHandleBtn1Motion", (XtActionProc) ContainerHandleBtn1Motion}, {"ContainerHandleBtn1Up", (XtActionProc) ContainerHandleBtn1Up}, {"ContainerHandleBtn2Down", (XtActionProc) ContainerHandleBtn2Down}, {"ContainerHandleBtn2Motion", (XtActionProc) ContainerHandleBtn2Motion}, {"ContainerHandleBtn2Up", (XtActionProc) ContainerHandleBtn2Up} }; static XtResource resources[] = { { XmNautomaticSelection,XmCAutomaticSelection, XmRAutomaticSelection,sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.automatic), XmRImmediate,(XtPointer)XmAUTO_SELECT}, { XmNcollapsedStatePixmap,XmCCollapsedStatePixmap,XmRDynamicPixmap, sizeof(Pixmap), XtOffsetOf(XmContainerRec, container.collapsed_state_pixmap), XmRCallProc, (XtPointer)DefaultCollapsedPixmap}, { XmNconvertCallback,XmCCallback,XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmContainerRec,container.convert_cb), XmRImmediate,(XtPointer)NULL}, { XmNdefaultActionCallback,XmCCallback,XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmContainerRec,container.default_action_cb), XmRImmediate,(XtPointer)NULL}, { XmNdestinationCallback,XmCCallback,XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmContainerRec,container.destination_cb), XmRImmediate,(XtPointer)NULL}, { XmNdetailColumnHeading,XmCDetailColumnHeading,XmRXmStringTable, sizeof(XmStringTable), XtOffsetOf(XmContainerRec,container.detail_heading), XmRImmediate,(XtPointer)NULL}, { XmNdetailColumnHeadingCount,XmCDetailColumnHeadingCount, XmRCardinal,sizeof(Cardinal), XtOffsetOf(XmContainerRec, container.detail_heading_count), XmRImmediate,(XtPointer)0}, { XmNdetailOrder,XmCDetailOrder,XmRCardinalList, sizeof(Cardinal *), XtOffsetOf(XmContainerRec,container.detail_order), XmRImmediate,(XtPointer)NULL}, { XmNdetailOrderCount,XmCDetailOrderCount,XmRCardinal, sizeof(Cardinal), XtOffsetOf(XmContainerRec,container.detail_order_count), XmRImmediate,(XtPointer)0}, { XmNdetailTabList,XmCDetailTabList,XmRTabList,sizeof(XmTabList), XtOffsetOf(XmContainerRec,container.detail_tablist), XmRImmediate,(XtPointer)NULL}, { XmNentryViewType,XmCEntryViewType,XmREntryViewType, sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.entry_viewtype), XmRImmediate,(XtPointer)XmANY_ICON}, { XmNexpandedStatePixmap,XmCExpandedStatePixmap,XmRDynamicPixmap, sizeof(Pixmap), XtOffsetOf(XmContainerRec, container.expanded_state_pixmap), XmRString,(XtPointer)"expanded"}, { XmNlargeCellHeight,XmCCellHeight,XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.large_cell_height), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNlargeCellWidth,XmCCellWidth,XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.large_cell_width), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNlayoutType,XmCLayoutType,XmRLayoutType, sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.layout_type), XmRImmediate,(XtPointer)XmSPATIAL}, { XmNmarginHeight,XmCMarginHeight,XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.margin_h), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNmarginWidth,XmCMarginWidth,XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.margin_w), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNoutlineButtonPolicy,XmCOutlineButtonPolicy, XmROutlineButtonPolicy,sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.ob_policy), XmRImmediate,(XtPointer)XmOUTLINE_BUTTON_PRESENT}, { XmNoutlineChangedCallback,XmCCallback,XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmContainerRec,container.outline_cb), XmRImmediate,(XtPointer)NULL}, { XmNoutlineColumnWidth,XmCOutlineColumnWidth,XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.first_col_width), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNoutlineIndentation,XmCOutlineIndentation,XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.outline_indent), XmRImmediate,(XtPointer)DEFAULT_INDENTATION}, { XmNoutlineLineStyle,XmCLineStyle,XmRLineStyle, sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.outline_sep_style), XmRImmediate,(XtPointer)XmSINGLE}, { XmNprimaryOwnership,XmCPrimaryOwnership,XmRPrimaryOwnership, sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.primary_ownership), XmRImmediate,(XtPointer)XmOWN_POSSIBLE_MULTIPLE}, { "pri.vate","Pri.vate",XmRBoolean, sizeof(Boolean), XtOffsetOf(XmContainerRec,container.first_change_managed), XmRImmediate, (XtPointer) False}, { XmNfontList,XmCFontList,XmRFontList, sizeof(XmRenderTable), XtOffsetOf(XmContainerRec,container.render_table), XmRCallProc, (XtPointer)CheckSetRenderTable}, { XmNrenderTable,XmCRenderTable,XmRRenderTable, sizeof(XmRenderTable), XtOffsetOf(XmContainerRec,container.render_table), XmRCallProc, (XtPointer)CheckSetRenderTable}, { XmNselectColor,XmCSelectColor,XmRSelectColor,sizeof(Pixel), XtOffsetOf(XmContainerRec,container.select_color), XmRImmediate,(XtPointer)XmREVERSED_GROUND_COLORS}, { XmNselectedObjects,XmCSelectedObjects,XmRWidgetList, sizeof(WidgetList), XtOffsetOf(XmContainerRec,container.selected_items), XmRImmediate,(XtPointer)NULL}, { XmNselectedObjectCount,XmCSelectedObjectCount,XmRInt, sizeof(int), XtOffsetOf(XmContainerRec, container.selected_item_count), XmRImmediate,(XtPointer)0}, { XmNselectionCallback,XmCCallback,XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmContainerRec,container.selection_cb), XmRImmediate,(XtPointer)NULL}, { XmNselectionPolicy,XmCSelectionPolicy,XmRSelectionPolicy, sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.selection_policy), XmRImmediate,(XtPointer)XmEXTENDED_SELECT}, { XmNselectionTechnique,XmCSelectionTechnique, XmRSelectionTechnique,sizeof(unsigned char), XtOffsetOf(XmContainerRec, container.selection_technique), XmRImmediate,(XtPointer)XmTOUCH_OVER}, { XmNsmallCellHeight,XmCCellHeight,XmRVerticalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.small_cell_height), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNsmallCellWidth,XmCCellWidth,XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.small_cell_width), XmRImmediate,(XtPointer)ZERO_DIM}, { XmNspatialIncludeModel,XmCSpatialIncludeModel, XmRSpatialIncludeModel,sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.include_model), XmRImmediate,(XtPointer)XmAPPEND}, { XmNspatialResizeModel,XmCSpatialResizeModel, XmRSpatialResizeModel,sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.resize_model), XmRImmediate,(XtPointer)XmGROW_MINOR}, { XmNspatialSnapModel,XmCSpatialSnapModel, XmRSpatialSnapModel,sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.snap_model), XmRImmediate,(XtPointer)XmNONE}, { XmNspatialStyle,XmCSpatialStyle,XmRSpatialStyle, sizeof(unsigned char), XtOffsetOf(XmContainerRec,container.spatial_style), XmRImmediate,(XtPointer)XmGRID}, }; static XmSyntheticResource syn_resources[] = { { XmNlargeCellHeight,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.large_cell_height), XmeFromVerticalPixels,XmeToVerticalPixels}, { XmNlargeCellWidth,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.large_cell_width), XmeFromHorizontalPixels,XmeToHorizontalPixels}, { XmNmarginHeight,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.margin_h), XmeFromVerticalPixels,XmeToVerticalPixels}, { XmNmarginWidth,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.margin_w), XmeFromHorizontalPixels,XmeToHorizontalPixels}, { XmNoutlineIndentation,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.outline_indent), XmeFromHorizontalPixels,XmeToHorizontalPixels}, { XmNselectedObjects,sizeof(WidgetList), XtOffsetOf(XmContainerRec,container.selected_items), GetSelectedItems,NULL}, { XmNsmallCellHeight,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.small_cell_height), XmeFromVerticalPixels,XmeToVerticalPixels}, { XmNsmallCellWidth,sizeof(Dimension), XtOffsetOf(XmContainerRec,container.small_cell_width), XmeFromHorizontalPixels,XmeToHorizontalPixels}, { XmNdetailColumnHeading, sizeof(XmStringTable), XtOffsetOf(XmContainerRec,container.detail_heading), GetDetailHeader, NULL}, { XmNdetailColumnHeadingCount, sizeof(Cardinal), XtOffsetOf(XmContainerRec, container.detail_heading_count), GetDetailHeaderCount, NULL}, { XmNoutlineColumnWidth, sizeof(Dimension), XtOffsetOf(XmContainerRec,container.first_col_width), GetOutlineColumnWidth, NULL}, }; /* The constraint resource list */ static XtResource constraints[] = { { XmNentryParent,XmCWidget,XmRWidget,sizeof(Widget), XtOffsetOf(XmContainerConstraintRec,container.entry_parent), XmRImmediate,(XtPointer)NULL}, { XmNoutlineState,XmCOutlineState,XmROutlineState, sizeof(unsigned char), XtOffsetOf(XmContainerConstraintRec,container.outline_state), XmRImmediate,(XtPointer)XmCOLLAPSED}, { XmNpositionIndex,XmCPositionIndex,XmRInt,sizeof(int), XtOffsetOf(XmContainerConstraintRec,container.position_index), XmRImmediate,(XtPointer)XmLAST_POSITION}, }; static XmManagerClassExtRec managerClassExtRec = { NULL, NULLQUARK, XmManagerClassExtVersion, sizeof(XmManagerClassExtRec), NULL, /* traversal_children */ ObjectAtPoint /* object_at_point */ }; externaldef( xmcontainerclassrec) XmContainerClassRec xmContainerClassRec = { /* CoreClassPart */ { (WidgetClass) &xmManagerClassRec, /* superclass */ "XmContainer", /* class_name */ sizeof(XmContainerRec), /* widget_size */ NULL, /* class_initialize */ ClassPartInitialize, /* class_initialize */ FALSE, /* class_inited */ Initialize, /* initialize */ NULL, /* initialize_hook */ XtInheritRealize, /* realize */ actionsList, /* actions */ XtNumber(actionsList), /* num_actions */ resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ XtExposeCompressMultiple, /* compress_exposure */ TRUE, /* compress_enterleave */ FALSE, /* visible_interest */ Destroy, /* destroy */ Resize, /* resize */ Redisplay, /* expose */ SetValues, /* set_values */ NULL, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback private */ defaultTranslations, /* tm_table */ QueryGeometry, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ }, /* Composite class fields */ { GeometryManager, /* geometry_manager */ ChangeManaged, /* change_managed */ XtInheritInsertChild, /* insert_child */ XtInheritDeleteChild, /* delete_child */ NULL, /* extension */ }, /* Constraint class fields */ { constraints, /* resource list */ XtNumber(constraints), /* num resources */ sizeof(XmContainerConstraintRec), /* constraint size */ ConstraintInitialize, /* init proc */ ConstraintDestroy, /* destroy proc */ ConstraintSetValues, /* set values proc */ NULL, /* extension */ }, /* XmManager class fields */ { traversalTranslations, /* translations */ syn_resources, /* get resources */ XtNumber(syn_resources), /* num get_resources */ NULL, /* get_cont_resources */ 0, /* num_get_cont_resources */ XmInheritParentProcess, /* parent_process */ (XtPointer)&managerClassExtRec, /* extension */ }, /* Container class fields */ { TestFitItem, /* test_fit_item */ PlaceItem, /* place_item */ RemoveItem, /* remove_item */ GetSpatialSize, /* get_spatial_size */ NULL, /* extension */ } }; externaldef( xmcontainerwidgetclass) WidgetClass xmContainerWidgetClass = (WidgetClass) &xmContainerClassRec; /* Transfer Trait record for Container */ static XmConst XmTransferTraitRec transferT = { 0, /* version */ (XmConvertCallbackProc) ContainerConvertProc, (XmDestinationCallbackProc) ContainerDestinationProc, (XmDestinationCallbackProc) ContainerDestPrehookProc, }; /* Trait record for ContainerT */ static XmConst XmContainerTraitRec containerT = { 0, /* version */ (XmContainerGetValuesProc) ContGetValues, }; /* TraversalControl Trait record for Container */ static XmConst XmTraversalControlTraitRec traversalControlT = { 0, /* version */ RedirectTraversal /* redirect */ }; /* Context for drag icon information */ static XContext dragIconInfoContext = 0; /* Data structure for drag icon info */ typedef struct _DragIconInfo { Widget state; Widget source; } DragIconInfoRec, *DragIconInfo; /************************************************************************ * GetDetailHeader ************************************************************************/ /*ARGSUSED*/ static void GetDetailHeader( Widget wid, int offset, /* unused */ XtArgVal *value) { XmContainerWidget cw = (XmContainerWidget) wid ; Widget icon_header ; Cardinal icon_detail_header_count, i ; XmStringTable detail_header = NULL, icon_detail_header ; XmString label_string ; /* If there is an icon_header, fetch the information out of it */ if ((icon_header = GetRealIconHeader(wid)) != NULL) { /* we get memory owned by IconG here */ XtVaGetValues (icon_header, XmNlabelString, &label_string, XmNdetail, &icon_detail_header, XmNdetailCount, &icon_detail_header_count, NULL); /* now we need to add the labelString itself, so malloc something in the Container itself. First free what is currently allocated. Last free is done in Destroy */ if (cw->container.cache_detail_heading) XtFree((char*)cw->container.cache_detail_heading) ; cw->container.cache_detail_heading = (XmStringTable) XtMalloc(sizeof(XmString) * (icon_detail_header_count + 1)) ; for (i=0; i < icon_detail_header_count; i++) cw->container.cache_detail_heading[i+1] = icon_detail_header[i] ; cw->container.cache_detail_heading[0] = label_string ; detail_header = cw->container.cache_detail_heading; /* app need not to free the returned array */ } else /* return real data set by the application, which we trust it ** has been maintaining */ detail_header = cw->container.detail_heading; *value = (XtArgVal)detail_header; } /************************************************************************ * GetDetailHeaderCount ************************************************************************/ /*ARGSUSED*/ static void GetDetailHeaderCount( Widget wid, int offset, /* unused */ XtArgVal *value) { Widget icon_header ; Cardinal detail_header_count = 0 ; /* If there is an icon_header, fetch the information out of it */ if ((icon_header = GetRealIconHeader(wid)) != NULL) { XtVaGetValues (icon_header, XmNdetailCount, &detail_header_count, NULL); detail_header_count += 1; /* +1 for the labelString itself */ } else { XmContainerWidget cw = (XmContainerWidget)wid; detail_header_count = cw->container.saved_detail_heading_count; } *value = (XtArgVal)detail_header_count; } /************************************************************************ * GetOutlineColumnWidth ************************************************************************/ /*ARGSUSED*/ static void GetOutlineColumnWidth( Widget wid, int offset, /* unused */ XtArgVal *value) { XmContainerWidget cw = (XmContainerWidget)wid; /* Send 0 if dynamic, real_first_col_width otherwise */ if (CtrIsDynamic(cw,FIRSTCW)) *value = (XtArgVal)0; else *value = (XtArgVal)cw->container.real_first_col_width; } /************************************************************************ * ClassPartInitialize (Core Method) ************************************************************************/ static void ClassPartInitialize( WidgetClass wc) { _XmFastSubclassInit(wc,XmCONTAINER_BIT); /* Allow inheritance for subclasses */ if (wc != xmContainerWidgetClass) { XmContainerClass this_class = (XmContainerClass)wc; XmContainerClass super = (XmContainerClass)wc; if (this_class->container_class.test_fit_item == XmInheritSpatialTestFitProc) this_class->container_class.test_fit_item = super->container_class.test_fit_item; if (this_class->container_class.place_item == XmInheritSpatialPlacementProc) this_class->container_class.place_item = super->container_class.place_item; if (this_class->container_class.remove_item == XmInheritSpatialRemoveProc) this_class->container_class.remove_item = super->container_class.remove_item; if (this_class->container_class.get_spatial_size == XmInheritSpatialGetSize) this_class->container_class.get_spatial_size = super->container_class.get_spatial_size; } XmeTraitSet((XtPointer)wc,XmQTtransfer,(XtPointer)&transferT); XmeTraitSet((XtPointer)wc,XmQTcontainer,(XtPointer)&containerT); XmeTraitSet((XtPointer)wc,XmQTtraversalControl,(XtPointer)&traversalControlT); } /************************************************************************ * Initialize (Core Method) ************************************************************************/ /*ARGSUSED*/ static void Initialize( Widget rw, Widget nw, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { XmContainerWidget ncw = (XmContainerWidget)nw; XmContainerWidget rcw = (XmContainerWidget)rw; int n, i; Arg wargs[10]; Atom targets[1]; XmScrollFrameTrait scrollFrameTrait; /* * Verify enumerated resources. */ if (!XmRepTypeValidValue(XmRID_AUTOMATIC_SELECTION, ncw->container.automatic,nw)) ncw->container.automatic = XmAUTO_SELECT; if (!XmRepTypeValidValue(XmRID_ENTRY_VIEW_TYPE, ncw->container.entry_viewtype,nw)) ncw->container.entry_viewtype = XmANY_ICON; if (!XmRepTypeValidValue(XmRID_SPATIAL_INCLUDE_MODEL, ncw->container.include_model,nw)) ncw->container.include_model = XmAPPEND; if (!XmRepTypeValidValue(XmRID_LAYOUT_TYPE, ncw->container.layout_type,nw)) ncw->container.layout_type = XmSPATIAL; if (!XmRepTypeValidValue(XmRID_LINE_STYLE, ncw->container.outline_sep_style,nw)) ncw->container.outline_sep_style = XmSINGLE; if (!XmRepTypeValidValue(XmRID_OUTLINE_BUTTON_POLICY, ncw->container.ob_policy,nw)) ncw->container.ob_policy = XmOUTLINE_BUTTON_PRESENT; if (!XmRepTypeValidValue(XmRID_SPATIAL_STYLE, ncw->container.spatial_style,nw)) ncw->container.spatial_style = XmGRID; if (!XmRepTypeValidValue(XmRID_PRIMARY_OWNERSHIP, ncw->container.primary_ownership,nw)) ncw->container.primary_ownership = XmOWN_POSSIBLE_MULTIPLE; if (!XmRepTypeValidValue(XmRID_SPATIAL_RESIZE_MODEL, ncw->container.resize_model,nw)) ncw->container.resize_model = XmGROW_MINOR; if (!XmRepTypeValidValue(XmRID_SELECTION_POLICY, ncw->container.selection_policy,nw)) ncw->container.selection_policy = XmEXTENDED_SELECT; if (!XmRepTypeValidValue(XmRID_SELECTION_TECHNIQUE, ncw->container.selection_technique,nw)) ncw->container.selection_technique = XmTOUCH_OVER; if (!XmRepTypeValidValue(XmRID_SPATIAL_SNAP_MODEL, ncw->container.snap_model,nw)) ncw->container.snap_model = XmNONE; /* * deal with XmNdetailOrder & XmNdetailOrderCount */ if (ncw->container.detail_order_count && ncw->container.detail_order) { ncw->container.detail_order = (Cardinal *) XtMalloc(sizeof(Cardinal) * ncw->container.detail_order_count); for (i=0; i < ncw->container.detail_order_count; i++) ncw->container.detail_order[i] = rcw->container.detail_order[i] ; } /* * Initialize internal variables. */ ncw->container.first_node = NULL; ncw->container.last_node = NULL; ncw->container.self = False; ncw->container.create_cwid_type = CONTAINER_ICON; ncw->container.toggle_pressed = False; ncw->container.extend_pressed = False; ncw->container.ob_pressed = False; ncw->container.cancel_pressed = False; ncw->container.kaddmode = (CtrPolicyIsMULTIPLE(ncw) || CtrPolicyIsSINGLE(ncw)); ncw->container.marquee_mode = !(CtrTechIsTOUCH_ONLY(ncw)); ncw->container.marquee_drawn = False; ncw->container.selection_state = XmSELECTED; ncw->container.anchor_cwid = NULL; ncw->container.have_primary = False; ncw->container.last_click_time = 0; ncw->container.selecting = False; ncw->container.dynamic_resource = 0L; ncw->container.cache_detail_heading = NULL; /* * Get default Font. */ if (ncw->container.render_table == NULL) { XmFontList defaultFont = NULL; defaultFont = XmeGetDefaultRenderTable(nw,XmLABEL_FONTLIST); ncw->container.render_table = XmFontListCopy(defaultFont); } else ncw->container.render_table = XmFontListCopy(ncw->container.render_table); /* * Copy XmTablist if set, otherwise, keep track that it's dynamic. */ if (ncw->container.detail_tablist == NULL) ncw->container.dynamic_resource |= TABLIST; if (ncw->container.detail_tablist != NULL) ncw->container.detail_tablist = XmTabListCopy(ncw->container.detail_tablist,0,0); /* * Deal with setting of selectColor special cases */ if (ncw->container.select_color == XmDEFAULT_SELECT_COLOR) { XrmValue val; _XmSelectColorDefault(nw, 0, &val); ncw->container.select_color = *((Pixel*) val.addr); } else if (ncw->container.select_color == XmHIGHLIGHT_COLOR) { ncw->container.select_color = ncw->manager.highlight_color ; } /* * Initialize GCs */ ncw->container.normalGC = NULL; ncw->container.marqueeGC = NULL; UpdateGCs(nw); ncw->container.size_ob = NULL; SizeOutlineButton(nw); /* this flag is used during: expansion/collapse of outlinebutton to know if the first column can grow/shrink. If it was set, it can't, otherwise, a default is calculated whenever changemanaged is called and it is updated when state of expansion change. We need to mark the first col resource so that any change is caught during setvalues */ if (ncw->container.first_col_width == 0) ncw->container.dynamic_resource |= FIRSTCW; ncw->container.real_first_col_width = ncw->container.first_col_width ; ncw->container.first_col_width = INVALID_DIMENSION ; ncw->container.saved_detail_heading_count = 0 ; ncw->container.icon_header = NULL; if ((ncw->container.detail_heading_count && !ncw->container.detail_heading) || (!ncw->container.detail_heading_count && ncw->container.detail_heading)) { XmeWarning ((Widget) ncw, MESSAGE1); } if (ncw->container.detail_heading_count > 0) { /* if detail heading resources specified, create icon_header */ if (ncw->container.detail_heading) { /* and point to right sized array ! */ CreateIconHeader(nw); /* ncw->container.icon_header is a DA iff we are in the automatic SW case. ncw->container.icon_header is created unmanaged */ if (CtrLayoutIsDETAIL(ncw)) XtManageChild(ncw->container.icon_header); else XtUnmanageChild(ncw->container.icon_header); } /* saved the heading count in case the heading is set later on. */ ncw->container.saved_detail_heading_count = ncw->container.detail_heading_count; /* mark the detail_heading_count as invalid so that any change will be trapped by SetValues */ ncw->container.detail_heading_count = INVALID_COUNT ; } ncw->container.max_depth = 0; ncw->container.outline_segs = NULL; ncw->container.outline_seg_count = 0; /* * Register as Drop site. */ n = 0; targets[0] = XInternAtom(XtDisplay(nw),XmS_MOTIF_DRAG_OFFSET,False); XtSetArg(wargs[n],XmNimportTargets,targets); n++; XtSetArg(wargs[n],XmNnumImportTargets,1); n++; XmeDropSink(nw,wargs,n); ncw->container.drag_context = (Widget) NULL; ncw->container.transfer_action = NULL; ncw->container.transfer_timer_id = 0; /* * Initialize prev width for Resize calculations * & first_change_managed for initial sizing calculations. */ ncw->container.prev_width = 0; ncw->container.first_change_managed = True; /* * Initialize GRID/CELLS */ ncw->container.cells = NULL; ncw->container.cell_count = 0; ncw->container.next_free_cell = 0; ncw->container.current_width_in_cells = 0; ncw->container.current_height_in_cells = 0; ncw->container.cells_region = XCreateRegion(); /* * Set Cell sizes. */ ncw->container.large_cell_dim_fixed = ((ncw->container.large_cell_height > 0) && (ncw->container.large_cell_width > 0)); ncw->container.small_cell_dim_fixed = ((ncw->container.small_cell_height > 0) && (ncw->container.small_cell_width > 0)); SetCellSizes(nw); /* * init auto scroll related data */ scrollFrameTrait = (XmScrollFrameTrait) XmeTraitGet((XtPointer)XtClass(XtParent(nw)),XmQTscrollFrame); if (scrollFrameTrait && (scrollFrameTrait->getInfo(XtParent(nw),NULL,NULL,NULL))) { XtAddEventHandler(nw, EnterWindowMask, False, EnterHandler, NULL); XtAddEventHandler(nw, LeaveWindowMask, False, LeaveHandler, NULL); } ncw->container.scroll_proc_id = 0; ncw->container.LeaveDir = 0; } /************************************************************************ * Destroy (Core Method) ************************************************************************/ static void Destroy( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; XmScrollFrameTrait scrollFrameTrait = (XmScrollFrameTrait) XmeTraitGet((XtPointer)XtClass(XtParent(wid)),XmQTscrollFrame); XmFontListFree(cw->container.render_table); XtReleaseGC(wid,cw->container.normalGC); XtReleaseGC(wid,cw->container.marqueeGC); if (cw->container.transfer_timer_id != 0) XtRemoveTimeOut(cw->container.transfer_timer_id); /* free the detail_heading array that might have been allocated during a getvalues */ if (cw->container.cache_detail_heading) XtFree((char*)cw->container.cache_detail_heading); if (cw->container.detail_order_count && cw->container.detail_order) { XtFree((char*)cw->container.detail_order); } if (cw->container.detail_tablist) XmTabListFree(cw->container.detail_tablist); if (cw->container.outline_segs) XtFree((char*)cw->container.outline_segs); if (cw->container.cells) XtFree((char*)cw->container.cells); XDestroyRegion(cw->container.cells_region); if (scrollFrameTrait) { /* only destroy the icon_header if not a child of the Container, the auto SW/DA case */ assert (XtParent(cw->container.icon_header) != wid); /* that will destroy the icon header child as well */ XtDestroyWidget(cw->container.icon_header); } /* else the icon_header is a child of the container and is ** already destroyed (which is why we can't refer to it until we ** know its lineage) */ if (cw->container.scroll_proc_id) XtRemoveTimeOut(cw->container.scroll_proc_id); } /************************************************************************ * Resize (Core Method) ************************************************************************/ static void Resize( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; /* * The Outline layout is oblivious to size constraints * in the Left-to-Right layout direction. */ if (CtrLayoutIsOUTLINE_DETAIL(cw) && (!CtrLayoutIsDETAIL(cw)) && (!LayoutIsRtoLM(cw))) return; /* * One-dimensional Right-to_Left layouts are oblivious to * height changes; so, just return if the width hasn't changed. */ if (CtrLayoutIsOUTLINE_DETAIL(cw) && (cw->core.width == cw->container.prev_width)) return; /* * Save the current width for next time and reLayout. */ cw->container.prev_width = cw->core.width; cw->container.self = True; Layout(wid); cw->container.self = False; /* * Outline lines will be moved in response to width change in a * Right-to_Left Outline Layout. Better clear everything to erase * the old lines. Also, details may be redrawn. */ if (CtrLayoutIsOUTLINE_DETAIL(cw)) if (XtIsRealized((Widget)cw)) XClearArea(XtDisplay((Widget)cw),XtWindow((Widget)cw),0,0,0,0,True); } /************************************************************************ * Redisplay (Core Method) * Special care must be taken to redraw the marquee which is drawn in XOR * mode. Normaly we should only need to draw the marquee with a clip * rectangle equal to the expose region. However, the XmIconGadgets do not * perform clipped redraw and redraw themselves entirely instead, because * its a pain to deal with both a clip rectangle and a possible clip mask. * So to avoid any problem, we must fully erase the marquee and then * redraw it. ************************************************************************/ static void Redisplay( Widget wid, XEvent *event, Region region) { XmContainerWidget cw = (XmContainerWidget)wid; /* Erase the marquee if there is any */ if (cw->container.marquee_drawn) { DrawMarquee(wid); XSetRegion(XtDisplay(wid), cw->container.normalGC, region); XSetForeground(XtDisplay(wid), cw->container.normalGC, cw->core.background_pixel); XFillRectangle(XtDisplay(wid), XtWindow(wid), cw->container.normalGC, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); XSetClipMask(XtDisplay(wid), cw->container.normalGC, None); XSetForeground(XtDisplay(wid), cw->container.normalGC, cw->manager.foreground); } /* * If lines are present & we're in outline layout, draw the lines. */ if (CtrDrawLinesOUTLINE(cw) && (cw->container.outline_seg_count > 0)) { XSetClipMask(XtDisplay(wid), cw->container.normalGC, None); XDrawSegments(XtDisplay(wid),XtWindow(wid), cw->container.normalGC, cw->container.outline_segs, cw->container.outline_seg_count); } /* * Redisplay all affected gadgets. */ XmeRedisplayGadgets(wid,event,region); /* Redraw marquee when needed */ if (cw->container.marquee_drawn) DrawMarquee(wid); } /************************************************************************ * SetValues (Core Method) ************************************************************************/ /*ARGSUSED*/ static Boolean SetValues( Widget cw, Widget rw, /* unused */ Widget nw, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { XmContainerWidget ccw = (XmContainerWidget)cw; XmContainerWidget ncw = (XmContainerWidget)nw; Boolean container_need_layout = False; Boolean spatial_need_layout = False; Boolean outline_need_layout = False; Boolean detail_need_layout = False; Boolean need_expose = False; CwidNode node; Widget cwid; XmContainerConstraint c; XPoint snap_point; int i; ncw->container.self = True; /* * Verify enumerated resources. */ if (ncw->container.automatic != ccw->container.automatic) { if (!XmRepTypeValidValue(XmRID_AUTOMATIC_SELECTION, ncw->container.automatic,nw)) ncw->container.automatic = ccw->container.automatic; } if (ncw->container.entry_viewtype != ccw->container.entry_viewtype) { if (!XmRepTypeValidValue(XmRID_ENTRY_VIEW_TYPE, ncw->container.entry_viewtype,nw)) ncw->container.entry_viewtype = ccw->container.entry_viewtype; } if (ncw->container.include_model != ccw->container.include_model) { if (!XmRepTypeValidValue(XmRID_SPATIAL_INCLUDE_MODEL, ncw->container.include_model,nw)) ncw->container.include_model = ccw->container.include_model; } if (ncw->container.layout_type != ccw->container.layout_type) { if (!XmRepTypeValidValue(XmRID_LAYOUT_TYPE, ncw->container.layout_type,nw)) ncw->container.layout_type = ccw->container.layout_type; } if (ncw->container.outline_sep_style != ccw->container.outline_sep_style) { if (!XmRepTypeValidValue(XmRID_LINE_STYLE, ncw->container.outline_sep_style,nw)) ncw->container.outline_sep_style = ccw->container.outline_sep_style; } if (ncw->container.ob_policy != ccw->container.ob_policy) { if (!XmRepTypeValidValue(XmRID_OUTLINE_BUTTON_POLICY, ncw->container.ob_policy,nw)) ncw->container.ob_policy = ccw->container.ob_policy; } if (ncw->container.spatial_style != ccw->container.spatial_style) { if (!XmRepTypeValidValue(XmRID_SPATIAL_STYLE, ncw->container.spatial_style,nw)) ncw->container.spatial_style = ccw->container.spatial_style; } if (ncw->container.primary_ownership != ccw->container.primary_ownership) { if (!XmRepTypeValidValue(XmRID_PRIMARY_OWNERSHIP, ncw->container.primary_ownership,nw)) ncw->container.primary_ownership = ccw->container.primary_ownership; } if (ncw->container.resize_model != ccw->container.resize_model) { if (!XmRepTypeValidValue(XmRID_SPATIAL_RESIZE_MODEL, ncw->container.resize_model,nw)) ncw->container.resize_model = ccw->container.resize_model; } if (ncw->container.selection_policy != ccw->container.selection_policy) { if (!XmRepTypeValidValue(XmRID_SELECTION_POLICY, ncw->container.selection_policy,nw)) ncw->container.selection_policy = ccw->container.selection_policy; } if (ncw->container.selection_technique != ccw->container.selection_technique) { if (!XmRepTypeValidValue(XmRID_SELECTION_TECHNIQUE, ncw->container.selection_technique,nw)) ncw->container.selection_technique = ccw->container.selection_technique; } if (ncw->container.snap_model != ccw->container.snap_model) { if (!XmRepTypeValidValue(XmRID_SPATIAL_SNAP_MODEL, ncw->container.snap_model,nw)) ncw->container.snap_model = ccw->container.snap_model; } if (ncw->container.render_table == NULL) { XmFontList defaultFont = NULL; defaultFont = XmeGetDefaultRenderTable(nw,XmLABEL_FONTLIST); ncw->container.render_table = XmFontListCopy(defaultFont); } else ncw->container.render_table = XmFontListCopy(ncw->container.render_table); if (ccw->container.render_table) XmRenderTableFree(ccw->container.render_table); /* * Check if we'll need layout. * we update 4 differents boolean and at the end we * decide if relayout is actually needed. */ if (ncw->container.layout_type != ccw->container.layout_type) { if (CtrLayoutIsSPATIAL(ncw) && CtrSpatialStyleIsNONE(ncw)) need_expose = True; else container_need_layout = True; } if (ncw->manager.string_direction != ccw->manager.string_direction) container_need_layout = True; if ((ncw->container.margin_h != ccw->container.margin_h) || (ncw->container.margin_w != ccw->container.margin_w)) container_need_layout = True; if ((ncw->container.spatial_style != ccw->container.spatial_style) && (!(CtrLayoutIsSPATIAL(ncw) && CtrSpatialStyleIsNONE(ncw)))) spatial_need_layout = True; /* * Change all IconGadget children's XmNentryType to match */ if ((ncw->container.entry_viewtype != ccw->container.entry_viewtype) && (ncw->container.entry_viewtype != XmANY_ICON)) { ChangeView(nw,ncw->container.entry_viewtype); container_need_layout = True; } else { /* * If we're changing to XmSPATIAL from XmDETAIL || XmOUTLINE we need to * resize the Icons so they get rid of their "detail" room. */ if (CtrLayoutIsSPATIAL(ncw) && !CtrLayoutIsSPATIAL(ccw)) { XtWidgetGeometry desired; node = ncw->container.first_node; while (node) { cwid = node->widget_ptr; /* * Get and set preferred size */ XtQueryGeometry(cwid, NULL, &desired); XmeConfigureObject(cwid,cwid->core.x,cwid->core.y, desired.width,desired.height,0); /* * Get the next cwid, whether it's managed or not */ node = node->next_ptr; } } } if ((ncw->container.entry_viewtype != ccw->container.entry_viewtype) && ((ncw->container.entry_viewtype == XmSMALL_ICON) || (ccw->container.entry_viewtype == XmSMALL_ICON))) { ncw->container.current_width_in_cells = 0; ncw->container.current_height_in_cells = 0; spatial_need_layout = True; } if (CtrLayoutIsSPATIAL(ncw) && !CtrSpatialStyleIsNONE(ncw) && (CtrViewIsLARGE_ICON(ncw) || CtrViewIsANY_ICON(ncw))) { if ((ncw->container.large_cell_width != ccw->container.large_cell_width) && (ncw->container.large_cell_width == 0)) ncw->container.large_cell_dim_fixed = False; if ((ncw->container.large_cell_height != ccw->container.large_cell_height) && (ncw->container.large_cell_height == 0)) ncw->container.large_cell_dim_fixed = False; SetCellSizes(nw); if ((ncw->container.real_large_cellw != ccw->container.real_large_cellw) || (ncw->container.real_large_cellh != ccw->container.real_large_cellh)) { ncw->container.current_width_in_cells = 0; ncw->container.current_height_in_cells = 0; spatial_need_layout = True; } } if (CtrLayoutIsSPATIAL(ncw) && !CtrSpatialStyleIsNONE(ncw) && CtrViewIsSMALL_ICON(ncw)) { if ((ncw->container.small_cell_width != ccw->container.small_cell_width) && (ncw->container.small_cell_width == 0)) ncw->container.small_cell_dim_fixed = False; if ((ncw->container.small_cell_height != ccw->container.small_cell_height) && (ncw->container.small_cell_height == 0)) ncw->container.small_cell_dim_fixed = False; SetCellSizes(nw); if ((ncw->container.real_small_cellw != ccw->container.real_small_cellw) || (ncw->container.real_small_cellh != ccw->container.real_small_cellh)) { ncw->container.current_width_in_cells = 0; ncw->container.current_height_in_cells = 0; spatial_need_layout = True; } } /* * Deal with setting of special selectColor values. * No need to check for a change since if select_color is one of * the special value, it is always a change - only pixel * could have been there at that point in time */ if (ncw->container.select_color == XmDEFAULT_SELECT_COLOR) { XrmValue val; _XmSelectColorDefault(nw, 0, &val); ncw->container.select_color = *((Pixel*) val.addr); /* must notify the children at this point */ need_expose |= _XmNotifyChildrenVisual (cw, nw, VisualSelectColor); } else if (ncw->container.select_color == XmHIGHLIGHT_COLOR) { ncw->container.select_color = ncw->manager.highlight_color ; /* must notify the children at this point */ need_expose |= _XmNotifyChildrenVisual (cw, nw, VisualSelectColor); } /* * Hide all non-level-0 children if we've switched to SPATIAL layout. */ if (CtrLayoutIsSPATIAL(ncw) && !CtrLayoutIsSPATIAL(ccw)) { for (i = 0; i < ncw->composite.num_children; i++) { cwid = ncw->composite.children[i]; c = GetContainerConstraint(cwid); if (!CtrICON(cwid) || (c->entry_parent)) HideCwid(cwid); } } if ((ncw->container.collapsed_state_pixmap != ccw->container.collapsed_state_pixmap) || (ncw->container.expanded_state_pixmap != ccw->container.expanded_state_pixmap)) { /* compute the size of the new outline buttons */ SizeOutlineButton(nw); /* if the size has change, mark it for relayout */ if ((ncw->container.ob_width != ccw->container.ob_width) || (ncw->container.ob_height != ccw->container.ob_height)) outline_need_layout = True; /* update all the buttons */ ChangeOutlineButtons(nw); } /* * just Redisplay, if line style has changed. */ if (CtrLayoutIsOUTLINE_DETAIL(ncw) && (ncw->container.outline_sep_style != ccw->container.outline_sep_style)) need_expose = True; /* * Recalculate FirstColWidth. * */ if (ncw->container.first_col_width != ccw->container.first_col_width) { if (!ncw->container.first_col_width) { ncw->container.dynamic_resource |= FIRSTCW; } else { ncw->container.dynamic_resource &= ~FIRSTCW; ncw->container.real_first_col_width = ncw->container.first_col_width ; } outline_need_layout = True ; ncw->container.first_col_width = INVALID_DIMENSION ; } if ((ncw->container.ob_width != ccw->container.ob_width) || (ncw->container.outline_indent != ccw->container.outline_indent) || (ncw->container.ob_policy != ccw->container.ob_policy)) outline_need_layout = True ; /* * deal with XmNdetailTabList */ if ((ncw->container.detail_tablist != ccw->container.detail_tablist)) { detail_need_layout = True ; if (ccw->container.detail_tablist) XmTabListFree(ccw->container.detail_tablist) ; if (ncw->container.detail_tablist == NULL) ncw->container.dynamic_resource |= TABLIST; else ncw->container.dynamic_resource &= ~TABLIST; if (ncw->container.detail_tablist != NULL) ncw->container.detail_tablist = XmTabListCopy(ncw->container.detail_tablist,0,0); } /* * deal with XmNdetailOrder & XmNdetailOrderCount changes */ if ((ncw->container.detail_order != ccw->container.detail_order) || (ncw->container.detail_order_count != ccw->container.detail_order_count)) { detail_need_layout = True ; if (ccw->container.detail_order_count && ccw->container.detail_order) { XtFree((char*)ccw->container.detail_order) ; } if (ncw->container.detail_order_count && ncw->container.detail_order) { Cardinal * detail_order ; detail_order = (Cardinal *) XtMalloc(sizeof(Cardinal) * ncw->container.detail_order_count); for (i=0; i < ncw->container.detail_order_count; i++) detail_order[i] = ncw->container.detail_order[i] ; ncw->container.detail_order = detail_order ; } } /* * Reset cell/placed info if Spatial Layout options * have changed. */ if (CtrLayoutIsSPATIAL(ncw) && ((ncw->container.layout_type != ccw->container.layout_type) || (ncw->container.spatial_style != ccw->container.spatial_style))) { if (((XmContainerWidgetClass)XtClass(ncw))->container_class.place_item) (*((XmContainerWidgetClass) XtClass(ncw))->container_class.place_item)(nw,NULL,ANY_FIT); need_expose = True; } /* * Set selected items, if necessary. */ if ((ncw->container.selected_item_count != ccw->container.selected_item_count) || (ncw->container.selected_items != ccw->container.selected_items)) { int save_item_count; save_item_count = ncw->container.selected_item_count; ncw->container.selected_item_count = ccw->container.selected_item_count; DeselectAllCwids(nw); /* ncw->container.selected_item_count = 0 */ if (ncw->container.selected_items != NULL) { for (i = 0; i < save_item_count; i++) /* MarkCwid increments ncw->container.selected_item_count */ MarkCwid(ncw->container.selected_items[i],False); ncw->container.selected_items = NULL; } need_expose = True; } /* * Change GC's, if necessary. */ if ((ncw->manager.foreground != ccw->manager.foreground) || (ncw->core.background_pixel != ccw->core.background_pixel)) UpdateGCs(nw); { /* ** Deal with heading change ** ** There are two resources which affect whether or not the icon header ** is created and what is in it (not visibility): XmNdetailColumnHeading ** and XmNdetailColumnHeadingCount. The icon header is created if and ** only if we have string data in detail_heading and a positive !0 count ** in detail_heading_count. That much is simple. Complicating the issue ** (and necessary to preserve for compatibilty with subclasses) is the ** attempt both to catch a widget creation/destruction sequence in ** which the widget data happens to be at the same address and also to ** catch the case in which one of the resources is set without the ** other; the idea is that the detail_heading_count is marked invalid ** and the real value is moved out to a cached space in the widget ** record. (An earlier scheme which did similar things to the ** detail_heading field was removed when it became clear that the ** memory-management issues were impossible to track correctly.) ** (This scheme works except in the case in which the user has set a ** new real count to be higher than the number of strings in the ** existing string table; however, this can be considered user error, ** as it is for other cases in which widgets use combined list/number ** resource pairs rather than a resource which is a structure which ** contains the two values.) ** ** What this means is that detail_heading has the real values NULL ** and !NULL, and the transitions which are valid for it are between ** those two values. But detail_heading_count has three possible ** values: 0, which indicates that there has never been a count ** assigned, or indicates that the current count is 0; INVALID_COUNT, ** which indicates that a real value has been set and that that value ** is now in saved_detail_heading_count; and some other non-zero value, ** which is a new value coming into this routine or into Initialize. ** Valid transitions are as usual, with INVALID_COUNT taking the place ** of regular !0 values. Note that the transition to 0 is valid. ** ** At the end of the block, detail_heading is of course either NULL or ** !NULL and detail_heading_count is either 0 or INVALID_COUNT. The ** icon header exists when there is a valid count, either in this ** iteration or previously set, and valid data. We don't care whether ** or not the icon header is to be displayed; just indicate whether it ** was changed so that we know whether we need a relayout. */ #define NONE_CHANGED 0 #define COUNT_CHANGED (1<<0) #define HEADING_CHANGED (1<<1) unsigned char whichChanged = NONE_CHANGED; #define NONE_VALID 0 #define COUNT_VALID (1<<0) #define HEADING_VALID (1<<1) #define BOTH_VALID (COUNT_VALID | HEADING_VALID) unsigned char whichValid = NONE_VALID; if (ncw->container.detail_heading != ccw->container.detail_heading) whichChanged |= HEADING_CHANGED; if ((INVALID_COUNT != ncw->container.detail_heading_count) && (ncw->container.detail_heading_count != ncw->container.saved_detail_heading_count)) whichChanged |= COUNT_CHANGED; if (NONE_CHANGED != whichChanged) { if (ncw->container.detail_heading != NULL) whichValid |= HEADING_VALID; if (HEADING_VALID & whichValid) { if (HEADING_CHANGED & whichChanged) { /* We have a new set of heading strings. ** If we have a heading but the count is invalid, then we ** need to fetch it from one of the caches, so that the ** user can set the heading and the count in separate ** set-values invocations (really, we could just store the ** value where it goes, except that we want to track a ** change in the count in a memory-reuse case) */ if (INVALID_COUNT == ncw->container.detail_heading_count) { if (ncw->container.icon_header) { XtVaGetValues(GetRealIconHeader(nw), XmNdetailCount, &(ncw->container.detail_heading_count), NULL); /* the labelString takes detail_heading[0] */ ncw->container.detail_heading_count++; } else ncw->container.detail_heading_count = ncw->container.saved_detail_heading_count; } /* else we will use whatever value has been ** set -- either 0 or a new value */ } /* else use existing set of strings below; count must ** have changed */ } /* else if now NULL will result in destruction below */ /* changing a count without a valid heading doesn't require any work; ** in fact, we don't need to track a change to the count -- we just ** care about the current value or the value reconstructed above. */ if ( (ncw->container.detail_heading_count != 0) && (INVALID_COUNT != ncw->container.detail_heading_count) ) whichValid |= COUNT_VALID; if (BOTH_VALID == (BOTH_VALID & whichValid)) { /* we have valid data, and at least one resource changed */ /* we need an icon header; either create or update it */ assert(ncw->container.detail_heading); assert(ncw->container.detail_heading_count); assert(INVALID_COUNT != ncw->container.detail_heading_count); if (ccw->container.icon_header == NULL) CreateIconHeader(nw); else { /* pass False if there was a change in the strings as well ** as the count, True if it's only a change in the detail ** heading count. */ UpdateIconHeader(nw, (HEADING_CHANGED & whichChanged) ? False : True); } if (CtrLayoutIsDETAIL(ncw)) { assert(ncw->container.icon_header); XtManageChild(ncw->container.icon_header); /* may be redundant if this is a new state */ detail_need_layout = True; } } else { /* we need no icon header; if it existed, destroy it */ if (ncw->container.icon_header) { XtDestroyWidget(ncw->container.icon_header); ncw->container.icon_header = NULL; if (CtrLayoutIsDETAIL(ncw)) detail_need_layout = True; /* may be redundant if this is a new state */ } } if (INVALID_COUNT != ncw->container.detail_heading_count) /* including 0 */ ncw->container.saved_detail_heading_count = ncw->container.detail_heading_count; if (COUNT_VALID & whichValid) ncw->container.detail_heading_count = INVALID_COUNT; /* else if it is 0 don't do anything -- let value stay; the ** saved value is either 0 or a real !0 value but cannot be ** INVALID_COUNT */ } /* else no change to either, so just continue with SetValues code */ #undef NONE_CHANGED #undef COUNT_CHANGED #undef HEADING_CHANGED #undef NONE_VALID #undef COUNT_VALID #undef HEADING_VALID } if (CtrLayoutIsDETAIL(ncw) && !CtrLayoutIsDETAIL(ccw) && (ncw->container.icon_header != NULL)) { detail_need_layout = True ; XtManageChild(ncw->container.icon_header); } if (!CtrLayoutIsDETAIL(ncw) && CtrLayoutIsDETAIL(ccw) && (ncw->container.icon_header)) { outline_need_layout = True ; XtUnmanageChild(ncw->container.icon_header); if (XtParent(ncw->container.icon_header) != nw) { Widget real_icon_header = GetRealIconHeader(nw); /* reposition the container itself too */ nw->core.y -= real_icon_header->core.height ; } } /* * Update header margins, only if we are in the detail SW case * where the container.icon_header is the DA. */ if ((ncw->container.margin_w != ccw->container.margin_w) || (ncw->container.margin_h != ccw->container.margin_h) || (ncw->manager.foreground != ccw->manager.foreground) || (ncw->core.border_width != ccw->core.border_width) || (ncw->core.background_pixel != ccw->core.background_pixel) || (ncw->container.layout_type != ccw->container.layout_type) || (ncw->core.background_pixmap != ccw->core.background_pixmap)) { if ((CtrLayoutIsDETAIL(ncw)) && (ncw->container.icon_header) && (XtParent(ncw->container.icon_header) != nw)) { Widget real_icon_header = GetRealIconHeader(nw); /* we need to update the margin on the DA, resize it and reposition the container. */ /* if (0 == nw->core.y) */ nw->core.y = real_icon_header->core.height ; XtVaSetValues(ncw->container.icon_header, XmNmarginWidth, ncw->container.margin_w, XmNmarginHeight, ncw->container.margin_h, XmNbackground, ncw->core.background_pixel, XmNbackgroundPixmap, ncw->core.background_pixmap, XmNforeground, ncw->manager.foreground, NULL); XmeConfigureObject(ncw->container.icon_header, /* the DA */ ncw->container.icon_header->core.x, ncw->container.icon_header->core.y, real_icon_header->core.width + 2*ncw->container.margin_w, real_icon_header->core.height + ncw->container.margin_h, ncw->core.border_width); } } /* need also the check for change in borderPixel, borderPixmap... */ /* * Set internal variables that are based on resource values. */ if (ncw->container.selection_policy != ccw->container.selection_policy) ncw->container.kaddmode = (CtrPolicyIsMULTIPLE(ncw) || CtrPolicyIsSINGLE(ncw)); if (ncw->container.selection_technique != ccw->container.selection_technique) ncw->container.marquee_mode = (CtrTechIsTOUCH_ONLY(ncw) ? False : True); /** perform some logic */ spatial_need_layout |= container_need_layout ; outline_need_layout |= container_need_layout ; detail_need_layout |= outline_need_layout ; if (CtrLayoutIsSPATIAL(ncw) && !CtrSpatialStyleIsNONE(ncw) && !spatial_need_layout && (ncw->container.snap_model != ccw->container.snap_model)) { node = GetFirstNode(ncw); while (node) { (void)SnapCwid(node->widget_ptr, node->widget_ptr->core.x, node->widget_ptr->core.y, &snap_point); XmeConfigureObject(node->widget_ptr, snap_point.x,snap_point.y, node->widget_ptr->core.width,node->widget_ptr->core.height,0); node = GetNextNode(node); } need_expose = True ; } if (((CtrLayoutIsOUTLINE_DETAIL(ncw) && outline_need_layout) || (CtrLayoutIsDETAIL(ncw) && detail_need_layout) || (CtrLayoutIsSPATIAL(ncw) && spatial_need_layout))) { XmClipWindowTrait clipWindowTrait; XmScrollFrameTrait scrollFrameTrait; Widget swparent; /* get our preferred size first */ ncw->container.ideal_width = 0; ncw->container.ideal_height = 0; GetSize(nw,&ncw->container.ideal_width,&ncw->container.ideal_height); ncw->core.width = ncw->container.ideal_width; ncw->core.height = ncw->container.ideal_height; Layout(nw); /* * update any scrolled window above to reflect a new original * y coordinate - CDExc19939 & CDExc23393 */ /* find a scrolled window*/ swparent = XtParent(ncw); clipWindowTrait = (XmClipWindowTrait) XmeTraitGet((XtPointer) XtClass(swparent), _XmQTclipWindow); if (clipWindowTrait != NULL) swparent = XtParent(swparent); scrollFrameTrait = (XmScrollFrameTrait) XmeTraitGet((XtPointer) XtClass(swparent), XmQTscrollFrame); /* if we have one, update the geom */ if (scrollFrameTrait != NULL && scrollFrameTrait->version >= 1 && scrollFrameTrait->getInfo(swparent, NULL, NULL, NULL) && scrollFrameTrait->updateOrigGeom != NULL) { XtWidgetGeometry preferred; preferred.request_mode = CWY; preferred.y = ncw->core.y; scrollFrameTrait->updateOrigGeom(swparent, (Widget) ncw, &preferred); } need_expose = True ; } ncw->container.self = False; return(need_expose); } /* * XmRCallProc routine for checking font before setting it to NULL * if no value is specified for both XmNrenderTable and XmNfontList. * If "first_change_managed" is True, this function has been called * twice on same widget, thus * resource needs to be set NULL, otherwise * leave it alone. */ /*ARGSUSED*/ static void CheckSetRenderTable(Widget wid, int offset, XrmValue *value) { XmContainerWidget cw = (XmContainerWidget)wid; if (cw->container.first_change_managed) /* Been here before, so set resource = NULL */ value->addr = NULL; else { cw->container.first_change_managed = True; value->addr = (char*)&(cw->container.render_table); } } /* * XmRCallProc routine to determine the correct default collapsed * pixmap for this layout direction. */ /*ARGSUSED*/ static void DefaultCollapsedPixmap(Widget wid, int offset, XrmValue *value) { static Pixmap result; XmContainerWidget cw = (XmContainerWidget)wid; result = XmGetPixmapByDepth(XtScreen(wid), (LayoutIsRtoLM(cw) ? "collapsed_rtol" : "collapsed"), cw->manager.foreground, cw->core.background_pixel, cw->core.depth); value->size = sizeof(result); value->addr = (char *) &result; } /************************************************************************ * * QueryGeometry (Core Method) * ************************************************************************/ static XtGeometryResult QueryGeometry( Widget widget, XtWidgetGeometry *intended, XtWidgetGeometry *desired ) { /* deal with user initial size setting */ if (!XtIsRealized(widget)) { desired->width = XtWidth(widget) ; /* might be 0 */ desired->height = XtHeight(widget) ; /* might be 0 */ } else { /* always computes natural size afterwards */ desired->width = 0 ; desired->height = 0 ; } GetSize (widget, &desired->width, &desired->height); /* this function will set CWidth and CHeight */ return XmeReplyToQueryGeometry(widget, intended, desired) ; } /************************************************************************ * GetSize * * Updates the following container instance variables: * cw->container.ideal_width * cw->container.ideal_height * cw->container.first_column_width (if dynamic) ************************************************************************/ static void GetSize ( Widget wid, Dimension * pwidth, Dimension * pheight) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Widget cwid; XmContainerConstraint c; XtWidgetGeometry desired; XmTabList save_dynamic_tablist = NULL; Position save_x; if (CtrLayoutIsSPATIAL(cw)) /* * Get width & height from class method. */ { if (((XmContainerWidgetClass) XtClass(wid))->container_class.get_spatial_size) { (*((XmContainerWidgetClass) XtClass(wid))->container_class.get_spatial_size) (wid, pwidth, pheight); cw->container.ideal_width = *pwidth; cw->container.ideal_height = *pheight; } return; } /* * Calculate ideal width/height for OUTLINE/DETAIL. */ cw->container.ideal_width = 0; cw->container.ideal_height = cw->container.margin_h; /* * Find desired First Column width */ if (CtrIsDynamic(cw,FIRSTCW)) { cw->container.real_first_col_width = GetDynFirstColWidth(wid); } /* * Save the current dynamic tablist and set to NULL, so Icon's * response to QueryGeo will not be based on current width. */ if (CtrIsDynamic(cw,TABLIST)) { save_dynamic_tablist = cw->container.detail_tablist; cw->container.detail_tablist = NULL; } /* header first. */ if ((cwid = GetRealIconHeader(wid)) && (XtIsManaged(cwid)) && ((XtParent(cwid) == wid) || (XtIsManaged(XtParent(cwid))))) { XtQueryGeometry(cwid, NULL, &desired); save_x = cwid->core.x; cwid->core.x = MAX(0,cwid->core.x); cw->container.ideal_width = MAX(cw->container.ideal_width, cwid->core.x + desired.width); cw->container.ideal_height += desired.height; cwid->core.x = save_x; } /* then the icons */ node = GetFirstNode(cw); while(node) { cwid = node->widget_ptr; c = GetContainerConstraint(cwid); /* This query depends on the current first column width and the current x position. It assumes L to R, since the width/height would be the same. */ save_x = cwid->core.x; cwid->core.x = cw->container.margin_w + c->depth*cw->container.outline_indent + ((CtrOB_PRESENT(cw))?cw->container.ob_width:0) ; XtQueryGeometry(cwid, NULL, &desired); cw->container.ideal_width = MAX(cw->container.ideal_width, cwid->core.x + desired.width); cw->container.ideal_height += desired.height; cwid->core.x = save_x; node = GetNextNode(node); } cw->container.ideal_width += cw->container.margin_w; cw->container.ideal_height += cw->container.margin_h; /* Reset dynamic XmTabList, if necessary */ if (CtrIsDynamic(cw,TABLIST)) cw->container.detail_tablist = save_dynamic_tablist; /* here if we are in the dynamic first column case and in detail, with dynamic tablist, we want to grow up front by the amount of the difference between the old first column and the new one. In outline, that should happen automatacilly, but in detail, if tablist is dynamic, we have to compute it here. [ samborn, 25-MAY-1999 ] This used to be done in {Expand,Collapse}Cwid, but moved it here. The reason is that it needs to be applied to the ideal, not the current width in core. */ if (CtrLayoutIsDETAIL(cw) && CtrIsDynamic(cw,TABLIST)) { cw->container.ideal_width += cw->container.real_first_col_width; } if (!(*pwidth)) *pwidth = cw->container.ideal_width; if (!(*pheight)) *pheight = cw->container.ideal_height; } /************************************************************************ * GeometryManager (Composite Method) ************************************************************************/ /*ARGSUSED*/ static XtGeometryResult GeometryManager( Widget cwid, XtWidgetGeometry *desired, XtWidgetGeometry *allowed) /* unused */ { Widget wid = XtParent(cwid); XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c = GetContainerConstraint(cwid); Position save_x,save_y; Dimension save_width, save_height, save_border_width; unsigned char save_include_model; /* * Position and changes always allowed for spatial None */ if (CtrSpatialStyleIsNONE(cw)) { /* Move the child and save the original positions */ if (desired->request_mode & CWX) { cwid->core.x = desired->x; } if (desired->request_mode & CWY) { cwid->core.y = desired->y; } if (desired->request_mode & CWWidth) { cwid->core.width = desired->width; } if (desired->request_mode & CWHeight) { cwid->core.height = desired->height; } if (desired->request_mode & CWBorderWidth) { cwid->core.border_width = desired->border_width; } /* Request new size */ RequestSpatialGrowth(wid, cwid); return(XtGeometryYes); } /* * Called from inside Container (ChangeView routine) * Container will resize later, so do the job and * return XtGeometryYes. */ if (cw->container.self || /* No Spatial Layout methods? or not placed? or spatialStyleNONE? * Do whatever it wants. */ (!(((XmContainerWidgetClass)XtClass(wid))-> container_class.remove_item)) || (!(((XmContainerWidgetClass)XtClass(wid))-> container_class.place_item)) || (!CtrItemIsPlaced(cwid))) { if (desired->request_mode & CWX) cwid->core.x = desired->x; if (desired->request_mode & CWY) cwid->core.y = desired->y; if (desired->request_mode & CWWidth) cwid->core.width = desired->width; if (desired->request_mode & CWHeight) cwid->core.height = desired->height; if (desired->request_mode & CWBorderWidth) cwid->core.border_width = desired->border_width; return(XtGeometryYes); } /* * Position change allowed for Spatial layout && PlaceModel == CLOSEST */ if (((desired->request_mode & CWX) || (desired->request_mode & CWY)) && ((!CtrLayoutIsSPATIAL(cw)) || !CtrIncludeIsCLOSEST(cw))) return(XtGeometryNo); save_x = c->user_x; save_y = c->user_y; save_width = cwid->core.width; save_height = cwid->core.height; save_border_width = cwid->core.border_width ; if (desired->request_mode & CWX) c->user_x = desired->x; if (desired->request_mode & CWY) c->user_y = desired->y; if (desired->request_mode & CWWidth) cwid->core.width = desired->width; if (desired->request_mode & CWHeight) cwid->core.height = desired->height; if (desired->request_mode & CWBorderWidth) cwid->core.border_width = desired->border_width; /* * Outline/Detail Layout case. * Request are always granted, relayout is done. */ if (CtrLayoutIsOUTLINE_DETAIL(cw)) { XtWidgetGeometry geo_desired; geo_desired.width = 0; geo_desired.height = 0; /* means resize as you want */ RequestOutlineDetail(wid, &geo_desired); return(XtGeometryYes); } (*((XmContainerWidgetClass) XtClass(wid))->container_class.remove_item)(wid,cwid); /* * Fake out include model, so we get placed in the same spot. */ if (!CtrIncludeIsCLOSEST(cw)) { c->user_x = cwid->core.x; c->user_y = cwid->core.y; } save_include_model = cw->container.include_model; cw->container.include_model = XmCLOSEST; (*((XmContainerWidgetClass) XtClass(wid))->container_class.place_item)(wid,cwid,EXACT_FIT); cw->container.include_model = save_include_model; if (CtrItemIsPlaced(cwid)) return(XtGeometryYes); /* * See if we can grow and then re-layout to try again. */ if (RequestSpatialGrowth(wid,cwid)) LayoutSpatial(wid,False,NULL); cwid->core.width = save_width; cwid->core.height = save_height; cwid->core.border_width = save_border_width; if (CtrItemIsPlaced(cwid)) return(XtGeometryYes); /* * Place the item back where it was. */ if (CtrIncludeIsCLOSEST(cw)) { c->user_x = save_x; c->user_y = save_y; } save_include_model = cw->container.include_model; cw->container.include_model = XmCLOSEST; (*((XmContainerWidgetClass) XtClass(wid))->container_class.place_item)(wid,cwid,FORCE); cw->container.include_model = save_include_model; return(XtGeometryNo); } /************************************************************************ * ChangeManaged (Composite Method) ************************************************************************/ static void ChangeManaged( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; int i; Widget cwid; XmContainerConstraint c; /* * If it's one of our changes (SetValues), let's leave. */ if (cw->container.self) return; for (i = 0; i < cw->composite.num_children; i++) { cwid = cw->composite.children[i]; c = GetContainerConstraint(cwid); if (CtrICON(cwid)) if (!NodeIsActive(c->node_ptr)) HideCwid(cwid); if (CtrLayoutIsSPATIAL(cw) && (CtrOUTLINE_BUTTON(cwid) || CtrHEADER(cwid) || (c->entry_parent))) HideCwid(cwid); } if (CtrLayoutIsOUTLINE_DETAIL(cw)) ChangeManagedOutlineDetail(wid); else ChangeManagedSpatial(wid); } /************************************************************************ * ChangeManagedOutlineDetail (Private Function) ************************************************************************/ static void ChangeManagedOutlineDetail( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; XtWidgetGeometry geo_desired; if (!XtIsRealized(wid)) { geo_desired.width = cw->core.width ; geo_desired.height = cw->core.height ; /* can be 0 too */ } else { geo_desired.width = 0; geo_desired.height = 0; } RequestOutlineDetail(wid, &geo_desired); cw->container.first_change_managed = False; } /************************************************************************ * ChangeManagedSpatial (Private Function) ************************************************************************/ static void ChangeManagedSpatial( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; Widget cwid; XtWidgetGeometry geo_desired; CwidNode node; if ((CtrSpatialStyleIsGRID(cw) || CtrSpatialStyleIsCELLS(cw))) { if ((CtrViewIsSMALL_ICON(cw) && (!cw->container.small_cell_dim_fixed)) || ((CtrViewIsLARGE_ICON(cw) || CtrViewIsANY_ICON(cw)) && (!cw->container.large_cell_dim_fixed))) SetCellSizes(wid); } if (cw->container.first_change_managed) /* * First time through. Get initial size from QueryGeo */ { if (((XmContainerWidgetClass) XtClass(wid))->container_class.get_spatial_size) { Dimension width, height; if (!XtIsRealized(wid)) { width = cw->core.width; /* Can be 0 */ height = cw->core.height; } else { width = 0; height = 0; } (*((XmContainerWidgetClass) XtClass(wid))->container_class.get_spatial_size) (wid, &width, &height); geo_desired.request_mode = (CWWidth | CWHeight); geo_desired.width = width; geo_desired.height = height; if (geo_desired.width < 1) geo_desired.width = cw->core.width ; if (geo_desired.height < 1) geo_desired.height = cw->core.height ; _XmMakeGeometryRequest(wid, &geo_desired); } cw->container.first_change_managed = False; } node = cw->container.first_node; while (node) /* * Now loop through the linked list to see who needs to be * removed from the Spatial Layout. */ { cwid = node->widget_ptr; if ((!(XtIsManaged(cwid))) && CtrItemIsPlaced(cwid) && (((XmContainerWidgetClass) XtClass(wid))->container_class.remove_item)) (*((XmContainerWidgetClass) XtClass(wid))->container_class.remove_item)(wid,cwid); node = node->next_ptr; } /* * Layout will handle placing newly-managed cwids */ LayoutSpatial(wid,True,NULL); } /************************************************************************ * RequestSpatialGrowth (Private Function) * * As opposed to GetSpatialSize which makes a calculation based upon * placing all icons in a configuration as close to a square as possible, * this function calculates only the additional size needed to accomodate * the one icon passed in as "cwid". This routine also makes the * Geometry request. ************************************************************************/ static Boolean RequestSpatialGrowth( Widget wid, Widget cwid) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c; Boolean grow_width_allowed = True; Boolean grow_height_allowed = True; Dimension width_increase = 0; Dimension height_increase = 0; int new_width,new_height; int cell_width,cell_height; int width_in_cells, height_in_cells; XtWidgetGeometry geo_desired; /* * Must determine the constraints on growth from XmNresizeModel. * At Realize time, XmNspatialResizeModel is assumed to be XmGROW_BALANCED. * Note: XmNspatialResizeModel is only valid * for XmNspatialStyle XmGRID || XmCELLS. */ if (!CtrSpatialStyleIsNONE(cw)) { if ((CtrResizeModelIsGROW_MINOR(cw)) && XtIsRealized(wid)) if (CtrIsHORIZONTAL(cw)) grow_width_allowed = False; else grow_height_allowed = False; if ((CtrResizeModelIsGROW_MAJOR(cw)) && XtIsRealized(wid)) if (CtrIsHORIZONTAL(cw)) grow_height_allowed = False; else grow_width_allowed = False; if ((!grow_width_allowed) && (!grow_height_allowed)) return(False); } c = GetContainerConstraint(cwid); if (CtrSpatialStyleIsNONE(cw)) { if (grow_width_allowed) { new_width = cwid->core.x + cwid->core.width + cw->container.margin_w; if (new_width > cw->core.width) width_increase = new_width - cw->core.width; } if (grow_height_allowed) { new_height = cwid->core.y + cwid->core.height + cw->container.margin_h; if (new_height > cw->core.height) height_increase = new_height - cw->core.height; } } else { if (grow_width_allowed) { if (CtrViewIsSMALL_ICON(cw)) cell_width = cw->container.real_small_cellw; else cell_width = cw->container.real_large_cellw; if (CtrSpatialStyleIsCELLS(cw)) { width_in_cells = cwid->core.width / cell_width; if (cwid->core.width % cell_width) width_in_cells++; width_increase = width_in_cells * cell_width; } else width_increase = cell_width; if (CtrIncludeIsCLOSEST(cw) && (c->user_x > (cw->core.width - cw->container.margin_w))) { width_in_cells = (c->user_x - (cw->core.width - cw->container.margin_w)) / cell_width; if (c->user_x - (cw->core.width - cw->container.margin_w) % cell_width) width_in_cells++; width_increase += (width_in_cells - 1) * cell_width; } } if (grow_height_allowed) { if (CtrViewIsSMALL_ICON(cw)) cell_height = cw->container.real_small_cellh; else cell_height = cw->container.real_large_cellh; if (CtrSpatialStyleIsCELLS(cw)) { height_in_cells = cwid->core.height / cell_height; if (cwid->core.height % cell_height) height_in_cells++; height_increase = height_in_cells * cell_height; } else height_increase = cell_height; if (CtrIncludeIsCLOSEST(cw) && (c->user_y > (cw->core.height - cw->container.margin_h))) { height_in_cells = (c->user_y - (cw->core.height - cw->container.margin_h)) / cell_height; if (c->user_y - (cw->core.height - cw->container.margin_h) % cell_height) height_in_cells++; height_increase += (height_in_cells - 1) * cell_height; } } } geo_desired.request_mode = 0; if (width_increase != 0) { geo_desired.request_mode |= CWWidth; geo_desired.width = cw->core.width + width_increase; } if (height_increase != 0) { geo_desired.request_mode |= CWHeight; geo_desired.height = cw->core.height + height_increase; } if (geo_desired.request_mode == 0) return(False); /* * Make the geometry request (this will update the core width/height.) * We return True and it's the caller's responsibility to call * LayoutSpatial() so all the appropriate variables to keep up * with cell_count,etc. are updated. */ return(_XmMakeGeometryRequest(wid,&geo_desired) == XtGeometryYes); } /************************************************************************ * ConstraintInitialize (Constraint Method) ************************************************************************/ /*ARGSUSED*/ static void ConstraintInitialize( Widget rcwid, /* unused */ Widget ncwid, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { XmContainerWidget cw = (XmContainerWidget)XtParent(ncwid); XmContainerConstraint nc = GetContainerConstraint(ncwid); XmContainerConstraint pc; /* parent's constraints */ nc->related_cwid = NULL; nc->cwid_type = cw->container.create_cwid_type; if (!CtrICON(ncwid)) return; /* * validate resource values */ if (!XmRepTypeValidValue(XmRID_OUTLINE_STATE,nc->outline_state,ncwid)) nc->outline_state = XmCOLLAPSED; if (nc->position_index != XmLAST_POSITION) nc->position_index = MAX(0,nc->position_index); /* I can be my own grandpa but not my own descendant; pre-check */ if (nc->entry_parent) if (ContainerIsDescendant(ncwid, nc->entry_parent)) nc->entry_parent = NULL; /* * Enforce margins. Save initial x,y info. */ if (!LayoutIsRtoLM(cw)) ncwid->core.x = MAX(ncwid->core.x,(Position)cw->container.margin_w); ncwid->core.y = MAX(ncwid->core.y,(Position)cw->container.margin_h); nc->user_x = ncwid->core.x; nc->user_y = ncwid->core.y; /* * Create new node for child and insert into list. */ InsertNode(NewNode(ncwid)); /* * Override XmNviewType */ if (!CtrViewIsANY_ICON(cw)) SetViewType(ncwid,cw->container.entry_viewtype); nc->selection_visual = GetVisualEmphasis(ncwid); if (nc->selection_visual == XmSELECTED) { cw->container.selected_item_count++; if (cw->container.anchor_cwid == NULL) cw->container.anchor_cwid = ncwid; } nc->selection_state = nc->selection_visual; if (nc->entry_parent) { pc = GetContainerConstraint(nc->entry_parent); nc->depth = pc->depth +1; cw->container.max_depth = MAX(cw->container.max_depth, nc->depth); if (pc->outline_state == XmEXPANDED) nc->visible_in_outline = pc->visible_in_outline; else nc->visible_in_outline = False; if ((!nc->visible_in_outline) || (!CtrLayoutIsOUTLINE_DETAIL(cw))) HideCwid(ncwid); } else { nc->visible_in_outline = True; nc->depth = 0; } /* * Initialize variables used by * Container SpatialLayout methods. */ nc->cell_idx = NO_CELL; } /************************************************************************ * ConstraintDestroy (Constraint Method) ************************************************************************/ static void ConstraintDestroy( Widget cwid) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); if (cwid == cw->container.anchor_cwid) cw->container.anchor_cwid = NULL; if (!CtrICON(cwid)) return; { CwidNode node = c->node_ptr->child_ptr; while (node) { Widget child = node->widget_ptr; XtVaSetValues(child, XmNentryParent, NULL, NULL); /* because the above operation has changed the ** linked-list, we just pull the first child off the ** list, rather than move along it */ node = c->node_ptr->child_ptr; } } DeleteNode(cwid); ContainerResequenceNodes(cw, c->entry_parent); if (c->selection_state == XmSELECTED) { unsigned char save_state = cw->container.selection_state; cw->container.selection_state = XmNOT_SELECTED; MarkCwid(cwid,False); cw->container.selection_state = save_state; } if (XtIsRealized((Widget)cw)) XClearArea(XtDisplay((Widget)cw),XtWindow((Widget)cw),0,0,0,0,True); } /************************************************************************ * ConstraintSetValues (Constraint Method) ************************************************************************/ /*ARGSUSED*/ static Boolean ConstraintSetValues( Widget ccwid, Widget rcwid, /* unused */ Widget ncwid, ArgList args, /* unused */ Cardinal *num_args) /* unused */ { XmContainerWidget cw = (XmContainerWidget)XtParent(ncwid); XmContainerConstraint cc = GetContainerConstraint(ccwid); XmContainerConstraint nc = GetContainerConstraint(ncwid); XmContainerConstraint pc; /* Parent's Contraints */ Boolean need_layout = False; Boolean need_expose = False; /* * SetValues called from inside Container - let's get out of here! */ if (cw->container.self) return(False); if (!CtrICON(ncwid)) return(False); /* * Validate resource values */ if (nc->outline_state != cc->outline_state) { if (!XmRepTypeValidValue(XmRID_OUTLINE_STATE,nc->outline_state,ncwid)) nc->outline_state = cc->outline_state; } if (nc->position_index < 0) if (XmLAST_POSITION != nc->position_index) nc->position_index = cc->position_index; /* I can be my own grandpa but not my own descendant; pre-check */ if (nc->entry_parent != cc->entry_parent) if (nc->entry_parent) if (ContainerIsDescendant(ncwid, nc->entry_parent)) nc->entry_parent = cc->entry_parent; /* * Check if layout required. */ if (CtrLayoutIsOUTLINE_DETAIL(cw) && ((nc->entry_parent != cc->entry_parent) || (nc->position_index != cc->position_index) || (nc->outline_state != cc->outline_state))) need_layout = True; /* * Check for change in selection status */ nc->selection_visual = GetVisualEmphasis(ncwid); if (nc->selection_visual != cc->selection_visual) { if (nc->selection_visual == XmSELECTED) { cw->container.selected_item_count++; if (cw->container.anchor_cwid == NULL) cw->container.anchor_cwid = ncwid; } else cw->container.selected_item_count--; nc->selection_state = nc->selection_visual; } /* * Changes in parentage or position. * If XmNpositionIndex has changed, but the "node" has no siblings, * then there's no need to change the node's position in the * linked list. */ if ((nc->entry_parent != cc->entry_parent) || ((nc->position_index != cc->position_index) && ((nc->node_ptr->prev_ptr) || (nc->node_ptr->next_ptr)))) { SeverNode(nc->node_ptr); ContainerResequenceNodes(cw, cc->entry_parent); ContainerResequenceNodes(cw, nc->entry_parent); InsertNode(nc->node_ptr); } if (nc->entry_parent != cc->entry_parent) if (nc->entry_parent == NULL) { nc->depth = 0; nc->visible_in_outline = True; ContainerResetDepths(nc); } else { pc = GetContainerConstraint(nc->entry_parent); nc->depth = pc->depth +1; ContainerResetDepths(nc); cw->container.max_depth = MAX(cw->container.max_depth,nc->depth); if (pc->outline_state == XmEXPANDED) nc->visible_in_outline = pc->visible_in_outline; else nc->visible_in_outline = False; if ((!nc->visible_in_outline) || (!CtrLayoutIsOUTLINE_DETAIL(cw))) HideCwid(ncwid); } if (nc->outline_state != cc->outline_state) OutlineButtonAction(ncwid, nc->outline_state, (XEvent*)NULL); /* * Change Spatial locations. */ if (((ncwid->core.x != ccwid->core.x) || (ncwid->core.y != ccwid->core.y)) && CtrLayoutIsSPATIAL(cw) && (((XmContainerWidgetClass) XtClass((Widget)cw))->container_class.remove_item) && (((XmContainerWidgetClass) XtClass((Widget)cw))->container_class.place_item)) { unsigned char save_include_model; unsigned char save_snap_model; (*((XmContainerWidgetClass) XtClass((Widget)cw))->container_class.remove_item) ((Widget)cw,ncwid); save_include_model = cw->container.include_model; cw->container.include_model = XmCLOSEST; save_snap_model = cw->container.snap_model; cw->container.snap_model = XmNONE; (*((XmContainerWidgetClass) XtClass((Widget)cw))->container_class.place_item) ((Widget)cw,ncwid,FORCE); cw->container.include_model = save_include_model; cw->container.snap_model = save_snap_model; need_expose = True; } if (need_layout) { if (CtrLayoutIsOUTLINE_DETAIL(cw)) { cw->container.ideal_width = 0; cw->container.ideal_height = 0; GetSize((Widget)cw,&cw->container.ideal_width, &cw->container.ideal_height); cw->core.width = cw->container.ideal_width; cw->core.height = cw->container.ideal_height; } Layout((Widget)cw); need_expose = True; } if (need_expose && XtIsRealized((Widget)cw)) XClearArea(XtDisplay((Widget)cw),XtWindow((Widget)cw),0,0,0,0,True); /* everything that needs to be done so far has been */ return(False); } /************************************************************************ * TestFitItem (Container Method) ************************************************************************/ static Boolean TestFitItem( Widget wid, Widget cwid, Position x, Position y) { XmContainerWidget cw = (XmContainerWidget)wid; int trial_cell; XPoint cell_coord; XmContainerConstraint cwidc = GetContainerConstraint(cwid); /* * Must be a 2-D layout. */ if (CtrLayoutIsOUTLINE_DETAIL(cw)) return(True); if (y < (Position)cw->container.margin_h) return(False); if (LayoutIsRtoLM(cw)) { if (x > (Position)(cw->core.width - cw->container.margin_w)) return(False); } else if (x < (Position)cw->container.margin_w) return(False); if (CtrSpatialStyleIsGRID(cw) || CtrSpatialStyleIsCELLS(cw)) { trial_cell = GetCellFromCoord(wid,x,y); /* First, we can always put a widget back where it started, but not if something else is there */ if (cw->container.cells[trial_cell] != 0) { if (cwidc -> cell_idx == trial_cell) return(True); else return(False); } (void)GetCoordFromCell(wid,trial_cell, &cell_coord); if (CtrSpatialStyleIsCELLS(cw)) if (XRectInRegion(cw->container.cells_region, cell_coord.x,cell_coord.y, cwid->core.width,cwid->core.height) != RectangleOut) return(False); } if (CtrSpatialStyleIsNONE(cw)) { XtWidgetGeometry child_req; XtGeometryResult result; /* If we don't need to resize, just return */ if ((XtWidth(cw) >= (x + XtWidth(cwid) + cw -> container.margin_w)) && (XtHeight(cw) >= (y + XtHeight(cwid) + cw -> container.margin_h))) return(True); /* Otherwise, we'll try it via the geometry manager */ child_req.request_mode = CWX | CWY; child_req.x = x; child_req.y = y; /* Make the request, but always allow the drop */ result = _XmMakeGeometryRequest(cwid, &child_req); } return(True); } /************************************************************************ * PlaceItem (Container Method) ************************************************************************/ static Boolean PlaceItem( Widget wid, Widget cwid, unsigned char fit_type) { XmContainerWidget cw = (XmContainerWidget)wid; /* cwid NULL means initialize */ if (cwid == NULL) { PlaceItemReset(wid); return(True); } if (CtrItemIsPlaced(cwid)) return(True); switch(cw->container.spatial_style) { case XmNONE: PlaceItemNone(wid,cwid,fit_type); break; case XmGRID: case XmCELLS: PlaceItemGridCells(wid,cwid,fit_type); } if ((!CtrItemIsPlaced(cwid)) && (!CtrSpatialStyleIsNONE(cw))) HideCwid(cwid); return(CtrItemIsPlaced(cwid)); } /************************************************************************ * RemoveItem (Container Method) ************************************************************************/ static Boolean RemoveItem( Widget wid, Widget cwid) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c = GetContainerConstraint(cwid); XRectangle cwid_rect; Region cwid_region; if (!CtrItemIsPlaced(cwid)) return(True); switch(cw->container.spatial_style) { case XmCELLS: cwid_rect.x = cwid->core.x; cwid_rect.y = cwid->core.y; cwid_rect.width = cwid->core.width; cwid_rect.height = cwid->core.height; cwid_region = XCreateRegion(); XUnionRectWithRegion(&cwid_rect,cwid_region,cwid_region); XSubtractRegion(cw->container.cells_region,cwid_region, cw->container.cells_region); XDestroyRegion(cwid_region); case XmGRID: cw->container.cells[c->cell_idx]--; case XmNONE: c->cell_idx = NO_CELL; } return(True); } /************************************************************************ * GetSpatialSize (Container method) ************************************************************************/ static void GetSpatialSize ( Widget wid, Dimension * pwidth, Dimension * pheight) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; XmContainerConstraint c; ContainerCwidCellInfo cwid_info; int cwid_info_count; Dimension trial_width = 0, trial_height = 0; Dimension cell_width = 0,cell_height = 0; int width_in_cells = 1,height_in_cells = 1; int min_width_in_cells = 1,min_height_in_cells = 1; int cwid_width_in_cells,cwid_height_in_cells; int cell_count = 0; Dimension width = 1, height = 1 ; if (CtrSpatialStyleIsGRID(cw) || CtrSpatialStyleIsCELLS(cw)) { if (CtrViewIsSMALL_ICON(cw)) { cell_width = cw->container.real_small_cellw; cell_height = cw->container.real_small_cellh; } else { cell_width = cw->container.real_large_cellw; cell_height = cw->container.real_large_cellh; } } /* * Must allocate array to hold cwid information so we can use it to * calculate adjustments to ideal size when we're in XmCELLS. Don't * really know how many we'll need, so allocate one for all children * of Container to be sure. */ if (CtrSpatialStyleIsCELLS(cw)) cwid_info = (ContainerCwidCellInfo) XtCalloc(cw->composite.num_children, sizeof(XmContainerCwidCellInfoRec)); else cwid_info = NULL; cwid_info_count = 0; /* * Go through the linked list of cwids and lets determine * their geometry needs. */ node = cw->container.first_node; while (node) { if (CtrSpatialStyleIsNONE(cw)) /* * In this case, we care about the desired x,y coordinates of * each child, so let's compute the smallest rectangle that * would contain all of them and still fulfill their desires: * (trial_width X trial_height) */ { trial_width = MAX(trial_width,node->widget_ptr->core.x + node->widget_ptr->core.width); trial_height = MAX(trial_height,node->widget_ptr->core.y + node->widget_ptr->core.height); } else if (CtrIncludeIsCLOSEST(cw)) { c = GetContainerConstraint(node->widget_ptr); trial_width = MAX(trial_width, c->user_x + node->widget_ptr->core.width); trial_height = MAX(trial_height, c->user_y + node->widget_ptr->core.height); } if (CtrSpatialStyleIsGRID(cw)) /* * CtrSpatialStyleIsGRID: One cell per cwid */ cell_count++; if (CtrSpatialStyleIsCELLS(cw)) /* * CtrSpatialStyleIsCELLS: Need enough cells to completely * contain all cwids. */ { cwid_width_in_cells = (node->widget_ptr)->core.width / cell_width; if ((node->widget_ptr)->core.width % cell_width) cwid_width_in_cells++; min_width_in_cells = MAX(min_width_in_cells,cwid_width_in_cells); cwid_height_in_cells = (node->widget_ptr)->core.height / cell_height; if ((node->widget_ptr)->core.height % cell_height) cwid_height_in_cells++; min_height_in_cells = MAX(min_height_in_cells, cwid_height_in_cells); cell_count += cwid_width_in_cells * cwid_height_in_cells; cwid_info[cwid_info_count].cwid_width_in_cells = cwid_width_in_cells; cwid_info[cwid_info_count].cwid_height_in_cells = cwid_height_in_cells; cwid_info_count++; } node = GetNextNode(node); } if (CtrSpatialStyleIsNONE(cw) || CtrIncludeIsCLOSEST(cw)) { trial_width += 2 * cw->container.margin_w; trial_height += 2 * cw->container.margin_h; } if (CtrSpatialStyleIsNONE(cw)) { width = trial_width; height = trial_height; } else /* CtrSpatialStyleIsGRID || CtrSpatialStyleIsCELLS */ { /* * Simple square will do. */ width_in_cells = Isqrt(cell_count); height_in_cells = width_in_cells; if (CtrSpatialStyleIsCELLS(cw)) /* * Make adjustments to accomodate very wide or tall cwids. * Then call GetSpatialSizeCellAdjustment() to do trial * placement and make furthur adjustments. */ { width_in_cells = MAX(width_in_cells,min_width_in_cells); height_in_cells = MAX(height_in_cells,min_height_in_cells); if (cwid_info != NULL) { GetSpatialSizeCellAdjustment(wid,&width_in_cells, &height_in_cells, cwid_info,cwid_info_count); XtFree((char*)cwid_info); } } /* * Add in the margins and calculate the pixels needed. */ width = width_in_cells * cell_width + 2 * cw->container.margin_w; height = height_in_cells * cell_height + 2 * cw->container.margin_h; if (CtrIncludeIsCLOSEST(cw)) /* * Make adjustments to accomodate cwids' desired x,y placement. */ { width = MAX(width,trial_width); height = MAX(height,trial_height); } } if (!*pwidth) *pwidth = width ; if (!*pheight) *pheight = height ; } /************************************************************************ * PlaceItemNone (Private Function) ************************************************************************/ /*ARGSUSED*/ static void PlaceItemNone( Widget wid, Widget cwid, unsigned char fit_type) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c = GetContainerConstraint(cwid); PlaceCwid(cwid,cwid->core.x,cwid->core.y); /* * Mark the cwid as placed (any value except NO_CELL) if it's within * the Container boundaries. */ if (((cwid->core.x + cwid->core.width) <= (cw->core.width - cw->container.margin_w)) && ((cwid->core.y + cwid->core.height) <= (cw->core.height - cw->container.margin_h))) c->cell_idx = 1; } /************************************************************************ * PlaceItemGridCells (Private Function) ************************************************************************/ static void PlaceItemGridCells( Widget wid, Widget cwid, unsigned char fit_type) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c = GetContainerConstraint(cwid); int start_cell; int trial_cell = 0; int closest_cell = -1; Boolean fits; XPoint cell_coord; XPoint place_point; XRectangle cwidrect; if (CtrIncludeIsAPPEND(cw)) trial_cell = cw->container.next_free_cell; if (CtrIncludeIsCLOSEST(cw)) { closest_cell = GetCellFromCoord(wid,c->user_x,c->user_y); trial_cell = closest_cell; if (trial_cell >= cw->container.cell_count) { if (fit_type == EXACT_FIT) return; /* exact fit or nothing! */ /* Adjust for current width/height boundaries */ trial_cell = GetCellFromCoord(wid, MIN(c->user_x, (Position)(cw->container.current_width_in_cells * (CtrViewIsSMALL_ICON(cw) ? cw->container.real_small_cellw : cw->container.real_large_cellw) - 1)), MIN(c->user_y, (Position)(cw->container.current_height_in_cells * (CtrViewIsSMALL_ICON(cw) ? cw->container.real_small_cellh : cw->container.real_large_cellh) - 1))); if (trial_cell >= cw->container.cell_count) /* This shouldn't occur - but just in case */ trial_cell = cw->container.next_free_cell; } } start_cell = trial_cell; if (trial_cell < cw->container.cell_count) { while (!CtrItemIsPlaced(cwid)) { fits = False; if ((cw->container.cells[trial_cell] == 0) && (fit_type != FORCE)) { if (CtrSpatialStyleIsGRID(cw)) fits = True; if (CtrSpatialStyleIsCELLS(cw)) { if (CtrIncludeIsCLOSEST(cw) && (trial_cell == closest_cell)) (void)SnapCwid(cwid,c->user_x,c->user_y, &place_point); else { (void)GetCoordFromCell(wid,trial_cell, &cell_coord); (void)SnapCwid(cwid,cell_coord.x,cell_coord.y,&place_point); } if ((XRectInRegion(cw->container.cells_region, place_point.x,place_point.y, cwid->core.width,cwid->core.height) == RectangleOut) && (place_point.x + cwid->core.width <= cw->core.width - cw->container.margin_w) && (place_point.y + cwid->core.height <= cw->core.height - cw->container.margin_h)) fits = True; } } if (fits || (fit_type == FORCE)) { cw->container.cells[trial_cell]++; c->cell_idx = trial_cell; } trial_cell++; if (trial_cell == cw->container.cell_count) trial_cell = 0; if (start_cell == trial_cell) break; } } if (!CtrItemIsPlaced(cwid)) return; if (CtrIncludeIsAPPEND(cw)) cw->container.next_free_cell = c->cell_idx + 1; if (CtrIncludeIsCLOSEST(cw) && (c->cell_idx == closest_cell)) (void)SnapCwid(cwid,c->user_x,c->user_y, &place_point); else { (void)GetCoordFromCell(wid,c->cell_idx, &cell_coord); (void)SnapCwid(cwid,cell_coord.x,cell_coord.y, &place_point); } if (CtrSpatialStyleIsCELLS(cw)) { cwidrect.x = place_point.x; cwidrect.y = place_point.y; cwidrect.width = cwid->core.width; cwidrect.height = cwid->core.height; XUnionRectWithRegion(&cwidrect,cw->container.cells_region, cw->container.cells_region); } PlaceCwid(cwid,place_point.x,place_point.y); } /************************************************************************ * GetCellFromCoord (Private Function) ************************************************************************/ static int GetCellFromCoord( Widget wid, Position x, Position y) { XmContainerWidget cw = (XmContainerWidget)wid; int cell_width,cell_height; int row,col; cell_width = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellw : cw->container.real_large_cellw; cell_height = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellh : cw->container.real_large_cellh; /* * Note: x & y parameters include Container margins. */ if (!LayoutIsRtoLM(cw)) x = MAX(0,x - cw->container.margin_w); y = MAX(0,y - cw->container.margin_h); row = y / cell_height; col = x / cell_width; if (LayoutIsRtoLM(cw)) col = cw->container.current_width_in_cells - col - 1; if (CtrIsHORIZONTAL(cw)) return(cw->container.current_width_in_cells * row + col); else return(cw->container.current_height_in_cells * col + row); } /************************************************************************ * GetCoordFromCell (Private Function) ************************************************************************/ static XPoint * GetCoordFromCell( Widget wid, int cell_idx, XPoint *point) { XmContainerWidget cw = (XmContainerWidget)wid; int cell_width,cell_height; int row,col; if (CtrIsHORIZONTAL(cw)) { row = cell_idx / cw->container.current_width_in_cells; col = cell_idx - (row * cw->container.current_width_in_cells); } else { col = cell_idx / cw->container.current_height_in_cells; row = cell_idx - (col * cw->container.current_height_in_cells); } if (LayoutIsRtoLM(cw)) col = cw->container.current_width_in_cells - col - 1; cell_width = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellw : cw->container.real_large_cellw; cell_height = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellh : cw->container.real_large_cellh; /* * Note: returned point must include Container Margins */ point->x = col * cell_width; if (!LayoutIsRtoLM(cw)) point->x += cw->container.margin_w; point->y = row * cell_height + cw->container.margin_h; return(point); } /************************************************************************ * PlaceItemReset (Private Function) ************************************************************************/ static void PlaceItemReset( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; int cell_width = 0,cell_height = 0; int width_in_cells = 0,height_in_cells = 0; /* * Deallocate old cell structure. */ if ((cw->container.cells) && (((XmContainerWidgetClass)XtClass(wid))->container_class.remove_item)) { node = cw->container.first_node; while (node) { if (CtrItemIsPlaced(node->widget_ptr)) (*((XmContainerWidgetClass) XtClass(wid))->container_class.remove_item) (wid,node->widget_ptr); node = GetNextNode(node); } XtFree((char*)cw->container.cells); cw->container.cells = NULL; } if (CtrSpatialStyleIsNONE(cw)) return; /* * Create new cell structure. */ cell_width = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellw : cw->container.real_large_cellw; cell_height = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellh : cw->container.real_large_cellh; if (cw->core.width > cell_width + 2 * cw->container.margin_w) width_in_cells = (cw->core.width - 2 * cw->container.margin_w) / cell_width; else width_in_cells = 1; if (cw->core.height > cell_height + 2 * cw->container.margin_h) height_in_cells = (cw->core.height - 2 * cw->container.margin_h) / cell_height; else height_in_cells = 1; cw->container.cell_count = width_in_cells * height_in_cells; cw->container.cells = (int *)XtCalloc(cw->container.cell_count,sizeof(int)); cw->container.next_free_cell = 0; cw->container.current_width_in_cells = width_in_cells; cw->container.current_height_in_cells = height_in_cells; if (CtrSpatialStyleIsGRID(cw)) return; XSubtractRegion(cw->container.cells_region,cw->container.cells_region, cw->container.cells_region); } /************************************************************************ * PlaceCwid (Private Function) ************************************************************************/ static void PlaceCwid( Widget cwid, Position x, Position y) { XmContainerWidget cw; if (cwid == NULL) return; cw = (XmContainerWidget)XtParent(cwid); /* * Adjust for margins */ if (LayoutIsRtoLM(cw)) { if ((cwid->core.width + (Position)cw->container.margin_w) >= cw->core.width) cwid->core.x = MIN(cwid->core.x,cw->core.width - cwid->core.width - (Position)cw->container.margin_w); } else x = MAX(x,(Position)cw->container.margin_w); y = MAX(y,(Position)cw->container.margin_h); if ((x != cwid->core.x) || (y != cwid->core.y)) XmeConfigureObject(cwid,x,y,cwid->core.width,cwid->core.height,0); } /************************************************************************ * SnapCwid (Private Function) ************************************************************************/ static XPoint * SnapCwid( Widget cwid, Position x, Position y, XPoint *point) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); int target_cell; XPoint target_cell_coord; int cell_width = 0,cell_height = 0; int width_in_cells = 0,height_in_cells = 0; target_cell = GetCellFromCoord((Widget)cw,x,y); (void)GetCoordFromCell((Widget)cw,target_cell, &target_cell_coord); point->x = target_cell_coord.x; point->y = target_cell_coord.y; if (CtrSnapModelIsSNAP(cw) && !LayoutIsRtoLM(cw)) return(point); if (CtrViewIsSMALL_ICON(cw)) { cell_width = cw->container.real_small_cellw; cell_height = cw->container.real_small_cellh; } else { cell_width = cw->container.real_large_cellw; cell_height = cw->container.real_large_cellh; } if (CtrSpatialStyleIsGRID(cw)) width_in_cells = height_in_cells = 1; else /* CtrSpatialStyleIsCELLS(cw) */ { width_in_cells = cwid->core.width / cell_width; if (cwid->core.width % cell_width) width_in_cells++; height_in_cells = cwid->core.height / cell_height; if (cwid->core.height % cell_height) height_in_cells++; } if (CtrSnapModelIsSNAP(cw)) /* LayoutIsRtoLM(cw) */ { point->x += (width_in_cells * cell_width) - cwid->core.width; return(point); } if (CtrSnapModelIsNONE(cw)) { point->x = MIN(x, target_cell_coord.x + (width_in_cells * cell_width) - 1); point->y = MIN(y, target_cell_coord.y + (height_in_cells * cell_height) - 1); return(point); } if (CtrSpatialStyleIsGRID(cw)) { /* Adjust large items to 0 so we don't try to center them */ width_in_cells = (cell_width < cwid->core.width) ? 0 : 1; height_in_cells = (cell_height < cwid->core.height) ? 0 : 1; } /* CtrSnapModelIsCENTER */ /* If this is small icon view then the icon is placed centered up/down, if this is large icon view then the icon is placed centered left/right */ if (CtrViewIsSMALL_ICON(cw)) { if (height_in_cells != 0) point->y += ((height_in_cells * cell_height) - cwid->core.height) / 2; if (LayoutIsRtoLM(cw)) point->x += ((width_in_cells * cell_width) - cwid->core.width); } else { if (width_in_cells != 0) point->x += ((width_in_cells * cell_width) - cwid->core.width) / 2; if (height_in_cells != 0) point->y += (height_in_cells * cell_height) - cwid->core.height; } return(point); } /************************************************************************ * HideCwid (Private Function) ************************************************************************/ static void HideCwid( Widget cwid) { XmContainerConstraint c; CwidNode node; CwidNode child_node; if (cwid == NULL) return; c = GetContainerConstraint(cwid); XmeConfigureObject( cwid,(Position)(0 - ((Widget)cwid)->core.width), (Position)(0 - ((Widget)cwid)->core.height), ((Widget)cwid)->core.width,((Widget)cwid)->core.height,0); if (!CtrICON(cwid)) return; /* * Hide our button! */ if (c->related_cwid) HideCwid(c->related_cwid); /* * If we're XmEXPANDED, then let's hide our children too. */ if (c->outline_state != XmEXPANDED) return; node = c->node_ptr; child_node = node->child_ptr; while (child_node) { HideCwid(child_node->widget_ptr); c = GetContainerConstraint(child_node->widget_ptr); if (c->related_cwid) HideCwid(c->related_cwid); child_node = child_node->next_ptr; } } /************************************************************************ * ContainerStartTransfer (Action Proc) ************************************************************************/ static void ContainerStartTransfer( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Widget cwid; int transfer_action; if (cw->container.selecting) /* Don't allow drag while select in progress */ return; if (CtrLayoutIsOUTLINE_DETAIL(wid)) { cwid = (Widget)_XmInputForGadget(wid, event->xbutton.x,event->xbutton.y); if ((cwid) && CtrOUTLINE_BUTTON(cwid)) { XtCallActionProc(wid,"ManagerGadgetDrag", event,params,*num_params); return; } } /* * Allocate transfer context record to temporarily hold * event and operation argument until we can figure out whether * this is a primary transfer or the start of a drag. * If a context record already exists (might happen if there * was a Btn2 double-click, for example), then just reuse it * instead of malloc'ing a new one. */ if (cw->container.transfer_action == NULL) { cw->container.transfer_action = (ContainerXfrAction) XtCalloc(1,sizeof(XmContainerXfrActionRec)); cw->container.transfer_action->event = (XEvent *) XtCalloc(1,sizeof(XEvent)); } cw->container.transfer_action->wid = (Widget)cw; memcpy((void *)cw->container.transfer_action->event,(void *)event, sizeof(XEvent)); cw->container.transfer_action->params = params; cw->container.transfer_action->num_params = num_params; if (num_params == 0 || _XmConvertActionParamToRepTypeId((Widget) cw, XmRID_CONTAINER_START_TRANSFER_ACTION_PARAMS, params[0], False, &transfer_action) == False) { /* We couldn't convert the value. Just assume a value of _COPY. */ transfer_action = _COPY; } if (transfer_action == _LINK) cw->container.transfer_action->operation = XmLINK; else if (transfer_action == _MOVE) cw->container.transfer_action->operation = XmMOVE; else cw->container.transfer_action->operation = XmCOPY; /* * Set off timer. */ if (cw->container.transfer_timer_id != 0) XtRemoveTimeOut(cw->container.transfer_timer_id); cw->container.transfer_timer_id = XtAppAddTimeOut( XtWidgetToApplicationContext((Widget)cw), XtGetMultiClickTime(XtDisplay((Widget)cw)), DragStart,(XtPointer)cw); } /************************************************************************ * ContainerEndTransfer (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerEndTransfer( Widget wid, XEvent *event, /* unused */ String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; /* * Kill the timeout. If it already expired, then we didn't make * the interval for primary transfer, so return. */ if (cw->container.transfer_timer_id != 0) XtRemoveTimeOut(cw->container.transfer_timer_id); else return; if (cw->container.transfer_action == NULL) return; /* No context record, shouldn't happen */ if (cw->container.transfer_action->operation == XmLINK) ContainerPrimaryLink(wid, cw->container.transfer_action->event,NULL,0); else if (cw->container.transfer_action->operation == XmMOVE) ContainerPrimaryMove(wid, cw->container.transfer_action->event,NULL,0); else ContainerPrimaryCopy(wid, cw->container.transfer_action->event,NULL,0); XtFree((char*)cw->container.transfer_action->event); XtFree((char*)cw->container.transfer_action); cw->container.transfer_action = NULL; } /************************************************************************ * ContainerPrimaryCopy (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerPrimaryCopy( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XPoint *loc_data; /* WARNING: do not free the following memory in this module. It * will be freed in FreeLocationData, triggered at the end of * the data transfer operation. */ loc_data = (XPoint *) XtMalloc(sizeof(XPoint)); loc_data->x = event->xbutton.x; loc_data->y = event->xbutton.y; XmePrimarySink(wid,XmCOPY, (XtPointer) loc_data,event->xbutton.time); } /************************************************************************ * ContainerPrimaryLink (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerPrimaryLink( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XPoint *loc_data; /* WARNING: do not free the following memory in this module. It * will be freed in FreeLocationData, triggered at the end of * the data transfer operation. */ loc_data = (XPoint *) XtMalloc(sizeof(XPoint)); loc_data->x = event->xbutton.x; loc_data->y = event->xbutton.y; XmePrimarySink(wid,XmLINK, (XtPointer) loc_data,event->xbutton.time); } /************************************************************************ * ContainerPrimaryMove (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerPrimaryMove( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XPoint *loc_data; /* WARNING: do not free the following memory in this module. It * will be freed in FreeLocationData, triggered at the end of * the data transfer operation. */ loc_data = (XPoint *) XtMalloc(sizeof(XPoint)); loc_data->x = event->xbutton.x; loc_data->y = event->xbutton.y; XmePrimarySink(wid,XmMOVE, (XtPointer) loc_data,event->xbutton.time); } /************************************************************************ * Actions to dispatch based on button1 transfer options * * The first parameter is the default action to call if * enableBtn1Transfer is XmOFF * * If there is a second parameter, it is COPY, MOVE or LINK. ************************************************************************/ /*ARGSUSED*/ static void ContainerNoop( Widget wid, /* unused */ XEvent *event, /* unused */ String *params, /* unused */ Cardinal *num_params) /* unused */ { /* Do nothing */ } /************************************************* * ContainerHandleBtn1Down * * We do a drag if enableBtn1Transfer is not XmOFF * Otherwise we do a select. * * Also, if nothing is selected we go ahead and do * a complete selection (Call ContainerBeginSelect,EndSelect) * so that we complete the selection before starting the * drag. *************************************************/ static void ContainerHandleBtn1Down( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint cwidc; Widget cwid = (Widget) NULL; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if (*num_params < 2) { XmeWarning(wid, WRONGPARAMS); return; } cwid = ObjectAtPoint(wid, event->xbutton.x,event->xbutton.y); if (cwid != (Widget) NULL) cwidc = GetContainerConstraint(cwid); else cwidc = (XmContainerConstraint) NULL; if (dpy -> display.enable_btn1_transfer && cwid != (Widget) NULL && !CtrOUTLINE_BUTTON(cwid)) { /* Select if over unselected item or background*/ if (cwidc -> selection_state != XmSELECTED) { XtCallActionProc(wid, params[0], event, NULL, 0); ContainerEndSelect(wid,event,NULL,0); } else { SetupDrag(wid,event,params,num_params); cw->container.selecting = False; } if (cwidc -> selection_state == XmSELECTED) XtCallActionProc(wid, "ContainerStartTransfer", event, ¶ms[1], 1); else XtCallActionProc(wid, params[0], event, NULL, 0); } else { XtCallActionProc(wid, params[0], event, NULL, 0); } } static void ContainerHandleBtn1Motion( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if (*num_params < 1) { XmeWarning(wid, WRONGPARAMS); return; } /* If we're doing btn1 transfer, then check to see if we've moved enough to start the drag */ if (dpy->display.enable_btn1_transfer != XmOFF && (! cw -> container.selecting)) { int dx, dy; dx = event->xmotion.x - cw->container.anchor_point.x; dy = event->xmotion.y - cw->container.anchor_point.y; if (ABS(dx) >= MOTION_THRESHOLD || ABS(dy) >= MOTION_THRESHOLD) { /* Force the drag to start */ DragStart((XtPointer) cw, &cw -> container.transfer_timer_id); } else { return; } } else { /* Do the default action */ XtCallActionProc(wid, params[0], event, NULL, 0); } } static void ContainerHandleBtn1Up( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if (*num_params < 1) { XmeWarning(wid, WRONGPARAMS); return; } /* If we're doing btn1 transfer, then remove the timer that starts the drag */ if (dpy->display.enable_btn1_transfer) { if (cw->container.transfer_timer_id != 0) XtRemoveTimeOut(cw->container.transfer_timer_id); if (cw->container.drag_context != (Widget) NULL) { XmDragCancel(cw->container.drag_context); cw->container.drag_context = (Widget) NULL; } } XtCallActionProc(wid, params[0], event, NULL, 0); } static void ContainerHandleBtn2Down( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if (*num_params < 2) { XmeWarning(wid, WRONGPARAMS); return; } if (dpy -> display.enable_btn1_transfer == XmBUTTON2_ADJUST) XtCallActionProc(wid, "ContainerBeginExtend", event, NULL, 0); else XtCallActionProc(wid, params[0], event, ¶ms[1], 1); } static void ContainerHandleBtn2Motion( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if (*num_params < 1) { XmeWarning(wid, WRONGPARAMS); return; } if (dpy->display.enable_btn1_transfer != XmBUTTON2_ADJUST && (! cw -> container.selecting)) { int dx, dy; dx = event->xmotion.x - cw->container.anchor_point.x; dy = event->xmotion.y - cw->container.anchor_point.y; if (ABS(dx) >= MOTION_THRESHOLD || ABS(dy) >= MOTION_THRESHOLD) { /* Force the drag to start */ DragStart((XtPointer) cw, &cw -> container.transfer_timer_id); } else { return; } } else XtCallActionProc(wid, params[0], event, NULL, 0); } static void ContainerHandleBtn2Up( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if ((dpy -> display.enable_btn1_transfer == XmBUTTON2_ADJUST) || (!num_params) || (*num_params < 1)) XtCallActionProc(wid, "ContainerEndExtend", event, NULL, 0); else XtCallActionProc(wid, params[0], event, NULL, 0); } /************************************************************************ * ContainerBeginSelect (Action Proc) ************************************************************************/ static void ContainerBeginSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Widget cwid = (Widget) NULL; cw->container.cancel_pressed = False; if (CtrLayoutIsOUTLINE_DETAIL(wid)) { cwid = (Widget)_XmInputForGadget(wid,event->xbutton.x,event->xbutton.y); if ((cwid) && CtrOUTLINE_BUTTON(cwid)) { XtCallActionProc(wid,"ManagerGadgetArm",event,params,*num_params); cw->container.ob_pressed = True; return; } } cw->container.extending_mode = (CtrPolicyIsMULTIPLE(cw)); cw->container.selecting = True; StartSelect(wid,event,params,num_params); } /************************************************************************ * ContainerButtonMotion (Action Proc) ************************************************************************/ static void ContainerButtonMotion( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Boolean selection_changes; /* if we are outside the window update LeaveDir */ if (cw->container.scroll_proc_id) { Widget clip = XtParent(wid); int rx, ry; /* event coords relative to the clip */ rx = event->xmotion.x + (int)wid->core.x; ry = event->xmotion.y + (int)wid->core.y; if (rx <= (int)clip->core.x) { cw->container.LeaveDir |= LEFTLEAVE; cw->container.LeaveDir &= ~RIGHTLEAVE; } else { cw->container.LeaveDir &= ~LEFTLEAVE; if (rx >= (int)clip->core.width) cw->container.LeaveDir |= RIGHTLEAVE; else cw->container.LeaveDir &= ~RIGHTLEAVE; } if (ry <= (int)clip->core.y) { cw->container.LeaveDir |= TOPLEAVE; cw->container.LeaveDir &= ~BOTTOMLEAVE; } else { cw->container.LeaveDir &= ~TOPLEAVE; if (ry >= (int)clip->core.height) cw->container.LeaveDir |= BOTTOMLEAVE; else cw->container.LeaveDir &= ~BOTTOMLEAVE; } /* store relative coordinates of the event */ cw->container.last_xmotion_x = rx; cw->container.last_xmotion_y = ry; } if (cw->container.cancel_pressed) return; if (cw->container.ob_pressed) { XtCallActionProc(wid,"ManagerGadgetButtonMotion", event,params,*num_params); return; } if (CtrPolicyIsSINGLE(wid)) return; if ((cw->container.extend_pressed) && (CtrLayoutIsSPATIAL(cw))) return; selection_changes = ProcessButtonMotion(wid,event,params,num_params); cw->container.no_auto_sel_changes |= selection_changes; if (CtrIsAUTO_SELECT(cw) && selection_changes) CallSelectCB(wid,event,XmAUTO_MOTION); } /************************************************************************ * ContainerEndSelect (Action Proc) ************************************************************************/ static void ContainerEndSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Boolean selection_changes; /* first remove TimeOutProc if any */ cw->container.LeaveDir = 0; if (cw->container.scroll_proc_id) { XtRemoveTimeOut(cw->container.scroll_proc_id); cw->container.scroll_proc_id = 0; } cw->container.selecting = False; if (cw->container.cancel_pressed) return; if (cw->container.toggle_pressed) { ContainerEndToggle(wid,event,params,num_params); return; } if (cw->container.extend_pressed) { ContainerEndExtend(wid,event,params,num_params); return; } if (cw->container.ob_pressed) { XtCallActionProc(wid,"ManagerGadgetActivate", event,params,*num_params); cw->container.ob_pressed = False; return; } if (CtrPolicyIsSINGLE(cw)) { GainPrimary(wid,event->xbutton.time); CallSelectCB(wid,event,XmAUTO_UNSET); return; } selection_changes = ProcessButtonMotion(wid,event,params,num_params); cw->container.no_auto_sel_changes |= selection_changes; if (cw->container.marquee_drawn) { DrawMarquee(wid); cw->container.marquee_drawn = False; if XtIsRealized(wid) XClearArea(XtDisplay(wid),XtWindow(wid), cw->container.marquee_smallest.x, cw->container.marquee_smallest.y, cw->container.marquee_largest.x, cw->container.marquee_largest.y,True); } if (cw->container.anchor_cwid) { if (!cw->container.kaddmode) { Boolean set_cursor = False; Widget current_focus = XmGetFocusWidget(wid); /* Only move the focus if the old focus child is no longer in the set. We can tell by looking at the constraint record off the current focus widget */ if (current_focus != (Widget) NULL && XtParent(current_focus) == wid) { XmContainerConstraint c = GetContainerConstraint(current_focus); if (c->selection_visual != XmSELECTED) set_cursor = True; } else { set_cursor = True; } if (set_cursor) SetLocationCursor(cw->container.anchor_cwid); } if (CtrPolicyIsBROWSE(cw)) cw->container.no_auto_sel_changes |= MarkCwid(cw->container.anchor_cwid,False); else /* CtrPolicyIsMULTIPLE || CtrPolicyIsEXTENDED */ SetMarkedCwids(wid); } GainPrimary(wid,event->xbutton.time); if (CtrIsAUTO_SELECT(cw)) if (selection_changes) CallSelectCB(wid,event,XmAUTO_CHANGE); else CallSelectCB(wid,event,XmAUTO_NO_CHANGE); else CallSelectCB(wid,event,XmAUTO_UNSET); } /************************************************************************ * ContainerBeginToggle (Action Proc) ************************************************************************/ static void ContainerBeginToggle( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Widget cwid; if (CtrLayoutIsOUTLINE_DETAIL(wid)) { cwid = (Widget)_XmInputForGadget(wid, event->xbutton.x,event->xbutton.y); if ((cwid) && CtrOUTLINE_BUTTON(cwid)) { XtCallActionProc(wid,"ManagerGadgetTraverseCurrent", event,params,*num_params); cw->container.ob_pressed = True; return; } } cw->container.toggle_pressed = True; cw->container.cancel_pressed = False; if (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw)) return; cw->container.extending_mode = True; cw->container.selecting = True; StartSelect(wid,event,params,num_params); } /************************************************************************ * ContainerEndToggle (Action Proc) ************************************************************************/ static void ContainerEndToggle( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; cw->container.toggle_pressed = False; cw->container.selecting = False; if (cw->container.cancel_pressed) return; if (cw->container.ob_pressed) { cw->container.ob_pressed = False; return; } if (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw)) return; ContainerEndSelect(wid,event,params,num_params); } /************************************************************************ * ContainerBeginExtend (Action Proc) ************************************************************************/ static void ContainerBeginExtend( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget current_cwid; if (CtrLayoutIsOUTLINE_DETAIL(wid)) { current_cwid = (Widget)_XmInputForGadget(wid, event->xbutton.x,event->xbutton.y); if ((current_cwid) && CtrOUTLINE_BUTTON(current_cwid)) { XtCallActionProc(wid,"ManagerGadgetArm", event,params,*num_params); cw->container.ob_pressed = True; return; } } cw->container.extend_pressed = True; cw->container.cancel_pressed = False; if (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw)) return; if (CtrLayoutIsSPATIAL(cw)) return; current_cwid = ObjectAtPoint(wid,event->xbutton.x,event->xbutton.y); /* Handle ObjectAtPoint returning an outline button */ if ((current_cwid) && CtrOUTLINE_BUTTON(current_cwid)) current_cwid = NULL; SetLocationCursor(current_cwid); if (current_cwid == NULL) return; if (cw->container.anchor_cwid == NULL) return; if (!cw->container.extending_mode) DeselectAllCwids(wid); (void) MarkCwidsInRange(wid,cw->container.anchor_cwid, current_cwid,(Boolean)True); if (CtrIsAUTO_SELECT(cw)) CallSelectCB(wid,event,XmAUTO_BEGIN); cw->container.selecting = True; } /************************************************************************ * ContainerEndExtend (Action Proc) ************************************************************************/ static void ContainerEndExtend( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Boolean selection_changes; cw->container.extend_pressed = False; cw->container.selecting = False; if (cw->container.cancel_pressed) return; if (cw->container.ob_pressed) { XtCallActionProc(wid,"ManagerGadgetActivate", event,params,*num_params); cw->container.ob_pressed = False; return; } if (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw)) return; if (CtrLayoutIsSPATIAL(cw)) return; selection_changes = ProcessButtonMotion(wid,event,params,num_params); if (cw->container.marquee_drawn) { DrawMarquee(wid); cw->container.marquee_drawn = False; if XtIsRealized(wid) XClearArea(XtDisplay(wid),XtWindow(wid), cw->container.marquee_smallest.x, cw->container.marquee_smallest.y, cw->container.marquee_largest.x, cw->container.marquee_largest.y,True); } SetMarkedCwids(wid); GainPrimary(wid,event->xbutton.time); if (CtrIsAUTO_SELECT(cw)) if (selection_changes) CallSelectCB(wid,event,XmAUTO_CHANGE); else CallSelectCB(wid,event,XmAUTO_NO_CHANGE); else CallSelectCB(wid,event,XmAUTO_UNSET); } /************************************************************************ * ContainerCancel (Action Proc) ************************************************************************/ static void ContainerCancel( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Boolean selection_changes = False; if (cw->container.ob_pressed) { XtCallActionProc(wid,"ManagerParentCancel", event,params,*num_params); cw->container.ob_pressed = False; return; } cw->container.toggle_pressed = False; cw->container.extend_pressed = False; if (CtrPolicyIsSINGLE(cw)) return; cw->container.cancel_pressed = True; if (CtrPolicyIsBROWSE(cw)) { if (cw->container.anchor_cwid) { selection_changes = UnmarkCwidVisual( cw->container.anchor_cwid); if (CtrIsAUTO_SELECT(cw) && selection_changes) { GainPrimary(wid,event->xbutton.time); CallSelectCB(wid,event,XmAUTO_CANCEL); } } return; } /* CtrPolicyIsMULTIPLE || CtrPolicyIsEXTENDED */ selection_changes = ResetMarkedCwids(wid); if (cw->container.marquee_drawn) { DrawMarquee(wid); cw->container.marquee_drawn = False; if XtIsRealized(wid) XClearArea(XtDisplay(wid),XtWindow(wid), cw->container.marquee_smallest.x, cw->container.marquee_smallest.y, cw->container.marquee_largest.x, cw->container.marquee_largest.y,True); } if (CtrIsAUTO_SELECT(cw) && selection_changes) { GainPrimary(wid,event->xbutton.time); CallSelectCB(wid,event,XmAUTO_CANCEL); } } /************************************************************************ * ContainerSelect (Action Proc) ************************************************************************/ static void ContainerSelect( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Widget focus_cwid = XmGetFocusWidget(wid); if (CtrLayoutIsOUTLINE_DETAIL(wid) && focus_cwid && (focus_cwid != wid) && CtrOUTLINE_BUTTON(focus_cwid)) { XtCallActionProc(wid,"ManagerGadgetSelect", event,params,*num_params); return; } cw->container.extending_mode = cw->container.kaddmode; KBSelect(wid,event,params,num_params); } /************************************************************************ * ContainerExtend (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerExtend( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget focus_cwid = XmGetFocusWidget(wid); if ((focus_cwid == wid) || (focus_cwid == NULL)) return; if (CtrOUTLINE_BUTTON(focus_cwid)) return; if (CtrLayoutIsSPATIAL(cw)) return; if (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw)) return; if (!(cw->container.kaddmode)) cw->container.no_auto_sel_changes |= DeselectAllCwids(wid); cw->container.no_auto_sel_changes |= MarkCwidsInRange(wid,cw->container.anchor_cwid, focus_cwid,(Boolean)False); GainPrimary(wid,event->xbutton.time); if (CtrIsAUTO_SELECT(cw)) { CallSelectCB(wid,event,XmAUTO_BEGIN); CallSelectCB(wid,event,XmAUTO_NO_CHANGE); } else if (cw->container.no_auto_sel_changes) CallSelectCB(wid,event,XmAUTO_UNSET); } /************************************************************************ * ContainerMoveCursor (Action Proc) ************************************************************************/ static void ContainerMoveCursor( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; Widget focus_cwid; if (*num_params == 0) return; if (_XmGetFocusPolicy(wid) == XmPOINTER) return; CalcNextLocationCursor(wid,params[0]); focus_cwid = XmGetFocusWidget(wid); if (focus_cwid && (focus_cwid != wid) && CtrOUTLINE_BUTTON(focus_cwid)) return; if (cw->container.kaddmode) return; cw->container.extending_mode = False; KBSelect(wid,event,params,num_params); } /************************************************************************ * ContainerExtendCursor (Action Proc) ************************************************************************/ static void ContainerExtendCursor( Widget wid, XEvent *event, String *params, Cardinal *num_params) { if (*num_params == 0) return; if (_XmGetFocusPolicy(wid) == XmPOINTER) return; if (CtrLayoutIsSPATIAL(wid)) return; if (CtrPolicyIsSINGLE(wid) || CtrPolicyIsBROWSE(wid)) return; CalcNextLocationCursor(wid,params[0]); ContainerExtend(wid,event,params,num_params); } /************************************************************************ * ContainerToggleMode (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerToggleMode( Widget wid, XEvent *event, /* unused */ String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget focus_cwid = XmGetFocusWidget(wid); if CtrPolicyIsEXTENDED(cw) cw->container.kaddmode = !cw->container.kaddmode; if (XtIsRealized(wid) && focus_cwid && (focus_cwid != wid)) XClearArea(XtDisplay(wid),XtWindow(wid), focus_cwid->core.x, focus_cwid->core.y, focus_cwid->core.width, focus_cwid->core.height, True); } /************************************************************************ * ContainerSelectAll (Action Proc) ************************************************************************/ static void ContainerSelectAll( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; if (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw)) { ContainerSelect(wid,event,params,num_params); return; } cw->container.no_auto_sel_changes |= SelectAllCwids(wid); GainPrimary(wid,event->xbutton.time); if (CtrIsAUTO_SELECT(cw)) { CallSelectCB(wid,event,XmAUTO_BEGIN); CallSelectCB(wid,event,XmAUTO_NO_CHANGE); } else if (cw->container.no_auto_sel_changes) CallSelectCB(wid,event,XmAUTO_UNSET); } /************************************************************************ * ContainerDeselectAll (Action Proc) ************************************************************************/ /*ARGSUSED*/ static void ContainerDeselectAll( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; cw->container.no_auto_sel_changes |= DeselectAllCwids(wid); GainPrimary(wid,event->xbutton.time); if (CtrIsAUTO_SELECT(cw) && (!CtrPolicyIsSINGLE(cw))) { CallSelectCB(wid,event,XmAUTO_BEGIN); CallSelectCB(wid,event,XmAUTO_NO_CHANGE); } else if (cw->container.no_auto_sel_changes) CallSelectCB(wid,event,XmAUTO_UNSET); } /************************************************************************ * ContainerActivate (Action Proc) ************************************************************************/ static void ContainerActivate( Widget wid, XEvent *event, String *params, Cardinal *num_params) { Widget focus_cwid = XmGetFocusWidget(wid); if ((focus_cwid == wid) || (focus_cwid == NULL)) return; if (CtrLayoutIsOUTLINE_DETAIL(wid) && CtrOUTLINE_BUTTON(focus_cwid)) { XtCallActionProc(wid,"ManagerParentActivate", event,params,*num_params); return; } CallActionCB(focus_cwid,event); } /************************************************************************ * ContainerExpandOrCollapse (Action Proc) ************************************************************************/ static void ContainerExpandOrCollapse( Widget wid, XEvent *event, String *params, Cardinal *num_params) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c; Widget focus_cwid; int state_to; unsigned char new_state; if (!num_params || *num_params != 1 || !params) return; if ( ((focus_cwid=XmGetFocusWidget(wid)) == NULL) || (wid != XtParent(focus_cwid)) || (CtrLayoutIsSPATIAL(cw)) || (CtrOUTLINE_BUTTON(focus_cwid))) return; if (_XmConvertActionParamToRepTypeId((Widget) cw, XmRID_CONTAINER_EXPAND_OR_COLLAPSE_ACTION_PARAMS, params[0], False, &state_to) == False) return; c = GetContainerConstraint(focus_cwid); /* check LtoR and reduce to _COLLAPSE and _EXPAND values */ if ((state_to == _LEFT) || (state_to == _RIGHT && (LayoutIsRtoLM(cw)))) new_state = XmCOLLAPSED; else if ((state_to == _RIGHT) || (state_to == _LEFT && (LayoutIsRtoLM(cw)))) new_state = XmEXPANDED; /* check if there is anything to do */ if (new_state == c->outline_state) return; OutlineButtonAction(focus_cwid, new_state, NULL); } /************************************************************************ * ContainerConvertProc (Trait Method) ************************************************************************/ static void ContainerConvertProc( Widget wid, XtPointer closure, XmConvertCallbackStruct *cs) { enum { XmA_MOTIF_LOSE_SELECTION, XmA_MOTIF_EXPORT_TARGETS, XmA_MOTIF_CLIPBOARD_TARGETS, XmA_COMPOUND_TEXT, XmA_MOTIF_COMPOUND_STRING, XmA_MOTIF_DRAG_OFFSET, XmA_MOTIF_DROP, XmA_TARGETS, NUM_ATOMS }; static char *atom_names[] = { XmS_MOTIF_LOSE_SELECTION, XmS_MOTIF_EXPORT_TARGETS, XmS_MOTIF_CLIPBOARD_TARGETS, XmSCOMPOUND_TEXT, XmS_MOTIF_COMPOUND_STRING, XmS_MOTIF_DRAG_OFFSET, XmS_MOTIF_DROP, XmSTARGETS }; XmContainerWidget cw = (XmContainerWidget)wid; WidgetList items = NULL; int item_count = 0; XtPointer value = NULL; unsigned int length = 0; int format = 0; Atom type = 0; Atom atoms[XtNumber(atom_names)]; /* Get Atom values from cache. */ assert(XtNumber(atom_names) == NUM_ATOMS); XInternAtoms(XtDisplay(wid), atom_names, XtNumber(atom_names), False, atoms); if (cs->target == atoms[XmA_MOTIF_LOSE_SELECTION]) { cw->container.have_primary = False; cs->value = NULL; cs->length = 0; cs->type = 0; cs->status = XmCONVERT_DONE; return; } if ((cs->target == atoms[XmA_TARGETS]) || (cs->target == atoms[XmA_MOTIF_EXPORT_TARGETS]) || (cs->target == atoms[XmA_MOTIF_CLIPBOARD_TARGETS])) { Atom *targargs; int n = 0; if (cs -> target == atoms[XmA_TARGETS]) targargs = XmeStandardTargets(wid,6,&n); else targargs = (Atom*) XtMalloc(sizeof(Atom) * 6); targargs[n++] = XA_PIXMAP; targargs[n++] = atoms[XmA_COMPOUND_TEXT]; targargs[n++] = atoms[XmA_MOTIF_COMPOUND_STRING]; if (cw->container.drag_context != (Widget) NULL) targargs[n++] = atoms[XmA_MOTIF_DRAG_OFFSET]; value = (XtPointer)targargs; format = 32; length = n; type = XA_ATOM; } else if (cs->target == atoms[XmA_MOTIF_DRAG_OFFSET]) { short *offset_args = (short *)XtCalloc(2,sizeof(short)); int n = 0; value = (XtPointer)offset_args; offset_args[n++] = cw->container.drag_offset_x; offset_args[n++] = cw->container.drag_offset_y; format = 16; length = n; type = XA_INTEGER; } else if ((cs->target == XA_PIXMAP) || (cs->target == atoms[XmA_MOTIF_COMPOUND_STRING]) || (cs->target == atoms[XmA_COMPOUND_TEXT])) { if ((cs->selection == atoms[XmA_MOTIF_DROP]) && (cs->location_data)) { items = (WidgetList)XtMalloc(sizeof(Widget)); items[0] = (Widget)cs->location_data; item_count = 1; } else { if ((item_count = cw->container.selected_item_count) == 0) ConvertRefuse(wid,closure,cs); items = GetSelectedCwids(wid); } } if (cs->target == XA_PIXMAP) { Arg wargs[10]; int n,i; Pixmap item_pm; Pixmap * return_pm = (Pixmap *) XtCalloc(item_count,sizeof(Pixmap)); int return_pm_count = 0; for (i = 0; i < item_count; i++) { n = 0; if (GetViewType(items[0]) == XmSMALL_ICON) XtSetArg(wargs[n],XmNsmallIconPixmap,&item_pm); else XtSetArg(wargs[n],XmNlargeIconPixmap,&item_pm); n++; item_pm = XmUNSPECIFIED_PIXMAP; XtGetValues(items[i],wargs,n); if (item_pm != XmUNSPECIFIED_PIXMAP) return_pm[return_pm_count++] = item_pm; } format = 32; type = XA_PIXMAP; value = (XtPointer)return_pm; length = return_pm_count; } else if ((cs->target == atoms[XmA_MOTIF_COMPOUND_STRING]) || (cs->target == atoms[XmA_COMPOUND_TEXT])) { Arg wargs[10]; int n,i; XmString item_xmstr; XmString return_xmstr = XmStringCreateLocalized(""); n = 0; XtSetArg(wargs[n],XmNlabelString,&item_xmstr); n++; for (i = 0; i < item_count; i++) { /* CR 7669: Concatenate efficiently and free strings. */ item_xmstr = NULL; XtGetValues(items[i],wargs,n); if (i > 0) return_xmstr = XmStringConcatAndFree(return_xmstr, XmStringSeparatorCreate()); return_xmstr = XmStringConcatAndFree(return_xmstr, item_xmstr); } format = 8; if (cs->target == atoms[XmA_MOTIF_COMPOUND_STRING]) { type = atoms[XmA_MOTIF_COMPOUND_STRING]; length = XmCvtXmStringToByteStream(return_xmstr, (unsigned char **)&(value)); } else if (cs->target == atoms[XmA_COMPOUND_TEXT]) { type = atoms[XmA_COMPOUND_TEXT]; value = XmCvtXmStringToCT(return_xmstr); length = strlen((char*) value); } XmStringFree(return_xmstr); } if (items) XtFree((char*) items); _XmConvertComplete(wid, value, length, format, type, cs); } /************************************************************************ * ContainerDestinationProc (Trait Method) ************************************************************************/ /*ARGSUSED*/ static void ContainerDestinationProc( Widget wid, XtPointer closure, /* unused */ XmDestinationCallbackStruct *cs) { enum { XmA_MOTIF_DROP, XmA_MOTIF_DRAG_OFFSET, NUM_ATOMS }; static char *atom_names[] = { XmS_MOTIF_DROP, XmS_MOTIF_DRAG_OFFSET }; XmContainerWidget cw = (XmContainerWidget)wid; XmDropProcCallbackStruct * dropproc_cs; Atom atoms[XtNumber(atom_names)]; /* ** In case of a primary transfer operation where a location_data ** has been allocated, register a done proc to be called when ** the data transfer is complete to free the location_data */ if (cs->selection == XA_PRIMARY && cs->location_data) XmeTransferAddDoneProc(cs->transfer_id, FreeLocationData); /* If we aren't sensitive, don't allow transfer */ if (! wid -> core.sensitive || ! wid -> core.ancestor_sensitive) XmTransferDone(cs -> transfer_id, XmTRANSFER_DONE_FAIL); /* Get Atom values from cache. */ assert(XtNumber(atom_names) == NUM_ATOMS); XInternAtoms(XtDisplay(wid), atom_names, XtNumber(atom_names), False, atoms); if (cs->selection != atoms[XmA_MOTIF_DROP]) return; if (cw->container.drag_context == (Widget) NULL) return; if (!CtrLayoutIsSPATIAL(cw)) { cw->container.drag_context = (Widget) NULL; return; } dropproc_cs = (XmDropProcCallbackStruct *)cs->destination_data; cw->container.dropspot.x = dropproc_cs->x; cw->container.dropspot.y = dropproc_cs->y; XmTransferValue(cs->transfer_id, atoms[XmA_MOTIF_DRAG_OFFSET], (XtCallbackProc)MoveItemCallback, (XtPointer)&cw->container.dropspot,cs->time); } /************************************************************************ * ContainerDestPrehookProc (Trait Method) ************************************************************************/ /*ARGSUSED*/ static void ContainerDestPrehookProc( Widget wid, XtPointer closure, /* unused */ XmDestinationCallbackStruct *cs) { XmContainerWidget cw = (XmContainerWidget)wid; XmDropProcCallbackStruct * dropproc_cs; XPoint *loc_data; /* For a PRIMARY selection, don't null out the location_data. * It can point to allocated memory, that will be free when * transfer is done. */ if (cs->selection != XA_PRIMARY) cs->location_data = NULL; if (cs->selection == XInternAtom(XtDisplay(wid),XmS_MOTIF_DROP,False)) { loc_data = (XPoint *) XtMalloc(sizeof(XPoint)); dropproc_cs = (XmDropProcCallbackStruct *) cs->destination_data; loc_data -> x = dropproc_cs->x; loc_data -> y = dropproc_cs->y; cs->location_data = (XtPointer) loc_data; XmeTransferAddDoneProc(cs->transfer_id, FreeLocationData); } } /************************************************ * Free data allocated for destination callback ************************************************/ /*ARGSUSED*/ static void FreeLocationData(Widget wid, /* unused */ XtEnum ignore_op, /* unused */ XmTransferDoneCallbackStruct* cs) { XmDestinationCallbackStruct *ds; ds = _XmTransferGetDestinationCBStruct(cs -> transfer_id); XtFree((char*) ds -> location_data); ds -> location_data = NULL; } /************************************************************************ * ContGetValues (Trait Method) ************************************************************************/ static void ContGetValues( Widget wid, XmContainerData contData) { XmContainerWidget cw = (XmContainerWidget)wid; if (CtrLayoutIsOUTLINE_DETAIL(cw)) { if (CtrLayoutIsDETAIL(cw)) { if (cw->container.detail_order_count) { contData->detail_order_count = cw->container.detail_order_count; contData->detail_order = cw->container.detail_order; /* detail_order might be NULL here */ } else /* take the max detail count and return NULL for the detail_order, so that the icon takes a default order */ if (contData->valueMask & ContDetailOrder) { contData->detail_order_count = MAX (GetDefaultDetailCount(wid), contData->detail_order_count); contData->detail_order = NULL ; } contData->detail_tablist = cw->container.detail_tablist; } else { contData->detail_order = NULL; contData->detail_order_count = 0; contData->detail_tablist = NULL; } /* we want to return a valid firstcolumnwidth even in pure outline, so that clipping can happen */ if (cw->container.real_first_col_width == 0) /* Use what was passed in so we always get something */ contData->first_column_width = contData->first_column_width; else contData->first_column_width = cw->container.real_first_col_width; contData->first_column_width += cw->container.margin_w; } else { contData->detail_order = NULL; contData->detail_order_count = 0; contData->detail_tablist = NULL; contData->first_column_width = 0; /* really the flag that says we're in spatial */ } if ((cw->container.kaddmode) && (_XmGetFocusPolicy(wid) == XmEXPLICIT)) contData->selection_mode = XmADD_MODE; else contData->selection_mode = XmNORMAL_MODE; contData->select_color = cw->container.select_color; } /************************************************************************ * GetVisualEmphasis (Private Function) ************************************************************************/ static unsigned char GetVisualEmphasis( Widget cwid) { XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) == NULL) return(XmNOT_SELECTED); cItemData.valueMask = ContItemVisualEmphasis; cItemTrait->getValues(cwid,(XmContainerItemData)&cItemData); return(cItemData.visual_emphasis); } /************************************************************************ * SetVisualEmphasis (Private Function) ************************************************************************/ static void SetVisualEmphasis( Widget cwid, unsigned char emphasis) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) == NULL) return; cItemData.valueMask = ContItemVisualEmphasis; cItemData.visual_emphasis = emphasis; cw->container.self = True; cItemTrait->setValues(cwid,(XmContainerItemData)&cItemData); cw->container.self = False; } /************************************************************************ * GetViewType (Private Function) ************************************************************************/ static unsigned char GetViewType( Widget cwid) { XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) == NULL) return(XmLARGE_ICON); cItemData.valueMask = ContItemViewType; cItemTrait->getValues(cwid,(XmContainerItemData)&cItemData); return(cItemData.view_type); } /************************************************************************ * SetViewType (Private Function) ************************************************************************/ static void SetViewType( Widget cwid, unsigned char viewtype) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) == NULL) return; cItemData.valueMask = ContItemViewType; cItemData.view_type = viewtype; cw->container.self = True; cItemTrait->setValues(cwid,(XmContainerItemData)&cItemData); cw->container.self = False; } /************************************************************************ * GetIconWidth (Private Function) ************************************************************************/ static Dimension GetIconWidth( Widget cwid) { XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) == NULL) return(cwid->core.width); cItemData.valueMask = ContItemIconWidth; cItemTrait->getValues(cwid,(XmContainerItemData)&cItemData); return(cItemData.icon_width); } /************************************************************************ * GetDefaultDetailCount (Private Function) ************************************************************************/ static Cardinal GetDefaultDetailCount( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerItemDataRec cItemData; XmContainerItemTrait cItemTrait; Widget cwid; CwidNode node; Cardinal detail_count = 0; /* * Get the IconHeader's detail_count first */ if ((cwid = GetRealIconHeader(wid)) && (XtIsManaged(cwid)) && ((XtParent(cwid) == wid) || (XtIsManaged(XtParent(cwid))))) { cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem); cItemData.valueMask = ContItemDetailCount; cItemTrait->getValues(cwid,(XmContainerItemData)&cItemData); detail_count = MAX(detail_count,cItemData.detail_count); } /* * Get MAX detail count of all Icons now */ node = GetFirstNode(cw); while (node) { cwid = node->widget_ptr; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) != NULL) { cItemData.valueMask = ContItemDetailCount; cItemTrait->getValues(cwid,(XmContainerItemData)&cItemData); detail_count = MAX(detail_count,cItemData.detail_count); } node = GetNextNode(node); } return(detail_count); } /************************************************************************ * SetDynamicTabList (Private Function) ************************************************************************/ static XmTabList SetDynamicTabList( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; int tab_size; Cardinal detail_order_count; if (!CtrIsDynamic(cw,TABLIST)) return(NULL); /* Just in case */ /* * Always free the previous XmTabList */ if (CtrIsDynamic(cw,TABLIST) && (cw->container.detail_tablist)) { XmTabListFree(cw->container.detail_tablist); cw->container.detail_tablist = NULL; } /* * If the Container has a valid size, a default tablist of * size detail_order_count shall be returned in detail_tablist. * The tabs in this tablist shall be equal to: * * (XmNwidth-2*XmNmarginWidth-XmNfirstColumnWidth) * /XmNdetailOrderCount * * If XmNwidth is not yet valid, a NULL detail_tablist * is returned, so that the icon can concat all its details * and get a reasonable size. */ if (cw->core.width == 0) return(NULL); tab_size = cw->core.width - (cw->container.margin_w * 2) - cw->container.real_first_col_width; detail_order_count = (cw->container.detail_order_count) ? cw->container.detail_order_count : GetDefaultDetailCount(wid); if (tab_size <= 0) return(NULL); if (detail_order_count == 0) return(NULL); tab_size /= detail_order_count; if (tab_size <=30) return NULL ; /* HACKKKK */ cw->container.detail_tablist = GetDumbTabList(tab_size,detail_order_count); return(cw->container.detail_tablist); } /************************************************************************ * GetDumbTabList (Private Function) ************************************************************************/ static XmTabList GetDumbTabList( int tab_size, Cardinal asked_num_tab) { static int Num_tab = 0 ; static XmTab * Tab_pool = NULL ; XmTabList Tab_list = NULL ; Cardinal i, prev_num_tab = Num_tab ; _XmProcessLock(); if (Num_tab < asked_num_tab) { Num_tab = MAX(asked_num_tab,100); /* HACKKKK */ Tab_pool = (XmTab*) XtRealloc((char*)Tab_pool,Num_tab*sizeof(XmTab)); } /* create more tabs */ for (i=prev_num_tab; igetValues(cwid,(XmContainerItemData)&cItemData); fcw = MAX(fcw,cItemData.icon_width); } /* * Get MAX icon_width of all Icons */ node = GetFirstNode(cw); while (node) { cwid = node->widget_ptr; if ((cItemTrait = (XmContainerItemTrait) XmeTraitGet((XtPointer)XtClass(cwid),XmQTcontainerItem)) != NULL) { cItemData.valueMask = ContItemIconWidth; cItemTrait->getValues(cwid,(XmContainerItemData)&cItemData); cwid_fcw = cItemData.icon_width; } else /* * Just use Gadget width, if it doesn't have the trait. */ cwid_fcw = cwid->core.width; c = GetContainerConstraint(cwid); cwid_fcw += cw->container.ob_width + c->depth * cw->container.outline_indent; fcw = MAX(fcw,cwid_fcw); node = GetNextNode(node); } return(fcw); } /************************************************************************ * ResizeIconWidths (Private Function) * This function gets the preferred width of all icons based on the * current width of Container (this affects dynamic tablists) and * resizes them all to the max. ************************************************************************/ static void ResizeIconWidths( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Widget cwid; XmContainerConstraint c; XtWidgetGeometry desired; Position max_x = 0 ; /*** get the maximum right edge first */ if (cw->core.width == cw->container.ideal_width) max_x = cw->container.ideal_width - cw->container.margin_w; else { if (CtrIsDynamic(cw,TABLIST)) max_x = MAX(cw->container.margin_w + cw->container.real_first_col_width, cw->core.width - cw->container.margin_w); else { /* header first. */ if ((cwid = GetRealIconHeader(wid)) && (XtIsManaged(cwid)) && ((XtParent(cwid) == wid) || (XtIsManaged(XtParent(cwid))))) { XtQueryGeometry(cwid, NULL, &desired); max_x = MAX(max_x, cwid->core.x + desired.width); } /* then the icons */ node = GetFirstNode(cw); while(node) { cwid = node->widget_ptr; c = GetContainerConstraint(cwid); /* This query depends on the current first column width, and the current x position. */ cwid->core.x = cw->container.margin_w + c->depth*cw->container.outline_indent + ((CtrOB_PRESENT(cw))?cw->container.ob_width:0) ; if (LayoutIsRtoLM(cw)) cwid->core.x = (Position)cw->core.width - (Position)cwid->core.width - cwid->core.x; XtQueryGeometry(cwid, NULL, &desired); max_x = MAX(max_x, cwid->core.x + desired.width); node = GetNextNode(node); } } } /*** Then resize */ if ((cwid = GetRealIconHeader(wid)) && (XtIsManaged(cwid)) && ((XtParent(cwid) == wid) || (XtIsManaged(XtParent(cwid))))) { XtQueryGeometry(cwid, NULL, &desired); XmeConfigureObject(cwid, cwid->core.x, cwid->core.y, max_x - cwid->core.x, cwid->core.height, cwid->core.border_width); /* also recongifure the DA parent if any */ if (XtParent(cwid) != wid) { XmeConfigureObject(cw->container.icon_header, /* the DA */ cw->container.icon_header->core.x, cw->container.icon_header->core.y, cwid->core.width + 2*cw->container.margin_w, cwid->core.height + cw->container.margin_h, cw->core.border_width); } } node = GetFirstNode(cw); while(node) { cwid = node->widget_ptr; c = GetContainerConstraint(cwid); cwid->core.x = cw->container.margin_w + c->depth*cw->container.outline_indent + ((CtrOB_PRESENT(cw))?cw->container.ob_width:0) ; cwid->core.width = max_x - cwid->core.x; if (LayoutIsRtoLM(cw)) cwid->core.x = (Position)cw->core.width - (Position)cwid->core.width - cwid->core.x; XmeConfigureObject(cwid, cwid->core.x, cwid->core.y, cwid->core.width, cwid->core.height, cwid->core.border_width); node = GetNextNode(node); } } /************************************************************************ * Layout (Private Function) ************************************************************************/ static void Layout( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; if (CtrLayoutIsOUTLINE_DETAIL(cw)) LayoutOutlineDetail(wid); else LayoutSpatial(wid,False,NULL); } /************************************************************************ * RequestOutlineDetail (Private Function) ************************************************************************/ static void RequestOutlineDetail( Widget wid, XtWidgetGeometry * geo_desired) { XmContainerWidget cw = (XmContainerWidget)wid; Dimension saved_width = 0 ; /* deal with special requirements for width */ if (geo_desired->width) { saved_width = cw->core.width; cw->core.width = geo_desired->width; } /* let's find out about our preferred size */ cw->container.ideal_width = 0; cw->container.ideal_height = 0; GetSize(wid,&cw->container.ideal_width,&cw->container.ideal_height); geo_desired->request_mode = (CWWidth | CWHeight); /* see if a constraint was placed on the preferred size */ if (!(geo_desired->width)) geo_desired->width = cw->container.ideal_width; else cw->core.width = saved_width ; if (!(geo_desired->height)) geo_desired->height = cw->container.ideal_height; if (geo_desired->width < 1) geo_desired->width = cw->core.width ; if (geo_desired->height < 1) geo_desired->height = cw->core.height ; _XmMakeGeometryRequest(wid,geo_desired); if (XtIsRealized((Widget)cw)) XClearArea(XtDisplay((Widget)cw),XtWindow((Widget)cw),0,0,0,0,True); LayoutOutlineDetail(wid); cw->container.prev_width = cw->core.width; } /************************************************************************ * LayoutOutlineDetail (Private Function) ************************************************************************/ static void LayoutOutlineDetail( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c; XmContainerConstraint pc; Position x,y,ob_y; CwidNode node; Widget cwid; int n_outline_segs,seg_idx; XPoint * point_at_depth = NULL; int i; if (CtrLayoutIsDETAIL(cw)) { if (CtrIsDynamic(cw,TABLIST)) SetDynamicTabList(wid); ResizeIconWidths(wid); } /* ** assert(c->depth == pc->depth + 1); ** for children with entry-parents, and otherwise ** assert(c->depth == 0); */ /* * Create array of XSegments to hold line descriptions for Outline. */ n_outline_segs = seg_idx = 0; node = GetFirstNode(cw); while (node) /* * So, how many XSegments do we need? */ { c = GetContainerConstraint(node->widget_ptr); if (c->depth != 0) n_outline_segs += 2; node = GetNextNode(node); } if (cw->container.outline_seg_count != n_outline_segs) { if (cw->container.outline_segs) XtFree((char*)cw->container.outline_segs); cw->container.outline_segs = (XSegment *)XtCalloc (n_outline_segs,sizeof(XSegment)); cw->container.outline_seg_count = n_outline_segs; } point_at_depth = (XPoint *)XtCalloc((cw->container.max_depth + 1), sizeof(XPoint)); y = cw->container.margin_h; if (CtrLayoutIsDETAIL(cw) && cw->container.icon_header) { /* * Position the header/Drawing-area. * assert: cw->container.icon_header is valid */ Widget real_icon_header = GetRealIconHeader(wid), header_parent = XtParent(real_icon_header) ; /* only if it is managed */ if (XtIsManaged(real_icon_header) && ((header_parent == wid) || (XtIsManaged(header_parent)))) { if (header_parent != wid) { /* auto SW case : DA is the parent of the header */ /* set y of the container so that it glue the bottom of the real icon header *inside* the DA. So no margin_h added here, container must start underneath the DA/icon header because it has a margin height that need to be hidden (replaced by the DA one) */ if (0 == cw->core.y) cw->core.y = real_icon_header->core.height ; /* resize the DA to remove the bottom margin */ XmeConfigureObject(header_parent, header_parent->core.x, header_parent->core.y, real_icon_header->core.width + 2*cw->container.margin_w, real_icon_header->core.height + cw->container.margin_h, cw->core.border_width); } else { XmeConfigureObject(cw->container.icon_header, cw->container.margin_w, cw->container.margin_h, cw->container.icon_header->core.width, cw->container.icon_header->core.height,0); y += cw->container.icon_header->core.height; } } } node = GetFirstNode(cw); while (node) { cw->container.last_node = node; cwid = node->widget_ptr; c = GetContainerConstraint(cwid); if (LayoutIsRtoLM(cw)) x = cw->core.width - cw->container.margin_w - c->depth * cw->container.outline_indent; else x = cw->container.margin_w + c->depth * cw->container.outline_indent; ob_y = y + (cwid->core.height - cw->container.ob_height) / 2; if (CtrOB_PRESENT(cw) && LayoutIsRtoLM(cw)) x -= cw->container.ob_width; if ((node->child_ptr) && CtrOB_PRESENT(cw)) { if (!c->related_cwid) MakeOutlineButton(cwid); /* * we need to hide the outline button if they appear * after the first column limit */ if ((!LayoutIsRtoLM(cw) && ((x + cw->container.ob_width) > (cw->container.margin_w + cw->container.real_first_col_width))) || (LayoutIsRtoLM(cw) && (x < (Position)(cw->core.width - cw->container.margin_w - cw->container.real_first_col_width)))) HideCwid(c->related_cwid) ; else XmeConfigureObject(c->related_cwid,x,ob_y, cw->container.ob_width, cw->container.ob_height,0); } else if (c->related_cwid) { XtDestroyWidget(c->related_cwid); c->related_cwid = NULL; } if (CtrOB_PRESENT(cw) && !LayoutIsRtoLM(cw)) x += cw->container.ob_width; /* * we don't want the x position to be bigger than * the firstcolumnwidth, otherwize the arithmetic in * Icong get confused. Hackk */ if (LayoutIsRtoLM(cw)) x = MAX(x,(Position)(cw->core.width - cw->container.margin_w - cw->container.real_first_col_width + 1)); else x = MIN(x,(Position)(cw->container.margin_w + cw->container.real_first_col_width - 1)); /* * Calculate Outline lines */ if (point_at_depth[c->depth].x == 0) { point_at_depth[c->depth].x = cw->container.margin_w + cw->container.outline_indent * c->depth; } if (CtrOB_PRESENT(cw)) point_at_depth[c->depth].y = ob_y + cw->container.ob_height; else point_at_depth[c->depth].y = y + cwid->core.height; if (c->entry_parent) { pc = GetContainerConstraint(c->entry_parent); if (CtrOB_PRESENT(cw)) { /* Optimally, the line would be drawn from the center of the Outline Button (OB) ** causing problems when indentation is small. So we drop the line ** MIN (midpoint of OB, midpoint of OB left & child left */ cw->container.outline_segs[seg_idx].x1 = MIN((point_at_depth[pc->depth].x + cw->container.ob_width/2), (point_at_depth[pc->depth].x +point_at_depth[c->depth].x)/2 ); } else { /* Optimally, the line would be drawn from the center of the parent ** causing problems when parent labelString is too long. So we drop the ** line MIN (midpoint of parent, midpoint of parent left & child left edge) */ cw->container.outline_segs[seg_idx].x1 = MIN((point_at_depth[pc->depth].x + GetIconWidth(c->entry_parent)/2), (point_at_depth[pc->depth].x +point_at_depth[c->depth].x)/2 ); } cw->container.outline_segs[seg_idx].y1 = point_at_depth[pc->depth].y; cw->container.outline_segs[seg_idx].x2 = cw->container.outline_segs[seg_idx].x1; cw->container.outline_segs[seg_idx].y2 = y + cwid->core.height/2; cw->container.outline_segs[seg_idx + 1].x1 = cw->container.outline_segs[seg_idx].x2; cw->container.outline_segs[seg_idx + 1].y1 = cw->container.outline_segs[seg_idx].y2; cw->container.outline_segs[seg_idx + 1].x2 = cw->container.margin_w + cw->container.outline_indent * c->depth; if (CtrOB_PRESENT(cw) && (!c->related_cwid)) cw->container.outline_segs[seg_idx + 1].x2 += cw->container.ob_width; cw->container.outline_segs[seg_idx + 1].y2 = cw->container.outline_segs[seg_idx].y2; seg_idx += 2; } if (LayoutIsRtoLM(cw)) x = x - (Position)cwid->core.width; XmeConfigureObject(cwid,x,y,cwid->core.width,cwid->core.height,0); y += cwid->core.height; node = GetNextNode(node); } /* * Free the Malloc'd point_at_depth. * If Left-to-Right, reverse all the x1's & x2's and adjust. */ if (point_at_depth) XtFree((char*)point_at_depth); for (i = 0; i < cw->container.outline_seg_count; i++) { int max_x = (int)cw->container.real_first_col_width + (int)cw->container.margin_w; /* we don't want the lines to be drawn after the first column width, so we clip here the x positions of the segments */ cw->container.outline_segs[i].x1 = MIN(max_x, cw->container.outline_segs[i].x1); cw->container.outline_segs[i].x2 = MIN(max_x, cw->container.outline_segs[i].x2); } if (LayoutIsRtoLM(cw)) { int adjust; adjust = (int)cw->core.width - (int)cw->container.ideal_width; for (i = 0; i < cw->container.outline_seg_count; i++) { cw->container.outline_segs[i].x1 = MAX(0, cw->container.ideal_width - cw->container.outline_segs[i].x1 + adjust); cw->container.outline_segs[i].x2 = MAX(0, cw->container.ideal_width - cw->container.outline_segs[i].x2 + adjust); } } } /************************************************************************ * LayoutSpatial (Private Function) ************************************************************************/ static void LayoutSpatial( Widget wid, Boolean growth_req_allowed, CwidNode stop_node) { XmContainerWidget cw = (XmContainerWidget)wid; int cell_width,cell_height; int width_in_cells,height_in_cells; CwidNode node; if (!((XmContainerWidgetClass)XtClass(wid))->container_class.place_item) return; if (CtrSpatialStyleIsGRID(cw) || CtrSpatialStyleIsCELLS(cw)) /* * Let's see if things have changed enough so that we have to reset. */ { cell_width = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellw : cw->container.real_large_cellw; cell_height = (CtrViewIsSMALL_ICON(cw)) ? cw->container.real_small_cellh : cw->container.real_large_cellh; width_in_cells = (cw->core.width - 2 * cw->container.margin_w) / cell_width; height_in_cells = (cw->core.height - 2 * cw->container.margin_h) / cell_height; if (((width_in_cells != cw->container.current_width_in_cells) && (CtrIsHORIZONTAL(wid))) || ((height_in_cells != cw->container.current_height_in_cells) && (CtrIsVERTICAL(wid)))) (*((XmContainerWidgetClass) XtClass(wid))->container_class.place_item)(wid,NULL,ANY_FIT); else /* * Just grow the number of cells if only the Minor dimension * has changed. */ { cw->container.current_width_in_cells = width_in_cells; cw->container.current_height_in_cells = height_in_cells; if ((width_in_cells * height_in_cells) > cw->container.cell_count) { int i,old_cell_count = cw->container.cell_count; cw->container.cell_count = width_in_cells * height_in_cells; if (CtrIsHORIZONTAL(cw)) /* For "clipped" items */ cw->container.cell_count += height_in_cells; else cw->container.cell_count += width_in_cells; cw->container.cells = (int *)XtRealloc((char *)cw->container.cells, (sizeof(int) * (cw->container.cell_count))); for (i = old_cell_count; i < cw->container.cell_count; i++) cw->container.cells[i] = 0; } } } node = GetFirstNode(cw); while (node) { Widget cwid = node -> widget_ptr; cw->container.last_node = node; if (CtrItemIsPlaced(cwid)) PlaceCwid(cwid,cwid->core.x,cwid->core.y); else { /* Not placed */ (*((XmContainerWidgetClass) XtClass(wid))->container_class.place_item) (wid,cwid, (growth_req_allowed ? EXACT_FIT : ANY_FIT)); if (!CtrItemIsPlaced(cwid) && (growth_req_allowed)) /* * See if we can grow and then try again. */ { if (RequestSpatialGrowth(wid,cwid)) /* * If RequestSpatialGrowth succeeds it will update * core width/height. Now, call LayoutSpatial again * so it can update info to keep track of cells, etc. * and can place the item we just got growth for. * Don't set the "growth_req_allowed" parameter or * we could recurse forever. */ LayoutSpatial(wid,False,node); else /* try again, but don't be so picky */ { (*((XmContainerWidgetClass) XtClass(wid))->container_class.place_item) (wid,cwid,ANY_FIT); if (!CtrItemIsPlaced(cwid)) HideCwid(cwid); } } } if ((stop_node) && (node == stop_node)) /* * This is just a little hack to keep from having to traverse * through all the nodes when we recursively call LayoutSpatial(). */ return; node = GetNextNode(node); } } /************************************************************************ * SetCellSizes (Private Function) ************************************************************************/ static void SetCellSizes( Widget wid) { if (!CtrSpatialStyleIsGRID(wid) && !CtrSpatialStyleIsCELLS(wid)) return; if (CtrViewIsSMALL_ICON(wid)) SetSmallCellSizes(wid); else SetLargeCellSizes(wid); } /************************************************************************ * SetSmallCellSizes (Private Function) ************************************************************************/ static void SetSmallCellSizes( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; if (!CtrDynamicSmallCellHeight(cw)) cw->container.real_small_cellh = cw->container.small_cell_height; if (!CtrDynamicSmallCellWidth(cw)) cw->container.real_small_cellw = cw->container.small_cell_width; if (!CtrDynamicSmallCellHeight(cw) && !CtrDynamicSmallCellWidth(cw)) return; if ((cw->container.first_node) && (cw->container.small_cell_dim_fixed)) return; cw->container.small_cell_dim_fixed = True; if (cw->container.first_node) { node = cw->container.first_node; if (CtrDynamicSmallCellHeight(cw)) cw->container.real_small_cellh = cw->container.first_node->widget_ptr->core.height; if (CtrDynamicSmallCellWidth(cw)) cw->container.real_small_cellw = cw->container.first_node->widget_ptr->core.width; while (node) { if (CtrSpatialStyleIsGRID(cw)) /* * GRID: cell should be size of largest cwid. */ { if (CtrDynamicSmallCellHeight(cw)) cw->container.real_small_cellh = MAX( cw->container.real_small_cellh, node->widget_ptr->core.height); if (CtrDynamicSmallCellWidth(cw)) cw->container.real_small_cellw = MAX( cw->container.real_small_cellw, node->widget_ptr->core.width); } else { /* * CELLS: cell should be size of smallest cwid. */ if (CtrDynamicSmallCellHeight(cw)) cw->container.real_small_cellh = MIN( cw->container.real_small_cellh, node->widget_ptr->core.height); if (CtrDynamicSmallCellWidth(cw)) cw->container.real_small_cellw = MIN( cw->container.real_small_cellw, node->widget_ptr->core.width); } node = GetNextNode(node); } } else { if (CtrDynamicSmallCellHeight(cw)) cw->container.real_small_cellh = MAX(10,(int) (.02 * HeightOfScreen(XtScreen((Widget)cw)))); if (CtrDynamicSmallCellWidth(cw)) cw->container.real_small_cellw = MAX(10,(int) (.02 * WidthOfScreen(XtScreen((Widget)cw)))); } } /************************************************************************ * SetLargeCellSizes (Private Function) ************************************************************************/ static void SetLargeCellSizes( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; if (!CtrDynamicLargeCellHeight(cw)) cw->container.real_large_cellh = cw->container.large_cell_height; if (!CtrDynamicLargeCellWidth(cw)) cw->container.real_large_cellw = cw->container.large_cell_width; if (!CtrDynamicLargeCellHeight(cw) && !CtrDynamicLargeCellWidth(cw)) return; if ((cw->container.first_node) && (cw->container.large_cell_dim_fixed)) return; if (cw->container.first_node) { cw->container.large_cell_dim_fixed = True; node = cw->container.first_node; if (CtrDynamicLargeCellHeight(cw)) cw->container.real_large_cellh = cw->container.first_node->widget_ptr->core.height; if (CtrDynamicLargeCellWidth(cw)) cw->container.real_large_cellw = cw->container.first_node->widget_ptr->core.width; while (node) { if (CtrSpatialStyleIsGRID(cw)) /* * GRID: cell should be size of largest cwid. */ { if (CtrDynamicLargeCellHeight(cw)) cw->container.real_large_cellh = MAX( cw->container.real_large_cellh, node->widget_ptr->core.height); if (CtrDynamicLargeCellWidth(cw)) cw->container.real_large_cellw = MAX( cw->container.real_large_cellw, node->widget_ptr->core.width); } else { /* * CELLS: cell should be size of smallest cwid. */ if (CtrDynamicLargeCellHeight(cw)) cw->container.real_large_cellh = MIN( cw->container.real_large_cellh, node->widget_ptr->core.height); if (CtrDynamicLargeCellWidth(cw)) cw->container.real_large_cellw = MIN( cw->container.real_large_cellw, node->widget_ptr->core.width); } node = GetNextNode(node); } } else { if (CtrDynamicLargeCellHeight(cw)) cw->container.real_large_cellh = MAX(20,(int) (.04 * HeightOfScreen(XtScreen((Widget)cw)))); if (CtrDynamicLargeCellWidth(cw)) cw->container.real_large_cellw = MAX(20,(int) (.04 * WidthOfScreen(XtScreen((Widget)cw)))); } } /************************************************************************ * SizeOutlineButton (Private Function) ************************************************************************/ static void SizeOutlineButton( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; Arg wargs[10]; int n; Dimension width,height; /* * Create dummy outline button so we can get size. */ n = 0; XtSetArg(wargs[n],XmNlabelType,XmPIXMAP); n++; XtSetArg(wargs[n],XmNlabelPixmap,cw->container.expanded_state_pixmap); n++; XtSetArg(wargs[n],XmNmarginWidth,0); n++; XtSetArg(wargs[n],XmNmarginHeight,0); n++; cw->container.self = True; if (cw->container.size_ob) XtSetValues(cw->container.size_ob,wargs,n); else { cw->container.create_cwid_type = CONTAINER_OUTLINE_BUTTON; cw->container.size_ob = XtCreateWidget(OBNAME, xmPushButtonGadgetClass,(Widget)cw,wargs,n); cw->container.create_cwid_type = CONTAINER_ICON; } XtVaGetValues(cw->container.size_ob,XmNwidth,&cw->container.ob_width, XmNheight,&cw->container.ob_height,NULL); n = 0; XtSetArg(wargs[n],XmNlabelType,XmPIXMAP); n++; XtSetArg(wargs[n],XmNlabelPixmap, cw->container.collapsed_state_pixmap); n++; XtSetValues(cw->container.size_ob,wargs,n); cw->container.self = False; XtVaGetValues(cw->container.size_ob, XmNwidth,&width,XmNheight,&height,NULL); cw->container.ob_width = MAX(cw->container.ob_width,width); cw->container.ob_height = MAX(cw->container.ob_height,height); } /************************************************************************ * UpdateGCs (Private Function) ************************************************************************/ static void UpdateGCs( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; XGCValues values; XtGCMask valueMask, unusedMask; /* * Free any previous GC's */ if (cw->container.normalGC) XtReleaseGC(wid,cw->container.normalGC); if (cw->container.marqueeGC) XtReleaseGC(wid,cw->container.marqueeGC); /* * Get GC's */ valueMask = GCForeground | GCBackground | GCGraphicsExposures; unusedMask = GCClipXOrigin | GCClipYOrigin | GCFont; values.foreground = cw->manager.foreground; values.background = cw->core.background_pixel; values.graphics_exposures = False; cw->container.normalGC = XtAllocateGC(wid, 0, valueMask, &values, GCClipMask, unusedMask); valueMask = GCForeground | GCSubwindowMode | GCFunction; values.foreground = cw->core.background_pixel ^ cw->manager.foreground; values.subwindow_mode = IncludeInferiors; values.function = GXxor; cw->container.marqueeGC = XtAllocateGC(wid, 0, valueMask, &values, GCClipMask, 0); } /************************************************************************ * GetSpatialSizeCellAdjustment (Private Function) * This routine does a trial placement of all items using the * information in the array passed in. If not all items fit, * it adds 1 to width_in_cells & height_in_cells and calls itself * recursively until everything fits. This routine assumes * placement goes left-to-right-top-to-bottom, but the calculations * arrived at should work for all layoutDirections. ************************************************************************/ static void GetSpatialSizeCellAdjustment( Widget wid, int *parm_width_in_cells, int *parm_height_in_cells, ContainerCwidCellInfo cwid_info, int cwid_info_count) { int width_in_cells = *parm_width_in_cells; int height_in_cells = *parm_height_in_cells; Boolean all_cwids_fit; Boolean cwid_placed; Boolean this_spot_fits; Boolean *cell_occupied; int i,start_row,start_col,row,col; cell_occupied = (Boolean *)XtCalloc((width_in_cells * height_in_cells), sizeof(Boolean)); i = 0; all_cwids_fit = True; while ((i < cwid_info_count) && (all_cwids_fit)) /* * Keep placing all the cwids into the cell_occupied[] grid until * one doesn't fit. */ { start_col = 0; cwid_placed = False; while ((start_col < width_in_cells) && (!cwid_placed)) { start_row = 0; while ((start_row < height_in_cells) && (!cwid_placed)) { /* * Cycle through all the [col,row] combinations in the * cell_occupied[] grid until we find one that the current cwid * will fit into. */ this_spot_fits = True; col = start_col; while ((col < start_col + cwid_info[i].cwid_width_in_cells) && (this_spot_fits)) { row = start_row; while ((row < start_row + cwid_info[i].cwid_height_in_cells) && (this_spot_fits)) /* * Test all the cells needed by this cwid at this particular * spot in the cell_occupied[] grid until we see that one is * out-of-bounds or already occupied. */ { this_spot_fits = ((col < width_in_cells) && (row < height_in_cells) && (!(cell_occupied[col * width_in_cells + row]))); row++; } col++; } if (this_spot_fits) /* Mark everything as occupied */ for (col = start_col; col < start_col + cwid_info[i].cwid_width_in_cells; col++) for (row = start_row; row < start_row + cwid_info[i].cwid_height_in_cells; row++) cell_occupied[col * width_in_cells + row] = True; cwid_placed = this_spot_fits; start_row++; } start_col++; } all_cwids_fit = cwid_placed; i++; } XtFree((char*)cell_occupied); if (!all_cwids_fit) /* * Not big enough for all the cwids, increment width/height and * try it again. */ { width_in_cells++; height_in_cells++; GetSpatialSizeCellAdjustment(wid,&width_in_cells,&height_in_cells, cwid_info,cwid_info_count); *parm_width_in_cells = width_in_cells; *parm_height_in_cells = height_in_cells; } } /************************************************************************ * CreateIconHeader (Private Function) ************************************************************************/ static void CreateIconHeader( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; Widget header_parent = wid ; Arg sargs[10]; Cardinal n = 0; unsigned char scrollp = XmAPPLICATION_DEFINED ; #define NO_PARENT 0 #define SWINDOW_PARENT 1 #define CWINDOW_PARENT 2 int inScrolledWindow = NO_PARENT; cw->container.self = True; cw->container.create_cwid_type = CONTAINER_HEADER; /* * Set up args for DrawingArea and Create. */ { XmScrollFrameTrait scrollFrameTrait = (XmScrollFrameTrait) XmeTraitGet((XtPointer)XtClass(XtParent(wid)),XmQTscrollFrame); if ((NULL != scrollFrameTrait) && scrollFrameTrait->getInfo(XtParent(wid),NULL,NULL,NULL)) inScrolledWindow = SWINDOW_PARENT; if (NO_PARENT == inScrolledWindow) { XmClipWindowTrait clipWindowTrait = (XmClipWindowTrait) XmeTraitGet((XtPointer)XtClass(XtParent(wid)),_XmQTclipWindow); if (NULL != clipWindowTrait) inScrolledWindow = CWINDOW_PARENT; } } if (NO_PARENT != inScrolledWindow) { Widget sWindow = (SWINDOW_PARENT == inScrolledWindow) ? XtParent(wid) : XtParent(XtParent(wid)); scrollp = XmAUTOMATIC ; /* use an intermediate DA so that we can have margins */ n = 0 ; XtSetArg(sargs[n], XmNscrolledWindowChildType, XmSCROLL_HOR); n++; XtSetArg(sargs[n], XmNmarginHeight, cw->container.margin_h); n++ ; XtSetArg(sargs[n], XmNmarginWidth, cw->container.margin_w); n++ ; XtSetArg(sargs[n], XmNforeground, cw->manager.foreground); n++; XtSetArg(sargs[n], XmNbackground, cw->core.background_pixel); n++; XtSetArg(sargs[n], XmNbackgroundPixmap, cw->core.background_pixmap); n++; XtSetArg(sargs[n], XmNborderWidth, cw->core.border_width); n++; XtSetArg(sargs[n], XmNborderColor, cw->core.border_pixel); n++; XtSetArg(sargs[n], XmNborderPixmap, cw->core.border_pixmap); n++; XtSetArg(sargs[n], XmNtraversalOn, False); n++; header_parent = XmCreateDrawingArea(sWindow, DANAME, sargs, n); } /* * Set up args for IconHeader and Create. */ n = 0; XtSetArg(sargs[n],XmNcontainerID,wid); n++; XtSetArg(sargs[n],XmNshadowThickness,0); n++; XtSetArg(sargs[n],XmNtraversalOn,False); n++; /* not really necessary */ XtSetArg(sargs[n],XmNlargeIconPixmap, XmUNSPECIFIED_PIXMAP); n++; XtSetArg(sargs[n],XmNsmallIconPixmap, XmUNSPECIFIED_PIXMAP); n++; assert(cw->container.detail_heading_count > 0) ; XtSetArg(sargs[n],XmNlabelString, cw->container.detail_heading[0]); n++; if (cw->container.detail_heading_count > 1) { XtSetArg(sargs[n],XmNdetail,&(cw->container.detail_heading[1])); n++; } XtSetArg(sargs[n],XmNdetailCount, cw->container.detail_heading_count - 1); n++; cw->container.icon_header = XmCreateIconHeader(header_parent, HEADERNAME, sargs,n); if (scrollp == XmAUTOMATIC) { /* set y of the container so that it glue the bottom of the Icon header *inside* the DA, that is, it overlap the DA */ if (CtrLayoutIsDETAIL(cw)) /* if (0 == cw->core.y) */ cw->core.y = cw->container.icon_header->core.height ; /* also resize the DA to remove the bottom margin */ XmeConfigureObject(header_parent, header_parent->core.x, header_parent->core.y, cw->container.icon_header->core.width + 2*cw->container.margin_w, cw->container.icon_header->core.height + cw->container.margin_h, header_parent->core.border_width); /* manage the child inside */ XtManageChild(cw->container.icon_header); /* keep the reference to the DA parent, since that's the one to manage/unmanaged all the time */ cw->container.icon_header = header_parent ; } /* if not scrolling, no need to do anything it, it will be dealt with as a regular kid */ /* set the internal creation flag down */ cw->container.create_cwid_type = CONTAINER_ICON; cw->container.self = False; } /************************************************************************ * GetRealIconHeader (Private Function) ************************************************************************/ static Widget GetRealIconHeader( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; if (!cw->container.icon_header) return NULL; /* determine the real icon_header id */ if (XtParent(cw->container.icon_header) != wid) /* we are in the SW auto case where a DA was created as the parent of the icon_header and store in container icon_header. */ return ((CompositeWidget)(cw->container.icon_header)) ->composite.children[0] ; else return cw->container.icon_header ; } /************************************************************************ * UpdateIconHeader (Private Function) ************************************************************************/ static void UpdateIconHeader( Widget wid, Boolean count_only) { XmContainerWidget cw = (XmContainerWidget)wid; Arg wargs[10]; int n; Widget icon_header = GetRealIconHeader(wid); cw->container.self = True ; /* * Set up args for IconHeader. */ assert (cw->container.detail_heading_count > 0); n = 0; if (!count_only) { XtSetArg(wargs[n],XmNlabelString, cw->container.detail_heading[0]); n++; if (cw->container.detail_heading_count > 1) { XtSetArg(wargs[n],XmNdetail,&(cw->container.detail_heading[1])); n++; } } XtSetArg(wargs[n],XmNdetailCount, cw->container.detail_heading_count - 1); n++; XtSetValues(icon_header,wargs,n); cw->container.self = True ; } /************************************************************************ * ChangeView (Private Function) ************************************************************************/ static void ChangeView( Widget wid, unsigned char view) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Widget cwid; node = cw->container.first_node; while (node) { cwid = node->widget_ptr; SetViewType(cwid,view); /* setting a new view type will have the child request and get its preferred size */ /* * Get the next cwid, whether it's visible or not */ if (node->child_ptr) node = node->child_ptr; else if (node->next_ptr) node = node->next_ptr; else node = GetNextUpLevelNode(node); } } /************************************************************************ * NewNode (Private Function) ************************************************************************/ static CwidNode NewNode( Widget cwid) { XmContainerConstraint c = GetContainerConstraint(cwid); CwidNode new_node; /* * Create the new CwidNode structure. */ new_node = (CwidNode)XtCalloc(1,sizeof(XmCwidNodeRec)); new_node->widget_ptr = cwid; /* node ----> widget link */ c->node_ptr = new_node; /* widget --> node link */ return(new_node); } /************************************************************************ * InsertNode (Private Function) ************************************************************************/ static void InsertNode( CwidNode node) { XmContainerWidget cw; XmContainerConstraint c; XmContainerConstraint pc; /* parent's constraints */ XmContainerConstraint sc; /* sibling's constraints */ Widget cwid; CwidNode prev_node; CwidNode next_node; CwidNode parent_node; int count = 0; /* resequence as we go along so that ** XmNpositionIndex always reflects the child's ** position within all widgets which name the ** same widget as their XmNentryParent; no ** widgets have the same value for ** XmNpositionIndex; XmNpositionIndex has no ** gaps */ cwid = node->widget_ptr; cw = (XmContainerWidget)XtParent(cwid); c = GetContainerConstraint(cwid); /* * Find the first cwid within XmNentryParent, NULL if none. */ if (c->entry_parent == NULL) { parent_node = NULL; prev_node = cw->container.first_node; } else { pc = GetContainerConstraint(c->entry_parent); parent_node = pc->node_ptr; prev_node = parent_node->child_ptr; } if (prev_node == NULL) { /* * Assume this is the first and only cwid within XmNentryParent. */ next_node = NULL; } else { /* * Chain through this level until we find the correct position. */ next_node = prev_node; prev_node = NULL; while (next_node) { sc = GetContainerConstraint(next_node->widget_ptr); if ((c->position_index != XmLAST_POSITION) && (c->position_index <= sc->position_index)) break; sc->position_index = count++; prev_node = next_node; next_node = next_node->next_ptr; } } c->position_index = count++; /* * Insert the node into the linked list. */ node->parent_ptr = parent_node; if ((node->prev_ptr = prev_node) != NULL) prev_node->next_ptr = node; if ((node->next_ptr = next_node) != NULL) next_node->prev_ptr = node; if ((parent_node) && (node->prev_ptr == NULL)) parent_node->child_ptr = node; /* if we've done other parts right, we shouldn't need to do this part */ next_node = node->next_ptr; while (next_node) { sc = GetContainerConstraint(next_node->widget_ptr); sc->position_index = count++; next_node = next_node->next_ptr; } /* * Update cw->container.first_node, if we're now the first node. */ if (node->next_ptr == cw->container.first_node) cw->container.first_node = node; } /************************************************************************ * SeverNode (Private Function) ************************************************************************/ static void SeverNode( CwidNode node) { XmContainerWidget cw; CwidNode parent_node; CwidNode prev_node; CwidNode next_node; if (node == NULL) return; cw = (XmContainerWidget)XtParent(node->widget_ptr); /* * Find new cw->container.first_node, if we're now the first node. */ if (node == cw->container.first_node) { if (node->next_ptr) cw->container.first_node = node->next_ptr; else cw->container.first_node = GetNextUpLevelNode(node); } /* * If we're child #1, fix up parent-child pointers. */ if ((node->prev_ptr == NULL) && (node->parent_ptr)) { parent_node = node->parent_ptr; parent_node->child_ptr = node->next_ptr; } /* * Unlink node from the linked list. */ if (node->prev_ptr) { prev_node = node->prev_ptr; prev_node->next_ptr = node->next_ptr; } if (node->next_ptr) { next_node = node->next_ptr; next_node->prev_ptr = node->prev_ptr; } } /************************************************************************ * DeleteNode (Private Function) ************************************************************************/ static void DeleteNode( Widget cwid) { XmContainerConstraint c = GetContainerConstraint(cwid); CwidNode target_node; CwidNode child_node; CwidNode target_child; if ((target_node = c->node_ptr) == NULL) return; /* * Delete any children first. */ child_node = target_node->child_ptr; while (child_node) { target_child = child_node; child_node = child_node->next_ptr; DeleteNode(target_child->widget_ptr); } SeverNode(target_node); XtFree((char*)target_node); c->node_ptr = NULL; c->visible_in_outline = False; } /************************************************************************ * GetFirstNode (Private Function) ************************************************************************/ static CwidNode GetFirstNode( XmContainerWidget cw) { if (NodeIsActive(cw->container.first_node)) return cw->container.first_node; else return GetNextNode(cw->container.first_node) ; } /************************************************************************ * GetNextNode (Private Function) ************************************************************************/ static CwidNode GetNextNode( CwidNode start_node) { XmContainerWidget cw; CwidNode node; if (!start_node) return(NULL); cw = (XmContainerWidget)XtParent(start_node->widget_ptr); if (CtrLayoutIsSPATIAL(cw)) { node = start_node->next_ptr; while (node) { if (NodeIsActive(node)) return(node); node = node->next_ptr; } return(NULL); } /* depth-first search of tree */ if (NodeIsActive(start_node) && (start_node->child_ptr)) node = start_node->child_ptr; else if (start_node->next_ptr) node = start_node->next_ptr; else node = GetNextUpLevelNode(start_node); while (node) { if (NodeIsActive(node)) return(node); if (node->next_ptr) node = node->next_ptr; else node = GetNextUpLevelNode(node); } return(NULL); } /************************************************************************ * NodeIsActive (Private Function) ************************************************************************/ static Boolean NodeIsActive( CwidNode node) { XmContainerWidget cw; XmContainerConstraint c; if (!node) return(False); if (!XtIsManaged(node->widget_ptr)) return(False); cw = (XmContainerWidget)XtParent(node->widget_ptr); if (CtrLayoutIsOUTLINE_DETAIL(cw)) { c = GetContainerConstraint(node->widget_ptr); if (!c->visible_in_outline) return(False); } return(True); } /************************************************************************ * GetNextUpLevelNode (Private Function) ************************************************************************/ static CwidNode GetNextUpLevelNode( CwidNode start_node) { CwidNode node; node = start_node; while (node) { node = node->parent_ptr; if (node) if (node->next_ptr) return(node->next_ptr); } return(NULL); } static void ContainerResetDepths (XmContainerConstraint c) { CwidNode node = c->node_ptr->child_ptr; while (node) { Widget child = node->widget_ptr; XmContainerConstraint cc = GetContainerConstraint(child); cc->depth = c->depth + 1; ContainerResetDepths(cc); node = node->next_ptr; } } /* true if newEntryParent (or any other widget) is a descendant of the target; ** determine by looking upward in the tree for a match. Returns True for the ** widget itself. */ static Boolean ContainerIsDescendant (Widget containerChild, Widget newEntryParent) { XmContainerConstraint nepc = GetContainerConstraint(newEntryParent); CwidNode node = nepc->node_ptr; while (node) { if (node->widget_ptr == containerChild) return True; node = node->parent_ptr; } return False; } static void ContainerResequenceNodes (XmContainerWidget cw, Widget entryParent) { XmContainerConstraint c; CwidNode node; int count = 0; if (entryParent) { c = GetContainerConstraint(entryParent); node = c->node_ptr->child_ptr; } else { node = cw->container.first_node; } while (node) { c = GetContainerConstraint(node->widget_ptr); c->position_index = count++; node = node->next_ptr; } } /************************************************************************ * StartSelect (Private Function) ************************************************************************/ static void StartSelect( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget current_cwid; XmContainerConstraint c; current_cwid = ObjectAtPoint(wid,event->xbutton.x,event->xbutton.y); /* Handle ObjectAtPoint returning an outline button */ if ((current_cwid) && CtrOUTLINE_BUTTON(current_cwid)) current_cwid = NULL; cw->container.no_auto_sel_changes = False; /* * Setup for marque drawing and multiclick time. * Will return true if XmNdefaultActionCallback invoked. */ if (SetupDrag(wid, event, params, num_params)) return; if (CtrPolicyIsSINGLE(cw)) { /* CR 8400 - clicking on selected item should unselect in SINGLE mode */ if (current_cwid && current_cwid == cw->container.anchor_cwid && cw->container.selection_state == XmSELECTED) { /* Unselect if clicking on a selected item */ c = GetContainerConstraint(current_cwid); cw->container.selection_state = XmNOT_SELECTED; MarkCwid(current_cwid,False); cw->container.anchor_cwid = NULL; return; } cw->container.no_auto_sel_changes |= DeselectAllCwids(wid); cw->container.anchor_cwid = current_cwid; if (cw->container.anchor_cwid == NULL) return; cw->container.no_auto_sel_changes |= MarkCwid(cw->container.anchor_cwid,False); SetLocationCursor(cw->container.anchor_cwid); return; } if (CtrPolicyIsBROWSE(cw)) { if (current_cwid != cw->container.anchor_cwid) { cw->container.no_auto_sel_changes |= DeselectAllCwids(wid); cw->container.anchor_cwid = current_cwid; if (cw->container.anchor_cwid) { cw->container.no_auto_sel_changes |= MarkCwid(cw->container.anchor_cwid, True); SetLocationCursor(cw->container.anchor_cwid); } } if (CtrIsAUTO_SELECT(cw)) CallSelectCB(wid,event,XmAUTO_BEGIN); return; } if (!cw->container.extending_mode) cw->container.no_auto_sel_changes |= DeselectAllCwids(wid); cw->container.anchor_cwid = current_cwid; if (cw->container.anchor_cwid) SetLocationCursor(cw->container.anchor_cwid); if (CtrTechIsTOUCH_OVER(cw)) if (cw->container.anchor_cwid == NULL) cw->container.marquee_mode = True; else cw->container.marquee_mode = False; if (cw->container.anchor_cwid == NULL) { if (CtrIsAUTO_SELECT(cw)) CallSelectCB(wid,event,XmAUTO_BEGIN); cw->container.started_in_anchor = False; return; } else cw->container.started_in_anchor = True; if (cw->container.extending_mode) { c = GetContainerConstraint(cw->container.anchor_cwid); if (c->selection_state == XmSELECTED) cw->container.selection_state = XmNOT_SELECTED; else cw->container.selection_state = XmSELECTED; } cw->container.no_auto_sel_changes |= MarkCwid(cw->container.anchor_cwid,True); if (CtrIsAUTO_SELECT(cw)) CallSelectCB(wid,event,XmAUTO_BEGIN); if ((CtrTechIsMARQUEE_ES(cw) || CtrTechIsMARQUEE_EB(cw)) && (!CtrLayoutIsDETAIL(cw))) { XSetClipMask(XtDisplay(wid), cw->container.marqueeGC, None); RecalcMarquee(wid,cw->container.anchor_cwid, event->xbutton.x,event->xbutton.y); DrawMarquee(wid); cw->container.marquee_drawn = True; } } /*ARGSUSED*/ static Boolean SetupDrag(Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget current_cwid; int multi_click_time; Time click_time; /* Figure out double clicking */ current_cwid = ObjectAtPoint(wid,event->xbutton.x,event->xbutton.y); /* Handle ObjectAtPoint returning an outline button */ if ((current_cwid) && CtrOUTLINE_BUTTON(current_cwid)) current_cwid = NULL; multi_click_time = XtGetMultiClickTime(XtDisplay(wid)); click_time = event->xbutton.time; if ((cw->container.anchor_cwid == current_cwid) && ((click_time - cw->container.last_click_time) < multi_click_time)) { cw->container.last_click_time = click_time; if (cw->container.anchor_cwid) CallActionCB(cw->container.anchor_cwid,event); cw->container.cancel_pressed = True; return(True); } cw->container.last_click_time = event->xbutton.time; cw->container.anchor_point.x = event->xbutton.x; cw->container.marquee_smallest.x = event->xbutton.x; cw->container.marquee_largest.x = event->xbutton.x; cw->container.anchor_point.y = event->xbutton.y; cw->container.marquee_smallest.y = event->xbutton.y; cw->container.marquee_largest.y = event->xbutton.y; return(False); } /************************************************************************ * ProcessButtonMotion (Private Function) ************************************************************************/ /*ARGSUSED*/ static Boolean ProcessButtonMotion( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget current_cwid; Boolean selection_changes = False; Boolean find_anchor = False; XmContainerConstraint c; current_cwid = ObjectAtPoint(wid,event->xbutton.x,event->xbutton.y); /* Handle ObjectAtPoint returning an outline button */ if ((current_cwid) && CtrOUTLINE_BUTTON(current_cwid)) current_cwid = NULL; if (CtrPolicyIsBROWSE(cw)) { if ((cw->container.extend_pressed) || (cw->container.toggle_pressed)) return(False); if (current_cwid == cw->container.anchor_cwid) return(False); if (cw->container.anchor_cwid) { cw->container.selection_state = XmNOT_SELECTED; selection_changes = MarkCwid(cw->container.anchor_cwid, False); cw->container.selection_state = XmSELECTED; } if (current_cwid) selection_changes |= MarkCwid(current_cwid,True); cw->container.anchor_cwid = current_cwid; return(selection_changes); } /* CtrPolicyIsMULTIPLE || CtrPolicyIsEXTENDED */ /* CUA Random Selection Technique */ if (CtrLayoutIsSPATIAL(cw) && (!cw->container.marquee_mode)) { if (current_cwid== NULL) return(False); if (cw->container.anchor_cwid == NULL) { /* Gotta have a reference point for toggling */ c = GetContainerConstraint(current_cwid); if (c->selection_visual == XmSELECTED) cw->container.selection_state = XmNOT_SELECTED; else cw->container.selection_state = XmSELECTED; cw->container.anchor_cwid = current_cwid; } return(MarkCwid(current_cwid,True)); } /* CUA Range Selection Technique */ if (CtrLayoutIsDETAIL(cw) || (CtrLayoutIsOUTLINE_DETAIL(cw) && !cw->container.marquee_mode)) return(MarkCwidsInRange(wid,cw->container.anchor_cwid, current_cwid,(Boolean)True)); /* CUA Marquee Selection Technique */ find_anchor = (cw->container.anchor_cwid == NULL); RecalcMarquee(wid,current_cwid,event->xbutton.x,event->xbutton.y); selection_changes = MarkCwidsInMarquee(wid,find_anchor,True); DrawMarquee(wid); cw->container.marquee_drawn = True; return(selection_changes); } /************************************************************************ * * ObjectAtPoint method * Given a composite widget and an (x, y) coordinate, see if the * (x, y) lies within one of the object (gadget or widget) contained * within the composite. * ************************************************************************/ static Widget ObjectAtPoint(Widget wid, Position x, Position y) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Widget prev_cwid; XmGadget g; XmPointInTrait pointInTrait ; node = cw->container.first_node; prev_cwid = NULL; while (node) { XmContainerConstraint c; g = (XmGadget)node->widget_ptr; c = GetContainerConstraint((Widget) g); /* If we are in OUTLINE_DETAIL, then check for hit in outline button, if there is one */ if (CtrLayoutIsOUTLINE_DETAIL(cw) && c -> related_cwid != (Widget) NULL) { Widget outline_button = c -> related_cwid; pointInTrait = (XmPointInTrait) XmeTraitGet((XtPointer)XtClass(outline_button),XmQTpointIn) ; if (pointInTrait) { if (pointInTrait->pointIn(outline_button, x, y)) return outline_button; } else if ((XtX(outline_button) <= x) && (XtX(outline_button) + XtWidth(outline_button) >= x) && (XtY(outline_button) <= y) && (XtY(outline_button) + XtHeight(outline_button) >= y)) return(outline_button); } pointInTrait = (XmPointInTrait) XmeTraitGet((XtPointer)XtClass(node->widget_ptr),XmQTpointIn) ; if ((y < g->rectangle.y) && CtrLayoutIsOUTLINE_DETAIL(cw)) return(prev_cwid); if (pointInTrait && ! CtrLayoutIsOUTLINE_DETAIL(cw)) { if (pointInTrait->pointIn(node->widget_ptr, x, y)) return node->widget_ptr ; } else if ((g->rectangle.x <= x) && (x <= g->rectangle.x + g->rectangle.width) && (g->rectangle.y <= y) && (y <= g->rectangle.y + g->rectangle.height)) return(node->widget_ptr); if ((g->rectangle.y + g->rectangle.height > cw->core.height) && CtrLayoutIsOUTLINE_DETAIL(cw)) return(NULL); if ((g->rectangle.x <= x) && (x <= g->rectangle.x + g->rectangle.width)) prev_cwid = node->widget_ptr; else prev_cwid = NULL; node = GetNextNode(node); } return(NULL); } /************************************************************************ * SelectAllCwids (Private Function) ************************************************************************/ static Boolean SelectAllCwids( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Boolean selection_changes = False; /* * Mark all visible cwids as XmSELECTED */ cw->container.selection_state = XmSELECTED; node = cw->container.first_node; while (node) { selection_changes |= MarkCwid(node->widget_ptr,False); node = GetNextNode(node); } return(selection_changes); } /************************************************************************ * DeselectAllCwids (Private Function) ************************************************************************/ static Boolean DeselectAllCwids( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Boolean selection_changes = False; if (cw->container.selected_item_count == 0) { cw->container.selection_state = XmSELECTED; return(False); } /* * Mark all visible cwids as XmNOT_SELECTED */ cw->container.selection_state = XmNOT_SELECTED; node = cw->container.first_node; while (node) { selection_changes |= MarkCwid(node->widget_ptr,False); node = GetNextNode(node); if (cw->container.selected_item_count == 0) { cw->container.selection_state = XmSELECTED; return(selection_changes); } } /* * Didn't work. There must be some hidden child cwids that are * XmSELECTED. We'll have to traverse the entire list. */ node = cw->container.first_node; while (node) { selection_changes |= MarkCwid(node->widget_ptr,False); if (cw->container.selected_item_count == 0) { cw->container.selection_state = XmSELECTED; return(selection_changes); } /* * depth-first search of tree, whether the cwids are * visible or not. */ if (node->child_ptr) node = node->child_ptr; else if (node->next_ptr) node = node->next_ptr; else node = GetNextUpLevelNode(node); } cw->container.selection_state = XmSELECTED; return(selection_changes); } /************************************************************************ * MarkCwid (Private Function) ************************************************************************/ static Boolean MarkCwid( Widget cwid, Boolean visual_only) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); Boolean selection_changes = False; if (XtIsSensitive(cwid)) { if (cw->container.selection_state != c->selection_visual) { c->selection_visual = cw->container.selection_state; SetVisualEmphasis(cwid,c->selection_visual); if (c->selection_visual == XmSELECTED) cw->container.selected_item_count++; else cw->container.selected_item_count--; selection_changes = True; } if (!visual_only) c->selection_state = c->selection_visual; } return(selection_changes); } /************************************************************************ * UnmarkCwidVisual (Private Function) ************************************************************************/ static Boolean UnmarkCwidVisual( Widget cwid) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); /* * If the item visual matches its select state, or the item * visual doesn't match our current select/unselect action, * then return. * Otherwise, restore the item's visual to its select state * and add to/remove from the selected items list. */ if ((c->selection_visual == c->selection_state) || (c->selection_visual != cw->container.selection_state)) return(False); c->selection_visual = c->selection_state; SetVisualEmphasis(cwid,c->selection_visual); if (c->selection_visual == XmSELECTED) cw->container.selected_item_count++; else cw->container.selected_item_count--; return(True); } /************************************************************************ * SetMarkedCwids (Private Function) ************************************************************************/ static void SetMarkedCwids( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; XmContainerConstraint c; node = cw->container.first_node; while (node) { c = GetContainerConstraint(node->widget_ptr); c->selection_state = c->selection_visual; node = GetNextNode(node); } } /************************************************************************ * ResetMarkedCwids (Private Function) ************************************************************************/ static Boolean ResetMarkedCwids( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Boolean selection_changes = False; node = cw->container.first_node; while (node) { selection_changes |= UnmarkCwidVisual(node->widget_ptr); node = GetNextNode(node); } return(selection_changes); } /************************************************************************ * MarkCwidsInRange (Private Function) ************************************************************************/ static Boolean MarkCwidsInRange( Widget wid, Widget cwid1, Widget cwid2, Boolean visual_only) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Boolean cwid1_found = False; Boolean cwid2_found = False; Boolean marking_started = False; Boolean marking_ended = False; Boolean selection_changes = False; node = cw->container.first_node; if (cwid1 == NULL) if ((cwid1 = cwid2) == NULL) return(False); if (cwid2 == NULL) if ((cwid2 = cwid1) == NULL) return(False); while (node) { if (node->widget_ptr == cwid1) cwid1_found = True; if (node->widget_ptr == cwid2) cwid2_found = True; if ((cwid1_found || cwid2_found) && (!marking_started)) marking_started = True; if (marking_started && (!marking_ended)) selection_changes |= MarkCwid(node->widget_ptr, visual_only); else selection_changes |= UnmarkCwidVisual(node->widget_ptr); if (cwid1_found && cwid2_found && marking_started) marking_ended = True; node = GetNextNode(node); } return(selection_changes); } /************************************************************************ * MarkCwidsInMarquee (Private Function) ************************************************************************/ static Boolean MarkCwidsInMarquee( Widget wid, Boolean find_anchor, Boolean visual_only) { XmContainerWidget cw = (XmContainerWidget)wid; CwidNode node; Boolean selection_changes = False; XmContainerConstraint c; node = cw->container.first_node; while (node) { if (InMarquee(node->widget_ptr)) { if (find_anchor) { cw->container.anchor_cwid = node->widget_ptr; c = GetContainerConstraint(node->widget_ptr); if (c->selection_state == XmSELECTED) cw->container.selection_state = XmNOT_SELECTED; else cw->container.selection_state = XmSELECTED; find_anchor = False; } selection_changes |= MarkCwid(node->widget_ptr, visual_only); } else selection_changes |= UnmarkCwidVisual(node->widget_ptr); node = GetNextNode(node); } return(selection_changes); } /************************************************************************ * InMarquee (Private Function) ************************************************************************/ static Boolean InMarquee( Widget cwid) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); Position cwid_x,cwid_y,cwid_xw,cwid_yh; Dimension width,height; XtVaGetValues(cwid,XmNx,&cwid_x,XmNy,&cwid_y, XmNwidth,&width,XmNheight,&height,NULL); cwid_xw = cwid_x + (Position)width; cwid_yh = cwid_y + (Position)height; return( (cwid_x >= cw->container.marquee_start.x) && (cwid_y >= cw->container.marquee_start.y) && (cwid_xw <= cw->container.marquee_end.x) && (cwid_yh <= cw->container.marquee_end.y)); } /************************************************************************ * RecalcMarquee (Private Function) ************************************************************************/ static void RecalcMarquee( Widget wid, Widget cwid, Position x, Position y) { XmContainerWidget cw = (XmContainerWidget)wid; Dimension width,height; Position anchor_x,anchor_y,anchor_xw,anchor_yh; Position cwid_x,cwid_y,cwid_xw,cwid_yh; /* * Erase any marquee that is currently drawn. */ if (cw->container.marquee_drawn) { DrawMarquee(wid); cw->container.marquee_drawn = False; } /* * Set the new marquee start and end points depending upon * the XmNselectionTechnique resource. * If XmMARQUEE_EXTEND_BOTH, use the anchor_cwid and current_cwid * corners as endpoints (if they are given). * If XmMARQUEE_EXTEND_START, use the anchor_cwid corners (if given) * and the current pointer position as endpoints. * If XmMARQUEE, use the original anchor points and the current * pointer position, given by the x & y parameters. * container.marquee_start.x & marquee_start.y always marks upper left. * container.marquee_end.x & marquee_end.y always marks lower right. */ switch(cw->container.selection_technique) { case XmMARQUEE_EXTEND_BOTH: if ((cw->container.started_in_anchor) && (cwid)) { XtVaGetValues(cw->container.anchor_cwid, XmNx,&anchor_x,XmNy,&anchor_y, XmNwidth,&width, XmNheight,&height,NULL); anchor_xw = anchor_x + (Position)width; anchor_yh = anchor_y + (Position)height; /* CR9113: adjust marquee to encompass child */ if(anchor_x > 0) anchor_x--, width++; if(anchor_y > 0) anchor_y--, height++; XtVaGetValues(cwid,XmNx,&cwid_x,XmNy,&cwid_y, XmNwidth,&width, XmNheight,&height,NULL); /* CR9113: adjust marquee to encompass child */ if(cwid_x > 0) cwid_x--, width++; if(cwid_y > 0) cwid_y--, height++; cwid_xw = cwid_x + (Position)width; cwid_yh = cwid_y + (Position)height; cw->container.marquee_start.x = MIN(anchor_x,cwid_x); cw->container.marquee_start.y = MIN(anchor_y,cwid_y); cw->container.marquee_end.x = MAX(anchor_xw,cwid_xw); cw->container.marquee_end.y = MAX(anchor_yh,cwid_yh); break; } if (cw->container.started_in_anchor) cwid = cw->container.anchor_cwid; if ((!cw->container.started_in_anchor) && (cwid)) { x = cw->container.anchor_point.x; y = cw->container.anchor_point.y; } case XmMARQUEE_EXTEND_START: if CtrTechIsMARQUEE_ES(cw) if (cw->container.started_in_anchor) cwid = cw->container.anchor_cwid; else cwid = NULL; if (cwid) { XtVaGetValues(cwid,XmNx,&cwid_x, XmNy,&cwid_y,XmNwidth,&width, XmNheight,&height,NULL); /* CR9113: adjust marquee to encompass child */ if(cwid_x > 0) cwid_x--, width++; if(cwid_y > 0) cwid_y--, height++; cwid_xw = cwid_x + (Position)width; cwid_yh = cwid_y + (Position)height; if (x <= cwid_xw) { cw->container.marquee_start.x = MIN(x,cwid_x); cw->container.marquee_end.x = cwid_xw; } else { cw->container.marquee_start.x = cwid_x; cw->container.marquee_end.x = MAX(x,cwid_xw); } if (y <= cwid_yh) { cw->container.marquee_start.y = MIN(y,cwid_y); cw->container.marquee_end.y = cwid_yh; } else { cw->container.marquee_start.y = cwid_y; cw->container.marquee_end.y = MAX(y,cwid_yh); } break; } case XmMARQUEE: case XmTOUCH_OVER: cw->container.marquee_start.x = MIN(x,cw->container.anchor_point.x); cw->container.marquee_start.y = MIN(y,cw->container.anchor_point.y); cw->container.marquee_end.x = MAX(x,cw->container.anchor_point.x); cw->container.marquee_end.y = MAX(y,cw->container.anchor_point.y); break; default: return; } /* * Keep track of the largest area covered by the marquee. */ cw->container.marquee_smallest.x = MIN(cw->container.marquee_start.x, cw->container.marquee_smallest.x); cw->container.marquee_smallest.y = MIN(cw->container.marquee_start.y, cw->container.marquee_smallest.y); cw->container.marquee_largest.x = MAX(cw->container.marquee_end.x, cw->container.marquee_largest.x); cw->container.marquee_largest.y = MAX(cw->container.marquee_end.y, cw->container.marquee_largest.y); } /************************************************************************ * DrawMarquee (Private Function) ************************************************************************/ static void DrawMarquee( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; Dimension width,height; /* * If the container widget is realized, draw the marquee rectangle * using the gc parameter. */ if (!XtIsRealized(wid)) return; width = (Dimension)(cw->container.marquee_end.x - cw->container.marquee_start.x); height = (Dimension)(cw->container.marquee_end.y - cw->container.marquee_start.y); XDrawRectangle(XtDisplay(wid),XtWindow(wid),cw->container.marqueeGC, cw->container.marquee_start.x,cw->container.marquee_start.y, width,height); } /************************************************************************ * KBSelect (Private Function) ************************************************************************/ /*ARGSUSED*/ static void KBSelect( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params) /* unused */ { XmContainerWidget cw = (XmContainerWidget)wid; Widget focus_cwid = XmGetFocusWidget(wid); XmContainerConstraint c; if ((focus_cwid == wid) || (focus_cwid == NULL)) return; cw->container.no_auto_sel_changes = False; c = GetContainerConstraint(focus_cwid); cw->container.anchor_cwid = focus_cwid; if ((!cw->container.extending_mode || CtrPolicyIsSINGLE(cw)) && ((cw->container.selected_item_count > 1) || (c->selection_state != XmSELECTED))) cw->container.no_auto_sel_changes |= DeselectAllCwids(wid); if (cw->container.extending_mode) { if (c->selection_state == XmSELECTED) cw->container.selection_state = XmNOT_SELECTED; else cw->container.selection_state = XmSELECTED; } cw->container.no_auto_sel_changes |= MarkCwid(focus_cwid,False); GainPrimary(wid,event->xbutton.time); if (CtrIsAUTO_SELECT(cw)) { CallSelectCB(wid,event,XmAUTO_BEGIN); CallSelectCB(wid,event,XmAUTO_NO_CHANGE); } else if (cw->container.no_auto_sel_changes) CallSelectCB(wid,event,XmAUTO_UNSET); } /************************************************************************ * SetLocationCursor (Private Function) ************************************************************************/ static void SetLocationCursor( Widget cwid) { if (cwid == NULL) return; if (cwid == XmGetFocusWidget(XtParent(cwid))) return; XmProcessTraversal(cwid,XmTRAVERSE_CURRENT); } /************************************************************************ * CalcNextLocationCursor (Private Function) ************************************************************************/ static void CalcNextLocationCursor( Widget wid, String direction) { XmContainerWidget cw = (XmContainerWidget)wid; int move_to; Widget w; if (_XmConvertActionParamToRepTypeId((Widget) cw, XmRID_CONTAINER_CURSOR_ACTION_PARAMS, direction, False, &move_to) == False) { /* We couldn't convert the value. Just assume a value of _FIRST. */ move_to = _FIRST; } if (CtrLayoutIsSPATIAL(cw)) { if (move_to == _LEFT) XmProcessTraversal(wid, XmTRAVERSE_LEFT); else if (move_to == _RIGHT) XmProcessTraversal(wid, XmTRAVERSE_RIGHT); else if (move_to == _UP) XmProcessTraversal(wid, XmTRAVERSE_UP); else if (move_to == _DOWN) XmProcessTraversal(wid, XmTRAVERSE_DOWN); else if (move_to == _FIRST) XmProcessTraversal(wid, XmTRAVERSE_HOME); else if (move_to == _LAST) XmProcessTraversal(cw->container.last_node->widget_ptr, XmTRAVERSE_CURRENT); } else /* CtrLayoutIsOUTLINE_DETAIL(cw) */ { if (move_to == _LEFT) XmProcessTraversal(wid, XmTRAVERSE_LEFT); else if (move_to == _RIGHT) XmProcessTraversal(wid, XmTRAVERSE_RIGHT); else if (move_to == _UP) XmProcessTraversal(wid, XmTRAVERSE_UP); else if (move_to == _DOWN) XmProcessTraversal(wid, XmTRAVERSE_DOWN); else if (move_to == _FIRST) XmProcessTraversal(wid, XmTRAVERSE_HOME); else if (move_to == _LAST) { w = GetLastTraversalWidget(cw, cw->container.first_node->widget_ptr, False); if (w) XmProcessTraversal(w, XmTRAVERSE_CURRENT); } } } /************************************************************************ * RedirectTraversal (ControlTraversal Trait Method) ************************************************************************/ static Widget RedirectTraversal( Widget old_focus, Widget new_focus, unsigned int focus_policy, XmTraversalDirection direction, unsigned int pass) { XmContainerWidget cw; Widget to_widget = new_focus; Boolean wrap; if ( (old_focus == NULL) || (focus_policy != XmEXPLICIT) || ( direction != XmTRAVERSE_PREV && direction != XmTRAVERSE_NEXT && direction != XmTRAVERSE_LEFT && direction != XmTRAVERSE_RIGHT && direction != XmTRAVERSE_UP && direction != XmTRAVERSE_DOWN && direction != XmTRAVERSE_HOME)) return new_focus; if ( ((cw=(XmContainerWidget)XtParent(old_focus)) == NULL) || (!XmIsContainer(cw)) || (CtrLayoutIsSPATIAL(cw)) || (CtrOUTLINE_BUTTON(old_focus))) return new_focus; wrap = !XmIsClipWindow((XmClipWindowWidget)XtParent(cw)); switch (direction) { case XmTRAVERSE_PREV: case XmTRAVERSE_LEFT: case XmTRAVERSE_UP: to_widget = GetPrevTraversalWidget(cw, old_focus, wrap); break; case XmTRAVERSE_NEXT: case XmTRAVERSE_RIGHT: case XmTRAVERSE_DOWN: to_widget = GetNextTraversalWidget(cw, old_focus, wrap); break; case XmTRAVERSE_HOME: to_widget = GetFirstTraversalWidget(cw, old_focus, wrap); break; } /* switch */ return (to_widget ? to_widget : old_focus); } /************************************************************************ * GetLastTraversableChild (Private Function) ************************************************************************/ static CwidNode GetLastTraversableChild( CwidNode node) { CwidNode last_node = NULL; CwidNode child_node; CwidNode recu_node; if (node && (child_node=node->child_ptr)) { while (child_node) { if (NodeIsActive(child_node)) { if (XtIsSensitive(child_node->widget_ptr)) last_node = child_node; if (recu_node=GetLastTraversableChild(child_node)) last_node = recu_node; } child_node = child_node->next_ptr; } } return(last_node); } /************************************************************************ * GetPrevTraversableSibling (Private Function) ************************************************************************/ static CwidNode GetPrevTraversableSibling( CwidNode node) { CwidNode prev_node = NULL; CwidNode recu_node; if (node && (prev_node=node->prev_ptr)) { while (prev_node) { if (NodeIsActive(prev_node)) { if (recu_node=GetLastTraversableChild(prev_node)) { prev_node = recu_node; break; } if (XtIsSensitive(prev_node->widget_ptr)) break; } prev_node = prev_node->prev_ptr; } } return(prev_node); } /************************************************************************ * GetPrevTraversableUplevel (Private Function) (Private Function) ************************************************************************/ static CwidNode GetPrevTraversableUplevel( CwidNode node) { CwidNode prev_node = NULL; CwidNode parent_node; CwidNode recu_node; if (node && (parent_node=node->parent_ptr)) { while (parent_node) { if (NodeIsActive(parent_node)) { if (XtIsSensitive(parent_node->widget_ptr)) { prev_node = parent_node; break; } if (recu_node=GetPrevTraversableSibling(parent_node)) { prev_node = recu_node; break; } } parent_node = parent_node->parent_ptr; } } return(prev_node); } /************************************************************************ * GetNextTraversableChild (Private Function) ************************************************************************/ static CwidNode GetNextTraversableChild( CwidNode node) { CwidNode next_node = NULL; CwidNode recu_node; if (node && (next_node=node->child_ptr)) { while (next_node) { if (NodeIsActive(next_node)) { if (XtIsSensitive(next_node->widget_ptr)) break; if (recu_node=GetNextTraversableChild(next_node)) { next_node = recu_node; break; } } next_node = next_node->next_ptr; } } return(next_node); } /************************************************************************ * GetNextTraversableSibling (Private Function) ************************************************************************/ static CwidNode GetNextTraversableSibling( CwidNode node) { CwidNode next_node = NULL; CwidNode recu_node; if (node && (next_node=node->next_ptr)) { while (next_node) { if (NodeIsActive(next_node)) { if (XtIsSensitive(next_node->widget_ptr)) break; if (recu_node=GetNextTraversableChild(next_node)) { next_node = recu_node; break; } } next_node = next_node->next_ptr; } } return(next_node); } /************************************************************************ * GetNextTraversableUplevel (Private Function) ************************************************************************/ static CwidNode GetNextTraversableUplevel( CwidNode node) { CwidNode next_node = NULL; CwidNode parent_node; if (node && (parent_node=node->parent_ptr)) { while (parent_node && (next_node == NULL)) { next_node = GetNextTraversableSibling(parent_node); if (next_node == NULL) parent_node = parent_node->parent_ptr; } } return(next_node); } /************************************************************************ * GetNextTraversable (Private Function) ************************************************************************/ static CwidNode GetNextTraversable( CwidNode node) { CwidNode next_node = NULL; if (node == NULL) return(NULL); next_node = GetNextTraversableChild(node); if (next_node == NULL) next_node = GetNextTraversableSibling(node); if (next_node == NULL) next_node = GetNextTraversableUplevel(node); return(next_node); } /************************************************************************ * GetLastTraversalWidget (Private Function) ************************************************************************/ static Widget GetLastTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap) { CwidNode last_node = NULL; CwidNode temp_node; CwidNode child_node; if (cw == NULL || child == NULL) return(NULL); child_node = cw->container.first_node; while (child_node && !NodeIsActive(child_node)) child_node = child_node->next_ptr; if (child_node) { last_node = child_node; while (temp_node=GetNextTraversableSibling(last_node)) last_node = temp_node; if (last_node && (temp_node=GetLastTraversableChild(last_node))) last_node = temp_node; if (last_node == NULL && XtIsSensitive(child_node->widget_ptr)) last_node = child_node; } if (last_node && !XmIsTraversable(last_node->widget_ptr)) last_node = NULL; return(last_node ? last_node->widget_ptr : NULL); } /************************************************************************ * GetFirstTraversalWidget (Private Function) ************************************************************************/ static Widget GetFirstTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap) { CwidNode first_node = NULL; CwidNode child_node; if (cw == NULL || child == NULL) return(NULL); child_node = cw->container.first_node; while (child_node && !NodeIsActive(child_node)) child_node = child_node->next_ptr; if (child_node) { if (XtIsSensitive(child_node->widget_ptr)) first_node = child_node; else first_node = GetNextTraversable(child_node); } if (first_node && !XmIsTraversable(first_node->widget_ptr)) first_node = NULL; return(first_node ? first_node->widget_ptr : NULL); } /************************************************************************ * GetNextTraversalWidget (Private Function) ************************************************************************/ static Widget GetNextTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap) { CwidNode child_node; CwidNode next_node; if (cw == NULL || child == NULL) return(NULL); child_node = GetContainerConstraint(child)->node_ptr; next_node = GetNextTraversable(child_node); if (next_node == NULL && wrap) return(GetFirstTraversalWidget(cw, child, wrap)); if (next_node && !XmIsTraversable(next_node->widget_ptr)) next_node = NULL; return(next_node ? next_node->widget_ptr : NULL); } /************************************************************************ * GetPrevTraversalWidget (Private Function) ************************************************************************/ static Widget GetPrevTraversalWidget( XmContainerWidget cw, Widget child, Boolean wrap) { CwidNode child_node; CwidNode prev_node; CwidNode last_node; if (cw == NULL || child == NULL) return(NULL); child_node = GetContainerConstraint(child)->node_ptr; prev_node = GetPrevTraversableSibling(child_node); if (prev_node == NULL) prev_node = GetPrevTraversableUplevel(child_node); if (prev_node == NULL && wrap) return(GetLastTraversalWidget(cw, child, wrap)); if (prev_node && !XmIsTraversable(prev_node->widget_ptr)) prev_node = NULL; return(prev_node ? prev_node->widget_ptr : NULL); } /************************************************************************ * MakeOutlineButton (Private Function) ************************************************************************/ static void MakeOutlineButton( Widget cwid) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); XmContainerConstraint obc; Pixmap pm; cw->container.self = True; if (c->outline_state == XmEXPANDED) pm = cw->container.expanded_state_pixmap; else pm = cw->container.collapsed_state_pixmap; cw->container.create_cwid_type = CONTAINER_OUTLINE_BUTTON; c->related_cwid = XtVaCreateWidget(OBNAME, xmPushButtonGadgetClass,(Widget)cw, XmNlabelType,XmPIXMAP, XmNlabelPixmap,pm, XmNtraversalOn,False, XmNmarginWidth,0, XmNmarginHeight,0, NULL); XtAddCallback(c->related_cwid,XmNactivateCallback, (XtCallbackProc)OutlineButtonCallback, (XtPointer)cwid); obc = GetContainerConstraint(c->related_cwid); obc->related_cwid = cwid; XtManageChild(c->related_cwid); cw->container.create_cwid_type = CONTAINER_ICON; cw->container.self = False; #undef NO_PARENT #undef SWINDOW_PARENT #undef CWINDOW_PARENT } /************************************************************************ * ChangeOutlineButton (Private Function) ************************************************************************/ static void ChangeOutlineButtons( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; int i; Widget cwid; XmContainerConstraint c; Pixmap pm; Arg wargs[2]; int n; for (i = 0; i < cw->composite.num_children; i++) { cwid = cw->composite.children[i]; if (CtrOUTLINE_BUTTON(cwid)) { c = GetContainerConstraint(cwid); if (c->outline_state == XmEXPANDED) pm = cw->container.expanded_state_pixmap; else pm = cw->container.collapsed_state_pixmap; n = 0; XtSetArg(wargs[n],XmNlabelPixmap,pm); n++; cw->container.self = True; XtSetValues(cwid,wargs,n); cw->container.self = False; } } } /************************************************************************ * ExpandCwid (Private Function) ************************************************************************/ static void ExpandCwid( Widget cwid) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); CwidNode node; CwidNode child_node; XtWidgetGeometry geo_desired ; if (c->related_cwid == NULL) return; cw->container.self = True; XtVaSetValues(c->related_cwid, XmNlabelPixmap,cw->container.expanded_state_pixmap,NULL); cw->container.self = False; c->outline_state = XmEXPANDED; node = c->node_ptr; child_node = node->child_ptr; if (child_node == NULL) return; while (child_node) { c = GetContainerConstraint(child_node->widget_ptr); c->visible_in_outline = True; child_node = child_node->next_ptr; } geo_desired.width = 0; geo_desired.height = 0; RequestOutlineDetail ((Widget)cw, &geo_desired); /* need to redraw lines correctly */ if (XtIsRealized((Widget)cw)) XClearArea(XtDisplay((Widget)cw),XtWindow((Widget)cw),0,0,0,0,True); } /************************************************************************ * CollapseCwid (Private Function) ************************************************************************/ static void CollapseCwid( Widget cwid) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); CwidNode node; CwidNode child_node; XtWidgetGeometry geo_desired ; if (c->related_cwid == NULL) return; cw->container.self = True; XtVaSetValues(c->related_cwid, XmNlabelPixmap,cw->container.collapsed_state_pixmap,NULL); cw->container.self = False; c->outline_state = XmCOLLAPSED; node = c->node_ptr; child_node = node->child_ptr; if (child_node == NULL) return; while (child_node) { c = GetContainerConstraint(child_node->widget_ptr); c->visible_in_outline = False; HideCwid(child_node->widget_ptr); if (c->related_cwid) HideCwid(c->related_cwid); child_node = child_node->next_ptr; } geo_desired.width = 0; geo_desired.height = 0; RequestOutlineDetail ((Widget)cw, &geo_desired); /* need to redraw lines correctly */ if (XtIsRealized((Widget)cw)) XClearArea(XtDisplay((Widget)cw),XtWindow((Widget)cw),0,0,0,0,True); } /************************************************************************ * CallActionCB (Private Function) ************************************************************************/ static void CallActionCB( Widget cwid, XEvent *event) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); XmContainerSelectCallbackStruct cbs; if (!(XtHasCallbacks((Widget)cw,XmNdefaultActionCallback) == XtCallbackHasSome)) return; if (!XtIsSensitive(cwid)) return; cbs.reason = XmCR_DEFAULT_ACTION; cbs.event = event; if (c->selection_state == XmSELECTED) { cbs.selected_items = GetSelectedCwids((Widget)cw); cbs.selected_item_count = cw->container.selected_item_count; } else { cbs.selected_items = (WidgetList)XtMalloc(sizeof(Widget)); cbs.selected_items[0] = cwid; cbs.selected_item_count = 1; } cbs.auto_selection_type = XmAUTO_UNSET; XtCallCallbackList((Widget)cw,cw->container.default_action_cb,&cbs); XtFree((char*)cbs.selected_items); } /************************************************************************ * CallSelectCB (Private Function) ************************************************************************/ static void CallSelectCB( Widget wid, XEvent *event, unsigned char auto_selection_type) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerSelectCallbackStruct cbs; if (!(XtHasCallbacks(wid,XmNselectionCallback) == XtCallbackHasSome)) return; cbs.selected_items = NULL; cbs.selected_item_count = 0; switch(cw->container.selection_policy) { case XmSINGLE_SELECT: cbs.reason = XmCR_SINGLE_SELECT; case XmBROWSE_SELECT: if (CtrPolicyIsBROWSE(cw)) cbs.reason = XmCR_BROWSE_SELECT; if (cw->container.anchor_cwid) { cbs.selected_items = (WidgetList) XtMalloc(sizeof(Widget)); cbs.selected_items[0] = cw->container.anchor_cwid; cbs.selected_item_count = 1; } break; case XmMULTIPLE_SELECT: cbs.reason = XmCR_MULTIPLE_SELECT; case XmEXTENDED_SELECT: if (CtrPolicyIsEXTENDED(cw)) cbs.reason = XmCR_EXTENDED_SELECT; cbs.selected_items = GetSelectedCwids(wid); cbs.selected_item_count = cw->container.selected_item_count; break; } cbs.event = event; cbs.auto_selection_type = auto_selection_type; XtCallCallbackList(wid,cw->container.selection_cb,&cbs); if (cbs.selected_items) XtFree((char*)cbs.selected_items); } /************************************************************************ * GetSelectedCwids (Private Function) ************************************************************************/ static WidgetList GetSelectedCwids( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; WidgetList selected_items; CwidNode node; unsigned int tally = 0; XmContainerConstraint c; if (cw->container.selected_item_count == 0) return(NULL); selected_items = (WidgetList)XtMalloc (cw->container.selected_item_count * sizeof(Widget)); /* * Search through all the visible items first - it'll work 99% of * the time and it's faster than searching through all the items. */ node = cw->container.first_node; while (node) { c = GetContainerConstraint(node->widget_ptr); if (c->selection_visual == XmSELECTED) { selected_items[tally] = node->widget_ptr; tally++; if (tally == cw->container.selected_item_count) return(selected_items); } node = GetNextNode(node); } /* * Didn't work. There must be some hidden child items that are * XmSELECTED. We'll have to traverse the entire list. */ tally = 0; node = cw->container.first_node; while (node) { c = GetContainerConstraint(node->widget_ptr); if (c->selection_visual == XmSELECTED) { selected_items[tally] = node->widget_ptr; tally++; if (tally == cw->container.selected_item_count) return(selected_items); } /* * depth-first search of tree, whether the items are * visible or not. */ if (node->child_ptr) node = node->child_ptr; else if (node->next_ptr) node = node->next_ptr; else node = GetNextUpLevelNode(node); } return(NULL); } /************************************************************************ * GetSelectedItems (Private Synthetic Resource Function) ************************************************************************/ /*ARGSUSED*/ static void GetSelectedItems( Widget wid, int offset, /* unused */ XtArgVal *value) { WidgetList selected_items; selected_items = GetSelectedCwids(wid); *value = (XtArgVal)selected_items; } /************************************************************************ * CompareInts (Private qsort Function) ************************************************************************/ static int CompareInts( XmConst void *p1, XmConst void *p2) { int i1 = * (int *)p1; int i2 = * (int *)p2; /* * A "qsort" function that simply compares two integers */ return(i1 - i2); } /************************************************************************ * Isqrt (Private Function) ************************************************************************/ static int Isqrt( int n) { /* * Integer Square Root (using Newton's Method) - rounded up */ int current_answer,next_trial; if (n <= 1) return(n); current_answer = n; next_trial = n/2; while(current_answer > next_trial) { current_answer = next_trial; next_trial = (next_trial + n/next_trial)/2; } if (current_answer * current_answer < n) current_answer++; return(current_answer); } /************************************************************************ * GainPrimary (Private Function) ************************************************************************/ static void GainPrimary( Widget wid, Time timestamp) { XmContainerWidget cw = (XmContainerWidget)wid; if (cw->container.primary_ownership == XmOWN_NEVER) return; if ((cw->container.primary_ownership == XmOWN_POSSIBLE_MULTIPLE) && (CtrPolicyIsSINGLE(cw) || CtrPolicyIsBROWSE(cw))) return; if ((cw->container.primary_ownership == XmOWN_MULTIPLE) && (cw->container.selected_item_count <= 1)) return; if (cw->container.selected_item_count == 0) return; cw->container.have_primary = XmePrimarySource(wid,timestamp); } /************************************************************************ * ConvertRefuse (Private Function) ************************************************************************/ /*ARGSUSED*/ static void ConvertRefuse( Widget wid, /* unused */ XtPointer closure, /* unused */ XmConvertCallbackStruct *cs) { cs->value = NULL; cs->length = 0; cs->type = 0; cs->status = XmCONVERT_REFUSE; } /************************************************************************ * DragStart (Private Function) ************************************************************************/ /*ARGSUSED*/ static void DragStart( XtPointer data, XtIntervalId * id) /* unused */ { XmContainerWidget cw = (XmContainerWidget)data; XmGadget g; Arg wargs[20]; int n; Pixmap pixmap = XmUNSPECIFIED_PIXMAP; Pixmap mask = XmUNSPECIFIED_PIXMAP; Widget drag_icon = (Widget) 0; unsigned char vis_state = XmNOT_SELECTED; XtPointer loc_data; Widget dc; Widget diParent = XmGetXmDisplay(XtDisplay(cw)); DragIconInfo dragIconInfo = NULL; int offsetx, offsety; Pixel bg, fg; cw->container.transfer_timer_id = 0; if (cw->container.transfer_action == NULL) return; /* No context record, shouldn't happen */ cw->container.druggee = ObjectAtPoint((Widget)cw, cw->container.transfer_action->event->xbutton.x, cw->container.transfer_action->event->xbutton.y); /* Handle ObjectAtPoint returning an outline button */ if ((cw->container.druggee) && CtrOUTLINE_BUTTON(cw->container.druggee)) cw->container.druggee = NULL; if (cw->container.druggee == NULL) { XtFree((char*)cw->container.transfer_action->event); XtFree((char*)cw->container.transfer_action); cw->container.transfer_action = NULL; return; } g = (XmGadget)cw->container.druggee; offsetx = cw->container.transfer_action->event->xbutton.x - g->rectangle.x; offsety = cw->container.transfer_action->event->xbutton.y - g->rectangle.y; cw->container.drag_offset_x = offsetx; cw->container.drag_offset_y = offsety; /* Get the pixmap if there is one from the IconGadget or other Container savvy object */ n = 0; if (GetViewType(cw->container.druggee) == XmSMALL_ICON) { XtSetArg(wargs[n],XmNsmallIconPixmap,&pixmap); n++; XtSetArg(wargs[n],XmNsmallIconMask,&mask); n++; } else { XtSetArg(wargs[n],XmNlargeIconPixmap,&pixmap); n++; XtSetArg(wargs[n],XmNlargeIconMask,&mask); n++; } XtGetValues(cw->container.druggee,wargs,n); vis_state = GetVisualEmphasis(cw->container.druggee); _XmProcessLock(); if (dragIconInfoContext == 0) dragIconInfoContext = XUniqueContext(); _XmProcessUnlock(); /* Note that there is one of these per display. That way we can just do a XtSetValues and not recreate the state XmDragIcon constantly */ if (XFindContext(XtDisplay(cw), None, dragIconInfoContext, (XPointer*) &dragIconInfo) == XCNOENT || dragIconInfo == (DragIconInfo) NULL) { Pixmap cross; Pixmap cross_m; GC tempgc; Arg args[10]; int n, midpoint = DRAG_STATE_SIZE / 2, farpoint = DRAG_STATE_SIZE; dragIconInfo = (DragIconInfo) XtMalloc(sizeof(DragIconInfoRec)); XSaveContext(XtDisplay(cw), None, dragIconInfoContext, (char*) dragIconInfo); dragIconInfo -> source = (Widget) NULL; cross = XCreatePixmap(XtDisplay(cw),XtWindow(cw),farpoint,farpoint,1); cross_m = XCreatePixmap(XtDisplay(cw),XtWindow(cw),farpoint,farpoint,1); tempgc = XCreateGC(XtDisplay(cw), cross, 0L, NULL); /* Draw a plus sign */ XSetForeground(XtDisplay(cw), tempgc, 0); XFillRectangle(XtDisplay(cw), cross, tempgc, 0, 0, farpoint, farpoint); XFillRectangle(XtDisplay(cw), cross_m, tempgc, 0, 0, farpoint, farpoint); XSetForeground(XtDisplay(cw), tempgc, 1); XSetLineAttributes(XtDisplay(cw), tempgc, 2, LineSolid, CapButt, JoinMiter); XDrawLine(XtDisplay(cw), cross, tempgc, midpoint, 0, midpoint, farpoint); XDrawLine(XtDisplay(cw), cross, tempgc, 0, midpoint, farpoint, midpoint); XSetLineAttributes(XtDisplay(cw), tempgc, 6, LineSolid, CapButt, JoinMiter); XDrawLine(XtDisplay(cw),cross_m,tempgc,midpoint,0,midpoint,farpoint); XDrawLine(XtDisplay(cw),cross_m,tempgc,0,midpoint,farpoint,midpoint); XFreeGC(XtDisplay(cw), tempgc); n = 0; XtSetArg(args[n], XmNpixmap, cross); n++; XtSetArg(args[n], XmNmask, cross_m); n++; XtSetArg(args[n], XmNheight, farpoint); n++; XtSetArg(args[n], XmNwidth, farpoint); n++; dragIconInfo -> state = XmCreateDragIcon(diParent, "stateIcon", args, n); } n = 0; XtSetArg(wargs[n],XmNforeground,&fg); n++; XtSetArg(wargs[n],XmNbackground,&bg); n++; XtGetValues((Widget) g, wargs, n); /* We're dragging from an icon gadget or other object with a pixmap obtained above. We use the pixmap as the source icon. The actual XmDragIcon object is cached to avoid constantly recreating and destroying the objects, and this is done on a per display basis. */ n = 0; if (pixmap != XmUNSPECIFIED_PIXMAP) { unsigned int rh, rw; int rd; int ix, iy; _XmIconGadgetIconPos((Widget) g, &ix, &iy); /* Fix the offset amounts */ offsetx -= ix; offsety -= iy; /* Adjust the state icon position */ XtSetArg(wargs[n],XmNoffsetX, offsetx); n++; XtSetArg(wargs[n],XmNoffsetY, offsety); n++; XtSetValues(dragIconInfo->state, wargs, n); /* now create or fix up the source icon */ XmeGetPixmapData(XtScreen(cw), pixmap, NULL, &rd, NULL, NULL, NULL, NULL, &rw, &rh); n = 0; XtSetArg(wargs[n],XmNpixmap,pixmap); n++; XtSetArg(wargs[n],XmNmask,mask); n++; XtSetArg(wargs[n],XmNheight, rh); n++; XtSetArg(wargs[n],XmNwidth, rw); n++; XtSetArg(wargs[n],XmNdepth, rd); n++; if (dragIconInfo -> source == (Widget) NULL) { drag_icon = XmCreateDragIcon(diParent,"dragIcon",wargs,n); dragIconInfo -> source = drag_icon; } else { drag_icon = dragIconInfo -> source; XtSetValues(drag_icon, wargs, n); } n = 0; XtSetArg(wargs[n],XmNsourcePixmapIcon,drag_icon); n++; XtSetArg(wargs[n],XmNstateCursorIcon,dragIconInfo->state); n++; } XtSetArg(wargs[n],XmNdragOperations, cw->container.transfer_action->operation); n++; if (vis_state == XmSELECTED) loc_data = NULL; else loc_data = (XtPointer)cw->container.druggee; XtSetArg(wargs[n],XmNcursorBackground,bg); n++; XtSetArg(wargs[n],XmNcursorForeground,fg); n++; dc = XmeDragSource((Widget)cw,loc_data, cw->container.transfer_action->event,wargs,n); if (dc) XtAddCallback(dc,XmNdropFinishCallback,DropDoneCallback,cw); cw->container.drag_context = (Widget) dc; XtFree((char*)cw->container.transfer_action->event); XtFree((char*)cw->container.transfer_action); cw->container.transfer_action = NULL; } /************************************************************************ * OutlineButtonCallback (Private Callback Function) ************************************************************************/ /*ARGSUSED*/ static void OutlineButtonCallback( Widget pbwid, /* unused */ XtPointer client_data, XtPointer call_data) { Widget cwid = (Widget)client_data; XmAnyCallbackStruct * pbcbs = (XmAnyCallbackStruct *)call_data; XmContainerConstraint c = GetContainerConstraint(cwid); if (c->outline_state == XmCOLLAPSED) OutlineButtonAction(cwid, XmEXPANDED, pbcbs->event); else /* if (c->outline_state == XmEXPANDED) */ OutlineButtonAction(cwid, XmCOLLAPSED, pbcbs->event); } /************************************************************************ * OutlineButtonAction (Private Callback Function) ************************************************************************/ /*ARGSUSED*/ static void OutlineButtonAction( Widget cwid, unsigned char new_state, XEvent *event) { XmContainerWidget cw = (XmContainerWidget)XtParent(cwid); XmContainerConstraint c = GetContainerConstraint(cwid); XmGadget g = (XmGadget)cwid; XmContainerOutlineCallbackStruct cbs; unsigned char state_before_callback; /* * call the XmNoutlineChangedCallback callback */ if (new_state == XmCOLLAPSED) cbs.reason = XmCR_COLLAPSED; else /* if (new_state == XmEXPANDED) */ cbs.reason = XmCR_EXPANDED; cbs.event = event; cbs.item = cwid; cbs.new_outline_state = new_state; c->outline_state = new_state; state_before_callback = c->outline_state; XtCallCallbackList((Widget)cw,cw->container.outline_cb,&cbs); /* in case user destroys child */ if (g->object.being_destroyed) return; /* verify value returned */ if ((cbs.new_outline_state != XmCOLLAPSED) && (cbs.new_outline_state != XmEXPANDED)) cbs.new_outline_state = state_before_callback; /* in case user has called SetValues in XmNoutlineChangedCallback */ if (c->outline_state != state_before_callback) return; /* the user wants to go back to the previous state */ if (cbs.new_outline_state != state_before_callback) { c->outline_state = cbs.new_outline_state; return; } if (c->outline_state == XmCOLLAPSED) CollapseCwid(cwid); else ExpandCwid(cwid); } /************************************************************************ * MoveItemCallback (Private Callback Function) ************************************************************************/ /* Create the multipliers to try the surrounding spots for cell or grid mode */ static int x_deltas[] = { 0, -1, 0, 1, -1, 1, -1, 0, 1}; static int y_deltas[] = { 0, -1, -1, -1, 0, 0, 1, 1, 1}; static void MoveItemCallback( Widget wid, XtPointer client_data, XtPointer call_data) { XmContainerWidget cw = (XmContainerWidget)wid; XPoint * dropspot = (XPoint *)client_data; XmSelectionCallbackStruct * cs = (XmSelectionCallbackStruct *)call_data; XmContainerConstraint c; unsigned char save_include_model = XmCLOSEST; Widget cwid = cw->container.druggee; XmDestinationCallbackStruct * ds = _XmTransferGetDestinationCBStruct(cs->transfer_id); XPoint *offset = (XPoint *) cs -> value; if (cwid == NULL) return; c = GetContainerConstraint(cwid); /* Offset the dropspot by the returned data */ dropspot->x -= offset->x; dropspot->y -= offset->y; if (((XmContainerWidgetClass) XtClass(wid))->container_class.test_fit_item ) { XmSpatialTestFitProc test_item; Boolean status; test_item = (XmSpatialTestFitProc) ((XmContainerWidgetClass) XtClass(wid)) ->container_class.test_fit_item; if (CtrSpatialStyleIsGRID(wid) || CtrSpatialStyleIsCELLS(wid)) { int pos; int dw, dh; int trial_x, trial_y; if (CtrViewIsLARGE_ICON(wid) || CtrViewIsANY_ICON(wid)) { dw = cw -> container.real_large_cellw; dh = cw -> container.real_large_cellh; } else { dw = cw -> container.real_small_cellw; dh = cw -> container.real_small_cellh; } /* Try all the array positions until one is found. Start at the center and work around left to right, top to bottom */ status = False; for(pos = 0; pos < 9; pos++) { trial_x = dropspot->x + x_deltas[pos] * dw; trial_y = dropspot->y + y_deltas[pos] * dh; status = test_item(wid, cwid, trial_x, trial_y); if (status) break; } if (status && pos < 9) { dropspot->x = trial_x; dropspot->y = trial_y; } } else { /* Just try the direct spot */ status = test_item(wid,cwid,dropspot->x,dropspot->y); } if (! status) { XmTransferDone(cs->transfer_id,XmTRANSFER_DONE_FAIL); return; } } if (((XmContainerWidgetClass) XtClass(wid))->container_class.remove_item) (*((XmContainerWidgetClass) XtClass(wid))->container_class.remove_item) (wid,cwid); /* Clear old placement */ XClearArea(XtDisplay(wid),XtWindow(wid), cwid->core.x,cwid->core.y, cwid->core.width,cwid->core.height, True); if (CtrSpatialStyleIsGRID(cw) || CtrSpatialStyleIsCELLS(cw)) /* * Fake the include model so it pays attention to core.x & core.y */ { save_include_model = cw->container.include_model; cw->container.include_model = XmCLOSEST; } XmeConfigureObject(cwid, dropspot->x, dropspot->y, cwid->core.width, cwid->core.height, cwid->core.border_width); c->user_x = dropspot->x; c->user_y = dropspot->y; if (((XmContainerWidgetClass) XtClass(wid))->container_class.place_item) (*((XmContainerWidgetClass) XtClass(wid))->container_class.place_item) (wid,cwid,FORCE); if (CtrSpatialStyleIsGRID(cw) || CtrSpatialStyleIsCELLS(cw)) cw->container.include_model = save_include_model; /* If we've gotten down here, and we came from the same widget, and we've succeeded, so cancel the drop effect, moving is enough (and faster) */ if (ds -> flags & XmCONVERTING_SAME) XmTransferValue(cs->transfer_id, XInternAtom(XtDisplay(wid), XmS_MOTIF_CANCEL_DROP_EFFECT, False), (XtCallbackProc)NULL,NULL, XtLastTimestampProcessed(XtDisplay(wid))); } /************************************************************************ * DropDoneCallback (Private Callback Function) ************************************************************************/ /*ARGSUSED*/ static void DropDoneCallback( Widget wid, /* unused */ XtPointer client_data, XtPointer call_data) /* unused */ { XmContainerWidget cw = (XmContainerWidget)client_data; cw->container.drag_context = (Widget) NULL; } /************************************************************************ * * * EnterHandler - If there is a drag timeout, remove it. * * * ************************************************************************/ /*ARGSUSED*/ static void EnterHandler( Widget wid, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch) { XmContainerWidget cw = (XmContainerWidget)wid; cw->container.LeaveDir = 0; if (cw->container.scroll_proc_id) { XtRemoveTimeOut(cw->container.scroll_proc_id); cw->container.scroll_proc_id = 0; } } /************************************************************************ * * * LeaveHandler - If the user leaves in Marquee Select mode set up a * * timer to scroll the container. * * * ************************************************************************/ /*ARGSUSED*/ static void LeaveHandler( Widget wid, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch) { XmContainerWidget cw = (XmContainerWidget)wid; Widget clip = XtParent(wid); int rx, ry; /* event coords relative to the clip */ int interval = 200; if (!cw->container.selecting || CtrPolicyIsSINGLE(cw)) return; /* first lets see which direction we left the window */ cw->container.LeaveDir = 0; rx = event->xcrossing.x + (int)wid->core.x; ry = event->xcrossing.y + (int)wid->core.y; if (rx <= (int)clip->core.x) cw->container.LeaveDir |= LEFTLEAVE; else if (rx >= (int)clip->core.width) cw->container.LeaveDir |= RIGHTLEAVE; if (ry <= (int)clip->core.y) cw->container.LeaveDir |= TOPLEAVE; else if (ry >= (int)clip->core.height) cw->container.LeaveDir |= BOTTOMLEAVE; /* then add a TimeOutProc to handle the auto scroll */ cw->container.scroll_proc_id = XtAppAddTimeOut(XtWidgetToApplicationContext(wid), (unsigned long) interval, ScrollProc, (XtPointer) cw); } /************************************************************************ * * * ScrollProc - timer proc that scrolls the container if the user has * * left the window with the button down. If the button has * * been released, call the standard click stuff. * * * ************************************************************************/ /*ARGSUSED*/ static void ScrollProc( XtPointer closure, XtIntervalId *id) { Widget wid = (Widget) closure; XmContainerWidget cw = (XmContainerWidget)closure; Widget sf; XmScrollFrameTrait scrollFrameTrait; XmNavigatorTrait navigatorTrait; XmNavigatorDataRec nav_data; Cardinal i, num_nav_list; Widget *nav; int interval = 100; XEvent event; Boolean selection_changes; if (cw->container.scroll_proc_id == 0) return; cw->container.scroll_proc_id = 0; /* since we've got reparented by the clip the scrollFrame is 2 levels up */ sf = XtParent(XtParent((Widget)cw)); scrollFrameTrait = (XmScrollFrameTrait) XmeTraitGet((XtPointer)XtClass(sf), XmQTscrollFrame); if (!(scrollFrameTrait && (scrollFrameTrait->getInfo(sf,NULL,&nav,&num_nav_list)))) return; /* this should never happen */ for (i=0; i < num_nav_list; i++, nav++) { navigatorTrait = (XmNavigatorTrait) XmeTraitGet((XtPointer)XtClass(*nav), XmQTnavigator); /* get the current position */ nav_data.valueMask = NavValue | NavIncrement | NavMinimum | NavMaximum | NavSliderSize; bzero(&nav_data,sizeof(XmNavigatorDataRec)); navigatorTrait->getValue(*nav, &nav_data); /* compute the new position */ if (cw->container.LeaveDir & BOTTOMLEAVE) nav_data.value.y += nav_data.increment.y; else if (cw->container.LeaveDir & TOPLEAVE) nav_data.value.y -= nav_data.increment.y; if (cw->container.LeaveDir & LEFTLEAVE) nav_data.value.x -= nav_data.increment.x; else if (cw->container.LeaveDir & RIGHTLEAVE) nav_data.value.x += nav_data.increment.x; if (nav_data.value.y < nav_data.minimum.y) nav_data.value.y = nav_data.minimum.y; if (nav_data.value.y > (nav_data.maximum.y - nav_data.slider_size.y)) nav_data.value.y = nav_data.maximum.y - nav_data.slider_size.y; if (nav_data.value.x < nav_data.minimum.x) nav_data.value.x = nav_data.minimum.x; if (nav_data.value.x > (nav_data.maximum.x - nav_data.slider_size.x)) nav_data.value.x = nav_data.maximum.x - nav_data.slider_size.x; /* and set it */ nav_data.valueMask = NavValue; navigatorTrait->setValue(*nav, &nav_data, True); } /* fake a button event using the last event coordinates */ event.xbutton.x = cw->container.last_xmotion_x - (int)wid->core.x; event.xbutton.y = cw->container.last_xmotion_y - (int)wid->core.y; selection_changes = ProcessButtonMotion(wid, &event, NULL, 0); cw->container.no_auto_sel_changes |= selection_changes; if (CtrIsAUTO_SELECT(cw) && selection_changes) CallSelectCB(wid, NULL, XmAUTO_MOTION); /* reset timer proc */ cw->container.scroll_proc_id = XtAppAddTimeOut(XtWidgetToApplicationContext(wid), (unsigned long) interval, ScrollProc, (XtPointer) cw); } /************************************************************************ * XmContainerCut (Public Function) ************************************************************************/ Boolean XmContainerCut( Widget wid, Time timestamp) { XmContainerWidget cw = (XmContainerWidget)wid; Boolean status; _XmWidgetToAppContext(wid); _XmAppLock(app); if (cw->container.selected_item_count == 0) { _XmAppUnlock(app); return(False); } if (!cw->container.have_primary) { _XmAppUnlock(app); return(False); } status = XmeClipboardSource(wid,XmMOVE,timestamp); _XmAppUnlock(app); return(status); } /************************************************************************ * XmContainerCopy (Public Function) ************************************************************************/ Boolean XmContainerCopy( Widget wid, Time timestamp) { XmContainerWidget cw = (XmContainerWidget)wid; Boolean status; _XmWidgetToAppContext(wid); _XmAppLock(app); if (cw->container.selected_item_count == 0) { _XmAppUnlock(app); return(False); } if (!cw->container.have_primary) { _XmAppUnlock(app); return(False); } status = XmeClipboardSource(wid,XmCOPY,timestamp); _XmAppUnlock(app); return(status); } /************************************************************************ * XmContainerPaste (Public Function) ************************************************************************/ Boolean XmContainerPaste( Widget wid) { return(XmeClipboardSink(wid,XmCOPY,NULL)); } /************************************************************************ * XmContainerCopyLink (Public Function) ************************************************************************/ Boolean XmContainerCopyLink( Widget wid, Time timestamp) { XmContainerWidget cw = (XmContainerWidget)wid; Boolean status; _XmWidgetToAppContext(wid); _XmAppLock(app); if (cw->container.selected_item_count == 0) { _XmAppUnlock(app); return(False); } if (!cw->container.have_primary) { _XmAppUnlock(app); return(False); } status = XmeClipboardSource(wid,XmLINK,timestamp); _XmAppUnlock(app); return(status); } /************************************************************************ * XmContainerPasteLink (Public Function) ************************************************************************/ Boolean XmContainerPasteLink( Widget wid) { return(XmeClipboardSink(wid,XmLINK,NULL)); } /************************************************************************ * XmContainerGetItemChildren (Public Function) ************************************************************************/ int XmContainerGetItemChildren( Widget wid, Widget item, WidgetList *item_children) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c; CwidNode node; CwidNode first_child_node; WidgetList clist; int i,clist_count; _XmWidgetToAppContext(wid); _XmAppLock(app); if (item == NULL) { if (cw->container.first_node == NULL) { _XmAppUnlock(app); return(0); } first_child_node = cw->container.first_node; } else { if (XtParent(item) != wid) { _XmAppUnlock(app); return(0); } c = GetContainerConstraint(item); node = c->node_ptr; if (node->child_ptr == NULL) { _XmAppUnlock(app); return(0); } first_child_node = node->child_ptr; } clist_count = 1; node = first_child_node; while (node->next_ptr) { clist_count++; node = node->next_ptr; } clist = (WidgetList)XtMalloc(clist_count * sizeof(Widget)); node = first_child_node; for (i = 0; i < clist_count; i++) { clist[i] = node->widget_ptr; node = node->next_ptr; } *item_children = clist; _XmAppUnlock(app); return(clist_count); } /************************************************************************ * XmContainerRelayout (Public Function) ************************************************************************/ void XmContainerRelayout( Widget wid) { XmContainerWidget cw = (XmContainerWidget)wid; _XmWidgetToAppContext(wid); if (!XtIsRealized(wid)) /* Don't need to relayout, will be right anyway */ return; _XmAppLock(app); if (CtrLayoutIsOUTLINE_DETAIL(cw)) { _XmAppUnlock(app); return; } if (CtrSpatialStyleIsNONE(cw)) { _XmAppUnlock(app); return; } if (!((XmContainerWidgetClass)XtClass(wid))->container_class.place_item) { _XmAppUnlock(app); return; } /* Reset grid/cell information */ (*((XmContainerWidgetClass)XtClass(wid))->container_class.place_item) (wid,NULL,ANY_FIT); /* Relayout - no geometry changes */ LayoutSpatial(wid,False,NULL); if (XtIsRealized(wid)) XClearArea(XtDisplay(wid),XtWindow(wid),0,0,0,0,True); _XmAppUnlock(app); } /************************************************************************ * XmContainerReorder (Public Function) ************************************************************************/ void XmContainerReorder( Widget wid, WidgetList cwid_list, int cwid_count) { XmContainerWidget cw = (XmContainerWidget)wid; XmContainerConstraint c; Widget pcwid; int * pi_list; int i, pi_count; _XmWidgetToAppContext(wid); if (cwid_count <= 1) return; _XmAppLock(app); c = GetContainerConstraint(cwid_list[0]); pcwid = c->entry_parent; pi_list = (int *)XtMalloc(cwid_count * sizeof(int)); pi_count = 0; for (i=0; i < cwid_count; i++) { c = GetContainerConstraint(cwid_list[i]); if (c->entry_parent == pcwid) { pi_list[pi_count] = c->position_index; pi_count++; } } qsort(pi_list,pi_count,sizeof(int),CompareInts); pi_count = 0; for (i=0; i < cwid_count; i++) { c = GetContainerConstraint(cwid_list[i]); if (c->entry_parent == pcwid) { c->position_index = pi_list[pi_count]; pi_count++; SeverNode(c->node_ptr); ContainerResequenceNodes(cw, c->entry_parent); InsertNode(c->node_ptr); } } XtFree((char*)pi_list); /* * Outline & Detail Layouts must always remain in order. */ if (CtrLayoutIsOUTLINE_DETAIL(cw)) Layout(wid); /* * Outline lines may have changed location, erase the old ones. */ if (CtrDrawLinesOUTLINE(cw) && XtIsRealized((Widget)cw)) XClearArea(XtDisplay(wid),XtWindow(wid),0,0,0,0,True); _XmAppUnlock(app); } /************************************************************************ * XmCreateContainer (Public Function) ************************************************************************/ Widget XmCreateContainer( Widget parent, String name, ArgList arglist, Cardinal argcount) { /* * Create an instance of a container and return the widget id. */ return(XtCreateWidget(name,xmContainerWidgetClass,parent,arglist,argcount)); }