749N/A#ifndef lint
749N/Astatic char Xrcsid[] =
749N/A "$XConsortium: Scrollbar.c,v 1.58 89/12/15 11:36:58 kit Exp $";
749N/A#endif /* lint */
749N/A
749N/A/***********************************************************
749N/ACopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
749N/Aand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
749N/A
749N/A All Rights Reserved
749N/A
749N/APermission to use, copy, modify, and distribute this software and its
749N/Adocumentation for any purpose and without fee is hereby granted,
749N/Aprovided that the above copyright notice appear in all copies and that
749N/Aboth that copyright notice and this permission notice appear in
749N/Asupporting documentation, and that the names of Digital or MIT not be
749N/Aused in advertising or publicity pertaining to distribution of the
749N/Asoftware without specific, written prior permission.
749N/A
749N/ADIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
749N/AALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
749N/ADIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
749N/AANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
749N/AWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
749N/AARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
749N/ASOFTWARE.
749N/A
749N/A******************************************************************/
749N/A
749N/A/* ScrollBar.c */
749N/A/* created by weissman, Mon Jul 7 13:20:03 1986 */
749N/A/* converted by swick, Thu Aug 27 1987 */
749N/A
749N/A#include <X11/IntrinsicP.h>
749N/A#include <X11/StringDefs.h>
749N/A
749N/A#include <./Xaw3_1XawInit.h>
749N/A#include <./Xaw3_1ScrollbarP.h>
749N/A
749N/A#include <X11/Xmu/Drawing.h> /* for XmuCreateStippledPixmap */
749N/A
749N/A/* Private definitions. */
749N/A
749N/Astatic char defaultTranslations[] =
749N/A "<Btn1Down>: StartScroll(Forward) \n\
749N/A <Btn2Down>: StartScroll(Continuous) MoveThumb() NotifyThumb() \n\
749N/A <Btn3Down>: StartScroll(Backward) \n\
749N/A <Btn2Motion>: MoveThumb() NotifyThumb() \n\
749N/A <BtnUp>: NotifyScroll(Proportional) EndScroll()";
749N/A
749N/A#ifdef bogusScrollKeys
749N/A /* examples */
749N/A "<KeyPress>f: StartScroll(Forward) NotifyScroll(FullLength) EndScroll()"
749N/A "<KeyPress>b: StartScroll(Backward) NotifyScroll(FullLength) EndScroll()"
749N/A#endif
749N/A
749N/Astatic float floatZero = 0.0;
749N/A
749N/A#define Offset(field) XtOffset(ScrollbarWidget, field)
749N/A
749N/Astatic XtResource resources[] = {
749N/A {XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
749N/A Offset(scrollbar.length), XtRImmediate, (caddr_t) 1},
749N/A {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
749N/A Offset(scrollbar.thickness), XtRImmediate, (caddr_t) 14},
749N/A {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
749N/A Offset(scrollbar.orientation), XtRImmediate, (caddr_t) XtorientVertical},
749N/A {XtNscrollProc, XtCCallback, XtRCallback, sizeof(caddr_t),
749N/A Offset(scrollbar.scrollProc), XtRCallback, NULL},
749N/A {XtNthumbProc, XtCCallback, XtRCallback, sizeof(caddr_t),
749N/A Offset(scrollbar.thumbProc), XtRCallback, NULL},
749N/A {XtNjumpProc, XtCCallback, XtRCallback, sizeof(caddr_t),
749N/A Offset(scrollbar.jumpProc), XtRCallback, NULL},
749N/A {XtNthumb, XtCThumb, XtRPixmap, sizeof(Pixmap),
749N/A Offset(scrollbar.thumb), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
749N/A {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
749N/A Offset(scrollbar.foreground), XtRString, XtDefaultForeground},
749N/A {XtNshown, XtCShown, XtRFloat, sizeof(float),
749N/A Offset(scrollbar.shown), XtRFloat, (caddr_t)&floatZero},
749N/A {XtNtopOfThumb, XtCTopOfThumb, XtRFloat, sizeof(float),
749N/A Offset(scrollbar.top), XtRFloat, (caddr_t)&floatZero},
749N/A {XtNscrollVCursor, XtCCursor, XtRCursor, sizeof(Cursor),
749N/A Offset(scrollbar.verCursor), XtRString, "sb_v_double_arrow"},
749N/A {XtNscrollHCursor, XtCCursor, XtRCursor, sizeof(Cursor),
749N/A Offset(scrollbar.horCursor), XtRString, "sb_h_double_arrow"},
749N/A {XtNscrollUCursor, XtCCursor, XtRCursor, sizeof(Cursor),
749N/A Offset(scrollbar.upCursor), XtRString, "sb_up_arrow"},
749N/A {XtNscrollDCursor, XtCCursor, XtRCursor, sizeof(Cursor),
749N/A Offset(scrollbar.downCursor), XtRString, "sb_down_arrow"},
749N/A {XtNscrollLCursor, XtCCursor, XtRCursor, sizeof(Cursor),
749N/A Offset(scrollbar.leftCursor), XtRString, "sb_left_arrow"},
749N/A {XtNscrollRCursor, XtCCursor, XtRCursor, sizeof(Cursor),
749N/A Offset(scrollbar.rightCursor), XtRString, "sb_right_arrow"},
749N/A {XtNminimumThumb, XtCMinimumThumb, XtRDimension, sizeof(Dimension),
749N/A Offset(scrollbar.min_thumb), XtRImmediate, (caddr_t) 7},
749N/A};
749N/A
749N/Astatic void ClassInitialize();
749N/Astatic void Initialize();
749N/Astatic void Destroy();
749N/Astatic void Realize();
749N/Astatic void Resize();
749N/Astatic void Redisplay();
749N/Astatic Boolean SetValues();
749N/A
749N/Astatic void StartScroll();
749N/Astatic void MoveThumb();
749N/Astatic void NotifyThumb();
749N/Astatic void NotifyScroll();
749N/Astatic void EndScroll();
749N/A
749N/Astatic XtActionsRec actions[] = {
749N/A {"StartScroll", StartScroll},
749N/A {"MoveThumb", MoveThumb},
749N/A {"NotifyThumb", NotifyThumb},
749N/A {"NotifyScroll", NotifyScroll},
749N/A {"EndScroll", EndScroll},
749N/A {NULL,NULL}
749N/A};
749N/A
749N/A
749N/AScrollbarClassRec scrollbarClassRec = {
749N/A/* core fields */
749N/A /* superclass */ (WidgetClass) &widgetClassRec,
749N/A /* class_name */ "Scrollbar",
749N/A /* size */ sizeof(ScrollbarRec),
749N/A /* class_initialize */ ClassInitialize,
749N/A /* class_part_init */ NULL,
749N/A /* class_inited */ FALSE,
749N/A /* initialize */ Initialize,
749N/A /* initialize_hook */ NULL,
749N/A /* realize */ Realize,
749N/A /* actions */ actions,
749N/A /* num_actions */ XtNumber(actions),
749N/A /* resources */ resources,
749N/A /* num_resources */ XtNumber(resources),
749N/A /* xrm_class */ NULLQUARK,
749N/A /* compress_motion */ TRUE,
749N/A /* compress_exposure*/ TRUE,
749N/A /* compress_enterleave*/ TRUE,
749N/A /* visible_interest */ FALSE,
749N/A /* destroy */ Destroy,
749N/A /* resize */ Resize,
749N/A /* expose */ Redisplay,
749N/A /* set_values */ SetValues,
749N/A /* set_values_hook */ NULL,
749N/A /* set_values_almost */ XtInheritSetValuesAlmost,
749N/A /* get_values_hook */ NULL,
749N/A /* accept_focus */ NULL,
749N/A /* version */ XtVersion,
749N/A /* callback_private */ NULL,
749N/A /* tm_table */ defaultTranslations,
749N/A /* query_geometry */ XtInheritQueryGeometry,
749N/A /* display_accelerator*/ XtInheritDisplayAccelerator,
749N/A /* extension */ NULL
749N/A};
749N/A
749N/AWidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec;
749N/A
749N/A#define NoButton -1
749N/A#define PICKLENGTH(widget, x, y) \
749N/A ((widget->scrollbar.orientation == XtorientHorizontal) ? x : y)
749N/A#define MIN(x,y) ((x) < (y) ? (x) : (y))
749N/A#define MAX(x,y) ((x) > (y) ? (x) : (y))
749N/A
749N/Astatic void ClassInitialize()
749N/A{
749N/A static XtConvertArgRec screenConvertArg[] = {
749N/A {XtWidgetBaseOffset, (caddr_t) XtOffset(Widget, core.screen),
749N/A sizeof(Screen *)}
749N/A };
749N/A
749N/A XawInitializeWidgetSet();
749N/A XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
749N/A NULL, (Cardinal)0 );
749N/A XtAddConverter( XtRString, XtRPixmap, XmuCvtStringToBitmap,
749N/A screenConvertArg, XtNumber(screenConvertArg));
749N/A}
749N/A
749N/A/*
749N/A * Make sure the first number is within the range specified by the other
749N/A * two numbers.
749N/A */
749N/A
749N/Astatic int InRange(num, small, big)
749N/Aint num, small, big;
749N/A{
749N/A return (num < small) ? small : ((num > big) ? big : num);
749N/A}
749N/A
749N/A/*
749N/A * Same as above, but for floating numbers.
749N/A */
749N/A
749N/Astatic float FloatInRange(num, small, big)
749N/Afloat num, small, big;
749N/A{
749N/A return (num < small) ? small : ((num > big) ? big : num);
749N/A}
749N/A
749N/A
749N/A/* Fill the area specified by top and bottom with the given pattern. */
749N/Astatic float FractionLoc(w, x, y)
749N/A ScrollbarWidget w;
749N/A int x, y;
749N/A{
749N/A float result;
749N/A
749N/A result = PICKLENGTH(w, (float) x/w->core.width,
749N/A (float) y/w->core.height);
749N/A return FloatInRange(result, 0.0, 1.0);
749N/A}
749N/A
749N/A
749N/Astatic void FillArea(w, top, bottom, thumb)
749N/A ScrollbarWidget w;
749N/A Position top, bottom;
749N/A int thumb;
749N/A{
749N/A Dimension length = bottom-top;
749N/A
749N/A if (bottom < 0) return;
749N/A
749N/A switch(thumb) {
749N/A /* Fill the new Thumb location */
749N/A case 1:
749N/A if (w->scrollbar.orientation == XtorientHorizontal)
749N/A XFillRectangle(XtDisplay(w), XtWindow(w),
749N/A w->scrollbar.gc, top, 1, length,
749N/A w->core.height-2);
749N/A
749N/A else XFillRectangle(XtDisplay(w), XtWindow(w), w->scrollbar.gc,
749N/A 1, top, w->core.width-2, length);
749N/A
749N/A break;
749N/A /* Clear the old Thumb location */
749N/A case 0:
749N/A if (w->scrollbar.orientation == XtorientHorizontal)
749N/A XClearArea(XtDisplay(w), XtWindow(w), top, 1,
749N/A length, w->core.height-2, FALSE);
749N/A
749N/A else XClearArea(XtDisplay(w), XtWindow(w), 1,
749N/A top, w->core.width-2, length, FALSE);
749N/A
749N/A }
749N/A}
749N/A
749N/A
749N/A/* Paint the thumb in the area specified by w->top and
749N/A w->shown. The old area is erased. The painting and
749N/A erasing is done cleverly so that no flickering will occur. */
749N/A
749N/Astatic void PaintThumb( w )
749N/A ScrollbarWidget w;
749N/A{
749N/A Position oldtop, oldbot, newtop, newbot;
749N/A
749N/A oldtop = w->scrollbar.topLoc;
749N/A oldbot = oldtop + w->scrollbar.shownLength;
749N/A newtop = w->scrollbar.length * w->scrollbar.top;
749N/A newbot = newtop + (int)(w->scrollbar.length * w->scrollbar.shown);
749N/A if (newbot < newtop + w->scrollbar.min_thumb)
749N/A newbot = newtop + w->scrollbar.min_thumb;
749N/A w->scrollbar.topLoc = newtop;
749N/A w->scrollbar.shownLength = newbot - newtop;
749N/A
749N/A if (XtIsRealized((Widget)w)) {
749N/A if (newtop < oldtop) FillArea(w, newtop, MIN(newbot, oldtop), 1);
749N/A if (newtop > oldtop) FillArea(w, oldtop, MIN(newtop, oldbot), 0);
749N/A if (newbot < oldbot) FillArea(w, MAX(newbot, oldtop), oldbot, 0);
749N/A if (newbot > oldbot) FillArea(w, MAX(newtop, oldbot), newbot, 1);
749N/A }
749N/A}
749N/A
749N/A
749N/Astatic void SetDimensions(w)
749N/A ScrollbarWidget w;
749N/A{
749N/A if (w->scrollbar.orientation == XtorientVertical) {
749N/A w->scrollbar.length = w->core.height;
749N/A w->scrollbar.thickness = w->core.width;
749N/A }
749N/A else {
749N/A w->scrollbar.length = w->core.width;
749N/A w->scrollbar.thickness = w->core.height;
749N/A }
749N/A}
749N/A
749N/A/* Function Name: Destroy
749N/A * Description: Called as the scrollbar is going away...
749N/A * Arguments: w - the scrollbar.
749N/A * Returns: nonw
749N/A */
749N/A
749N/Astatic void
749N/ADestroy(w)
749N/AWidget w;
749N/A{
749N/A ScrollbarWidget sbw = (ScrollbarWidget) w;
749N/A
749N/A XtReleaseGC(w, sbw->scrollbar.gc);
749N/A}
749N/A
749N/A/* Function Name: CreateGC
749N/A * Description: Creates the GC.
749N/A * Arguments: w - the scrollbar widget.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ACreateGC(w)
749N/AWidget w;
749N/A{
749N/A ScrollbarWidget sbw = (ScrollbarWidget) w;
749N/A XGCValues gcValues;
749N/A XtGCMask mask;
749N/A unsigned int depth = 1;
749N/A
749N/A if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) {
749N/A sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w),
749N/A (Pixel) 1, (Pixel) 0,
749N/A depth);
749N/A }
749N/A else if (sbw->scrollbar.thumb != None) {
749N/A Window root;
749N/A int x, y;
749N/A unsigned int width, height, bw;
749N/A if (XGetGeometry(XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y,
749N/A &width, &height, &bw, &depth) == 0) {
749N/A XtAppError(XtWidgetToApplicationContext(w),
749N/A "Scrollbar Widget: Could not get geometry of thumb pixmap.");
749N/A }
749N/A }
749N/A
749N/A gcValues.foreground = sbw->scrollbar.foreground;
749N/A gcValues.background = sbw->core.background_pixel;
749N/A mask = GCForeground | GCBackground;
749N/A
749N/A if (sbw->scrollbar.thumb != None) {
749N/A if (depth == 1) {
749N/A gcValues.fill_style = FillOpaqueStippled;
749N/A gcValues.stipple = sbw->scrollbar.thumb;
749N/A mask |= GCFillStyle | GCStipple;
749N/A }
749N/A else {
749N/A gcValues.fill_style = FillTiled;
749N/A gcValues.tile = sbw->scrollbar.thumb;
749N/A mask |= GCFillStyle | GCTile;
749N/A }
749N/A }
749N/A sbw->scrollbar.gc = XtGetGC( w, mask, &gcValues);
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic void Initialize( request, new )
749N/A Widget request; /* what the client asked for */
749N/A Widget new; /* what we're going to give him */
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) new;
749N/A
749N/A CreateGC(new);
749N/A
749N/A if (w->core.width == 0)
749N/A w->core.width = (w->scrollbar.orientation == XtorientVertical)
749N/A ? w->scrollbar.thickness : w->scrollbar.length;
749N/A
749N/A if (w->core.height == 0)
749N/A w->core.height = (w->scrollbar.orientation == XtorientHorizontal)
749N/A ? w->scrollbar.thickness : w->scrollbar.length;
749N/A
749N/A SetDimensions( w );
749N/A w->scrollbar.direction = 0;
749N/A w->scrollbar.topLoc = 0;
749N/A w->scrollbar.shownLength = w->scrollbar.min_thumb;
749N/A}
749N/A
749N/Astatic void Realize( gw, valueMask, attributes )
749N/A Widget gw;
749N/A Mask *valueMask;
749N/A XSetWindowAttributes *attributes;
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A
749N/A w->scrollbar.inactiveCursor =
749N/A (w->scrollbar.orientation == XtorientVertical)
749N/A ? w->scrollbar.verCursor
749N/A : w->scrollbar.horCursor;
749N/A
749N/A attributes->cursor = w->scrollbar.inactiveCursor;
749N/A *valueMask |= CWCursor;
749N/A
749N/A XtCreateWindow( gw, InputOutput, (Visual *)CopyFromParent,
749N/A *valueMask, attributes );
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic Boolean
749N/ASetValues( current, request, desired )
749N/AWidget current, /* what I am */
749N/A request, /* what he wants me to be */
749N/A desired; /* what I will become */
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) current;
749N/A ScrollbarWidget dw = (ScrollbarWidget) desired;
749N/A Boolean redraw = FALSE;
749N/A
749N/A/*
749N/A * If these values are outside the acceptable range ignore them...
749N/A */
749N/A
749N/A if (dw->scrollbar.top < 0.0 || dw->scrollbar.top > 1.0)
749N/A dw->scrollbar.top = w->scrollbar.top;
749N/A
749N/A if (dw->scrollbar.shown < 0.0 || dw->scrollbar.shown > 1.0)
749N/A dw->scrollbar.shown = w->scrollbar.shown;
749N/A
749N/A/*
749N/A * Change colors and stuff...
749N/A */
749N/A
749N/A if ( XtIsRealized (desired) ) {
749N/A if ( (w->scrollbar.foreground != dw->scrollbar.foreground) ||
749N/A (w->core.background_pixel != dw->core.background_pixel) ||
749N/A (w->scrollbar.thumb != dw->scrollbar.thumb) )
749N/A {
749N/A XtReleaseGC((Widget)w, w->scrollbar.gc);
749N/A CreateGC( (Widget) dw);
749N/A redraw = TRUE;
749N/A }
749N/A if (w->scrollbar.top != dw->scrollbar.top ||
749N/A w->scrollbar.shown != dw->scrollbar.shown)
749N/A redraw = TRUE;
749N/A }
749N/A
749N/A return( redraw );
749N/A}
749N/A
749N/Astatic void Resize( gw )
749N/A Widget gw;
749N/A{
749N/A /* ForgetGravity has taken care of background, but thumb may
749N/A * have to move as a result of the new size. */
749N/A SetDimensions( (ScrollbarWidget)gw );
749N/A Redisplay( gw, (XEvent*)NULL, (Region)NULL );
749N/A}
749N/A
749N/A
749N/A/* ARGSUSED */
749N/Astatic void Redisplay( gw, event, region )
749N/A Widget gw;
749N/A XEvent *event;
749N/A Region region;
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A int x, y;
749N/A unsigned int width, height;
749N/A
749N/A if (w->scrollbar.orientation == XtorientHorizontal) {
749N/A x = w->scrollbar.topLoc;
749N/A y = 1;
749N/A width = w->scrollbar.shownLength;
749N/A height = w->core.height - 2;
749N/A } else {
749N/A x = 1;
749N/A y = w->scrollbar.topLoc;
749N/A width = w->core.width - 2;
749N/A height = w->scrollbar.shownLength;
749N/A }
749N/A
749N/A if ( (region == NULL) ||
749N/A (XRectInRegion(region, x, y, width, height) != RectangleOut) ) {
749N/A /* Forces entire thumb to be painted. */
749N/A w->scrollbar.topLoc = -(w->scrollbar.length + 1);
749N/A PaintThumb( w );
749N/A }
749N/A}
749N/A
749N/A
749N/A/* ARGSUSED */
749N/Astatic void StartScroll( gw, event, params, num_params )
749N/A Widget gw;
749N/A XEvent *event;
749N/A String *params; /* direction: Back|Forward|Smooth */
749N/A Cardinal *num_params; /* we only support 1 */
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A Cursor cursor;
749N/A char direction;
749N/A
749N/A if (w->scrollbar.direction != 0) return; /* if we're already scrolling */
749N/A if (*num_params > 0) direction = *params[0];
749N/A else direction = 'C';
749N/A
749N/A w->scrollbar.direction = direction;
749N/A
749N/A switch( direction ) {
749N/A case 'B':
749N/A case 'b': cursor = (w->scrollbar.orientation == XtorientVertical)
749N/A ? w->scrollbar.downCursor
749N/A : w->scrollbar.rightCursor; break;
749N/A
749N/A case 'F':
749N/A case 'f': cursor = (w->scrollbar.orientation == XtorientVertical)
749N/A ? w->scrollbar.upCursor
749N/A : w->scrollbar.leftCursor; break;
749N/A
749N/A case 'C':
749N/A case 'c': cursor = (w->scrollbar.orientation == XtorientVertical)
749N/A ? w->scrollbar.rightCursor
749N/A : w->scrollbar.upCursor; break;
749N/A
749N/A default: return; /* invalid invocation */
749N/A }
749N/A
749N/A XDefineCursor(XtDisplay(w), XtWindow(w), cursor);
749N/A
749N/A XFlush(XtDisplay(w));
749N/A}
749N/A
749N/A
749N/Astatic Boolean CompareEvents( oldEvent, newEvent )
749N/A XEvent *oldEvent, *newEvent;
749N/A{
749N/A#define Check(field) if (newEvent->field != oldEvent->field) return False;
749N/A
749N/A Check(xany.display);
749N/A Check(xany.type);
749N/A Check(xany.window);
749N/A
749N/A switch( newEvent->type ) {
749N/A case MotionNotify:
749N/A Check(xmotion.state); break;
749N/A case ButtonPress:
749N/A case ButtonRelease:
749N/A Check(xbutton.state);
749N/A Check(xbutton.button); break;
749N/A case KeyPress:
749N/A case KeyRelease:
749N/A Check(xkey.state);
749N/A Check(xkey.keycode); break;
749N/A case EnterNotify:
749N/A case LeaveNotify:
749N/A Check(xcrossing.mode);
749N/A Check(xcrossing.detail);
749N/A Check(xcrossing.state); break;
749N/A }
749N/A#undef Check
749N/A
749N/A return True;
749N/A}
749N/A
749N/Astruct EventData {
749N/A XEvent *oldEvent;
749N/A int count;
749N/A};
749N/A
749N/Astatic Bool PeekNotifyEvent( dpy, event, args )
749N/A Display *dpy;
749N/A XEvent *event;
749N/A char *args;
749N/A{
749N/A struct EventData *eventData = (struct EventData*)args;
749N/A
749N/A return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */
749N/A || CompareEvents(event, eventData->oldEvent));
749N/A}
749N/A
749N/A
749N/Astatic Boolean LookAhead( w, event )
749N/A Widget w;
749N/A XEvent *event;
749N/A{
749N/A XEvent newEvent;
749N/A struct EventData eventData;
749N/A
749N/A if (QLength(XtDisplay(w)) == 0) return False;
749N/A
749N/A eventData.count = 0;
749N/A eventData.oldEvent = event;
749N/A
749N/A XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData);
749N/A
749N/A if (CompareEvents(event, &newEvent))
749N/A return True;
749N/A else
749N/A return False;
749N/A}
749N/A
749N/A
749N/Astatic void ExtractPosition( event, x, y )
749N/A XEvent *event;
749N/A Position *x, *y; /* RETURN */
749N/A{
749N/A switch( event->type ) {
749N/A case MotionNotify:
749N/A *x = event->xmotion.x; *y = event->xmotion.y; break;
749N/A case ButtonPress:
749N/A case ButtonRelease:
749N/A *x = event->xbutton.x; *y = event->xbutton.y; break;
749N/A case KeyPress:
749N/A case KeyRelease:
749N/A *x = event->xkey.x; *y = event->xkey.y; break;
749N/A case EnterNotify:
749N/A case LeaveNotify:
749N/A *x = event->xcrossing.x; *y = event->xcrossing.y; break;
749N/A default:
749N/A *x = 0; *y = 0;
749N/A }
749N/A}
749N/A
749N/Astatic void NotifyScroll( gw, event, params, num_params )
749N/A Widget gw;
749N/A XEvent *event;
749N/A String *params; /* style: Proportional|FullLength */
749N/A Cardinal *num_params; /* we only support 1 */
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A int call_data;
749N/A char style;
749N/A Position x, y;
749N/A
749N/A if (w->scrollbar.direction == 0) return; /* if no StartScroll */
749N/A
749N/A if (LookAhead(gw, event)) return;
749N/A
749N/A if (*num_params > 0) style = *params[0];
749N/A else style = 'P';
749N/A
749N/A switch( style ) {
749N/A case 'P': /* Proportional */
749N/A case 'p': ExtractPosition( event, &x, &y );
749N/A call_data = InRange( PICKLENGTH( w, x, y ),
749N/A 0,
749N/A (int) w->scrollbar.length); break;
749N/A
749N/A case 'F': /* FullLength */
749N/A case 'f': call_data = w->scrollbar.length; break;
749N/A }
749N/A
749N/A switch( w->scrollbar.direction ) {
749N/A case 'B':
749N/A case 'b': call_data = -call_data;
749N/A /* fall through */
749N/A case 'F':
749N/A case 'f': XtCallCallbacks( gw, XtNscrollProc, (caddr_t)call_data );
749N/A break;
749N/A
749N/A case 'C':
749N/A case 'c': /* NotifyThumb has already called the thumbProc(s) */
749N/A break;
749N/A }
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic void EndScroll(gw, event, params, num_params )
749N/A Widget gw;
749N/A XEvent *event; /* unused */
749N/A String *params; /* unused */
749N/A Cardinal *num_params; /* unused */
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A
749N/A XDefineCursor(XtDisplay(w), XtWindow(w), w->scrollbar.inactiveCursor);
749N/A XFlush(XtDisplay(w));
749N/A
749N/A w->scrollbar.direction = 0;
749N/A}
749N/A
749N/A
749N/A/* ARGSUSED */
749N/Astatic void MoveThumb( gw, event, params, num_params )
749N/A Widget gw;
749N/A XEvent *event;
749N/A String *params; /* unused */
749N/A Cardinal *num_params; /* unused */
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A Position x, y;
749N/A
749N/A if (w->scrollbar.direction == 0) return; /* if no StartScroll */
749N/A
749N/A if (LookAhead(gw, event)) return;
749N/A
749N/A ExtractPosition( event, &x, &y );
749N/A w->scrollbar.top = FractionLoc(w, x, y);
749N/A PaintThumb(w);
749N/A XFlush(XtDisplay(w)); /* re-draw it before Notifying */
749N/A}
749N/A
749N/A
749N/A/* ARGSUSED */
749N/Astatic void NotifyThumb( gw, event, params, num_params )
749N/A Widget gw;
749N/A XEvent *event;
749N/A String *params; /* unused */
749N/A Cardinal *num_params; /* unused */
749N/A{
749N/A register ScrollbarWidget w = (ScrollbarWidget) gw;
749N/A
749N/A if (w->scrollbar.direction == 0) return; /* if no StartScroll */
749N/A
749N/A if (LookAhead(gw, event)) return;
749N/A
749N/A XtCallCallbacks( gw, XtNthumbProc, &w->scrollbar.top);
749N/A XtCallCallbacks( gw, XtNjumpProc, &w->scrollbar.top);
749N/A}
749N/A
749N/A
749N/A
749N/A/************************************************************
749N/A *
749N/A * Public routines.
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Set the scroll bar to the given location. */
749N/A
749N/Aextern void
749N/AXawScrollbarSetThumb( gw, top, shown )
749N/AWidget gw;
749N/Afloat top, shown;
749N/A{
749N/A ScrollbarWidget w = (ScrollbarWidget)gw;
749N/A
749N/A if (w->scrollbar.direction == 'c') return; /* if still thumbing */
749N/A
749N/A w->scrollbar.top = (top > 1.0) ? 1.0 :
749N/A (top >= 0.0) ? top :
749N/A w->scrollbar.top;
749N/A
749N/A w->scrollbar.shown = (shown > 1.0) ? 1.0 :
749N/A (shown >= 0.0) ? shown :
749N/A w->scrollbar.shown;
749N/A
749N/A PaintThumb( w );
749N/A}