From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- libXaw/src/Viewport.c | 2198 ++++++++++++++++++++++++------------------------- 1 file changed, 1099 insertions(+), 1099 deletions(-) (limited to 'libXaw/src/Viewport.c') diff --git a/libXaw/src/Viewport.c b/libXaw/src/Viewport.c index ac2857257..68bd1682b 100644 --- a/libXaw/src/Viewport.c +++ b/libXaw/src/Viewport.c @@ -1,1099 +1,1099 @@ -/*********************************************************** - -Copyright 1987, 1988, 1994, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include "Private.h" - -/* - * Class Methods - */ -static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool); -static void XawViewportChangeManaged(Widget); -static void XawViewportInitialize(Widget, Widget, ArgList, Cardinal*); -static void -XawViewportConstraintInitialize(Widget, Widget, ArgList, Cardinal*); -static XtGeometryResult XawViewportGeometryManager(Widget, XtWidgetGeometry*, - XtWidgetGeometry*); -static XtGeometryResult XawViewportQueryGeometry(Widget, - XtWidgetGeometry*, - XtWidgetGeometry*); -static void XawViewportRealize(Widget, XtValueMask*, XSetWindowAttributes*); -static void XawViewportResize(Widget); -static Boolean XawViewportSetValues(Widget, Widget, Widget, - ArgList, Cardinal*); - -/* - * Prototypes - */ -static void ComputeLayout(Widget, Bool, Bool); -static void ComputeWithForceBars(Widget, Bool, XtWidgetGeometry*, - int*, int*); -static Widget CreateScrollbar(ViewportWidget, Bool); -static XtGeometryResult GeometryRequestPlusScrollbar(ViewportWidget, Bool, - XtWidgetGeometry*, - XtWidgetGeometry*); -static Bool GetGeometry(Widget, unsigned int, unsigned int); -static void MoveChild(ViewportWidget, int, int); -static XtGeometryResult QueryGeometry(ViewportWidget, XtWidgetGeometry*, - XtWidgetGeometry*); -static void RedrawThumbs(ViewportWidget); -static void ScrollUpDownProc(Widget, XtPointer, XtPointer); -static void SendReport(ViewportWidget, unsigned int); -static void SetBar(Widget, int, unsigned int, unsigned int); -static XtGeometryResult TestSmaller(ViewportWidget, XtWidgetGeometry*, - XtWidgetGeometry*); -static void ThumbProc(Widget, XtPointer, XtPointer); - -/* - * Initialization - */ -#define offset(field) XtOffsetOf(ViewportRec, viewport.field) -static XtResource resources[] = { - { - XtNforceBars, - XtCBoolean, - XtRBoolean, - sizeof(Boolean), - offset(forcebars), - XtRImmediate, - (XtPointer)False - }, - { - XtNallowHoriz, - XtCBoolean, - XtRBoolean, - sizeof(Boolean), - offset(allowhoriz), - XtRImmediate, - (XtPointer)False - }, - { - XtNallowVert, - XtCBoolean, - XtRBoolean, - sizeof(Boolean), - offset(allowvert), - XtRImmediate, - (XtPointer)False - }, - { - XtNuseBottom, - XtCBoolean, - XtRBoolean, - sizeof(Boolean), - offset(usebottom), - XtRImmediate, - (XtPointer)False - }, - { - XtNuseRight, - XtCBoolean, - XtRBoolean, - sizeof(Boolean), - offset(useright), - XtRImmediate, - (XtPointer)False - }, - { - XtNreportCallback, - XtCReportCallback, - XtRCallback, - sizeof(XtPointer), - offset(report_callbacks), - XtRImmediate, - NULL - }, -}; -#undef offset - -#define Superclass (&formClassRec) -ViewportClassRec viewportClassRec = { - /* core */ - { - (WidgetClass)Superclass, /* superclass */ - "Viewport", /* class_name */ - sizeof(ViewportRec), /* widget_size */ - XawInitializeWidgetSet, /* class_initialize */ - NULL, /* class_part_init */ - False, /* class_inited */ - XawViewportInitialize, /* initialize */ - NULL, /* initialize_hook */ - XawViewportRealize, /* realize */ - NULL, /* actions */ - 0, /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resources */ - NULLQUARK, /* xrm_class */ - True, /* compress_motion */ - True, /* compress_exposure */ - True, /* compress_enterleave */ - False, /* visible_interest */ - NULL, /* destroy */ - XawViewportResize, /* resize */ - XtInheritExpose, /* expose */ - XawViewportSetValues, /* set_values */ - NULL, /* set_values_hook */ - XtInheritSetValuesAlmost, /* set_values_almost */ - NULL, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback_private */ - NULL, /* tm_table */ - XawViewportQueryGeometry, /* query_geometry */ - XtInheritDisplayAccelerator, /* display_accelerator */ - NULL, /* extension */ - }, - /* composite */ - { - XawViewportGeometryManager, /* geometry_manager */ - XawViewportChangeManaged, /* change_managed */ - XtInheritInsertChild, /* insert_child */ - XtInheritDeleteChild, /* delete_child */ - NULL, /* extension */ - }, - /* constraint */ - { - NULL, /* subresourses */ - 0, /* subresource_count */ - sizeof(ViewportConstraintsRec), /* constraint_size */ - XawViewportConstraintInitialize, /* initialize */ - NULL, /* destroy */ - NULL, /* set_values */ - NULL, /* extension */ - }, - /* form */ - { - Layout, /* layout */ - }, - /* viewport */ - { - NULL, /* extension */ - }, -}; - -WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec; - -/* - * Implementation - */ -static Widget -CreateScrollbar(ViewportWidget w, Bool horizontal) -{ - static Arg barArgs[] = { - {XtNorientation, 0}, - {XtNlength, 0}, - {XtNleft, 0}, - {XtNright, 0}, - {XtNtop, 0}, - {XtNbottom, 0}, - {XtNmappedWhenManaged, False}, - }; - Widget clip = w->viewport.clip; - ViewportConstraints constraints = - (ViewportConstraints)clip->core.constraints; - Widget bar; - - XtSetArg(barArgs[0], XtNorientation, - horizontal ? XtorientHorizontal : XtorientVertical); - XtSetArg(barArgs[1], XtNlength, - horizontal ? XtWidth(clip) : XtHeight(clip)); - XtSetArg(barArgs[2], XtNleft, - !horizontal && w->viewport.useright ? XtChainRight : XtChainLeft); - XtSetArg(barArgs[3], XtNright, - !horizontal && !w->viewport.useright ? XtChainLeft : XtChainRight); - XtSetArg(barArgs[4], XtNtop, - horizontal && w->viewport.usebottom ? XtChainBottom: XtChainTop); - XtSetArg(barArgs[5], XtNbottom, - horizontal && !w->viewport.usebottom ? XtChainTop: XtChainBottom); - - bar = XtCreateWidget(horizontal ? "horizontal" : "vertical", - scrollbarWidgetClass, (Widget)w, - barArgs, XtNumber(barArgs)); - XtAddCallback(bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w); - XtAddCallback(bar, XtNjumpProc, ThumbProc, (XtPointer)w); - - if (horizontal) { - w->viewport.horiz_bar = bar; - constraints->form.vert_base = bar; - } - else { - w->viewport.vert_bar = bar; - constraints->form.horiz_base = bar; - } - - XtManageChild(bar); - - return (bar); -} - -/*ARGSUSED*/ -static void -XawViewportInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - ViewportWidget w = (ViewportWidget)cnew; - static Arg clip_args[8]; - Cardinal arg_cnt; - Widget h_bar, v_bar; - Dimension clip_height, clip_width; - - w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */ - - /* - * Initialize all widget pointers to NULL - */ - w->viewport.child = NULL; - w->viewport.horiz_bar = w->viewport.vert_bar = NULL; - - /* - * Create Clip Widget - */ - arg_cnt = 0; - XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w)); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w)); arg_cnt++; - - w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew, - clip_args, arg_cnt); - - if (!w->viewport.forcebars) - return; /* If we are not forcing the bars then we are done */ - - if (w->viewport.allowhoriz) - (void)CreateScrollbar(w, True); - if (w->viewport.allowvert) - (void)CreateScrollbar(w, False); - - h_bar = w->viewport.horiz_bar; - v_bar = w->viewport.vert_bar; - - /* - * Set the clip widget to the correct height - */ - clip_width = XtWidth(w); - clip_height = XtHeight(w); - - if (h_bar != NULL && XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar)) - clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar); - - if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar)) - clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar); - - arg_cnt = 0; - XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++; - XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++; - XtSetValues(w->viewport.clip, clip_args, arg_cnt); -} - -/*ARGSUSED*/ -static void -XawViewportConstraintInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - ((ViewportConstraints)cnew->core.constraints)->viewport.reparented = False; -} - -static void -XawViewportRealize(Widget widget, XtValueMask *value_mask, - XSetWindowAttributes *attributes) -{ - ViewportWidget w = (ViewportWidget)widget; - Widget child = w->viewport.child; - Widget clip = w->viewport.clip; - - *value_mask |= CWBitGravity; - attributes->bit_gravity = NorthWestGravity; - (*Superclass->core_class.realize)(widget, value_mask, attributes); - - (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */ - - if (child != NULL) { - XtMoveWidget(child, 0, 0); - XtRealizeWidget(clip); - XtRealizeWidget(child); - XReparentWindow(XtDisplay(w), XtWindow(child), XtWindow(clip), 0, 0); - XtMapWidget(child); - } -} - -/*ARGSUSED*/ -static Boolean -XawViewportSetValues(Widget current, Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - ViewportWidget w = (ViewportWidget)cnew; - ViewportWidget cw = (ViewportWidget)current; - - if (w->viewport.forcebars != cw->viewport.forcebars - || w->viewport.allowvert != cw->viewport.allowvert - || w->viewport.allowhoriz != cw->viewport.allowhoriz - || w->viewport.useright != cw->viewport.useright - || w->viewport.usebottom != cw->viewport.usebottom) - (*w->core.widget_class->core_class.resize)(cnew); /* Recompute layout */ - - return (False); -} - -static void -XawViewportChangeManaged(Widget widget) -{ - ViewportWidget w = (ViewportWidget)widget; - int num_children = w->composite.num_children; - Widget child, *childP; - int i; - - child = NULL; - for (childP = w->composite.children, - i = 0; i < num_children; - childP++, i++) { - if (XtIsManaged(*childP) - && *childP != w->viewport.clip - && *childP != w->viewport.horiz_bar - && *childP != w->viewport.vert_bar) { - child = *childP; - break; - } - } - - if (child != w->viewport.child) { - w->viewport.child = child; - if (child != NULL) { - XtResizeWidget(child, XtWidth(child), XtHeight(child), 0); - if (XtIsRealized(widget)) { - ViewportConstraints constraints = - (ViewportConstraints)child->core.constraints; - if (!XtIsRealized(child)) { - Window window = XtWindow(w); - - XtMoveWidget(child, 0, 0); - w->core.window = XtWindow(w->viewport.clip); - XtRealizeWidget(child); - w->core.window = window; - constraints->viewport.reparented = True; - } - else if (!constraints->viewport.reparented) { - XReparentWindow(XtDisplay(w), XtWindow(child), - XtWindow(w->viewport.clip), 0, 0); - constraints->viewport.reparented = True; - if (child->core.mapped_when_managed) - XtMapWidget(child); - } - } - GetGeometry(widget, XtWidth(child), XtHeight(child)); - (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout) - ((FormWidget)w, XtWidth(w), XtHeight(w), True /* True? */); - } - } - -#ifdef notdef - (*Superclass->composite_class.change_managed)(widget); -#endif -} - -static void -SetBar(Widget w, int top, unsigned int length, unsigned int total) -{ - XawScrollbarSetThumb(w, (float)top / (float)total, - (float)length / (float)total); -} - -static void -RedrawThumbs(ViewportWidget w) -{ - Widget child = w->viewport.child; - Widget clip = w->viewport.clip; - - if (w->viewport.horiz_bar != NULL) - SetBar(w->viewport.horiz_bar, -(int)XtX(child), - XtWidth(clip), XtWidth(child)); - - if (w->viewport.vert_bar != NULL) - SetBar(w->viewport.vert_bar, -(int)XtY(child), - XtHeight(clip), XtHeight(child)); -} - -static void -SendReport(ViewportWidget w, unsigned int changed) -{ - XawPannerReport rep; - - if (w->viewport.report_callbacks) { - Widget child = w->viewport.child; - Widget clip = w->viewport.clip; - - rep.changed = changed; - rep.slider_x = -XtX(child); /* child is canvas */ - rep.slider_y = -XtY(child); /* clip is slider */ - rep.slider_width = XtWidth(clip); - rep.slider_height = XtHeight(clip); - rep.canvas_width = XtWidth(child); - rep.canvas_height = XtHeight(child); - XtCallCallbackList((Widget)w, w->viewport.report_callbacks, - (XtPointer)&rep); - } -} - -static void -MoveChild(ViewportWidget w, int x, int y) -{ - Widget child = w->viewport.child; - Widget clip = w->viewport.clip; - - /* make sure we never move past right/bottom borders */ - if (-x + (int)XtWidth(clip) > XtWidth(child)) - x = -(int)(XtWidth(child) - XtWidth(clip)); - - if (-y + (int)XtHeight(clip) > XtHeight(child)) - y = -(int)(XtHeight(child) - XtHeight(clip)); - - /* make sure we never move past left/top borders */ - if (x >= 0) - x = 0; - if (y >= 0) - y = 0; - - XtMoveWidget(child, x, y); - SendReport(w, (XawPRSliderX | XawPRSliderY)); - - RedrawThumbs(w); -} - -static void -ComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars) -{ - ViewportWidget w = (ViewportWidget)widget; - Widget child = w->viewport.child; - Widget clip = w->viewport.clip; - ViewportConstraints constraints = - (ViewportConstraints)clip->core.constraints; - Bool needshoriz, needsvert; - int clip_width, clip_height; - XtWidgetGeometry intended; - - if (child == NULL) - return; - - clip_width = XtWidth(w); - clip_height = XtHeight(w); - intended.request_mode = CWBorderWidth; - intended.border_width = 0; - - if (w->viewport.forcebars) { - needsvert = w->viewport.allowvert; - needshoriz = w->viewport.allowhoriz; - ComputeWithForceBars(widget, query, &intended, - &clip_width, &clip_height); - } - else { - Dimension prev_width, prev_height; - XtGeometryMask prev_mode; - XtWidgetGeometry preferred; - - needshoriz = needsvert = False; - - /* - * intended.{width,height} caches the eventual child dimensions, - * but we don't set the mode bits until after we decide that the - * child's preferences are not acceptable - */ - if (!w->viewport.allowhoriz) - intended.request_mode |= CWWidth; - - if (XtWidth(child) < clip_width) - intended.width = clip_width; - else - intended.width = XtWidth(child); - - if (XtHeight(child) < clip_height) - intended.height = clip_height; - else - intended.height = XtHeight(child); - - if (!w->viewport.allowvert) - intended.request_mode |= CWHeight; - - if (!query) { - preferred.width = XtWidth(child); - preferred.height = XtHeight(child); - } - do { /* while intended != prev */ - if (query) { - (void)XtQueryGeometry(child, &intended, &preferred); - if (!(preferred.request_mode & CWWidth)) - preferred.width = intended.width; - if (!(preferred.request_mode & CWHeight)) - preferred.height = intended.height; - } - prev_width = intended.width; - prev_height = intended.height; - prev_mode = intended.request_mode; - /* - * note that having once decided to turn on either bar - * we'll not change our mind until we're next resized, - * thus avoiding potential oscillations - */ -#define CheckHoriz() \ - if (w->viewport.allowhoriz && \ - preferred.width > clip_width) { \ - if (!needshoriz) { \ - Widget bar; \ - \ - needshoriz = True; \ - if ((bar = w->viewport.horiz_bar) == NULL) \ - bar = CreateScrollbar(w, True); \ - clip_height -= XtHeight(bar) + XtBorderWidth(bar); \ - if (clip_height < 1) \ - clip_height = 1; \ - } \ - intended.width = preferred.width; \ - } - - CheckHoriz(); - if (w->viewport.allowvert && preferred.height > clip_height) { - if (!needsvert) { - Widget bar; - needsvert = True; - if ((bar = w->viewport.vert_bar) == NULL) - bar = CreateScrollbar(w, False); - clip_width -= XtWidth(bar) + XtBorderWidth(bar); - if (clip_width < 1) - clip_width = 1; - CheckHoriz(); - } - intended.height = preferred.height; - } - if (!w->viewport.allowhoriz || preferred.width < clip_width) { - intended.width = clip_width; - intended.request_mode |= CWWidth; - } - if (!w->viewport.allowvert || preferred.height < clip_height) { - intended.height = clip_height; - intended.request_mode |= CWHeight; - } - } while (intended.request_mode != prev_mode - || (intended.request_mode & CWWidth - && intended.width != prev_width) - || (intended.request_mode & CWHeight - && intended.height != prev_height)); - } - - if (XtIsRealized(clip)) - XRaiseWindow(XtDisplay(clip), XtWindow(clip)); - - XtMoveWidget(clip, - needsvert ? w->viewport.useright ? 0 : - XtWidth(w->viewport.vert_bar) - + XtBorderWidth(w->viewport.vert_bar) : 0, - needshoriz ? w->viewport.usebottom ? 0 : - XtHeight(w->viewport.horiz_bar) - + XtBorderWidth(w->viewport.horiz_bar) : 0); - XtResizeWidget(clip, clip_width, clip_height, 0); - - if (w->viewport.horiz_bar != NULL) { - Widget bar = w->viewport.horiz_bar; - - if (!needshoriz) { - constraints->form.vert_base = NULL; - if (destroy_scrollbars) { - XtDestroyWidget(bar); - w->viewport.horiz_bar = NULL; - } - } - else { - int bw = XtBorderWidth(bar); - - XtResizeWidget(bar, clip_width, XtHeight(bar), bw); - XtMoveWidget(bar, - needsvert && !w->viewport.useright - ? XtWidth(w->viewport.vert_bar) : -bw, - w->viewport.usebottom - ? XtHeight(w) - XtHeight(bar) - bw : -bw); - XtSetMappedWhenManaged(bar, True); - } - } - - if (w->viewport.vert_bar != NULL) { - Widget bar = w->viewport.vert_bar; - - if (!needsvert) { - constraints->form.horiz_base = NULL; - if (destroy_scrollbars) { - XtDestroyWidget(bar); - w->viewport.vert_bar = NULL; - } - } - else { - int bw = bar->core.border_width; - - XtResizeWidget(bar, XtWidth(bar), clip_height, bw); - XtMoveWidget(bar, - w->viewport.useright - ? XtWidth(w) - XtWidth(bar) - bw : -bw, - needshoriz && !w->viewport.usebottom - ? XtHeight(w->viewport.horiz_bar) : -bw); - XtSetMappedWhenManaged(bar, True); - } - } - - if (child != NULL) { - XtResizeWidget(child, intended.width, intended.height, 0); - MoveChild(w, needshoriz ? XtX(child) : 0, needsvert ? XtY(child) : 0); - } - - SendReport (w, XawPRAll); -} - -/* - * Function: - * ComputeWithForceBars - * - * Parameters: - * widget - viewport widget - * query - whether or not to query the child - * intended - cache of the childs height is stored here - * (used and returned) - * clip_width - size of clip window (used and returned) - * clip_height - "" - * - * Description: - * Computes the layout give forcebars is set. - */ -static void -ComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended, - int *clip_width, int *clip_height) -{ - ViewportWidget w = (ViewportWidget)widget; - Widget child = w->viewport.child; - XtWidgetGeometry preferred; - - /* - * If forcebars then needs = allows = has - * Thus if needsvert is set it MUST have a scrollbar - */ - if (w->viewport.allowvert) { - if (w->viewport.vert_bar == NULL) - w->viewport.vert_bar = CreateScrollbar(w, False); - - *clip_width -= XtWidth(w->viewport.vert_bar) + - XtBorderWidth(w->viewport.vert_bar); - } - - if (w->viewport.allowhoriz) { - if (w->viewport.horiz_bar == NULL) - w->viewport.horiz_bar = CreateScrollbar(w, True); - - *clip_height -= XtHeight(w->viewport.horiz_bar) + - XtBorderWidth(w->viewport.horiz_bar); - } - - AssignMax(*clip_width, 1); - AssignMax(*clip_height, 1); - - if (!w->viewport.allowvert) { - intended->height = *clip_height; - intended->request_mode = CWHeight; - } - if (!w->viewport.allowhoriz) { - intended->width = *clip_width; - intended->request_mode = CWWidth; - } - - if (query) { - if (w->viewport.allowvert || w->viewport.allowhoriz) { - XtQueryGeometry(child, intended, &preferred); - - if (!(intended->request_mode & CWWidth)) { - if (preferred.request_mode & CWWidth) - intended->width = preferred.width; - else - intended->width = XtWidth(child); - } - - if (!(intended->request_mode & CWHeight)) { - if (preferred.request_mode & CWHeight) - intended->height = preferred.height; - else - intended->height = XtHeight(child); - } - } - } - else { - if (w->viewport.allowvert) - intended->height = XtHeight(child); - if (w->viewport.allowhoriz) - intended->width = XtWidth(child); - } - - if (*clip_width > (int)intended->width) - intended->width = *clip_width; - if (*clip_height > (int)intended->height) - intended->height = *clip_height; -} - -static void -XawViewportResize(Widget widget) -{ - ComputeLayout(widget, True, True); -} - -/*ARGSUSED*/ -static Boolean -Layout(FormWidget w, unsigned int width, unsigned int height, Bool force) -{ - ComputeLayout((Widget)w, True, True); - w->form.preferred_width = XtWidth(w); - w->form.preferred_height = XtHeight(w); - - return (False); -} - -static void -ScrollUpDownProc(Widget widget, XtPointer closure, XtPointer call_data) -{ - ViewportWidget w = (ViewportWidget)closure; - Widget child = w->viewport.child; - int pix = (long)call_data; - int x, y; - - if (child == NULL) - return; - - x = XtX(child) - (widget == w->viewport.horiz_bar ? pix : 0); - y = XtY(child) - (widget == w->viewport.vert_bar ? pix : 0); - MoveChild(w, x, y); -} - -/*ARGSUSED*/ -static void -ThumbProc(Widget widget, XtPointer closure, XtPointer call_data) -{ - ViewportWidget w = (ViewportWidget)closure; - Widget child = w->viewport.child; - float percent = *(float *)call_data; - int x, y; - - if (child == NULL) - return; - - if (widget == w->viewport.horiz_bar) - x = -percent * XtWidth(child); - else - x = XtX(child); - - if (widget == w->viewport.vert_bar) - y = -percent * XtHeight(child); - else - y = XtY(child); - - MoveChild(w, x, y); -} - -static XtGeometryResult -TestSmaller(ViewportWidget w, XtWidgetGeometry *request, - XtWidgetGeometry *reply_return) -{ - if (request->width < XtWidth(w) || request->height < XtHeight(w)) - return (XtMakeGeometryRequest((Widget)w, request, reply_return)); - - return (XtGeometryYes); -} - -static XtGeometryResult -GeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal, - XtWidgetGeometry *request, - XtWidgetGeometry *reply_return) -{ - Widget sb; - XtWidgetGeometry plusScrollbars; - - plusScrollbars = *request; - if ((sb = w->viewport.horiz_bar) == NULL) - sb = CreateScrollbar(w, horizontal); - request->width += XtWidth(sb); - request->height += XtHeight(sb); - XtDestroyWidget(sb); - return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return)); -} - -#define WidthChange() (request->width != XtWidth(w)) -#define HeightChange() (request->height != XtHeight(w)) -static XtGeometryResult -QueryGeometry(ViewportWidget w, XtWidgetGeometry *request, - XtWidgetGeometry *reply_return) -{ - if (w->viewport.allowhoriz && w->viewport.allowvert) - return (TestSmaller(w, request, reply_return)); - - else if (w->viewport.allowhoriz && !w->viewport.allowvert) { - if (WidthChange() && !HeightChange()) - return (TestSmaller(w, request, reply_return)); - else if (!WidthChange() && HeightChange()) - return (XtMakeGeometryRequest((Widget)w, request, reply_return)); - else if (WidthChange() && HeightChange()) - return (GeometryRequestPlusScrollbar(w, True, request, reply_return)); - else /* !WidthChange() && !HeightChange() */ - return (XtGeometryYes); - } - else if (!w->viewport.allowhoriz && w->viewport.allowvert) { - if (!WidthChange() && HeightChange()) - return (TestSmaller(w, request, reply_return)); - else if (WidthChange() && !HeightChange()) - return (XtMakeGeometryRequest((Widget)w, request, reply_return)); - else if (WidthChange() && HeightChange()) - return (GeometryRequestPlusScrollbar(w, False, request, reply_return)); - else /* !WidthChange() && !HeightChange() */ - return (XtGeometryYes); - } - else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */ - return (XtMakeGeometryRequest((Widget)w, request, reply_return)); -} -#undef WidthChange -#undef HeightChange - -static XtGeometryResult -XawViewportGeometryManager(Widget child, XtWidgetGeometry *request, - XtWidgetGeometry *reply) -{ - ViewportWidget w = (ViewportWidget)child->core.parent; - Bool rWidth = (request->request_mode & CWWidth) != 0; - Bool rHeight = (request->request_mode & CWHeight) != 0; - XtWidgetGeometry allowed; - XtGeometryResult result; - Bool reconfigured; - Bool child_changed_size; - unsigned int height_remaining; - - if (request->request_mode & XtCWQueryOnly) - return (QueryGeometry(w, request, reply)); - - if (child != w->viewport.child - || request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth) - || ((request->request_mode & CWBorderWidth) - && request->border_width > 0)) - return (XtGeometryNo); - - allowed = *request; - - reconfigured = GetGeometry((Widget)w, - rWidth ? request->width : XtWidth(w), - rHeight ? request->height : XtHeight(w)); - - child_changed_size = (rWidth && XtWidth(child) != request->width) || - (rHeight && XtHeight(child) != request->height); - - height_remaining = XtHeight(w); - if (rWidth && XtWidth(w) != request->width) { - if (w->viewport.allowhoriz && request->width > XtWidth(w)) { - /* horizontal scrollbar will be needed so possibly reduce height */ - Widget bar; - - if ((bar = w->viewport.horiz_bar) == NULL) - bar = CreateScrollbar(w, True); - height_remaining -= XtHeight(bar) + XtBorderWidth(bar); - reconfigured = True; - } - else - allowed.width = XtWidth(w); - } - if (rHeight && height_remaining != request->height) { - if (w->viewport.allowvert && request->height > height_remaining) { - /* vertical scrollbar will be needed, so possibly reduce width */ - if (!w->viewport.allowhoriz || request->width < XtWidth(w)) { - Widget bar; - - if ((bar = w->viewport.vert_bar) == NULL) - bar = CreateScrollbar(w, False); - if (!rWidth) { - allowed.width = XtWidth(w); - allowed.request_mode |= CWWidth; - } - if (allowed.width > XtWidth(bar) + XtBorderWidth(bar)) - allowed.width -= XtWidth(bar) + XtBorderWidth(bar); - else - allowed.width = 1; - reconfigured = True; - } - } - else - allowed.height = height_remaining; - } - - if (allowed.width != request->width || allowed.height != request->height) { - *reply = allowed; - result = XtGeometryAlmost; - } - else { - if (rWidth) - XtWidth(child) = request->width; - if (rHeight) - XtHeight(child) = request->height; - result = XtGeometryYes; - } - - if (reconfigured || child_changed_size) - ComputeLayout((Widget)w, False, result == XtGeometryYes); - - return (result); -} - -static Bool -GetGeometry(Widget w, unsigned int width, unsigned int height) -{ - XtWidgetGeometry geometry, return_geom; - XtGeometryResult result; - - if (width == XtWidth(w) && height == XtHeight(w)) - return (False); - - geometry.request_mode = CWWidth | CWHeight; - geometry.width = width; - geometry.height = height; - - if (XtIsRealized(w)) { - if (((ViewportWidget)w)->viewport.allowhoriz && width > XtWidth(w)) - geometry.width = XtWidth(w); - if (((ViewportWidget)w)->viewport.allowvert && height > XtHeight(w)) - geometry.height = XtHeight(w); - } - else { - /* This is the Realize call; we'll inherit a w&h iff none currently */ - if (XtWidth(w) != 0) { - if (XtHeight(w) != 0) - return (False); - geometry.width = XtWidth(w); - } - if (XtHeight(w) != 0) - geometry.height = XtHeight(w); - } - - result = XtMakeGeometryRequest(w, &geometry, &return_geom); - if (result == XtGeometryAlmost) - result = XtMakeGeometryRequest(w, &return_geom, NULL); - - return (result == XtGeometryYes); -} - -static XtGeometryResult -XawViewportQueryGeometry(Widget w, XtWidgetGeometry *constraints, - XtWidgetGeometry *reply) -{ - if (((ViewportWidget)w)->viewport.child != NULL) - return (XtQueryGeometry(((ViewportWidget)w)->viewport.child, - constraints, reply)); - - return (XtGeometryYes); -} - -void -XawViewportSetLocation -( - Widget gw, -#if NeedWidePrototypes - double xoff, double yoff -#else - float xoff, float yoff -#endif - ) -{ - ViewportWidget w = (ViewportWidget)gw; - Widget child = w->viewport.child; - int x, y; - - if (xoff > 1.0) /* scroll to right */ - x = XtWidth(child); - else if (xoff < 0.0) /* if the offset is < 0.0 nothing */ - x = XtX(child); - else - x = (float)XtWidth(child) * xoff; - - if (yoff > 1.0) - y = XtHeight(child); - else if (yoff < 0.0) - y = XtY(child); - else - y = (float)XtHeight(child) * yoff; - - MoveChild (w, -x, -y); -} - -void -XawViewportSetCoordinates(Widget gw, -#if NeedWidePrototypes - int x, int y -#else - Position x, Position y -#endif -) -{ - ViewportWidget w = (ViewportWidget)gw; - Widget child = w->viewport.child; - - if (x > XtWidth(child)) - x = XtWidth(child); - else if (x < 0) - x = XtX(child); - - if (y > XtHeight(child)) - y = XtHeight(child); - else if (y < 0) - y = XtY(child); - - MoveChild (w, -x, -y); -} +/*********************************************************** + +Copyright 1987, 1988, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include "Private.h" + +/* + * Class Methods + */ +static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool); +static void XawViewportChangeManaged(Widget); +static void XawViewportInitialize(Widget, Widget, ArgList, Cardinal*); +static void +XawViewportConstraintInitialize(Widget, Widget, ArgList, Cardinal*); +static XtGeometryResult XawViewportGeometryManager(Widget, XtWidgetGeometry*, + XtWidgetGeometry*); +static XtGeometryResult XawViewportQueryGeometry(Widget, + XtWidgetGeometry*, + XtWidgetGeometry*); +static void XawViewportRealize(Widget, XtValueMask*, XSetWindowAttributes*); +static void XawViewportResize(Widget); +static Boolean XawViewportSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static void ComputeLayout(Widget, Bool, Bool); +static void ComputeWithForceBars(Widget, Bool, XtWidgetGeometry*, + int*, int*); +static Widget CreateScrollbar(ViewportWidget, Bool); +static XtGeometryResult GeometryRequestPlusScrollbar(ViewportWidget, Bool, + XtWidgetGeometry*, + XtWidgetGeometry*); +static Bool GetGeometry(Widget, unsigned int, unsigned int); +static void MoveChild(ViewportWidget, int, int); +static XtGeometryResult QueryGeometry(ViewportWidget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void RedrawThumbs(ViewportWidget); +static void ScrollUpDownProc(Widget, XtPointer, XtPointer); +static void SendReport(ViewportWidget, unsigned int); +static void SetBar(Widget, int, unsigned int, unsigned int); +static XtGeometryResult TestSmaller(ViewportWidget, XtWidgetGeometry*, + XtWidgetGeometry*); +static void ThumbProc(Widget, XtPointer, XtPointer); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(ViewportRec, viewport.field) +static XtResource resources[] = { + { + XtNforceBars, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(forcebars), + XtRImmediate, + (XtPointer)False + }, + { + XtNallowHoriz, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(allowhoriz), + XtRImmediate, + (XtPointer)False + }, + { + XtNallowVert, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(allowvert), + XtRImmediate, + (XtPointer)False + }, + { + XtNuseBottom, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(usebottom), + XtRImmediate, + (XtPointer)False + }, + { + XtNuseRight, + XtCBoolean, + XtRBoolean, + sizeof(Boolean), + offset(useright), + XtRImmediate, + (XtPointer)False + }, + { + XtNreportCallback, + XtCReportCallback, + XtRCallback, + sizeof(XtPointer), + offset(report_callbacks), + XtRImmediate, + NULL + }, +}; +#undef offset + +#define Superclass (&formClassRec) +ViewportClassRec viewportClassRec = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Viewport", /* class_name */ + sizeof(ViewportRec), /* widget_size */ + XawInitializeWidgetSet, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawViewportInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawViewportRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + NULL, /* destroy */ + XawViewportResize, /* resize */ + XtInheritExpose, /* expose */ + XawViewportSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XawViewportQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* composite */ + { + XawViewportGeometryManager, /* geometry_manager */ + XawViewportChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + /* constraint */ + { + NULL, /* subresourses */ + 0, /* subresource_count */ + sizeof(ViewportConstraintsRec), /* constraint_size */ + XawViewportConstraintInitialize, /* initialize */ + NULL, /* destroy */ + NULL, /* set_values */ + NULL, /* extension */ + }, + /* form */ + { + Layout, /* layout */ + }, + /* viewport */ + { + NULL, /* extension */ + }, +}; + +WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec; + +/* + * Implementation + */ +static Widget +CreateScrollbar(ViewportWidget w, Bool horizontal) +{ + static Arg barArgs[] = { + {XtNorientation, 0}, + {XtNlength, 0}, + {XtNleft, 0}, + {XtNright, 0}, + {XtNtop, 0}, + {XtNbottom, 0}, + {XtNmappedWhenManaged, False}, + }; + Widget clip = w->viewport.clip; + ViewportConstraints constraints = + (ViewportConstraints)clip->core.constraints; + Widget bar; + + XtSetArg(barArgs[0], XtNorientation, + horizontal ? XtorientHorizontal : XtorientVertical); + XtSetArg(barArgs[1], XtNlength, + horizontal ? XtWidth(clip) : XtHeight(clip)); + XtSetArg(barArgs[2], XtNleft, + !horizontal && w->viewport.useright ? XtChainRight : XtChainLeft); + XtSetArg(barArgs[3], XtNright, + !horizontal && !w->viewport.useright ? XtChainLeft : XtChainRight); + XtSetArg(barArgs[4], XtNtop, + horizontal && w->viewport.usebottom ? XtChainBottom: XtChainTop); + XtSetArg(barArgs[5], XtNbottom, + horizontal && !w->viewport.usebottom ? XtChainTop: XtChainBottom); + + bar = XtCreateWidget(horizontal ? "horizontal" : "vertical", + scrollbarWidgetClass, (Widget)w, + barArgs, XtNumber(barArgs)); + XtAddCallback(bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w); + XtAddCallback(bar, XtNjumpProc, ThumbProc, (XtPointer)w); + + if (horizontal) { + w->viewport.horiz_bar = bar; + constraints->form.vert_base = bar; + } + else { + w->viewport.vert_bar = bar; + constraints->form.horiz_base = bar; + } + + XtManageChild(bar); + + return (bar); +} + +/*ARGSUSED*/ +static void +XawViewportInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ViewportWidget w = (ViewportWidget)cnew; + static Arg clip_args[8]; + Cardinal arg_cnt; + Widget h_bar, v_bar; + Dimension clip_height, clip_width; + + w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */ + + /* + * Initialize all widget pointers to NULL + */ + w->viewport.child = NULL; + w->viewport.horiz_bar = w->viewport.vert_bar = NULL; + + /* + * Create Clip Widget + */ + arg_cnt = 0; + XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w)); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w)); arg_cnt++; + + w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew, + clip_args, arg_cnt); + + if (!w->viewport.forcebars) + return; /* If we are not forcing the bars then we are done */ + + if (w->viewport.allowhoriz) + (void)CreateScrollbar(w, True); + if (w->viewport.allowvert) + (void)CreateScrollbar(w, False); + + h_bar = w->viewport.horiz_bar; + v_bar = w->viewport.vert_bar; + + /* + * Set the clip widget to the correct height + */ + clip_width = XtWidth(w); + clip_height = XtHeight(w); + + if (h_bar != NULL && XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar)) + clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar); + + if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar)) + clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar); + + arg_cnt = 0; + XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++; + XtSetValues(w->viewport.clip, clip_args, arg_cnt); +} + +/*ARGSUSED*/ +static void +XawViewportConstraintInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ((ViewportConstraints)cnew->core.constraints)->viewport.reparented = False; +} + +static void +XawViewportRealize(Widget widget, XtValueMask *value_mask, + XSetWindowAttributes *attributes) +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + *value_mask |= CWBitGravity; + attributes->bit_gravity = NorthWestGravity; + (*Superclass->core_class.realize)(widget, value_mask, attributes); + + (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */ + + if (child != NULL) { + XtMoveWidget(child, 0, 0); + XtRealizeWidget(clip); + XtRealizeWidget(child); + XReparentWindow(XtDisplay(w), XtWindow(child), XtWindow(clip), 0, 0); + XtMapWidget(child); + } +} + +/*ARGSUSED*/ +static Boolean +XawViewportSetValues(Widget current, Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ViewportWidget w = (ViewportWidget)cnew; + ViewportWidget cw = (ViewportWidget)current; + + if (w->viewport.forcebars != cw->viewport.forcebars + || w->viewport.allowvert != cw->viewport.allowvert + || w->viewport.allowhoriz != cw->viewport.allowhoriz + || w->viewport.useright != cw->viewport.useright + || w->viewport.usebottom != cw->viewport.usebottom) + (*w->core.widget_class->core_class.resize)(cnew); /* Recompute layout */ + + return (False); +} + +static void +XawViewportChangeManaged(Widget widget) +{ + ViewportWidget w = (ViewportWidget)widget; + int num_children = w->composite.num_children; + Widget child, *childP; + int i; + + child = NULL; + for (childP = w->composite.children, + i = 0; i < num_children; + childP++, i++) { + if (XtIsManaged(*childP) + && *childP != w->viewport.clip + && *childP != w->viewport.horiz_bar + && *childP != w->viewport.vert_bar) { + child = *childP; + break; + } + } + + if (child != w->viewport.child) { + w->viewport.child = child; + if (child != NULL) { + XtResizeWidget(child, XtWidth(child), XtHeight(child), 0); + if (XtIsRealized(widget)) { + ViewportConstraints constraints = + (ViewportConstraints)child->core.constraints; + if (!XtIsRealized(child)) { + Window window = XtWindow(w); + + XtMoveWidget(child, 0, 0); + w->core.window = XtWindow(w->viewport.clip); + XtRealizeWidget(child); + w->core.window = window; + constraints->viewport.reparented = True; + } + else if (!constraints->viewport.reparented) { + XReparentWindow(XtDisplay(w), XtWindow(child), + XtWindow(w->viewport.clip), 0, 0); + constraints->viewport.reparented = True; + if (child->core.mapped_when_managed) + XtMapWidget(child); + } + } + GetGeometry(widget, XtWidth(child), XtHeight(child)); + (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout) + ((FormWidget)w, XtWidth(w), XtHeight(w), True /* True? */); + } + } + +#ifdef notdef + (*Superclass->composite_class.change_managed)(widget); +#endif +} + +static void +SetBar(Widget w, int top, unsigned int length, unsigned int total) +{ + XawScrollbarSetThumb(w, (float)top / (float)total, + (float)length / (float)total); +} + +static void +RedrawThumbs(ViewportWidget w) +{ + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + if (w->viewport.horiz_bar != NULL) + SetBar(w->viewport.horiz_bar, -(int)XtX(child), + XtWidth(clip), XtWidth(child)); + + if (w->viewport.vert_bar != NULL) + SetBar(w->viewport.vert_bar, -(int)XtY(child), + XtHeight(clip), XtHeight(child)); +} + +static void +SendReport(ViewportWidget w, unsigned int changed) +{ + XawPannerReport rep; + + if (w->viewport.report_callbacks) { + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + rep.changed = changed; + rep.slider_x = -XtX(child); /* child is canvas */ + rep.slider_y = -XtY(child); /* clip is slider */ + rep.slider_width = XtWidth(clip); + rep.slider_height = XtHeight(clip); + rep.canvas_width = XtWidth(child); + rep.canvas_height = XtHeight(child); + XtCallCallbackList((Widget)w, w->viewport.report_callbacks, + (XtPointer)&rep); + } +} + +static void +MoveChild(ViewportWidget w, int x, int y) +{ + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + /* make sure we never move past right/bottom borders */ + if (-x + (int)XtWidth(clip) > XtWidth(child)) + x = -(int)(XtWidth(child) - XtWidth(clip)); + + if (-y + (int)XtHeight(clip) > XtHeight(child)) + y = -(int)(XtHeight(child) - XtHeight(clip)); + + /* make sure we never move past left/top borders */ + if (x >= 0) + x = 0; + if (y >= 0) + y = 0; + + XtMoveWidget(child, x, y); + SendReport(w, (XawPRSliderX | XawPRSliderY)); + + RedrawThumbs(w); +} + +static void +ComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars) +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + ViewportConstraints constraints = + (ViewportConstraints)clip->core.constraints; + Bool needshoriz, needsvert; + int clip_width, clip_height; + XtWidgetGeometry intended; + + if (child == NULL) + return; + + clip_width = XtWidth(w); + clip_height = XtHeight(w); + intended.request_mode = CWBorderWidth; + intended.border_width = 0; + + if (w->viewport.forcebars) { + needsvert = w->viewport.allowvert; + needshoriz = w->viewport.allowhoriz; + ComputeWithForceBars(widget, query, &intended, + &clip_width, &clip_height); + } + else { + Dimension prev_width, prev_height; + XtGeometryMask prev_mode; + XtWidgetGeometry preferred; + + needshoriz = needsvert = False; + + /* + * intended.{width,height} caches the eventual child dimensions, + * but we don't set the mode bits until after we decide that the + * child's preferences are not acceptable + */ + if (!w->viewport.allowhoriz) + intended.request_mode |= CWWidth; + + if (XtWidth(child) < clip_width) + intended.width = clip_width; + else + intended.width = XtWidth(child); + + if (XtHeight(child) < clip_height) + intended.height = clip_height; + else + intended.height = XtHeight(child); + + if (!w->viewport.allowvert) + intended.request_mode |= CWHeight; + + if (!query) { + preferred.width = XtWidth(child); + preferred.height = XtHeight(child); + } + do { /* while intended != prev */ + if (query) { + (void)XtQueryGeometry(child, &intended, &preferred); + if (!(preferred.request_mode & CWWidth)) + preferred.width = intended.width; + if (!(preferred.request_mode & CWHeight)) + preferred.height = intended.height; + } + prev_width = intended.width; + prev_height = intended.height; + prev_mode = intended.request_mode; + /* + * note that having once decided to turn on either bar + * we'll not change our mind until we're next resized, + * thus avoiding potential oscillations + */ +#define CheckHoriz() \ + if (w->viewport.allowhoriz && \ + preferred.width > clip_width) { \ + if (!needshoriz) { \ + Widget bar; \ + \ + needshoriz = True; \ + if ((bar = w->viewport.horiz_bar) == NULL) \ + bar = CreateScrollbar(w, True); \ + clip_height -= XtHeight(bar) + XtBorderWidth(bar); \ + if (clip_height < 1) \ + clip_height = 1; \ + } \ + intended.width = preferred.width; \ + } + + CheckHoriz(); + if (w->viewport.allowvert && preferred.height > clip_height) { + if (!needsvert) { + Widget bar; + needsvert = True; + if ((bar = w->viewport.vert_bar) == NULL) + bar = CreateScrollbar(w, False); + clip_width -= XtWidth(bar) + XtBorderWidth(bar); + if (clip_width < 1) + clip_width = 1; + CheckHoriz(); + } + intended.height = preferred.height; + } + if (!w->viewport.allowhoriz || preferred.width < clip_width) { + intended.width = clip_width; + intended.request_mode |= CWWidth; + } + if (!w->viewport.allowvert || preferred.height < clip_height) { + intended.height = clip_height; + intended.request_mode |= CWHeight; + } + } while (intended.request_mode != prev_mode + || (intended.request_mode & CWWidth + && intended.width != prev_width) + || (intended.request_mode & CWHeight + && intended.height != prev_height)); + } + + if (XtIsRealized(clip)) + XRaiseWindow(XtDisplay(clip), XtWindow(clip)); + + XtMoveWidget(clip, + needsvert ? w->viewport.useright ? 0 : + XtWidth(w->viewport.vert_bar) + + XtBorderWidth(w->viewport.vert_bar) : 0, + needshoriz ? w->viewport.usebottom ? 0 : + XtHeight(w->viewport.horiz_bar) + + XtBorderWidth(w->viewport.horiz_bar) : 0); + XtResizeWidget(clip, clip_width, clip_height, 0); + + if (w->viewport.horiz_bar != NULL) { + Widget bar = w->viewport.horiz_bar; + + if (!needshoriz) { + constraints->form.vert_base = NULL; + if (destroy_scrollbars) { + XtDestroyWidget(bar); + w->viewport.horiz_bar = NULL; + } + } + else { + int bw = XtBorderWidth(bar); + + XtResizeWidget(bar, clip_width, XtHeight(bar), bw); + XtMoveWidget(bar, + needsvert && !w->viewport.useright + ? XtWidth(w->viewport.vert_bar) : -bw, + w->viewport.usebottom + ? XtHeight(w) - XtHeight(bar) - bw : -bw); + XtSetMappedWhenManaged(bar, True); + } + } + + if (w->viewport.vert_bar != NULL) { + Widget bar = w->viewport.vert_bar; + + if (!needsvert) { + constraints->form.horiz_base = NULL; + if (destroy_scrollbars) { + XtDestroyWidget(bar); + w->viewport.vert_bar = NULL; + } + } + else { + int bw = bar->core.border_width; + + XtResizeWidget(bar, XtWidth(bar), clip_height, bw); + XtMoveWidget(bar, + w->viewport.useright + ? XtWidth(w) - XtWidth(bar) - bw : -bw, + needshoriz && !w->viewport.usebottom + ? XtHeight(w->viewport.horiz_bar) : -bw); + XtSetMappedWhenManaged(bar, True); + } + } + + if (child != NULL) { + XtResizeWidget(child, intended.width, intended.height, 0); + MoveChild(w, needshoriz ? XtX(child) : 0, needsvert ? XtY(child) : 0); + } + + SendReport (w, XawPRAll); +} + +/* + * Function: + * ComputeWithForceBars + * + * Parameters: + * widget - viewport widget + * query - whether or not to query the child + * intended - cache of the childs height is stored here + * (used and returned) + * clip_width - size of clip window (used and returned) + * clip_height - "" + * + * Description: + * Computes the layout give forcebars is set. + */ +static void +ComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended, + int *clip_width, int *clip_height) +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + XtWidgetGeometry preferred; + + /* + * If forcebars then needs = allows = has + * Thus if needsvert is set it MUST have a scrollbar + */ + if (w->viewport.allowvert) { + if (w->viewport.vert_bar == NULL) + w->viewport.vert_bar = CreateScrollbar(w, False); + + *clip_width -= XtWidth(w->viewport.vert_bar) + + XtBorderWidth(w->viewport.vert_bar); + } + + if (w->viewport.allowhoriz) { + if (w->viewport.horiz_bar == NULL) + w->viewport.horiz_bar = CreateScrollbar(w, True); + + *clip_height -= XtHeight(w->viewport.horiz_bar) + + XtBorderWidth(w->viewport.horiz_bar); + } + + AssignMax(*clip_width, 1); + AssignMax(*clip_height, 1); + + if (!w->viewport.allowvert) { + intended->height = *clip_height; + intended->request_mode = CWHeight; + } + if (!w->viewport.allowhoriz) { + intended->width = *clip_width; + intended->request_mode = CWWidth; + } + + if (query) { + if (w->viewport.allowvert || w->viewport.allowhoriz) { + XtQueryGeometry(child, intended, &preferred); + + if (!(intended->request_mode & CWWidth)) { + if (preferred.request_mode & CWWidth) + intended->width = preferred.width; + else + intended->width = XtWidth(child); + } + + if (!(intended->request_mode & CWHeight)) { + if (preferred.request_mode & CWHeight) + intended->height = preferred.height; + else + intended->height = XtHeight(child); + } + } + } + else { + if (w->viewport.allowvert) + intended->height = XtHeight(child); + if (w->viewport.allowhoriz) + intended->width = XtWidth(child); + } + + if (*clip_width > (int)intended->width) + intended->width = *clip_width; + if (*clip_height > (int)intended->height) + intended->height = *clip_height; +} + +static void +XawViewportResize(Widget widget) +{ + ComputeLayout(widget, True, True); +} + +/*ARGSUSED*/ +static Boolean +Layout(FormWidget w, unsigned int width, unsigned int height, Bool force) +{ + ComputeLayout((Widget)w, True, True); + w->form.preferred_width = XtWidth(w); + w->form.preferred_height = XtHeight(w); + + return (False); +} + +static void +ScrollUpDownProc(Widget widget, XtPointer closure, XtPointer call_data) +{ + ViewportWidget w = (ViewportWidget)closure; + Widget child = w->viewport.child; + int pix = (long)call_data; + int x, y; + + if (child == NULL) + return; + + x = XtX(child) - (widget == w->viewport.horiz_bar ? pix : 0); + y = XtY(child) - (widget == w->viewport.vert_bar ? pix : 0); + MoveChild(w, x, y); +} + +/*ARGSUSED*/ +static void +ThumbProc(Widget widget, XtPointer closure, XtPointer call_data) +{ + ViewportWidget w = (ViewportWidget)closure; + Widget child = w->viewport.child; + float percent = *(float *)call_data; + int x, y; + + if (child == NULL) + return; + + if (widget == w->viewport.horiz_bar) + x = -percent * XtWidth(child); + else + x = XtX(child); + + if (widget == w->viewport.vert_bar) + y = -percent * XtHeight(child); + else + y = XtY(child); + + MoveChild(w, x, y); +} + +static XtGeometryResult +TestSmaller(ViewportWidget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply_return) +{ + if (request->width < XtWidth(w) || request->height < XtHeight(w)) + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); + + return (XtGeometryYes); +} + +static XtGeometryResult +GeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal, + XtWidgetGeometry *request, + XtWidgetGeometry *reply_return) +{ + Widget sb; + XtWidgetGeometry plusScrollbars; + + plusScrollbars = *request; + if ((sb = w->viewport.horiz_bar) == NULL) + sb = CreateScrollbar(w, horizontal); + request->width += XtWidth(sb); + request->height += XtHeight(sb); + XtDestroyWidget(sb); + return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return)); +} + +#define WidthChange() (request->width != XtWidth(w)) +#define HeightChange() (request->height != XtHeight(w)) +static XtGeometryResult +QueryGeometry(ViewportWidget w, XtWidgetGeometry *request, + XtWidgetGeometry *reply_return) +{ + if (w->viewport.allowhoriz && w->viewport.allowvert) + return (TestSmaller(w, request, reply_return)); + + else if (w->viewport.allowhoriz && !w->viewport.allowvert) { + if (WidthChange() && !HeightChange()) + return (TestSmaller(w, request, reply_return)); + else if (!WidthChange() && HeightChange()) + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); + else if (WidthChange() && HeightChange()) + return (GeometryRequestPlusScrollbar(w, True, request, reply_return)); + else /* !WidthChange() && !HeightChange() */ + return (XtGeometryYes); + } + else if (!w->viewport.allowhoriz && w->viewport.allowvert) { + if (!WidthChange() && HeightChange()) + return (TestSmaller(w, request, reply_return)); + else if (WidthChange() && !HeightChange()) + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); + else if (WidthChange() && HeightChange()) + return (GeometryRequestPlusScrollbar(w, False, request, reply_return)); + else /* !WidthChange() && !HeightChange() */ + return (XtGeometryYes); + } + else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */ + return (XtMakeGeometryRequest((Widget)w, request, reply_return)); +} +#undef WidthChange +#undef HeightChange + +static XtGeometryResult +XawViewportGeometryManager(Widget child, XtWidgetGeometry *request, + XtWidgetGeometry *reply) +{ + ViewportWidget w = (ViewportWidget)child->core.parent; + Bool rWidth = (request->request_mode & CWWidth) != 0; + Bool rHeight = (request->request_mode & CWHeight) != 0; + XtWidgetGeometry allowed; + XtGeometryResult result; + Bool reconfigured; + Bool child_changed_size; + unsigned int height_remaining; + + if (request->request_mode & XtCWQueryOnly) + return (QueryGeometry(w, request, reply)); + + if (child != w->viewport.child + || request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth) + || ((request->request_mode & CWBorderWidth) + && request->border_width > 0)) + return (XtGeometryNo); + + allowed = *request; + + reconfigured = GetGeometry((Widget)w, + rWidth ? request->width : XtWidth(w), + rHeight ? request->height : XtHeight(w)); + + child_changed_size = (rWidth && XtWidth(child) != request->width) || + (rHeight && XtHeight(child) != request->height); + + height_remaining = XtHeight(w); + if (rWidth && XtWidth(w) != request->width) { + if (w->viewport.allowhoriz && request->width > XtWidth(w)) { + /* horizontal scrollbar will be needed so possibly reduce height */ + Widget bar; + + if ((bar = w->viewport.horiz_bar) == NULL) + bar = CreateScrollbar(w, True); + height_remaining -= XtHeight(bar) + XtBorderWidth(bar); + reconfigured = True; + } + else + allowed.width = XtWidth(w); + } + if (rHeight && height_remaining != request->height) { + if (w->viewport.allowvert && request->height > height_remaining) { + /* vertical scrollbar will be needed, so possibly reduce width */ + if (!w->viewport.allowhoriz || request->width < XtWidth(w)) { + Widget bar; + + if ((bar = w->viewport.vert_bar) == NULL) + bar = CreateScrollbar(w, False); + if (!rWidth) { + allowed.width = XtWidth(w); + allowed.request_mode |= CWWidth; + } + if (allowed.width > XtWidth(bar) + XtBorderWidth(bar)) + allowed.width -= XtWidth(bar) + XtBorderWidth(bar); + else + allowed.width = 1; + reconfigured = True; + } + } + else + allowed.height = height_remaining; + } + + if (allowed.width != request->width || allowed.height != request->height) { + *reply = allowed; + result = XtGeometryAlmost; + } + else { + if (rWidth) + XtWidth(child) = request->width; + if (rHeight) + XtHeight(child) = request->height; + result = XtGeometryYes; + } + + if (reconfigured || child_changed_size) + ComputeLayout((Widget)w, False, result == XtGeometryYes); + + return (result); +} + +static Bool +GetGeometry(Widget w, unsigned int width, unsigned int height) +{ + XtWidgetGeometry geometry, return_geom; + XtGeometryResult result; + + if (width == XtWidth(w) && height == XtHeight(w)) + return (False); + + geometry.request_mode = CWWidth | CWHeight; + geometry.width = width; + geometry.height = height; + + if (XtIsRealized(w)) { + if (((ViewportWidget)w)->viewport.allowhoriz && width > XtWidth(w)) + geometry.width = XtWidth(w); + if (((ViewportWidget)w)->viewport.allowvert && height > XtHeight(w)) + geometry.height = XtHeight(w); + } + else { + /* This is the Realize call; we'll inherit a w&h iff none currently */ + if (XtWidth(w) != 0) { + if (XtHeight(w) != 0) + return (False); + geometry.width = XtWidth(w); + } + if (XtHeight(w) != 0) + geometry.height = XtHeight(w); + } + + result = XtMakeGeometryRequest(w, &geometry, &return_geom); + if (result == XtGeometryAlmost) + result = XtMakeGeometryRequest(w, &return_geom, NULL); + + return (result == XtGeometryYes); +} + +static XtGeometryResult +XawViewportQueryGeometry(Widget w, XtWidgetGeometry *constraints, + XtWidgetGeometry *reply) +{ + if (((ViewportWidget)w)->viewport.child != NULL) + return (XtQueryGeometry(((ViewportWidget)w)->viewport.child, + constraints, reply)); + + return (XtGeometryYes); +} + +void +XawViewportSetLocation +( + Widget gw, +#if NeedWidePrototypes + double xoff, double yoff +#else + float xoff, float yoff +#endif + ) +{ + ViewportWidget w = (ViewportWidget)gw; + Widget child = w->viewport.child; + int x, y; + + if (xoff > 1.0) /* scroll to right */ + x = XtWidth(child); + else if (xoff < 0.0) /* if the offset is < 0.0 nothing */ + x = XtX(child); + else + x = (float)XtWidth(child) * xoff; + + if (yoff > 1.0) + y = XtHeight(child); + else if (yoff < 0.0) + y = XtY(child); + else + y = (float)XtHeight(child) * yoff; + + MoveChild (w, -x, -y); +} + +void +XawViewportSetCoordinates(Widget gw, +#if NeedWidePrototypes + int x, int y +#else + Position x, Position y +#endif +) +{ + ViewportWidget w = (ViewportWidget)gw; + Widget child = w->viewport.child; + + if (x > XtWidth(child)) + x = XtWidth(child); + else if (x < 0) + x = XtX(child); + + if (y > XtHeight(child)) + y = XtHeight(child); + else if (y < 0) + y = XtY(child); + + MoveChild (w, -x, -y); +} -- cgit v1.2.3