home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xaw / Paned.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-21  |  53.2 KB  |  1,906 lines

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