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/Scrollbar.c | 1764 ++++++++++++++++++++++++------------------------ 1 file changed, 882 insertions(+), 882 deletions(-) (limited to 'libXaw/src/Scrollbar.c') diff --git a/libXaw/src/Scrollbar.c b/libXaw/src/Scrollbar.c index 777043063..6413f0bf6 100644 --- a/libXaw/src/Scrollbar.c +++ b/libXaw/src/Scrollbar.c @@ -1,882 +1,882 @@ -/*********************************************************** - -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 "Private.h" - -#define NoButton -1 -#define PICKLENGTH(widget, x, y) \ -(((widget)->scrollbar.orientation == XtorientHorizontal) ? (x) : (y)) - -/* - * Class Methods - */ -static void XawScrollbarClassInitialize(void); -static void XawScrollbarDestroy(Widget); -static void XawScrollbarInitialize(Widget, Widget, ArgList, Cardinal*_args); -static void XawScrollbarRealize(Widget, Mask*, XSetWindowAttributes*); -static void XawScrollbarRedisplay(Widget, XEvent*, Region); -static void XawScrollbarResize(Widget); -static Boolean XawScrollbarSetValues(Widget, Widget, Widget, - ArgList, Cardinal*); - -/* - * Prototypes - */ -static Boolean CompareEvents(XEvent*, XEvent*); -static void CreateGC(Widget); -static float FloatInRange(float, float, float); -static float FractionLoc(ScrollbarWidget, int, int); -static void ExtractPosition(XEvent*, Position*, Position*); -static int InRange(int, int, int); -static void FillArea(ScrollbarWidget, int, int, int); -static Bool LookAhead(Widget, XEvent*); -static void PaintThumb(ScrollbarWidget); -static Bool PeekNotifyEvent(Display*, XEvent*, char*); -static void SetDimensions(ScrollbarWidget); - -/* - * Actions - */ -static void EndScroll(Widget, XEvent*, String*, Cardinal*); -static void MoveThumb(Widget, XEvent*, String*, Cardinal*); -static void NotifyScroll(Widget, XEvent*, String*, Cardinal*); -static void NotifyThumb(Widget, XEvent*, String*, Cardinal*); -static void StartScroll(Widget, XEvent*, String*, Cardinal*); - -/* - * Initialization - */ -static char defaultTranslations[] = -":" "StartScroll(Forward)\n" -":" "StartScroll(Continuous) MoveThumb() NotifyThumb()\n" -":" "StartScroll(Backward)\n" -":" "MoveThumb() NotifyThumb()\n" -":" "NotifyScroll(Proportional) EndScroll()\n"; - -static float floatZero = 0.0; - -#define Offset(field) XtOffsetOf(ScrollbarRec, field) - -static XtResource resources[] = { - { - XtNlength, - XtCLength, - XtRDimension, - sizeof(Dimension), - Offset(scrollbar.length), - XtRImmediate, - (XtPointer)1 - }, - { - XtNthickness, - XtCThickness, - XtRDimension, - sizeof(Dimension), - Offset(scrollbar.thickness), - XtRImmediate, - (XtPointer)14 - }, - { - XtNorientation, - XtCOrientation, - XtROrientation, - sizeof(XtOrientation), - Offset(scrollbar.orientation), - XtRImmediate, - (XtPointer)XtorientVertical - }, - { - XtNscrollProc, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - Offset(scrollbar.scrollProc), - XtRCallback, - NULL - }, - { - XtNthumbProc, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - Offset(scrollbar.thumbProc), - XtRCallback, - NULL - }, - { - XtNjumpProc, - XtCCallback, - XtRCallback, - sizeof(XtPointer), - Offset(scrollbar.jumpProc), - XtRCallback, - NULL - }, - { - XtNthumb, - XtCThumb, - XtRBitmap, - sizeof(Pixmap), - Offset(scrollbar.thumb), - XtRImmediate, - (XtPointer)XtUnspecifiedPixmap - }, - { - XtNforeground, - XtCForeground, - XtRPixel, - sizeof(Pixel), - Offset(scrollbar.foreground), - XtRString, - XtDefaultForeground - }, - { - XtNshown, - XtCShown, - XtRFloat, - sizeof(float), - Offset(scrollbar.shown), - XtRFloat, - (XtPointer)&floatZero - }, - { - XtNtopOfThumb, - XtCTopOfThumb, - XtRFloat, - sizeof(float), - Offset(scrollbar.top), - XtRFloat, - (XtPointer)&floatZero - }, - { - XtNscrollVCursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - Offset(scrollbar.verCursor), - XtRString, - "sb_v_double_arrow" - }, - { - XtNscrollHCursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - Offset(scrollbar.horCursor), - XtRString, - "sb_h_double_arrow" - }, - { - XtNscrollUCursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - Offset(scrollbar.upCursor), - XtRString, - "sb_up_arrow" - }, - { - XtNscrollDCursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - Offset(scrollbar.downCursor), - XtRString, - "sb_down_arrow" - }, - { - XtNscrollLCursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - Offset(scrollbar.leftCursor), - XtRString, - "sb_left_arrow" - }, - { - XtNscrollRCursor, - XtCCursor, - XtRCursor, - sizeof(Cursor), - Offset(scrollbar.rightCursor), - XtRString, - "sb_right_arrow" - }, - { - XtNminimumThumb, - XtCMinimumThumb, - XtRDimension, - sizeof(Dimension), - Offset(scrollbar.min_thumb), - XtRImmediate, - (XtPointer)7 - }, -}; -#undef Offset - -static XtActionsRec actions[] = { - {"StartScroll", StartScroll}, - {"MoveThumb", MoveThumb}, - {"NotifyThumb", NotifyThumb}, - {"NotifyScroll", NotifyScroll}, - {"EndScroll", EndScroll}, -}; - -#define Superclass (&simpleClassRec) -ScrollbarClassRec scrollbarClassRec = { - /* core */ - { - (WidgetClass)&simpleClassRec, /* superclass */ - "Scrollbar", /* class_name */ - sizeof(ScrollbarRec), /* widget_size */ - XawScrollbarClassInitialize, /* class_initialize */ - NULL, /* class_part_init */ - False, /* class_inited */ - XawScrollbarInitialize, /* initialize */ - NULL, /* initialize_hook */ - XawScrollbarRealize, /* realize */ - actions, /* actions */ - XtNumber(actions), /* num_actions */ - resources, /* resources */ - XtNumber(resources), /* num_resources */ - NULLQUARK, /* xrm_class */ - True, /* compress_motion */ - True, /* compress_exposure */ - True, /* compress_enterleave */ - False, /* visible_interest */ - XawScrollbarDestroy, /* destroy */ - XawScrollbarResize, /* resize */ - XawScrollbarRedisplay, /* expose */ - XawScrollbarSetValues, /* set_values */ - NULL, /* set_values_hook */ - XtInheritSetValuesAlmost, /* set_values_almost */ - NULL, /* get_values_hook */ - NULL, /* accept_focus */ - XtVersion, /* version */ - NULL, /* callback_private */ - defaultTranslations, /* tm_table */ - XtInheritQueryGeometry, /* query_geometry */ - XtInheritDisplayAccelerator, /* display_accelerator */ - NULL, /* extension */ - }, - /* simple */ - { - XtInheritChangeSensitive, /* change_sensitive */ - }, - /* scrollbar */ - { - NULL, /* extension */ - }, -}; - -WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec; - -/* - * Implementation - */ -static void -XawScrollbarClassInitialize(void) -{ - XawInitializeWidgetSet(); - XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation, - NULL, 0); - XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString, - NULL, 0, XtCacheNone, NULL); -} - -/* - * Make sure the first number is within the range specified by the other - * two numbers. - */ -static int -InRange(int num, int small, int big) -{ - return ((num < small) ? small : ((num > big) ? big : num)); -} - -/* - * Same as above, but for floating numbers - */ -static float -FloatInRange(float num, float small, float big) -{ - return ((num < small) ? small : ((num > big) ? big : num)); -} - -/* Fill the area specified by top and bottom with the given pattern */ -static float -FractionLoc(ScrollbarWidget w, int x, int y) -{ - float result; - - result = PICKLENGTH(w, x / (float)XtWidth(w), y / (float)XtHeight(w)); - - return (FloatInRange(result, 0.0, 1.0)); -} - -static void -FillArea(ScrollbarWidget w, int top, int bottom, int thumb) -{ - Dimension length; - - top = XawMax(1, top); - if (w->scrollbar.orientation == XtorientHorizontal) - bottom = XawMin(bottom, XtWidth(w) - 1); - else - bottom = XawMin(bottom, XtHeight(w) - 1); - - if (bottom <= top) - return; - - length = bottom - top; - - switch(thumb) { - /* Fill the new Thumb location */ - case 1: - if (w->scrollbar.orientation == XtorientHorizontal) - XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc, - top, 1, length, XtHeight(w) - 2); - else - XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc, - 1, top, XtWidth(w) - 2, length); - break; - /* Clear the old Thumb location */ - case 0: - if (w->scrollbar.orientation == XtorientHorizontal) - XClearArea(XtDisplay(w), XtWindow(w), - top, 1, length, XtHeight(w) - 2, False); - else - XClearArea(XtDisplay(w), XtWindow(w), - 1, top, XtWidth(w) - 2, length, False); - break; - } -} - - -/* Paint the thumb in the area specified by w->top and - w->shown. The old area is erased. The painting and - erasing is done cleverly so that no flickering will occur. */ -static void -PaintThumb(ScrollbarWidget w) -{ - Position oldtop, oldbot, newtop, newbot; - - oldtop = w->scrollbar.topLoc; - oldbot = oldtop + w->scrollbar.shownLength; - newtop = w->scrollbar.length * w->scrollbar.top; - newbot = newtop + (int)(w->scrollbar.length * w->scrollbar.shown); - if (newbot < newtop + (int)w->scrollbar.min_thumb) - newbot = newtop + w->scrollbar.min_thumb; - w->scrollbar.topLoc = newtop; - w->scrollbar.shownLength = newbot - newtop; - - if (XtIsRealized((Widget)w)) { - if (newtop < oldtop) - FillArea(w, newtop, XawMin(newbot, oldtop), 1); - if (newtop > oldtop) - FillArea(w, oldtop, XawMin(newtop, oldbot), 0); - if (newbot < oldbot) - FillArea(w, XawMax(newbot, oldtop), oldbot, 0); - if (newbot > oldbot) - FillArea(w, XawMax(newtop, oldbot), newbot, 1); - } -} - -static void -SetDimensions(ScrollbarWidget w) -{ - if (w->scrollbar.orientation == XtorientVertical) { - w->scrollbar.length = XtHeight(w); - w->scrollbar.thickness = XtWidth(w); - } - else { - w->scrollbar.length = XtWidth(w); - w->scrollbar.thickness = XtHeight(w); - } -} - -static void -XawScrollbarDestroy(Widget w) -{ - ScrollbarWidget sbw = (ScrollbarWidget)w; - - XtReleaseGC(w, sbw->scrollbar.gc); -} - -static void -CreateGC(Widget w) -{ - ScrollbarWidget sbw = (ScrollbarWidget)w; - XGCValues gcValues; - XtGCMask mask; - unsigned int depth = 1; - - if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) - sbw->scrollbar.thumb = XmuCreateStippledPixmap(XtScreen(w), - (Pixel)1, (Pixel)0, - depth); - else if (sbw->scrollbar.thumb != None) { - Window root; - int x, y; - unsigned int width, height, bw; - - XGetGeometry(XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y, - &width, &height, &bw, &depth); - } - - gcValues.foreground = sbw->scrollbar.foreground; - gcValues.background = sbw->core.background_pixel; - mask = GCForeground | GCBackground; - - if (sbw->scrollbar.thumb != None) { - if (depth == 1) { - gcValues.fill_style = FillOpaqueStippled; - gcValues.stipple = sbw->scrollbar.thumb; - mask |= GCFillStyle | GCStipple; - } - else { - gcValues.fill_style = FillTiled; - gcValues.tile = sbw->scrollbar.thumb; - mask |= GCFillStyle | GCTile; - } - } - sbw->scrollbar.gc = XtGetGC(w, mask, &gcValues); -} - -/* ARGSUSED */ -static void -XawScrollbarInitialize(Widget request, Widget cnew, - ArgList args, Cardinal *num_args) -{ - ScrollbarWidget w = (ScrollbarWidget)cnew; - - CreateGC(cnew); - - if (XtWidth(w) == 0) - XtWidth(w) = w->scrollbar.orientation == XtorientVertical ? - w->scrollbar.thickness : w->scrollbar.length; - - if (XtHeight(w) == 0) - XtHeight(w) = w->scrollbar.orientation == XtorientHorizontal ? - w->scrollbar.thickness : w->scrollbar.length; - - SetDimensions(w); - w->scrollbar.direction = 0; - w->scrollbar.topLoc = 0; - w->scrollbar.shownLength = w->scrollbar.min_thumb; -} - -static void -XawScrollbarRealize(Widget gw, Mask *valueMask, - XSetWindowAttributes *attributes) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - - w->scrollbar.inactiveCursor = w->scrollbar.orientation == XtorientVertical ? - w->scrollbar.verCursor : w->scrollbar.horCursor; - - XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL); - - /* - * The Simple widget actually stuffs the value in the valuemask - */ - (*scrollbarWidgetClass->core_class.superclass->core_class.realize) - (gw, valueMask, attributes); -} - -/*ARGSUSED*/ -static Boolean -XawScrollbarSetValues(Widget current, Widget request, Widget desired, - ArgList args, Cardinal *num_args) -{ - ScrollbarWidget w = (ScrollbarWidget)current; - ScrollbarWidget dw = (ScrollbarWidget)desired; - Boolean redraw = False; - - /* - * If these values are outside the acceptable range ignore them... - */ - if (dw->scrollbar.top < 0.0 || dw->scrollbar.top > 1.0) - dw->scrollbar.top = w->scrollbar.top; - - if (dw->scrollbar.shown < 0.0 || dw->scrollbar.shown > 1.0) - dw->scrollbar.shown = w->scrollbar.shown; - - if (XtIsRealized (desired)) { - if (w->scrollbar.foreground != dw->scrollbar.foreground || - w->core.background_pixel != dw->core.background_pixel || - w->scrollbar.thumb != dw->scrollbar.thumb) { - XtReleaseGC((Widget)dw, w->scrollbar.gc); - CreateGC((Widget)dw); - redraw = True; - } - if (w->scrollbar.top != dw->scrollbar.top || - w->scrollbar.shown != dw->scrollbar.shown) - redraw = True; - } - - return (redraw); -} - -static void -XawScrollbarResize(Widget gw) -{ - /* ForgetGravity has taken care of background, but thumb may - * have to move as a result of the new size. */ - SetDimensions((ScrollbarWidget)gw); - XawScrollbarRedisplay(gw, NULL, NULL); -} - -/*ARGSUSED*/ -static void -XawScrollbarRedisplay(Widget gw, XEvent *event, Region region) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - int x, y; - unsigned int width, height; - - if (Superclass->core_class.expose) - (*Superclass->core_class.expose)(gw, event, region); - - if (w->scrollbar.orientation == XtorientHorizontal) { - x = w->scrollbar.topLoc; - y = 1; - width = w->scrollbar.shownLength; - height = XtHeight(w) - 2; - } - else { - x = 1; - y = w->scrollbar.topLoc; - width = XtWidth(w) - 2; - height = w->scrollbar.shownLength; - } - - if (region == NULL || - XRectInRegion(region, x, y, width, height) != RectangleOut) { - /* Forces entire thumb to be painted */ - w->scrollbar.topLoc = -(w->scrollbar.length + 1); - PaintThumb(w); - } -} - -/*ARGSUSED*/ -static void -StartScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - Cursor cursor; - char direction; - - if (w->scrollbar.direction != 0) /* if we're already scrolling */ - return; - if (*num_params > 0) - direction = *params[0]; - else - direction = 'C'; - - w->scrollbar.direction = direction; - - switch(direction) { - case 'B': - case 'b': - cursor = w->scrollbar.orientation == XtorientVertical ? - w->scrollbar.downCursor : w->scrollbar.rightCursor; - break; - case 'F': - case 'f': - cursor = w->scrollbar.orientation == XtorientVertical ? - w->scrollbar.upCursor : w->scrollbar.leftCursor; - break; - case 'C': - case 'c': - cursor = w->scrollbar.orientation == XtorientVertical ? - w->scrollbar.rightCursor : w->scrollbar.upCursor; - break; - default: - return; /* invalid invocation */ - } - - XtVaSetValues(gw, XtNcursor, cursor, NULL); - - XFlush(XtDisplay(w)); -} - -static Boolean -CompareEvents(XEvent *oldEvent, XEvent *newEvent) -{ -#define Check(field) if (newEvent->field != oldEvent->field) return (False) - - Check(xany.display); - Check(xany.type); - Check(xany.window); - - switch(newEvent->type) { - case MotionNotify: - Check(xmotion.state); - break; - case ButtonPress: - case ButtonRelease: - Check(xbutton.state); - Check(xbutton.button); - break; - case KeyPress: - case KeyRelease: - Check(xkey.state); - Check(xkey.keycode); - break; - case EnterNotify: - case LeaveNotify: - Check(xcrossing.mode); - Check(xcrossing.detail); - Check(xcrossing.state); - break; - } -#undef Check - - return (True); -} - -struct EventData { - XEvent *oldEvent; - int count; -}; - -static Bool -PeekNotifyEvent(Display *dpy, XEvent *event, char *args) -{ - struct EventData *eventData = (struct EventData*)args; - - return (++eventData->count == QLength(dpy) /* since PeekIf blocks */ - || CompareEvents(event, eventData->oldEvent)); -} - -static Bool -LookAhead(Widget w, XEvent *event) -{ - XEvent newEvent; - struct EventData eventData; - - if (QLength(XtDisplay(w)) == 0) - return (False); - - eventData.count = 0; - eventData.oldEvent = event; - - XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData); - - if (CompareEvents(event, &newEvent)) - return (True); - - return (False); -} - -static void -ExtractPosition(XEvent *event, Position *x, Position *y) -{ - switch(event->type) { - case MotionNotify: - *x = event->xmotion.x; - *y = event->xmotion.y; - break; - case ButtonPress: - case ButtonRelease: - *x = event->xbutton.x; - *y = event->xbutton.y; - break; - case KeyPress: - case KeyRelease: - *x = event->xkey.x; - *y = event->xkey.y; - break; - case EnterNotify: - case LeaveNotify: - *x = event->xcrossing.x; - *y = event->xcrossing.y; - break; - default: - *x = 0; - *y = 0; - break; - } -} - -static void -NotifyScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - long call_data = 0; - char style; - Position x, y; - - if (w->scrollbar.direction == 0) /* if no StartScroll */ - return; - - if (LookAhead(gw, event)) - return; - - if (*num_params > 0) - style = *params[0]; - else - style = 'P'; - - switch(style) { - case 'P': /* Proportional */ - case 'p': - ExtractPosition(event, &x, &y); - call_data = InRange(PICKLENGTH(w, x, y), 0, (int)w->scrollbar.length); - break; - case 'F': /* FullLength */ - case 'f': - call_data = w->scrollbar.length; - break; - } - - switch(w->scrollbar.direction) { - case 'B': - case 'b': - call_data = -call_data; - /*FALLTHROUGH*/ - case 'F': - case 'f': - XtCallCallbacks(gw, XtNscrollProc, (XtPointer)call_data); - break; - case 'C': - case 'c': /* NotifyThumb has already called the thumbProc(s) */ - break; - } -} - -/*ARGSUSED*/ -static void -EndScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - - XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL); - XFlush(XtDisplay(w)); /* make sure it get propogated */ - - w->scrollbar.direction = 0; -} - -/*ARGSUSED*/ -static void -MoveThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - Position x, y; - - if (w->scrollbar.direction == 0) /* if no StartScroll */ - return; - - if (LookAhead(gw, event)) - return; - - if (!event->xmotion.same_screen) - return; - - ExtractPosition(event, &x, &y); - w->scrollbar.top = FractionLoc(w, x, y); -} - -/*ARGSUSED*/ -static void -NotifyThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - union { - XtPointer xtp; - float xtf; - } xtpf; - - if (w->scrollbar.direction == 0) /* if no StartScroll */ - return; - - if (LookAhead(gw, event)) - return; - - /* thumbProc is not pretty, but is necessary for backwards - compatibility on those architectures for which it work{s,ed}; - the intent is to pass a (truncated) float by value. */ - xtpf.xtf = w->scrollbar.top; - XtCallCallbacks(gw, XtNthumbProc, xtpf.xtp); - XtCallCallbacks(gw, XtNjumpProc, (XtPointer)&w->scrollbar.top); - - PaintThumb(w); -} - -/* - * Public routines - */ -/* Set the scroll bar to the given location. */ -void -XawScrollbarSetThumb(Widget gw, -#if NeedWidePrototypes - double top, double shown -#else - float top, float shown -#endif - ) -{ - ScrollbarWidget w = (ScrollbarWidget)gw; - - if (w->scrollbar.direction == 'c') /* if still thumbing */ - return; - - w->scrollbar.top = top > 1.0 ? 1.0 : top >= 0.0 ? top : w->scrollbar.top; - - w->scrollbar.shown = shown > 1.0 ? 1.0 : shown >= 0.0 ? - shown : w->scrollbar.shown; - PaintThumb(w); -} +/*********************************************************** + +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 "Private.h" + +#define NoButton -1 +#define PICKLENGTH(widget, x, y) \ +(((widget)->scrollbar.orientation == XtorientHorizontal) ? (x) : (y)) + +/* + * Class Methods + */ +static void XawScrollbarClassInitialize(void); +static void XawScrollbarDestroy(Widget); +static void XawScrollbarInitialize(Widget, Widget, ArgList, Cardinal*_args); +static void XawScrollbarRealize(Widget, Mask*, XSetWindowAttributes*); +static void XawScrollbarRedisplay(Widget, XEvent*, Region); +static void XawScrollbarResize(Widget); +static Boolean XawScrollbarSetValues(Widget, Widget, Widget, + ArgList, Cardinal*); + +/* + * Prototypes + */ +static Boolean CompareEvents(XEvent*, XEvent*); +static void CreateGC(Widget); +static float FloatInRange(float, float, float); +static float FractionLoc(ScrollbarWidget, int, int); +static void ExtractPosition(XEvent*, Position*, Position*); +static int InRange(int, int, int); +static void FillArea(ScrollbarWidget, int, int, int); +static Bool LookAhead(Widget, XEvent*); +static void PaintThumb(ScrollbarWidget); +static Bool PeekNotifyEvent(Display*, XEvent*, char*); +static void SetDimensions(ScrollbarWidget); + +/* + * Actions + */ +static void EndScroll(Widget, XEvent*, String*, Cardinal*); +static void MoveThumb(Widget, XEvent*, String*, Cardinal*); +static void NotifyScroll(Widget, XEvent*, String*, Cardinal*); +static void NotifyThumb(Widget, XEvent*, String*, Cardinal*); +static void StartScroll(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +static char defaultTranslations[] = +":" "StartScroll(Forward)\n" +":" "StartScroll(Continuous) MoveThumb() NotifyThumb()\n" +":" "StartScroll(Backward)\n" +":" "MoveThumb() NotifyThumb()\n" +":" "NotifyScroll(Proportional) EndScroll()\n"; + +static float floatZero = 0.0; + +#define Offset(field) XtOffsetOf(ScrollbarRec, field) + +static XtResource resources[] = { + { + XtNlength, + XtCLength, + XtRDimension, + sizeof(Dimension), + Offset(scrollbar.length), + XtRImmediate, + (XtPointer)1 + }, + { + XtNthickness, + XtCThickness, + XtRDimension, + sizeof(Dimension), + Offset(scrollbar.thickness), + XtRImmediate, + (XtPointer)14 + }, + { + XtNorientation, + XtCOrientation, + XtROrientation, + sizeof(XtOrientation), + Offset(scrollbar.orientation), + XtRImmediate, + (XtPointer)XtorientVertical + }, + { + XtNscrollProc, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + Offset(scrollbar.scrollProc), + XtRCallback, + NULL + }, + { + XtNthumbProc, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + Offset(scrollbar.thumbProc), + XtRCallback, + NULL + }, + { + XtNjumpProc, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + Offset(scrollbar.jumpProc), + XtRCallback, + NULL + }, + { + XtNthumb, + XtCThumb, + XtRBitmap, + sizeof(Pixmap), + Offset(scrollbar.thumb), + XtRImmediate, + (XtPointer)XtUnspecifiedPixmap + }, + { + XtNforeground, + XtCForeground, + XtRPixel, + sizeof(Pixel), + Offset(scrollbar.foreground), + XtRString, + XtDefaultForeground + }, + { + XtNshown, + XtCShown, + XtRFloat, + sizeof(float), + Offset(scrollbar.shown), + XtRFloat, + (XtPointer)&floatZero + }, + { + XtNtopOfThumb, + XtCTopOfThumb, + XtRFloat, + sizeof(float), + Offset(scrollbar.top), + XtRFloat, + (XtPointer)&floatZero + }, + { + XtNscrollVCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.verCursor), + XtRString, + "sb_v_double_arrow" + }, + { + XtNscrollHCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.horCursor), + XtRString, + "sb_h_double_arrow" + }, + { + XtNscrollUCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.upCursor), + XtRString, + "sb_up_arrow" + }, + { + XtNscrollDCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.downCursor), + XtRString, + "sb_down_arrow" + }, + { + XtNscrollLCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.leftCursor), + XtRString, + "sb_left_arrow" + }, + { + XtNscrollRCursor, + XtCCursor, + XtRCursor, + sizeof(Cursor), + Offset(scrollbar.rightCursor), + XtRString, + "sb_right_arrow" + }, + { + XtNminimumThumb, + XtCMinimumThumb, + XtRDimension, + sizeof(Dimension), + Offset(scrollbar.min_thumb), + XtRImmediate, + (XtPointer)7 + }, +}; +#undef Offset + +static XtActionsRec actions[] = { + {"StartScroll", StartScroll}, + {"MoveThumb", MoveThumb}, + {"NotifyThumb", NotifyThumb}, + {"NotifyScroll", NotifyScroll}, + {"EndScroll", EndScroll}, +}; + +#define Superclass (&simpleClassRec) +ScrollbarClassRec scrollbarClassRec = { + /* core */ + { + (WidgetClass)&simpleClassRec, /* superclass */ + "Scrollbar", /* class_name */ + sizeof(ScrollbarRec), /* widget_size */ + XawScrollbarClassInitialize, /* class_initialize */ + NULL, /* class_part_init */ + False, /* class_inited */ + XawScrollbarInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawScrollbarRealize, /* realize */ + actions, /* actions */ + XtNumber(actions), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawScrollbarDestroy, /* destroy */ + XawScrollbarResize, /* resize */ + XawScrollbarRedisplay, /* expose */ + XawScrollbarSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* scrollbar */ + { + NULL, /* extension */ + }, +}; + +WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec; + +/* + * Implementation + */ +static void +XawScrollbarClassInitialize(void) +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation, + NULL, 0); + XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString, + NULL, 0, XtCacheNone, NULL); +} + +/* + * Make sure the first number is within the range specified by the other + * two numbers. + */ +static int +InRange(int num, int small, int big) +{ + return ((num < small) ? small : ((num > big) ? big : num)); +} + +/* + * Same as above, but for floating numbers + */ +static float +FloatInRange(float num, float small, float big) +{ + return ((num < small) ? small : ((num > big) ? big : num)); +} + +/* Fill the area specified by top and bottom with the given pattern */ +static float +FractionLoc(ScrollbarWidget w, int x, int y) +{ + float result; + + result = PICKLENGTH(w, x / (float)XtWidth(w), y / (float)XtHeight(w)); + + return (FloatInRange(result, 0.0, 1.0)); +} + +static void +FillArea(ScrollbarWidget w, int top, int bottom, int thumb) +{ + Dimension length; + + top = XawMax(1, top); + if (w->scrollbar.orientation == XtorientHorizontal) + bottom = XawMin(bottom, XtWidth(w) - 1); + else + bottom = XawMin(bottom, XtHeight(w) - 1); + + if (bottom <= top) + return; + + length = bottom - top; + + switch(thumb) { + /* Fill the new Thumb location */ + case 1: + if (w->scrollbar.orientation == XtorientHorizontal) + XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc, + top, 1, length, XtHeight(w) - 2); + else + XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc, + 1, top, XtWidth(w) - 2, length); + break; + /* Clear the old Thumb location */ + case 0: + if (w->scrollbar.orientation == XtorientHorizontal) + XClearArea(XtDisplay(w), XtWindow(w), + top, 1, length, XtHeight(w) - 2, False); + else + XClearArea(XtDisplay(w), XtWindow(w), + 1, top, XtWidth(w) - 2, length, False); + break; + } +} + + +/* Paint the thumb in the area specified by w->top and + w->shown. The old area is erased. The painting and + erasing is done cleverly so that no flickering will occur. */ +static void +PaintThumb(ScrollbarWidget w) +{ + Position oldtop, oldbot, newtop, newbot; + + oldtop = w->scrollbar.topLoc; + oldbot = oldtop + w->scrollbar.shownLength; + newtop = w->scrollbar.length * w->scrollbar.top; + newbot = newtop + (int)(w->scrollbar.length * w->scrollbar.shown); + if (newbot < newtop + (int)w->scrollbar.min_thumb) + newbot = newtop + w->scrollbar.min_thumb; + w->scrollbar.topLoc = newtop; + w->scrollbar.shownLength = newbot - newtop; + + if (XtIsRealized((Widget)w)) { + if (newtop < oldtop) + FillArea(w, newtop, XawMin(newbot, oldtop), 1); + if (newtop > oldtop) + FillArea(w, oldtop, XawMin(newtop, oldbot), 0); + if (newbot < oldbot) + FillArea(w, XawMax(newbot, oldtop), oldbot, 0); + if (newbot > oldbot) + FillArea(w, XawMax(newtop, oldbot), newbot, 1); + } +} + +static void +SetDimensions(ScrollbarWidget w) +{ + if (w->scrollbar.orientation == XtorientVertical) { + w->scrollbar.length = XtHeight(w); + w->scrollbar.thickness = XtWidth(w); + } + else { + w->scrollbar.length = XtWidth(w); + w->scrollbar.thickness = XtHeight(w); + } +} + +static void +XawScrollbarDestroy(Widget w) +{ + ScrollbarWidget sbw = (ScrollbarWidget)w; + + XtReleaseGC(w, sbw->scrollbar.gc); +} + +static void +CreateGC(Widget w) +{ + ScrollbarWidget sbw = (ScrollbarWidget)w; + XGCValues gcValues; + XtGCMask mask; + unsigned int depth = 1; + + if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) + sbw->scrollbar.thumb = XmuCreateStippledPixmap(XtScreen(w), + (Pixel)1, (Pixel)0, + depth); + else if (sbw->scrollbar.thumb != None) { + Window root; + int x, y; + unsigned int width, height, bw; + + XGetGeometry(XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y, + &width, &height, &bw, &depth); + } + + gcValues.foreground = sbw->scrollbar.foreground; + gcValues.background = sbw->core.background_pixel; + mask = GCForeground | GCBackground; + + if (sbw->scrollbar.thumb != None) { + if (depth == 1) { + gcValues.fill_style = FillOpaqueStippled; + gcValues.stipple = sbw->scrollbar.thumb; + mask |= GCFillStyle | GCStipple; + } + else { + gcValues.fill_style = FillTiled; + gcValues.tile = sbw->scrollbar.thumb; + mask |= GCFillStyle | GCTile; + } + } + sbw->scrollbar.gc = XtGetGC(w, mask, &gcValues); +} + +/* ARGSUSED */ +static void +XawScrollbarInitialize(Widget request, Widget cnew, + ArgList args, Cardinal *num_args) +{ + ScrollbarWidget w = (ScrollbarWidget)cnew; + + CreateGC(cnew); + + if (XtWidth(w) == 0) + XtWidth(w) = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.thickness : w->scrollbar.length; + + if (XtHeight(w) == 0) + XtHeight(w) = w->scrollbar.orientation == XtorientHorizontal ? + w->scrollbar.thickness : w->scrollbar.length; + + SetDimensions(w); + w->scrollbar.direction = 0; + w->scrollbar.topLoc = 0; + w->scrollbar.shownLength = w->scrollbar.min_thumb; +} + +static void +XawScrollbarRealize(Widget gw, Mask *valueMask, + XSetWindowAttributes *attributes) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + + w->scrollbar.inactiveCursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.verCursor : w->scrollbar.horCursor; + + XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL); + + /* + * The Simple widget actually stuffs the value in the valuemask + */ + (*scrollbarWidgetClass->core_class.superclass->core_class.realize) + (gw, valueMask, attributes); +} + +/*ARGSUSED*/ +static Boolean +XawScrollbarSetValues(Widget current, Widget request, Widget desired, + ArgList args, Cardinal *num_args) +{ + ScrollbarWidget w = (ScrollbarWidget)current; + ScrollbarWidget dw = (ScrollbarWidget)desired; + Boolean redraw = False; + + /* + * If these values are outside the acceptable range ignore them... + */ + if (dw->scrollbar.top < 0.0 || dw->scrollbar.top > 1.0) + dw->scrollbar.top = w->scrollbar.top; + + if (dw->scrollbar.shown < 0.0 || dw->scrollbar.shown > 1.0) + dw->scrollbar.shown = w->scrollbar.shown; + + if (XtIsRealized (desired)) { + if (w->scrollbar.foreground != dw->scrollbar.foreground || + w->core.background_pixel != dw->core.background_pixel || + w->scrollbar.thumb != dw->scrollbar.thumb) { + XtReleaseGC((Widget)dw, w->scrollbar.gc); + CreateGC((Widget)dw); + redraw = True; + } + if (w->scrollbar.top != dw->scrollbar.top || + w->scrollbar.shown != dw->scrollbar.shown) + redraw = True; + } + + return (redraw); +} + +static void +XawScrollbarResize(Widget gw) +{ + /* ForgetGravity has taken care of background, but thumb may + * have to move as a result of the new size. */ + SetDimensions((ScrollbarWidget)gw); + XawScrollbarRedisplay(gw, NULL, NULL); +} + +/*ARGSUSED*/ +static void +XawScrollbarRedisplay(Widget gw, XEvent *event, Region region) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + int x, y; + unsigned int width, height; + + if (Superclass->core_class.expose) + (*Superclass->core_class.expose)(gw, event, region); + + if (w->scrollbar.orientation == XtorientHorizontal) { + x = w->scrollbar.topLoc; + y = 1; + width = w->scrollbar.shownLength; + height = XtHeight(w) - 2; + } + else { + x = 1; + y = w->scrollbar.topLoc; + width = XtWidth(w) - 2; + height = w->scrollbar.shownLength; + } + + if (region == NULL || + XRectInRegion(region, x, y, width, height) != RectangleOut) { + /* Forces entire thumb to be painted */ + w->scrollbar.topLoc = -(w->scrollbar.length + 1); + PaintThumb(w); + } +} + +/*ARGSUSED*/ +static void +StartScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + Cursor cursor; + char direction; + + if (w->scrollbar.direction != 0) /* if we're already scrolling */ + return; + if (*num_params > 0) + direction = *params[0]; + else + direction = 'C'; + + w->scrollbar.direction = direction; + + switch(direction) { + case 'B': + case 'b': + cursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.downCursor : w->scrollbar.rightCursor; + break; + case 'F': + case 'f': + cursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.upCursor : w->scrollbar.leftCursor; + break; + case 'C': + case 'c': + cursor = w->scrollbar.orientation == XtorientVertical ? + w->scrollbar.rightCursor : w->scrollbar.upCursor; + break; + default: + return; /* invalid invocation */ + } + + XtVaSetValues(gw, XtNcursor, cursor, NULL); + + XFlush(XtDisplay(w)); +} + +static Boolean +CompareEvents(XEvent *oldEvent, XEvent *newEvent) +{ +#define Check(field) if (newEvent->field != oldEvent->field) return (False) + + Check(xany.display); + Check(xany.type); + Check(xany.window); + + switch(newEvent->type) { + case MotionNotify: + Check(xmotion.state); + break; + case ButtonPress: + case ButtonRelease: + Check(xbutton.state); + Check(xbutton.button); + break; + case KeyPress: + case KeyRelease: + Check(xkey.state); + Check(xkey.keycode); + break; + case EnterNotify: + case LeaveNotify: + Check(xcrossing.mode); + Check(xcrossing.detail); + Check(xcrossing.state); + break; + } +#undef Check + + return (True); +} + +struct EventData { + XEvent *oldEvent; + int count; +}; + +static Bool +PeekNotifyEvent(Display *dpy, XEvent *event, char *args) +{ + struct EventData *eventData = (struct EventData*)args; + + return (++eventData->count == QLength(dpy) /* since PeekIf blocks */ + || CompareEvents(event, eventData->oldEvent)); +} + +static Bool +LookAhead(Widget w, XEvent *event) +{ + XEvent newEvent; + struct EventData eventData; + + if (QLength(XtDisplay(w)) == 0) + return (False); + + eventData.count = 0; + eventData.oldEvent = event; + + XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData); + + if (CompareEvents(event, &newEvent)) + return (True); + + return (False); +} + +static void +ExtractPosition(XEvent *event, Position *x, Position *y) +{ + switch(event->type) { + case MotionNotify: + *x = event->xmotion.x; + *y = event->xmotion.y; + break; + case ButtonPress: + case ButtonRelease: + *x = event->xbutton.x; + *y = event->xbutton.y; + break; + case KeyPress: + case KeyRelease: + *x = event->xkey.x; + *y = event->xkey.y; + break; + case EnterNotify: + case LeaveNotify: + *x = event->xcrossing.x; + *y = event->xcrossing.y; + break; + default: + *x = 0; + *y = 0; + break; + } +} + +static void +NotifyScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + long call_data = 0; + char style; + Position x, y; + + if (w->scrollbar.direction == 0) /* if no StartScroll */ + return; + + if (LookAhead(gw, event)) + return; + + if (*num_params > 0) + style = *params[0]; + else + style = 'P'; + + switch(style) { + case 'P': /* Proportional */ + case 'p': + ExtractPosition(event, &x, &y); + call_data = InRange(PICKLENGTH(w, x, y), 0, (int)w->scrollbar.length); + break; + case 'F': /* FullLength */ + case 'f': + call_data = w->scrollbar.length; + break; + } + + switch(w->scrollbar.direction) { + case 'B': + case 'b': + call_data = -call_data; + /*FALLTHROUGH*/ + case 'F': + case 'f': + XtCallCallbacks(gw, XtNscrollProc, (XtPointer)call_data); + break; + case 'C': + case 'c': /* NotifyThumb has already called the thumbProc(s) */ + break; + } +} + +/*ARGSUSED*/ +static void +EndScroll(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + + XtVaSetValues(gw, XtNcursor, w->scrollbar.inactiveCursor, NULL); + XFlush(XtDisplay(w)); /* make sure it get propogated */ + + w->scrollbar.direction = 0; +} + +/*ARGSUSED*/ +static void +MoveThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + Position x, y; + + if (w->scrollbar.direction == 0) /* if no StartScroll */ + return; + + if (LookAhead(gw, event)) + return; + + if (!event->xmotion.same_screen) + return; + + ExtractPosition(event, &x, &y); + w->scrollbar.top = FractionLoc(w, x, y); +} + +/*ARGSUSED*/ +static void +NotifyThumb(Widget gw, XEvent *event, String *params, Cardinal *num_params) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + union { + XtPointer xtp; + float xtf; + } xtpf; + + if (w->scrollbar.direction == 0) /* if no StartScroll */ + return; + + if (LookAhead(gw, event)) + return; + + /* thumbProc is not pretty, but is necessary for backwards + compatibility on those architectures for which it work{s,ed}; + the intent is to pass a (truncated) float by value. */ + xtpf.xtf = w->scrollbar.top; + XtCallCallbacks(gw, XtNthumbProc, xtpf.xtp); + XtCallCallbacks(gw, XtNjumpProc, (XtPointer)&w->scrollbar.top); + + PaintThumb(w); +} + +/* + * Public routines + */ +/* Set the scroll bar to the given location. */ +void +XawScrollbarSetThumb(Widget gw, +#if NeedWidePrototypes + double top, double shown +#else + float top, float shown +#endif + ) +{ + ScrollbarWidget w = (ScrollbarWidget)gw; + + if (w->scrollbar.direction == 'c') /* if still thumbing */ + return; + + w->scrollbar.top = top > 1.0 ? 1.0 : top >= 0.0 ? top : w->scrollbar.top; + + w->scrollbar.shown = shown > 1.0 ? 1.0 : shown >= 0.0 ? + shown : w->scrollbar.shown; + PaintThumb(w); +} -- cgit v1.2.3