Home | History | Annotate | Line # | Download | only in src
      1 /***********************************************************
      2 
      3 Copyright 1987, 1988, 1994, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24 
     25 
     26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
     27 
     28                         All Rights Reserved
     29 
     30 Permission to use, copy, modify, and distribute this software and its
     31 documentation for any purpose and without fee is hereby granted,
     32 provided that the above copyright notice appear in all copies and that
     33 both that copyright notice and this permission notice appear in
     34 supporting documentation, and that the name of Digital not be
     35 used in advertising or publicity pertaining to distribution of the
     36 software without specific, written prior permission.
     37 
     38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     44 SOFTWARE.
     45 
     46 ******************************************************************/
     47 
     48 /*
     49  * Updated and significantly modified from the Athena VPaned Widget.
     50  *
     51  * Date:    March 1, 1989
     52  *
     53  * By:      Chris D. Peterson
     54  *          MIT X Consortium
     55  *          kit (at) expo.lcs.mit.edu
     56  */
     57 
     58 #ifdef HAVE_CONFIG_H
     59 #include <config.h>
     60 #endif
     61 #include <X11/IntrinsicP.h>
     62 #include <X11/cursorfont.h>
     63 #include <X11/StringDefs.h>
     64 #include <X11/Xmu/CharSet.h>
     65 #include <X11/Xmu/Converters.h>
     66 #include <X11/Xmu/Misc.h>
     67 #include <X11/Xaw/Grip.h>
     68 #include <X11/Xaw/PanedP.h>
     69 #include <X11/Xaw/XawImP.h>
     70 #include <X11/Xaw/XawInit.h>
     71 #include "Private.h"
     72 
     73 typedef enum {
     74   UpLeftPane = 'U',
     75   LowRightPane = 'L',
     76   ThisBorderOnly = 'T',
     77   AnyPane = 'A'
     78 } Direction;
     79 
     80 #define NO_INDEX -100
     81 #define IS_GRIP  NULL
     82 
     83 #define PaneInfo(w)	((Pane)(w)->core.constraints)
     84 #define HasGrip(w)	(PaneInfo(w)->grip != NULL)
     85 #define IsPane(w)	((w)->core.widget_class != gripWidgetClass)
     86 #define PaneIndex(w)	(PaneInfo(w)->position)
     87 #define IsVert(w)	((w)->paned.orientation == XtorientVertical)
     88 
     89 #define ForAllPanes(pw, childP) \
     90 for ((childP) = (pw)->composite.children;				\
     91      (childP) < (pw)->composite.children + (pw)->paned.num_panes;	\
     92      (childP)++)
     93 
     94 #define ForAllChildren(pw, childP) \
     95 for ((childP) = (pw)->composite.children;				 \
     96      (childP) < (pw)->composite.children + (pw)->composite.num_children; \
     97      (childP)++)
     98 
     99 #define PaneSize(paned, vertical)			\
    100      ((vertical) ? XtHeight(paned) : XtWidth(paned))
    101 
    102 #define GetRequestInfo(geo, vertical)			\
    103      ((vertical) ? (geo)->height : (geo)->width)
    104 
    105 #define SatisfiesRule1(pane, shrink)			\
    106      (((shrink) && ((pane)->size != (pane)->min))	\
    107       || (!(shrink) && ((pane)->size != (pane)->max)))
    108 
    109 #define SatisfiesRule2(pane)					\
    110      (!(pane)->skip_adjust || (pane)->paned_adjusted_me)
    111 
    112 #define SatisfiesRule3(pane, shrink)					\
    113      ((pane)->paned_adjusted_me						\
    114       && (((shrink) && ((int)(pane)->wp_size <= (pane)->size))		\
    115 	  || (!(shrink) && ((int)(pane)->wp_size >= (pane)->size))))
    116 
    117 
    118 /*
    119  * Class Methods
    120  */
    121 static void XawPanedClassInitialize(void);
    122 static void XawPanedChangeManaged(Widget);
    123 static void XawPanedDeleteChild(Widget);
    124 static void XawPanedDestroy(Widget);
    125 static XtGeometryResult XawPanedGeometryManager(Widget, XtWidgetGeometry*,
    126 						XtWidgetGeometry*);
    127 static void XawPanedInitialize(Widget, Widget, ArgList, Cardinal*);
    128 static void XawPanedInsertChild(Widget);
    129 static Boolean XawPanedPaneSetValues(Widget, Widget, Widget,
    130 				     ArgList, Cardinal*);
    131 static void XawPanedRealize(Widget, Mask*, XSetWindowAttributes*);
    132 static void XawPanedRedisplay(Widget, XEvent*, Region);
    133 static void XawPanedResize(Widget);
    134 static Boolean XawPanedSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
    135 
    136 /*
    137  * Prototypes
    138  */
    139 static void _DrawInternalBorders(PanedWidget, GC);
    140 static void _DrawRect(PanedWidget, GC, int, int, unsigned int, unsigned int);
    141 static void _DrawTrackLines(PanedWidget, Bool);
    142 static void AdjustPanedSize(PanedWidget, unsigned int, XtGeometryResult*,
    143 			    Dimension*, Dimension*);
    144 static void ChangeAllGripCursors(PanedWidget);
    145 static Pane ChoosePaneToResize(PanedWidget, int, Direction, Bool);
    146 static void ClearPaneStack(PanedWidget);
    147 static void CommitGripAdjustment(PanedWidget);
    148 static void CreateGrip(Widget);
    149 static int GetEventLocation(PanedWidget, XEvent*);
    150 static void GetGCs(Widget);
    151 static void GetPaneStack(PanedWidget, Bool, Pane*, int*);
    152 static void HandleGrip(Widget, XtPointer, XtPointer);
    153 static void LoopAndRefigureChildren(PanedWidget, int, Direction, int*);
    154 static void ManageAndUnmanageGrips(PanedWidget);
    155 static void MoveGripAdjustment(PanedWidget, Widget, Direction, int);
    156 static Bool PopPaneStack(PanedWidget);
    157 static void PushPaneStack(PanedWidget, Pane);
    158 static void RefigureLocations(PanedWidget, int, Direction);
    159 static void RefigureLocationsAndCommit(Widget);
    160 static void ReleaseGCs(Widget);
    161 static void ResortChildren(PanedWidget);
    162 static void SetChildrenPrefSizes(PanedWidget, unsigned int);
    163 static void StartGripAdjustment(PanedWidget, Widget, Direction);
    164 
    165 /*
    166  * Initialization
    167  */
    168 static char defGripTranslations[] =
    169 "<Btn1Down>:"		"GripAction(Start,UpLeftPane)\n"
    170 "<Btn2Down>:"		"GripAction(Start,ThisBorderOnly)\n"
    171 "<Btn3Down>:"		"GripAction(Start,LowRightPane)\n"
    172 "<Btn1Motion>:"		"GripAction(Move,UpLeft)\n"
    173 "<Btn2Motion>:"		"GripAction(Move,ThisBorder)\n"
    174 "<Btn3Motion>:"		"GripAction(Move,LowRight)\n"
    175 "Any<BtnUp>:"		"GripAction(Commit)\n"
    176 ;
    177 
    178 #define offset(field) XtOffsetOf(PanedRec, paned.field)
    179 static XtResource resources[] = {
    180   {
    181     XtNinternalBorderColor,
    182     XtCBorderColor,
    183     XtRPixel,
    184     sizeof(Pixel),
    185     offset(internal_bp),
    186     XtRString,
    187     (XtPointer)XtDefaultForeground
    188   },
    189   {
    190     XtNinternalBorderWidth,
    191     XtCBorderWidth,
    192     XtRDimension,
    193     sizeof(Dimension),
    194     offset(internal_bw),
    195     XtRImmediate,
    196     (XtPointer)1
    197   },
    198   {
    199     XtNgripIndent,
    200     XtCGripIndent,
    201     XtRPosition,
    202     sizeof(Position),
    203     offset(grip_indent),
    204     XtRImmediate,
    205     (XtPointer)10
    206   },
    207   {
    208     XtNrefigureMode,
    209     XtCBoolean,
    210     XtRBoolean,
    211     sizeof(Boolean),
    212     offset(refiguremode),
    213     XtRImmediate,
    214     (XtPointer)True
    215   },
    216   {
    217     XtNgripTranslations,
    218     XtCTranslations,
    219     XtRTranslationTable,
    220     sizeof(XtTranslations),
    221     offset(grip_translations),
    222     XtRString,
    223     (XtPointer)defGripTranslations
    224   },
    225   {
    226     XtNorientation,
    227     XtCOrientation,
    228     XtROrientation,
    229     sizeof(XtOrientation),
    230     offset(orientation),
    231     XtRImmediate,
    232     (XtPointer)XtorientVertical
    233   },
    234   {
    235     XtNcursor,
    236     XtCCursor,
    237     XtRCursor,
    238     sizeof(Cursor),
    239     offset(cursor),
    240     XtRImmediate,
    241     NULL
    242   },
    243   {
    244     XtNgripCursor,
    245     XtCCursor,
    246     XtRCursor,
    247     sizeof(Cursor),
    248     offset(grip_cursor),
    249     XtRImmediate,
    250     NULL
    251   },
    252   {
    253     XtNverticalGripCursor,
    254     XtCCursor,
    255     XtRCursor,
    256     sizeof(Cursor),
    257     offset(v_grip_cursor),
    258     XtRString,
    259     (XtPointer)"sb_v_double_arrow"
    260   },
    261   {
    262     XtNhorizontalGripCursor,
    263     XtCCursor,
    264     XtRCursor,
    265     sizeof(Cursor),
    266     offset(h_grip_cursor),
    267     XtRString,
    268     (XtPointer)"sb_h_double_arrow"
    269   },
    270   {
    271     XtNbetweenCursor,
    272     XtCCursor,
    273     XtRCursor,
    274     sizeof(Cursor),
    275     offset(adjust_this_cursor),
    276     XtRString,
    277     NULL
    278   },
    279   {
    280     XtNverticalBetweenCursor,
    281     XtCCursor,
    282     XtRCursor,
    283     sizeof(Cursor),
    284     offset(v_adjust_this_cursor),
    285     XtRString,
    286     (XtPointer)"sb_left_arrow"
    287   },
    288   {
    289     XtNhorizontalBetweenCursor,
    290     XtCCursor,
    291     XtRCursor,
    292     sizeof(Cursor),
    293     offset(h_adjust_this_cursor),
    294     XtRString,
    295     (XtPointer)"sb_up_arrow"
    296   },
    297   {
    298     XtNupperCursor,
    299     XtCCursor,
    300     XtRCursor,
    301     sizeof(Cursor),
    302     offset(adjust_upper_cursor),
    303     XtRString,
    304     (XtPointer)"sb_up_arrow"
    305   },
    306   {
    307     XtNlowerCursor,
    308     XtCCursor,
    309     XtRCursor,
    310     sizeof(Cursor),
    311     offset(adjust_lower_cursor),
    312     XtRString,
    313     (XtPointer)"sb_down_arrow"
    314   },
    315   {
    316     XtNleftCursor,
    317     XtCCursor,
    318     XtRCursor,
    319     sizeof(Cursor),
    320     offset(adjust_left_cursor),
    321     XtRString,
    322     (XtPointer)"sb_left_arrow"
    323   },
    324   {
    325     XtNrightCursor,
    326     XtCCursor,
    327     XtRCursor,
    328     sizeof(Cursor),
    329     offset(adjust_right_cursor),
    330     XtRString,
    331     (XtPointer)"sb_right_arrow"
    332   },
    333 };
    334 #undef offset
    335 
    336 #define offset(field) XtOffsetOf(PanedConstraintsRec, paned.field)
    337 static XtResource subresources[] = {
    338   {
    339     XtNallowResize,
    340     XtCBoolean,
    341     XtRBoolean,
    342     sizeof(Boolean),
    343     offset(allow_resize),
    344     XtRImmediate,
    345     (XtPointer)False
    346   },
    347   {
    348     XtNposition,
    349     XtCPosition,
    350     XtRInt,
    351     sizeof(int),
    352     offset(position),
    353     XtRImmediate,
    354     (XtPointer)0
    355   },
    356   {
    357     XtNmin,
    358     XtCMin,
    359     XtRDimension,
    360     sizeof(Dimension),
    361     offset(min),
    362     XtRImmediate,
    363     (XtPointer)PANED_GRIP_SIZE
    364   },
    365   {
    366     XtNmax,
    367     XtCMax,
    368     XtRDimension,
    369     sizeof(Dimension),
    370     offset(max),
    371     XtRImmediate,
    372     (XtPointer)~0
    373   },
    374   {
    375     XtNpreferredPaneSize,
    376     XtCPreferredPaneSize,
    377     XtRDimension,
    378     sizeof(Dimension),
    379     offset(preferred_size),
    380     XtRImmediate,
    381     (XtPointer)PANED_ASK_CHILD
    382   },
    383   {
    384     XtNresizeToPreferred,
    385     XtCBoolean,
    386     XtRBoolean,
    387     sizeof(Boolean),
    388     offset(resize_to_pref),
    389     XtRImmediate,
    390     (XtPointer)False
    391   },
    392   {
    393     XtNskipAdjust,
    394     XtCBoolean,
    395     XtRBoolean,
    396     sizeof(Boolean),
    397     offset(skip_adjust),
    398     XtRImmediate,
    399     (XtPointer)False
    400   },
    401   {
    402     XtNshowGrip,
    403     XtCShowGrip,
    404     XtRBoolean,
    405     sizeof(Boolean),
    406     offset(show_grip),
    407     XtRImmediate,
    408     (XtPointer)True
    409   },
    410 };
    411 #undef offset
    412 
    413 #define SuperClass ((ConstraintWidgetClass)&constraintClassRec)
    414 
    415 PanedClassRec panedClassRec = {
    416    /* core */
    417    {
    418     (WidgetClass)SuperClass,		/* superclass */
    419     "Paned",				/* class name */
    420     sizeof(PanedRec),			/* size */
    421     XawPanedClassInitialize,		/* class_initialize */
    422     NULL,				/* class_part init */
    423     False,				/* class_inited */
    424     XawPanedInitialize,			/* initialize */
    425     NULL,				/* initialize_hook */
    426     XawPanedRealize,			/* realize */
    427     NULL,				/* actions */
    428     0,					/* num_actions */
    429     resources,				/* resources */
    430     XtNumber(resources),		/* num_resources */
    431     NULLQUARK,				/* xrm_class */
    432     True,				/* compress_motion */
    433     True,				/* compress_exposure */
    434     True,				/* compress_enterleave */
    435     False,				/* visible_interest */
    436     XawPanedDestroy,			/* destroy */
    437     XawPanedResize,			/* resize */
    438     XawPanedRedisplay,			/* expose */
    439     XawPanedSetValues,			/* set_values */
    440     NULL,				/* set_values_hook */
    441     XtInheritSetValuesAlmost,		/* set_values_almost */
    442     NULL,				/* get_values_hook */
    443     NULL,				/* accept_focus */
    444     XtVersion,				/* version */
    445     NULL,				/* callback_private */
    446     NULL,				/* tm_table */
    447     XtInheritQueryGeometry,		/* query_geometry */
    448     XtInheritDisplayAccelerator,	/* display_accelerator */
    449     NULL,				/* extension */
    450   },
    451   /* composite */
    452   {
    453     XawPanedGeometryManager,		/* geometry_manager */
    454     XawPanedChangeManaged,		/* change_managed */
    455     XawPanedInsertChild,		/* insert_child */
    456     XawPanedDeleteChild,		/* delete_child */
    457     NULL,				/* extension */
    458   },
    459   /* constraint */
    460   {
    461     subresources,			/* subresources */
    462     XtNumber(subresources),		/* subresource_count */
    463     sizeof(PanedConstraintsRec),	/* constraint_size */
    464     NULL,				/* initialize */
    465     NULL,				/* destroy */
    466     XawPanedPaneSetValues,		/* set_values */
    467     NULL,				/* extension */
    468   },
    469   /* paned */
    470   {
    471     NULL,				/* extension */
    472   }
    473 };
    474 
    475 WidgetClass panedWidgetClass = (WidgetClass)&panedClassRec;
    476 WidgetClass vPanedWidgetClass = (WidgetClass)&panedClassRec;
    477 
    478 /*
    479  * Implementation
    480  */
    481 /* Function:
    482  *	AdjustPanedSize
    483  *
    484  * Parameters:
    485  *	pw	     - paned widget to adjust
    486  *	off_size     - new off_size to use
    487  *	result_ret   - result of query (return)
    488  *	on_size_ret  - new on_size  (return)
    489  *	off_size_ret - new off_size (return)
    490  *
    491  * Description:
    492  *	Adjusts the size of the pane.
    493  *
    494  * Returns:
    495  *	amount of change in size
    496  */
    497 static void
    498 AdjustPanedSize(PanedWidget pw, unsigned int off_size,
    499 		XtGeometryResult *result_ret,
    500 		Dimension *on_size_ret, Dimension *off_size_ret)
    501 {
    502     Dimension old_size = PaneSize((Widget)pw, IsVert(pw));
    503     Dimension newsize = 0;
    504     Widget *childP;
    505     XtWidgetGeometry request, reply;
    506 
    507     request.request_mode = CWWidth | CWHeight;
    508 
    509     ForAllPanes(pw, childP) {
    510 	int size = Max(PaneInfo(*childP)->size, (int)PaneInfo(*childP)->min);
    511 
    512 	AssignMin(size, (int)PaneInfo(*childP)->max);
    513 	newsize = (Dimension)(newsize + (size + pw->paned.internal_bw));
    514     }
    515     newsize = (Dimension)(newsize - pw->paned.internal_bw);
    516 
    517     if (newsize < 1)
    518 	newsize = 1;
    519 
    520     if (IsVert(pw)) {
    521 	request.width = (Dimension)off_size;
    522 	request.height = newsize;
    523     }
    524     else {
    525 	request.width = newsize;
    526 	request.height = (Dimension)off_size;
    527     }
    528 
    529     if (result_ret != NULL) {
    530 	request.request_mode |= XtCWQueryOnly;
    531 
    532 	*result_ret = XtMakeGeometryRequest((Widget)pw, &request, &reply);
    533 	_XawImCallVendorShellExtResize((Widget)pw);
    534 
    535 	if (newsize == old_size || *result_ret == XtGeometryNo) {
    536 	    *on_size_ret = old_size;
    537 	    *off_size_ret = (Dimension)off_size;
    538 	    return;
    539 	}
    540 	if (*result_ret != XtGeometryAlmost) {
    541 	    *on_size_ret = GetRequestInfo(&request, IsVert(pw));
    542 	    *off_size_ret = GetRequestInfo(&request, !IsVert(pw));
    543 	    return;
    544 	}
    545 	*on_size_ret = GetRequestInfo(&reply, IsVert(pw));
    546 	*off_size_ret = GetRequestInfo(&reply, !IsVert(pw));
    547 	return;
    548     }
    549 
    550     if (newsize == old_size)
    551 	return;
    552 
    553     if (XtMakeGeometryRequest((Widget)pw, &request, &reply) == XtGeometryAlmost)
    554 	XtMakeGeometryRequest((Widget)pw, &reply, &request);
    555 }
    556 
    557 /*
    558  * Function:
    559  *	ChoosePaneToResize.
    560  *
    561  * Parameters:
    562  *	pw	  - paned widget
    563  *	paneindex - index of the current pane
    564  *	dir	  - direction to search first
    565  *	shrink	  - True if we need to shrink a pane, False otherwise
    566  *
    567  * Description:
    568  *	  This function chooses a pane to resize.
    569  *	  They are chosen using the following rules:
    570  *
    571  *		   1) size < max && size > min
    572  *	2) skip adjust == False
    573  *	3) widget not its preferred height
    574  *	   && this change will bring it closer
    575  *	   && The user has not resized this pane.
    576  *
    577  *		   If no widgets are found that fits all the rules then
    578  *		      rule #3 is broken.
    579  *		   If there are still no widgets found than
    580  *		      rule #2 is broken.
    581  *		   Rule #1 is never broken.
    582  *		   If no widgets are found then NULL is returned.
    583  *
    584  * Returns:
    585  *	pane to resize or NULL
    586  */
    587 static Pane
    588 ChoosePaneToResize(PanedWidget pw, int paneindex, Direction dir, Bool shrink)
    589 {
    590     Widget *childP;
    591     int rules = 3;
    592     Direction _dir = dir;
    593     int _index = paneindex;
    594 
    595     if (paneindex == NO_INDEX || dir == AnyPane) {		/* Use defaults */
    596 	_dir = LowRightPane;			/* Go up - really */
    597 	_index = pw->paned.num_panes - 1;	/* Start the last pane, and work
    598 						   backwards */
    599     }
    600     childP = pw->composite.children + _index;
    601 
    602     /*CONSTCOND*/
    603     while(True) {
    604 	Pane pane = PaneInfo(*childP);
    605 
    606 	if ((rules < 3 || SatisfiesRule3(pane, shrink))
    607 	    && (rules < 2 || SatisfiesRule2(pane))
    608 	    && SatisfiesRule1(pane, shrink)
    609 	    && (paneindex != PaneIndex(*childP) || dir == AnyPane))
    610 	    return (pane);
    611 
    612 	/*
    613 	 * This is counter-intuitive, but if we are resizing the pane
    614 	 * above the grip we want to choose a pane below the grip to lose,
    615 	 * and visa-versa
    616 	 */
    617 	if (_dir == LowRightPane)
    618 	    --childP;
    619 	else
    620 	    ++childP;
    621 
    622 	/*
    623 	 * If we have come to and edge then reduce the rule set, and try again
    624 	 * If we are reduced the rules to none, then return NULL
    625 	 */
    626 	if ((childP - pw->composite.children) < 0 ||
    627 	    (childP - pw->composite.children) >= pw->paned.num_panes) {
    628 	    if (--rules < 1)	/* less strict rules */
    629 		return (NULL);
    630 	    childP = pw->composite.children + _index;
    631 	}
    632     }
    633 }
    634 
    635 /*
    636  * Function:
    637  *	LoopAndRefigureChildren
    638  *
    639  * Parameters:
    640  *	pw	  - paned widget
    641  *	paneindex - number of the pane border we are moving
    642  *	dir	  - pane to move (either UpLeftPane or LowRightPane)
    643  *	sizeused  - current amount of space used (used and returned)
    644  *
    645  * Description:
    646  *	  If we are resizing either the UpleftPane or LowRight Pane loop
    647  *	through all the children to see if any will allow us to resize them.
    648  */
    649 static void
    650 LoopAndRefigureChildren(PanedWidget pw, int paneindex, Direction dir,
    651 			int *sizeused)
    652 {
    653     int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
    654     Boolean shrink = (*sizeused > pane_size);
    655 
    656     if (dir == LowRightPane)
    657 	paneindex++;
    658 
    659     /* While all panes do not fit properly */
    660     while (*sizeused != pane_size) {
    661 	/*
    662 	 * Choose a pane to resize
    663 	 * First look on the Pane Stack, and then go hunting for another one
    664 	 * If we fail to find a pane to resize then give up
    665 	 */
    666 	Pane pane;
    667 	int start_size;
    668 	Dimension old;
    669 	Boolean rule3_ok = False, from_stack = True;
    670 
    671 	GetPaneStack(pw, shrink, &pane, &start_size);
    672 	if (pane == NULL) {
    673 	    pane = ChoosePaneToResize(pw, paneindex, dir, shrink);
    674 	    if (pane == NULL)
    675 		return; /* no one to resize, give up */
    676 
    677 	    rule3_ok = SatisfiesRule3(pane, shrink);
    678 	    from_stack = False;
    679 	    PushPaneStack(pw, pane);
    680 	}
    681 
    682 	/*
    683 	 * Try to resize this pane so that all panes will fit, take min and max
    684 	 * into account
    685 	 */
    686 	old = (Dimension) pane->size;
    687 	pane->size += pane_size - *sizeused;
    688 
    689 	if (from_stack) {
    690 	    if (shrink) {
    691 		AssignMax(pane->size, start_size);
    692 	    }	/* don't remove these braces */
    693 	    else
    694 		AssignMin(pane->size, start_size);
    695 
    696 	  if (pane->size == start_size)
    697 	    (void)PopPaneStack(pw);
    698 	}
    699 	else if (rule3_ok) {
    700 	    if (shrink) {
    701 		AssignMax(pane->size, (int)pane->wp_size);
    702 	    }	/* don't remove these braces */
    703 	    else
    704 		AssignMin(pane->size, (int)pane->wp_size);
    705 	}
    706 
    707 	pane->paned_adjusted_me = pane->size != pane->wp_size;
    708 	AssignMax(pane->size, (int)pane->min);
    709 	AssignMin(pane->size, (int)pane->max);
    710 	*sizeused += (pane->size - old);
    711     }
    712 }
    713 
    714 /*
    715  * Function:
    716  *	RefigureLocations
    717  *
    718  * Parameters:
    719  *	pw	  - paned widget
    720  *	paneindex - child to start refiguring at
    721  *	dir	  - direction to move from child
    722  *
    723  * Description:
    724  *	  Refigures all locations of children.
    725  *      There are special arguments to paneindex and dir, they are:
    726  *      paneindex - NO_INDEX.
    727  *      dir   - AnyPane.
    728  *
    729  *      If either of these is true then all panes may be resized and
    730  *      the choosing of panes proceeds in reverse order starting with the
    731  *      last child.
    732  */
    733 static void
    734 RefigureLocations(PanedWidget pw, int paneindex, Direction dir)
    735 {
    736     Widget *childP;
    737     int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
    738     int sizeused = 0;
    739     Position loc = 0;
    740 
    741     if (pw->paned.num_panes == 0 || !pw->paned.refiguremode)
    742 	return;
    743 
    744     /*
    745      * Get an initial estimate of the size we will use
    746      */
    747     ForAllPanes(pw, childP) {
    748 	Pane pane = PaneInfo(*childP);
    749 
    750 	AssignMax(pane->size, (int) pane->min);
    751 	AssignMin(pane->size, (int) pane->max);
    752 	sizeused += (int)pane->size + (int)pw->paned.internal_bw;
    753     }
    754     sizeused -= (int)pw->paned.internal_bw;
    755 
    756     if (dir != ThisBorderOnly && sizeused != pane_size)
    757 	LoopAndRefigureChildren(pw, paneindex, dir, &sizeused);
    758 
    759     /*
    760      * If we still are not the right size, then tell the pane that
    761      * wanted to resize that it can't
    762      */
    763     if (paneindex != NO_INDEX && dir != AnyPane) {
    764 	Pane pane = PaneInfo(*(pw->composite.children + paneindex));
    765 	Dimension old = (Dimension)pane->size;
    766 
    767 	pane->size += pane_size - sizeused;
    768 	AssignMax(pane->size, (int) pane->min);
    769 	AssignMin(pane->size, (int) pane->max);
    770 	sizeused += pane->size - old;
    771     }
    772 
    773     /*
    774      * It is possible that the panes will not fit inside the vpaned widget, but
    775      * we have tried out best
    776      *
    777      * Assign each pane a location
    778      */
    779     ForAllPanes(pw, childP) {
    780 	PaneInfo(*childP)->delta = loc;
    781 	loc = (Position)(loc + (PaneInfo(*childP)->size + pw->paned.internal_bw));
    782     }
    783 }
    784 
    785 /*
    786  * Function:
    787  *	CommitNewLocations
    788  *
    789  * Parameters:
    790  *	pw - paned widget
    791  *
    792  * Description:
    793  *	Commits all of the previously figured locations.
    794  */
    795 static void
    796 CommitNewLocations(PanedWidget pw)
    797 {
    798     Widget *childP;
    799     XWindowChanges changes = { .stack_mode = Above };
    800 
    801     ForAllPanes(pw, childP) {
    802 	Pane pane = PaneInfo(*childP);
    803 	Widget grip = pane->grip;	/* may be NULL */
    804 
    805 	if (IsVert(pw)) {
    806 	    XtMoveWidget(*childP, (Position) 0, pane->delta);
    807 	    XtResizeWidget(*childP, XtWidth(pw), (Dimension)pane->size, 0);
    808 
    809 	    if (HasGrip(*childP)) {	/* Move and Display the Grip */
    810 		changes.x = XtWidth(pw) - pw->paned.grip_indent -
    811 			    XtWidth(grip) - (XtBorderWidth(grip) << 1);
    812 		changes.y = XtY(*childP) + XtHeight(*childP) -
    813 			    (XtHeight(grip) >> 1) - XtBorderWidth(grip) +
    814 			    (pw->paned.internal_bw >> 1);
    815 	    }
    816 	}
    817 	else {
    818 	    XtMoveWidget(*childP, pane->delta, 0);
    819 	    XtResizeWidget(*childP, (Dimension)pane->size, (Dimension)XtHeight(pw), 0);
    820 
    821 	    if (HasGrip(*childP)) {		/* Move and Display the Grip */
    822 		changes.x = XtX(*childP) + XtWidth(*childP) -
    823 			    (XtWidth(grip) >> 1) - XtBorderWidth(grip) +
    824 			    (pw->paned.internal_bw >> 1);
    825 		changes.y = XtHeight(pw) - pw->paned.grip_indent -
    826 			    XtHeight(grip) - (XtBorderWidth(grip) << 1);
    827 	    }
    828 	}
    829 
    830 	/*
    831 	 * This should match XtMoveWidget, except that we're also insuring the
    832 	 * grip is Raised in the same request
    833 	 */
    834 
    835 	if (HasGrip(*childP)) {
    836 	    XtX(grip) = (Position)changes.x;
    837 	    XtY(grip) = (Position)changes.y;
    838 
    839 	    if (XtIsRealized(pane->grip))
    840 		XConfigureWindow(XtDisplay(pane->grip), XtWindow(pane->grip),
    841 				 CWX | CWY | CWStackMode, &changes);
    842 	}
    843     }
    844     ClearPaneStack(pw);
    845 }
    846 
    847 /*
    848  * Function:
    849  *	RefigureLocationsAndCommit
    850  *
    851  * Parameters:
    852  *	pw - paned widget
    853  *
    854  * Description:
    855  *	Refigures all locations in a paned widget and commits them immediately.
    856  *
    857  *      This function does nothing if any of the following are true.
    858  *      o refiguremode is false.
    859  *      o The widget is unrealized.
    860  *      o There are no panes is the paned widget.
    861  */
    862 static void
    863 RefigureLocationsAndCommit(Widget w)
    864 {
    865     PanedWidget pw = (PanedWidget)w;
    866 
    867     if (pw->paned.refiguremode && XtIsRealized(w) && pw->paned.num_panes > 0) {
    868 	RefigureLocations(pw, NO_INDEX, AnyPane);
    869 	CommitNewLocations(pw);
    870     }
    871 }
    872 
    873 /*
    874  * Function:
    875  *	_DrawRect
    876  *
    877  * Parameters:
    878  *	pw	 - paned widget
    879  *	gc	 - gc to used for the draw
    880  *	on_olc	 - location of upper left corner of rect
    881  *	off_loc	 - ""
    882  *	on_size	 - size of rectangle
    883  *	off_size - ""
    884  *
    885  * Description:
    886  *	Draws a rectangle in the proper orientation.
    887  */
    888 static void
    889 _DrawRect(PanedWidget pw, GC gc, int on_loc, int off_loc,
    890 	  unsigned int on_size, unsigned int off_size)
    891 {
    892     if (IsVert(pw))
    893 	XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
    894 		       off_loc, on_loc, off_size, on_size);
    895     else
    896 	XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
    897 		       on_loc, off_loc, on_size, off_size);
    898 }
    899 
    900 /*
    901  * Function:
    902  *	_DrawInternalBorders
    903  *
    904  * Parameters:
    905  *	pw - paned widget
    906  *	gc - GC to use to draw the borders
    907  *
    908  * Description:
    909  *	Draws the internal borders into the paned widget.
    910  */
    911 static void
    912 _DrawInternalBorders(PanedWidget pw, GC gc)
    913 {
    914     Widget *childP;
    915     int off_loc;
    916     unsigned int on_size, off_size;
    917 
    918     /*
    919      * This is an optimization.  Do not paint the internal borders if
    920      * they are the same color as the background
    921      */
    922     if (pw->core.background_pixel == pw->paned.internal_bp)
    923 	return;
    924 
    925     off_loc = 0;
    926     off_size = (unsigned int) PaneSize((Widget)pw, !IsVert(pw));
    927     on_size = (unsigned int)pw->paned.internal_bw;
    928 
    929     ForAllPanes(pw, childP) {
    930 	int on_loc = IsVert(pw) ? XtY(*childP) : XtX(*childP);
    931 	on_loc -= (int)on_size;
    932 
    933 	_DrawRect(pw, gc, on_loc, off_loc, on_size, off_size);
    934     }
    935 }
    936 
    937 #define DrawInternalBorders(pw)				\
    938 	_DrawInternalBorders((pw), (pw)->paned.normgc)
    939 #define EraseInternalBorders(pw)			\
    940 	_DrawInternalBorders((pw), (pw)->paned.invgc)
    941 /*
    942  * Function Name:
    943  *	_DrawTrackLines
    944  *
    945  * Parameters:
    946  *	pw - Paned widget
    947  *	erase - if True then just erase track lines, else draw them in
    948  *
    949  * Description:
    950  *	Draws the lines that animate the pane borders when the grips are moved.
    951  */
    952 static void
    953 _DrawTrackLines(PanedWidget pw, Bool erase)
    954 {
    955     Widget *childP;
    956     Pane pane;
    957     int on_loc, off_loc;
    958     unsigned int on_size, off_size;
    959 
    960     off_loc = 0;
    961     off_size = PaneSize((Widget)pw, !IsVert(pw));
    962 
    963     ForAllPanes(pw, childP) {
    964 	pane = PaneInfo(*childP);
    965 	if (erase || pane->olddelta != pane->delta) {
    966 	    on_size = pw->paned.internal_bw;
    967 	    if (!erase) {
    968 		on_loc = PaneInfo(*childP)->olddelta - (int) on_size;
    969 		_DrawRect(pw, pw->paned.flipgc,
    970 			  on_loc, off_loc, on_size, off_size);
    971 	    }
    972 
    973 	    on_loc = PaneInfo(*childP)->delta - (int)on_size;
    974 
    975 	    _DrawRect(pw, pw->paned.flipgc,
    976 		      on_loc, off_loc, on_size, off_size);
    977 
    978 	    pane->olddelta = pane->delta;
    979 	}
    980     }
    981 }
    982 
    983 #define DrawTrackLines(pw)	_DrawTrackLines((pw), False);
    984 #define EraseTrackLines(pw)	_DrawTrackLines((pw), True);
    985 /*
    986  * Function:
    987  *	GetEventLocation
    988  *
    989  * Parameters:
    990  *	pw    - the paned widget
    991  *	event - pointer to an event
    992  *
    993  * Description:
    994  *	Converts and event to an x and y location.
    995  *
    996  * Returns:
    997  *	if this is a vertical pane then (y) else (x)
    998  */
    999 static int
   1000 GetEventLocation(PanedWidget pw, XEvent *event)
   1001 {
   1002     int x, y;
   1003 
   1004     switch (event->xany.type) {
   1005 	case ButtonPress:
   1006 	case ButtonRelease:
   1007 	    x = event->xbutton.x_root;
   1008 	    y = event->xbutton.y_root;
   1009 	    break;
   1010 	case KeyPress:
   1011 	case KeyRelease:
   1012 	    x = event->xkey.x_root;
   1013 	    y = event->xkey.y_root;
   1014 	    break;
   1015 	case MotionNotify:
   1016 	    x = event->xmotion.x_root;
   1017 	    y = event->xmotion.y_root;
   1018 	    break;
   1019 	default:
   1020 	    x = pw->paned.start_loc;
   1021 	    y = pw->paned.start_loc;
   1022     }
   1023 
   1024     if (IsVert(pw))
   1025 	return (y);
   1026 
   1027   return (x);
   1028 }
   1029 
   1030 /*
   1031  * Function:
   1032  *	StartGripAdjustment
   1033  *
   1034  * Parameters:
   1035  *	pw   - paned widget
   1036  *	grip - grip widget selected
   1037  *	dir  - direction that we are to be moving
   1038  *
   1039  * Description:
   1040  *	Starts the grip adjustment procedure.
   1041  */
   1042 static void
   1043 StartGripAdjustment(PanedWidget pw, Widget grip, Direction dir)
   1044 {
   1045     Widget *childP;
   1046 
   1047     pw->paned.whichadd = pw->paned.whichsub = NULL;
   1048 
   1049     if (dir == ThisBorderOnly || dir == UpLeftPane)
   1050 	pw->paned.whichadd = pw->composite.children[PaneIndex(grip)];
   1051     if (dir == ThisBorderOnly || dir == LowRightPane)
   1052 	pw->paned.whichsub = pw->composite.children[PaneIndex(grip) + 1];
   1053 
   1054     /*
   1055      * Change the cursor
   1056      */
   1057     if (XtIsRealized(grip)) {
   1058 	Cursor cursor;
   1059 
   1060 	if (IsVert(pw)) {
   1061 	    if (dir == UpLeftPane)
   1062 		cursor = pw->paned.adjust_upper_cursor;
   1063 	    else if (dir == LowRightPane)
   1064 		cursor = pw->paned.adjust_lower_cursor;
   1065 	    else {
   1066 		if (pw->paned.adjust_this_cursor == None)
   1067 		    cursor = pw->paned.v_adjust_this_cursor;
   1068 		else
   1069 		    cursor = pw->paned.adjust_this_cursor;
   1070 	    }
   1071 	}
   1072 	else {
   1073 	    if (dir == UpLeftPane)
   1074 		cursor = pw->paned.adjust_left_cursor;
   1075 	    else if (dir == LowRightPane)
   1076 		cursor = pw->paned.adjust_right_cursor;
   1077 	    else {
   1078 		if (pw->paned.adjust_this_cursor == None)
   1079 		    cursor = pw->paned.h_adjust_this_cursor;
   1080 		else
   1081 		    cursor = pw->paned.adjust_this_cursor;
   1082 	    }
   1083 	}
   1084 
   1085 	XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
   1086     }
   1087 
   1088     EraseInternalBorders(pw);
   1089     ForAllPanes(pw, childP)
   1090 	PaneInfo(*childP)->olddelta = -99;
   1091 
   1092     EraseTrackLines(pw);
   1093 }
   1094 
   1095 /*
   1096  * Function:
   1097  *	MoveGripAdjustment
   1098  *
   1099  * Parameters:
   1100  *	pw   - paned widget
   1101  *	grip - grip that we are moving
   1102  *	dir  - direction the pane we are interested is w.r.t the grip
   1103  *	loc  - location of pointer in proper direction
   1104  *
   1105  * Description:
   1106  *	This routine moves all panes around when a grip is moved.
   1107  */
   1108 static void
   1109 MoveGripAdjustment(PanedWidget pw, Widget grip, Direction dir, int loc)
   1110 {
   1111     int diff, add_size = 0, sub_size = 0;
   1112 
   1113     diff = loc - pw->paned.start_loc;
   1114 
   1115     if (pw->paned.whichadd)
   1116     add_size = PaneSize(pw->paned.whichadd, IsVert(pw)) + diff;
   1117 
   1118     if (pw->paned.whichsub)
   1119     sub_size = PaneSize(pw->paned.whichsub, IsVert(pw)) - diff;
   1120 
   1121     /*
   1122      * If moving this border only then do not allow either of the borders
   1123      * to go beyond the min or max size allowed
   1124      */
   1125     if (dir == ThisBorderOnly) {
   1126 	int old_add_size = add_size, old_sub_size;
   1127 
   1128 	if (pw->paned.whichadd == NULL)
   1129 	    return;
   1130 
   1131 	AssignMax(add_size, (int)PaneInfo(pw->paned.whichadd)->min);
   1132 	AssignMin(add_size, (int)PaneInfo(pw->paned.whichadd)->max);
   1133 	if (add_size != old_add_size)
   1134 	    sub_size += old_add_size - add_size;
   1135 
   1136 	if (pw->paned.whichsub == NULL)
   1137 	    return;
   1138 
   1139 	old_sub_size = sub_size;
   1140 	AssignMax(sub_size, (int)PaneInfo(pw->paned.whichsub)->min);
   1141 	AssignMin(sub_size, (int)PaneInfo(pw->paned.whichsub)->max);
   1142 	if (sub_size != old_sub_size)
   1143 	    return;	/* Abort to current sizes */
   1144     }
   1145 
   1146     if (add_size != 0)
   1147 	PaneInfo(pw->paned.whichadd)->size = add_size;
   1148     if (sub_size != 0)
   1149 	PaneInfo(pw->paned.whichsub)->size = sub_size;
   1150     RefigureLocations(pw, PaneIndex(grip), dir);
   1151     DrawTrackLines(pw);
   1152 }
   1153 
   1154 /*
   1155  * Function:
   1156  *	CommitGripAdjustment
   1157  *
   1158  * Parameters:
   1159  *	pw - paned widget
   1160  *
   1161  * Description:
   1162  *	Commits the grip adjustment.
   1163  */
   1164 static void
   1165 CommitGripAdjustment(PanedWidget pw)
   1166 {
   1167     EraseTrackLines(pw);
   1168     CommitNewLocations(pw);
   1169     DrawInternalBorders(pw);
   1170 
   1171     /*
   1172      * Since the user selected this size then use it as the preferred size
   1173      */
   1174     if (pw->paned.whichadd) {
   1175 	Pane pane = PaneInfo(pw->paned.whichadd);
   1176 
   1177 	pane->wp_size = (Dimension)pane->size;
   1178     }
   1179     if (pw->paned.whichsub) {
   1180 	Pane pane = PaneInfo(pw->paned.whichsub);
   1181 
   1182 	pane->wp_size = (Dimension)pane->size;
   1183     }
   1184 }
   1185 
   1186 /*
   1187  * Function:
   1188  *	HandleGrip
   1189  *
   1190  * Parameters:
   1191  *	grip	  - grip widget that has been moved
   1192  *	temp	  - (not used)
   1193  *	call_data - data passed to us from the grip widget
   1194  *
   1195  * Description:
   1196  *	Handles the grip manipulations.
   1197  */
   1198 /*ARGSUSED*/
   1199 static void
   1200 HandleGrip(Widget grip, XtPointer temp _X_UNUSED, XtPointer callData)
   1201 {
   1202     XawGripCallData call_data = (XawGripCallData)callData;
   1203     PanedWidget pw = (PanedWidget) XtParent(grip);
   1204     int loc;
   1205     char action_type[2], direction[2];
   1206     Cursor cursor;
   1207     Arg arglist[1];
   1208 
   1209     if (call_data->num_params)
   1210 	XmuNCopyISOLatin1Uppered(action_type, call_data->params[0],
   1211 				 sizeof(action_type));
   1212 
   1213     if (call_data->num_params == 0
   1214 	|| (action_type[0] == 'C' && call_data->num_params != 1)
   1215 	|| (action_type[0] != 'C' && call_data->num_params != 2))
   1216 	XtAppError(XtWidgetToApplicationContext(grip),
   1217 		   "Paned GripAction has been passed incorrect parameters.");
   1218 
   1219     loc = GetEventLocation(pw, (XEvent *)call_data->event);
   1220 
   1221     if (action_type[0] != 'C')
   1222 	XmuNCopyISOLatin1Uppered(direction, call_data->params[1],
   1223 				 sizeof(direction));
   1224 
   1225     switch (action_type[0]) {
   1226 	case 'S':		/* Start adjustment */
   1227 	    pw->paned.resize_children_to_pref = False;
   1228 	    StartGripAdjustment(pw, grip, (Direction)direction[0]);
   1229 	    pw->paned.start_loc = loc;
   1230 	    break;
   1231 	case 'M':
   1232 	    MoveGripAdjustment(pw, grip, (Direction)direction[0], loc);
   1233 	    break;
   1234 	case 'C':
   1235 	    XtSetArg(arglist[0], XtNcursor, &cursor);
   1236 	    XtGetValues(grip, arglist, 1);
   1237 	    XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
   1238 	    CommitGripAdjustment(pw);
   1239 	    break;
   1240 	default:
   1241 	    XtAppError(XtWidgetToApplicationContext(grip),
   1242 		       "Paned GripAction(); 1st parameter invalid");
   1243 	    break;
   1244      }
   1245 }
   1246 
   1247 /*
   1248  * Function:
   1249  *	ResortChildren
   1250  *
   1251  * Arguments:
   1252  *	pw - paned widget
   1253  *
   1254  * Description:
   1255  *	Resorts the children so that all managed children are first.
   1256  */
   1257 static void
   1258 ResortChildren(PanedWidget pw)
   1259 {
   1260     Widget *unmanagedP, *childP;
   1261 
   1262     unmanagedP = NULL;
   1263     ForAllChildren(pw, childP) {
   1264 	if (!IsPane(*childP) || !XtIsManaged(*childP)) {
   1265 	    /*
   1266 	     * We only keep track of the first unmanaged pane
   1267 	     */
   1268 	    if (unmanagedP == NULL)
   1269 		unmanagedP = childP;
   1270 	}
   1271 	else {			/* must be a managed pane */
   1272 	    /*
   1273 	     * If an earlier widget was not a managed pane, then swap
   1274 	     */
   1275 	    if (unmanagedP != NULL) {
   1276 		Widget child = *unmanagedP;
   1277 
   1278 		*unmanagedP = *childP;
   1279 		*childP = child;
   1280 		childP = unmanagedP;  /* easiest to just back-track */
   1281 		unmanagedP = NULL;    /* in case there is another managed */
   1282 	   }
   1283        }
   1284    }
   1285 }
   1286 
   1287 /*
   1288  * Function:
   1289  *	ManageAndUnmanageGrips
   1290  *
   1291  * Parameters:
   1292  *	pw - paned widget
   1293  *
   1294  * Description:
   1295  *	  This function manages and unmanages the grips so that
   1296  *		   the managed state of each grip matches that of its pane.
   1297  */
   1298 static void
   1299 ManageAndUnmanageGrips(PanedWidget pw)
   1300 {
   1301     WidgetList managed_grips, unmanaged_grips;
   1302     Widget *managedP, *unmanagedP, *childP;
   1303     Cardinal alloc_size;
   1304 
   1305     alloc_size = (Cardinal)(sizeof(Widget) * (pw->composite.num_children >> 1));
   1306     managedP = managed_grips = (WidgetList)XtMalloc(alloc_size);
   1307     unmanagedP = unmanaged_grips = (WidgetList)XtMalloc(alloc_size);
   1308 
   1309     ForAllChildren(pw, childP)
   1310 	if (IsPane(*childP) && HasGrip(*childP)) {
   1311 	    if (XtIsManaged(*childP))
   1312 		*managedP++ = PaneInfo(*childP)->grip;
   1313 	    else
   1314 		*unmanagedP++ = PaneInfo(*childP)->grip;
   1315 	}
   1316 
   1317     if (managedP != managed_grips) {
   1318 	*unmanagedP++ = *--managedP;   /* Last grip is never managed */
   1319 	XtManageChildren(managed_grips, (Cardinal)(managedP - managed_grips));
   1320     }
   1321 
   1322     if (unmanagedP != unmanaged_grips)
   1323 	XtUnmanageChildren(unmanaged_grips, (Cardinal)(unmanagedP - unmanaged_grips));
   1324 
   1325     XtFree((char *)managed_grips);
   1326     XtFree((char *)unmanaged_grips);
   1327 }
   1328 
   1329 /*
   1330  * Function:
   1331  *	CreateGrip
   1332  *
   1333  * Parameters:
   1334  *	child - child that wants a grip to be created for it
   1335  *
   1336  * Description:
   1337  *	Creates a grip widget.
   1338  */
   1339 static void
   1340 CreateGrip(Widget child)
   1341 {
   1342     PanedWidget pw = (PanedWidget)XtParent(child);
   1343     Arg arglist[2];
   1344     Cardinal num_args = 0;
   1345     Cursor cursor;
   1346 
   1347     XtSetArg(arglist[num_args], XtNtranslations, pw->paned.grip_translations);
   1348     num_args++;
   1349     if ((cursor = pw->paned.grip_cursor) == None) {
   1350 	if (IsVert(pw))
   1351 	    cursor = pw->paned.v_grip_cursor;
   1352 	else
   1353 	    cursor = pw->paned.h_grip_cursor;
   1354     }
   1355 
   1356     XtSetArg(arglist[num_args], XtNcursor, cursor);
   1357     num_args++;
   1358     PaneInfo(child)->grip = XtCreateWidget("grip", gripWidgetClass, (Widget)pw,
   1359 					   arglist, num_args);
   1360 
   1361     XtAddCallback(PaneInfo(child)->grip, XtNcallback,
   1362 		  HandleGrip, (XtPointer)child);
   1363 }
   1364 
   1365 /*
   1366  * Function:
   1367  *	GetGCs
   1368  *
   1369  * Parameters:
   1370  *	w - paned widget
   1371  */
   1372 static void
   1373 GetGCs(Widget w)
   1374 {
   1375     PanedWidget pw = (PanedWidget)w;
   1376     XtGCMask valuemask;
   1377     XGCValues values;
   1378 
   1379     /*
   1380      * Draw pane borders in internal border color
   1381      */
   1382     values.foreground = pw->paned.internal_bp;
   1383     valuemask = GCForeground;
   1384     pw->paned.normgc = XtGetGC(w, valuemask, &values);
   1385 
   1386     /*
   1387      * Erase pane borders with background color
   1388      */
   1389     values.foreground = pw->core.background_pixel;
   1390     valuemask = GCForeground;
   1391     pw->paned.invgc = XtGetGC(w, valuemask, &values);
   1392 
   1393     /*
   1394      * Draw Track lines (animate pane borders) in
   1395      * internal border color ^ bg color
   1396      */
   1397     values.function = GXinvert;
   1398     values.plane_mask = pw->paned.internal_bp ^ pw->core.background_pixel;
   1399     values.subwindow_mode = IncludeInferiors;
   1400     valuemask = GCPlaneMask | GCFunction | GCSubwindowMode;
   1401     pw->paned.flipgc = XtGetGC(w, valuemask, &values);
   1402 }
   1403 
   1404 /*
   1405  * Function:
   1406  *	SetChildrenPrefSizes
   1407  *
   1408  * Parameters:
   1409  *	pw - paned widget
   1410  *
   1411  * Description:
   1412  *	Sets the preferred sizes of the children.
   1413  */
   1414 static void
   1415 SetChildrenPrefSizes(PanedWidget pw, unsigned int off_size)
   1416 {
   1417     Widget *childP;
   1418     Boolean vert = IsVert(pw);
   1419     XtWidgetGeometry request, reply;
   1420 
   1421     ForAllPanes(pw, childP)
   1422 	if (pw->paned.resize_children_to_pref || PaneInfo(*childP)->size == 0 ||
   1423 	    PaneInfo(*childP)->resize_to_pref) {
   1424 	    if (PaneInfo(*childP)->preferred_size != PANED_ASK_CHILD)
   1425 		PaneInfo(*childP)->wp_size = PaneInfo(*childP)->preferred_size;
   1426 	    else {
   1427 		if(vert) {
   1428 		    request.request_mode = CWWidth;
   1429 		    request.width = (Dimension) off_size;
   1430 		}
   1431 		else {
   1432 		    request.request_mode = CWHeight;
   1433 		    request.height = (Dimension) off_size;
   1434 		}
   1435 
   1436 		if ((XtQueryGeometry(*childP, &request, &reply)
   1437 		     == XtGeometryAlmost)
   1438 		    && (reply.request_mode = (vert ? CWHeight : CWWidth)))
   1439 		    PaneInfo(*childP)->wp_size = GetRequestInfo(&reply, vert);
   1440 		else
   1441 		    PaneInfo(*childP)->wp_size = PaneSize(*childP, vert);
   1442 	    }
   1443 
   1444 	    PaneInfo(*childP)->size = PaneInfo(*childP)->wp_size;
   1445 	}
   1446 }
   1447 
   1448 /*
   1449  * Function:
   1450  *	ChangeAllGripCursors
   1451  *
   1452  * Parameters:
   1453  *	pw - paned widget
   1454  *
   1455  *	Description:
   1456  *	Changes all the grip cursors.
   1457  */
   1458 static void
   1459 ChangeAllGripCursors(PanedWidget pw)
   1460 {
   1461     Widget *childP;
   1462 
   1463     ForAllPanes(pw, childP) {
   1464 	Cursor cursor;
   1465 
   1466 	if ((cursor = pw->paned.grip_cursor) == None) {
   1467 	    if (IsVert(pw))
   1468 		cursor = pw->paned.v_grip_cursor;
   1469 	    else
   1470 		cursor = pw->paned.h_grip_cursor;
   1471 	}
   1472 
   1473 	if (HasGrip(*childP)) {
   1474 	    Arg arglist[1];
   1475 
   1476 	    XtSetArg(arglist[0], XtNcursor, cursor);
   1477 	    XtSetValues(PaneInfo(*childP)->grip, arglist, 1);
   1478 	}
   1479     }
   1480 }
   1481 
   1482 /*
   1483  * Function:
   1484  *	PushPaneStack
   1485  *
   1486  * Parameters:
   1487  *	pw   - paned widget
   1488  *	pane - pane that we are pushing
   1489  *
   1490  * Description:
   1491  *	Pushes a value onto the pane stack.
   1492  */
   1493 static void
   1494 PushPaneStack(PanedWidget pw, Pane pane)
   1495 {
   1496     PaneStack *stack = (PaneStack *)XtMalloc(sizeof(PaneStack));
   1497 
   1498     stack->next = pw->paned.stack;
   1499     stack->pane = pane;
   1500     stack->start_size = pane->size;
   1501 
   1502     pw->paned.stack = stack;
   1503 }
   1504 
   1505 /*
   1506  * Function:
   1507  *	GetPaneStack
   1508  *
   1509  * Parameters:
   1510  *	pw - paned widget
   1511  *	shrink	   - True if we want to shrink this pane, False otherwise
   1512  *	pane	   - pane that we are popping (return)
   1513  *	start_size - size that this pane started at (return)
   1514  *
   1515  * Description:
   1516  *	Gets the top value from the pane stack.
   1517  */
   1518 static void
   1519 GetPaneStack(PanedWidget pw, Bool shrink, Pane *pane, int *start_size)
   1520 {
   1521     if (pw->paned.stack == NULL) {
   1522 	*pane = NULL;
   1523 	return;
   1524     }
   1525 
   1526     *pane = pw->paned.stack->pane;
   1527     *start_size = pw->paned.stack->start_size;
   1528 
   1529     if (shrink != ((*pane)->size > *start_size))
   1530 	*pane = NULL;
   1531 }
   1532 
   1533 /*
   1534  * Function:
   1535  *	PopPaneStack
   1536  *
   1537  * Parameters:
   1538  *	pw - paned widget
   1539  *
   1540  * Description:
   1541  *	Pops the top item off the pane stack.
   1542  *
   1543  * Returns: True if this is not the last element on the stack
   1544  */
   1545 static Bool
   1546 PopPaneStack(PanedWidget pw)
   1547 {
   1548     PaneStack *stack = pw->paned.stack;
   1549 
   1550     if (stack == NULL)
   1551 	return (False);
   1552 
   1553     pw->paned.stack = stack->next;
   1554     XtFree((char *)stack);
   1555 
   1556     if (pw->paned.stack == NULL)
   1557 	return (False);
   1558 
   1559     return (True);
   1560 }
   1561 
   1562 /*
   1563  * Function:
   1564  *	ClearPaneStack
   1565  *
   1566  * Parameters:
   1567  *	pw - paned widget
   1568  *
   1569  * Description:
   1570  *	Removes all entries from the pane stack.
   1571  */
   1572 static void
   1573 ClearPaneStack(PanedWidget pw)
   1574 {
   1575     while(PopPaneStack(pw))
   1576 	;
   1577 }
   1578 
   1579 static void
   1580 XawPanedClassInitialize(void)
   1581 {
   1582     XawInitializeWidgetSet();
   1583     XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
   1584 		   NULL, 0);
   1585     XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString,
   1586 		       NULL, 0, XtCacheNone, NULL);
   1587 }
   1588 
   1589 /* The Geometry Manager only allows changes after Realize if
   1590  * allow_resize is True in the constraints record.
   1591  *
   1592  * For vertically paned widgets:
   1593  *
   1594  * It only allows height changes, but offers the requested height
   1595  * as a compromise if both width and height changes were requested.
   1596  *
   1597  * For horizontal widgets the converse is true.
   1598  * As all good Geometry Managers should, we will return No if the
   1599  * request will have no effect; i.e. when the requestor is already
   1600  * of the desired geometry.
   1601  */
   1602 static XtGeometryResult
   1603 XawPanedGeometryManager(Widget w, XtWidgetGeometry *request,
   1604 			XtWidgetGeometry *reply)
   1605 {
   1606     PanedWidget pw = (PanedWidget)XtParent(w);
   1607     XtGeometryMask mask = request->request_mode;
   1608     Dimension old_size, old_wpsize, old_paned_size;
   1609     Pane pane = PaneInfo(w);
   1610     Boolean vert = IsVert(pw);
   1611     Dimension on_size, off_size;
   1612     XtGeometryResult result;
   1613     Boolean almost = False;
   1614 
   1615     /*
   1616      * If any of the following is true, disallow the geometry change
   1617      *
   1618      * o The paned widget is realized and allow_resize is false for the pane
   1619      * o The child did not ask to change the on_size
   1620      * o The request is not a width or height request
   1621      * o The requested size is the same as the current size
   1622      */
   1623 
   1624     if ((XtIsRealized((Widget)pw) && !pane->allow_resize)
   1625 	|| !(mask & (vert ? CWHeight : CWWidth))
   1626 	|| (mask & (XtGeometryMask)(~(CWWidth | CWHeight)))
   1627 	|| GetRequestInfo(request, vert) ==  PaneSize(w, vert))
   1628 	return (XtGeometryNo);
   1629 
   1630     old_paned_size = PaneSize((Widget)pw, vert);
   1631     old_wpsize = pane->wp_size;
   1632     old_size = (Dimension)pane->size;
   1633 
   1634     pane->wp_size = (Dimension)(pane->size = GetRequestInfo(request, vert));
   1635 
   1636     AdjustPanedSize(pw, PaneSize((Widget)pw, !vert), &result, &on_size,
   1637 		    &off_size);
   1638 
   1639     /*
   1640      * Fool the Refigure Locations proc to thinking that we are
   1641      * a different on_size
   1642      */
   1643 
   1644     if (result != XtGeometryNo) {
   1645 	if (vert)
   1646 	    XtHeight(pw) = on_size;
   1647 	else
   1648 	    XtWidth(pw) = on_size;
   1649     }
   1650 
   1651     RefigureLocations(pw, PaneIndex(w), AnyPane);
   1652 
   1653     /*
   1654      * Set up reply struct and reset core on_size
   1655      */
   1656     if (vert) {
   1657 	XtHeight(pw) = old_paned_size;
   1658 	reply->height = (Dimension) pane->size;
   1659 	reply->width = off_size;
   1660     }
   1661     else {
   1662 	XtWidth(pw) = old_paned_size;
   1663 	reply->height = off_size;
   1664 	reply->width = (Dimension) pane->size;
   1665     }
   1666 
   1667     /*
   1668      * IF either of the following is true
   1669      *
   1670      * o There was a "off_size" request and the new "off_size" is different
   1671      *   from that requested
   1672      * o There was no "off_size" request and the new "off_size" is different
   1673      *
   1674      * o The "on_size" we will allow is different from that requested
   1675      *
   1676      * THEN: set almost
   1677      */
   1678     if (!((vert ? CWWidth : CWHeight) & mask)) {
   1679 	if (vert)
   1680 	    request->width = XtWidth(w);
   1681 	else
   1682 	    request->height = XtHeight(w);
   1683     }
   1684 
   1685     almost = GetRequestInfo(request, !vert) != GetRequestInfo(reply, !vert);
   1686     almost = (Boolean)(almost | (GetRequestInfo(request, vert) != GetRequestInfo(reply, vert)));
   1687 
   1688     if ((mask & XtCWQueryOnly) || almost) {
   1689 	pane->wp_size = old_wpsize;
   1690 	pane->size = old_size;
   1691 	RefigureLocations(pw, PaneIndex(w), AnyPane);
   1692 	reply->request_mode = CWWidth | CWHeight;
   1693 	if (almost)
   1694 	    return (XtGeometryAlmost);
   1695     }
   1696     else {
   1697 	AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), NULL, NULL, NULL);
   1698 	CommitNewLocations(pw);		/* layout already refigured */
   1699     }
   1700 
   1701     return (XtGeometryDone);
   1702 }
   1703 
   1704 /*ARGSUSED*/
   1705 static void
   1706 XawPanedInitialize(Widget request _X_UNUSED, Widget cnew,
   1707 		   ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
   1708 {
   1709     PanedWidget pw = (PanedWidget)cnew;
   1710 
   1711     GetGCs((Widget)pw);
   1712 
   1713     pw->paned.recursively_called = False;
   1714     pw->paned.stack = NULL;
   1715     pw->paned.resize_children_to_pref = True;
   1716     pw->paned.num_panes = 0;
   1717 }
   1718 
   1719 static void
   1720 XawPanedRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
   1721 {
   1722     PanedWidget pw = (PanedWidget)w;
   1723     Widget *childP;
   1724 
   1725     if ((attributes->cursor = pw->paned.cursor) != None)
   1726 	*valueMask |= CWCursor;
   1727 
   1728     (*SuperClass->core_class.realize)(w, valueMask, attributes);
   1729 
   1730     /*
   1731      * Before we commit the new locations we need to realize all the panes and
   1732      * their grips
   1733      */
   1734     ForAllPanes(pw, childP) {
   1735 	XtRealizeWidget(*childP);
   1736 	if (HasGrip(*childP))
   1737 	    XtRealizeWidget(PaneInfo(*childP)->grip);
   1738     }
   1739 
   1740     RefigureLocationsAndCommit(w);
   1741     pw->paned.resize_children_to_pref = False;
   1742 }
   1743 
   1744 static void
   1745 XawPanedDestroy(Widget w)
   1746 {
   1747     ReleaseGCs(w);
   1748 }
   1749 
   1750 static void
   1751 ReleaseGCs(Widget w)
   1752 {
   1753     PanedWidget pw = (PanedWidget)w;
   1754 
   1755     XtReleaseGC(w, pw->paned.normgc);
   1756     XtReleaseGC(w, pw->paned.invgc);
   1757     XtReleaseGC(w, pw->paned.flipgc);
   1758 }
   1759 
   1760 static void
   1761 XawPanedInsertChild(Widget w)
   1762 {
   1763     Pane pane = PaneInfo(w);
   1764 
   1765     /* insert the child widget in the composite children list with the
   1766        superclass insert_child routine
   1767      */
   1768     (*SuperClass->composite_class.insert_child)(w);
   1769 
   1770     if (!IsPane(w))
   1771 	return;
   1772 
   1773     if (pane->show_grip == True) {
   1774 	CreateGrip(w);
   1775 	if (pane->min == PANED_GRIP_SIZE)
   1776 	    pane->min = PaneSize(pane->grip, IsVert((PanedWidget)XtParent(w)));
   1777     }
   1778     else {
   1779 	if (pane->min == PANED_GRIP_SIZE)
   1780 	    pane->min = 1;
   1781 	pane->grip = NULL;
   1782     }
   1783 
   1784     pane->size = 0;
   1785     pane->paned_adjusted_me = False;
   1786 }
   1787 
   1788 static void
   1789 XawPanedDeleteChild(Widget w)
   1790 {
   1791     /* remove the subwidget info and destroy the grip */
   1792     if (IsPane(w) && HasGrip(w))
   1793 	XtDestroyWidget(PaneInfo(w)->grip);
   1794 
   1795     /* delete the child widget in the composite children list with the
   1796        superclass delete_child routine
   1797      */
   1798     (*SuperClass->composite_class.delete_child)(w);
   1799 }
   1800 
   1801 static void
   1802 XawPanedChangeManaged(Widget w)
   1803 {
   1804     PanedWidget pw = (PanedWidget)w;
   1805     Boolean vert = IsVert(pw);
   1806     Dimension size;
   1807     Widget *childP;
   1808 
   1809     if (pw->paned.recursively_called++)
   1810 	return;
   1811 
   1812     /*
   1813      * If the size is zero then set it to the size of the widest or tallest pane
   1814      */
   1815 
   1816     if ((size = PaneSize((Widget)pw, !vert)) == 0) {
   1817 	size = 1;
   1818 	ForAllChildren(pw, childP)
   1819 	if (XtIsManaged(*childP) && (PaneSize(*childP, !vert) > size))
   1820 	    size = PaneSize(*childP, !vert);
   1821     }
   1822 
   1823     ManageAndUnmanageGrips(pw);
   1824     pw->paned.recursively_called = False;
   1825     ResortChildren(pw);
   1826 
   1827     pw->paned.num_panes = 0;
   1828     ForAllChildren(pw, childP)
   1829 	if (IsPane(*childP)) {
   1830 	    if (XtIsManaged(*childP)) {
   1831 		Pane pane = PaneInfo(*childP);
   1832 
   1833 		if (HasGrip(*childP))
   1834 		    PaneInfo(pane->grip)->position = pw->paned.num_panes;
   1835 		pane->position = pw->paned.num_panes; /* TEMPORARY -CDP 3/89 */
   1836 		pw->paned.num_panes++;
   1837 	    }
   1838 	    else
   1839 		break;		 /* This list is already sorted */
   1840 	}
   1841 
   1842     SetChildrenPrefSizes((PanedWidget) w, size);
   1843 
   1844     /*
   1845      * ForAllPanes can now be used
   1846      */
   1847     if (PaneSize((Widget) pw, vert) == 0)
   1848 	AdjustPanedSize(pw, size, NULL, NULL, NULL);
   1849 
   1850     if (XtIsRealized((Widget)pw))
   1851 	RefigureLocationsAndCommit((Widget)pw);
   1852 }
   1853 
   1854 static void
   1855 XawPanedResize(Widget w)
   1856 {
   1857     SetChildrenPrefSizes((PanedWidget)w,
   1858 			 PaneSize(w, !IsVert((PanedWidget)w)));
   1859     RefigureLocationsAndCommit(w);
   1860 }
   1861 
   1862 /*ARGSUSED*/
   1863 static void
   1864 XawPanedRedisplay(Widget w, XEvent *event _X_UNUSED, Region region _X_UNUSED)
   1865 {
   1866     DrawInternalBorders((PanedWidget)w);
   1867 }
   1868 
   1869 /*ARGSUSED*/
   1870 static Boolean
   1871 XawPanedSetValues(Widget old, Widget request _X_UNUSED, Widget cnew,
   1872 		  ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
   1873 {
   1874     PanedWidget old_pw = (PanedWidget)old;
   1875     PanedWidget new_pw = (PanedWidget)cnew;
   1876     Boolean redisplay = False;
   1877 
   1878     if ((old_pw->paned.cursor != new_pw->paned.cursor) && XtIsRealized(cnew))
   1879 	XDefineCursor(XtDisplay(cnew), XtWindow(cnew), new_pw->paned.cursor);
   1880 
   1881     if (old_pw->paned.internal_bp != new_pw->paned.internal_bp ||
   1882 	old_pw->core.background_pixel != new_pw->core.background_pixel) {
   1883 	ReleaseGCs(old);
   1884 	GetGCs(cnew);
   1885 	redisplay = True;
   1886     }
   1887 
   1888     if (old_pw->paned.grip_cursor != new_pw->paned.grip_cursor ||
   1889 	old_pw->paned.v_grip_cursor != new_pw->paned.v_grip_cursor ||
   1890 	old_pw->paned.h_grip_cursor != new_pw->paned.h_grip_cursor)
   1891 	ChangeAllGripCursors(new_pw);
   1892 
   1893     if (IsVert(old_pw) != IsVert(new_pw)) {
   1894 	/*
   1895 	 * We are fooling the paned widget into thinking that is needs to
   1896 	 * fully refigure everything, which is what we want
   1897 	 */
   1898 	if (IsVert(new_pw))
   1899 	    XtWidth(new_pw) = 0;
   1900 	else
   1901 	    XtHeight(new_pw) = 0;
   1902 
   1903 	new_pw->paned.resize_children_to_pref = True;
   1904 	XawPanedChangeManaged(cnew); /* Seems weird, but does the right thing */
   1905 	new_pw->paned.resize_children_to_pref = False;
   1906 	if (new_pw->paned.grip_cursor == None)
   1907 	    ChangeAllGripCursors(new_pw);
   1908 	return (True);
   1909     }
   1910 
   1911     if (old_pw->paned.internal_bw != new_pw->paned.internal_bw) {
   1912 	AdjustPanedSize(new_pw, PaneSize(cnew, !IsVert(old_pw)),
   1913 		        NULL, NULL, NULL);
   1914 	RefigureLocationsAndCommit(cnew);
   1915 	return (True);		/* We have done a full configuration, return */
   1916     }
   1917 
   1918     if (old_pw->paned.grip_indent != new_pw->paned.grip_indent &&
   1919 	XtIsRealized(cnew)) {
   1920 	CommitNewLocations(new_pw);
   1921 	redisplay = True;
   1922     }
   1923 
   1924     return (redisplay);
   1925 }
   1926 
   1927 /*ARGSUSED*/
   1928 static Boolean
   1929 XawPanedPaneSetValues(Widget old, Widget request _X_UNUSED, Widget cnew,
   1930 		      ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
   1931 {
   1932     Pane old_pane = PaneInfo(old);
   1933     Pane new_pane = PaneInfo(cnew);
   1934     Boolean redisplay = False;
   1935 
   1936     /* Check for new min and max */
   1937     if (old_pane->min != new_pane->min || old_pane->max != new_pane->max)
   1938 	XawPanedSetMinMax(cnew, (int)new_pane->min, (int)new_pane->max);
   1939 
   1940     /* Check for change in XtNshowGrip */
   1941     if (old_pane->show_grip != new_pane->show_grip) {
   1942 	if (new_pane->show_grip == True) {
   1943 	    CreateGrip(cnew);
   1944 	    if (XtIsRealized(XtParent(cnew))) {
   1945 		if (XtIsManaged(cnew))	/* if paned is unrealized this will
   1946 					   happen automatically at realize time
   1947 					 */
   1948 		    XtManageChild(PaneInfo(cnew)->grip);	/* manage the grip */
   1949 		XtRealizeWidget(PaneInfo(cnew)->grip); /* realize the grip */
   1950 		CommitNewLocations((PanedWidget)XtParent(cnew));
   1951 	    }
   1952 	}
   1953 	else if (HasGrip(old)) {
   1954 	    XtDestroyWidget(old_pane->grip);
   1955 	    new_pane->grip = NULL;
   1956 	    redisplay = True;
   1957 	}
   1958     }
   1959 
   1960     return (redisplay);
   1961 }
   1962 
   1963 /*
   1964  * Public routines
   1965  */
   1966 /*
   1967  * Function:
   1968  *	XawPanedSetMinMax
   1969  *
   1970  * Parameters:
   1971  *	widget - widget that is a child of the Paned widget
   1972  *	min    - new min and max size for the pane
   1973  *	max    - ""
   1974  *
   1975  * Description:
   1976  *	Sets the min and max size for a pane.
   1977  */
   1978 void
   1979 XawPanedSetMinMax(Widget widget, int min, int max)
   1980 {
   1981     Pane pane = PaneInfo(widget);
   1982 
   1983     pane->min = (Dimension) min;
   1984     pane->max = (Dimension) max;
   1985     RefigureLocationsAndCommit(widget->core.parent);
   1986 }
   1987 
   1988 /*
   1989  * Function:
   1990  *	XawPanedGetMinMax
   1991  *
   1992  * Parameters:
   1993  *	widget - widget that is a child of the Paned widget
   1994  *	min    - current min and max size for the pane (return)
   1995  *	max    - ""
   1996  *
   1997  * Description:
   1998  *	Gets the min and max size for a pane.
   1999  */
   2000 void
   2001 XawPanedGetMinMax(Widget widget, int *min, int *max)
   2002 {
   2003     Pane pane = PaneInfo(widget);
   2004 
   2005     *min = pane->min;
   2006     *max = pane->max;
   2007 }
   2008 
   2009 /*
   2010  * Function:
   2011  *	XawPanedSetRefigureMode
   2012  *
   2013  * Parameters:
   2014  *	w    - paned widget
   2015  *	mode - if False then inhibit refigure
   2016  *
   2017  * Description:
   2018  *	Allows a flag to be set the will inhibit
   2019  *		   the paned widgets relayout routine.
   2020  */
   2021 void
   2022 XawPanedSetRefigureMode(Widget w,
   2023 #if NeedWidePrototypes
   2024 	int mode
   2025 #else
   2026 	Boolean mode
   2027 #endif
   2028 )
   2029 {
   2030     ((PanedWidget)w)->paned.refiguremode = mode;
   2031     RefigureLocationsAndCommit(w);
   2032 }
   2033 
   2034 /*
   2035  * Function:
   2036  *	XawPanedGetNumSub
   2037  *
   2038  * Parameters:
   2039  *	w - paned widget
   2040  *
   2041  * Description:
   2042  *	Returns the number of panes in the paned widget.
   2043  * Returns:
   2044  *	the number of panes in the paned widget
   2045  */
   2046 int
   2047 XawPanedGetNumSub(Widget w)
   2048 {
   2049     return (((PanedWidget)w)->paned.num_panes);
   2050 }
   2051 
   2052 /*
   2053  * Function:
   2054  *	XawPanedAllowResize
   2055  *
   2056  * Parameters:
   2057  *	widget - child of the paned widget
   2058  *
   2059  * Description:
   2060  *	  Allows a flag to be set that determines if the paned
   2061  *	widget will allow geometry requests from this child.
   2062  */
   2063 void
   2064 XawPanedAllowResize(Widget widget,
   2065 #if NeedWidePrototypes
   2066 	int allow_resize
   2067 #else
   2068 	Boolean allow_resize
   2069 #endif
   2070 )
   2071 {
   2072     PaneInfo(widget)->allow_resize = allow_resize;
   2073 }
   2074