Scrollbar.c

Go to the documentation of this file.
00001 
00002 /* MODIFIED ATHENA SCROLLBAR (USING ARROWHEADS AT ENDS OF TRAVEL) */
00003 /* Modifications Copyright 1992 by Mitch Trachtenberg             */
00004 /* Rights, permissions, and disclaimer of warranty are as in the  */
00005 /* DEC and MIT notice below.                                      */
00006 /* $XConsortium: Scrollbar.c,v 1.70 91/10/16 21:39:40 eswu Exp $ */
00007 
00008 /***********************************************************
00009 
00010 Copyright (c) 1987, 1988, 1994  X Consortium
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files (the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions:
00018 
00019 The above copyright notice and this permission notice shall be included in
00020 all copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00025 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00026 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00027 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00028 
00029 Except as contained in this notice, the name of the X Consortium shall not be
00030 used in advertising or otherwise to promote the sale, use or other dealings
00031 in this Software without prior written authorization from the X Consortium.
00032 
00033 
00034 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
00035 
00036                         All Rights Reserved
00037 
00038 Permission to use, copy, modify, and distribute this software and its
00039 documentation for any purpose and without fee is hereby granted,
00040 provided that the above copyright notice appear in all copies and that
00041 both that copyright notice and this permission notice appear in
00042 supporting documentation, and that the name of Digital not be
00043 used in advertising or publicity pertaining to distribution of the
00044 software without specific, written prior permission.
00045 
00046 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
00047 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00048 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
00049 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00050 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
00051 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00052 SOFTWARE.
00053 
00054 ******************************************************************/
00055 
00056 /* ScrollBar.c */
00057 /* created by weissman, Mon Jul  7 13:20:03 1986 */
00058 /* converted by swick, Thu Aug 27 1987 */
00059 
00060 #include <X11/IntrinsicP.h>
00061 #include <X11/StringDefs.h>
00062 
00063 #include <X11/Xaw3d/XawInit.h>
00064 #include <X11/Xaw3d/ScrollbarP.h>
00065 
00066 #include <X11/Xmu/Drawing.h>
00067 
00068 /* Private definitions. */
00069 
00070 #ifdef ARROW_SCROLLBAR
00071 static char defaultTranslations[] =
00072     "<Btn1Down>:   NotifyScroll()\n\
00073      <Btn2Down>:   MoveThumb() NotifyThumb() \n\
00074      <Btn3Down>:   NotifyScroll()\n\
00075      <Btn1Motion>: HandleThumb() \n\
00076      <Btn3Motion>: HandleThumb() \n\
00077      <Btn2Motion>: MoveThumb() NotifyThumb() \n\
00078      <BtnUp>:      EndScroll()";
00079 #else
00080 static char defaultTranslations[] =
00081     "<Btn1Down>:   StartScroll(Forward) \n\
00082      <Btn2Down>:   StartScroll(Continuous) MoveThumb() NotifyThumb() \n\
00083      <Btn3Down>:   StartScroll(Backward) \n\
00084      <Btn2Motion>: MoveThumb() NotifyThumb() \n\
00085      <BtnUp>:      NotifyScroll(Proportional) EndScroll()";
00086 #ifdef bogusScrollKeys
00087     /* examples */
00088     "<KeyPress>f:  StartScroll(Forward) NotifyScroll(FullLength) EndScroll()"
00089     "<KeyPress>b:  StartScroll(Backward) NotifyScroll(FullLength) EndScroll()"
00090 #endif
00091 #endif
00092 
00093 static float floatZero = 0.0;
00094 
00095 #define Offset(field) XtOffsetOf(ScrollbarRec, field)
00096 
00097 static XtResource resources[] = {
00098 #ifdef ARROW_SCROLLBAR
00099 /*  {XtNscrollCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00100        Offset(scrollbar.cursor), XtRString, "crosshair"},*/
00101 #else
00102   {XtNscrollVCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00103        Offset(scrollbar.verCursor), XtRString, "sb_v_double_arrow"},
00104   {XtNscrollHCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00105        Offset(scrollbar.horCursor), XtRString, "sb_h_double_arrow"},
00106   {XtNscrollUCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00107        Offset(scrollbar.upCursor), XtRString, "sb_up_arrow"},
00108   {XtNscrollDCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00109        Offset(scrollbar.downCursor), XtRString, "sb_down_arrow"},
00110   {XtNscrollLCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00111        Offset(scrollbar.leftCursor), XtRString, "sb_left_arrow"},
00112   {XtNscrollRCursor, XtCCursor, XtRCursor, sizeof(Cursor),
00113        Offset(scrollbar.rightCursor), XtRString, "sb_right_arrow"},
00114 #endif
00115   {XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
00116        Offset(scrollbar.length), XtRImmediate, (XtPointer) 1},
00117   {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
00118        Offset(scrollbar.thickness), XtRImmediate, (XtPointer) 14},
00119   {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
00120       Offset(scrollbar.orientation), XtRImmediate, (XtPointer) XtorientVertical},
00121   {XtNscrollProc, XtCCallback, XtRCallback, sizeof(XtPointer),
00122        Offset(scrollbar.scrollProc), XtRCallback, NULL},
00123   {XtNthumbProc, XtCCallback, XtRCallback, sizeof(XtPointer),
00124        Offset(scrollbar.thumbProc), XtRCallback, NULL},
00125   {XtNjumpProc, XtCCallback, XtRCallback, sizeof(XtPointer),
00126        Offset(scrollbar.jumpProc), XtRCallback, NULL},
00127   {XtNthumb, XtCThumb, XtRBitmap, sizeof(Pixmap),
00128        Offset(scrollbar.thumb), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
00129   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
00130        Offset(scrollbar.foreground), XtRString, XtDefaultForeground},
00131   {XtNshown, XtCShown, XtRFloat, sizeof(float),
00132        Offset(scrollbar.shown), XtRFloat, (XtPointer)&floatZero},
00133   {XtNtopOfThumb, XtCTopOfThumb, XtRFloat, sizeof(float),
00134        Offset(scrollbar.top), XtRFloat, (XtPointer)&floatZero},
00135   {XtNpickTop, XtCPickTop, XtRBoolean, sizeof(Boolean),
00136        Offset(scrollbar.pick_top), XtRBoolean, (XtPointer) False},
00137   {XtNminimumThumb, XtCMinimumThumb, XtRDimension, sizeof(Dimension),
00138        Offset(scrollbar.min_thumb), XtRImmediate, (XtPointer) 7}
00139 };
00140 #undef Offset
00141 
00142 static void ClassInitialize();
00143 static void Initialize();
00144 static void Destroy();
00145 static void Realize();
00146 static void Resize();
00147 static void Redisplay();
00148 static Boolean SetValues();
00149 
00150 #ifdef ARROW_SCROLLBAR
00151 static void HandleThumb();
00152 #else
00153 static void StartScroll();
00154 #endif
00155 static void MoveThumb();
00156 static void NotifyThumb();
00157 static void NotifyScroll();
00158 static void EndScroll();
00159 
00160 static XtActionsRec actions[] = {
00161 #ifdef ARROW_SCROLLBAR
00162     {"HandleThumb",     HandleThumb},
00163 #else
00164     {"StartScroll",     StartScroll},
00165 #endif
00166     {"MoveThumb",       MoveThumb},
00167     {"NotifyThumb",     NotifyThumb},
00168     {"NotifyScroll",    NotifyScroll},
00169     {"EndScroll",       EndScroll}
00170 };
00171 
00172 
00173 ScrollbarClassRec scrollbarClassRec = {
00174   { /* core fields */
00175     /* superclass       */      (WidgetClass) &threeDClassRec,
00176     /* class_name       */      "Scrollbar",
00177     /* size             */      sizeof(ScrollbarRec),
00178     /* class_initialize */      ClassInitialize,
00179     /* class_part_init  */      NULL,
00180     /* class_inited     */      FALSE,
00181     /* initialize       */      Initialize,
00182     /* initialize_hook  */      NULL,
00183     /* realize          */      Realize,
00184     /* actions          */      actions,
00185     /* num_actions      */      XtNumber(actions),
00186     /* resources        */      resources,
00187     /* num_resources    */      XtNumber(resources),
00188     /* xrm_class        */      NULLQUARK,
00189     /* compress_motion  */      TRUE,
00190     /* compress_exposure*/      TRUE,
00191     /* compress_enterleave*/    TRUE,
00192     /* visible_interest */      FALSE,
00193     /* destroy          */      Destroy,
00194     /* resize           */      Resize,
00195     /* expose           */      Redisplay,
00196     /* set_values       */      SetValues,
00197     /* set_values_hook  */      NULL,
00198     /* set_values_almost */     XtInheritSetValuesAlmost,
00199     /* get_values_hook  */      NULL,
00200     /* accept_focus     */      NULL,
00201     /* version          */      XtVersion,
00202     /* callback_private */      NULL,
00203     /* tm_table         */      defaultTranslations,
00204     /* query_geometry   */      XtInheritQueryGeometry,
00205     /* display_accelerator*/    XtInheritDisplayAccelerator,
00206     /* extension        */      NULL
00207   },
00208   { /* simple fields */
00209     /* change_sensitive */      XtInheritChangeSensitive
00210   },
00211   { /* threeD fields */
00212     /* shadowdraw       */      XtInheritXaw3dShadowDraw /*,*/
00213     /* shadowboxdraw    */      /*XtInheritXaw3dShadowBoxDraw*/
00214   },
00215   { /* scrollbar fields */
00216     /* ignore           */      0
00217   }
00218 
00219 };
00220 
00221 WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec;
00222 
00223 #define NoButton -1
00224 #define PICKLENGTH(widget, x, y) \
00225     ((widget->scrollbar.orientation == XtorientHorizontal) ? x : y)
00226 #define MIN(x,y)        ((x) < (y) ? (x) : (y))
00227 #define MAX(x,y)        ((x) > (y) ? (x) : (y))
00228 
00229 static void ClassInitialize()
00230 {
00231     XawInitializeWidgetSet();
00232     XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
00233                     (XtConvertArgList)NULL, (Cardinal)0 );
00234 }
00235 
00236 #ifdef ARROW_SCROLLBAR
00237 /* CHECKIT #define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->threeD.shadow_width */
00238 #define MARGIN(sbw) (sbw)->scrollbar.thickness
00239 #else
00240 #define MARGIN(sbw) (sbw)->threeD.shadow_width
00241 #endif
00242 
00243 /* 
00244  The original Xaw Scrollbar's FillArea *really* relied on the fact that the 
00245  server was going to clip at the window boundaries; so the logic was really
00246  rather sloppy.  To avoid drawing over the shadows and the arrows requires 
00247  some extra care...  Hope I didn't make any mistakes.
00248 */
00249 static void FillArea (sbw, top, bottom, fill)
00250     ScrollbarWidget sbw;
00251     Position top, bottom;
00252     int fill;
00253 {
00254     int tlen = bottom - top;    /* length of thumb in pixels */
00255     int sw, margin, floor;
00256     int lx, ly, lw, lh;
00257 
00258     if (bottom <= 0 || bottom <= top) 
00259         return;
00260     if ((sw = sbw->threeD.shadow_width) < 0) 
00261         sw = 0;
00262     margin = MARGIN (sbw);
00263     floor = sbw->scrollbar.length - margin;
00264 
00265     if (sbw->scrollbar.orientation == XtorientHorizontal) {
00266         lx = ((top < margin) ? margin : top);
00267         ly = sw;
00268         lw = ((bottom > floor) ? floor - top : tlen);
00269 /* CHECKIT      lw = (((top + tlen) > floor) ? floor - top : tlen); */
00270         lh = sbw->core.height - 2 * sw;
00271     } else {
00272         lx = sw;
00273         ly = ((top < margin) ? margin : top);
00274         lw = sbw->core.width - 2 * sw;
00275 /* CHECKIT      lh = (((top + tlen) > floor) ? floor - top : tlen); */
00276         lh = ((bottom > floor) ? floor - top : tlen);
00277     }
00278     if (lh <= 0 || lw <= 0) return;
00279     if (fill) {
00280         XFillRectangle(XtDisplay((Widget) sbw), XtWindow((Widget) sbw), 
00281                         sbw->scrollbar.gc, 
00282                         lx, ly, (unsigned int) lw, (unsigned int) lh);
00283     } else {
00284         XClearArea (XtDisplay((Widget) sbw), XtWindow((Widget) sbw), 
00285                         lx, ly, (unsigned int) lw, (unsigned int) lh, 
00286                         FALSE);
00287     }
00288 }
00289 
00290 
00291 
00292 /* _ShadowSurroundedBox is somewhat redundant with 
00293      _Xaw3dDrawShadows (gw, event, region, out)
00294   in ThreeD.c; however, it is more general and allows to
00295   specify the boxsize of the shawdowbox explicitely. In order
00296   to keep the changes in other parts of Xaw3d to Kaleb's distribution
00297   minimal, we define it here instead of as a method in the ThreeD class.
00298 
00299  -gustaf */
00300 
00301 /* ARGSUSED */
00302 static void
00303 _ShadowSurroundedBox (gw, event, region, xtl, ytl, xbr, ybr, out)
00304     Widget gw;
00305     XEvent *event;
00306     Region region;
00307     Dimension  xtl, ytl, xbr, ybr; /* INNER corners */
00308     Boolean out;
00309 {
00310     XPoint       pt[6];
00311     ThreeDWidget tdw = (ThreeDWidget) gw;
00312     Dimension    s   = tdw->threeD.shadow_width;
00313 
00314     /* 
00315      *  no point to do anything if the shadow_width is 0 or the
00316      *  widget has not been realized.
00317      */ 
00318     if((s > 0) && XtIsRealized (gw)){
00319 
00320         Dimension       xms = xtl - s;
00321         Dimension       yms = ytl - s;
00322         Dimension       xps = xbr + s;
00323         Dimension       yps = ybr + s;
00324         Display         *dpy = XtDisplay (gw);
00325         Window          win = XtWindow (gw);
00326         GC              top, bot;
00327 
00328         if (out) {
00329             top = tdw->threeD.top_shadow_GC;
00330             bot = tdw->threeD.bot_shadow_GC;
00331         } else {
00332             top = tdw->threeD.bot_shadow_GC;
00333             bot = tdw->threeD.top_shadow_GC;
00334         }
00335         /* Draw shadows. Points are numbered as follows:
00336          *
00337          *   1_________________________________ 2
00338          *   |                               / /|
00339          *   |                              / / |
00340          *   |   4_________________________/ /  |
00341          *   |   |                         3|   |
00342 
00343          *   |   |                          |   |
00344          *   |   |                          |   |
00345          *   |   |                          |   |
00346          *   |   |5_________________________|   |
00347          *   |  / /                         4   |
00348          *   | / /                              |
00349          *   |/ /_______________________________|
00350          *   3                                  1
00351          */
00352 
00353         /* points common to top and bottom shadow */
00354         pt[0].x = xms;  pt[0].y = yps;
00355         pt[2].x = xps;  pt[2].y = yms;
00356         pt[3].x = xbr;  pt[3].y = ytl;
00357         pt[5].x = xtl;  pt[5].y = ybr;
00358 
00359         /* top-left shadow */
00360         if ((region == NULL) ||
00361             (XRectInRegion (region, xms, yms, xps, ytl) != RectangleOut) ||
00362             (XRectInRegion (region, xms, yms, xtl, yps) != RectangleOut)) {
00363 
00364             pt[1].x = xms;      pt[1].y = yms;
00365             pt[4].x = xtl;      pt[4].y = ytl;
00366             XFillPolygon (dpy, win, top, pt, 6,Complex,CoordModeOrigin);
00367         }
00368 
00369         /* bottom-right shadow */
00370         if ((region == NULL) ||
00371             (XRectInRegion (region, xms, ybr, xps, yps) != RectangleOut) ||
00372             (XRectInRegion (region, xbr, yms, xps, yps) != RectangleOut)) {
00373 
00374             /* swap points from top left to bottom right */
00375             pt[1].x = xps;      pt[1].y = yps;
00376             pt[4].x = xbr;      pt[4].y = ybr;
00377             XFillPolygon (dpy, win, bot, pt,6, Complex,CoordModeOrigin);
00378         }
00379     }
00380 }
00381 
00382 
00383 /* Paint the thumb in the area specified by sbw->top and
00384    sbw->shown.  The old area is erased.  The painting and
00385    erasing is done cleverly so that no flickering will occur. */
00386 
00387 static void PaintThumb (sbw, event)
00388     ScrollbarWidget sbw;
00389     XEvent *event; 
00390 {
00391     Dimension s                   = sbw->threeD.shadow_width;
00392     Position  oldtop              = sbw->scrollbar.topLoc;
00393     Position  oldbot              = oldtop + sbw->scrollbar.shownLength;
00394     Dimension margin              = MARGIN (sbw);
00395     Dimension tzl                 = sbw->scrollbar.length - margin - margin;
00396     Position newtop, newbot;    
00397     Position  floor               = sbw->scrollbar.length - margin;
00398 
00399     newtop = margin + (int)(tzl * sbw->scrollbar.top);
00400     newbot = newtop + (int)(tzl * sbw->scrollbar.shown);
00401     if (sbw->scrollbar.shown < 1.) newbot++;
00402     if (newbot < newtop + (int)sbw->scrollbar.min_thumb +
00403                         2 * (int)sbw->threeD.shadow_width) 
00404       newbot = newtop + sbw->scrollbar.min_thumb +
00405                         2 * sbw->threeD.shadow_width;
00406     if ( newbot >= floor ) {
00407         newtop = floor-(newbot-newtop)+1;
00408         newbot = floor;
00409     }
00410 
00411     sbw->scrollbar.topLoc = newtop;
00412     sbw->scrollbar.shownLength = newbot - newtop;
00413     if (XtIsRealized ((Widget) sbw)) {
00414       /*  3D thumb wanted ?
00415        */
00416       if (s) 
00417           {
00418           if (newtop < oldtop) FillArea(sbw, oldtop, oldtop + s, 0);
00419           if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0);
00420           if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0);
00421           if (newbot > oldbot) FillArea(sbw, oldbot - s, oldbot, 0);
00422 
00423           if (sbw->scrollbar.orientation == XtorientHorizontal) 
00424               {
00425               _ShadowSurroundedBox(
00426                   sbw, event,
00427                   (Region)NULL,
00428                   newtop + s, 2 * s,
00429                   newbot - s, sbw->core.height - 2 * s, TRUE);
00430               }
00431           else 
00432               {
00433               _ShadowSurroundedBox(
00434                   sbw, event,
00435                   (Region)NULL,
00436                   2 * s, newtop + s,
00437                   sbw->core.width - 2 * s, newbot - s,
00438                   TRUE);
00439               }
00440           }
00441       else 
00442           {
00443           /* 
00444             Note to Mitch: FillArea is (now) correctly implemented to 
00445             not draw over shadows or the arrows. Therefore setting clipmasks 
00446             doesn't seem to be necessary.  Correct me if I'm wrong!
00447           */
00448           if (newtop < oldtop) FillArea(sbw, newtop, MIN(newbot, oldtop), 1);
00449           if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0);
00450           if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0);
00451           if (newbot > oldbot) FillArea(sbw, MAX(newtop, oldbot), newbot, 1);
00452           }
00453     }
00454 }
00455 
00456 #ifdef ARROW_SCROLLBAR
00457 static void PaintArrows (sbw)
00458     ScrollbarWidget sbw;
00459 {
00460     XPoint    pt[20];
00461     Dimension s   = sbw->threeD.shadow_width;
00462     Dimension t   = sbw->scrollbar.thickness;
00463     Dimension l   = sbw->scrollbar.length;
00464     Dimension tms = t - s, lms = l - s;
00465     Dimension tm1 = t - 1;
00466     Dimension lmt = l - t;
00467     Dimension lp1 = lmt + 1;
00468     Dimension sm1 = s - 1;
00469     Dimension t2  = t / 2;
00470     Dimension sa30 = (Dimension)(1.732 * s );  /* cotangent of 30 deg */
00471     Display   *dpy = XtDisplay (sbw);
00472     Window    win = XtWindow (sbw);
00473     GC        top = sbw->threeD.top_shadow_GC;
00474     GC        bot = sbw->threeD.bot_shadow_GC;
00475   
00476 
00477     if (XtIsRealized ((Widget) sbw)) {
00478         /* 3D arrows?
00479          */
00480         if (s) {
00481             /* upper/right arrow */
00482             pt[0].x = sm1;         pt[0].y = tm1;
00483             pt[1].x = t2;          pt[1].y = sm1;
00484             pt[2].x = t2;          pt[2].y = s + sa30;
00485             pt[3].x = sm1 + sa30;  pt[3].y = tms - 1;
00486 
00487             pt[4].x = sm1;         pt[4].y = tm1;
00488             pt[5].x = tms;         pt[5].y = tm1;
00489             pt[6].x = t2;          pt[6].y = sm1;
00490             pt[7].x = t2;          pt[7].y = s + sa30;
00491             pt[8].x = tms - sa30;  pt[8].y = tms - 1;
00492             pt[9].x = sm1 + sa30;  pt[9].y = tms - 1;
00493 
00494             /* lower/left arrow */
00495             pt[10].x = tms;        pt[10].y = lp1;
00496             pt[11].x = s;          pt[11].y = lp1;
00497             pt[12].x = t2;         pt[12].y = lms;
00498             pt[13].x = t2;         pt[13].y = lms - sa30;
00499             pt[14].x = s + sa30;   pt[14].y = lmt + s + 1;
00500             pt[15].x = tms - sa30; pt[15].y = lmt + s + 1;
00501 
00502             pt[16].x = tms;        pt[16].y = lp1;
00503             pt[17].x = t2;         pt[17].y = lms;
00504             pt[18].x = t2;         pt[18].y = lms - sa30;
00505             pt[19].x = tms - sa30; pt[19].y = lmt + s + 1;
00506 
00507             /* horizontal arrows require that x and y coordinates be swapped */
00508             if (sbw->scrollbar.orientation == XtorientHorizontal) {
00509                 int n;
00510                 int swap;
00511                 for (n = 0; n < 20; n++) {
00512                     swap = pt[n].x;
00513                     pt[n].x = pt[n].y;
00514                     pt[n].y = swap;
00515                 }
00516             }
00517             XFillPolygon (dpy, win, top, pt, 4, Complex, CoordModeOrigin);
00518             XFillPolygon (dpy, win, bot, pt + 4, 6, Complex, CoordModeOrigin);
00519             XFillPolygon (dpy, win, top, pt + 10, 6, Complex, CoordModeOrigin);
00520             XFillPolygon (dpy, win, bot, pt + 16, 4, Complex, CoordModeOrigin);
00521 
00522         } else {
00523             pt[0].x = 0;      pt[0].y = tm1;
00524             pt[1].x = t;      pt[1].y = tm1;
00525             pt[2].x = t2;     pt[2].y = 0;
00526       
00527             pt[3].x = 0;      pt[3].y = lp1;
00528             pt[4].x = t;      pt[4].y = lp1;
00529             pt[5].x = t2;     pt[5].y = l;
00530 
00531             /* horizontal arrows require that x and y coordinates be swapped */
00532             if (sbw->scrollbar.orientation == XtorientHorizontal) {
00533                 int n;
00534                 int swap;
00535                 for (n = 0; n < 6; n++) {
00536                     swap = pt[n].x;
00537                     pt[n].x = pt[n].y;
00538                     pt[n].y = swap;
00539                 }
00540             }
00541             /* draw the up/left arrow */
00542             XFillPolygon (dpy, win, sbw->scrollbar.gc, 
00543                           pt, 3, 
00544                           Convex, CoordModeOrigin);
00545             /* draw the down/right arrow */
00546             XFillPolygon (dpy, win, sbw->scrollbar.gc, 
00547                           pt+3, 3, 
00548                           Convex, CoordModeOrigin);
00549         }
00550     }
00551 }
00552 #endif
00553 
00554 /*      Function Name: Destroy
00555  *      Description: Called as the scrollbar is going away...
00556  *      Arguments: w - the scrollbar.
00557  *      Returns: nonw
00558  */
00559 static void Destroy (w)
00560     Widget w;
00561 {
00562     ScrollbarWidget sbw = (ScrollbarWidget) w;
00563 #ifdef ARROW_SCROLLBAR
00564     if(sbw->scrollbar.timer_id != (XtIntervalId) 0)
00565         XtRemoveTimeOut (sbw->scrollbar.timer_id);
00566 #endif
00567     XtReleaseGC (w, sbw->scrollbar.gc);
00568 }
00569 
00570 /*      Function Name: CreateGC
00571  *      Description: Creates the GC.
00572  *      Arguments: w - the scrollbar widget.
00573  *      Returns: none. 
00574  */
00575 
00576 static void CreateGC (w)
00577     Widget w;
00578 {
00579     ScrollbarWidget sbw = (ScrollbarWidget) w;
00580     XGCValues gcValues;
00581     XtGCMask mask;
00582     unsigned int depth = 1;
00583 
00584     if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) {
00585         sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w), 
00586                                         (Pixel) 1, (Pixel) 0, depth);
00587     } else if (sbw->scrollbar.thumb != None) {
00588         Window root;
00589         int x, y;
00590         unsigned int width, height, bw;
00591         if (XGetGeometry (XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y,
00592                          &width, &height, &bw, &depth) == 0) {
00593             XtAppError (XtWidgetToApplicationContext (w),
00594                "Scrollbar Widget: Could not get geometry of thumb pixmap.");
00595         }
00596     }
00597 
00598     gcValues.foreground = sbw->scrollbar.foreground;
00599     gcValues.background = sbw->core.background_pixel;
00600     mask = GCForeground | GCBackground;
00601 
00602     if (sbw->scrollbar.thumb != None) {
00603         if (depth == 1) {
00604             gcValues.fill_style = FillOpaqueStippled;
00605             gcValues.stipple = sbw->scrollbar.thumb;
00606             mask |= GCFillStyle | GCStipple;
00607         }
00608         else {
00609             gcValues.fill_style = FillTiled;
00610             gcValues.tile = sbw->scrollbar.thumb;
00611             mask |= GCFillStyle | GCTile;
00612         }
00613     }
00614     /* the creation should be non-caching, because */
00615     /* we now set and clear clip masks on the gc returned */
00616     sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues);
00617 }
00618 
00619 static void SetDimensions (sbw)
00620     ScrollbarWidget sbw;
00621 {
00622     if (sbw->scrollbar.orientation == XtorientVertical) {
00623         sbw->scrollbar.length = sbw->core.height;
00624         sbw->scrollbar.thickness = sbw->core.width;
00625     } else {
00626         sbw->scrollbar.length = sbw->core.width;
00627         sbw->scrollbar.thickness = sbw->core.height;
00628     }
00629 }
00630 
00631 /* ARGSUSED */
00632 static void Initialize( request, new, args, num_args )
00633     Widget request;             /* what the client asked for */
00634     Widget new;                 /* what we're going to give him */
00635     ArgList args;
00636     Cardinal *num_args;
00637 {
00638     ScrollbarWidget sbw = (ScrollbarWidget) new;
00639 
00640     CreateGC (new);
00641 
00642     if (sbw->core.width == 0)
00643         sbw->core.width = (sbw->scrollbar.orientation == XtorientVertical)
00644             ? sbw->scrollbar.thickness : sbw->scrollbar.length;
00645 
00646     if (sbw->core.height == 0)
00647         sbw->core.height = (sbw->scrollbar.orientation == XtorientHorizontal)
00648             ? sbw->scrollbar.thickness : sbw->scrollbar.length;
00649 
00650     SetDimensions (sbw);
00651 #ifdef ARROW_SCROLLBAR
00652     sbw->scrollbar.scroll_mode = 0;
00653     sbw->scrollbar.timer_id = (XtIntervalId)0;
00654 #endif
00655     sbw->scrollbar.topLoc = 0;
00656     sbw->scrollbar.shownLength = sbw->scrollbar.min_thumb;
00657 }
00658 
00659 static void Realize (w, valueMask, attributes)
00660     Widget w;
00661     Mask *valueMask;
00662     XSetWindowAttributes *attributes;
00663 {
00664     ScrollbarWidget sbw = (ScrollbarWidget) w;
00665 #ifdef ARROW_SCROLLBAR
00666     if(sbw->simple.cursor_name == NULL)
00667         XtVaSetValues(w, XtNcursorName, "crosshair", NULL);
00668     /* dont set the cursor of the window to anything */
00669     *valueMask &= ~CWCursor;
00670 #else
00671     sbw->scrollbar.inactiveCursor =
00672       (sbw->scrollbar.orientation == XtorientVertical)
00673         ? sbw->scrollbar.verCursor
00674         : sbw->scrollbar.horCursor;
00675 
00676     XtVaSetValues (w, XtNcursor, sbw->scrollbar.inactiveCursor, NULL);
00677 #endif
00678     /* 
00679      * The Simple widget actually stuffs the value in the valuemask. 
00680      */
00681     
00682     (*scrollbarWidgetClass->core_class.superclass->core_class.realize)
00683         (w, valueMask, attributes);
00684 }
00685 
00686 /* ARGSUSED */
00687 static Boolean SetValues (current, request, desired, args, num_args)
00688     Widget  current,            /* what I am */
00689             request,            /* what he wants me to be */
00690             desired;            /* what I will become */
00691     ArgList args;
00692     Cardinal *num_args;
00693 {
00694     ScrollbarWidget sbw = (ScrollbarWidget) current;
00695     ScrollbarWidget dsbw = (ScrollbarWidget) desired;
00696     Boolean redraw = FALSE;
00697 
00698 /*
00699  * If these values are outside the acceptable range ignore them...
00700  */
00701 
00702     if (dsbw->scrollbar.top < 0.0 || dsbw->scrollbar.top > 1.0)
00703         dsbw->scrollbar.top = sbw->scrollbar.top;
00704 
00705     if (dsbw->scrollbar.shown < 0.0 || dsbw->scrollbar.shown > 1.0)
00706         dsbw->scrollbar.shown = sbw->scrollbar.shown;
00707 
00708 /*
00709  * Change colors and stuff...
00710  */
00711     if (XtIsRealized (desired)) {
00712         if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground ||
00713             sbw->core.background_pixel != dsbw->core.background_pixel ||
00714             sbw->scrollbar.thumb != dsbw->scrollbar.thumb) {
00715             XtReleaseGC (desired, sbw->scrollbar.gc);
00716             CreateGC (desired);
00717             redraw = TRUE;
00718         }
00719         if (sbw->scrollbar.top != dsbw->scrollbar.top ||
00720             sbw->scrollbar.shown != dsbw->scrollbar.shown)
00721             redraw = TRUE;
00722     }
00723     return redraw;
00724 }
00725 
00726 static void Resize (w)
00727     Widget w;
00728 {
00729     /* ForgetGravity has taken care of background, but thumb may
00730      * have to move as a result of the new size. */
00731     SetDimensions ((ScrollbarWidget) w);
00732     Redisplay (w, (XEvent*) NULL, (Region)NULL);
00733 }
00734 
00735 
00736 /* ARGSUSED */
00737 static void Redisplay (w, event, region)
00738     Widget w;
00739     XEvent *event;
00740     Region region;
00741 {
00742     ScrollbarWidget sbw = (ScrollbarWidget) w;
00743     ScrollbarWidgetClass swclass = (ScrollbarWidgetClass) XtClass (w);
00744     int x, y;
00745     unsigned int width, height;
00746 
00747     (*swclass->threeD_class.shadowdraw) (w, event, region, FALSE);
00748 
00749     if (sbw->scrollbar.orientation == XtorientHorizontal) {
00750         x = sbw->scrollbar.topLoc;
00751         y = 1;
00752         width = sbw->scrollbar.shownLength;
00753         height = sbw->core.height - 2;
00754     } else {
00755         x = 1;
00756         y = sbw->scrollbar.topLoc;
00757         width = sbw->core.width - 2;
00758         height = sbw->scrollbar.shownLength;
00759     }
00760     if (region == NULL ||
00761         XRectInRegion (region, x, y, width, height) != RectangleOut) {
00762         /* Forces entire thumb to be painted. */
00763         sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1);
00764         PaintThumb (sbw, event); 
00765     }
00766 #ifdef ARROW_SCROLLBAR
00767     /* we'd like to be region aware here!!!! */
00768     PaintArrows (sbw);
00769 #endif
00770 
00771 }
00772 
00773 
00774 static Boolean CompareEvents (oldEvent, newEvent)
00775     XEvent *oldEvent, *newEvent;
00776 {
00777 #define Check(field) if (newEvent->field != oldEvent->field) return False;
00778 
00779     Check(xany.display);
00780     Check(xany.type);
00781     Check(xany.window);
00782 
00783     switch (newEvent->type) {
00784     case MotionNotify:
00785         Check(xmotion.state); 
00786         break;
00787     case ButtonPress:
00788     case ButtonRelease:
00789         Check(xbutton.state);
00790         Check(xbutton.button); 
00791         break;
00792     case KeyPress:
00793     case KeyRelease:
00794         Check(xkey.state);
00795         Check(xkey.keycode); 
00796         break;
00797     case EnterNotify:
00798     case LeaveNotify:
00799         Check(xcrossing.mode);
00800         Check(xcrossing.detail);
00801         Check(xcrossing.state); 
00802         break;
00803     }
00804 #undef Check
00805 
00806     return True;
00807 }
00808 
00809 struct EventData {
00810     XEvent *oldEvent;
00811     int count;
00812 };
00813 
00814 static Bool PeekNotifyEvent (dpy, event, args)
00815     Display *dpy;
00816     XEvent *event;
00817     char *args;
00818 {
00819     struct EventData *eventData = (struct EventData*)args;
00820 
00821     return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */
00822             || CompareEvents(event, eventData->oldEvent));
00823 }
00824 
00825 
00826 static Boolean LookAhead (w, event)
00827     Widget w;
00828     XEvent *event;
00829 {
00830     XEvent newEvent;
00831     struct EventData eventData;
00832 
00833     if (QLength (XtDisplay (w)) == 0) return False;
00834 
00835     eventData.count = 0;
00836     eventData.oldEvent = event;
00837 
00838     XPeekIfEvent (XtDisplay (w), &newEvent, PeekNotifyEvent, (char*)&eventData);
00839 
00840     return CompareEvents (event, &newEvent);
00841 }
00842 
00843 
00844 static void ExtractPosition (event, x, y)
00845     XEvent *event;
00846     Position *x, *y;            /* RETURN */
00847 {
00848     switch( event->type ) {
00849     case MotionNotify:
00850         *x = event->xmotion.x;   
00851         *y = event->xmotion.y;    
00852         break;
00853     case ButtonPress:
00854     case ButtonRelease:
00855         *x = event->xbutton.x;   
00856         *y = event->xbutton.y;   
00857         break;
00858     case KeyPress:
00859     case KeyRelease:
00860         *x = event->xkey.x;      
00861         *y = event->xkey.y;       
00862         break;
00863     case EnterNotify:
00864     case LeaveNotify:
00865         *x = event->xcrossing.x; 
00866         *y = event->xcrossing.y; 
00867         break;
00868     default:
00869         *x = 0; *y = 0;
00870     }
00871 }
00872 
00873 #ifdef ARROW_SCROLLBAR
00874 /* ARGSUSED */
00875 static void HandleThumb (w, event, params, num_params)
00876     Widget w;
00877     XEvent *event;
00878     String *params;             /* unused */
00879     Cardinal *num_params;       /* unused */
00880 {
00881     Position x,y;
00882     ScrollbarWidget sbw = (ScrollbarWidget) w;
00883 
00884     ExtractPosition( event, &x, &y );
00885     /* if the motion event puts the pointer in thumb, call Move and Notify */
00886     /* also call Move and Notify if we're already in continuous scroll mode */
00887     if (sbw->scrollbar.scroll_mode == 2 ||
00888         (PICKLENGTH (sbw,x,y) >= sbw->scrollbar.topLoc &&
00889         PICKLENGTH (sbw,x,y) <= sbw->scrollbar.topLoc + sbw->scrollbar.shownLength)){
00890         XtCallActionProc(w, "MoveThumb", event, params, *num_params);
00891         XtCallActionProc(w, "NotifyThumb", event, params, *num_params);
00892     }
00893 }
00894 
00895 static void RepeatNotify (client_data, idp)
00896     XtPointer client_data;
00897     XtIntervalId *idp;
00898 {
00899 #define A_FEW_PIXELS 5
00900     ScrollbarWidget sbw = (ScrollbarWidget) client_data;
00901     int call_data;
00902     if (sbw->scrollbar.scroll_mode != 1 && sbw->scrollbar.scroll_mode != 3) {
00903         sbw->scrollbar.timer_id = (XtIntervalId) 0;
00904         return;
00905     }
00906     call_data = MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
00907     if (sbw->scrollbar.scroll_mode == 1)
00908         call_data = -call_data;
00909     XtCallCallbacks((Widget)sbw, XtNscrollProc, (XtPointer) call_data);
00910     sbw->scrollbar.timer_id = 
00911     XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)sbw),
00912                     (unsigned long) 150,
00913                     RepeatNotify,
00914                     client_data);
00915 }
00916 
00917 #else /* ARROW_SCROLLBAR */
00918 /* ARGSUSED */
00919 static void StartScroll (w, event, params, num_params )
00920     Widget w;
00921     XEvent *event;
00922     String *params;             /* direction: Back|Forward|Smooth */
00923     Cardinal *num_params;       /* we only support 1 */
00924 {
00925     ScrollbarWidget sbw = (ScrollbarWidget) w;
00926     Cursor cursor;
00927     char direction;
00928 
00929     if (sbw->scrollbar.direction != 0) return; /* if we're already scrolling */
00930     if (*num_params > 0) 
00931         direction = *params[0];
00932     else
00933         direction = 'C';
00934 
00935     sbw->scrollbar.direction = direction;
00936 
00937     switch (direction) {
00938     case 'B':
00939     case 'b':   
00940         cursor = (sbw->scrollbar.orientation == XtorientVertical)
00941                         ? sbw->scrollbar.downCursor
00942                         : sbw->scrollbar.rightCursor; 
00943         break;
00944     case 'F':
00945     case 'f':
00946         cursor = (sbw->scrollbar.orientation == XtorientVertical)
00947                         ? sbw->scrollbar.upCursor
00948                         : sbw->scrollbar.leftCursor; 
00949         break;
00950     case 'C':
00951     case 'c':
00952         cursor = (sbw->scrollbar.orientation == XtorientVertical)
00953                         ? sbw->scrollbar.rightCursor
00954                         : sbw->scrollbar.upCursor; 
00955         break;
00956     default:    
00957         return; /* invalid invocation */
00958     }
00959     XtVaSetValues (w, XtNcursor, cursor, NULL);
00960     XFlush (XtDisplay (w));
00961 }
00962 #endif /* ARROW_SCROLLBAR */
00963 
00964 /*
00965  * Make sure the first number is within the range specified by the other
00966  * two numbers.
00967  */
00968 
00969 #ifndef ARROW_SCROLLBAR
00970 static int InRange(num, small, big)
00971     int num, small, big;
00972 {
00973     return (num < small) ? small : ((num > big) ? big : num);
00974 }
00975 #endif
00976 
00977 /*
00978  * Same as above, but for floating numbers. 
00979  */
00980 
00981 static float FloatInRange(num, small, big)
00982     float num, small, big;
00983 {
00984     return (num < small) ? small : ((num > big) ? big : num);
00985 }
00986 
00987 
00988 #ifdef ARROW_SCROLLBAR
00989 static void NotifyScroll (w, event, params, num_params)
00990     Widget w;
00991     XEvent *event;
00992     String *params;             
00993     Cardinal *num_params;       
00994 {
00995     ScrollbarWidget sbw = (ScrollbarWidget) w;
00996     int call_data;
00997     Position x, y;
00998 
00999     if (sbw->scrollbar.scroll_mode == 2  /* if scroll continuous */
01000         || LookAhead (w, event)) 
01001         return;
01002 
01003     ExtractPosition (event, &x, &y);
01004 
01005     if (PICKLENGTH (sbw,x,y) < sbw->scrollbar.thickness) {
01006         /* handle first arrow zone */
01007         call_data = -MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
01008         XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01009         /* establish autoscroll */
01010         sbw->scrollbar.timer_id = 
01011             XtAppAddTimeOut (XtWidgetToApplicationContext (w),
01012                                 (unsigned long) 300, RepeatNotify, (XtPointer)w);
01013         sbw->scrollbar.scroll_mode = 1;
01014     } else if (PICKLENGTH (sbw,x,y) > sbw->scrollbar.length - sbw->scrollbar.thickness) {
01015         /* handle last arrow zone */
01016         call_data = MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
01017         XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01018         /* establish autoscroll */
01019         sbw->scrollbar.timer_id =
01020             XtAppAddTimeOut (XtWidgetToApplicationContext (w), 
01021                                 (unsigned long) 300, RepeatNotify, (XtPointer)w);
01022         sbw->scrollbar.scroll_mode = 3;
01023     } else if (PICKLENGTH (sbw, x, y) < sbw->scrollbar.topLoc) {
01024         /* handle zone "above" the thumb */
01025         call_data = - sbw->scrollbar.length;
01026         XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01027     } else if (PICKLENGTH (sbw, x, y) > sbw->scrollbar.topLoc + sbw->scrollbar.shownLength) {
01028         /* handle zone "below" the thumb */
01029         call_data = sbw->scrollbar.length;
01030         XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01031     } else 
01032         {
01033         /* handle the thumb in the motion notify action */
01034         }
01035     return;
01036 }
01037 #else /* ARROW_SCROLLBAR */
01038 static void NotifyScroll (w, event, params, num_params)
01039     Widget w;
01040     XEvent *event;
01041     String *params;             /* style: Proportional|FullLength */
01042     Cardinal *num_params;       /* we only support 1 */
01043 {
01044     ScrollbarWidget sbw = (ScrollbarWidget) w;
01045     int call_data;
01046     char style;
01047     Position x, y;
01048 
01049     if (sbw->scrollbar.direction == 0) return; /* if no StartScroll */
01050     if (LookAhead (w, event)) return;
01051     if (*num_params > 0) 
01052         style = *params[0];
01053     else
01054         style = 'P';
01055 
01056     switch (style) {
01057     case 'P':    /* Proportional */
01058     case 'p':
01059         ExtractPosition (event, &x, &y);
01060         call_data = 
01061             InRange (PICKLENGTH (sbw, x, y), 0, (int) sbw->scrollbar.length); 
01062         break;
01063 
01064     case 'F':    /* FullLength */
01065     case 'f':    
01066         call_data = sbw->scrollbar.length; 
01067         break;
01068     }
01069     switch (sbw->scrollbar.direction) {
01070     case 'B':
01071     case 'b':    
01072         call_data = -call_data;
01073         /* fall through */
01074 
01075     case 'F':
01076     case 'f':    
01077         XtCallCallbacks (w, XtNscrollProc, (XtPointer)call_data);
01078         break;
01079 
01080     case 'C':
01081     case 'c':
01082         /* NotifyThumb has already called the thumbProc(s) */
01083         break;
01084     }
01085 }
01086 #endif /* ARROW_SCROLLBAR */
01087 
01088 /* ARGSUSED */
01089 static void EndScroll(w, event, params, num_params )
01090     Widget w;
01091     XEvent *event;              /* unused */
01092     String *params;             /* unused */
01093     Cardinal *num_params;       /* unused */
01094 {
01095     ScrollbarWidget sbw = (ScrollbarWidget) w;
01096 
01097 #ifdef ARROW_SCROLLBAR
01098     sbw->scrollbar.scroll_mode = 0;
01099     /* no need to remove any autoscroll timeout; it will no-op */
01100     /* because the scroll_mode is 0 */
01101     /* but be sure to remove timeout in destroy proc */
01102 #else
01103     XtVaSetValues (w, XtNcursor, sbw->scrollbar.inactiveCursor, NULL);
01104     XFlush (XtDisplay (w));
01105     sbw->scrollbar.direction = 0;
01106 #endif
01107 }
01108 
01109 static float FractionLoc (sbw, x, y)
01110     ScrollbarWidget sbw;
01111     int x, y;
01112 {
01113     float   result;
01114     int margin;
01115     float   height, width;
01116 
01117     margin = MARGIN (sbw);
01118     x -= margin;
01119     y -= margin;
01120     height = sbw->core.height - 2 * margin;
01121     width = sbw->core.width - 2 * margin;
01122     result = PICKLENGTH (sbw, x / width, y / height);
01123     return FloatInRange(result, 0.0, 1.0);
01124 }
01125 
01126 
01127 static void MoveThumb (w, event, params, num_params)
01128     Widget w;
01129     XEvent *event;
01130     String *params;             /* unused */
01131     Cardinal *num_params;       /* unused */
01132 {
01133     ScrollbarWidget sbw = (ScrollbarWidget) w;
01134     Position x, y;
01135     float loc, t, s;
01136 
01137 #ifndef ARROW_SCROLLBAR
01138     if (sbw->scrollbar.direction == 0) return; /* if no StartScroll */
01139 #endif
01140 
01141     if (LookAhead (w, event)) return;
01142 
01143     if (!event->xmotion.same_screen) return;
01144 
01145     ExtractPosition (event, &x, &y);
01146     loc = FractionLoc (sbw, x, y);
01147     t = sbw->scrollbar.top;
01148     s = sbw->scrollbar.shown;
01149 #ifdef ARROW_SCROLLBAR
01150     if (sbw->scrollbar.scroll_mode != 2 )
01151       /* initialize picked position */
01152       sbw->scrollbar.picked = (FloatInRange( loc, t, t + s ) - t);
01153 #else
01154     sbw->scrollbar.picked = 0.5 * s;
01155 #endif
01156     if (sbw->scrollbar.pick_top)
01157       sbw->scrollbar.top = loc;
01158     else {
01159       sbw->scrollbar.top = loc - sbw->scrollbar.picked;
01160       if (sbw->scrollbar.top < 0.0) sbw->scrollbar.top = 0.0;
01161     }
01162 
01163     if (sbw->scrollbar.top + sbw->scrollbar.shown > 1.0)
01164       sbw->scrollbar.top = 1.0 - sbw->scrollbar.shown;
01165 #ifdef ARROW_SCROLLBAR
01166     sbw->scrollbar.scroll_mode = 2; /* indicate continuous scroll */
01167 #endif
01168     PaintThumb (sbw, event);
01169     XFlush (XtDisplay (w));     /* re-draw it before Notifying */
01170 }
01171 
01172 
01173 /* ARGSUSED */
01174 static void NotifyThumb (w, event, params, num_params )
01175     Widget w;
01176     XEvent *event;
01177     String *params;             /* unused */
01178     Cardinal *num_params;       /* unused */
01179 {
01180     register ScrollbarWidget sbw = (ScrollbarWidget) w;
01181     float top = sbw->scrollbar.top;
01182 
01183 #ifndef ARROW_SCROLLBAR
01184     if (sbw->scrollbar.direction == 0) return; /* if no StartScroll */
01185 #endif
01186 
01187     if (LookAhead (w, event)) return;
01188 
01189     /* thumbProc is not pretty, but is necessary for backwards
01190        compatibility on those architectures for which it work{s,ed};
01191        the intent is to pass a (truncated) float by value. */
01192 #ifdef ARROW_SCROLLBAR
01193     /* This corrects for rounding errors: If the thumb is moved to the end of
01194        the scrollable area sometimes the last line/column is not displayed.
01195        This can happen when the integer number of the top line or leftmost
01196        column to be be displayed is calculated from the float value
01197        sbw->scrollbar.top. The numerical error of this rounding problem is
01198        very small. We therefore add a small value which then forces the
01199        next line/column (the correct one) to be used. Since we can expect
01200        that the resolution of display screens will not be higher then
01201        10000 text lines/columns we add 1/10000 to the top position. The
01202        intermediate variable `top' is used to avoid erroneous summing up
01203        corrections (can this happen at all?). If the arrows are not displayed
01204        there is no problem since in this case there is always a constant
01205        integer number of pixels the thumb must be moved in order to scroll
01206        to the next line/column. */
01207     top += 0.0001;
01208 #endif
01209     XtCallCallbacks (w, XtNthumbProc, *(XtPointer*)&top);
01210     XtCallCallbacks (w, XtNjumpProc, (XtPointer)&top);
01211 }
01212 
01213 
01214 
01215 /************************************************************
01216  *
01217  *  Public routines. 
01218  *
01219  ************************************************************/
01220 
01221 /* Set the scroll bar to the given location. */
01222 
01223 #if NeedFunctionPrototypes
01224 void XawScrollbarSetThumb (Widget w, 
01225 #if NeedWidePrototypes
01226                         double top, double shown)
01227 #else
01228                         float top, float shown)
01229 #endif
01230 #else
01231 void XawScrollbarSetThumb (w, top, shown)
01232     Widget w;
01233     float top, shown;
01234 #endif
01235 {
01236     ScrollbarWidget sbw = (ScrollbarWidget) w;
01237 
01238 #ifdef WIERD
01239     fprintf(stderr,"< XawScrollbarSetThumb w=%p, top=%f, shown=%f\n", 
01240             w,top,shown);
01241 #endif
01242 
01243 #ifdef ARROW_SCROLLBAR
01244     if (sbw->scrollbar.scroll_mode == (char) 2) return; /* if still thumbing */
01245 #else
01246     if (sbw->scrollbar.direction == 'c') return; /* if still thumbing */
01247 #endif
01248 
01249     sbw->scrollbar.top = (top > 1.0) ? 1.0 :
01250                                 (top >= 0.0) ? top : sbw->scrollbar.top;
01251 
01252     sbw->scrollbar.shown = (shown > 1.0) ? 1.0 :
01253                                 (shown >= 0.0) ? shown : sbw->scrollbar.shown;
01254 
01255     PaintThumb (sbw);
01256 }
01257 

Generated on Sun Mar 4 15:03:55 2007 for Scilab [trunk] by  doxygen 1.5.1