Viewport.c revision 7a84e134
17a84e134Smrg/* $Xorg: Viewport.c,v 1.4 2001/02/09 02:03:47 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/Viewport.c,v 1.10 2001/08/23 00:03:20 dawes Exp $ */
507a84e134Smrg
517a84e134Smrg#ifdef HAVE_CONFIG_H
527a84e134Smrg#include <config.h>
537a84e134Smrg#endif
547a84e134Smrg#include <X11/IntrinsicP.h>
557a84e134Smrg#include <X11/StringDefs.h>
567a84e134Smrg#include <X11/Xmu/Misc.h>
577a84e134Smrg#include <X11/Xaw/Scrollbar.h>
587a84e134Smrg#include <X11/Xaw/ViewportP.h>
597a84e134Smrg#include <X11/Xaw/XawInit.h>
607a84e134Smrg#include "Private.h"
617a84e134Smrg
627a84e134Smrg/*
637a84e134Smrg * Class Methods
647a84e134Smrg */
657a84e134Smrgstatic Boolean Layout(FormWidget, unsigned int, unsigned int, Bool);
667a84e134Smrgstatic void XawViewportChangeManaged(Widget);
677a84e134Smrgstatic void XawViewportInitialize(Widget, Widget, ArgList, Cardinal*);
687a84e134Smrgstatic void
697a84e134SmrgXawViewportConstraintInitialize(Widget, Widget, ArgList, Cardinal*);
707a84e134Smrgstatic XtGeometryResult XawViewportGeometryManager(Widget, XtWidgetGeometry*,
717a84e134Smrg						   XtWidgetGeometry*);
727a84e134Smrgstatic XtGeometryResult XawViewportQueryGeometry(Widget,
737a84e134Smrg						 XtWidgetGeometry*,
747a84e134Smrg						 XtWidgetGeometry*);
757a84e134Smrgstatic void XawViewportRealize(Widget, XtValueMask*, XSetWindowAttributes*);
767a84e134Smrgstatic void XawViewportResize(Widget);
777a84e134Smrgstatic Boolean XawViewportSetValues(Widget, Widget, Widget,
787a84e134Smrg				    ArgList, Cardinal*);
797a84e134Smrg
807a84e134Smrg/*
817a84e134Smrg * Prototypes
827a84e134Smrg */
837a84e134Smrgstatic void ComputeLayout(Widget, Bool, Bool);
847a84e134Smrgstatic void ComputeWithForceBars(Widget, Bool, XtWidgetGeometry*,
857a84e134Smrg				 int*, int*);
867a84e134Smrgstatic Widget CreateScrollbar(ViewportWidget, Bool);
877a84e134Smrgstatic XtGeometryResult GeometryRequestPlusScrollbar(ViewportWidget, Bool,
887a84e134Smrg						     XtWidgetGeometry*,
897a84e134Smrg						     XtWidgetGeometry*);
907a84e134Smrgstatic Bool GetGeometry(Widget, unsigned int, unsigned int);
917a84e134Smrgstatic void MoveChild(ViewportWidget, int, int);
927a84e134Smrgstatic XtGeometryResult QueryGeometry(ViewportWidget, XtWidgetGeometry*,
937a84e134Smrg				      XtWidgetGeometry*);
947a84e134Smrgstatic void RedrawThumbs(ViewportWidget);
957a84e134Smrgstatic void ScrollUpDownProc(Widget, XtPointer, XtPointer);
967a84e134Smrgstatic void SendReport(ViewportWidget, unsigned int);
977a84e134Smrgstatic void SetBar(Widget, int, unsigned int, unsigned int);
987a84e134Smrgstatic XtGeometryResult TestSmaller(ViewportWidget, XtWidgetGeometry*,
997a84e134Smrg				    XtWidgetGeometry*);
1007a84e134Smrgstatic void ThumbProc(Widget, XtPointer, XtPointer);
1017a84e134Smrg
1027a84e134Smrg/*
1037a84e134Smrg * Initialization
1047a84e134Smrg */
1057a84e134Smrg#define offset(field) XtOffsetOf(ViewportRec, viewport.field)
1067a84e134Smrgstatic XtResource resources[] = {
1077a84e134Smrg  {
1087a84e134Smrg    XtNforceBars,
1097a84e134Smrg    XtCBoolean,
1107a84e134Smrg    XtRBoolean,
1117a84e134Smrg    sizeof(Boolean),
1127a84e134Smrg    offset(forcebars),
1137a84e134Smrg    XtRImmediate,
1147a84e134Smrg    (XtPointer)False
1157a84e134Smrg  },
1167a84e134Smrg  {
1177a84e134Smrg    XtNallowHoriz,
1187a84e134Smrg    XtCBoolean,
1197a84e134Smrg    XtRBoolean,
1207a84e134Smrg    sizeof(Boolean),
1217a84e134Smrg    offset(allowhoriz),
1227a84e134Smrg    XtRImmediate,
1237a84e134Smrg    (XtPointer)False
1247a84e134Smrg  },
1257a84e134Smrg  {
1267a84e134Smrg    XtNallowVert,
1277a84e134Smrg    XtCBoolean,
1287a84e134Smrg    XtRBoolean,
1297a84e134Smrg    sizeof(Boolean),
1307a84e134Smrg    offset(allowvert),
1317a84e134Smrg    XtRImmediate,
1327a84e134Smrg    (XtPointer)False
1337a84e134Smrg  },
1347a84e134Smrg  {
1357a84e134Smrg    XtNuseBottom,
1367a84e134Smrg    XtCBoolean,
1377a84e134Smrg    XtRBoolean,
1387a84e134Smrg    sizeof(Boolean),
1397a84e134Smrg    offset(usebottom),
1407a84e134Smrg    XtRImmediate,
1417a84e134Smrg    (XtPointer)False
1427a84e134Smrg  },
1437a84e134Smrg  {
1447a84e134Smrg    XtNuseRight,
1457a84e134Smrg    XtCBoolean,
1467a84e134Smrg    XtRBoolean,
1477a84e134Smrg    sizeof(Boolean),
1487a84e134Smrg    offset(useright),
1497a84e134Smrg    XtRImmediate,
1507a84e134Smrg    (XtPointer)False
1517a84e134Smrg  },
1527a84e134Smrg  {
1537a84e134Smrg    XtNreportCallback,
1547a84e134Smrg    XtCReportCallback,
1557a84e134Smrg    XtRCallback,
1567a84e134Smrg    sizeof(XtPointer),
1577a84e134Smrg    offset(report_callbacks),
1587a84e134Smrg    XtRImmediate,
1597a84e134Smrg    NULL
1607a84e134Smrg  },
1617a84e134Smrg};
1627a84e134Smrg#undef offset
1637a84e134Smrg
1647a84e134Smrg#define Superclass	(&formClassRec)
1657a84e134SmrgViewportClassRec viewportClassRec = {
1667a84e134Smrg  /* core */
1677a84e134Smrg  {
1687a84e134Smrg    (WidgetClass)Superclass,		/* superclass */
1697a84e134Smrg    "Viewport",				/* class_name */
1707a84e134Smrg    sizeof(ViewportRec),		/* widget_size */
1717a84e134Smrg    XawInitializeWidgetSet,		/* class_initialize */
1727a84e134Smrg    NULL,				/* class_part_init */
1737a84e134Smrg    False,				/* class_inited */
1747a84e134Smrg    XawViewportInitialize,		/* initialize */
1757a84e134Smrg    NULL,				/* initialize_hook */
1767a84e134Smrg    XawViewportRealize,			/* realize */
1777a84e134Smrg    NULL,				/* actions */
1787a84e134Smrg    0,					/* num_actions */
1797a84e134Smrg    resources,				/* resources */
1807a84e134Smrg    XtNumber(resources),		/* num_resources */
1817a84e134Smrg    NULLQUARK,				/* xrm_class */
1827a84e134Smrg    True,				/* compress_motion */
1837a84e134Smrg    True,				/* compress_exposure */
1847a84e134Smrg    True,				/* compress_enterleave */
1857a84e134Smrg    False,				/* visible_interest */
1867a84e134Smrg    NULL,				/* destroy */
1877a84e134Smrg    XawViewportResize,			/* resize */
1887a84e134Smrg    XtInheritExpose,			/* expose */
1897a84e134Smrg    XawViewportSetValues,		/* set_values */
1907a84e134Smrg    NULL,				/* set_values_hook */
1917a84e134Smrg    XtInheritSetValuesAlmost,		/* set_values_almost */
1927a84e134Smrg    NULL,				/* get_values_hook */
1937a84e134Smrg    NULL,				/* accept_focus */
1947a84e134Smrg    XtVersion,				/* version */
1957a84e134Smrg    NULL,				/* callback_private */
1967a84e134Smrg    NULL,				/* tm_table */
1977a84e134Smrg    XawViewportQueryGeometry,		/* query_geometry */
1987a84e134Smrg    XtInheritDisplayAccelerator,	/* display_accelerator */
1997a84e134Smrg    NULL,				/* extension */
2007a84e134Smrg  },
2017a84e134Smrg  /* composite */
2027a84e134Smrg  {
2037a84e134Smrg    XawViewportGeometryManager,		/* geometry_manager */
2047a84e134Smrg    XawViewportChangeManaged,		/* change_managed */
2057a84e134Smrg    XtInheritInsertChild,		/* insert_child */
2067a84e134Smrg    XtInheritDeleteChild,		/* delete_child */
2077a84e134Smrg    NULL,				/* extension */
2087a84e134Smrg  },
2097a84e134Smrg  /* constraint */
2107a84e134Smrg  {
2117a84e134Smrg    NULL,				/* subresourses */
2127a84e134Smrg    0,					/* subresource_count */
2137a84e134Smrg    sizeof(ViewportConstraintsRec),	/* constraint_size */
2147a84e134Smrg    XawViewportConstraintInitialize,	/* initialize */
2157a84e134Smrg    NULL,				/* destroy */
2167a84e134Smrg    NULL,				/* set_values */
2177a84e134Smrg    NULL,				/* extension */
2187a84e134Smrg  },
2197a84e134Smrg  /* form */
2207a84e134Smrg  {
2217a84e134Smrg    Layout,				/* layout */
2227a84e134Smrg  },
2237a84e134Smrg  /* viewport */
2247a84e134Smrg  {
2257a84e134Smrg    NULL,				/* extension */
2267a84e134Smrg  },
2277a84e134Smrg};
2287a84e134Smrg
2297a84e134SmrgWidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec;
2307a84e134Smrg
2317a84e134Smrg/*
2327a84e134Smrg * Implementation
2337a84e134Smrg */
2347a84e134Smrgstatic Widget
2357a84e134SmrgCreateScrollbar(ViewportWidget w, Bool horizontal)
2367a84e134Smrg{
2377a84e134Smrg    static Arg barArgs[] = {
2387a84e134Smrg	{XtNorientation,	    0},
2397a84e134Smrg	{XtNlength,		    0},
2407a84e134Smrg	{XtNleft,		    0},
2417a84e134Smrg	{XtNright,		    0},
2427a84e134Smrg	{XtNtop,		    0},
2437a84e134Smrg	{XtNbottom,		    0},
2447a84e134Smrg	{XtNmappedWhenManaged,	    False},
2457a84e134Smrg    };
2467a84e134Smrg    Widget clip = w->viewport.clip;
2477a84e134Smrg    ViewportConstraints constraints =
2487a84e134Smrg	(ViewportConstraints)clip->core.constraints;
2497a84e134Smrg    Widget bar;
2507a84e134Smrg
2517a84e134Smrg    XtSetArg(barArgs[0], XtNorientation,
2527a84e134Smrg	   horizontal ? XtorientHorizontal : XtorientVertical);
2537a84e134Smrg    XtSetArg(barArgs[1], XtNlength,
2547a84e134Smrg	   horizontal ? XtWidth(clip) : XtHeight(clip));
2557a84e134Smrg    XtSetArg(barArgs[2], XtNleft,
2567a84e134Smrg	   !horizontal && w->viewport.useright ? XtChainRight : XtChainLeft);
2577a84e134Smrg    XtSetArg(barArgs[3], XtNright,
2587a84e134Smrg	   !horizontal && !w->viewport.useright ? XtChainLeft : XtChainRight);
2597a84e134Smrg    XtSetArg(barArgs[4], XtNtop,
2607a84e134Smrg	   horizontal && w->viewport.usebottom ? XtChainBottom: XtChainTop);
2617a84e134Smrg    XtSetArg(barArgs[5], XtNbottom,
2627a84e134Smrg	   horizontal && !w->viewport.usebottom ? XtChainTop: XtChainBottom);
2637a84e134Smrg
2647a84e134Smrg    bar = XtCreateWidget(horizontal ? "horizontal" : "vertical",
2657a84e134Smrg			 scrollbarWidgetClass, (Widget)w,
2667a84e134Smrg			 barArgs, XtNumber(barArgs));
2677a84e134Smrg    XtAddCallback(bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w);
2687a84e134Smrg    XtAddCallback(bar, XtNjumpProc, ThumbProc, (XtPointer)w);
2697a84e134Smrg
2707a84e134Smrg    if (horizontal) {
2717a84e134Smrg	w->viewport.horiz_bar = bar;
2727a84e134Smrg	constraints->form.vert_base = bar;
2737a84e134Smrg    }
2747a84e134Smrg    else {
2757a84e134Smrg	w->viewport.vert_bar = bar;
2767a84e134Smrg	constraints->form.horiz_base = bar;
2777a84e134Smrg    }
2787a84e134Smrg
2797a84e134Smrg    XtManageChild(bar);
2807a84e134Smrg
2817a84e134Smrg    return (bar);
2827a84e134Smrg}
2837a84e134Smrg
2847a84e134Smrg/*ARGSUSED*/
2857a84e134Smrgstatic void
2867a84e134SmrgXawViewportInitialize(Widget request, Widget cnew,
2877a84e134Smrg		      ArgList args, Cardinal *num_args)
2887a84e134Smrg{
2897a84e134Smrg    ViewportWidget w = (ViewportWidget)cnew;
2907a84e134Smrg    static Arg clip_args[8];
2917a84e134Smrg    Cardinal arg_cnt;
2927a84e134Smrg    Widget h_bar, v_bar;
2937a84e134Smrg    Dimension clip_height, clip_width;
2947a84e134Smrg
2957a84e134Smrg    w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */
2967a84e134Smrg
2977a84e134Smrg    /*
2987a84e134Smrg     * Initialize all widget pointers to NULL
2997a84e134Smrg     */
3007a84e134Smrg    w->viewport.child = NULL;
3017a84e134Smrg    w->viewport.horiz_bar = w->viewport.vert_bar = NULL;
3027a84e134Smrg
3037a84e134Smrg    /*
3047a84e134Smrg     * Create Clip Widget
3057a84e134Smrg     */
3067a84e134Smrg    arg_cnt = 0;
3077a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None);	arg_cnt++;
3087a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0);		arg_cnt++;
3097a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft);		arg_cnt++;
3107a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight);	arg_cnt++;
3117a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop);		arg_cnt++;
3127a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom);	arg_cnt++;
3137a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w));		arg_cnt++;
3147a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w));	arg_cnt++;
3157a84e134Smrg
3167a84e134Smrg    w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew,
3177a84e134Smrg					     clip_args, arg_cnt);
3187a84e134Smrg
3197a84e134Smrg    if (!w->viewport.forcebars)
3207a84e134Smrg	return;		 /* If we are not forcing the bars then we are done */
3217a84e134Smrg
3227a84e134Smrg    if (w->viewport.allowhoriz)
3237a84e134Smrg	(void)CreateScrollbar(w, True);
3247a84e134Smrg    if (w->viewport.allowvert)
3257a84e134Smrg	(void)CreateScrollbar(w, False);
3267a84e134Smrg
3277a84e134Smrg    h_bar = w->viewport.horiz_bar;
3287a84e134Smrg    v_bar = w->viewport.vert_bar;
3297a84e134Smrg
3307a84e134Smrg    /*
3317a84e134Smrg     * Set the clip widget to the correct height
3327a84e134Smrg     */
3337a84e134Smrg    clip_width = XtWidth(w);
3347a84e134Smrg    clip_height = XtHeight(w);
3357a84e134Smrg
3367a84e134Smrg    if (h_bar != NULL &&  XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar))
3377a84e134Smrg	clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar);
3387a84e134Smrg
3397a84e134Smrg    if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar))
3407a84e134Smrg	clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar);
3417a84e134Smrg
3427a84e134Smrg    arg_cnt = 0;
3437a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++;
3447a84e134Smrg    XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++;
3457a84e134Smrg    XtSetValues(w->viewport.clip, clip_args, arg_cnt);
3467a84e134Smrg}
3477a84e134Smrg
3487a84e134Smrg/*ARGSUSED*/
3497a84e134Smrgstatic void
3507a84e134SmrgXawViewportConstraintInitialize(Widget request, Widget cnew,
3517a84e134Smrg				ArgList args, Cardinal *num_args)
3527a84e134Smrg{
3537a84e134Smrg    ((ViewportConstraints)cnew->core.constraints)->viewport.reparented = False;
3547a84e134Smrg}
3557a84e134Smrg
3567a84e134Smrgstatic void
3577a84e134SmrgXawViewportRealize(Widget widget, XtValueMask *value_mask,
3587a84e134Smrg		   XSetWindowAttributes *attributes)
3597a84e134Smrg{
3607a84e134Smrg    ViewportWidget w = (ViewportWidget)widget;
3617a84e134Smrg    Widget child = w->viewport.child;
3627a84e134Smrg    Widget clip = w->viewport.clip;
3637a84e134Smrg
3647a84e134Smrg    *value_mask |= CWBitGravity;
3657a84e134Smrg    attributes->bit_gravity = NorthWestGravity;
3667a84e134Smrg    (*Superclass->core_class.realize)(widget, value_mask, attributes);
3677a84e134Smrg
3687a84e134Smrg    (*w->core.widget_class->core_class.resize)(widget);	/* turn on bars */
3697a84e134Smrg
3707a84e134Smrg    if (child != NULL) {
3717a84e134Smrg	XtMoveWidget(child, 0, 0);
3727a84e134Smrg	XtRealizeWidget(clip);
3737a84e134Smrg	XtRealizeWidget(child);
3747a84e134Smrg	XReparentWindow(XtDisplay(w), XtWindow(child), XtWindow(clip), 0, 0);
3757a84e134Smrg	XtMapWidget(child);
3767a84e134Smrg    }
3777a84e134Smrg}
3787a84e134Smrg
3797a84e134Smrg/*ARGSUSED*/
3807a84e134Smrgstatic Boolean
3817a84e134SmrgXawViewportSetValues(Widget current, Widget request, Widget cnew,
3827a84e134Smrg		     ArgList args, Cardinal *num_args)
3837a84e134Smrg{
3847a84e134Smrg    ViewportWidget w = (ViewportWidget)cnew;
3857a84e134Smrg    ViewportWidget cw = (ViewportWidget)current;
3867a84e134Smrg
3877a84e134Smrg    if (w->viewport.forcebars != cw->viewport.forcebars
3887a84e134Smrg	|| w->viewport.allowvert != cw->viewport.allowvert
3897a84e134Smrg	|| w->viewport.allowhoriz != cw->viewport.allowhoriz
3907a84e134Smrg	|| w->viewport.useright != cw->viewport.useright
3917a84e134Smrg	|| w->viewport.usebottom != cw->viewport.usebottom)
3927a84e134Smrg	(*w->core.widget_class->core_class.resize)(cnew); /* Recompute layout */
3937a84e134Smrg
3947a84e134Smrg    return (False);
3957a84e134Smrg}
3967a84e134Smrg
3977a84e134Smrgstatic void
3987a84e134SmrgXawViewportChangeManaged(Widget widget)
3997a84e134Smrg{
4007a84e134Smrg    ViewportWidget w = (ViewportWidget)widget;
4017a84e134Smrg    int num_children = w->composite.num_children;
4027a84e134Smrg    Widget child, *childP;
4037a84e134Smrg    int i;
4047a84e134Smrg
4057a84e134Smrg    child = NULL;
4067a84e134Smrg    for (childP = w->composite.children,
4077a84e134Smrg	 i = 0; i < num_children;
4087a84e134Smrg	 childP++, i++) {
4097a84e134Smrg	if (XtIsManaged(*childP)
4107a84e134Smrg	    && *childP != w->viewport.clip
4117a84e134Smrg	    && *childP != w->viewport.horiz_bar
4127a84e134Smrg	    && *childP != w->viewport.vert_bar)	{
4137a84e134Smrg	    child = *childP;
4147a84e134Smrg	    break;
4157a84e134Smrg	}
4167a84e134Smrg    }
4177a84e134Smrg
4187a84e134Smrg    if (child != w->viewport.child) {
4197a84e134Smrg	w->viewport.child = child;
4207a84e134Smrg	if (child != NULL) {
4217a84e134Smrg	    XtResizeWidget(child, XtWidth(child), XtHeight(child), 0);
4227a84e134Smrg	    if (XtIsRealized(widget)) {
4237a84e134Smrg		ViewportConstraints constraints =
4247a84e134Smrg		    (ViewportConstraints)child->core.constraints;
4257a84e134Smrg		if (!XtIsRealized(child)) {
4267a84e134Smrg		    Window window = XtWindow(w);
4277a84e134Smrg
4287a84e134Smrg		    XtMoveWidget(child, 0, 0);
4297a84e134Smrg		    w->core.window = XtWindow(w->viewport.clip);
4307a84e134Smrg		    XtRealizeWidget(child);
4317a84e134Smrg		    w->core.window = window;
4327a84e134Smrg		    constraints->viewport.reparented = True;
4337a84e134Smrg		}
4347a84e134Smrg		else if (!constraints->viewport.reparented) {
4357a84e134Smrg		    XReparentWindow(XtDisplay(w), XtWindow(child),
4367a84e134Smrg				    XtWindow(w->viewport.clip), 0, 0);
4377a84e134Smrg		    constraints->viewport.reparented = True;
4387a84e134Smrg		    if (child->core.mapped_when_managed)
4397a84e134Smrg		    XtMapWidget(child);
4407a84e134Smrg		}
4417a84e134Smrg	    }
4427a84e134Smrg	    GetGeometry(widget, XtWidth(child), XtHeight(child));
4437a84e134Smrg	    (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout)
4447a84e134Smrg	    ((FormWidget)w, XtWidth(w), XtHeight(w), True /* True? */);
4457a84e134Smrg	}
4467a84e134Smrg    }
4477a84e134Smrg
4487a84e134Smrg#ifdef notdef
4497a84e134Smrg    (*Superclass->composite_class.change_managed)(widget);
4507a84e134Smrg#endif
4517a84e134Smrg}
4527a84e134Smrg
4537a84e134Smrgstatic void
4547a84e134SmrgSetBar(Widget w, int top, unsigned int length, unsigned int total)
4557a84e134Smrg{
4567a84e134Smrg    XawScrollbarSetThumb(w, (float)top / (float)total,
4577a84e134Smrg			 (float)length / (float)total);
4587a84e134Smrg}
4597a84e134Smrg
4607a84e134Smrgstatic void
4617a84e134SmrgRedrawThumbs(ViewportWidget w)
4627a84e134Smrg{
4637a84e134Smrg    Widget child = w->viewport.child;
4647a84e134Smrg    Widget clip = w->viewport.clip;
4657a84e134Smrg
4667a84e134Smrg    if (w->viewport.horiz_bar != NULL)
4677a84e134Smrg	SetBar(w->viewport.horiz_bar, -(int)XtX(child),
4687a84e134Smrg	       XtWidth(clip), XtWidth(child));
4697a84e134Smrg
4707a84e134Smrg    if (w->viewport.vert_bar != NULL)
4717a84e134Smrg	SetBar(w->viewport.vert_bar, -(int)XtY(child),
4727a84e134Smrg	       XtHeight(clip), XtHeight(child));
4737a84e134Smrg}
4747a84e134Smrg
4757a84e134Smrgstatic void
4767a84e134SmrgSendReport(ViewportWidget w, unsigned int changed)
4777a84e134Smrg{
4787a84e134Smrg    XawPannerReport rep;
4797a84e134Smrg
4807a84e134Smrg    if (w->viewport.report_callbacks) {
4817a84e134Smrg	Widget child = w->viewport.child;
4827a84e134Smrg	Widget clip = w->viewport.clip;
4837a84e134Smrg
4847a84e134Smrg	rep.changed = changed;
4857a84e134Smrg	rep.slider_x = -XtX(child);	/* child is canvas */
4867a84e134Smrg	rep.slider_y = -XtY(child);	/* clip is slider */
4877a84e134Smrg	rep.slider_width = XtWidth(clip);
4887a84e134Smrg	rep.slider_height = XtHeight(clip);
4897a84e134Smrg	rep.canvas_width = XtWidth(child);
4907a84e134Smrg	rep.canvas_height = XtHeight(child);
4917a84e134Smrg	XtCallCallbackList((Widget)w, w->viewport.report_callbacks,
4927a84e134Smrg			   (XtPointer)&rep);
4937a84e134Smrg    }
4947a84e134Smrg}
4957a84e134Smrg
4967a84e134Smrgstatic void
4977a84e134SmrgMoveChild(ViewportWidget w, int x, int y)
4987a84e134Smrg{
4997a84e134Smrg    Widget child = w->viewport.child;
5007a84e134Smrg    Widget clip = w->viewport.clip;
5017a84e134Smrg
5027a84e134Smrg    /* make sure we never move past right/bottom borders */
5037a84e134Smrg    if (-x + (int)XtWidth(clip) > XtWidth(child))
5047a84e134Smrg	x = -(int)(XtWidth(child) - XtWidth(clip));
5057a84e134Smrg
5067a84e134Smrg    if (-y + (int)XtHeight(clip) > XtHeight(child))
5077a84e134Smrg	y = -(int)(XtHeight(child) - XtHeight(clip));
5087a84e134Smrg
5097a84e134Smrg    /* make sure we never move past left/top borders */
5107a84e134Smrg    if (x >= 0)
5117a84e134Smrg	x = 0;
5127a84e134Smrg    if (y >= 0)
5137a84e134Smrg	y = 0;
5147a84e134Smrg
5157a84e134Smrg    XtMoveWidget(child, x, y);
5167a84e134Smrg    SendReport(w, (XawPRSliderX | XawPRSliderY));
5177a84e134Smrg
5187a84e134Smrg    RedrawThumbs(w);
5197a84e134Smrg}
5207a84e134Smrg
5217a84e134Smrgstatic void
5227a84e134SmrgComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars)
5237a84e134Smrg{
5247a84e134Smrg    ViewportWidget w = (ViewportWidget)widget;
5257a84e134Smrg    Widget child = w->viewport.child;
5267a84e134Smrg    Widget clip = w->viewport.clip;
5277a84e134Smrg    ViewportConstraints constraints =
5287a84e134Smrg	(ViewportConstraints)clip->core.constraints;
5297a84e134Smrg    Bool needshoriz, needsvert;
5307a84e134Smrg    int clip_width, clip_height;
5317a84e134Smrg    XtWidgetGeometry intended;
5327a84e134Smrg
5337a84e134Smrg    if (child == NULL)
5347a84e134Smrg	return;
5357a84e134Smrg
5367a84e134Smrg    clip_width = XtWidth(w);
5377a84e134Smrg    clip_height = XtHeight(w);
5387a84e134Smrg    intended.request_mode = CWBorderWidth;
5397a84e134Smrg    intended.border_width = 0;
5407a84e134Smrg
5417a84e134Smrg    if (w->viewport.forcebars) {
5427a84e134Smrg	needsvert = w->viewport.allowvert;
5437a84e134Smrg	needshoriz = w->viewport.allowhoriz;
5447a84e134Smrg	ComputeWithForceBars(widget, query, &intended,
5457a84e134Smrg			     &clip_width, &clip_height);
5467a84e134Smrg    }
5477a84e134Smrg    else {
5487a84e134Smrg	Dimension prev_width, prev_height;
5497a84e134Smrg	XtGeometryMask prev_mode;
5507a84e134Smrg	XtWidgetGeometry preferred;
5517a84e134Smrg
5527a84e134Smrg	needshoriz = needsvert = False;
5537a84e134Smrg
5547a84e134Smrg	/*
5557a84e134Smrg	 * intended.{width,height} caches the eventual child dimensions,
5567a84e134Smrg	 * but we don't set the mode bits until after we decide that the
5577a84e134Smrg	 * child's preferences are not acceptable
5587a84e134Smrg	 */
5597a84e134Smrg	if (!w->viewport.allowhoriz)
5607a84e134Smrg	    intended.request_mode |= CWWidth;
5617a84e134Smrg
5627a84e134Smrg	if (XtWidth(child) < clip_width)
5637a84e134Smrg	    intended.width = clip_width;
5647a84e134Smrg	else
5657a84e134Smrg	    intended.width = XtWidth(child);
5667a84e134Smrg
5677a84e134Smrg	if (XtHeight(child) < clip_height)
5687a84e134Smrg	    intended.height = clip_height;
5697a84e134Smrg	else
5707a84e134Smrg	    intended.height = XtHeight(child);
5717a84e134Smrg
5727a84e134Smrg	if (!w->viewport.allowvert)
5737a84e134Smrg	    intended.request_mode |= CWHeight;
5747a84e134Smrg
5757a84e134Smrg	if (!query) {
5767a84e134Smrg	    preferred.width = XtWidth(child);
5777a84e134Smrg	    preferred.height = XtHeight(child);
5787a84e134Smrg	}
5797a84e134Smrg	do { /* while intended != prev  */
5807a84e134Smrg	    if (query) {
5817a84e134Smrg		(void)XtQueryGeometry(child, &intended, &preferred);
5827a84e134Smrg		if (!(preferred.request_mode & CWWidth))
5837a84e134Smrg		    preferred.width = intended.width;
5847a84e134Smrg		if (!(preferred.request_mode & CWHeight))
5857a84e134Smrg		    preferred.height = intended.height;
5867a84e134Smrg	    }
5877a84e134Smrg	    prev_width = intended.width;
5887a84e134Smrg	    prev_height = intended.height;
5897a84e134Smrg	    prev_mode = intended.request_mode;
5907a84e134Smrg	    /*
5917a84e134Smrg	     * note that having once decided to turn on either bar
5927a84e134Smrg	     * we'll not change our mind until we're next resized,
5937a84e134Smrg	     * thus avoiding potential oscillations
5947a84e134Smrg	     */
5957a84e134Smrg#define CheckHoriz() \
5967a84e134Smrg	    if (w->viewport.allowhoriz &&				\
5977a84e134Smrg		preferred.width > clip_width) {				\
5987a84e134Smrg		if (!needshoriz) {					\
5997a84e134Smrg		    Widget bar;						\
6007a84e134Smrg									\
6017a84e134Smrg		    needshoriz = True;					\
6027a84e134Smrg		    if ((bar = w->viewport.horiz_bar) == NULL)		\
6037a84e134Smrg			bar = CreateScrollbar(w, True);			\
6047a84e134Smrg		    clip_height -= XtHeight(bar) + XtBorderWidth(bar);	\
6057a84e134Smrg		    if (clip_height < 1)				\
6067a84e134Smrg			clip_height = 1;				\
6077a84e134Smrg		}							\
6087a84e134Smrg		intended.width = preferred.width;			\
6097a84e134Smrg	    }
6107a84e134Smrg
6117a84e134Smrg	    CheckHoriz();
6127a84e134Smrg	    if (w->viewport.allowvert && preferred.height > clip_height) {
6137a84e134Smrg		if (!needsvert) {
6147a84e134Smrg		    Widget bar;
6157a84e134Smrg		    needsvert = True;
6167a84e134Smrg		    if ((bar = w->viewport.vert_bar) == NULL)
6177a84e134Smrg			bar = CreateScrollbar(w, False);
6187a84e134Smrg		    clip_width -= XtWidth(bar) + XtBorderWidth(bar);
6197a84e134Smrg		    if (clip_width < 1)
6207a84e134Smrg			clip_width = 1;
6217a84e134Smrg		    CheckHoriz();
6227a84e134Smrg		}
6237a84e134Smrg		intended.height = preferred.height;
6247a84e134Smrg	    }
6257a84e134Smrg	    if (!w->viewport.allowhoriz || preferred.width < clip_width) {
6267a84e134Smrg		intended.width = clip_width;
6277a84e134Smrg		intended.request_mode |= CWWidth;
6287a84e134Smrg	    }
6297a84e134Smrg	    if (!w->viewport.allowvert || preferred.height < clip_height) {
6307a84e134Smrg		intended.height = clip_height;
6317a84e134Smrg		intended.request_mode |= CWHeight;
6327a84e134Smrg	    }
6337a84e134Smrg	} while (intended.request_mode != prev_mode
6347a84e134Smrg		 || (intended.request_mode & CWWidth
6357a84e134Smrg		     && intended.width != prev_width)
6367a84e134Smrg		 || (intended.request_mode & CWHeight
6377a84e134Smrg		     && intended.height != prev_height));
6387a84e134Smrg    }
6397a84e134Smrg
6407a84e134Smrg    if (XtIsRealized(clip))
6417a84e134Smrg	XRaiseWindow(XtDisplay(clip), XtWindow(clip));
6427a84e134Smrg
6437a84e134Smrg    XtMoveWidget(clip,
6447a84e134Smrg		 needsvert ? w->viewport.useright ? 0 :
6457a84e134Smrg		 XtWidth(w->viewport.vert_bar)
6467a84e134Smrg		 + XtBorderWidth(w->viewport.vert_bar) : 0,
6477a84e134Smrg		 needshoriz ? w->viewport.usebottom ? 0 :
6487a84e134Smrg		 XtHeight(w->viewport.horiz_bar)
6497a84e134Smrg		 + XtBorderWidth(w->viewport.horiz_bar) : 0);
6507a84e134Smrg    XtResizeWidget(clip, clip_width, clip_height, 0);
6517a84e134Smrg
6527a84e134Smrg    if (w->viewport.horiz_bar != NULL) {
6537a84e134Smrg	Widget bar = w->viewport.horiz_bar;
6547a84e134Smrg
6557a84e134Smrg	if (!needshoriz) {
6567a84e134Smrg	    constraints->form.vert_base = NULL;
6577a84e134Smrg	    if (destroy_scrollbars) {
6587a84e134Smrg		XtDestroyWidget(bar);
6597a84e134Smrg		w->viewport.horiz_bar = NULL;
6607a84e134Smrg	    }
6617a84e134Smrg	}
6627a84e134Smrg	else {
6637a84e134Smrg	    int bw = XtBorderWidth(bar);
6647a84e134Smrg
6657a84e134Smrg	    XtResizeWidget(bar, clip_width, XtHeight(bar), bw);
6667a84e134Smrg	    XtMoveWidget(bar,
6677a84e134Smrg			 needsvert && !w->viewport.useright
6687a84e134Smrg			 ? XtWidth(w->viewport.vert_bar) : -bw,
6697a84e134Smrg			 w->viewport.usebottom
6707a84e134Smrg			 ? XtHeight(w) - XtHeight(bar) - bw : -bw);
6717a84e134Smrg	    XtSetMappedWhenManaged(bar, True);
6727a84e134Smrg	}
6737a84e134Smrg    }
6747a84e134Smrg
6757a84e134Smrg    if (w->viewport.vert_bar != NULL) {
6767a84e134Smrg	Widget bar = w->viewport.vert_bar;
6777a84e134Smrg
6787a84e134Smrg	if (!needsvert)	{
6797a84e134Smrg	    constraints->form.horiz_base = NULL;
6807a84e134Smrg	    if (destroy_scrollbars) {
6817a84e134Smrg		XtDestroyWidget(bar);
6827a84e134Smrg		w->viewport.vert_bar = NULL;
6837a84e134Smrg	    }
6847a84e134Smrg	}
6857a84e134Smrg	else {
6867a84e134Smrg	    int bw = bar->core.border_width;
6877a84e134Smrg
6887a84e134Smrg	    XtResizeWidget(bar, XtWidth(bar), clip_height, bw);
6897a84e134Smrg	    XtMoveWidget(bar,
6907a84e134Smrg			w->viewport.useright
6917a84e134Smrg			? XtWidth(w) - XtWidth(bar) - bw : -bw,
6927a84e134Smrg			needshoriz && !w->viewport.usebottom
6937a84e134Smrg			? XtHeight(w->viewport.horiz_bar) : -bw);
6947a84e134Smrg	   XtSetMappedWhenManaged(bar, True);
6957a84e134Smrg	}
6967a84e134Smrg    }
6977a84e134Smrg
6987a84e134Smrg    if (child != NULL) {
6997a84e134Smrg	XtResizeWidget(child, intended.width, intended.height, 0);
7007a84e134Smrg	MoveChild(w, needshoriz ? XtX(child) : 0,	needsvert ? XtY(child) : 0);
7017a84e134Smrg    }
7027a84e134Smrg
7037a84e134Smrg    SendReport (w, XawPRAll);
7047a84e134Smrg}
7057a84e134Smrg
7067a84e134Smrg/*
7077a84e134Smrg * Function:
7087a84e134Smrg *	ComputeWithForceBars
7097a84e134Smrg *
7107a84e134Smrg * Parameters:
7117a84e134Smrg *	widget	    - viewport widget
7127a84e134Smrg *	query	    - whether or not to query the child
7137a84e134Smrg *	intended    - cache of the childs height is stored here
7147a84e134Smrg *		      (used and returned)
7157a84e134Smrg *	clip_width  - size of clip window (used and returned)
7167a84e134Smrg *	clip_height - ""
7177a84e134Smrg *
7187a84e134Smrg * Description:
7197a84e134Smrg *	Computes the layout give forcebars is set.
7207a84e134Smrg */
7217a84e134Smrgstatic void
7227a84e134SmrgComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended,
7237a84e134Smrg		     int *clip_width, int *clip_height)
7247a84e134Smrg{
7257a84e134Smrg    ViewportWidget w = (ViewportWidget)widget;
7267a84e134Smrg    Widget child = w->viewport.child;
7277a84e134Smrg    XtWidgetGeometry preferred;
7287a84e134Smrg
7297a84e134Smrg    /*
7307a84e134Smrg     * If forcebars then needs = allows = has
7317a84e134Smrg     * Thus if needsvert is set it MUST have a scrollbar
7327a84e134Smrg     */
7337a84e134Smrg    if (w->viewport.allowvert) {
7347a84e134Smrg	if (w->viewport.vert_bar == NULL)
7357a84e134Smrg	    w->viewport.vert_bar = CreateScrollbar(w, False);
7367a84e134Smrg
7377a84e134Smrg	*clip_width -= XtWidth(w->viewport.vert_bar) +
7387a84e134Smrg		       XtBorderWidth(w->viewport.vert_bar);
7397a84e134Smrg    }
7407a84e134Smrg
7417a84e134Smrg    if (w->viewport.allowhoriz) {
7427a84e134Smrg	if (w->viewport.horiz_bar == NULL)
7437a84e134Smrg	    w->viewport.horiz_bar = CreateScrollbar(w, True);
7447a84e134Smrg
7457a84e134Smrg	*clip_height -= XtHeight(w->viewport.horiz_bar) +
7467a84e134Smrg			XtBorderWidth(w->viewport.horiz_bar);
7477a84e134Smrg    }
7487a84e134Smrg
7497a84e134Smrg    AssignMax(*clip_width, 1);
7507a84e134Smrg    AssignMax(*clip_height, 1);
7517a84e134Smrg
7527a84e134Smrg    if (!w->viewport.allowvert) {
7537a84e134Smrg	intended->height = *clip_height;
7547a84e134Smrg	intended->request_mode = CWHeight;
7557a84e134Smrg    }
7567a84e134Smrg    if (!w->viewport.allowhoriz) {
7577a84e134Smrg	intended->width = *clip_width;
7587a84e134Smrg	intended->request_mode = CWWidth;
7597a84e134Smrg    }
7607a84e134Smrg
7617a84e134Smrg    if (query) {
7627a84e134Smrg	if (w->viewport.allowvert || w->viewport.allowhoriz) {
7637a84e134Smrg	    XtQueryGeometry(child, intended, &preferred);
7647a84e134Smrg
7657a84e134Smrg	    if (!(intended->request_mode & CWWidth)) {
7667a84e134Smrg		if (preferred.request_mode & CWWidth)
7677a84e134Smrg		    intended->width = preferred.width;
7687a84e134Smrg		else
7697a84e134Smrg		    intended->width = XtWidth(child);
7707a84e134Smrg	    }
7717a84e134Smrg
7727a84e134Smrg	    if (!(intended->request_mode & CWHeight)) {
7737a84e134Smrg		if (preferred.request_mode & CWHeight)
7747a84e134Smrg		    intended->height = preferred.height;
7757a84e134Smrg		else
7767a84e134Smrg		    intended->height = XtHeight(child);
7777a84e134Smrg	    }
7787a84e134Smrg	}
7797a84e134Smrg    }
7807a84e134Smrg    else {
7817a84e134Smrg	if (w->viewport.allowvert)
7827a84e134Smrg	    intended->height = XtHeight(child);
7837a84e134Smrg	if (w->viewport.allowhoriz)
7847a84e134Smrg	    intended->width = XtWidth(child);
7857a84e134Smrg    }
7867a84e134Smrg
7877a84e134Smrg    if (*clip_width > (int)intended->width)
7887a84e134Smrg	intended->width = *clip_width;
7897a84e134Smrg    if (*clip_height > (int)intended->height)
7907a84e134Smrg	intended->height = *clip_height;
7917a84e134Smrg}
7927a84e134Smrg
7937a84e134Smrgstatic void
7947a84e134SmrgXawViewportResize(Widget widget)
7957a84e134Smrg{
7967a84e134Smrg    ComputeLayout(widget, True, True);
7977a84e134Smrg}
7987a84e134Smrg
7997a84e134Smrg/*ARGSUSED*/
8007a84e134Smrgstatic Boolean
8017a84e134SmrgLayout(FormWidget w, unsigned int width, unsigned int height, Bool force)
8027a84e134Smrg{
8037a84e134Smrg    ComputeLayout((Widget)w, True, True);
8047a84e134Smrg    w->form.preferred_width = XtWidth(w);
8057a84e134Smrg    w->form.preferred_height = XtHeight(w);
8067a84e134Smrg
8077a84e134Smrg    return (False);
8087a84e134Smrg}
8097a84e134Smrg
8107a84e134Smrgstatic void
8117a84e134SmrgScrollUpDownProc(Widget widget, XtPointer closure, XtPointer call_data)
8127a84e134Smrg{
8137a84e134Smrg    ViewportWidget w = (ViewportWidget)closure;
8147a84e134Smrg    Widget child = w->viewport.child;
8157a84e134Smrg    int pix = (long)call_data;
8167a84e134Smrg    int x, y;
8177a84e134Smrg
8187a84e134Smrg    if (child == NULL)
8197a84e134Smrg	return;
8207a84e134Smrg
8217a84e134Smrg    x = XtX(child) - (widget == w->viewport.horiz_bar ? pix : 0);
8227a84e134Smrg    y = XtY(child) - (widget == w->viewport.vert_bar ? pix : 0);
8237a84e134Smrg    MoveChild(w, x, y);
8247a84e134Smrg}
8257a84e134Smrg
8267a84e134Smrg/*ARGSUSED*/
8277a84e134Smrgstatic void
8287a84e134SmrgThumbProc(Widget widget, XtPointer closure, XtPointer call_data)
8297a84e134Smrg{
8307a84e134Smrg    ViewportWidget w = (ViewportWidget)closure;
8317a84e134Smrg    Widget child = w->viewport.child;
8327a84e134Smrg    float percent = *(float *)call_data;
8337a84e134Smrg    int x, y;
8347a84e134Smrg
8357a84e134Smrg    if (child == NULL)
8367a84e134Smrg	return;
8377a84e134Smrg
8387a84e134Smrg    if (widget == w->viewport.horiz_bar)
8397a84e134Smrg	x = -percent * XtWidth(child);
8407a84e134Smrg    else
8417a84e134Smrg	x = XtX(child);
8427a84e134Smrg
8437a84e134Smrg    if (widget == w->viewport.vert_bar)
8447a84e134Smrg	y = -percent * XtHeight(child);
8457a84e134Smrg    else
8467a84e134Smrg	y = XtY(child);
8477a84e134Smrg
8487a84e134Smrg    MoveChild(w, x, y);
8497a84e134Smrg}
8507a84e134Smrg
8517a84e134Smrgstatic XtGeometryResult
8527a84e134SmrgTestSmaller(ViewportWidget w, XtWidgetGeometry *request,
8537a84e134Smrg	    XtWidgetGeometry *reply_return)
8547a84e134Smrg{
8557a84e134Smrg    if (request->width < XtWidth(w) || request->height < XtHeight(w))
8567a84e134Smrg	return (XtMakeGeometryRequest((Widget)w, request, reply_return));
8577a84e134Smrg
8587a84e134Smrg    return (XtGeometryYes);
8597a84e134Smrg}
8607a84e134Smrg
8617a84e134Smrgstatic XtGeometryResult
8627a84e134SmrgGeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal,
8637a84e134Smrg			     XtWidgetGeometry *request,
8647a84e134Smrg			     XtWidgetGeometry *reply_return)
8657a84e134Smrg{
8667a84e134Smrg    Widget sb;
8677a84e134Smrg    XtWidgetGeometry plusScrollbars;
8687a84e134Smrg
8697a84e134Smrg    plusScrollbars = *request;
8707a84e134Smrg    if ((sb = w->viewport.horiz_bar) == NULL)
8717a84e134Smrg	sb = CreateScrollbar(w, horizontal);
8727a84e134Smrg    request->width += XtWidth(sb);
8737a84e134Smrg    request->height += XtHeight(sb);
8747a84e134Smrg    XtDestroyWidget(sb);
8757a84e134Smrg    return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return));
8767a84e134Smrg}
8777a84e134Smrg
8787a84e134Smrg#define WidthChange()	(request->width != XtWidth(w))
8797a84e134Smrg#define HeightChange()	(request->height != XtHeight(w))
8807a84e134Smrgstatic XtGeometryResult
8817a84e134SmrgQueryGeometry(ViewportWidget w, XtWidgetGeometry *request,
8827a84e134Smrg	      XtWidgetGeometry *reply_return)
8837a84e134Smrg{
8847a84e134Smrg    if (w->viewport.allowhoriz && w->viewport.allowvert)
8857a84e134Smrg	return (TestSmaller(w, request, reply_return));
8867a84e134Smrg
8877a84e134Smrg    else if (w->viewport.allowhoriz && !w->viewport.allowvert) {
8887a84e134Smrg	if (WidthChange() && !HeightChange())
8897a84e134Smrg	    return (TestSmaller(w, request, reply_return));
8907a84e134Smrg	else if (!WidthChange() && HeightChange())
8917a84e134Smrg	    return (XtMakeGeometryRequest((Widget)w, request, reply_return));
8927a84e134Smrg	else if (WidthChange() && HeightChange())
8937a84e134Smrg	    return (GeometryRequestPlusScrollbar(w, True, request, reply_return));
8947a84e134Smrg	else /* !WidthChange() && !HeightChange() */
8957a84e134Smrg	    return (XtGeometryYes);
8967a84e134Smrg    }
8977a84e134Smrg    else if (!w->viewport.allowhoriz && w->viewport.allowvert) {
8987a84e134Smrg	if (!WidthChange() && HeightChange())
8997a84e134Smrg	    return (TestSmaller(w, request, reply_return));
9007a84e134Smrg	else if (WidthChange() && !HeightChange())
9017a84e134Smrg	    return (XtMakeGeometryRequest((Widget)w, request, reply_return));
9027a84e134Smrg	else if (WidthChange() && HeightChange())
9037a84e134Smrg	    return (GeometryRequestPlusScrollbar(w, False, request, reply_return));
9047a84e134Smrg	else /* !WidthChange() && !HeightChange() */
9057a84e134Smrg	    return (XtGeometryYes);
9067a84e134Smrg    }
9077a84e134Smrg    else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */
9087a84e134Smrg	return (XtMakeGeometryRequest((Widget)w, request, reply_return));
9097a84e134Smrg}
9107a84e134Smrg#undef WidthChange
9117a84e134Smrg#undef HeightChange
9127a84e134Smrg
9137a84e134Smrgstatic XtGeometryResult
9147a84e134SmrgXawViewportGeometryManager(Widget child, XtWidgetGeometry *request,
9157a84e134Smrg			   XtWidgetGeometry *reply)
9167a84e134Smrg{
9177a84e134Smrg    ViewportWidget w = (ViewportWidget)child->core.parent;
9187a84e134Smrg    Bool rWidth = (request->request_mode & CWWidth) != 0;
9197a84e134Smrg    Bool rHeight = (request->request_mode & CWHeight) != 0;
9207a84e134Smrg    XtWidgetGeometry allowed;
9217a84e134Smrg    XtGeometryResult result;
9227a84e134Smrg    Bool reconfigured;
9237a84e134Smrg    Bool child_changed_size;
9247a84e134Smrg    unsigned int height_remaining;
9257a84e134Smrg
9267a84e134Smrg    if (request->request_mode & XtCWQueryOnly)
9277a84e134Smrg	return (QueryGeometry(w, request, reply));
9287a84e134Smrg
9297a84e134Smrg    if (child != w->viewport.child
9307a84e134Smrg	|| request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth)
9317a84e134Smrg	|| ((request->request_mode & CWBorderWidth)
9327a84e134Smrg	    && request->border_width > 0))
9337a84e134Smrg	return (XtGeometryNo);
9347a84e134Smrg
9357a84e134Smrg    allowed = *request;
9367a84e134Smrg
9377a84e134Smrg    reconfigured = GetGeometry((Widget)w,
9387a84e134Smrg				rWidth ? request->width : XtWidth(w),
9397a84e134Smrg				rHeight ? request->height : XtHeight(w));
9407a84e134Smrg
9417a84e134Smrg    child_changed_size = (rWidth && XtWidth(child) != request->width) ||
9427a84e134Smrg			 (rHeight && XtHeight(child) != request->height);
9437a84e134Smrg
9447a84e134Smrg    height_remaining = XtHeight(w);
9457a84e134Smrg    if (rWidth && XtWidth(w) != request->width) {
9467a84e134Smrg	if (w->viewport.allowhoriz && request->width > XtWidth(w)) {
9477a84e134Smrg	    /* horizontal scrollbar will be needed so possibly reduce height */
9487a84e134Smrg	    Widget bar;
9497a84e134Smrg
9507a84e134Smrg	    if ((bar = w->viewport.horiz_bar) == NULL)
9517a84e134Smrg		bar = CreateScrollbar(w, True);
9527a84e134Smrg	    height_remaining -= XtHeight(bar) + XtBorderWidth(bar);
9537a84e134Smrg	    reconfigured = True;
9547a84e134Smrg	}
9557a84e134Smrg	else
9567a84e134Smrg	    allowed.width = XtWidth(w);
9577a84e134Smrg    }
9587a84e134Smrg    if (rHeight && height_remaining != request->height) {
9597a84e134Smrg	if (w->viewport.allowvert && request->height > height_remaining) {
9607a84e134Smrg	    /* vertical scrollbar will be needed, so possibly reduce width */
9617a84e134Smrg	    if (!w->viewport.allowhoriz || request->width < XtWidth(w)) {
9627a84e134Smrg		Widget bar;
9637a84e134Smrg
9647a84e134Smrg		if ((bar = w->viewport.vert_bar) == NULL)
9657a84e134Smrg		    bar = CreateScrollbar(w, False);
9667a84e134Smrg		if (!rWidth) {
9677a84e134Smrg		    allowed.width = XtWidth(w);
9687a84e134Smrg		    allowed.request_mode |= CWWidth;
9697a84e134Smrg		}
9707a84e134Smrg		if (allowed.width  >  XtWidth(bar) + XtBorderWidth(bar))
9717a84e134Smrg		    allowed.width -= XtWidth(bar) + XtBorderWidth(bar);
9727a84e134Smrg		else
9737a84e134Smrg		    allowed.width = 1;
9747a84e134Smrg		reconfigured = True;
9757a84e134Smrg	    }
9767a84e134Smrg	}
9777a84e134Smrg	else
9787a84e134Smrg	    allowed.height = height_remaining;
9797a84e134Smrg    }
9807a84e134Smrg
9817a84e134Smrg    if (allowed.width != request->width || allowed.height != request->height) {
9827a84e134Smrg	*reply = allowed;
9837a84e134Smrg	result = XtGeometryAlmost;
9847a84e134Smrg    }
9857a84e134Smrg    else {
9867a84e134Smrg	if (rWidth)
9877a84e134Smrg	    XtWidth(child) = request->width;
9887a84e134Smrg	if (rHeight)
9897a84e134Smrg	    XtHeight(child) = request->height;
9907a84e134Smrg	result = XtGeometryYes;
9917a84e134Smrg    }
9927a84e134Smrg
9937a84e134Smrg    if (reconfigured || child_changed_size)
9947a84e134Smrg	ComputeLayout((Widget)w, False, result == XtGeometryYes);
9957a84e134Smrg
9967a84e134Smrg    return (result);
9977a84e134Smrg}
9987a84e134Smrg
9997a84e134Smrgstatic Bool
10007a84e134SmrgGetGeometry(Widget w, unsigned int width, unsigned int height)
10017a84e134Smrg{
10027a84e134Smrg    XtWidgetGeometry geometry, return_geom;
10037a84e134Smrg    XtGeometryResult result;
10047a84e134Smrg
10057a84e134Smrg    if (width == XtWidth(w) && height == XtHeight(w))
10067a84e134Smrg	return (False);
10077a84e134Smrg
10087a84e134Smrg    geometry.request_mode = CWWidth | CWHeight;
10097a84e134Smrg    geometry.width = width;
10107a84e134Smrg    geometry.height = height;
10117a84e134Smrg
10127a84e134Smrg    if (XtIsRealized(w)) {
10137a84e134Smrg	if (((ViewportWidget)w)->viewport.allowhoriz && width > XtWidth(w))
10147a84e134Smrg	    geometry.width = XtWidth(w);
10157a84e134Smrg	if (((ViewportWidget)w)->viewport.allowvert && height > XtHeight(w))
10167a84e134Smrg	    geometry.height = XtHeight(w);
10177a84e134Smrg    }
10187a84e134Smrg    else {
10197a84e134Smrg	/* This is the Realize call; we'll inherit a w&h iff none currently */
10207a84e134Smrg	if (XtWidth(w) != 0) {
10217a84e134Smrg	    if (XtHeight(w) != 0)
10227a84e134Smrg		return (False);
10237a84e134Smrg	    geometry.width = XtWidth(w);
10247a84e134Smrg	}
10257a84e134Smrg	if (XtHeight(w) != 0)
10267a84e134Smrg	    geometry.height = XtHeight(w);
10277a84e134Smrg    }
10287a84e134Smrg
10297a84e134Smrg    result = XtMakeGeometryRequest(w, &geometry, &return_geom);
10307a84e134Smrg    if (result == XtGeometryAlmost)
10317a84e134Smrg	result = XtMakeGeometryRequest(w, &return_geom, NULL);
10327a84e134Smrg
10337a84e134Smrg    return (result == XtGeometryYes);
10347a84e134Smrg}
10357a84e134Smrg
10367a84e134Smrgstatic XtGeometryResult
10377a84e134SmrgXawViewportQueryGeometry(Widget w, XtWidgetGeometry *constraints,
10387a84e134Smrg			 XtWidgetGeometry *reply)
10397a84e134Smrg{
10407a84e134Smrg    if (((ViewportWidget)w)->viewport.child != NULL)
10417a84e134Smrg	return (XtQueryGeometry(((ViewportWidget)w)->viewport.child,
10427a84e134Smrg				constraints, reply));
10437a84e134Smrg
10447a84e134Smrg    return (XtGeometryYes);
10457a84e134Smrg}
10467a84e134Smrg
10477a84e134Smrgvoid
10487a84e134SmrgXawViewportSetLocation
10497a84e134Smrg(
10507a84e134Smrg Widget gw,
10517a84e134Smrg#if NeedWidePrototypes
10527a84e134Smrg double xoff, double yoff
10537a84e134Smrg#else
10547a84e134Smrg float xoff, float yoff
10557a84e134Smrg#endif
10567a84e134Smrg )
10577a84e134Smrg{
10587a84e134Smrg    ViewportWidget w = (ViewportWidget)gw;
10597a84e134Smrg    Widget child = w->viewport.child;
10607a84e134Smrg    int x, y;
10617a84e134Smrg
10627a84e134Smrg    if (xoff > 1.0)			/* scroll to right */
10637a84e134Smrg	x = XtWidth(child);
10647a84e134Smrg    else if (xoff < 0.0)		/* if the offset is < 0.0 nothing */
10657a84e134Smrg	x = XtX(child);
10667a84e134Smrg    else
10677a84e134Smrg	x = (float)XtWidth(child) * xoff;
10687a84e134Smrg
10697a84e134Smrg    if (yoff > 1.0)
10707a84e134Smrg	y = XtHeight(child);
10717a84e134Smrg    else if (yoff < 0.0)
10727a84e134Smrg	y = XtY(child);
10737a84e134Smrg    else
10747a84e134Smrg	y = (float)XtHeight(child) * yoff;
10757a84e134Smrg
10767a84e134Smrg    MoveChild (w, -x, -y);
10777a84e134Smrg}
10787a84e134Smrg
10797a84e134Smrgvoid
10807a84e134SmrgXawViewportSetCoordinates(Widget gw,
10817a84e134Smrg#if NeedWidePrototypes
10827a84e134Smrg	int x, int y
10837a84e134Smrg#else
10847a84e134Smrg	Position x, Position y
10857a84e134Smrg#endif
10867a84e134Smrg)
10877a84e134Smrg{
10887a84e134Smrg    ViewportWidget w = (ViewportWidget)gw;
10897a84e134Smrg    Widget child = w->viewport.child;
10907a84e134Smrg
10917a84e134Smrg    if (x > XtWidth(child))
10927a84e134Smrg	x = XtWidth(child);
10937a84e134Smrg    else if (x < 0)
10947a84e134Smrg	x = XtX(child);
10957a84e134Smrg
10967a84e134Smrg    if (y > XtHeight(child))
10977a84e134Smrg	y = XtHeight(child);
10987a84e134Smrg    else if (y < 0)
10997a84e134Smrg	y = XtY(child);
11007a84e134Smrg
11017a84e134Smrg    MoveChild (w, -x, -y);
11027a84e134Smrg}
1103