1 /* vi:set ts=8 sts=4 sw=4: */
3 * MODIFIED ATHENA SCROLLBAR (USING ARROWHEADS AT ENDS OF TRAVEL)
4 * Modifications Copyright 1992 by Mitch Trachtenberg
5 * Rights, permissions, and disclaimer of warranty are as in the DEC and MIT
7 * $XConsortium: Scrollbar.c,v 1.72 94/04/17 20:12:40 kaleb Exp $
11 * Modified for Vim by Bill Foster and Bram Moolenaar
16 Copyright (c) 1987, 1988, 1994 X Consortium
18 Permission is hereby granted, free of charge, to any person obtaining a copy
19 of this software and associated documentation files (the "Software"), to deal
20 in the Software without restriction, including without limitation the rights
21 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 copies of the Software, and to permit persons to whom the Software is
23 furnished to do so, subject to the following conditions:
25 The above copyright notice and this permission notice shall be included in all
26 copies or substantial portions of the Software.
28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X
31 CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 Except as contained in this notice, the name of the X Consortium shall not be
36 used in advertising or otherwise to promote the sale, use or other dealings in
37 this Software without prior written authorization from the X Consortium.
39 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
43 Permission to use, copy, modify, and distribute this software and its
44 documentation for any purpose and without fee is hereby granted, provided that
45 the above copyright notice appear in all copies and that both that copyright
46 notice and this permission notice appear in supporting documentation, and that
47 the name of Digital not be used in advertising or publicity pertaining to
48 distribution of the software without specific, written prior permission.
50 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
51 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL
52 BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
53 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
54 OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
55 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
60 /* created by weissman, Mon Jul 7 13:20:03 1986 */
61 /* converted by swick, Thu Aug 27 1987 */
63 #include <X11/IntrinsicP.h>
64 #include <X11/StringDefs.h>
66 #include <X11/Xaw/XawInit.h>
68 #include "gui_at_sb.h"
70 #include <X11/Xmu/Drawing.h>
72 /* Private definitions. */
74 static char defaultTranslations
[] =
75 "<Btn1Down>: NotifyScroll()\n\
76 <Btn2Down>: MoveThumb() NotifyThumb()\n\
77 <Btn3Down>: NotifyScroll()\n\
78 <Btn4Down>: ScrollOneLineUp()\n\
79 Shift<Btn4Down>: ScrollPageUp()\n\
80 <Btn5Down>: ScrollOneLineDown()\n\
81 Shift<Btn5Down>: ScrollPageDown()\n\
82 <Btn1Motion>: HandleThumb()\n\
83 <Btn3Motion>: HandleThumb()\n\
84 <Btn2Motion>: MoveThumb() NotifyThumb()\n\
85 <BtnUp>: EndScroll()";
87 static float floatZero
= 0.0;
89 #define Offset(field) XtOffsetOf(ScrollbarRec, field)
91 static XtResource resources
[] =
93 {XtNlength
, XtCLength
, XtRDimension
, sizeof(Dimension
),
94 Offset(scrollbar
.length
), XtRImmediate
, (XtPointer
) 1},
95 {XtNthickness
, XtCThickness
, XtRDimension
, sizeof(Dimension
),
96 Offset(scrollbar
.thickness
), XtRImmediate
, (XtPointer
) 14},
97 {XtNorientation
, XtCOrientation
, XtROrientation
, sizeof(XtOrientation
),
98 Offset(scrollbar
.orientation
), XtRImmediate
, (XtPointer
) XtorientVertical
},
99 {XtNscrollProc
, XtCCallback
, XtRCallback
, sizeof(XtPointer
),
100 Offset(scrollbar
.scrollProc
), XtRCallback
, NULL
},
101 {XtNthumbProc
, XtCCallback
, XtRCallback
, sizeof(XtPointer
),
102 Offset(scrollbar
.thumbProc
), XtRCallback
, NULL
},
103 {XtNjumpProc
, XtCCallback
, XtRCallback
, sizeof(XtPointer
),
104 Offset(scrollbar
.jumpProc
), XtRCallback
, NULL
},
105 {XtNthumb
, XtCThumb
, XtRBitmap
, sizeof(Pixmap
),
106 Offset(scrollbar
.thumb
), XtRImmediate
, (XtPointer
) XtUnspecifiedPixmap
},
107 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
108 Offset(scrollbar
.foreground
), XtRString
, XtDefaultForeground
},
109 {XtNshown
, XtCShown
, XtRFloat
, sizeof(float),
110 Offset(scrollbar
.shown
), XtRFloat
, (XtPointer
)&floatZero
},
111 {XtNtopOfThumb
, XtCTopOfThumb
, XtRFloat
, sizeof(float),
112 Offset(scrollbar
.top
), XtRFloat
, (XtPointer
)&floatZero
},
113 {XtNmaxOfThumb
, XtCMaxOfThumb
, XtRFloat
, sizeof(float),
114 Offset(scrollbar
.max
), XtRFloat
, (XtPointer
)&floatZero
},
115 {XtNminimumThumb
, XtCMinimumThumb
, XtRDimension
, sizeof(Dimension
),
116 Offset(scrollbar
.min_thumb
), XtRImmediate
, (XtPointer
) 7},
117 {XtNshadowWidth
, XtCShadowWidth
, XtRDimension
, sizeof(Dimension
),
118 Offset(scrollbar
.shadow_width
), XtRImmediate
, (XtPointer
) 1},
119 {XtNtopShadowPixel
, XtCTopShadowPixel
, XtRPixel
, sizeof(Pixel
),
120 Offset(scrollbar
.top_shadow_pixel
), XtRString
, XtDefaultBackground
},
121 {XtNbottomShadowPixel
, XtCBottomShadowPixel
, XtRPixel
, sizeof(Pixel
),
122 Offset(scrollbar
.bot_shadow_pixel
), XtRString
, XtDefaultForeground
},
123 {XtNlimitThumb
, XtCLimitThumb
, XtRBool
, sizeof(Bool
),
124 Offset(scrollbar
.limit_thumb
), XtRImmediate
, (XtPointer
)0}
128 static void ClassInitialize
__ARGS((void));
129 static void Initialize
__ARGS((Widget
, Widget
, ArgList
, Cardinal
*));
130 static void Destroy
__ARGS((Widget
));
131 static void Realize
__ARGS((Widget
, Mask
*, XSetWindowAttributes
*));
132 static void Resize
__ARGS((Widget
));
133 static void Redisplay
__ARGS((Widget
, XEvent
*, Region
));
134 static Boolean SetValues
__ARGS((Widget
, Widget
, Widget
, ArgList
, Cardinal
*));
136 static void HandleThumb
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
137 static void MoveThumb
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
138 static void NotifyThumb
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
139 static void NotifyScroll
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
140 static void EndScroll
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
141 static void ScrollOneLineUp
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
142 static void ScrollOneLineDown
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
143 static void ScrollPageUp
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
144 static void ScrollPageDown
__ARGS((Widget
, XEvent
*, String
*, Cardinal
*));
145 static void ScrollSome
__ARGS((Widget w
, XEvent
*event
, int call_data
));
146 static void _Xaw3dDrawShadows
__ARGS((Widget
, XEvent
*, Region
, int));
147 static void AllocTopShadowGC
__ARGS((Widget
));
148 static void AllocBotShadowGC
__ARGS((Widget
));
150 static XtActionsRec actions
[] =
152 {"HandleThumb", HandleThumb
},
153 {"MoveThumb", MoveThumb
},
154 {"NotifyThumb", NotifyThumb
},
155 {"NotifyScroll", NotifyScroll
},
156 {"EndScroll", EndScroll
},
157 {"ScrollOneLineUp", ScrollOneLineUp
},
158 {"ScrollOneLineDown", ScrollOneLineDown
},
159 {"ScrollPageUp", ScrollPageUp
},
160 {"ScrollPageDown", ScrollPageDown
}
164 ScrollbarClassRec vim_scrollbarClassRec
=
167 /* superclass */ (WidgetClass
) &simpleClassRec
,
168 /* class_name */ "Scrollbar",
169 /* size */ sizeof(ScrollbarRec
),
170 /* class_initialize */ ClassInitialize
,
171 /* class_part_init */ NULL
,
172 /* class_inited */ FALSE
,
173 /* initialize */ Initialize
,
174 /* initialize_hook */ NULL
,
175 /* realize */ Realize
,
176 /* actions */ actions
,
177 /* num_actions */ XtNumber(actions
),
178 /* resources */ resources
,
179 /* num_resources */ XtNumber(resources
),
180 /* xrm_class */ NULLQUARK
,
181 /* compress_motion */ TRUE
,
182 /* compress_exposure*/ TRUE
,
183 /* compress_enterleave*/ TRUE
,
184 /* visible_interest */ FALSE
,
185 /* destroy */ Destroy
,
187 /* expose */ Redisplay
,
188 /* set_values */ SetValues
,
189 /* set_values_hook */ NULL
,
190 /* set_values_almost */ XtInheritSetValuesAlmost
,
191 /* get_values_hook */ NULL
,
192 /* accept_focus */ NULL
,
193 /* version */ XtVersion
,
194 /* callback_private */ NULL
,
195 /* tm_table */ defaultTranslations
,
196 /* query_geometry */ XtInheritQueryGeometry
,
197 /* display_accelerator*/ XtInheritDisplayAccelerator
,
200 { /* simple fields */
201 /* change_sensitive */ XtInheritChangeSensitive
,
206 { /* scrollbar fields */
211 WidgetClass vim_scrollbarWidgetClass
= (WidgetClass
)&vim_scrollbarClassRec
;
214 #define PICKLENGTH(widget, x, y) \
215 ((widget->scrollbar.orientation == XtorientHorizontal) ? (x) : (y))
216 #define AT_MIN(x,y) ((x) < (y) ? (x) : (y))
217 #define AT_MAX(x,y) ((x) > (y) ? (x) : (y))
219 #define LINE_DELAY 300
220 #define PAGE_DELAY 300
221 #define LINE_REPEAT 50
222 #define PAGE_REPEAT 250
227 XawInitializeWidgetSet();
228 XtAddConverter( XtRString
, XtROrientation
, XmuCvtStringToOrientation
,
229 (XtConvertArgList
)NULL
, (Cardinal
)0 );
232 #define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->scrollbar.shadow_width
235 FillArea(sbw
, top
, bottom
, fill
, draw_shadow
)
237 Position top
, bottom
;
241 int tlen
= bottom
- top
; /* length of thumb in pixels */
242 int sw
, margin
, floor
;
245 if (bottom
<= 0 || bottom
<= top
)
247 sw
= sbw
->scrollbar
.shadow_width
;
250 margin
= MARGIN (sbw
);
251 floor
= sbw
->scrollbar
.length
- margin
+ 2;
253 if (sbw
->scrollbar
.orientation
== XtorientHorizontal
)
255 lx
= ((top
< margin
) ? margin
: top
);
257 lw
= (((top
+ tlen
) > floor
) ? floor
- top
: tlen
);
258 lh
= sbw
->core
.height
- 2 * sw
;
263 ly
= ((top
< margin
) ? margin
: top
);
264 lw
= sbw
->core
.width
- 2 * sw
;
265 lh
= (((top
+ tlen
) > floor
) ? floor
- top
: tlen
);
267 if (lh
<= 0 || lw
<= 0)
272 if (!(sbw
->scrollbar
.orientation
== XtorientHorizontal
))
275 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
276 sbw
->scrollbar
.top_shadow_GC
,
277 lx
, ly
, lx
+ lw
- 1, ly
);
280 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
281 sbw
->scrollbar
.bot_shadow_GC
,
282 lx
, ly
+ lh
- 1, lx
+ lw
- 1, ly
+ lh
- 1);
287 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
288 sbw
->scrollbar
.top_shadow_GC
,
289 lx
, ly
, lx
, ly
+ lh
- 1);
292 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
293 sbw
->scrollbar
.bot_shadow_GC
,
294 lx
+ lw
- 1, ly
, lx
+ lw
- 1, ly
+ lh
- 1);
301 XFillRectangle(XtDisplay((Widget
) sbw
), XtWindow((Widget
) sbw
),
303 lx
, ly
, (unsigned int) lw
, (unsigned int) lh
);
305 if (!(sbw
->scrollbar
.orientation
== XtorientHorizontal
))
308 XDrawLine(XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
309 sbw
->scrollbar
.top_shadow_GC
,
310 lx
, ly
, lx
, ly
+ lh
- 1);
313 XDrawLine(XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
314 sbw
->scrollbar
.bot_shadow_GC
,
315 lx
+ lw
- 1, ly
, lx
+ lw
- 1, ly
+ lh
- 1);
320 XDrawLine(XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
321 sbw
->scrollbar
.top_shadow_GC
,
322 lx
, ly
, lx
+ lw
- 1, ly
);
325 XDrawLine(XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
326 sbw
->scrollbar
.bot_shadow_GC
,
327 lx
, ly
+ lh
- 1, lx
+ lw
- 1, ly
+ lh
- 1);
332 XClearArea(XtDisplay((Widget
) sbw
), XtWindow((Widget
) sbw
),
333 lx
, ly
, (unsigned int) lw
, (unsigned int) lh
, FALSE
);
337 /* Paint the thumb in the area specified by sbw->top and
338 sbw->shown. The old area is erased. The painting and
339 erasing is done cleverly so that no flickering will occur.
346 Position oldtop
, oldbot
, newtop
, newbot
;
347 Dimension margin
, tzl
;
349 margin
= MARGIN (sbw
);
350 tzl
= sbw
->scrollbar
.length
- 2 * margin
;
351 newtop
= margin
+ (int)(tzl
* sbw
->scrollbar
.top
);
352 newbot
= newtop
+ (int)(tzl
* sbw
->scrollbar
.shown
) + 1;
353 if (newbot
< newtop
+ (int)sbw
->scrollbar
.min_thumb
)
354 newbot
= newtop
+ sbw
->scrollbar
.min_thumb
;
356 oldtop
= sbw
->scrollbar
.topLoc
;
357 oldbot
= oldtop
+ sbw
->scrollbar
.shownLength
;
358 sbw
->scrollbar
.topLoc
= newtop
;
359 sbw
->scrollbar
.shownLength
= newbot
- newtop
;
360 if (XtIsRealized ((Widget
) sbw
))
363 FillArea(sbw
, newtop
, AT_MIN(newbot
, oldtop
+1),1,0);
365 FillArea(sbw
, oldtop
, AT_MIN(newtop
, oldbot
),0,0);
367 FillArea(sbw
, AT_MAX(newbot
, oldtop
), oldbot
, 0,0);
369 FillArea(sbw
, AT_MAX(newtop
, oldbot
-1), newbot
, 1,0);
371 /* Only draw the missing shadows */
372 FillArea(sbw
, newtop
, newbot
, 0, 1);
381 Dimension thickness
= sbw
->scrollbar
.thickness
- 1;
385 if (XtIsRealized((Widget
) sbw
))
387 if ((int)thickness
* 2 > (int)sbw
->scrollbar
.length
)
389 size
= sbw
->scrollbar
.length
/ 2;
390 off
= (int)(thickness
- size
) / 2;
397 point
[0].x
= off
+ sbw
->scrollbar
.shadow_width
;
399 point
[1].x
= thickness
- off
- sbw
->scrollbar
.shadow_width
;
401 point
[2].x
= thickness
/ 2;
402 point
[2].y
= sbw
->scrollbar
.shadow_width
;
404 point
[3].x
= off
+ sbw
->scrollbar
.shadow_width
;
405 point
[3].y
= sbw
->scrollbar
.length
- size
;
406 point
[4].x
= thickness
- off
- sbw
->scrollbar
.shadow_width
;
407 point
[4].y
= sbw
->scrollbar
.length
- size
;
408 point
[5].x
= thickness
/ 2;
409 point
[5].y
= sbw
->scrollbar
.length
- sbw
->scrollbar
.shadow_width
- 1;
411 /* horizontal arrows require that x and y coordinates be swapped */
412 if (sbw
->scrollbar
.orientation
== XtorientHorizontal
)
416 for (n
= 0; n
< 6; n
++)
419 point
[n
].x
= point
[n
].y
;
423 /* draw the up/left arrow */
424 XFillPolygon (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
427 Convex
, CoordModeOrigin
);
428 XDrawLines (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
429 sbw
->scrollbar
.bot_shadow_GC
,
432 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
433 sbw
->scrollbar
.top_shadow_GC
,
434 point
[0].x
, point
[0].y
,
435 point
[2].x
, point
[2].y
);
436 /* draw the down/right arrow */
437 XFillPolygon (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
440 Convex
, CoordModeOrigin
);
441 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
442 sbw
->scrollbar
.top_shadow_GC
,
443 point
[3].x
, point
[3].y
,
444 point
[4].x
, point
[4].y
);
445 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
446 sbw
->scrollbar
.top_shadow_GC
,
447 point
[3].x
, point
[3].y
,
448 point
[5].x
, point
[5].y
);
449 XDrawLine (XtDisplay ((Widget
) sbw
), XtWindow ((Widget
) sbw
),
450 sbw
->scrollbar
.bot_shadow_GC
,
451 point
[4].x
, point
[4].y
,
452 point
[5].x
, point
[5].y
);
460 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
461 if (sbw
->scrollbar
.timer_id
!= (XtIntervalId
) 0)
462 XtRemoveTimeOut (sbw
->scrollbar
.timer_id
);
463 XtReleaseGC(w
, sbw
->scrollbar
.gc
);
464 XtReleaseGC(w
, sbw
->scrollbar
.top_shadow_GC
);
465 XtReleaseGC(w
, sbw
->scrollbar
.bot_shadow_GC
);
472 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
475 unsigned int depth
= 1;
477 if (sbw
->scrollbar
.thumb
== XtUnspecifiedPixmap
)
479 sbw
->scrollbar
.thumb
= XmuCreateStippledPixmap (XtScreen(w
),
480 (Pixel
) 1, (Pixel
) 0, depth
);
482 else if (sbw
->scrollbar
.thumb
!= None
)
486 unsigned int width
, height
, bw
;
488 if (XGetGeometry (XtDisplay(w
), sbw
->scrollbar
.thumb
, &root
, &x
, &y
,
489 &width
, &height
, &bw
, &depth
) == 0)
490 EMSG(_("Scrollbar Widget: Could not get geometry of thumb pixmap."));
493 gcValues
.foreground
= sbw
->scrollbar
.foreground
;
494 gcValues
.background
= sbw
->core
.background_pixel
;
495 mask
= GCForeground
| GCBackground
;
497 if (sbw
->scrollbar
.thumb
!= None
)
499 gcValues
.fill_style
= FillSolid
;
502 /* the creation should be non-caching, because */
503 /* we now set and clear clip masks on the gc returned */
504 sbw
->scrollbar
.gc
= XtGetGC (w
, mask
, &gcValues
);
511 if (sbw
->scrollbar
.orientation
== XtorientVertical
)
513 sbw
->scrollbar
.length
= sbw
->core
.height
;
514 sbw
->scrollbar
.thickness
= sbw
->core
.width
;
518 sbw
->scrollbar
.length
= sbw
->core
.width
;
519 sbw
->scrollbar
.thickness
= sbw
->core
.height
;
524 Initialize(request
, new, args
, num_args
)
525 Widget request UNUSED
; /* what the client asked for */
526 Widget
new; /* what we're going to give him */
528 Cardinal
*num_args UNUSED
;
530 ScrollbarWidget sbw
= (ScrollbarWidget
) new;
533 AllocTopShadowGC(new);
534 AllocBotShadowGC(new);
536 if (sbw
->core
.width
== 0)
537 sbw
->core
.width
= (sbw
->scrollbar
.orientation
== XtorientVertical
)
538 ? sbw
->scrollbar
.thickness
: sbw
->scrollbar
.length
;
540 if (sbw
->core
.height
== 0)
541 sbw
->core
.height
= (sbw
->scrollbar
.orientation
== XtorientHorizontal
)
542 ? sbw
->scrollbar
.thickness
: sbw
->scrollbar
.length
;
545 sbw
->scrollbar
.scroll_mode
= SMODE_NONE
;
546 sbw
->scrollbar
.timer_id
= (XtIntervalId
)0;
547 sbw
->scrollbar
.topLoc
= 0;
548 sbw
->scrollbar
.shownLength
= sbw
->scrollbar
.min_thumb
;
552 Realize(w
, valueMask
, attributes
)
555 XSetWindowAttributes
*attributes
;
557 /* The Simple widget actually stuffs the value in the valuemask. */
558 (*vim_scrollbarWidgetClass
->core_class
.superclass
->core_class
.realize
)
559 (w
, valueMask
, attributes
);
563 SetValues(current
, request
, desired
, args
, num_args
)
564 Widget current
; /* what I am */
565 Widget request UNUSED
; /* what he wants me to be */
566 Widget desired
; /* what I will become */
568 Cardinal
*num_args UNUSED
;
570 ScrollbarWidget sbw
= (ScrollbarWidget
) current
;
571 ScrollbarWidget dsbw
= (ScrollbarWidget
) desired
;
572 Boolean redraw
= FALSE
;
575 * If these values are outside the acceptable range ignore them...
577 if (dsbw
->scrollbar
.top
< 0.0 || dsbw
->scrollbar
.top
> 1.0)
578 dsbw
->scrollbar
.top
= sbw
->scrollbar
.top
;
580 if (dsbw
->scrollbar
.shown
< 0.0 || dsbw
->scrollbar
.shown
> 1.0)
581 dsbw
->scrollbar
.shown
= sbw
->scrollbar
.shown
;
584 * Change colors and stuff...
586 if (XtIsRealized(desired
))
588 if (sbw
->scrollbar
.foreground
!= dsbw
->scrollbar
.foreground
||
589 sbw
->core
.background_pixel
!= dsbw
->core
.background_pixel
||
590 sbw
->scrollbar
.thumb
!= dsbw
->scrollbar
.thumb
)
592 XtReleaseGC(desired
, sbw
->scrollbar
.gc
);
596 if (sbw
->scrollbar
.top
!= dsbw
->scrollbar
.top
||
597 sbw
->scrollbar
.shown
!= dsbw
->scrollbar
.shown
)
607 /* ForgetGravity has taken care of background, but thumb may
608 * have to move as a result of the new size. */
609 SetDimensions ((ScrollbarWidget
) w
);
610 Redisplay(w
, (XEvent
*) NULL
, (Region
)NULL
);
615 Redisplay(w
, event
, region
)
620 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
622 unsigned int width
, height
;
624 _Xaw3dDrawShadows(w
, event
, region
, FALSE
);
626 if (sbw
->scrollbar
.orientation
== XtorientHorizontal
)
628 x
= sbw
->scrollbar
.topLoc
;
630 width
= sbw
->scrollbar
.shownLength
;
631 height
= sbw
->core
.height
- 2;
636 y
= sbw
->scrollbar
.topLoc
;
637 width
= sbw
->core
.width
- 2;
638 height
= sbw
->scrollbar
.shownLength
;
640 if (region
== NULL
||
641 XRectInRegion (region
, x
, y
, width
, height
) != RectangleOut
)
643 /* Forces entire thumb to be painted. */
644 sbw
->scrollbar
.topLoc
= -(sbw
->scrollbar
.length
+ 1);
647 /* we'd like to be region aware here!!!! */
653 CompareEvents(oldEvent
, newEvent
)
654 XEvent
*oldEvent
, *newEvent
;
656 #define Check(field) if (newEvent->field != oldEvent->field) return False;
662 switch (newEvent
->type
)
665 Check(xmotion
.state
);
669 Check(xbutton
.state
);
670 Check(xbutton
.button
);
679 Check(xcrossing
.mode
);
680 Check(xcrossing
.detail
);
681 Check(xcrossing
.state
);
696 PeekNotifyEvent(dpy
, event
, args
)
701 struct EventData
*eventData
= (struct EventData
*)args
;
703 return ((++eventData
->count
== QLength(dpy
)) /* since PeekIf blocks */
704 || CompareEvents(event
, eventData
->oldEvent
));
714 struct EventData eventData
;
716 if (QLength (XtDisplay (w
)) == 0)
720 eventData
.oldEvent
= event
;
722 XPeekIfEvent (XtDisplay (w
), &newEvent
, PeekNotifyEvent
, (char*)&eventData
);
724 return CompareEvents (event
, &newEvent
);
729 ExtractPosition(event
, x
, y
, state
)
731 Position
*x
, *y
; /* RETURN */
732 unsigned int *state
; /* RETURN */
737 *x
= event
->xmotion
.x
;
738 *y
= event
->xmotion
.y
;
740 *state
= event
->xmotion
.state
;
744 *x
= event
->xbutton
.x
;
745 *y
= event
->xbutton
.y
;
747 *state
= event
->xbutton
.state
;
754 *state
= event
->xkey
.state
;
758 *x
= event
->xcrossing
.x
;
759 *y
= event
->xcrossing
.y
;
761 *state
= event
->xcrossing
.state
;
771 HandleThumb(w
, event
, params
, num_params
)
775 Cardinal
*num_params
;
778 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
780 ExtractPosition(event
, &x
, &y
, (unsigned int *)NULL
);
781 loc
= PICKLENGTH(sbw
, x
, y
);
782 /* if the motion event puts the pointer in thumb, call Move and Notify */
783 /* also call Move and Notify if we're already in continuous scroll mode */
784 if (sbw
->scrollbar
.scroll_mode
== SMODE_CONT
||
785 (loc
>= sbw
->scrollbar
.topLoc
&&
786 loc
<= sbw
->scrollbar
.topLoc
+ (int)sbw
->scrollbar
.shownLength
))
788 XtCallActionProc(w
, "MoveThumb", event
, params
, *num_params
);
789 XtCallActionProc(w
, "NotifyThumb", event
, params
, *num_params
);
794 RepeatNotify(client_data
, idp
)
795 XtPointer client_data
;
796 XtIntervalId
*idp UNUSED
;
798 ScrollbarWidget sbw
= (ScrollbarWidget
) client_data
;
800 char mode
= sbw
->scrollbar
.scroll_mode
;
803 if (mode
== SMODE_NONE
|| mode
== SMODE_CONT
)
805 sbw
->scrollbar
.timer_id
= (XtIntervalId
)0;
809 if (mode
== SMODE_LINE_DOWN
|| mode
== SMODE_LINE_UP
)
811 call_data
= ONE_LINE_DATA
;
816 call_data
= ONE_PAGE_DATA
;
820 if (mode
== SMODE_PAGE_UP
|| mode
== SMODE_LINE_UP
)
821 call_data
= -call_data
;
823 XtCallCallbacks((Widget
)sbw
, XtNscrollProc
, (XtPointer
)call_data
);
825 sbw
->scrollbar
.timer_id
=
826 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget
)sbw
),
833 * Same as above, but for floating numbers.
836 FloatInRange(num
, small
, big
)
837 float num
, small
, big
;
839 return (num
< small
) ? small
: ((num
> big
) ? big
: num
);
843 ScrollOneLineUp(w
, event
, params
, num_params
)
846 String
*params UNUSED
;
847 Cardinal
*num_params UNUSED
;
849 ScrollSome(w
, event
, -ONE_LINE_DATA
);
853 ScrollOneLineDown(w
, event
, params
, num_params
)
856 String
*params UNUSED
;
857 Cardinal
*num_params UNUSED
;
859 ScrollSome(w
, event
, ONE_LINE_DATA
);
863 ScrollPageDown(w
, event
, params
, num_params
)
866 String
*params UNUSED
;
867 Cardinal
*num_params UNUSED
;
869 ScrollSome(w
, event
, ONE_PAGE_DATA
);
873 ScrollPageUp(w
, event
, params
, num_params
)
876 String
*params UNUSED
;
877 Cardinal
*num_params UNUSED
;
879 ScrollSome(w
, event
, -ONE_PAGE_DATA
);
883 ScrollSome(w
, event
, call_data
)
888 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
890 if (sbw
->scrollbar
.scroll_mode
== SMODE_CONT
) /* if scroll continuous */
893 if (LookAhead(w
, event
))
896 sbw
->scrollbar
.scroll_mode
= SMODE_LINE_UP
;
897 XtCallCallbacks(w
, XtNscrollProc
, (XtPointer
)call_data
);
901 NotifyScroll(w
, event
, params
, num_params
)
904 String
*params UNUSED
;
905 Cardinal
*num_params UNUSED
;
907 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
909 Dimension arrow_size
;
910 unsigned long delay
= 0;
914 if (sbw
->scrollbar
.scroll_mode
== SMODE_CONT
) /* if scroll continuous */
917 if (LookAhead (w
, event
))
920 ExtractPosition(event
, &x
, &y
, &state
);
921 loc
= PICKLENGTH(sbw
, x
, y
);
923 if ((int)sbw
->scrollbar
.thickness
* 2 > (int)sbw
->scrollbar
.length
)
924 arrow_size
= sbw
->scrollbar
.length
/ 2;
926 arrow_size
= sbw
->scrollbar
.thickness
;
929 * handle CTRL modifier
931 if (state
& ControlMask
)
933 if (loc
> sbw
->scrollbar
.topLoc
+ (Position
)sbw
->scrollbar
.shownLength
)
934 call_data
= END_PAGE_DATA
;
936 call_data
= -END_PAGE_DATA
;
937 sbw
->scrollbar
.scroll_mode
= SMODE_NONE
;
940 * handle first arrow zone
942 else if (loc
< (Position
)arrow_size
)
944 call_data
= -ONE_LINE_DATA
;
945 sbw
->scrollbar
.scroll_mode
= SMODE_LINE_UP
;
950 * handle last arrow zone
952 else if (loc
> (Position
)(sbw
->scrollbar
.length
- arrow_size
))
954 call_data
= ONE_LINE_DATA
;
955 sbw
->scrollbar
.scroll_mode
= SMODE_LINE_DOWN
;
960 * handle zone "above" the thumb
962 else if (loc
< sbw
->scrollbar
.topLoc
)
964 call_data
= -ONE_PAGE_DATA
;
965 sbw
->scrollbar
.scroll_mode
= SMODE_PAGE_UP
;
970 * handle zone "below" the thumb
972 else if (loc
> sbw
->scrollbar
.topLoc
+ (Position
)sbw
->scrollbar
.shownLength
)
974 call_data
= ONE_PAGE_DATA
;
975 sbw
->scrollbar
.scroll_mode
= SMODE_PAGE_DOWN
;
980 XtCallCallbacks(w
, XtNscrollProc
, (XtPointer
)call_data
);
982 /* establish autoscroll */
984 sbw
->scrollbar
.timer_id
=
985 XtAppAddTimeOut(XtWidgetToApplicationContext(w
),
986 delay
, RepeatNotify
, (XtPointer
)w
);
990 EndScroll(w
, event
, params
, num_params
)
992 XEvent
*event UNUSED
;
993 String
*params UNUSED
;
994 Cardinal
*num_params UNUSED
;
996 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
998 sbw
->scrollbar
.scroll_mode
= SMODE_NONE
;
999 /* no need to remove any autoscroll timeout; it will no-op */
1000 /* because the scroll_mode is SMODE_NONE */
1001 /* but be sure to remove timeout in destroy proc */
1005 FractionLoc(sbw
, x
, y
)
1006 ScrollbarWidget sbw
;
1010 float height
, width
;
1012 margin
= MARGIN(sbw
);
1015 height
= (float)sbw
->core
.height
- 2 * margin
;
1016 width
= (float)sbw
->core
.width
- 2 * margin
;
1017 return PICKLENGTH(sbw
, x
/ width
, y
/ height
);
1021 MoveThumb(w
, event
, params
, num_params
)
1024 String
*params UNUSED
;
1025 Cardinal
*num_params UNUSED
;
1027 ScrollbarWidget sbw
= (ScrollbarWidget
)w
;
1030 char old_mode
= sbw
->scrollbar
.scroll_mode
;
1032 sbw
->scrollbar
.scroll_mode
= SMODE_CONT
; /* indicate continuous scroll */
1034 if (LookAhead(w
, event
))
1037 if (!event
->xmotion
.same_screen
)
1040 ExtractPosition(event
, &x
, &y
, (unsigned int *)NULL
);
1042 top
= FractionLoc(sbw
, x
, y
);
1044 if (old_mode
!= SMODE_CONT
) /* start dragging: set offset */
1046 if (event
->xbutton
.button
== Button2
)
1047 sbw
->scrollbar
.scroll_off
= sbw
->scrollbar
.shown
/ 2.;
1049 sbw
->scrollbar
.scroll_off
= top
- sbw
->scrollbar
.top
;
1052 top
-= sbw
->scrollbar
.scroll_off
;
1053 if (sbw
->scrollbar
.limit_thumb
)
1054 top
= FloatInRange(top
, 0.0,
1055 sbw
->scrollbar
.max
- sbw
->scrollbar
.shown
+ 0.000001);
1057 top
= FloatInRange(top
, 0.0, sbw
->scrollbar
.max
);
1059 sbw
->scrollbar
.top
= top
;
1061 XFlush(XtDisplay(w
)); /* re-draw it before Notifying */
1066 NotifyThumb(w
, event
, params
, num_params
)
1069 String
*params UNUSED
;
1070 Cardinal
*num_params UNUSED
;
1072 ScrollbarWidget sbw
= (ScrollbarWidget
)w
;
1073 /* Use a union to avoid a warning for the weird conversion from float to
1074 * XtPointer. Comes from Xaw/Scrollbar.c. */
1080 if (LookAhead(w
, event
))
1083 /* thumbProc is not pretty, but is necessary for backwards
1084 compatibility on those architectures for which it work{s,ed};
1085 the intent is to pass a (truncated) float by value. */
1086 xtpf
.xtf
= sbw
->scrollbar
.top
;
1087 XtCallCallbacks(w
, XtNthumbProc
, xtpf
.xtp
);
1088 XtCallCallbacks(w
, XtNjumpProc
, (XtPointer
)&sbw
->scrollbar
.top
);
1095 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
1099 valuemask
= GCForeground
;
1100 myXGCV
.foreground
= sbw
->scrollbar
.top_shadow_pixel
;
1101 sbw
->scrollbar
.top_shadow_GC
= XtGetGC(w
, valuemask
, &myXGCV
);
1108 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
1112 valuemask
= GCForeground
;
1113 myXGCV
.foreground
= sbw
->scrollbar
.bot_shadow_pixel
;
1114 sbw
->scrollbar
.bot_shadow_GC
= XtGetGC(w
, valuemask
, &myXGCV
);
1118 _Xaw3dDrawShadows(gw
, event
, region
, out
)
1120 XEvent
*event UNUSED
;
1125 ScrollbarWidget sbw
= (ScrollbarWidget
) gw
;
1126 Dimension s
= sbw
->scrollbar
.shadow_width
;
1128 * draw the shadows using the core part width and height,
1129 * and the scrollbar part shadow_width.
1131 * no point to do anything if the shadow_width is 0 or the
1132 * widget has not been realized.
1134 if (s
> 0 && XtIsRealized(gw
))
1136 Dimension h
= sbw
->core
.height
;
1137 Dimension w
= sbw
->core
.width
;
1138 Dimension wms
= w
- s
;
1139 Dimension hms
= h
- s
;
1140 Display
*dpy
= XtDisplay (gw
);
1141 Window win
= XtWindow (gw
);
1146 top
= sbw
->scrollbar
.top_shadow_GC
;
1147 bot
= sbw
->scrollbar
.bot_shadow_GC
;
1151 top
= sbw
->scrollbar
.bot_shadow_GC
;
1152 bot
= sbw
->scrollbar
.top_shadow_GC
;
1155 /* top-left shadow */
1156 if ((region
== NULL
) ||
1157 (XRectInRegion (region
, 0, 0, w
, s
) != RectangleOut
) ||
1158 (XRectInRegion (region
, 0, 0, s
, h
) != RectangleOut
))
1160 pt
[0].x
= 0; pt
[0].y
= h
;
1161 pt
[1].x
= pt
[1].y
= 0;
1162 pt
[2].x
= w
; pt
[2].y
= 0;
1163 pt
[3].x
= wms
; pt
[3].y
= s
;
1164 pt
[4].x
= pt
[4].y
= s
;
1165 pt
[5].x
= s
; pt
[5].y
= hms
;
1166 XFillPolygon (dpy
, win
, top
, pt
, 6, Complex
, CoordModeOrigin
);
1169 /* bottom-right shadow */
1170 if ((region
== NULL
) ||
1171 (XRectInRegion (region
, 0, hms
, w
, s
) != RectangleOut
) ||
1172 (XRectInRegion (region
, wms
, 0, s
, h
) != RectangleOut
))
1174 pt
[0].x
= 0; pt
[0].y
= h
;
1175 pt
[1].x
= w
; pt
[1].y
= h
;
1176 pt
[2].x
= w
; pt
[2].y
= 0;
1177 pt
[3].x
= wms
; pt
[3].y
= s
;
1178 pt
[4].x
= wms
; pt
[4].y
= hms
;
1179 pt
[5].x
= s
; pt
[5].y
= hms
;
1180 XFillPolygon (dpy
, win
, bot
, pt
, 6, Complex
, CoordModeOrigin
);
1187 * Set the scroll bar to the given location.
1190 vim_XawScrollbarSetThumb(w
, top
, shown
, max
)
1192 double top
, shown
, max
;
1194 ScrollbarWidget sbw
= (ScrollbarWidget
) w
;
1196 if (sbw
->scrollbar
.scroll_mode
== SMODE_CONT
) /* if still thumbing */
1199 sbw
->scrollbar
.max
= (max
> 1.0) ? 1.0 :
1200 (max
>= 0.0) ? max
: sbw
->scrollbar
.max
;
1202 sbw
->scrollbar
.top
= (top
> sbw
->scrollbar
.max
) ? sbw
->scrollbar
.max
:
1203 (top
>= 0.0) ? top
: sbw
->scrollbar
.top
;
1205 sbw
->scrollbar
.shown
= (shown
> 1.0) ? 1.0 :
1206 (shown
>= 0.0) ? shown
: sbw
->scrollbar
.shown
;