Paned.c revision 775e7de9
17a84e134Smrg/* $Xorg: Paned.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $ */
27a84e134Smrg
37a84e134Smrg/***********************************************************
47a84e134Smrg
57a84e134SmrgCopyright 1987, 1988, 1994, 1998  The Open Group
67a84e134Smrg
77a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its
87a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that
97a84e134Smrgthe above copyright notice appear in all copies and that both that
107a84e134Smrgcopyright notice and this permission notice appear in supporting
117a84e134Smrgdocumentation.
127a84e134Smrg
137a84e134SmrgThe above copyright notice and this permission notice shall be included in
147a84e134Smrgall copies or substantial portions of the Software.
157a84e134Smrg
167a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
197a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
207a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
217a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
227a84e134Smrg
237a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be
247a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings
257a84e134Smrgin this Software without prior written authorization from The Open Group.
267a84e134Smrg
277a84e134Smrg
287a84e134SmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
297a84e134Smrg
307a84e134Smrg                        All Rights Reserved
317a84e134Smrg
327a84e134SmrgPermission to use, copy, modify, and distribute this software and its
337a84e134Smrgdocumentation for any purpose and without fee is hereby granted,
347a84e134Smrgprovided that the above copyright notice appear in all copies and that
357a84e134Smrgboth that copyright notice and this permission notice appear in
367a84e134Smrgsupporting documentation, and that the name of Digital not be
377a84e134Smrgused in advertising or publicity pertaining to distribution of the
387a84e134Smrgsoftware without specific, written prior permission.
397a84e134Smrg
407a84e134SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
417a84e134SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
427a84e134SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
437a84e134SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
447a84e134SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
457a84e134SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
467a84e134SmrgSOFTWARE.
477a84e134Smrg
487a84e134Smrg******************************************************************/
497a84e134Smrg/* $XFree86: xc/lib/Xaw/Paned.c,v 1.11 2001/08/23 00:03:19 dawes Exp $ */
507a84e134Smrg
517a84e134Smrg/*
527a84e134Smrg * Updated and significantly modified from the Athena VPaned Widget.
537a84e134Smrg *
547a84e134Smrg * Date:    March 1, 1989
557a84e134Smrg *
567a84e134Smrg * By:      Chris D. Peterson
577a84e134Smrg *          MIT X Consortium
587a84e134Smrg *          kit@expo.lcs.mit.edu
597a84e134Smrg */
607a84e134Smrg
617a84e134Smrg#ifdef HAVE_CONFIG_H
627a84e134Smrg#include <config.h>
637a84e134Smrg#endif
647a84e134Smrg#include <X11/IntrinsicP.h>
657a84e134Smrg#include <X11/cursorfont.h>
667a84e134Smrg#include <X11/StringDefs.h>
677a84e134Smrg#include <X11/Xmu/CharSet.h>
687a84e134Smrg#include <X11/Xmu/Converters.h>
697a84e134Smrg#include <X11/Xmu/Misc.h>
707a84e134Smrg#include <X11/Xmu/SysUtil.h>
717a84e134Smrg#include <X11/Xaw/Grip.h>
727a84e134Smrg#include <X11/Xaw/PanedP.h>
737a84e134Smrg#include <X11/Xaw/XawImP.h>
747a84e134Smrg#include <X11/Xaw/XawInit.h>
757a84e134Smrg#include "Private.h"
767a84e134Smrg
777a84e134Smrgtypedef enum {
787a84e134Smrg  UpLeftPane = 'U',
797a84e134Smrg  LowRightPane = 'L',
807a84e134Smrg  ThisBorderOnly = 'T',
817a84e134Smrg  AnyPane = 'A'
827a84e134Smrg} Direction;
837a84e134Smrg
847a84e134Smrg#define NO_INDEX -100
857a84e134Smrg#define IS_GRIP  NULL
867a84e134Smrg
877a84e134Smrg#define PaneInfo(w)	((Pane)(w)->core.constraints)
887a84e134Smrg#define HasGrip(w)	(PaneInfo(w)->grip != NULL)
897a84e134Smrg#define IsPane(w)	((w)->core.widget_class != gripWidgetClass)
907a84e134Smrg#define PaneIndex(w)	(PaneInfo(w)->position)
917a84e134Smrg#define IsVert(w)	((w)->paned.orientation == XtorientVertical)
927a84e134Smrg
937a84e134Smrg#define ForAllPanes(pw, childP) \
947a84e134Smrgfor ((childP) = (pw)->composite.children;				\
957a84e134Smrg     (childP) < (pw)->composite.children + (pw)->paned.num_panes;	\
967a84e134Smrg     (childP)++)
977a84e134Smrg
987a84e134Smrg#define ForAllChildren(pw, childP) \
997a84e134Smrgfor ((childP) = (pw)->composite.children;				 \
1007a84e134Smrg     (childP) < (pw)->composite.children + (pw)->composite.num_children; \
1017a84e134Smrg     (childP)++)
1027a84e134Smrg
1037a84e134Smrg#define PaneSize(paned, vertical)			\
1047a84e134Smrg     ((vertical) ? XtHeight(paned) : XtWidth(paned))
1057a84e134Smrg
1067a84e134Smrg#define GetRequestInfo(geo, vertical)			\
1077a84e134Smrg     ((vertical) ? (geo)->height : (geo)->width)
1087a84e134Smrg
1097a84e134Smrg#define SatisfiesRule1(pane, shrink)			\
1107a84e134Smrg     (((shrink) && ((pane)->size != (pane)->min))	\
1117a84e134Smrg      || (!(shrink) && ((pane)->size != (pane)->max)))
1127a84e134Smrg
1137a84e134Smrg#define SatisfiesRule2(pane)					\
1147a84e134Smrg     (!(pane)->skip_adjust || (pane)->paned_adjusted_me)
1157a84e134Smrg
1167a84e134Smrg#define SatisfiesRule3(pane, shrink)					\
1177a84e134Smrg     ((pane)->paned_adjusted_me						\
1187a84e134Smrg      && (((shrink) && ((int)(pane)->wp_size <= (pane)->size))		\
1197a84e134Smrg	  || (!(shrink) && ((int)(pane)->wp_size >= (pane)->size))))
1207a84e134Smrg
1217a84e134Smrg
1227a84e134Smrg/*
1237a84e134Smrg * Class Methods
1247a84e134Smrg */
1257a84e134Smrgstatic void XawPanedClassInitialize(void);
1267a84e134Smrgstatic void XawPanedChangeManaged(Widget);
1277a84e134Smrgstatic void XawPanedDeleteChild(Widget);
1287a84e134Smrgstatic void XawPanedDestroy(Widget);
1297a84e134Smrgstatic XtGeometryResult XawPanedGeometryManager(Widget, XtWidgetGeometry*,
1307a84e134Smrg						XtWidgetGeometry*);
1317a84e134Smrgstatic void XawPanedInitialize(Widget, Widget, ArgList, Cardinal*);
1327a84e134Smrgstatic void XawPanedInsertChild(Widget);
1337a84e134Smrgstatic Boolean XawPanedPaneSetValues(Widget, Widget, Widget,
1347a84e134Smrg				     ArgList, Cardinal*);
1357a84e134Smrgstatic void XawPanedRealize(Widget, Mask*, XSetWindowAttributes*);
1367a84e134Smrgstatic void XawPanedRedisplay(Widget, XEvent*, Region);
1377a84e134Smrgstatic void XawPanedResize(Widget);
1387a84e134Smrgstatic Boolean XawPanedSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
1397a84e134Smrg
1407a84e134Smrg/*
1417a84e134Smrg * Prototypes
1427a84e134Smrg */
1437a84e134Smrgstatic void _DrawInternalBorders(PanedWidget, GC);
1447a84e134Smrgstatic void _DrawRect(PanedWidget, GC, int, int, unsigned int, unsigned int);
1457a84e134Smrgstatic void _DrawTrackLines(PanedWidget, Bool);
1467a84e134Smrgstatic void AdjustPanedSize(PanedWidget, unsigned int, XtGeometryResult*,
1477a84e134Smrg			    Dimension*, Dimension*);
1487a84e134Smrgstatic void ChangeAllGripCursors(PanedWidget);
1497a84e134Smrgstatic Pane ChoosePaneToResize(PanedWidget, int, Direction, Bool);
1507a84e134Smrgstatic void ClearPaneStack(PanedWidget);
1517a84e134Smrgstatic void CommitGripAdjustment(PanedWidget);
1527a84e134Smrgstatic void CreateGrip(Widget);
1537a84e134Smrgstatic int GetEventLocation(PanedWidget, XEvent*);
1547a84e134Smrgstatic void GetGCs(Widget);
1557a84e134Smrgstatic void GetPaneStack(PanedWidget, Bool, Pane*, int*);
1567a84e134Smrgstatic void HandleGrip(Widget, XtPointer, XtPointer);
1577a84e134Smrgstatic void LoopAndRefigureChildren(PanedWidget, int, Direction, int*);
1587a84e134Smrgstatic void ManageAndUnmanageGrips(PanedWidget);
1597a84e134Smrgstatic void MoveGripAdjustment(PanedWidget, Widget, Direction, int);
1607a84e134Smrgstatic Bool PopPaneStack(PanedWidget);
1617a84e134Smrgstatic void PushPaneStack(PanedWidget, Pane);
1627a84e134Smrgstatic void RefigureLocations(PanedWidget, int, Direction);
1637a84e134Smrgstatic void RefigureLocationsAndCommit(Widget);
1647a84e134Smrgstatic void ReleaseGCs(Widget);
1657a84e134Smrgstatic void ResortChildren(PanedWidget);
1667a84e134Smrgstatic void SetChildrenPrefSizes(PanedWidget, unsigned int);
1677a84e134Smrgstatic void StartGripAdjustment(PanedWidget, Widget, Direction);
1687a84e134Smrg
1697a84e134Smrg/*
1707a84e134Smrg * Initialization
1717a84e134Smrg */
1727a84e134Smrgstatic char defGripTranslations[] =
1737a84e134Smrg"<Btn1Down>:"		"GripAction(Start,UpLeftPane)\n"
1747a84e134Smrg"<Btn2Down>:"		"GripAction(Start,ThisBorderOnly)\n"
1757a84e134Smrg"<Btn3Down>:"		"GripAction(Start,LowRightPane)\n"
1767a84e134Smrg"<Btn1Motion>:"		"GripAction(Move,UpLeft)\n"
1777a84e134Smrg"<Btn2Motion>:"		"GripAction(Move,ThisBorder)\n"
1787a84e134Smrg"<Btn3Motion>:"		"GripAction(Move,LowRight)\n"
1797a84e134Smrg"Any<BtnUp>:"		"GripAction(Commit)\n"
1807a84e134Smrg;
1817a84e134Smrg
1827a84e134Smrg#define offset(field) XtOffsetOf(PanedRec, paned.field)
1837a84e134Smrgstatic XtResource resources[] = {
1847a84e134Smrg  {
1857a84e134Smrg    XtNinternalBorderColor,
1867a84e134Smrg    XtCBorderColor,
1877a84e134Smrg    XtRPixel,
1887a84e134Smrg    sizeof(Pixel),
1897a84e134Smrg    offset(internal_bp),
1907a84e134Smrg    XtRString,
1917a84e134Smrg    (XtPointer)XtDefaultForeground
1927a84e134Smrg  },
1937a84e134Smrg  {
1947a84e134Smrg    XtNinternalBorderWidth,
1957a84e134Smrg    XtCBorderWidth,
1967a84e134Smrg    XtRDimension,
1977a84e134Smrg    sizeof(Dimension),
1987a84e134Smrg    offset(internal_bw),
1997a84e134Smrg    XtRImmediate,
2007a84e134Smrg    (XtPointer)1
2017a84e134Smrg  },
2027a84e134Smrg  {
2037a84e134Smrg    XtNgripIndent,
2047a84e134Smrg    XtCGripIndent,
2057a84e134Smrg    XtRPosition,
2067a84e134Smrg    sizeof(Position),
2077a84e134Smrg    offset(grip_indent),
2087a84e134Smrg    XtRImmediate,
2097a84e134Smrg    (XtPointer)10
2107a84e134Smrg  },
2117a84e134Smrg  {
2127a84e134Smrg    XtNrefigureMode,
2137a84e134Smrg    XtCBoolean,
2147a84e134Smrg    XtRBoolean,
2157a84e134Smrg    sizeof(Boolean),
2167a84e134Smrg    offset(refiguremode),
2177a84e134Smrg    XtRImmediate,
2187a84e134Smrg    (XtPointer)True
2197a84e134Smrg  },
2207a84e134Smrg  {
2217a84e134Smrg    XtNgripTranslations,
2227a84e134Smrg    XtCTranslations,
2237a84e134Smrg    XtRTranslationTable,
2247a84e134Smrg    sizeof(XtTranslations),
2257a84e134Smrg    offset(grip_translations),
2267a84e134Smrg    XtRString,
2277a84e134Smrg    (XtPointer)defGripTranslations
2287a84e134Smrg  },
2297a84e134Smrg  {
2307a84e134Smrg    XtNorientation,
2317a84e134Smrg    XtCOrientation,
2327a84e134Smrg    XtROrientation,
2337a84e134Smrg    sizeof(XtOrientation),
2347a84e134Smrg    offset(orientation),
2357a84e134Smrg    XtRImmediate,
2367a84e134Smrg    (XtPointer)XtorientVertical
2377a84e134Smrg  },
2387a84e134Smrg  {
2397a84e134Smrg    XtNcursor,
2407a84e134Smrg    XtCCursor,
2417a84e134Smrg    XtRCursor,
2427a84e134Smrg    sizeof(Cursor),
2437a84e134Smrg    offset(cursor),
2447a84e134Smrg    XtRImmediate,
245775e7de9Smrg    NULL
2467a84e134Smrg  },
2477a84e134Smrg  {
2487a84e134Smrg    XtNgripCursor,
2497a84e134Smrg    XtCCursor,
2507a84e134Smrg    XtRCursor,
2517a84e134Smrg    sizeof(Cursor),
2527a84e134Smrg    offset(grip_cursor),
2537a84e134Smrg    XtRImmediate,
254775e7de9Smrg    NULL
2557a84e134Smrg  },
2567a84e134Smrg  {
2577a84e134Smrg    XtNverticalGripCursor,
2587a84e134Smrg    XtCCursor,
2597a84e134Smrg    XtRCursor,
2607a84e134Smrg    sizeof(Cursor),
2617a84e134Smrg    offset(v_grip_cursor),
2627a84e134Smrg    XtRString,
2637a84e134Smrg    "sb_v_double_arrow"
2647a84e134Smrg  },
2657a84e134Smrg  {
2667a84e134Smrg    XtNhorizontalGripCursor,
2677a84e134Smrg    XtCCursor,
2687a84e134Smrg    XtRCursor,
2697a84e134Smrg    sizeof(Cursor),
2707a84e134Smrg    offset(h_grip_cursor),
2717a84e134Smrg    XtRString,
2727a84e134Smrg    "sb_h_double_arrow"
2737a84e134Smrg  },
2747a84e134Smrg  {
2757a84e134Smrg    XtNbetweenCursor,
2767a84e134Smrg    XtCCursor,
2777a84e134Smrg    XtRCursor,
2787a84e134Smrg    sizeof(Cursor),
2797a84e134Smrg    offset(adjust_this_cursor),
2807a84e134Smrg    XtRString,
281775e7de9Smrg    NULL
2827a84e134Smrg  },
2837a84e134Smrg  {
2847a84e134Smrg    XtNverticalBetweenCursor,
2857a84e134Smrg    XtCCursor,
2867a84e134Smrg    XtRCursor,
2877a84e134Smrg    sizeof(Cursor),
2887a84e134Smrg    offset(v_adjust_this_cursor),
2897a84e134Smrg    XtRString,
2907a84e134Smrg    "sb_left_arrow"
2917a84e134Smrg  },
2927a84e134Smrg  {
2937a84e134Smrg    XtNhorizontalBetweenCursor,
2947a84e134Smrg    XtCCursor,
2957a84e134Smrg    XtRCursor,
2967a84e134Smrg    sizeof(Cursor),
2977a84e134Smrg    offset(h_adjust_this_cursor),
2987a84e134Smrg    XtRString,
2997a84e134Smrg    "sb_up_arrow"
3007a84e134Smrg  },
3017a84e134Smrg  {
3027a84e134Smrg    XtNupperCursor,
3037a84e134Smrg    XtCCursor,
3047a84e134Smrg    XtRCursor,
3057a84e134Smrg    sizeof(Cursor),
3067a84e134Smrg    offset(adjust_upper_cursor),
3077a84e134Smrg    XtRString,
3087a84e134Smrg    "sb_up_arrow"
3097a84e134Smrg  },
3107a84e134Smrg  {
3117a84e134Smrg    XtNlowerCursor,
3127a84e134Smrg    XtCCursor,
3137a84e134Smrg    XtRCursor,
3147a84e134Smrg    sizeof(Cursor),
3157a84e134Smrg    offset(adjust_lower_cursor),
3167a84e134Smrg    XtRString,
3177a84e134Smrg    "sb_down_arrow"
3187a84e134Smrg  },
3197a84e134Smrg  {
3207a84e134Smrg    XtNleftCursor,
3217a84e134Smrg    XtCCursor,
3227a84e134Smrg    XtRCursor,
3237a84e134Smrg    sizeof(Cursor),
3247a84e134Smrg    offset(adjust_left_cursor),
3257a84e134Smrg    XtRString,
3267a84e134Smrg    "sb_left_arrow"
3277a84e134Smrg  },
3287a84e134Smrg  {
3297a84e134Smrg    XtNrightCursor,
3307a84e134Smrg    XtCCursor,
3317a84e134Smrg    XtRCursor,
3327a84e134Smrg    sizeof(Cursor),
3337a84e134Smrg    offset(adjust_right_cursor),
3347a84e134Smrg    XtRString,
3357a84e134Smrg    "sb_right_arrow"
3367a84e134Smrg  },
3377a84e134Smrg};
3387a84e134Smrg#undef offset
3397a84e134Smrg
3407a84e134Smrg#define offset(field) XtOffsetOf(PanedConstraintsRec, paned.field)
3417a84e134Smrgstatic XtResource subresources[] = {
3427a84e134Smrg  {
3437a84e134Smrg    XtNallowResize,
3447a84e134Smrg    XtCBoolean,
3457a84e134Smrg    XtRBoolean,
3467a84e134Smrg    sizeof(Boolean),
3477a84e134Smrg    offset(allow_resize),
3487a84e134Smrg    XtRImmediate,
3497a84e134Smrg    (XtPointer)False
3507a84e134Smrg  },
3517a84e134Smrg  {
3527a84e134Smrg    XtNposition,
3537a84e134Smrg    XtCPosition,
3547a84e134Smrg    XtRInt,
3557a84e134Smrg    sizeof(int),
3567a84e134Smrg    offset(position),
3577a84e134Smrg    XtRImmediate,
3587a84e134Smrg    (XtPointer)0
3597a84e134Smrg  },
3607a84e134Smrg  {
3617a84e134Smrg    XtNmin,
3627a84e134Smrg    XtCMin,
3637a84e134Smrg    XtRDimension,
3647a84e134Smrg    sizeof(Dimension),
3657a84e134Smrg    offset(min),
3667a84e134Smrg    XtRImmediate,
3677a84e134Smrg    (XtPointer)PANED_GRIP_SIZE
3687a84e134Smrg  },
3697a84e134Smrg  {
3707a84e134Smrg    XtNmax,
3717a84e134Smrg    XtCMax,
3727a84e134Smrg    XtRDimension,
3737a84e134Smrg    sizeof(Dimension),
3747a84e134Smrg    offset(max),
3757a84e134Smrg    XtRImmediate,
3767a84e134Smrg    (XtPointer)~0
3777a84e134Smrg  },
3787a84e134Smrg  {
3797a84e134Smrg    XtNpreferredPaneSize,
3807a84e134Smrg    XtCPreferredPaneSize,
3817a84e134Smrg    XtRDimension,
3827a84e134Smrg    sizeof(Dimension),
3837a84e134Smrg    offset(preferred_size),
3847a84e134Smrg    XtRImmediate,
3857a84e134Smrg    (XtPointer)PANED_ASK_CHILD
3867a84e134Smrg  },
3877a84e134Smrg  {
3887a84e134Smrg    XtNresizeToPreferred,
3897a84e134Smrg    XtCBoolean,
3907a84e134Smrg    XtRBoolean,
3917a84e134Smrg    sizeof(Boolean),
3927a84e134Smrg    offset(resize_to_pref),
3937a84e134Smrg    XtRImmediate,
3947a84e134Smrg    (XtPointer)False
3957a84e134Smrg  },
3967a84e134Smrg  {
3977a84e134Smrg    XtNskipAdjust,
3987a84e134Smrg    XtCBoolean,
3997a84e134Smrg    XtRBoolean,
4007a84e134Smrg    sizeof(Boolean),
4017a84e134Smrg    offset(skip_adjust),
4027a84e134Smrg    XtRImmediate,
4037a84e134Smrg    (XtPointer)False
4047a84e134Smrg  },
4057a84e134Smrg  {
4067a84e134Smrg    XtNshowGrip,
4077a84e134Smrg    XtCShowGrip,
4087a84e134Smrg    XtRBoolean,
4097a84e134Smrg    sizeof(Boolean),
4107a84e134Smrg    offset(show_grip),
4117a84e134Smrg    XtRImmediate,
4127a84e134Smrg    (XtPointer)True
4137a84e134Smrg  },
4147a84e134Smrg};
4157a84e134Smrg#undef offset
4167a84e134Smrg
4177a84e134Smrg#define SuperClass ((ConstraintWidgetClass)&constraintClassRec)
4187a84e134Smrg
4197a84e134SmrgPanedClassRec panedClassRec = {
4207a84e134Smrg   /* core */
4217a84e134Smrg   {
4227a84e134Smrg    (WidgetClass)SuperClass,		/* superclass */
4237a84e134Smrg    "Paned",				/* class name */
4247a84e134Smrg    sizeof(PanedRec),			/* size */
4257a84e134Smrg    XawPanedClassInitialize,		/* class_initialize */
4267a84e134Smrg    NULL,				/* class_part init */
4277a84e134Smrg    False,				/* class_inited */
4287a84e134Smrg    XawPanedInitialize,			/* initialize */
4297a84e134Smrg    NULL,				/* initialize_hook */
4307a84e134Smrg    XawPanedRealize,			/* realize */
4317a84e134Smrg    NULL,				/* actions */
4327a84e134Smrg    0,					/* num_actions */
4337a84e134Smrg    resources,				/* resources */
4347a84e134Smrg    XtNumber(resources),		/* num_resources */
4357a84e134Smrg    NULLQUARK,				/* xrm_class */
4367a84e134Smrg    True,				/* compress_motion */
4377a84e134Smrg    True,				/* compress_exposure */
4387a84e134Smrg    True,				/* compress_enterleave */
4397a84e134Smrg    False,				/* visible_interest */
4407a84e134Smrg    XawPanedDestroy,			/* destroy */
4417a84e134Smrg    XawPanedResize,			/* resize */
4427a84e134Smrg    XawPanedRedisplay,			/* expose */
4437a84e134Smrg    XawPanedSetValues,			/* set_values */
4447a84e134Smrg    NULL,				/* set_values_hook */
4457a84e134Smrg    XtInheritSetValuesAlmost,		/* set_values_almost */
4467a84e134Smrg    NULL,				/* get_values_hook */
4477a84e134Smrg    NULL,				/* accept_focus */
4487a84e134Smrg    XtVersion,				/* version */
4497a84e134Smrg    NULL,				/* callback_private */
4507a84e134Smrg    NULL,				/* tm_table */
4517a84e134Smrg    XtInheritQueryGeometry,		/* query_geometry */
4527a84e134Smrg    XtInheritDisplayAccelerator,	/* display_accelerator */
4537a84e134Smrg    NULL,				/* extension */
4547a84e134Smrg  },
4557a84e134Smrg  /* composite */
4567a84e134Smrg  {
4577a84e134Smrg    XawPanedGeometryManager,		/* geometry_manager */
4587a84e134Smrg    XawPanedChangeManaged,		/* change_managed */
4597a84e134Smrg    XawPanedInsertChild,		/* insert_child */
4607a84e134Smrg    XawPanedDeleteChild,		/* delete_child */
4617a84e134Smrg    NULL,				/* extension */
4627a84e134Smrg  },
4637a84e134Smrg  /* constraint */
4647a84e134Smrg  {
4657a84e134Smrg    subresources,			/* subresources */
4667a84e134Smrg    XtNumber(subresources),		/* subresource_count */
4677a84e134Smrg    sizeof(PanedConstraintsRec),	/* constraint_size */
4687a84e134Smrg    NULL,				/* initialize */
4697a84e134Smrg    NULL,				/* destroy */
4707a84e134Smrg    XawPanedPaneSetValues,		/* set_values */
4717a84e134Smrg    NULL,				/* extension */
4727a84e134Smrg  },
4737a84e134Smrg};
4747a84e134Smrg
4757a84e134SmrgWidgetClass panedWidgetClass = (WidgetClass)&panedClassRec;
4767a84e134SmrgWidgetClass vPanedWidgetClass = (WidgetClass)&panedClassRec;
4777a84e134Smrg
4787a84e134Smrg/*
4797a84e134Smrg * Implementation
4807a84e134Smrg */
4817a84e134Smrg/* Function:
4827a84e134Smrg *	AdjustPanedSize
4837a84e134Smrg *
4847a84e134Smrg * Parameters:
4857a84e134Smrg *	pw	     - paned widget to adjust
4867a84e134Smrg *	off_size     - new off_size to use
4877a84e134Smrg *	result_ret   - result of query (return)
4887a84e134Smrg *	on_size_ret  - new on_size  (return)
4897a84e134Smrg *	off_size_ret - new off_size (return)
4907a84e134Smrg *
4917a84e134Smrg * Description:
4927a84e134Smrg *	Adjusts the size of the pane.
4937a84e134Smrg *
4947a84e134Smrg * Returns:
4957a84e134Smrg *	amount of change in size
4967a84e134Smrg */
4977a84e134Smrgstatic void
4987a84e134SmrgAdjustPanedSize(PanedWidget pw, unsigned int off_size,
4997a84e134Smrg		XtGeometryResult *result_ret,
5007a84e134Smrg		Dimension *on_size_ret, Dimension *off_size_ret)
5017a84e134Smrg{
5027a84e134Smrg    Dimension old_size = PaneSize((Widget)pw, IsVert(pw));
5037a84e134Smrg    Dimension newsize = 0;
5047a84e134Smrg    Widget *childP;
5057a84e134Smrg    XtWidgetGeometry request, reply;
5067a84e134Smrg
5077a84e134Smrg    request.request_mode = CWWidth | CWHeight;
5087a84e134Smrg
5097a84e134Smrg    ForAllPanes(pw, childP) {
5107a84e134Smrg	int size = Max(PaneInfo(*childP)->size, (int)PaneInfo(*childP)->min);
5117a84e134Smrg
5127a84e134Smrg	AssignMin(size, (int)PaneInfo(*childP)->max);
5137a84e134Smrg	newsize += size + pw->paned.internal_bw;
5147a84e134Smrg    }
5157a84e134Smrg    newsize -= pw->paned.internal_bw;
5167a84e134Smrg
5177a84e134Smrg    if (newsize < 1)
5187a84e134Smrg	newsize = 1;
5197a84e134Smrg
5207a84e134Smrg    if (IsVert(pw)) {
5217a84e134Smrg	request.width = off_size;
5227a84e134Smrg	request.height = newsize;
5237a84e134Smrg    }
5247a84e134Smrg    else {
5257a84e134Smrg	request.width = newsize;
5267a84e134Smrg	request.height = off_size;
5277a84e134Smrg    }
5287a84e134Smrg
5297a84e134Smrg    if (result_ret != NULL) {
5307a84e134Smrg	request.request_mode |= XtCWQueryOnly;
5317a84e134Smrg
5327a84e134Smrg	*result_ret = XtMakeGeometryRequest((Widget)pw, &request, &reply);
5337a84e134Smrg	_XawImCallVendorShellExtResize((Widget)pw);
5347a84e134Smrg
5357a84e134Smrg	if (newsize == old_size || *result_ret == XtGeometryNo) {
5367a84e134Smrg	    *on_size_ret = old_size;
5377a84e134Smrg	    *off_size_ret = off_size;
5387a84e134Smrg	    return;
5397a84e134Smrg	}
5407a84e134Smrg	if (*result_ret != XtGeometryAlmost) {
5417a84e134Smrg	    *on_size_ret = GetRequestInfo(&request, IsVert(pw));
5427a84e134Smrg      	    *off_size_ret = GetRequestInfo(&request, !IsVert(pw));
5437a84e134Smrg	    return;
5447a84e134Smrg	}
5457a84e134Smrg	*on_size_ret = GetRequestInfo(&reply, IsVert(pw));
5467a84e134Smrg	*off_size_ret = GetRequestInfo(&reply, !IsVert(pw));
5477a84e134Smrg	return;
5487a84e134Smrg    }
5497a84e134Smrg
5507a84e134Smrg    if (newsize == old_size)
5517a84e134Smrg	return;
5527a84e134Smrg
5537a84e134Smrg    if (XtMakeGeometryRequest((Widget)pw, &request, &reply) == XtGeometryAlmost)
5547a84e134Smrg	XtMakeGeometryRequest((Widget)pw, &reply, &request);
5557a84e134Smrg}
5567a84e134Smrg
5577a84e134Smrg/*
5587a84e134Smrg * Function:
5597a84e134Smrg *	ChoosePaneToResize.
5607a84e134Smrg *
5617a84e134Smrg * Parameters:
5627a84e134Smrg *	pw	  - paned widget
5637a84e134Smrg *	paneindex - index of the current pane
5647a84e134Smrg *	dir	  - direction to search first
5657a84e134Smrg *	shrink	  - True if we need to shrink a pane, False otherwise
5667a84e134Smrg *
5677a84e134Smrg * Description:
5687a84e134Smrg *	  This function chooses a pane to resize.
5697a84e134Smrg 	They are chosen using the following rules:
5707a84e134Smrg *
5717a84e134Smrg *		   1) size < max && size > min
5727a84e134Smrg *	2) skip adjust == False
5737a84e134Smrg *	3) widget not its prefered height
5747a84e134Smrg *	   && this change will bring it closer
5757a84e134Smrg *	   && The user has not resized this pane.
5767a84e134Smrg *
5777a84e134Smrg *		   If no widgets are found that fits all the rules then
5787a84e134Smrg *		      rule #3 is broken.
5797a84e134Smrg *		   If there are still no widgets found than
5807a84e134Smrg *		      rule #2 is broken.
5817a84e134Smrg *		   Rule #1 is never broken.
5827a84e134Smrg *		   If no widgets are found then NULL is returned.
5837a84e134Smrg *
5847a84e134Smrg * Returns:
5857a84e134Smrg *	pane to resize or NULL
5867a84e134Smrg */
5877a84e134Smrgstatic Pane
5887a84e134SmrgChoosePaneToResize(PanedWidget pw, int paneindex, Direction dir, Bool shrink)
5897a84e134Smrg{
5907a84e134Smrg    Widget *childP;
5917a84e134Smrg    int rules = 3;
5927a84e134Smrg    Direction _dir = dir;
5937a84e134Smrg    int _index = paneindex;
5947a84e134Smrg
5957a84e134Smrg    if (paneindex == NO_INDEX || dir == AnyPane) {		/* Use defaults */
5967a84e134Smrg	_dir = LowRightPane;			/* Go up - really */
5977a84e134Smrg	_index = pw->paned.num_panes - 1;	/* Start the last pane, and work
5987a84e134Smrg						   backwards */
5997a84e134Smrg    }
6007a84e134Smrg    childP = pw->composite.children + _index;
6017a84e134Smrg
6027a84e134Smrg    /*CONSTCOND*/
6037a84e134Smrg    while(True) {
6047a84e134Smrg	Pane pane = PaneInfo(*childP);
6057a84e134Smrg
6067a84e134Smrg	if ((rules < 3 || SatisfiesRule3(pane, shrink))
6077a84e134Smrg	    && (rules < 2 || SatisfiesRule2(pane))
6087a84e134Smrg	    && SatisfiesRule1(pane, shrink)
6097a84e134Smrg	    && (paneindex != PaneIndex(*childP) || dir == AnyPane))
6107a84e134Smrg	    return (pane);
6117a84e134Smrg
6127a84e134Smrg	/*
6137a84e134Smrg	 * This is counter-intuitive, but if we are resizing the pane
6147a84e134Smrg	 * above the grip we want to choose a pane below the grip to lose,
6157a84e134Smrg	 * and visa-versa
6167a84e134Smrg	 */
6177a84e134Smrg	if (_dir == LowRightPane)
6187a84e134Smrg	    --childP;
6197a84e134Smrg	else
6207a84e134Smrg	    ++childP;
6217a84e134Smrg
6227a84e134Smrg	/*
6237a84e134Smrg	 * If we have come to and edge then reduce the rule set, and try again
6247a84e134Smrg	 * If we are reduced the rules to none, then return NULL
6257a84e134Smrg	 */
6267a84e134Smrg	if ((childP - pw->composite.children) < 0 ||
6277a84e134Smrg	    (childP - pw->composite.children) >= pw->paned.num_panes) {
6287a84e134Smrg	    if (--rules < 1)	/* less strict rules */
6297a84e134Smrg		return (NULL);
6307a84e134Smrg	    childP = pw->composite.children + _index;
6317a84e134Smrg	}
6327a84e134Smrg    }
6337a84e134Smrg}
6347a84e134Smrg
6357a84e134Smrg/*
6367a84e134Smrg * Function:
6377a84e134Smrg *	LoopAndRefigureChildren
6387a84e134Smrg *
6397a84e134Smrg * Parameters:
6407a84e134Smrg *	pw	  - paned widget
6417a84e134Smrg * 	paneindex - number of the pane border we are moving
6427a84e134Smrg *	dir	  - pane to move (either UpLeftPane or LowRightPane)
6437a84e134Smrg *	sizeused  - current amount of space used (used and returned)
6447a84e134Smrg *
6457a84e134Smrg * Description:
6467a84e134Smrg *	  If we are resizing either the UpleftPane or LowRight Pane loop
6477a84e134Smrg *	through all the children to see if any will allow us to resize them.
6487a84e134Smrg */
6497a84e134Smrgstatic void
6507a84e134SmrgLoopAndRefigureChildren(PanedWidget pw, int paneindex, Direction dir,
6517a84e134Smrg			int *sizeused)
6527a84e134Smrg{
6537a84e134Smrg    int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
6547a84e134Smrg    Boolean shrink = (*sizeused > pane_size);
6557a84e134Smrg
6567a84e134Smrg    if (dir == LowRightPane)
6577a84e134Smrg	paneindex++;
6587a84e134Smrg
6597a84e134Smrg    /* While all panes do not fit properly */
6607a84e134Smrg    while (*sizeused != pane_size) {
6617a84e134Smrg	/*
6627a84e134Smrg	 * Choose a pane to resize
6637a84e134Smrg	 * First look on the Pane Stack, and then go hunting for another one
6647a84e134Smrg	 * If we fail to find a pane to resize then give up
6657a84e134Smrg	 */
6667a84e134Smrg	Pane pane;
6677a84e134Smrg	int start_size;
6687a84e134Smrg	Dimension old;
6697a84e134Smrg	Boolean rule3_ok = False, from_stack = True;
6707a84e134Smrg
6717a84e134Smrg	GetPaneStack(pw, shrink, &pane, &start_size);
6727a84e134Smrg	if (pane == NULL) {
6737a84e134Smrg	    pane = ChoosePaneToResize(pw, paneindex, dir, shrink);
6747a84e134Smrg	    if (pane == NULL)
6757a84e134Smrg		return; /* no one to resize, give up */
6767a84e134Smrg
6777a84e134Smrg	    rule3_ok = SatisfiesRule3(pane, shrink);
6787a84e134Smrg	    from_stack = False;
6797a84e134Smrg	    PushPaneStack(pw, pane);
6807a84e134Smrg	}
6817a84e134Smrg
6827a84e134Smrg	/*
6837a84e134Smrg	 * Try to resize this pane so that all panes will fit, take min and max
6847a84e134Smrg	 * into account
6857a84e134Smrg	 */
6867a84e134Smrg	old = pane->size;
6877a84e134Smrg	pane->size += pane_size - *sizeused;
6887a84e134Smrg
6897a84e134Smrg	if (from_stack) {
6907a84e134Smrg	    if (shrink) {
6917a84e134Smrg		AssignMax(pane->size, start_size);
6927a84e134Smrg	    }	/* don't remove these braces */
6937a84e134Smrg	    else
6947a84e134Smrg		AssignMin(pane->size, start_size);
6957a84e134Smrg
6967a84e134Smrg	  if (pane->size == start_size)
6977a84e134Smrg	    (void)PopPaneStack(pw);
6987a84e134Smrg	}
6997a84e134Smrg	else if (rule3_ok) {
7007a84e134Smrg	    if (shrink) {
7017a84e134Smrg		AssignMax(pane->size, (int)pane->wp_size);
7027a84e134Smrg	    }	/* don't remove these braces */
7037a84e134Smrg	    else
7047a84e134Smrg		AssignMin(pane->size, (int)pane->wp_size);
7057a84e134Smrg	}
7067a84e134Smrg
7077a84e134Smrg	pane->paned_adjusted_me = pane->size != pane->wp_size;
7087a84e134Smrg	AssignMax(pane->size, (int)pane->min);
7097a84e134Smrg	AssignMin(pane->size, (int)pane->max);
7107a84e134Smrg	*sizeused += (pane->size - old);
7117a84e134Smrg    }
7127a84e134Smrg}
7137a84e134Smrg
7147a84e134Smrg/*
7157a84e134Smrg * Function:
7167a84e134Smrg *	RefigureLocations
7177a84e134Smrg *
7187a84e134Smrg * Parameters:
7197a84e134Smrg *	pw	  - paned widget
7207a84e134Smrg *	paneindex - child to start refiguring at
7217a84e134Smrg *	dir	  - direction to move from child
7227a84e134Smrg *
7237a84e134Smrg * Description:
7247a84e134Smrg *	  Refigures all locations of children.
7257a84e134Smrg *      There are special arguments to paneindex and dir, they are:
7267a84e134Smrg *      paneindex - NO_INDEX.
7277a84e134Smrg *      dir   - AnyPane.
7287a84e134Smrg *
7297a84e134Smrg *      If either of these is true then all panes may be resized and
7307a84e134Smrg *      the choosing of panes procedes in reverse order starting with the
7317a84e134Smrg *      last child.
7327a84e134Smrg */
7337a84e134Smrgstatic void
7347a84e134SmrgRefigureLocations(PanedWidget pw, int paneindex, Direction dir)
7357a84e134Smrg{
7367a84e134Smrg    Widget *childP;
7377a84e134Smrg    int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
7387a84e134Smrg    int sizeused = 0;
7397a84e134Smrg    Position loc = 0;
7407a84e134Smrg
7417a84e134Smrg    if (pw->paned.num_panes == 0 || !pw->paned.refiguremode)
7427a84e134Smrg	return;
7437a84e134Smrg
7447a84e134Smrg    /*
7457a84e134Smrg     * Get an initial estimate of the size we will use
7467a84e134Smrg     */
7477a84e134Smrg    ForAllPanes(pw, childP) {
7487a84e134Smrg	Pane pane = PaneInfo(*childP);
7497a84e134Smrg
7507a84e134Smrg	AssignMax(pane->size, (int) pane->min);
7517a84e134Smrg	AssignMin(pane->size, (int) pane->max);
7527a84e134Smrg	sizeused += (int)pane->size + (int)pw->paned.internal_bw;
7537a84e134Smrg    }
7547a84e134Smrg    sizeused -= (int)pw->paned.internal_bw;
7557a84e134Smrg
7567a84e134Smrg    if (dir != ThisBorderOnly && sizeused != pane_size)
7577a84e134Smrg	LoopAndRefigureChildren(pw, paneindex, dir, &sizeused);
7587a84e134Smrg
7597a84e134Smrg    /*
7607a84e134Smrg     * If we still are not the right size, then tell the pane that
7617a84e134Smrg     * wanted to resize that it can't
7627a84e134Smrg     */
7637a84e134Smrg    if (paneindex != NO_INDEX && dir != AnyPane) {
7647a84e134Smrg	Pane pane = PaneInfo(*(pw->composite.children + paneindex));
7657a84e134Smrg	Dimension old = pane->size;
7667a84e134Smrg
7677a84e134Smrg	pane->size += pane_size - sizeused;
7687a84e134Smrg	AssignMax(pane->size, (int) pane->min);
7697a84e134Smrg	AssignMin(pane->size, (int) pane->max);
7707a84e134Smrg	sizeused += pane->size - old;
7717a84e134Smrg    }
7727a84e134Smrg
7737a84e134Smrg    /*
7747a84e134Smrg     * It is possible that the panes will not fit inside the vpaned widget, but
7757a84e134Smrg     * we have tried out best
7767a84e134Smrg     *
7777a84e134Smrg     * Assign each pane a location
7787a84e134Smrg     */
7797a84e134Smrg    ForAllPanes(pw, childP) {
7807a84e134Smrg	PaneInfo(*childP)->delta = loc;
7817a84e134Smrg	loc += PaneInfo(*childP)->size + pw->paned.internal_bw;
7827a84e134Smrg    }
7837a84e134Smrg}
7847a84e134Smrg
7857a84e134Smrg/*
7867a84e134Smrg * Function:
7877a84e134Smrg *	CommitNewLocations
7887a84e134Smrg *
7897a84e134Smrg * Parameters:
7907a84e134Smrg *	pw - paned widget
7917a84e134Smrg *
7927a84e134Smrg * Description:
7937a84e134Smrg *	Commits all of the previously figured locations.
7947a84e134Smrg */
7957a84e134Smrgstatic void
7967a84e134SmrgCommitNewLocations(PanedWidget pw)
7977a84e134Smrg{
7987a84e134Smrg    Widget *childP;
7997a84e134Smrg    XWindowChanges changes;
8007a84e134Smrg
8017a84e134Smrg    changes.stack_mode = Above;
8027a84e134Smrg
8037a84e134Smrg    ForAllPanes(pw, childP) {
8047a84e134Smrg	Pane pane = PaneInfo(*childP);
8057a84e134Smrg	Widget grip = pane->grip;	/* may be NULL */
8067a84e134Smrg
8077a84e134Smrg	if (IsVert(pw)) {
8087a84e134Smrg	    XtMoveWidget(*childP, (Position) 0, pane->delta);
8097a84e134Smrg	    XtResizeWidget(*childP, XtWidth(pw), pane->size, 0);
8107a84e134Smrg
8117a84e134Smrg	    if (HasGrip(*childP)) {	/* Move and Display the Grip */
8127a84e134Smrg		changes.x = XtWidth(pw) - pw->paned.grip_indent -
8137a84e134Smrg			    XtWidth(grip) - (XtBorderWidth(grip) << 1);
8147a84e134Smrg		changes.y = XtY(*childP) + XtHeight(*childP) -
8157a84e134Smrg			    (XtHeight(grip) >> 1) - XtBorderWidth(grip) +
8167a84e134Smrg			    (pw->paned.internal_bw >> 1);
8177a84e134Smrg	    }
8187a84e134Smrg	}
8197a84e134Smrg	else {
8207a84e134Smrg	    XtMoveWidget(*childP, pane->delta, 0);
8217a84e134Smrg	    XtResizeWidget(*childP, pane->size, XtHeight(pw), 0);
8227a84e134Smrg
8237a84e134Smrg	    if (HasGrip(*childP)) {		/* Move and Display the Grip */
8247a84e134Smrg		changes.x = XtX(*childP) + XtWidth(*childP) -
8257a84e134Smrg			    (XtWidth(grip) >> 1) - XtBorderWidth(grip) +
8267a84e134Smrg			    (pw->paned.internal_bw >> 1);
8277a84e134Smrg		changes.y = XtHeight(pw) - pw->paned.grip_indent -
8287a84e134Smrg			    XtHeight(grip) - (XtBorderWidth(grip) << 1);
8297a84e134Smrg	    }
8307a84e134Smrg	}
8317a84e134Smrg
8327a84e134Smrg	/*
8337a84e134Smrg	 * This should match XtMoveWidget, except that we're also insuring the
8347a84e134Smrg	 * grip is Raised in the same request
8357a84e134Smrg	 */
8367a84e134Smrg
8377a84e134Smrg	if (HasGrip(*childP)) {
8387a84e134Smrg	    XtX(grip) = changes.x;
8397a84e134Smrg	    XtY(grip) = changes.y;
8407a84e134Smrg
8417a84e134Smrg	    if (XtIsRealized(pane->grip))
8427a84e134Smrg		XConfigureWindow(XtDisplay(pane->grip), XtWindow(pane->grip),
8437a84e134Smrg				 CWX | CWY | CWStackMode, &changes);
8447a84e134Smrg	}
8457a84e134Smrg    }
8467a84e134Smrg    ClearPaneStack(pw);
8477a84e134Smrg}
8487a84e134Smrg
8497a84e134Smrg/*
8507a84e134Smrg * Function:
8517a84e134Smrg *	RefigureLocationsAndCommit
8527a84e134Smrg *
8537a84e134Smrg * Parameters:
8547a84e134Smrg *	pw - paned widget
8557a84e134Smrg *
8567a84e134Smrg * Description:
8577a84e134Smrg * 	Refigures all locations in a paned widget and commits them immediately.
8587a84e134Smrg *
8597a84e134Smrg *      This function does nothing if any of the following are true.
8607a84e134Smrg *      o refiguremode is false.
8617a84e134Smrg *      o The widget is unrealized.
8627a84e134Smrg *      o There are no panes is the paned widget.
8637a84e134Smrg */
8647a84e134Smrgstatic void
8657a84e134SmrgRefigureLocationsAndCommit(Widget w)
8667a84e134Smrg{
8677a84e134Smrg    PanedWidget pw = (PanedWidget)w;
8687a84e134Smrg
8697a84e134Smrg    if (pw->paned.refiguremode && XtIsRealized(w) && pw->paned.num_panes > 0) {
8707a84e134Smrg	RefigureLocations(pw, NO_INDEX, AnyPane);
8717a84e134Smrg	CommitNewLocations(pw);
8727a84e134Smrg    }
8737a84e134Smrg}
8747a84e134Smrg
8757a84e134Smrg/*
8767a84e134Smrg * Function:
8777a84e134Smrg *	_DrawRect
8787a84e134Smrg *
8797a84e134Smrg * Parameters:
8807a84e134Smrg *	pw	 - paned widget
8817a84e134Smrg *	gc	 - gc to used for the draw
8827a84e134Smrg *	on_olc	 - location of upper left corner of rect
8837a84e134Smrg *	off_loc	 - ""
8847a84e134Smrg *	on_size	 - size of rectangle
8857a84e134Smrg *	off_size - ""
8867a84e134Smrg *
8877a84e134Smrg * Description:
8887a84e134Smrg *	Draws a rectangle in the proper orientation.
8897a84e134Smrg */
8907a84e134Smrgstatic void
8917a84e134Smrg_DrawRect(PanedWidget pw, GC gc, int on_loc, int off_loc,
8927a84e134Smrg	  unsigned int on_size, unsigned int off_size)
8937a84e134Smrg{
8947a84e134Smrg    if (IsVert(pw))
8957a84e134Smrg	XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
8967a84e134Smrg		       off_loc, on_loc, off_size, on_size);
8977a84e134Smrg    else
8987a84e134Smrg	XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
8997a84e134Smrg		       on_loc, off_loc, on_size, off_size);
9007a84e134Smrg}
9017a84e134Smrg
9027a84e134Smrg/*
9037a84e134Smrg * Function:
9047a84e134Smrg *	_DrawInternalBorders
9057a84e134Smrg *
9067a84e134Smrg * Parameters:
9077a84e134Smrg *	pw - paned widget
9087a84e134Smrg *	gc - GC to use to draw the borders
9097a84e134Smrg *
9107a84e134Smrg * Description:
9117a84e134Smrg *	Draws the internal borders into the paned widget.
9127a84e134Smrg */
9137a84e134Smrgstatic void
9147a84e134Smrg_DrawInternalBorders(PanedWidget pw, GC gc)
9157a84e134Smrg{
9167a84e134Smrg    Widget *childP;
9177a84e134Smrg    int on_loc, off_loc;
9187a84e134Smrg    unsigned int on_size, off_size;
9197a84e134Smrg
9207a84e134Smrg    /*
9217a84e134Smrg     * This is an optimization.  Do not paint the internal borders if
9227a84e134Smrg     * they are the same color as the background
9237a84e134Smrg     */
9247a84e134Smrg    if (pw->core.background_pixel == pw->paned.internal_bp)
9257a84e134Smrg	return;
9267a84e134Smrg
9277a84e134Smrg    off_loc = 0;
9287a84e134Smrg    off_size = (unsigned int) PaneSize((Widget)pw, !IsVert(pw));
9297a84e134Smrg    on_size = (unsigned int)pw->paned.internal_bw;
9307a84e134Smrg
9317a84e134Smrg    ForAllPanes(pw, childP) {
9327a84e134Smrg	on_loc = IsVert(pw) ? XtY(*childP) : XtX(*childP);
9337a84e134Smrg	on_loc -= (int)on_size;
9347a84e134Smrg
9357a84e134Smrg	_DrawRect(pw, gc, on_loc, off_loc, on_size, off_size);
9367a84e134Smrg    }
9377a84e134Smrg}
9387a84e134Smrg
9397a84e134Smrg#define DrawInternalBorders(pw)				\
9407a84e134Smrg	_DrawInternalBorders((pw), (pw)->paned.normgc)
9417a84e134Smrg#define EraseInternalBorders(pw)			\
9427a84e134Smrg	_DrawInternalBorders((pw), (pw)->paned.invgc)
9437a84e134Smrg/*
9447a84e134Smrg * Function Name:
9457a84e134Smrg *	_DrawTrackLines
9467a84e134Smrg *
9477a84e134Smrg * Parameters:
9487a84e134Smrg *	pw - Paned widget
9497a84e134Smrg *	erase - if True then just erase track lines, else draw them in
9507a84e134Smrg *
9517a84e134Smrg * Description:
9527a84e134Smrg *	Draws the lines that animate the pane borders when the grips are moved.
9537a84e134Smrg */
9547a84e134Smrgstatic void
9557a84e134Smrg_DrawTrackLines(PanedWidget pw, Bool erase)
9567a84e134Smrg{
9577a84e134Smrg    Widget *childP;
9587a84e134Smrg    Pane pane;
9597a84e134Smrg    int on_loc, off_loc;
9607a84e134Smrg    unsigned int on_size, off_size;
9617a84e134Smrg
9627a84e134Smrg    off_loc = 0;
9637a84e134Smrg    off_size = PaneSize((Widget)pw, !IsVert(pw));
9647a84e134Smrg
9657a84e134Smrg    ForAllPanes(pw, childP) {
9667a84e134Smrg	pane = PaneInfo(*childP);
9677a84e134Smrg	if (erase || pane->olddelta != pane->delta) {
9687a84e134Smrg	    on_size = pw->paned.internal_bw;
9697a84e134Smrg	    if (!erase) {
9707a84e134Smrg		on_loc = PaneInfo(*childP)->olddelta - (int) on_size;
9717a84e134Smrg		_DrawRect(pw, pw->paned.flipgc,
9727a84e134Smrg			  on_loc, off_loc, on_size, off_size);
9737a84e134Smrg	    }
9747a84e134Smrg
9757a84e134Smrg	    on_loc = PaneInfo(*childP)->delta - (int)on_size;
9767a84e134Smrg
9777a84e134Smrg	    _DrawRect(pw, pw->paned.flipgc,
9787a84e134Smrg		      on_loc, off_loc, on_size, off_size);
9797a84e134Smrg
9807a84e134Smrg	    pane->olddelta = pane->delta;
9817a84e134Smrg	}
9827a84e134Smrg    }
9837a84e134Smrg}
9847a84e134Smrg
9857a84e134Smrg#define DrawTrackLines(pw)	_DrawTrackLines((pw), False);
9867a84e134Smrg#define EraseTrackLines(pw)	_DrawTrackLines((pw), True);
9877a84e134Smrg/*
9887a84e134Smrg * Function:
9897a84e134Smrg *	GetEventLocation
9907a84e134Smrg *
9917a84e134Smrg * Parameters:
9927a84e134Smrg *	pw    - the paned widget
9937a84e134Smrg *	event - pointer to an event
9947a84e134Smrg *
9957a84e134Smrg * Description:
9967a84e134Smrg *	Converts and event to an x and y location.
9977a84e134Smrg *
9987a84e134Smrg * Returns:
9997a84e134Smrg *	if this is a vertical pane then (y) else (x)
10007a84e134Smrg */
10017a84e134Smrgstatic int
10027a84e134SmrgGetEventLocation(PanedWidget pw, XEvent *event)
10037a84e134Smrg{
10047a84e134Smrg    int x, y;
10057a84e134Smrg
10067a84e134Smrg    switch (event->xany.type) {
10077a84e134Smrg	case ButtonPress:
10087a84e134Smrg	case ButtonRelease:
10097a84e134Smrg	    x = event->xbutton.x_root;
10107a84e134Smrg	    y = event->xbutton.y_root;
10117a84e134Smrg	    break;
10127a84e134Smrg	case KeyPress:
10137a84e134Smrg	case KeyRelease:
10147a84e134Smrg	    x = event->xkey.x_root;
10157a84e134Smrg	    y = event->xkey.y_root;
10167a84e134Smrg	    break;
10177a84e134Smrg	case MotionNotify:
10187a84e134Smrg	    x = event->xmotion.x_root;
10197a84e134Smrg	    y = event->xmotion.y_root;
10207a84e134Smrg	    break;
10217a84e134Smrg	default:
10227a84e134Smrg	    x = pw->paned.start_loc;
10237a84e134Smrg	    y = pw->paned.start_loc;
10247a84e134Smrg    }
10257a84e134Smrg
10267a84e134Smrg    if (IsVert(pw))
10277a84e134Smrg	return (y);
10287a84e134Smrg
10297a84e134Smrg  return (x);
10307a84e134Smrg}
10317a84e134Smrg
10327a84e134Smrg/*
10337a84e134Smrg * Function:
10347a84e134Smrg *	StartGripAdjustment
10357a84e134Smrg *
10367a84e134Smrg * Parameters:
10377a84e134Smrg *	pw   - paned widget
10387a84e134Smrg *	grip - grip widget selected
10397a84e134Smrg *	dir  - direction that we are to be moving
10407a84e134Smrg *
10417a84e134Smrg * Description:
10427a84e134Smrg *	Starts the grip adjustment procedure.
10437a84e134Smrg */
10447a84e134Smrgstatic void
10457a84e134SmrgStartGripAdjustment(PanedWidget pw, Widget grip, Direction dir)
10467a84e134Smrg{
10477a84e134Smrg    Widget *childP;
10487a84e134Smrg    Cursor cursor;
10497a84e134Smrg
10507a84e134Smrg    pw->paned.whichadd = pw->paned.whichsub = NULL;
10517a84e134Smrg
10527a84e134Smrg    if (dir == ThisBorderOnly || dir == UpLeftPane)
10537a84e134Smrg	pw->paned.whichadd = pw->composite.children[PaneIndex(grip)];
10547a84e134Smrg    if (dir == ThisBorderOnly || dir == LowRightPane)
10557a84e134Smrg	pw->paned.whichsub = pw->composite.children[PaneIndex(grip) + 1];
10567a84e134Smrg
10577a84e134Smrg    /*
10587a84e134Smrg     * Change the cursor
10597a84e134Smrg     */
10607a84e134Smrg    if (XtIsRealized(grip)) {
10617a84e134Smrg	if (IsVert(pw)) {
10627a84e134Smrg	    if (dir == UpLeftPane)
10637a84e134Smrg		cursor = pw->paned.adjust_upper_cursor;
10647a84e134Smrg	    else if (dir == LowRightPane)
10657a84e134Smrg  		cursor = pw->paned.adjust_lower_cursor;
10667a84e134Smrg	    else {
10677a84e134Smrg		if (pw->paned.adjust_this_cursor == None)
10687a84e134Smrg		    cursor = pw->paned.v_adjust_this_cursor;
10697a84e134Smrg		else
10707a84e134Smrg		    cursor = pw->paned.adjust_this_cursor;
10717a84e134Smrg	    }
10727a84e134Smrg	}
10737a84e134Smrg	else {
10747a84e134Smrg	    if (dir == UpLeftPane)
10757a84e134Smrg		cursor = pw->paned.adjust_left_cursor;
10767a84e134Smrg	    else if (dir == LowRightPane)
10777a84e134Smrg  		cursor = pw->paned.adjust_right_cursor;
10787a84e134Smrg	    else {
10797a84e134Smrg		if (pw->paned.adjust_this_cursor == None)
10807a84e134Smrg		    cursor = pw->paned.h_adjust_this_cursor;
10817a84e134Smrg		else
10827a84e134Smrg		    cursor = pw->paned.adjust_this_cursor;
10837a84e134Smrg	    }
10847a84e134Smrg	}
10857a84e134Smrg
10867a84e134Smrg	XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
10877a84e134Smrg    }
10887a84e134Smrg
10897a84e134Smrg    EraseInternalBorders(pw);
10907a84e134Smrg    ForAllPanes(pw, childP)
10917a84e134Smrg	PaneInfo(*childP)->olddelta = -99;
10927a84e134Smrg
10937a84e134Smrg    EraseTrackLines(pw);
10947a84e134Smrg}
10957a84e134Smrg
10967a84e134Smrg/*
10977a84e134Smrg * Function:
10987a84e134Smrg *	MoveGripAdjustment
10997a84e134Smrg *
11007a84e134Smrg * Parameters:
11017a84e134Smrg *	pw   - paned widget
11027a84e134Smrg *	grip - grip that we are moving
11037a84e134Smrg *	dir  - direction the pane we are interested is w.r.t the grip
11047a84e134Smrg *	loc  - location of pointer in proper direction
11057a84e134Smrg *
11067a84e134Smrg * Description:
11077a84e134Smrg *	This routine moves all panes around when a grip is moved.
11087a84e134Smrg */
11097a84e134Smrgstatic void
11107a84e134SmrgMoveGripAdjustment(PanedWidget pw, Widget grip, Direction dir, int loc)
11117a84e134Smrg{
11127a84e134Smrg    int diff, add_size = 0, sub_size = 0;
11137a84e134Smrg
11147a84e134Smrg    diff = loc - pw->paned.start_loc;
11157a84e134Smrg
11167a84e134Smrg    if (pw->paned.whichadd)
11177a84e134Smrg    add_size = PaneSize(pw->paned.whichadd, IsVert(pw)) + diff;
11187a84e134Smrg
11197a84e134Smrg    if (pw->paned.whichsub)
11207a84e134Smrg    sub_size = PaneSize(pw->paned.whichsub, IsVert(pw)) - diff;
11217a84e134Smrg
11227a84e134Smrg    /*
11237a84e134Smrg     * If moving this border only then do not allow either of the borders
11247a84e134Smrg     * to go beyond the min or max size allowed
11257a84e134Smrg     */
11267a84e134Smrg    if (dir == ThisBorderOnly) {
11277a84e134Smrg	int old_add_size = add_size, old_sub_size;
11287a84e134Smrg
11297a84e134Smrg	AssignMax(add_size, (int)PaneInfo(pw->paned.whichadd)->min);
11307a84e134Smrg	AssignMin(add_size, (int)PaneInfo(pw->paned.whichadd)->max);
11317a84e134Smrg	if (add_size != old_add_size)
11327a84e134Smrg	    sub_size += old_add_size - add_size;
11337a84e134Smrg
11347a84e134Smrg	old_sub_size = sub_size;
11357a84e134Smrg	AssignMax(sub_size, (int)PaneInfo(pw->paned.whichsub)->min);
11367a84e134Smrg	AssignMin(sub_size, (int)PaneInfo(pw->paned.whichsub)->max);
11377a84e134Smrg	if (sub_size != old_sub_size)
11387a84e134Smrg	    return;	/* Abort to current sizes */
11397a84e134Smrg    }
11407a84e134Smrg
11417a84e134Smrg    if (add_size != 0)
11427a84e134Smrg	PaneInfo(pw->paned.whichadd)->size = add_size;
11437a84e134Smrg    if (sub_size != 0)
11447a84e134Smrg	PaneInfo(pw->paned.whichsub)->size = sub_size;
11457a84e134Smrg    RefigureLocations(pw, PaneIndex(grip), dir);
11467a84e134Smrg    DrawTrackLines(pw);
11477a84e134Smrg}
11487a84e134Smrg
11497a84e134Smrg/*
11507a84e134Smrg * Function:
11517a84e134Smrg *	CommitGripAdjustment
11527a84e134Smrg *
11537a84e134Smrg * Parameters:
11547a84e134Smrg *	pw - paned widget
11557a84e134Smrg *
11567a84e134Smrg * Description:
11577a84e134Smrg *	Commits the grip adjustment.
11587a84e134Smrg */
11597a84e134Smrgstatic void
11607a84e134SmrgCommitGripAdjustment(PanedWidget pw)
11617a84e134Smrg{
11627a84e134Smrg    EraseTrackLines(pw);
11637a84e134Smrg    CommitNewLocations(pw);
11647a84e134Smrg    DrawInternalBorders(pw);
11657a84e134Smrg
11667a84e134Smrg    /*
11677a84e134Smrg     * Since the user selected this size then use it as the preferred size
11687a84e134Smrg     */
11697a84e134Smrg    if (pw->paned.whichadd) {
11707a84e134Smrg	Pane pane = PaneInfo(pw->paned.whichadd);
11717a84e134Smrg
11727a84e134Smrg	pane->wp_size = pane->size;
11737a84e134Smrg    }
11747a84e134Smrg    if (pw->paned.whichsub) {
11757a84e134Smrg	Pane pane = PaneInfo(pw->paned.whichsub);
11767a84e134Smrg
11777a84e134Smrg	pane->wp_size = pane->size;
11787a84e134Smrg    }
11797a84e134Smrg}
11807a84e134Smrg
11817a84e134Smrg/*
11827a84e134Smrg * Function:
11837a84e134Smrg *	HandleGrip
11847a84e134Smrg *
11857a84e134Smrg * Parameters:
11867a84e134Smrg *	grip	  - grip widget that has been moved
11877a84e134Smrg *	temp	  - (not used)
11887a84e134Smrg *	call_data - data passed to us from the grip widget
11897a84e134Smrg *
11907a84e134Smrg * Description:
11917a84e134Smrg *	Handles the grip manipulations.
11927a84e134Smrg */
11937a84e134Smrg/*ARGSUSED*/
11947a84e134Smrgstatic void
11957a84e134SmrgHandleGrip(Widget grip, XtPointer temp, XtPointer callData)
11967a84e134Smrg{
11977a84e134Smrg    XawGripCallData call_data = (XawGripCallData)callData;
11987a84e134Smrg    PanedWidget pw = (PanedWidget) XtParent(grip);
11997a84e134Smrg    int loc;
12007a84e134Smrg    char action_type[2], direction[2];
12017a84e134Smrg    Cursor cursor;
12027a84e134Smrg    Arg arglist[1];
12037a84e134Smrg
12047a84e134Smrg    if (call_data->num_params)
12057a84e134Smrg	XmuNCopyISOLatin1Uppered(action_type, call_data->params[0],
12067a84e134Smrg				 sizeof(action_type));
12077a84e134Smrg
12087a84e134Smrg    if (call_data->num_params == 0
12097a84e134Smrg	|| (action_type[0] == 'C' && call_data->num_params != 1)
12107a84e134Smrg	|| (action_type[0] != 'C' && call_data->num_params != 2))
12117a84e134Smrg	XtAppError(XtWidgetToApplicationContext(grip),
12127a84e134Smrg		   "Paned GripAction has been passed incorrect parameters.");
12137a84e134Smrg
12147a84e134Smrg    loc = GetEventLocation(pw, (XEvent *)call_data->event);
12157a84e134Smrg
12167a84e134Smrg    if (action_type[0] != 'C')
12177a84e134Smrg	XmuNCopyISOLatin1Uppered(direction, call_data->params[1],
12187a84e134Smrg				 sizeof(direction));
12197a84e134Smrg
12207a84e134Smrg    switch (action_type[0]) {
12217a84e134Smrg	case 'S':		/* Start adjustment */
12227a84e134Smrg	    pw->paned.resize_children_to_pref = False;
12237a84e134Smrg	    StartGripAdjustment(pw, grip, (Direction)direction[0]);
12247a84e134Smrg	    pw->paned.start_loc = loc;
12257a84e134Smrg	    break;
12267a84e134Smrg	case 'M':
12277a84e134Smrg	    MoveGripAdjustment(pw, grip, (Direction)direction[0], loc);
12287a84e134Smrg	    break;
12297a84e134Smrg	case 'C':
12307a84e134Smrg	    XtSetArg(arglist[0], XtNcursor, &cursor);
12317a84e134Smrg	    XtGetValues(grip, arglist, 1);
12327a84e134Smrg	    XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
12337a84e134Smrg	    CommitGripAdjustment(pw);
12347a84e134Smrg	    break;
12357a84e134Smrg	default:
12367a84e134Smrg	    XtAppError(XtWidgetToApplicationContext(grip),
12377a84e134Smrg		       "Paned GripAction(); 1st parameter invalid");
12387a84e134Smrg	    break;
12397a84e134Smrg     }
12407a84e134Smrg}
12417a84e134Smrg
12427a84e134Smrg/*
12437a84e134Smrg * Function:
12447a84e134Smrg *	ResortChildren
12457a84e134Smrg *
12467a84e134Smrg * Arguments:
12477a84e134Smrg *	pw - paned widget
12487a84e134Smrg *
12497a84e134Smrg * Description:
12507a84e134Smrg *	Resorts the children so that all managed children are first.
12517a84e134Smrg */
12527a84e134Smrgstatic void
12537a84e134SmrgResortChildren(PanedWidget pw)
12547a84e134Smrg{
12557a84e134Smrg    Widget *unmanagedP, *childP;
12567a84e134Smrg
12577a84e134Smrg    unmanagedP = NULL;
12587a84e134Smrg    ForAllChildren(pw, childP) {
12597a84e134Smrg	if (!IsPane(*childP) || !XtIsManaged(*childP)) {
12607a84e134Smrg	    /*
12617a84e134Smrg	     * We only keep track of the first unmanaged pane
12627a84e134Smrg	     */
12637a84e134Smrg	    if (unmanagedP == NULL)
12647a84e134Smrg		unmanagedP = childP;
12657a84e134Smrg	}
12667a84e134Smrg	else {			/* must be a managed pane */
12677a84e134Smrg	    /*
12687a84e134Smrg	     * If an earlier widget was not a managed pane, then swap
12697a84e134Smrg	     */
12707a84e134Smrg	    if (unmanagedP != NULL) {
12717a84e134Smrg		Widget child = *unmanagedP;
12727a84e134Smrg
12737a84e134Smrg		*unmanagedP = *childP;
12747a84e134Smrg		*childP = child;
12757a84e134Smrg		childP = unmanagedP;  /* easiest to just back-track */
12767a84e134Smrg		unmanagedP = NULL;    /* in case there is another managed */
12777a84e134Smrg	   }
12787a84e134Smrg       }
12797a84e134Smrg   }
12807a84e134Smrg}
12817a84e134Smrg
12827a84e134Smrg/*
12837a84e134Smrg * Function:
12847a84e134Smrg *	ManageAndUnmanageGrips
12857a84e134Smrg *
12867a84e134Smrg * Parameters:
12877a84e134Smrg *	pw - paned widget
12887a84e134Smrg *
12897a84e134Smrg * Description:
12907a84e134Smrg *	  This function manages and unmanages the grips so that
12917a84e134Smrg *		   the managed state of each grip matches that of its pane.
12927a84e134Smrg */
12937a84e134Smrgstatic void
12947a84e134SmrgManageAndUnmanageGrips(PanedWidget pw)
12957a84e134Smrg{
12967a84e134Smrg    WidgetList managed_grips, unmanaged_grips;
12977a84e134Smrg    Widget *managedP, *unmanagedP, *childP;
12987a84e134Smrg    Cardinal alloc_size;
12997a84e134Smrg
13007a84e134Smrg    alloc_size = sizeof(Widget) * (pw->composite.num_children >> 1);
13017a84e134Smrg    managedP = managed_grips = (WidgetList)XtMalloc(alloc_size);
13027a84e134Smrg    unmanagedP = unmanaged_grips = (WidgetList)XtMalloc(alloc_size);
13037a84e134Smrg
13047a84e134Smrg    ForAllChildren(pw, childP)
13057a84e134Smrg	if (IsPane(*childP) && HasGrip(*childP)) {
13067a84e134Smrg	    if (XtIsManaged(*childP))
13077a84e134Smrg		*managedP++ = PaneInfo(*childP)->grip;
13087a84e134Smrg	    else
13097a84e134Smrg		*unmanagedP++ = PaneInfo(*childP)->grip;
13107a84e134Smrg	}
13117a84e134Smrg
13127a84e134Smrg    if (managedP != managed_grips) {
13137a84e134Smrg	*unmanagedP++ = *--managedP;   /* Last grip is never managed */
13147a84e134Smrg	XtManageChildren(managed_grips, managedP - managed_grips);
13157a84e134Smrg    }
13167a84e134Smrg
13177a84e134Smrg    if (unmanagedP != unmanaged_grips)
13187a84e134Smrg	XtUnmanageChildren(unmanaged_grips, unmanagedP - unmanaged_grips);
13197a84e134Smrg
13207a84e134Smrg    XtFree((char *)managed_grips);
13217a84e134Smrg    XtFree((char *)unmanaged_grips);
13227a84e134Smrg}
13237a84e134Smrg
13247a84e134Smrg/*
13257a84e134Smrg * Function:
13267a84e134Smrg *	CreateGrip
13277a84e134Smrg *
13287a84e134Smrg * Parameters:
13297a84e134Smrg *	child - child that wants a grip to be created for it
13307a84e134Smrg *
13317a84e134Smrg * Description:
13327a84e134Smrg *	Creates a grip widget.
13337a84e134Smrg */
13347a84e134Smrgstatic void
13357a84e134SmrgCreateGrip(Widget child)
13367a84e134Smrg{
13377a84e134Smrg    PanedWidget pw = (PanedWidget)XtParent(child);
13387a84e134Smrg    Arg arglist[2];
13397a84e134Smrg    Cardinal num_args = 0;
13407a84e134Smrg    Cursor cursor;
13417a84e134Smrg
13427a84e134Smrg    XtSetArg(arglist[num_args], XtNtranslations, pw->paned.grip_translations);
13437a84e134Smrg    num_args++;
13447a84e134Smrg    if ((cursor = pw->paned.grip_cursor) == None) {
13457a84e134Smrg	if (IsVert(pw))
13467a84e134Smrg	    cursor = pw->paned.v_grip_cursor;
13477a84e134Smrg	else
13487a84e134Smrg	    cursor = pw->paned.h_grip_cursor;
13497a84e134Smrg    }
13507a84e134Smrg
13517a84e134Smrg    XtSetArg(arglist[num_args], XtNcursor, cursor);
13527a84e134Smrg    num_args++;
13537a84e134Smrg    PaneInfo(child)->grip = XtCreateWidget("grip", gripWidgetClass, (Widget)pw,
13547a84e134Smrg					   arglist, num_args);
13557a84e134Smrg
13567a84e134Smrg    XtAddCallback(PaneInfo(child)->grip, XtNcallback,
13577a84e134Smrg		  HandleGrip, (XtPointer)child);
13587a84e134Smrg}
13597a84e134Smrg
13607a84e134Smrg/*
13617a84e134Smrg * Function:
13627a84e134Smrg *	GetGCs
13637a84e134Smrg *
13647a84e134Smrg * Parameters:
13657a84e134Smrg *	w - paned widget
13667a84e134Smrg */
13677a84e134Smrgstatic void
13687a84e134SmrgGetGCs(Widget w)
13697a84e134Smrg{
13707a84e134Smrg    PanedWidget pw = (PanedWidget)w;
13717a84e134Smrg    XtGCMask valuemask;
13727a84e134Smrg    XGCValues values;
13737a84e134Smrg
13747a84e134Smrg    /*
13757a84e134Smrg     * Draw pane borders in internal border color
13767a84e134Smrg     */
13777a84e134Smrg    values.foreground = pw->paned.internal_bp;
13787a84e134Smrg    valuemask = GCForeground;
13797a84e134Smrg    pw->paned.normgc = XtGetGC(w, valuemask, &values);
13807a84e134Smrg
13817a84e134Smrg    /*
13827a84e134Smrg     * Erase pane borders with background color
13837a84e134Smrg     */
13847a84e134Smrg    values.foreground = pw->core.background_pixel;
13857a84e134Smrg    valuemask = GCForeground;
13867a84e134Smrg    pw->paned.invgc = XtGetGC(w, valuemask, &values);
13877a84e134Smrg
13887a84e134Smrg    /*
13897a84e134Smrg     * Draw Track lines (animate pane borders) in
13907a84e134Smrg     * internal border color ^ bg color
13917a84e134Smrg     */
13927a84e134Smrg    values.function = GXinvert;
13937a84e134Smrg    values.plane_mask = pw->paned.internal_bp ^ pw->core.background_pixel;
13947a84e134Smrg    values.subwindow_mode = IncludeInferiors;
13957a84e134Smrg    valuemask = GCPlaneMask | GCFunction | GCSubwindowMode;
13967a84e134Smrg    pw->paned.flipgc = XtGetGC(w, valuemask, &values);
13977a84e134Smrg}
13987a84e134Smrg
13997a84e134Smrg/*
14007a84e134Smrg * Function:
14017a84e134Smrg *	SetChildrenPrefSizes
14027a84e134Smrg *
14037a84e134Smrg * Parameters:
14047a84e134Smrg *	pw - paned widget
14057a84e134Smrg *
14067a84e134Smrg * Description:
14077a84e134Smrg *	Sets the preferred sizes of the children.
14087a84e134Smrg */
14097a84e134Smrgstatic void
14107a84e134SmrgSetChildrenPrefSizes(PanedWidget pw, unsigned int off_size)
14117a84e134Smrg{
14127a84e134Smrg    Widget *childP;
14137a84e134Smrg    Boolean vert = IsVert(pw);
14147a84e134Smrg    XtWidgetGeometry request, reply;
14157a84e134Smrg
14167a84e134Smrg    ForAllPanes(pw, childP)
14177a84e134Smrg	if (pw->paned.resize_children_to_pref || PaneInfo(*childP)->size == 0 ||
14187a84e134Smrg	    PaneInfo(*childP)->resize_to_pref) {
14197a84e134Smrg	    if (PaneInfo(*childP)->preferred_size != PANED_ASK_CHILD)
14207a84e134Smrg		PaneInfo(*childP)->wp_size = PaneInfo(*childP)->preferred_size;
14217a84e134Smrg	    else {
14227a84e134Smrg		if(vert) {
14237a84e134Smrg		    request.request_mode = CWWidth;
14247a84e134Smrg		    request.width = off_size;
14257a84e134Smrg		}
14267a84e134Smrg		else {
14277a84e134Smrg		    request.request_mode = CWHeight;
14287a84e134Smrg		    request.height = off_size;
14297a84e134Smrg		}
14307a84e134Smrg
14317a84e134Smrg		if ((XtQueryGeometry(*childP, &request, &reply)
14327a84e134Smrg		     == XtGeometryAlmost)
14337a84e134Smrg		    && (reply.request_mode = (vert ? CWHeight : CWWidth)))
14347a84e134Smrg		    PaneInfo(*childP)->wp_size = GetRequestInfo(&reply, vert);
14357a84e134Smrg		else
14367a84e134Smrg		    PaneInfo(*childP)->wp_size = PaneSize(*childP, vert);
14377a84e134Smrg	    }
14387a84e134Smrg
14397a84e134Smrg	    PaneInfo(*childP)->size = PaneInfo(*childP)->wp_size;
14407a84e134Smrg	}
14417a84e134Smrg}
14427a84e134Smrg
14437a84e134Smrg/*
14447a84e134Smrg * Function:
14457a84e134Smrg *	ChangeAllGripCursors
14467a84e134Smrg *
14477a84e134Smrg * Parameters:
14487a84e134Smrg *	pw - paned widget
14497a84e134Smrg *
14507a84e134Smrg *	Description:
14517a84e134Smrg *	Changes all the grip cursors.
14527a84e134Smrg */
14537a84e134Smrgstatic void
14547a84e134SmrgChangeAllGripCursors(PanedWidget pw)
14557a84e134Smrg{
14567a84e134Smrg    Widget *childP;
14577a84e134Smrg
14587a84e134Smrg    ForAllPanes(pw, childP) {
14597a84e134Smrg	Arg arglist[1];
14607a84e134Smrg	Cursor cursor;
14617a84e134Smrg
14627a84e134Smrg	if ((cursor = pw->paned.grip_cursor) == None) {
14637a84e134Smrg	    if (IsVert(pw))
14647a84e134Smrg		cursor = pw->paned.v_grip_cursor;
14657a84e134Smrg	    else
14667a84e134Smrg		cursor = pw->paned.h_grip_cursor;
14677a84e134Smrg	}
14687a84e134Smrg
14697a84e134Smrg	if (HasGrip(*childP)) {
14707a84e134Smrg	    XtSetArg(arglist[0], XtNcursor, cursor);
14717a84e134Smrg	    XtSetValues(PaneInfo(*childP)->grip, arglist, 1);
14727a84e134Smrg	}
14737a84e134Smrg    }
14747a84e134Smrg}
14757a84e134Smrg
14767a84e134Smrg/*
14777a84e134Smrg * Function:
14787a84e134Smrg *	PushPaneStack
14797a84e134Smrg *
14807a84e134Smrg * Parameters:
14817a84e134Smrg *	pw   - paned widget
14827a84e134Smrg *	pane - pane that we are pushing
14837a84e134Smrg *
14847a84e134Smrg * Description:
14857a84e134Smrg *	Pushes a value onto the pane stack.
14867a84e134Smrg */
14877a84e134Smrgstatic void
14887a84e134SmrgPushPaneStack(PanedWidget pw, Pane pane)
14897a84e134Smrg{
14907a84e134Smrg    PaneStack *stack = (PaneStack *)XtMalloc(sizeof(PaneStack));
14917a84e134Smrg
14927a84e134Smrg    stack->next = pw->paned.stack;
14937a84e134Smrg    stack->pane = pane;
14947a84e134Smrg    stack->start_size = pane->size;
14957a84e134Smrg
14967a84e134Smrg    pw->paned.stack = stack;
14977a84e134Smrg}
14987a84e134Smrg
14997a84e134Smrg/*
15007a84e134Smrg * Function:
15017a84e134Smrg *	GetPaneStack
15027a84e134Smrg *
15037a84e134Smrg * Parameters:
15047a84e134Smrg *	pw - paned widget
15057a84e134Smrg *	shrink	   - True if we want to shrink this pane, False otherwise
15067a84e134Smrg *	pane	   - pane that we are popping (return)
15077a84e134Smrg *	start_size - size that this pane started at (return)
15087a84e134Smrg *
15097a84e134Smrg * Description:
15107a84e134Smrg *	Gets the top value from the pane stack.
15117a84e134Smrg */
15127a84e134Smrgstatic void
15137a84e134SmrgGetPaneStack(PanedWidget pw, Bool shrink, Pane *pane, int *start_size)
15147a84e134Smrg{
15157a84e134Smrg    if (pw->paned.stack == NULL) {
15167a84e134Smrg	*pane = NULL;
15177a84e134Smrg	return;
15187a84e134Smrg    }
15197a84e134Smrg
15207a84e134Smrg    *pane = pw->paned.stack->pane;
15217a84e134Smrg    *start_size = pw->paned.stack->start_size;
15227a84e134Smrg
15237a84e134Smrg    if (shrink != ((*pane)->size > *start_size))
15247a84e134Smrg	*pane = NULL;
15257a84e134Smrg}
15267a84e134Smrg
15277a84e134Smrg/*
15287a84e134Smrg * Function:
15297a84e134Smrg *	PopPaneStack
15307a84e134Smrg *
15317a84e134Smrg * Parameters:
15327a84e134Smrg *	pw - paned widget
15337a84e134Smrg *
15347a84e134Smrg * Description:
15357a84e134Smrg *	Pops the top item off the pane stack.
15367a84e134Smrg *
15377a84e134Smrg * Returns: True if this is not the last element on the stack
15387a84e134Smrg */
15397a84e134Smrgstatic Bool
15407a84e134SmrgPopPaneStack(PanedWidget pw)
15417a84e134Smrg{
15427a84e134Smrg    PaneStack *stack = pw->paned.stack;
15437a84e134Smrg
15447a84e134Smrg    if (stack == NULL)
15457a84e134Smrg	return (False);
15467a84e134Smrg
15477a84e134Smrg    pw->paned.stack = stack->next;
15487a84e134Smrg    XtFree((char *)stack);
15497a84e134Smrg
15507a84e134Smrg    if (pw->paned.stack == NULL)
15517a84e134Smrg	return (False);
15527a84e134Smrg
15537a84e134Smrg    return (True);
15547a84e134Smrg}
15557a84e134Smrg
15567a84e134Smrg/*
15577a84e134Smrg * Function:
15587a84e134Smrg *	ClearPaneStack
15597a84e134Smrg *
15607a84e134Smrg * Parameters:
15617a84e134Smrg *	pw - paned widget
15627a84e134Smrg *
15637a84e134Smrg * Description:
15647a84e134Smrg *	Removes all entries from the pane stack.
15657a84e134Smrg */
15667a84e134Smrgstatic void
15677a84e134SmrgClearPaneStack(PanedWidget pw)
15687a84e134Smrg{
15697a84e134Smrg    while(PopPaneStack(pw))
15707a84e134Smrg	;
15717a84e134Smrg}
15727a84e134Smrg
15737a84e134Smrgstatic void
15747a84e134SmrgXawPanedClassInitialize(void)
15757a84e134Smrg{
15767a84e134Smrg    XawInitializeWidgetSet();
15777a84e134Smrg    XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
15787a84e134Smrg		   NULL, 0);
15797a84e134Smrg    XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString,
15807a84e134Smrg		       NULL, 0, XtCacheNone, NULL);
15817a84e134Smrg}
15827a84e134Smrg
15837a84e134Smrg/* The Geometry Manager only allows changes after Realize if
15847a84e134Smrg * allow_resize is True in the constraints record.
15857a84e134Smrg *
15867a84e134Smrg * For vertically paned widgets:
15877a84e134Smrg *
15887a84e134Smrg * It only allows height changes, but offers the requested height
15897a84e134Smrg * as a compromise if both width and height changes were requested.
15907a84e134Smrg *
15917a84e134Smrg * For horizontal widgets the converse is true.
15927a84e134Smrg * As all good Geometry Managers should, we will return No if the
15937a84e134Smrg * request will have no effect; i.e. when the requestor is already
15947a84e134Smrg * of the desired geometry.
15957a84e134Smrg */
15967a84e134Smrgstatic XtGeometryResult
15977a84e134SmrgXawPanedGeometryManager(Widget w, XtWidgetGeometry *request,
15987a84e134Smrg			XtWidgetGeometry *reply)
15997a84e134Smrg{
16007a84e134Smrg    PanedWidget pw = (PanedWidget)XtParent(w);
16017a84e134Smrg    XtGeometryMask mask = request->request_mode;
16027a84e134Smrg    Dimension old_size, old_wpsize, old_paned_size;
16037a84e134Smrg    Pane pane = PaneInfo(w);
16047a84e134Smrg    Boolean vert = IsVert(pw);
16057a84e134Smrg    Dimension on_size, off_size;
16067a84e134Smrg    XtGeometryResult result;
16077a84e134Smrg    Boolean almost = False;
16087a84e134Smrg
16097a84e134Smrg    /*
16107a84e134Smrg     * If any of the following is true, disallow the geometry change
16117a84e134Smrg     *
16127a84e134Smrg     * o The paned widget is realized and allow_resize is false for the pane
16137a84e134Smrg     * o The child did not ask to change the on_size
16147a84e134Smrg     * o The request is not a width or height request
16157a84e134Smrg     * o The requested size is the same as the current size
16167a84e134Smrg     */
16177a84e134Smrg
16187a84e134Smrg    if ((XtIsRealized((Widget)pw) && !pane->allow_resize)
16197a84e134Smrg	|| !(mask & (vert ? CWHeight : CWWidth))
16207a84e134Smrg	||(mask & ~(CWWidth | CWHeight))
16217a84e134Smrg	|| GetRequestInfo(request, vert) ==  PaneSize(w, vert))
16227a84e134Smrg	return (XtGeometryNo);
16237a84e134Smrg
16247a84e134Smrg    old_paned_size = PaneSize((Widget)pw, vert);
16257a84e134Smrg    old_wpsize = pane->wp_size;
16267a84e134Smrg    old_size = pane->size;
16277a84e134Smrg
16287a84e134Smrg    pane->wp_size = pane->size = GetRequestInfo(request, vert);
16297a84e134Smrg
16307a84e134Smrg    AdjustPanedSize(pw, PaneSize((Widget)pw, !vert), &result, &on_size,
16317a84e134Smrg		    &off_size);
16327a84e134Smrg
16337a84e134Smrg    /*
16347a84e134Smrg     * Fool the Refigure Locations proc to thinking that we are
16357a84e134Smrg     * a different on_size
16367a84e134Smrg     */
16377a84e134Smrg
16387a84e134Smrg    if (result != XtGeometryNo) {
16397a84e134Smrg	if (vert)
16407a84e134Smrg	    XtHeight(pw) = on_size;
16417a84e134Smrg	else
16427a84e134Smrg	    XtWidth(pw) = on_size;
16437a84e134Smrg    }
16447a84e134Smrg
16457a84e134Smrg    RefigureLocations(pw, PaneIndex(w), AnyPane);
16467a84e134Smrg
16477a84e134Smrg    /*
16487a84e134Smrg     * Set up reply struct and reset core on_size
16497a84e134Smrg     */
16507a84e134Smrg    if (vert) {
16517a84e134Smrg	XtHeight(pw) = old_paned_size;
16527a84e134Smrg	reply->height = pane->size;
16537a84e134Smrg	reply->width = off_size;
16547a84e134Smrg    }
16557a84e134Smrg    else {
16567a84e134Smrg	XtWidth(pw) = old_paned_size;
16577a84e134Smrg	reply->height = off_size;
16587a84e134Smrg	reply->width = pane->size;
16597a84e134Smrg    }
16607a84e134Smrg
16617a84e134Smrg    /*
16627a84e134Smrg     * IF either of the following is true
16637a84e134Smrg     *
16647a84e134Smrg     * o There was a "off_size" request and the new "off_size" is different
16657a84e134Smrg     *   from that requested
16667a84e134Smrg     * o There was no "off_size" request and the new "off_size" is different
16677a84e134Smrg     *
16687a84e134Smrg     * o The "on_size" we will allow is different from that requested
16697a84e134Smrg     *
16707a84e134Smrg     * THEN: set almost
16717a84e134Smrg     */
16727a84e134Smrg    if (!((vert ? CWWidth : CWHeight) & mask)) {
16737a84e134Smrg	if (vert)
16747a84e134Smrg	    request->width = XtWidth(w);
16757a84e134Smrg	else
16767a84e134Smrg	    request->height = XtHeight(w);
16777a84e134Smrg    }
16787a84e134Smrg
16797a84e134Smrg    almost = GetRequestInfo(request, !vert) != GetRequestInfo(reply, !vert);
16807a84e134Smrg    almost |= (GetRequestInfo(request, vert) != GetRequestInfo(reply, vert));
16817a84e134Smrg
16827a84e134Smrg    if ((mask & XtCWQueryOnly) || almost) {
16837a84e134Smrg	pane->wp_size = old_wpsize;
16847a84e134Smrg	pane->size = old_size;
16857a84e134Smrg	RefigureLocations(pw, PaneIndex(w), AnyPane);
16867a84e134Smrg	reply->request_mode = CWWidth | CWHeight;
16877a84e134Smrg	if (almost)
16887a84e134Smrg	    return (XtGeometryAlmost);
16897a84e134Smrg    }
16907a84e134Smrg    else {
16917a84e134Smrg	AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), NULL, NULL, NULL);
16927a84e134Smrg	CommitNewLocations(pw);		/* layout already refigured */
16937a84e134Smrg    }
16947a84e134Smrg
16957a84e134Smrg    return (XtGeometryDone);
16967a84e134Smrg}
16977a84e134Smrg
16987a84e134Smrg/*ARGSUSED*/
16997a84e134Smrgstatic void
17007a84e134SmrgXawPanedInitialize(Widget request, Widget cnew,
17017a84e134Smrg		   ArgList args, Cardinal *num_args)
17027a84e134Smrg{
17037a84e134Smrg    PanedWidget pw = (PanedWidget)cnew;
17047a84e134Smrg
17057a84e134Smrg    GetGCs((Widget)pw);
17067a84e134Smrg
17077a84e134Smrg    pw->paned.recursively_called = False;
17087a84e134Smrg    pw->paned.stack = NULL;
17097a84e134Smrg    pw->paned.resize_children_to_pref = True;
17107a84e134Smrg    pw->paned.num_panes = 0;
17117a84e134Smrg}
17127a84e134Smrg
17137a84e134Smrgstatic void
17147a84e134SmrgXawPanedRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
17157a84e134Smrg{
17167a84e134Smrg    PanedWidget pw = (PanedWidget)w;
17177a84e134Smrg    Widget *childP;
17187a84e134Smrg
17197a84e134Smrg    if ((attributes->cursor = pw->paned.cursor) != None)
17207a84e134Smrg	*valueMask |= CWCursor;
17217a84e134Smrg
17227a84e134Smrg    (*SuperClass->core_class.realize)(w, valueMask, attributes);
17237a84e134Smrg
17247a84e134Smrg    /*
17257a84e134Smrg     * Before we commit the new locations we need to realize all the panes and
17267a84e134Smrg     * their grips
17277a84e134Smrg     */
17287a84e134Smrg    ForAllPanes(pw, childP) {
17297a84e134Smrg	XtRealizeWidget(*childP);
17307a84e134Smrg	if (HasGrip(*childP))
17317a84e134Smrg	    XtRealizeWidget(PaneInfo(*childP)->grip);
17327a84e134Smrg    }
17337a84e134Smrg
17347a84e134Smrg    RefigureLocationsAndCommit(w);
17357a84e134Smrg    pw->paned.resize_children_to_pref = False;
17367a84e134Smrg}
17377a84e134Smrg
17387a84e134Smrgstatic void
17397a84e134SmrgXawPanedDestroy(Widget w)
17407a84e134Smrg{
17417a84e134Smrg    ReleaseGCs(w);
17427a84e134Smrg}
17437a84e134Smrg
17447a84e134Smrgstatic void
17457a84e134SmrgReleaseGCs(Widget w)
17467a84e134Smrg{
17477a84e134Smrg    PanedWidget pw = (PanedWidget)w;
17487a84e134Smrg
17497a84e134Smrg    XtReleaseGC(w, pw->paned.normgc);
17507a84e134Smrg    XtReleaseGC(w, pw->paned.invgc);
17517a84e134Smrg    XtReleaseGC(w, pw->paned.flipgc);
17527a84e134Smrg}
17537a84e134Smrg
17547a84e134Smrgstatic void
17557a84e134SmrgXawPanedInsertChild(Widget w)
17567a84e134Smrg{
17577a84e134Smrg    Pane pane = PaneInfo(w);
17587a84e134Smrg
17597a84e134Smrg    /* insert the child widget in the composite children list with the
17607a84e134Smrg       superclass insert_child routine
17617a84e134Smrg     */
17627a84e134Smrg    (*SuperClass->composite_class.insert_child)(w);
17637a84e134Smrg
17647a84e134Smrg    if (!IsPane(w))
17657a84e134Smrg	return;
17667a84e134Smrg
17677a84e134Smrg    if (pane->show_grip == True) {
17687a84e134Smrg	CreateGrip(w);
17697a84e134Smrg	if (pane->min == PANED_GRIP_SIZE)
17707a84e134Smrg	    pane->min = PaneSize(pane->grip, IsVert((PanedWidget)XtParent(w)));
17717a84e134Smrg    }
17727a84e134Smrg    else {
17737a84e134Smrg	if (pane->min == PANED_GRIP_SIZE)
17747a84e134Smrg	    pane->min = 1;
17757a84e134Smrg	pane->grip = NULL;
17767a84e134Smrg    }
17777a84e134Smrg
17787a84e134Smrg    pane->size = 0;
17797a84e134Smrg    pane->paned_adjusted_me = False;
17807a84e134Smrg}
17817a84e134Smrg
17827a84e134Smrgstatic void
17837a84e134SmrgXawPanedDeleteChild(Widget w)
17847a84e134Smrg{
17857a84e134Smrg    /* remove the subwidget info and destroy the grip */
17867a84e134Smrg    if (IsPane(w) && HasGrip(w))
17877a84e134Smrg	XtDestroyWidget(PaneInfo(w)->grip);
17887a84e134Smrg
17897a84e134Smrg    /* delete the child widget in the composite children list with the
17907a84e134Smrg       superclass delete_child routine
17917a84e134Smrg     */
17927a84e134Smrg    (*SuperClass->composite_class.delete_child)(w);
17937a84e134Smrg}
17947a84e134Smrg
17957a84e134Smrgstatic void
17967a84e134SmrgXawPanedChangeManaged(Widget w)
17977a84e134Smrg{
17987a84e134Smrg    PanedWidget pw = (PanedWidget)w;
17997a84e134Smrg    Boolean vert = IsVert(pw);
18007a84e134Smrg    Dimension size;
18017a84e134Smrg    Widget *childP;
18027a84e134Smrg
18037a84e134Smrg    if (pw->paned.recursively_called++)
18047a84e134Smrg	return;
18057a84e134Smrg
18067a84e134Smrg    /*
18077a84e134Smrg     * If the size is zero then set it to the size of the widest or tallest pane
18087a84e134Smrg     */
18097a84e134Smrg
18107a84e134Smrg    if ((size = PaneSize((Widget)pw, !vert)) == 0) {
18117a84e134Smrg	size = 1;
18127a84e134Smrg	ForAllChildren(pw, childP)
18137a84e134Smrg	if (XtIsManaged(*childP) && (PaneSize(*childP, !vert) > size))
18147a84e134Smrg	    size = PaneSize(*childP, !vert);
18157a84e134Smrg    }
18167a84e134Smrg
18177a84e134Smrg    ManageAndUnmanageGrips(pw);
18187a84e134Smrg    pw->paned.recursively_called = False;
18197a84e134Smrg    ResortChildren(pw);
18207a84e134Smrg
18217a84e134Smrg    pw->paned.num_panes = 0;
18227a84e134Smrg    ForAllChildren(pw, childP)
18237a84e134Smrg	if (IsPane(*childP)) {
18247a84e134Smrg	    if (XtIsManaged(*childP)) {
18257a84e134Smrg		Pane pane = PaneInfo(*childP);
18267a84e134Smrg
18277a84e134Smrg		if (HasGrip(*childP))
18287a84e134Smrg		    PaneInfo(pane->grip)->position = pw->paned.num_panes;
18297a84e134Smrg		pane->position = pw->paned.num_panes; /* TEMPORY -CDP 3/89 */
18307a84e134Smrg		pw->paned.num_panes++;
18317a84e134Smrg	    }
18327a84e134Smrg	    else
18337a84e134Smrg		break; 		 /* This list is already sorted */
18347a84e134Smrg	}
18357a84e134Smrg
18367a84e134Smrg    SetChildrenPrefSizes((PanedWidget) w, size);
18377a84e134Smrg
18387a84e134Smrg    /*
18397a84e134Smrg     * ForAllPanes can now be used
18407a84e134Smrg     */
18417a84e134Smrg    if (PaneSize((Widget) pw, vert) == 0)
18427a84e134Smrg	AdjustPanedSize(pw, size, NULL, NULL, NULL);
18437a84e134Smrg
18447a84e134Smrg    if (XtIsRealized((Widget)pw))
18457a84e134Smrg	RefigureLocationsAndCommit((Widget)pw);
18467a84e134Smrg}
18477a84e134Smrg
18487a84e134Smrgstatic void
18497a84e134SmrgXawPanedResize(Widget w)
18507a84e134Smrg{
18517a84e134Smrg    SetChildrenPrefSizes((PanedWidget)w,
18527a84e134Smrg			 PaneSize(w, !IsVert((PanedWidget)w)));
18537a84e134Smrg    RefigureLocationsAndCommit(w);
18547a84e134Smrg}
18557a84e134Smrg
18567a84e134Smrg/*ARGSUSED*/
18577a84e134Smrgstatic void
18587a84e134SmrgXawPanedRedisplay(Widget w, XEvent *event, Region region)
18597a84e134Smrg{
18607a84e134Smrg    DrawInternalBorders((PanedWidget)w);
18617a84e134Smrg}
18627a84e134Smrg
18637a84e134Smrg/*ARGSUSED*/
18647a84e134Smrgstatic Boolean
18657a84e134SmrgXawPanedSetValues(Widget old, Widget request, Widget cnew,
18667a84e134Smrg		  ArgList args, Cardinal *num_args)
18677a84e134Smrg{
18687a84e134Smrg    PanedWidget old_pw = (PanedWidget)old;
18697a84e134Smrg    PanedWidget new_pw = (PanedWidget)cnew;
18707a84e134Smrg    Boolean redisplay = False;
18717a84e134Smrg
18727a84e134Smrg    if ((old_pw->paned.cursor != new_pw->paned.cursor) && XtIsRealized(cnew))
18737a84e134Smrg	XDefineCursor(XtDisplay(cnew), XtWindow(cnew), new_pw->paned.cursor);
18747a84e134Smrg
18757a84e134Smrg    if (old_pw->paned.internal_bp != new_pw->paned.internal_bp ||
18767a84e134Smrg	old_pw->core.background_pixel != new_pw->core.background_pixel) {
18777a84e134Smrg	ReleaseGCs(old);
18787a84e134Smrg	GetGCs(cnew);
18797a84e134Smrg	redisplay = True;
18807a84e134Smrg    }
18817a84e134Smrg
18827a84e134Smrg    if (old_pw->paned.grip_cursor != new_pw->paned.grip_cursor ||
18837a84e134Smrg	old_pw->paned.v_grip_cursor != new_pw->paned.v_grip_cursor ||
18847a84e134Smrg	old_pw->paned.h_grip_cursor != new_pw->paned.h_grip_cursor)
18857a84e134Smrg	ChangeAllGripCursors(new_pw);
18867a84e134Smrg
18877a84e134Smrg    if (IsVert(old_pw) != IsVert(new_pw)) {
18887a84e134Smrg	/*
18897a84e134Smrg	 * We are fooling the paned widget into thinking that is needs to
18907a84e134Smrg	 * fully refigure everything, which is what we want
18917a84e134Smrg	 */
18927a84e134Smrg	if (IsVert(new_pw))
18937a84e134Smrg	    XtWidth(new_pw) = 0;
18947a84e134Smrg	else
18957a84e134Smrg	    XtHeight(new_pw) = 0;
18967a84e134Smrg
18977a84e134Smrg	new_pw->paned.resize_children_to_pref = True;
18987a84e134Smrg	XawPanedChangeManaged(cnew); /* Seems weird, but does the right thing */
18997a84e134Smrg	new_pw->paned.resize_children_to_pref = False;
19007a84e134Smrg	if (new_pw->paned.grip_cursor == None)
19017a84e134Smrg	    ChangeAllGripCursors(new_pw);
19027a84e134Smrg	return (True);
19037a84e134Smrg    }
19047a84e134Smrg
19057a84e134Smrg    if (old_pw->paned.internal_bw != new_pw->paned.internal_bw) {
19067a84e134Smrg	AdjustPanedSize(new_pw, PaneSize(cnew, !IsVert(old_pw)),
19077a84e134Smrg		        NULL, NULL, NULL);
19087a84e134Smrg	RefigureLocationsAndCommit(cnew);
19097a84e134Smrg	return (True);		/* We have done a full configuration, return */
19107a84e134Smrg    }
19117a84e134Smrg
19127a84e134Smrg    if (old_pw->paned.grip_indent != new_pw->paned.grip_indent &&
19137a84e134Smrg	XtIsRealized(cnew)) {
19147a84e134Smrg	CommitNewLocations(new_pw);
19157a84e134Smrg	redisplay = True;
19167a84e134Smrg    }
19177a84e134Smrg
19187a84e134Smrg    return (redisplay);
19197a84e134Smrg}
19207a84e134Smrg
19217a84e134Smrg/*ARGSUSED*/
19227a84e134Smrgstatic Boolean
19237a84e134SmrgXawPanedPaneSetValues(Widget old, Widget request, Widget cnew,
19247a84e134Smrg		      ArgList args, Cardinal *num_args)
19257a84e134Smrg{
19267a84e134Smrg    Pane old_pane = PaneInfo(old);
19277a84e134Smrg    Pane new_pane = PaneInfo(cnew);
19287a84e134Smrg    Boolean redisplay = False;
19297a84e134Smrg
19307a84e134Smrg    /* Check for new min and max */
19317a84e134Smrg    if (old_pane->min != new_pane->min || old_pane->max != new_pane->max)
19327a84e134Smrg	XawPanedSetMinMax(cnew, (int)new_pane->min, (int)new_pane->max);
19337a84e134Smrg
19347a84e134Smrg    /* Check for change in XtNshowGrip */
19357a84e134Smrg    if (old_pane->show_grip != new_pane->show_grip) {
19367a84e134Smrg	if (new_pane->show_grip == True) {
19377a84e134Smrg	    CreateGrip(cnew);
19387a84e134Smrg	    if (XtIsRealized(XtParent(cnew))) {
19397a84e134Smrg		if (XtIsManaged(cnew))	/* if paned is unrealized this will
19407a84e134Smrg					   happen automatically at realize time
19417a84e134Smrg					 */
19427a84e134Smrg		    XtManageChild(PaneInfo(cnew)->grip);	/* manage the grip */
19437a84e134Smrg		XtRealizeWidget(PaneInfo(cnew)->grip); /* realize the grip */
19447a84e134Smrg		CommitNewLocations((PanedWidget)XtParent(cnew));
19457a84e134Smrg	    }
19467a84e134Smrg	}
19477a84e134Smrg	else if (HasGrip(old)) {
19487a84e134Smrg	    XtDestroyWidget(old_pane->grip);
19497a84e134Smrg	    new_pane->grip = NULL;
19507a84e134Smrg	    redisplay = True;
19517a84e134Smrg	}
19527a84e134Smrg    }
19537a84e134Smrg
19547a84e134Smrg    return (redisplay);
19557a84e134Smrg}
19567a84e134Smrg
19577a84e134Smrg/*
19587a84e134Smrg * Public routines
19597a84e134Smrg */
19607a84e134Smrg/*
19617a84e134Smrg * Function:
19627a84e134Smrg *	XawPanedSetMinMax
19637a84e134Smrg *
19647a84e134Smrg * Parameters:
19657a84e134Smrg *	widget - widget that is a child of the Paned widget
19667a84e134Smrg *	min    - new min and max size for the pane
19677a84e134Smrg *	max    - ""
19687a84e134Smrg *
19697a84e134Smrg * Description:
19707a84e134Smrg *	Sets the min and max size for a pane.
19717a84e134Smrg */
19727a84e134Smrgvoid
19737a84e134SmrgXawPanedSetMinMax(Widget widget, int min, int max)
19747a84e134Smrg{
19757a84e134Smrg    Pane pane = PaneInfo(widget);
19767a84e134Smrg
19777a84e134Smrg    pane->min = min;
19787a84e134Smrg    pane->max = max;
19797a84e134Smrg    RefigureLocationsAndCommit(widget->core.parent);
19807a84e134Smrg}
19817a84e134Smrg
19827a84e134Smrg/*
19837a84e134Smrg * Function:
19847a84e134Smrg *	XawPanedGetMinMax
19857a84e134Smrg *
19867a84e134Smrg * Parameters:
19877a84e134Smrg *	widget - widget that is a child of the Paned widget
19887a84e134Smrg *	min    - current min and max size for the pane (return)
19897a84e134Smrg *	max    - ""
19907a84e134Smrg *
19917a84e134Smrg * Description:
19927a84e134Smrg *	Gets the min and max size for a pane.
19937a84e134Smrg */
19947a84e134Smrgvoid
19957a84e134SmrgXawPanedGetMinMax(Widget widget, int *min, int *max)
19967a84e134Smrg{
19977a84e134Smrg    Pane pane = PaneInfo(widget);
19987a84e134Smrg
19997a84e134Smrg    *min = pane->min;
20007a84e134Smrg    *max = pane->max;
20017a84e134Smrg}
20027a84e134Smrg
20037a84e134Smrg/*
20047a84e134Smrg * Function:
20057a84e134Smrg *	XawPanedSetRefigureMode
20067a84e134Smrg *
20077a84e134Smrg * Parameters:
20087a84e134Smrg *	w    - paned widget
20097a84e134Smrg *	mode - if False then inhibit refigure
20107a84e134Smrg *
20117a84e134Smrg * Description:
20127a84e134Smrg *	Allows a flag to be set the will inhibit
20137a84e134Smrg *		   the paned widgets relayout routine.
20147a84e134Smrg */
20157a84e134Smrgvoid
20167a84e134SmrgXawPanedSetRefigureMode(Widget w,
20177a84e134Smrg#if NeedWidePrototypes
20187a84e134Smrg	int mode
20197a84e134Smrg#else
20207a84e134Smrg	Boolean mode
20217a84e134Smrg#endif
20227a84e134Smrg)
20237a84e134Smrg{
20247a84e134Smrg    ((PanedWidget)w)->paned.refiguremode = mode;
20257a84e134Smrg    RefigureLocationsAndCommit(w);
20267a84e134Smrg}
20277a84e134Smrg
20287a84e134Smrg/*
20297a84e134Smrg * Function:
20307a84e134Smrg *	XawPanedGetNumSub
20317a84e134Smrg *
20327a84e134Smrg * Parameters:
20337a84e134Smrg *	w - paned widget
20347a84e134Smrg *
20357a84e134Smrg * Description:
20367a84e134Smrg *	Returns the number of panes in the paned widget.
20377a84e134Smrg * Returns:
20387a84e134Smrg *	the number of panes in the paned widget
20397a84e134Smrg */
20407a84e134Smrgint
20417a84e134SmrgXawPanedGetNumSub(Widget w)
20427a84e134Smrg{
20437a84e134Smrg    return (((PanedWidget)w)->paned.num_panes);
20447a84e134Smrg}
20457a84e134Smrg
20467a84e134Smrg/*
20477a84e134Smrg * Function:
20487a84e134Smrg *	XawPanedAllowResize
20497a84e134Smrg *
20507a84e134Smrg * Parameters:
20517a84e134Smrg *	widget - child of the paned widget
20527a84e134Smrg *
20537a84e134Smrg * Description:
20547a84e134Smrg *	  Allows a flag to be set that determines if the paned
20557a84e134Smrg *	widget will allow geometry requests from this child.
20567a84e134Smrg */
20577a84e134Smrgvoid
20587a84e134SmrgXawPanedAllowResize(Widget widget,
20597a84e134Smrg#if NeedWidePrototypes
20607a84e134Smrg	int allow_resize
20617a84e134Smrg#else
20627a84e134Smrg	Boolean allow_resize
20637a84e134Smrg#endif
20647a84e134Smrg)
20657a84e134Smrg{
20667a84e134Smrg    PaneInfo(widget)->allow_resize = allow_resize;
20677a84e134Smrg}
2068