00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
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
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
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
00100
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 {
00175 (WidgetClass) &threeDClassRec,
00176 "Scrollbar",
00177 sizeof(ScrollbarRec),
00178 ClassInitialize,
00179 NULL,
00180 FALSE,
00181 Initialize,
00182 NULL,
00183 Realize,
00184 actions,
00185 XtNumber(actions),
00186 resources,
00187 XtNumber(resources),
00188 NULLQUARK,
00189 TRUE,
00190 TRUE,
00191 TRUE,
00192 FALSE,
00193 Destroy,
00194 Resize,
00195 Redisplay,
00196 SetValues,
00197 NULL,
00198 XtInheritSetValuesAlmost,
00199 NULL,
00200 NULL,
00201 XtVersion,
00202 NULL,
00203 defaultTranslations,
00204 XtInheritQueryGeometry,
00205 XtInheritDisplayAccelerator,
00206 NULL
00207 },
00208 {
00209 XtInheritChangeSensitive
00210 },
00211 {
00212 XtInheritXaw3dShadowDraw
00213
00214 },
00215 {
00216 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
00238 #define MARGIN(sbw) (sbw)->scrollbar.thickness
00239 #else
00240 #define MARGIN(sbw) (sbw)->threeD.shadow_width
00241 #endif
00242
00243
00244
00245
00246
00247
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;
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
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
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
00293
00294
00295
00296
00297
00298
00299
00300
00301
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;
00308 Boolean out;
00309 {
00310 XPoint pt[6];
00311 ThreeDWidget tdw = (ThreeDWidget) gw;
00312 Dimension s = tdw->threeD.shadow_width;
00313
00314
00315
00316
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
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
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
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
00370 if ((region == NULL) ||
00371 (XRectInRegion (region, xms, ybr, xps, yps) != RectangleOut) ||
00372 (XRectInRegion (region, xbr, yms, xps, yps) != RectangleOut)) {
00373
00374
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
00384
00385
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
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
00445
00446
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 );
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
00479
00480 if (s) {
00481
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
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
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
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
00542 XFillPolygon (dpy, win, sbw->scrollbar.gc,
00543 pt, 3,
00544 Convex, CoordModeOrigin);
00545
00546 XFillPolygon (dpy, win, sbw->scrollbar.gc,
00547 pt+3, 3,
00548 Convex, CoordModeOrigin);
00549 }
00550 }
00551 }
00552 #endif
00553
00554
00555
00556
00557
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
00571
00572
00573
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
00615
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
00632 static void Initialize( request, new, args, num_args )
00633 Widget request;
00634 Widget new;
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
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
00680
00681
00682 (*scrollbarWidgetClass->core_class.superclass->core_class.realize)
00683 (w, valueMask, attributes);
00684 }
00685
00686
00687 static Boolean SetValues (current, request, desired, args, num_args)
00688 Widget current,
00689 request,
00690 desired;
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
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
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
00730
00731 SetDimensions ((ScrollbarWidget) w);
00732 Redisplay (w, (XEvent*) NULL, (Region)NULL);
00733 }
00734
00735
00736
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
00763 sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1);
00764 PaintThumb (sbw, event);
00765 }
00766 #ifdef ARROW_SCROLLBAR
00767
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))
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;
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
00875 static void HandleThumb (w, event, params, num_params)
00876 Widget w;
00877 XEvent *event;
00878 String *params;
00879 Cardinal *num_params;
00880 {
00881 Position x,y;
00882 ScrollbarWidget sbw = (ScrollbarWidget) w;
00883
00884 ExtractPosition( event, &x, &y );
00885
00886
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
00918
00919 static void StartScroll (w, event, params, num_params )
00920 Widget w;
00921 XEvent *event;
00922 String *params;
00923 Cardinal *num_params;
00924 {
00925 ScrollbarWidget sbw = (ScrollbarWidget) w;
00926 Cursor cursor;
00927 char direction;
00928
00929 if (sbw->scrollbar.direction != 0) return;
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;
00958 }
00959 XtVaSetValues (w, XtNcursor, cursor, NULL);
00960 XFlush (XtDisplay (w));
00961 }
00962 #endif
00963
00964
00965
00966
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
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
01000 || LookAhead (w, event))
01001 return;
01002
01003 ExtractPosition (event, &x, &y);
01004
01005 if (PICKLENGTH (sbw,x,y) < sbw->scrollbar.thickness) {
01006
01007 call_data = -MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
01008 XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01009
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
01016 call_data = MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
01017 XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01018
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
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
01029 call_data = sbw->scrollbar.length;
01030 XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
01031 } else
01032 {
01033
01034 }
01035 return;
01036 }
01037 #else
01038 static void NotifyScroll (w, event, params, num_params)
01039 Widget w;
01040 XEvent *event;
01041 String *params;
01042 Cardinal *num_params;
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;
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':
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':
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
01074
01075 case 'F':
01076 case 'f':
01077 XtCallCallbacks (w, XtNscrollProc, (XtPointer)call_data);
01078 break;
01079
01080 case 'C':
01081 case 'c':
01082
01083 break;
01084 }
01085 }
01086 #endif
01087
01088
01089 static void EndScroll(w, event, params, num_params )
01090 Widget w;
01091 XEvent *event;
01092 String *params;
01093 Cardinal *num_params;
01094 {
01095 ScrollbarWidget sbw = (ScrollbarWidget) w;
01096
01097 #ifdef ARROW_SCROLLBAR
01098 sbw->scrollbar.scroll_mode = 0;
01099
01100
01101
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;
01131 Cardinal *num_params;
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;
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
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;
01167 #endif
01168 PaintThumb (sbw, event);
01169 XFlush (XtDisplay (w));
01170 }
01171
01172
01173
01174 static void NotifyThumb (w, event, params, num_params )
01175 Widget w;
01176 XEvent *event;
01177 String *params;
01178 Cardinal *num_params;
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;
01185 #endif
01186
01187 if (LookAhead (w, event)) return;
01188
01189
01190
01191
01192 #ifdef ARROW_SCROLLBAR
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
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
01218
01219
01220
01221
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;
01245 #else
01246 if (sbw->scrollbar.direction == 'c') return;
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