blob: 189647a48133a6678f5a76c05b80a0b97ccb5036 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4: */
2/*
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
6 * notice below.
7 * $XConsortium: Scrollbar.c,v 1.72 94/04/17 20:12:40 kaleb Exp $
8 */
9
10/*
11 * Modified for Vim by Bill Foster and Bram Moolenaar
12 */
13
14/*
15
16Copyright (c) 1987, 1988, 1994 X Consortium
17
18Permission is hereby granted, free of charge, to any person obtaining a copy
19of this software and associated documentation files (the "Software"), to deal
20in the Software without restriction, including without limitation the rights
21to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22copies of the Software, and to permit persons to whom the Software is
23furnished to do so, subject to the following conditions:
24
25The above copyright notice and this permission notice shall be included in all
26copies or substantial portions of the Software.
27
28THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X
31CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34
35Except as contained in this notice, the name of the X Consortium shall not be
36used in advertising or otherwise to promote the sale, use or other dealings in
37this Software without prior written authorization from the X Consortium.
38
39Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
40
41 All Rights Reserved
42
43Permission to use, copy, modify, and distribute this software and its
44documentation for any purpose and without fee is hereby granted, provided that
45the above copyright notice appear in all copies and that both that copyright
46notice and this permission notice appear in supporting documentation, and that
47the name of Digital not be used in advertising or publicity pertaining to
48distribution of the software without specific, written prior permission.
49
50DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
51IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL
52BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
53WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
54OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
55CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
56
57*/
58
59/* ScrollBar.c */
60/* created by weissman, Mon Jul 7 13:20:03 1986 */
61/* converted by swick, Thu Aug 27 1987 */
62
63#include <X11/IntrinsicP.h>
64#include <X11/StringDefs.h>
65
66#include <X11/Xaw/XawInit.h>
67#include "vim.h"
68#include "gui_at_sb.h"
69
70#include <X11/Xmu/Drawing.h>
71
72/* Private definitions. */
73
74static 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()";
86
87static float floatZero = 0.0;
88
89#define Offset(field) XtOffsetOf(ScrollbarRec, field)
90
91static XtResource resources[] =
92{
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}
125};
126#undef Offset
127
Bram Moolenaar56985072016-01-29 23:23:06 +0100128static void ClassInitialize(void);
129static void Initialize(Widget, Widget, ArgList, Cardinal *);
130static void Destroy(Widget);
131static void Realize(Widget, Mask *, XSetWindowAttributes *);
132static void Resize(Widget);
133static void Redisplay(Widget, XEvent *, Region);
134static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000135
Bram Moolenaar56985072016-01-29 23:23:06 +0100136static void HandleThumb(Widget, XEvent *, String *, Cardinal *);
137static void MoveThumb(Widget, XEvent *, String *, Cardinal *);
138static void NotifyThumb(Widget, XEvent *, String *, Cardinal *);
139static void NotifyScroll(Widget, XEvent *, String *, Cardinal *);
140static void EndScroll(Widget, XEvent *, String *, Cardinal *);
141static void ScrollOneLineUp(Widget, XEvent *, String *, Cardinal *);
142static void ScrollOneLineDown(Widget, XEvent *, String *, Cardinal *);
143static void ScrollPageUp(Widget, XEvent *, String *, Cardinal *);
144static void ScrollPageDown(Widget, XEvent *, String *, Cardinal *);
145static void ScrollSome(Widget w, XEvent *event, int call_data);
146static void _Xaw3dDrawShadows(Widget, XEvent *, Region, int);
147static void AllocTopShadowGC(Widget);
148static void AllocBotShadowGC(Widget);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149
150static XtActionsRec actions[] =
151{
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}
161};
162
163
164ScrollbarClassRec vim_scrollbarClassRec =
165{
166 { /* core fields */
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,
186 /* resize */ Resize,
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,
198 /* extension */ NULL
199 },
200 { /* simple fields */
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000201 /* change_sensitive */ XtInheritChangeSensitive,
202#ifndef OLDXAW
203 /* extension */ NULL
204#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205 },
206 { /* scrollbar fields */
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000207 /* empty */ 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208 }
209};
210
211WidgetClass vim_scrollbarWidgetClass = (WidgetClass)&vim_scrollbarClassRec;
212
213#define NoButton -1
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))
218
219#define LINE_DELAY 300
220#define PAGE_DELAY 300
221#define LINE_REPEAT 50
222#define PAGE_REPEAT 250
223
224 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100225ClassInitialize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000226{
227 XawInitializeWidgetSet();
228 XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
229 (XtConvertArgList)NULL, (Cardinal)0 );
230}
231
232#define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->scrollbar.shadow_width
233
234 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100235FillArea(
236 ScrollbarWidget sbw,
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100237 Position top,
238 Position bottom,
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100239 int fill,
240 int draw_shadow)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000241{
242 int tlen = bottom - top; /* length of thumb in pixels */
243 int sw, margin, floor;
244 int lx, ly, lw, lh;
245
246 if (bottom <= 0 || bottom <= top)
247 return;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000248 sw = sbw->scrollbar.shadow_width;
249 if (sw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000250 sw = 0;
251 margin = MARGIN (sbw);
252 floor = sbw->scrollbar.length - margin + 2;
253
254 if (sbw->scrollbar.orientation == XtorientHorizontal)
255 {
256 lx = ((top < margin) ? margin : top);
257 ly = sw;
258 lw = (((top + tlen) > floor) ? floor - top : tlen);
259 lh = sbw->core.height - 2 * sw;
260 }
261 else
262 {
263 lx = sw;
264 ly = ((top < margin) ? margin : top);
265 lw = sbw->core.width - 2 * sw;
266 lh = (((top + tlen) > floor) ? floor - top : tlen);
267 }
268 if (lh <= 0 || lw <= 0)
269 return;
270
271 if (draw_shadow)
272 {
273 if (!(sbw->scrollbar.orientation == XtorientHorizontal))
274 {
275 /* Top border */
276 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
277 sbw->scrollbar.top_shadow_GC,
278 lx, ly, lx + lw - 1, ly);
279
280 /* Bottom border */
281 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
282 sbw->scrollbar.bot_shadow_GC,
283 lx, ly + lh - 1, lx + lw - 1, ly + lh - 1);
284 }
285 else
286 {
287 /* Left border */
288 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
289 sbw->scrollbar.top_shadow_GC,
290 lx, ly, lx, ly + lh - 1);
291
292 /* Right border */
293 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
294 sbw->scrollbar.bot_shadow_GC,
295 lx + lw - 1, ly, lx + lw - 1, ly + lh - 1);
296 }
297 return;
298 }
299
300 if (fill)
301 {
302 XFillRectangle(XtDisplay((Widget) sbw), XtWindow((Widget) sbw),
303 sbw->scrollbar.gc,
304 lx, ly, (unsigned int) lw, (unsigned int) lh);
305
306 if (!(sbw->scrollbar.orientation == XtorientHorizontal))
307 {
308 /* Left border */
309 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
310 sbw->scrollbar.top_shadow_GC,
311 lx, ly, lx, ly + lh - 1);
312
313 /* Right border */
314 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
315 sbw->scrollbar.bot_shadow_GC,
316 lx + lw - 1, ly, lx + lw - 1, ly + lh - 1);
317 }
318 else
319 {
320 /* Top border */
321 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
322 sbw->scrollbar.top_shadow_GC,
323 lx, ly, lx + lw - 1, ly);
324
325 /* Bottom border */
326 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
327 sbw->scrollbar.bot_shadow_GC,
328 lx, ly + lh - 1, lx + lw - 1, ly + lh - 1);
329 }
330 }
331 else
332 {
333 XClearArea(XtDisplay((Widget) sbw), XtWindow((Widget) sbw),
334 lx, ly, (unsigned int) lw, (unsigned int) lh, FALSE);
335 }
336}
337
338/* Paint the thumb in the area specified by sbw->top and
339 sbw->shown. The old area is erased. The painting and
340 erasing is done cleverly so that no flickering will occur.
341 */
342
343 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100344PaintThumb(ScrollbarWidget sbw)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000345{
346 Position oldtop, oldbot, newtop, newbot;
347 Dimension margin, tzl;
348
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;
355
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))
361 {
362 if (newtop < oldtop)
363 FillArea(sbw, newtop, AT_MIN(newbot, oldtop+1),1,0);
364 if (newtop > oldtop)
365 FillArea(sbw, oldtop, AT_MIN(newtop, oldbot ),0,0);
366 if (newbot < oldbot)
367 FillArea(sbw, AT_MAX(newbot, oldtop), oldbot, 0,0);
368 if (newbot > oldbot)
369 FillArea(sbw, AT_MAX(newtop, oldbot-1), newbot, 1,0);
370
371 /* Only draw the missing shadows */
372 FillArea(sbw, newtop, newbot, 0, 1);
373 }
374}
375
376 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100377PaintArrows(ScrollbarWidget sbw)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000378{
379 XPoint point[6];
380 Dimension thickness = sbw->scrollbar.thickness - 1;
381 Dimension size;
382 Dimension off;
383
384 if (XtIsRealized((Widget) sbw))
385 {
386 if ((int)thickness * 2 > (int)sbw->scrollbar.length)
387 {
388 size = sbw->scrollbar.length / 2;
389 off = (int)(thickness - size) / 2;
390 }
391 else
392 {
393 size = thickness;
394 off = 0;
395 }
396 point[0].x = off + sbw->scrollbar.shadow_width;
397 point[0].y = size;
398 point[1].x = thickness - off - sbw->scrollbar.shadow_width;
399 point[1].y = size;
400 point[2].x = thickness / 2;
401 point[2].y = sbw->scrollbar.shadow_width;
402
403 point[3].x = off + sbw->scrollbar.shadow_width;
404 point[3].y = sbw->scrollbar.length - size;
405 point[4].x = thickness - off - sbw->scrollbar.shadow_width;
406 point[4].y = sbw->scrollbar.length - size;
407 point[5].x = thickness / 2;
408 point[5].y = sbw->scrollbar.length - sbw->scrollbar.shadow_width - 1;
409
410 /* horizontal arrows require that x and y coordinates be swapped */
411 if (sbw->scrollbar.orientation == XtorientHorizontal)
412 {
413 int n;
414 int swap;
415 for (n = 0; n < 6; n++)
416 {
417 swap = point[n].x;
418 point[n].x = point[n].y;
419 point[n].y = swap;
420 }
421 }
422 /* draw the up/left arrow */
423 XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
424 sbw->scrollbar.gc,
425 point, 3,
426 Convex, CoordModeOrigin);
427 XDrawLines (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
428 sbw->scrollbar.bot_shadow_GC,
429 point, 3,
430 CoordModeOrigin);
431 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
432 sbw->scrollbar.top_shadow_GC,
433 point[0].x, point[0].y,
434 point[2].x, point[2].y);
435 /* draw the down/right arrow */
436 XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
437 sbw->scrollbar.gc,
438 point+3, 3,
439 Convex, CoordModeOrigin);
440 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
441 sbw->scrollbar.top_shadow_GC,
442 point[3].x, point[3].y,
443 point[4].x, point[4].y);
444 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
445 sbw->scrollbar.top_shadow_GC,
446 point[3].x, point[3].y,
447 point[5].x, point[5].y);
448 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
449 sbw->scrollbar.bot_shadow_GC,
450 point[4].x, point[4].y,
451 point[5].x, point[5].y);
452 }
453}
454
455 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100456Destroy(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000457{
458 ScrollbarWidget sbw = (ScrollbarWidget) w;
459 if (sbw->scrollbar.timer_id != (XtIntervalId) 0)
460 XtRemoveTimeOut (sbw->scrollbar.timer_id);
461 XtReleaseGC(w, sbw->scrollbar.gc);
462 XtReleaseGC(w, sbw->scrollbar.top_shadow_GC);
463 XtReleaseGC(w, sbw->scrollbar.bot_shadow_GC);
464}
465
466 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100467CreateGC(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000468{
469 ScrollbarWidget sbw = (ScrollbarWidget) w;
470 XGCValues gcValues;
471 XtGCMask mask;
472 unsigned int depth = 1;
473
474 if (sbw->scrollbar.thumb == XtUnspecifiedPixmap)
475 {
476 sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w),
477 (Pixel) 1, (Pixel) 0, depth);
478 }
479 else if (sbw->scrollbar.thumb != None)
480 {
481 Window root;
482 int x, y;
483 unsigned int width, height, bw;
484
485 if (XGetGeometry (XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y,
486 &width, &height, &bw, &depth) == 0)
487 EMSG(_("Scrollbar Widget: Could not get geometry of thumb pixmap."));
488 }
489
490 gcValues.foreground = sbw->scrollbar.foreground;
491 gcValues.background = sbw->core.background_pixel;
492 mask = GCForeground | GCBackground;
493
494 if (sbw->scrollbar.thumb != None)
495 {
496 gcValues.fill_style = FillSolid;
497 mask |= GCFillStyle;
498 }
499 /* the creation should be non-caching, because */
500 /* we now set and clear clip masks on the gc returned */
501 sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues);
502}
503
504 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100505SetDimensions(ScrollbarWidget sbw)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000506{
507 if (sbw->scrollbar.orientation == XtorientVertical)
508 {
509 sbw->scrollbar.length = sbw->core.height;
510 sbw->scrollbar.thickness = sbw->core.width;
511 }
512 else
513 {
514 sbw->scrollbar.length = sbw->core.width;
515 sbw->scrollbar.thickness = sbw->core.height;
516 }
517}
518
Bram Moolenaar071d4272004-06-13 20:20:40 +0000519 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100520Initialize(
521 Widget request UNUSED, /* what the client asked for */
522 Widget new, /* what we're going to give him */
523 ArgList args UNUSED,
524 Cardinal *num_args UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525{
526 ScrollbarWidget sbw = (ScrollbarWidget) new;
527
528 CreateGC(new);
529 AllocTopShadowGC(new);
530 AllocBotShadowGC(new);
531
532 if (sbw->core.width == 0)
533 sbw->core.width = (sbw->scrollbar.orientation == XtorientVertical)
534 ? sbw->scrollbar.thickness : sbw->scrollbar.length;
535
536 if (sbw->core.height == 0)
537 sbw->core.height = (sbw->scrollbar.orientation == XtorientHorizontal)
538 ? sbw->scrollbar.thickness : sbw->scrollbar.length;
539
540 SetDimensions(sbw);
541 sbw->scrollbar.scroll_mode = SMODE_NONE;
542 sbw->scrollbar.timer_id = (XtIntervalId)0;
543 sbw->scrollbar.topLoc = 0;
544 sbw->scrollbar.shownLength = sbw->scrollbar.min_thumb;
545}
546
547 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100548Realize(
549 Widget w,
550 Mask *valueMask,
551 XSetWindowAttributes *attributes)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000552{
553 /* The Simple widget actually stuffs the value in the valuemask. */
554 (*vim_scrollbarWidgetClass->core_class.superclass->core_class.realize)
555 (w, valueMask, attributes);
556}
557
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 static Boolean
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100559SetValues(
560 Widget current, /* what I am */
561 Widget request UNUSED, /* what he wants me to be */
562 Widget desired, /* what I will become */
563 ArgList args UNUSED,
564 Cardinal *num_args UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000565{
566 ScrollbarWidget sbw = (ScrollbarWidget) current;
567 ScrollbarWidget dsbw = (ScrollbarWidget) desired;
568 Boolean redraw = FALSE;
569
570/*
571 * If these values are outside the acceptable range ignore them...
572 */
573 if (dsbw->scrollbar.top < 0.0 || dsbw->scrollbar.top > 1.0)
574 dsbw->scrollbar.top = sbw->scrollbar.top;
575
576 if (dsbw->scrollbar.shown < 0.0 || dsbw->scrollbar.shown > 1.0)
577 dsbw->scrollbar.shown = sbw->scrollbar.shown;
578
579/*
580 * Change colors and stuff...
581 */
582 if (XtIsRealized(desired))
583 {
584 if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground ||
585 sbw->core.background_pixel != dsbw->core.background_pixel ||
586 sbw->scrollbar.thumb != dsbw->scrollbar.thumb)
587 {
588 XtReleaseGC(desired, sbw->scrollbar.gc);
589 CreateGC (desired);
590 redraw = TRUE;
591 }
592 if (sbw->scrollbar.top != dsbw->scrollbar.top ||
593 sbw->scrollbar.shown != dsbw->scrollbar.shown)
594 redraw = TRUE;
595 }
596 return redraw;
597}
598
599 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100600Resize(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000601{
602 /* ForgetGravity has taken care of background, but thumb may
603 * have to move as a result of the new size. */
604 SetDimensions ((ScrollbarWidget) w);
605 Redisplay(w, (XEvent*) NULL, (Region)NULL);
606}
607
608
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100610Redisplay(Widget w, XEvent *event, Region region)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000611{
612 ScrollbarWidget sbw = (ScrollbarWidget) w;
613 int x, y;
614 unsigned int width, height;
615
616 _Xaw3dDrawShadows(w, event, region, FALSE);
617
618 if (sbw->scrollbar.orientation == XtorientHorizontal)
619 {
620 x = sbw->scrollbar.topLoc;
621 y = 1;
622 width = sbw->scrollbar.shownLength;
623 height = sbw->core.height - 2;
624 }
625 else
626 {
627 x = 1;
628 y = sbw->scrollbar.topLoc;
629 width = sbw->core.width - 2;
630 height = sbw->scrollbar.shownLength;
631 }
632 if (region == NULL ||
633 XRectInRegion (region, x, y, width, height) != RectangleOut)
634 {
635 /* Forces entire thumb to be painted. */
636 sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1);
637 PaintThumb (sbw);
638 }
639 /* we'd like to be region aware here!!!! */
640 PaintArrows(sbw);
641}
642
643
644 static Boolean
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100645CompareEvents(XEvent *oldEvent, XEvent *newEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000646{
647#define Check(field) if (newEvent->field != oldEvent->field) return False;
648
649 Check(xany.display);
650 Check(xany.type);
651 Check(xany.window);
652
653 switch (newEvent->type)
654 {
655 case MotionNotify:
656 Check(xmotion.state);
657 break;
658 case ButtonPress:
659 case ButtonRelease:
660 Check(xbutton.state);
661 Check(xbutton.button);
662 break;
663 case KeyPress:
664 case KeyRelease:
665 Check(xkey.state);
666 Check(xkey.keycode);
667 break;
668 case EnterNotify:
669 case LeaveNotify:
670 Check(xcrossing.mode);
671 Check(xcrossing.detail);
672 Check(xcrossing.state);
673 break;
674 }
675#undef Check
676
677 return True;
678}
679
680struct EventData
681{
682 XEvent *oldEvent;
683 int count;
684};
685
686 static Bool
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100687PeekNotifyEvent(Display *dpy, XEvent *event, char *args)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688{
689 struct EventData *eventData = (struct EventData*)args;
690
691 return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */
692 || CompareEvents(event, eventData->oldEvent));
693}
694
695
696 static Boolean
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100697LookAhead(Widget w, XEvent *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698{
699 XEvent newEvent;
700 struct EventData eventData;
701
702 if (QLength (XtDisplay (w)) == 0)
703 return False;
704
705 eventData.count = 0;
706 eventData.oldEvent = event;
707
708 XPeekIfEvent (XtDisplay (w), &newEvent, PeekNotifyEvent, (char*)&eventData);
709
710 return CompareEvents (event, &newEvent);
711}
712
713
714 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100715ExtractPosition(
716 XEvent *event,
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100717 Position *x, /* RETURN */
718 Position *y, /* RETURN */
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100719 unsigned int *state) /* RETURN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000720{
721 switch (event->type)
722 {
723 case MotionNotify:
724 *x = event->xmotion.x;
725 *y = event->xmotion.y;
726 if (state != NULL)
727 *state = event->xmotion.state;
728 break;
729 case ButtonPress:
730 case ButtonRelease:
731 *x = event->xbutton.x;
732 *y = event->xbutton.y;
733 if (state != NULL)
734 *state = event->xbutton.state;
735 break;
736 case KeyPress:
737 case KeyRelease:
738 *x = event->xkey.x;
739 *y = event->xkey.y;
740 if (state != NULL)
741 *state = event->xkey.state;
742 break;
743 case EnterNotify:
744 case LeaveNotify:
745 *x = event->xcrossing.x;
746 *y = event->xcrossing.y;
747 if (state != NULL)
748 *state = event->xcrossing.state;
749 break;
750 default:
751 *x = 0; *y = 0;
752 if (state != NULL)
753 *state = 0;
754 }
755}
756
757 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100758HandleThumb(
759 Widget w,
760 XEvent *event,
761 String *params,
762 Cardinal *num_params)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000763{
764 Position x, y, loc;
765 ScrollbarWidget sbw = (ScrollbarWidget) w;
766
767 ExtractPosition(event, &x, &y, (unsigned int *)NULL);
768 loc = PICKLENGTH(sbw, x, y);
769 /* if the motion event puts the pointer in thumb, call Move and Notify */
770 /* also call Move and Notify if we're already in continuous scroll mode */
771 if (sbw->scrollbar.scroll_mode == SMODE_CONT ||
772 (loc >= sbw->scrollbar.topLoc &&
773 loc <= sbw->scrollbar.topLoc + (int)sbw->scrollbar.shownLength))
774 {
775 XtCallActionProc(w, "MoveThumb", event, params, *num_params);
776 XtCallActionProc(w, "NotifyThumb", event, params, *num_params);
777 }
778}
779
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100781RepeatNotify(XtPointer client_data, XtIntervalId *idp UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782{
783 ScrollbarWidget sbw = (ScrollbarWidget) client_data;
784 int call_data;
785 char mode = sbw->scrollbar.scroll_mode;
786 unsigned long rep;
787
788 if (mode == SMODE_NONE || mode == SMODE_CONT)
789 {
790 sbw->scrollbar.timer_id = (XtIntervalId)0;
791 return;
792 }
793
794 if (mode == SMODE_LINE_DOWN || mode == SMODE_LINE_UP)
795 {
796 call_data = ONE_LINE_DATA;
797 rep = LINE_REPEAT;
798 }
799 else
800 {
801 call_data = ONE_PAGE_DATA;
802 rep = PAGE_REPEAT;
803 }
804
805 if (mode == SMODE_PAGE_UP || mode == SMODE_LINE_UP)
806 call_data = -call_data;
807
Bram Moolenaar9d6650f2010-06-06 23:04:47 +0200808 XtCallCallbacks((Widget)sbw, XtNscrollProc, (XtPointer)(long_u)call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809
810 sbw->scrollbar.timer_id =
811 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)sbw),
812 rep,
813 RepeatNotify,
814 client_data);
815}
816
817/*
818 * Same as above, but for floating numbers.
819 */
820 static float
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100821FloatInRange(float num, float small, float big)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822{
823 return (num < small) ? small : ((num > big) ? big : num);
824}
825
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100827ScrollOneLineUp(
828 Widget w,
829 XEvent *event,
830 String *params UNUSED,
831 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832{
833 ScrollSome(w, event, -ONE_LINE_DATA);
834}
835
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100837ScrollOneLineDown(
838 Widget w,
839 XEvent *event,
840 String *params UNUSED,
841 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842{
843 ScrollSome(w, event, ONE_LINE_DATA);
844}
845
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100847ScrollPageDown(
848 Widget w,
849 XEvent *event,
850 String *params UNUSED,
851 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852{
853 ScrollSome(w, event, ONE_PAGE_DATA);
854}
855
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100857ScrollPageUp(
858 Widget w,
859 XEvent *event,
860 String *params UNUSED,
861 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862{
863 ScrollSome(w, event, -ONE_PAGE_DATA);
864}
865
866 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100867ScrollSome(
868 Widget w,
869 XEvent *event,
870 int call_data)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871{
872 ScrollbarWidget sbw = (ScrollbarWidget) w;
873
874 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */
875 return;
876
877 if (LookAhead(w, event))
878 return;
879
880 sbw->scrollbar.scroll_mode = SMODE_LINE_UP;
Bram Moolenaar9d6650f2010-06-06 23:04:47 +0200881 XtCallCallbacks(w, XtNscrollProc, (XtPointer)(long_u)call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882}
883
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100885NotifyScroll(
886 Widget w,
887 XEvent *event,
888 String *params UNUSED,
889 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890{
891 ScrollbarWidget sbw = (ScrollbarWidget) w;
892 Position x, y, loc;
893 Dimension arrow_size;
894 unsigned long delay = 0;
895 int call_data = 0;
896 unsigned int state;
897
898 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */
899 return;
900
901 if (LookAhead (w, event))
902 return;
903
904 ExtractPosition(event, &x, &y, &state);
905 loc = PICKLENGTH(sbw, x, y);
906
907 if ((int)sbw->scrollbar.thickness * 2 > (int)sbw->scrollbar.length)
908 arrow_size = sbw->scrollbar.length / 2;
909 else
910 arrow_size = sbw->scrollbar.thickness;
911
912 /*
913 * handle CTRL modifier
914 */
915 if (state & ControlMask)
916 {
917 if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength)
918 call_data = END_PAGE_DATA;
919 else
920 call_data = -END_PAGE_DATA;
921 sbw->scrollbar.scroll_mode = SMODE_NONE;
922 }
923 /*
924 * handle first arrow zone
925 */
926 else if (loc < (Position)arrow_size)
927 {
928 call_data = -ONE_LINE_DATA;
929 sbw->scrollbar.scroll_mode = SMODE_LINE_UP;
930 delay = LINE_DELAY;
931 }
932
933 /*
934 * handle last arrow zone
935 */
936 else if (loc > (Position)(sbw->scrollbar.length - arrow_size))
937 {
938 call_data = ONE_LINE_DATA;
939 sbw->scrollbar.scroll_mode = SMODE_LINE_DOWN;
940 delay = LINE_DELAY;
941 }
942
943 /*
944 * handle zone "above" the thumb
945 */
946 else if (loc < sbw->scrollbar.topLoc)
947 {
948 call_data = -ONE_PAGE_DATA;
949 sbw->scrollbar.scroll_mode = SMODE_PAGE_UP;
950 delay = PAGE_DELAY;
951 }
952
953 /*
954 * handle zone "below" the thumb
955 */
956 else if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength)
957 {
958 call_data = ONE_PAGE_DATA;
959 sbw->scrollbar.scroll_mode = SMODE_PAGE_DOWN;
960 delay = PAGE_DELAY;
961 }
962
963 if (call_data)
Bram Moolenaar9d6650f2010-06-06 23:04:47 +0200964 XtCallCallbacks(w, XtNscrollProc, (XtPointer)(long_u)call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000965
966 /* establish autoscroll */
967 if (delay)
968 sbw->scrollbar.timer_id =
969 XtAppAddTimeOut(XtWidgetToApplicationContext(w),
970 delay, RepeatNotify, (XtPointer)w);
971}
972
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100974EndScroll(
975 Widget w,
976 XEvent *event UNUSED,
977 String *params UNUSED,
978 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979{
980 ScrollbarWidget sbw = (ScrollbarWidget) w;
981
982 sbw->scrollbar.scroll_mode = SMODE_NONE;
983 /* no need to remove any autoscroll timeout; it will no-op */
984 /* because the scroll_mode is SMODE_NONE */
985 /* but be sure to remove timeout in destroy proc */
986}
987
988 static float
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100989FractionLoc(ScrollbarWidget sbw, int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990{
991 int margin;
992 float height, width;
993
994 margin = MARGIN(sbw);
995 x -= margin;
996 y -= margin;
997 height = (float)sbw->core.height - 2 * margin;
998 width = (float)sbw->core.width - 2 * margin;
999 return PICKLENGTH(sbw, x / width, y / height);
1000}
1001
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001003MoveThumb(
1004 Widget w,
1005 XEvent *event,
1006 String *params UNUSED,
1007 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008{
1009 ScrollbarWidget sbw = (ScrollbarWidget)w;
1010 Position x, y;
1011 float top;
1012 char old_mode = sbw->scrollbar.scroll_mode;
1013
1014 sbw->scrollbar.scroll_mode = SMODE_CONT; /* indicate continuous scroll */
1015
1016 if (LookAhead(w, event))
1017 return;
1018
1019 if (!event->xmotion.same_screen)
1020 return;
1021
1022 ExtractPosition(event, &x, &y, (unsigned int *)NULL);
1023
1024 top = FractionLoc(sbw, x, y);
1025
1026 if (old_mode != SMODE_CONT) /* start dragging: set offset */
1027 {
1028 if (event->xbutton.button == Button2)
1029 sbw->scrollbar.scroll_off = sbw->scrollbar.shown / 2.;
1030 else
1031 sbw->scrollbar.scroll_off = top - sbw->scrollbar.top;
1032 }
1033
1034 top -= sbw->scrollbar.scroll_off;
1035 if (sbw->scrollbar.limit_thumb)
1036 top = FloatInRange(top, 0.0,
1037 sbw->scrollbar.max - sbw->scrollbar.shown + 0.000001);
1038 else
1039 top = FloatInRange(top, 0.0, sbw->scrollbar.max);
1040
1041 sbw->scrollbar.top = top;
1042 PaintThumb(sbw);
1043 XFlush(XtDisplay(w)); /* re-draw it before Notifying */
1044}
1045
1046
Bram Moolenaar071d4272004-06-13 20:20:40 +00001047 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001048NotifyThumb(
1049 Widget w,
1050 XEvent *event,
1051 String *params UNUSED,
1052 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053{
1054 ScrollbarWidget sbw = (ScrollbarWidget)w;
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00001055 /* Use a union to avoid a warning for the weird conversion from float to
1056 * XtPointer. Comes from Xaw/Scrollbar.c. */
1057 union {
1058 XtPointer xtp;
1059 float xtf;
1060 } xtpf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001061
1062 if (LookAhead(w, event))
1063 return;
1064
1065 /* thumbProc is not pretty, but is necessary for backwards
1066 compatibility on those architectures for which it work{s,ed};
1067 the intent is to pass a (truncated) float by value. */
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00001068 xtpf.xtf = sbw->scrollbar.top;
1069 XtCallCallbacks(w, XtNthumbProc, xtpf.xtp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001070 XtCallCallbacks(w, XtNjumpProc, (XtPointer)&sbw->scrollbar.top);
1071}
1072
Bram Moolenaar071d4272004-06-13 20:20:40 +00001073 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001074AllocTopShadowGC(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075{
1076 ScrollbarWidget sbw = (ScrollbarWidget) w;
1077 XtGCMask valuemask;
1078 XGCValues myXGCV;
1079
1080 valuemask = GCForeground;
1081 myXGCV.foreground = sbw->scrollbar.top_shadow_pixel;
1082 sbw->scrollbar.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
1083}
1084
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001086AllocBotShadowGC(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087{
1088 ScrollbarWidget sbw = (ScrollbarWidget) w;
1089 XtGCMask valuemask;
1090 XGCValues myXGCV;
1091
1092 valuemask = GCForeground;
1093 myXGCV.foreground = sbw->scrollbar.bot_shadow_pixel;
1094 sbw->scrollbar.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
1095}
1096
Bram Moolenaar071d4272004-06-13 20:20:40 +00001097 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001098_Xaw3dDrawShadows(
1099 Widget gw,
1100 XEvent *event UNUSED,
1101 Region region,
1102 int out)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001103{
1104 XPoint pt[6];
1105 ScrollbarWidget sbw = (ScrollbarWidget) gw;
1106 Dimension s = sbw->scrollbar.shadow_width;
1107 /*
1108 * draw the shadows using the core part width and height,
1109 * and the scrollbar part shadow_width.
1110 *
1111 * no point to do anything if the shadow_width is 0 or the
1112 * widget has not been realized.
1113 */
1114 if (s > 0 && XtIsRealized(gw))
1115 {
1116 Dimension h = sbw->core.height;
1117 Dimension w = sbw->core.width;
1118 Dimension wms = w - s;
1119 Dimension hms = h - s;
1120 Display *dpy = XtDisplay (gw);
1121 Window win = XtWindow (gw);
1122 GC top, bot;
1123
1124 if (out)
1125 {
1126 top = sbw->scrollbar.top_shadow_GC;
1127 bot = sbw->scrollbar.bot_shadow_GC;
1128 }
1129 else
1130 {
1131 top = sbw->scrollbar.bot_shadow_GC;
1132 bot = sbw->scrollbar.top_shadow_GC;
1133 }
1134
1135 /* top-left shadow */
1136 if ((region == NULL) ||
1137 (XRectInRegion (region, 0, 0, w, s) != RectangleOut) ||
1138 (XRectInRegion (region, 0, 0, s, h) != RectangleOut))
1139 {
1140 pt[0].x = 0; pt[0].y = h;
1141 pt[1].x = pt[1].y = 0;
1142 pt[2].x = w; pt[2].y = 0;
1143 pt[3].x = wms; pt[3].y = s;
1144 pt[4].x = pt[4].y = s;
1145 pt[5].x = s; pt[5].y = hms;
1146 XFillPolygon (dpy, win, top, pt, 6, Complex, CoordModeOrigin);
1147 }
1148
1149 /* bottom-right shadow */
1150 if ((region == NULL) ||
1151 (XRectInRegion (region, 0, hms, w, s) != RectangleOut) ||
1152 (XRectInRegion (region, wms, 0, s, h) != RectangleOut))
1153 {
1154 pt[0].x = 0; pt[0].y = h;
1155 pt[1].x = w; pt[1].y = h;
1156 pt[2].x = w; pt[2].y = 0;
1157 pt[3].x = wms; pt[3].y = s;
1158 pt[4].x = wms; pt[4].y = hms;
1159 pt[5].x = s; pt[5].y = hms;
1160 XFillPolygon (dpy, win, bot, pt, 6, Complex, CoordModeOrigin);
1161 }
1162 }
1163}
1164
1165
1166/*
1167 * Set the scroll bar to the given location.
1168 */
1169 void
Bram Moolenaar02fdaea2016-01-30 18:13:55 +01001170vim_XawScrollbarSetThumb(Widget w, double top, double shown, double max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001171{
1172 ScrollbarWidget sbw = (ScrollbarWidget) w;
1173
1174 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if still thumbing */
1175 return;
1176
1177 sbw->scrollbar.max = (max > 1.0) ? 1.0 :
1178 (max >= 0.0) ? max : sbw->scrollbar.max;
1179
1180 sbw->scrollbar.top = (top > sbw->scrollbar.max) ? sbw->scrollbar.max :
1181 (top >= 0.0) ? top : sbw->scrollbar.top;
1182
1183 sbw->scrollbar.shown = (shown > 1.0) ? 1.0 :
1184 (shown >= 0.0) ? shown : sbw->scrollbar.shown;
1185
1186 PaintThumb(sbw);
1187}