blob: 659e93463ca751709e4b4892a2e913a3e4b88e85 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet: */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002/*
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
Bram Moolenaarf7506ca2017-02-25 16:01:49 +010063#include "vim.h"
64
Bram Moolenaar071d4272004-06-13 20:20:40 +000065#include <X11/IntrinsicP.h>
66#include <X11/StringDefs.h>
67
68#include <X11/Xaw/XawInit.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000069#include "gui_at_sb.h"
70
71#include <X11/Xmu/Drawing.h>
72
73/* Private definitions. */
74
75static char defaultTranslations[] =
76 "<Btn1Down>: NotifyScroll()\n\
77 <Btn2Down>: MoveThumb() NotifyThumb()\n\
78 <Btn3Down>: NotifyScroll()\n\
79 <Btn4Down>: ScrollOneLineUp()\n\
80 Shift<Btn4Down>: ScrollPageUp()\n\
81 <Btn5Down>: ScrollOneLineDown()\n\
82 Shift<Btn5Down>: ScrollPageDown()\n\
83 <Btn1Motion>: HandleThumb()\n\
84 <Btn3Motion>: HandleThumb()\n\
85 <Btn2Motion>: MoveThumb() NotifyThumb()\n\
86 <BtnUp>: EndScroll()";
87
88static float floatZero = 0.0;
89
90#define Offset(field) XtOffsetOf(ScrollbarRec, field)
91
92static XtResource resources[] =
93{
94 {XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
95 Offset(scrollbar.length), XtRImmediate, (XtPointer) 1},
96 {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
97 Offset(scrollbar.thickness), XtRImmediate, (XtPointer) 14},
98 {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
99 Offset(scrollbar.orientation), XtRImmediate, (XtPointer) XtorientVertical},
100 {XtNscrollProc, XtCCallback, XtRCallback, sizeof(XtPointer),
101 Offset(scrollbar.scrollProc), XtRCallback, NULL},
102 {XtNthumbProc, XtCCallback, XtRCallback, sizeof(XtPointer),
103 Offset(scrollbar.thumbProc), XtRCallback, NULL},
104 {XtNjumpProc, XtCCallback, XtRCallback, sizeof(XtPointer),
105 Offset(scrollbar.jumpProc), XtRCallback, NULL},
106 {XtNthumb, XtCThumb, XtRBitmap, sizeof(Pixmap),
107 Offset(scrollbar.thumb), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
108 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
109 Offset(scrollbar.foreground), XtRString, XtDefaultForeground},
110 {XtNshown, XtCShown, XtRFloat, sizeof(float),
111 Offset(scrollbar.shown), XtRFloat, (XtPointer)&floatZero},
112 {XtNtopOfThumb, XtCTopOfThumb, XtRFloat, sizeof(float),
113 Offset(scrollbar.top), XtRFloat, (XtPointer)&floatZero},
114 {XtNmaxOfThumb, XtCMaxOfThumb, XtRFloat, sizeof(float),
115 Offset(scrollbar.max), XtRFloat, (XtPointer)&floatZero},
116 {XtNminimumThumb, XtCMinimumThumb, XtRDimension, sizeof(Dimension),
117 Offset(scrollbar.min_thumb), XtRImmediate, (XtPointer) 7},
118 {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
119 Offset(scrollbar.shadow_width), XtRImmediate, (XtPointer) 1},
120 {XtNtopShadowPixel, XtCTopShadowPixel, XtRPixel, sizeof(Pixel),
121 Offset(scrollbar.top_shadow_pixel), XtRString, XtDefaultBackground},
122 {XtNbottomShadowPixel, XtCBottomShadowPixel, XtRPixel, sizeof(Pixel),
123 Offset(scrollbar.bot_shadow_pixel), XtRString, XtDefaultForeground},
124 {XtNlimitThumb, XtCLimitThumb, XtRBool, sizeof(Bool),
125 Offset(scrollbar.limit_thumb), XtRImmediate, (XtPointer)0}
126};
127#undef Offset
128
Bram Moolenaar56985072016-01-29 23:23:06 +0100129static void ClassInitialize(void);
130static void Initialize(Widget, Widget, ArgList, Cardinal *);
131static void Destroy(Widget);
132static void Realize(Widget, Mask *, XSetWindowAttributes *);
133static void Resize(Widget);
134static void Redisplay(Widget, XEvent *, Region);
135static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000136
Bram Moolenaar56985072016-01-29 23:23:06 +0100137static void HandleThumb(Widget, XEvent *, String *, Cardinal *);
138static void MoveThumb(Widget, XEvent *, String *, Cardinal *);
139static void NotifyThumb(Widget, XEvent *, String *, Cardinal *);
140static void NotifyScroll(Widget, XEvent *, String *, Cardinal *);
141static void EndScroll(Widget, XEvent *, String *, Cardinal *);
142static void ScrollOneLineUp(Widget, XEvent *, String *, Cardinal *);
143static void ScrollOneLineDown(Widget, XEvent *, String *, Cardinal *);
144static void ScrollPageUp(Widget, XEvent *, String *, Cardinal *);
145static void ScrollPageDown(Widget, XEvent *, String *, Cardinal *);
146static void ScrollSome(Widget w, XEvent *event, int call_data);
147static void _Xaw3dDrawShadows(Widget, XEvent *, Region, int);
148static void AllocTopShadowGC(Widget);
149static void AllocBotShadowGC(Widget);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150
151static XtActionsRec actions[] =
152{
153 {"HandleThumb", HandleThumb},
154 {"MoveThumb", MoveThumb},
155 {"NotifyThumb", NotifyThumb},
156 {"NotifyScroll", NotifyScroll},
157 {"EndScroll", EndScroll},
158 {"ScrollOneLineUp", ScrollOneLineUp},
159 {"ScrollOneLineDown", ScrollOneLineDown},
160 {"ScrollPageUp", ScrollPageUp},
161 {"ScrollPageDown", ScrollPageDown}
162};
163
164
165ScrollbarClassRec vim_scrollbarClassRec =
166{
167 { /* core fields */
168 /* superclass */ (WidgetClass) &simpleClassRec,
169 /* class_name */ "Scrollbar",
170 /* size */ sizeof(ScrollbarRec),
171 /* class_initialize */ ClassInitialize,
172 /* class_part_init */ NULL,
173 /* class_inited */ FALSE,
174 /* initialize */ Initialize,
175 /* initialize_hook */ NULL,
176 /* realize */ Realize,
177 /* actions */ actions,
178 /* num_actions */ XtNumber(actions),
179 /* resources */ resources,
180 /* num_resources */ XtNumber(resources),
181 /* xrm_class */ NULLQUARK,
182 /* compress_motion */ TRUE,
183 /* compress_exposure*/ TRUE,
184 /* compress_enterleave*/ TRUE,
185 /* visible_interest */ FALSE,
186 /* destroy */ Destroy,
187 /* resize */ Resize,
188 /* expose */ Redisplay,
189 /* set_values */ SetValues,
190 /* set_values_hook */ NULL,
191 /* set_values_almost */ XtInheritSetValuesAlmost,
192 /* get_values_hook */ NULL,
193 /* accept_focus */ NULL,
194 /* version */ XtVersion,
195 /* callback_private */ NULL,
196 /* tm_table */ defaultTranslations,
197 /* query_geometry */ XtInheritQueryGeometry,
198 /* display_accelerator*/ XtInheritDisplayAccelerator,
199 /* extension */ NULL
200 },
201 { /* simple fields */
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000202 /* change_sensitive */ XtInheritChangeSensitive,
203#ifndef OLDXAW
204 /* extension */ NULL
205#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000206 },
207 { /* scrollbar fields */
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000208 /* empty */ 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000209 }
210};
211
212WidgetClass vim_scrollbarWidgetClass = (WidgetClass)&vim_scrollbarClassRec;
213
214#define NoButton -1
215#define PICKLENGTH(widget, x, y) \
216 ((widget->scrollbar.orientation == XtorientHorizontal) ? (x) : (y))
217#define AT_MIN(x,y) ((x) < (y) ? (x) : (y))
218#define AT_MAX(x,y) ((x) > (y) ? (x) : (y))
219
220#define LINE_DELAY 300
221#define PAGE_DELAY 300
222#define LINE_REPEAT 50
223#define PAGE_REPEAT 250
224
225 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100226ClassInitialize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000227{
228 XawInitializeWidgetSet();
229 XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
230 (XtConvertArgList)NULL, (Cardinal)0 );
231}
232
233#define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->scrollbar.shadow_width
234
235 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100236FillArea(
237 ScrollbarWidget sbw,
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100238 Position top,
239 Position bottom,
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100240 int fill,
241 int draw_shadow)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242{
243 int tlen = bottom - top; /* length of thumb in pixels */
244 int sw, margin, floor;
245 int lx, ly, lw, lh;
246
247 if (bottom <= 0 || bottom <= top)
248 return;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000249 sw = sbw->scrollbar.shadow_width;
250 if (sw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251 sw = 0;
252 margin = MARGIN (sbw);
253 floor = sbw->scrollbar.length - margin + 2;
254
255 if (sbw->scrollbar.orientation == XtorientHorizontal)
256 {
257 lx = ((top < margin) ? margin : top);
258 ly = sw;
259 lw = (((top + tlen) > floor) ? floor - top : tlen);
260 lh = sbw->core.height - 2 * sw;
261 }
262 else
263 {
264 lx = sw;
265 ly = ((top < margin) ? margin : top);
266 lw = sbw->core.width - 2 * sw;
267 lh = (((top + tlen) > floor) ? floor - top : tlen);
268 }
269 if (lh <= 0 || lw <= 0)
270 return;
271
272 if (draw_shadow)
273 {
274 if (!(sbw->scrollbar.orientation == XtorientHorizontal))
275 {
276 /* Top border */
277 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
278 sbw->scrollbar.top_shadow_GC,
279 lx, ly, lx + lw - 1, ly);
280
281 /* Bottom border */
282 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
283 sbw->scrollbar.bot_shadow_GC,
284 lx, ly + lh - 1, lx + lw - 1, ly + lh - 1);
285 }
286 else
287 {
288 /* Left border */
289 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
290 sbw->scrollbar.top_shadow_GC,
291 lx, ly, lx, ly + lh - 1);
292
293 /* Right border */
294 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
295 sbw->scrollbar.bot_shadow_GC,
296 lx + lw - 1, ly, lx + lw - 1, ly + lh - 1);
297 }
298 return;
299 }
300
301 if (fill)
302 {
303 XFillRectangle(XtDisplay((Widget) sbw), XtWindow((Widget) sbw),
304 sbw->scrollbar.gc,
305 lx, ly, (unsigned int) lw, (unsigned int) lh);
306
307 if (!(sbw->scrollbar.orientation == XtorientHorizontal))
308 {
309 /* Left border */
310 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
311 sbw->scrollbar.top_shadow_GC,
312 lx, ly, lx, ly + lh - 1);
313
314 /* Right border */
315 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
316 sbw->scrollbar.bot_shadow_GC,
317 lx + lw - 1, ly, lx + lw - 1, ly + lh - 1);
318 }
319 else
320 {
321 /* Top border */
322 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
323 sbw->scrollbar.top_shadow_GC,
324 lx, ly, lx + lw - 1, ly);
325
326 /* Bottom border */
327 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
328 sbw->scrollbar.bot_shadow_GC,
329 lx, ly + lh - 1, lx + lw - 1, ly + lh - 1);
330 }
331 }
332 else
333 {
334 XClearArea(XtDisplay((Widget) sbw), XtWindow((Widget) sbw),
335 lx, ly, (unsigned int) lw, (unsigned int) lh, FALSE);
336 }
337}
338
339/* Paint the thumb in the area specified by sbw->top and
340 sbw->shown. The old area is erased. The painting and
341 erasing is done cleverly so that no flickering will occur.
342 */
343
344 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100345PaintThumb(ScrollbarWidget sbw)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000346{
347 Position oldtop, oldbot, newtop, newbot;
348 Dimension margin, tzl;
349
350 margin = MARGIN (sbw);
351 tzl = sbw->scrollbar.length - 2 * margin;
352 newtop = margin + (int)(tzl * sbw->scrollbar.top);
353 newbot = newtop + (int)(tzl * sbw->scrollbar.shown) + 1;
354 if (newbot < newtop + (int)sbw->scrollbar.min_thumb)
355 newbot = newtop + sbw->scrollbar.min_thumb;
356
357 oldtop = sbw->scrollbar.topLoc;
358 oldbot = oldtop + sbw->scrollbar.shownLength;
359 sbw->scrollbar.topLoc = newtop;
360 sbw->scrollbar.shownLength = newbot - newtop;
361 if (XtIsRealized ((Widget) sbw))
362 {
363 if (newtop < oldtop)
364 FillArea(sbw, newtop, AT_MIN(newbot, oldtop+1),1,0);
365 if (newtop > oldtop)
366 FillArea(sbw, oldtop, AT_MIN(newtop, oldbot ),0,0);
367 if (newbot < oldbot)
368 FillArea(sbw, AT_MAX(newbot, oldtop), oldbot, 0,0);
369 if (newbot > oldbot)
370 FillArea(sbw, AT_MAX(newtop, oldbot-1), newbot, 1,0);
371
372 /* Only draw the missing shadows */
373 FillArea(sbw, newtop, newbot, 0, 1);
374 }
375}
376
377 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100378PaintArrows(ScrollbarWidget sbw)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000379{
380 XPoint point[6];
381 Dimension thickness = sbw->scrollbar.thickness - 1;
382 Dimension size;
383 Dimension off;
384
385 if (XtIsRealized((Widget) sbw))
386 {
387 if ((int)thickness * 2 > (int)sbw->scrollbar.length)
388 {
389 size = sbw->scrollbar.length / 2;
390 off = (int)(thickness - size) / 2;
391 }
392 else
393 {
394 size = thickness;
395 off = 0;
396 }
397 point[0].x = off + sbw->scrollbar.shadow_width;
398 point[0].y = size;
399 point[1].x = thickness - off - sbw->scrollbar.shadow_width;
400 point[1].y = size;
401 point[2].x = thickness / 2;
402 point[2].y = sbw->scrollbar.shadow_width;
403
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;
410
411 /* horizontal arrows require that x and y coordinates be swapped */
412 if (sbw->scrollbar.orientation == XtorientHorizontal)
413 {
414 int n;
415 int swap;
416 for (n = 0; n < 6; n++)
417 {
418 swap = point[n].x;
419 point[n].x = point[n].y;
420 point[n].y = swap;
421 }
422 }
423 /* draw the up/left arrow */
424 XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
425 sbw->scrollbar.gc,
426 point, 3,
427 Convex, CoordModeOrigin);
428 XDrawLines (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
429 sbw->scrollbar.bot_shadow_GC,
430 point, 3,
431 CoordModeOrigin);
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),
438 sbw->scrollbar.gc,
439 point+3, 3,
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);
453 }
454}
455
456 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100457Destroy(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000458{
459 ScrollbarWidget sbw = (ScrollbarWidget) w;
460 if (sbw->scrollbar.timer_id != (XtIntervalId) 0)
461 XtRemoveTimeOut (sbw->scrollbar.timer_id);
462 XtReleaseGC(w, sbw->scrollbar.gc);
463 XtReleaseGC(w, sbw->scrollbar.top_shadow_GC);
464 XtReleaseGC(w, sbw->scrollbar.bot_shadow_GC);
465}
466
467 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100468CreateGC(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000469{
470 ScrollbarWidget sbw = (ScrollbarWidget) w;
471 XGCValues gcValues;
472 XtGCMask mask;
473 unsigned int depth = 1;
474
475 if (sbw->scrollbar.thumb == XtUnspecifiedPixmap)
476 {
477 sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w),
478 (Pixel) 1, (Pixel) 0, depth);
479 }
480 else if (sbw->scrollbar.thumb != None)
481 {
482 Window root;
483 int x, y;
484 unsigned int width, height, bw;
485
486 if (XGetGeometry (XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y,
487 &width, &height, &bw, &depth) == 0)
488 EMSG(_("Scrollbar Widget: Could not get geometry of thumb pixmap."));
489 }
490
491 gcValues.foreground = sbw->scrollbar.foreground;
492 gcValues.background = sbw->core.background_pixel;
493 mask = GCForeground | GCBackground;
494
495 if (sbw->scrollbar.thumb != None)
496 {
497 gcValues.fill_style = FillSolid;
498 mask |= GCFillStyle;
499 }
500 /* the creation should be non-caching, because */
501 /* we now set and clear clip masks on the gc returned */
502 sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues);
503}
504
505 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100506SetDimensions(ScrollbarWidget sbw)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000507{
508 if (sbw->scrollbar.orientation == XtorientVertical)
509 {
510 sbw->scrollbar.length = sbw->core.height;
511 sbw->scrollbar.thickness = sbw->core.width;
512 }
513 else
514 {
515 sbw->scrollbar.length = sbw->core.width;
516 sbw->scrollbar.thickness = sbw->core.height;
517 }
518}
519
Bram Moolenaar071d4272004-06-13 20:20:40 +0000520 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100521Initialize(
522 Widget request UNUSED, /* what the client asked for */
523 Widget new, /* what we're going to give him */
524 ArgList args UNUSED,
525 Cardinal *num_args UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526{
527 ScrollbarWidget sbw = (ScrollbarWidget) new;
528
529 CreateGC(new);
530 AllocTopShadowGC(new);
531 AllocBotShadowGC(new);
532
533 if (sbw->core.width == 0)
534 sbw->core.width = (sbw->scrollbar.orientation == XtorientVertical)
535 ? sbw->scrollbar.thickness : sbw->scrollbar.length;
536
537 if (sbw->core.height == 0)
538 sbw->core.height = (sbw->scrollbar.orientation == XtorientHorizontal)
539 ? sbw->scrollbar.thickness : sbw->scrollbar.length;
540
541 SetDimensions(sbw);
542 sbw->scrollbar.scroll_mode = SMODE_NONE;
543 sbw->scrollbar.timer_id = (XtIntervalId)0;
544 sbw->scrollbar.topLoc = 0;
545 sbw->scrollbar.shownLength = sbw->scrollbar.min_thumb;
546}
547
548 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100549Realize(
550 Widget w,
551 Mask *valueMask,
552 XSetWindowAttributes *attributes)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000553{
554 /* The Simple widget actually stuffs the value in the valuemask. */
555 (*vim_scrollbarWidgetClass->core_class.superclass->core_class.realize)
556 (w, valueMask, attributes);
557}
558
Bram Moolenaar071d4272004-06-13 20:20:40 +0000559 static Boolean
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100560SetValues(
561 Widget current, /* what I am */
562 Widget request UNUSED, /* what he wants me to be */
563 Widget desired, /* what I will become */
564 ArgList args UNUSED,
565 Cardinal *num_args UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566{
567 ScrollbarWidget sbw = (ScrollbarWidget) current;
568 ScrollbarWidget dsbw = (ScrollbarWidget) desired;
569 Boolean redraw = FALSE;
570
571/*
572 * If these values are outside the acceptable range ignore them...
573 */
574 if (dsbw->scrollbar.top < 0.0 || dsbw->scrollbar.top > 1.0)
575 dsbw->scrollbar.top = sbw->scrollbar.top;
576
577 if (dsbw->scrollbar.shown < 0.0 || dsbw->scrollbar.shown > 1.0)
578 dsbw->scrollbar.shown = sbw->scrollbar.shown;
579
580/*
581 * Change colors and stuff...
582 */
583 if (XtIsRealized(desired))
584 {
585 if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground ||
586 sbw->core.background_pixel != dsbw->core.background_pixel ||
587 sbw->scrollbar.thumb != dsbw->scrollbar.thumb)
588 {
589 XtReleaseGC(desired, sbw->scrollbar.gc);
590 CreateGC (desired);
591 redraw = TRUE;
592 }
593 if (sbw->scrollbar.top != dsbw->scrollbar.top ||
594 sbw->scrollbar.shown != dsbw->scrollbar.shown)
595 redraw = TRUE;
596 }
597 return redraw;
598}
599
600 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100601Resize(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000602{
603 /* ForgetGravity has taken care of background, but thumb may
604 * have to move as a result of the new size. */
605 SetDimensions ((ScrollbarWidget) w);
606 Redisplay(w, (XEvent*) NULL, (Region)NULL);
607}
608
609
Bram Moolenaar071d4272004-06-13 20:20:40 +0000610 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100611Redisplay(Widget w, XEvent *event, Region region)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612{
613 ScrollbarWidget sbw = (ScrollbarWidget) w;
614 int x, y;
615 unsigned int width, height;
616
617 _Xaw3dDrawShadows(w, event, region, FALSE);
618
619 if (sbw->scrollbar.orientation == XtorientHorizontal)
620 {
621 x = sbw->scrollbar.topLoc;
622 y = 1;
623 width = sbw->scrollbar.shownLength;
624 height = sbw->core.height - 2;
625 }
626 else
627 {
628 x = 1;
629 y = sbw->scrollbar.topLoc;
630 width = sbw->core.width - 2;
631 height = sbw->scrollbar.shownLength;
632 }
633 if (region == NULL ||
634 XRectInRegion (region, x, y, width, height) != RectangleOut)
635 {
636 /* Forces entire thumb to be painted. */
637 sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1);
638 PaintThumb (sbw);
639 }
640 /* we'd like to be region aware here!!!! */
641 PaintArrows(sbw);
642}
643
644
645 static Boolean
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100646CompareEvents(XEvent *oldEvent, XEvent *newEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000647{
648#define Check(field) if (newEvent->field != oldEvent->field) return False;
649
650 Check(xany.display);
651 Check(xany.type);
652 Check(xany.window);
653
654 switch (newEvent->type)
655 {
656 case MotionNotify:
657 Check(xmotion.state);
658 break;
659 case ButtonPress:
660 case ButtonRelease:
661 Check(xbutton.state);
662 Check(xbutton.button);
663 break;
664 case KeyPress:
665 case KeyRelease:
666 Check(xkey.state);
667 Check(xkey.keycode);
668 break;
669 case EnterNotify:
670 case LeaveNotify:
671 Check(xcrossing.mode);
672 Check(xcrossing.detail);
673 Check(xcrossing.state);
674 break;
675 }
676#undef Check
677
678 return True;
679}
680
681struct EventData
682{
683 XEvent *oldEvent;
684 int count;
685};
686
687 static Bool
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100688PeekNotifyEvent(Display *dpy, XEvent *event, char *args)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000689{
690 struct EventData *eventData = (struct EventData*)args;
691
692 return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */
693 || CompareEvents(event, eventData->oldEvent));
694}
695
696
697 static Boolean
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100698LookAhead(Widget w, XEvent *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000699{
700 XEvent newEvent;
701 struct EventData eventData;
702
703 if (QLength (XtDisplay (w)) == 0)
704 return False;
705
706 eventData.count = 0;
707 eventData.oldEvent = event;
708
709 XPeekIfEvent (XtDisplay (w), &newEvent, PeekNotifyEvent, (char*)&eventData);
710
711 return CompareEvents (event, &newEvent);
712}
713
714
715 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100716ExtractPosition(
717 XEvent *event,
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100718 Position *x, /* RETURN */
719 Position *y, /* RETURN */
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100720 unsigned int *state) /* RETURN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000721{
722 switch (event->type)
723 {
724 case MotionNotify:
725 *x = event->xmotion.x;
726 *y = event->xmotion.y;
727 if (state != NULL)
728 *state = event->xmotion.state;
729 break;
730 case ButtonPress:
731 case ButtonRelease:
732 *x = event->xbutton.x;
733 *y = event->xbutton.y;
734 if (state != NULL)
735 *state = event->xbutton.state;
736 break;
737 case KeyPress:
738 case KeyRelease:
739 *x = event->xkey.x;
740 *y = event->xkey.y;
741 if (state != NULL)
742 *state = event->xkey.state;
743 break;
744 case EnterNotify:
745 case LeaveNotify:
746 *x = event->xcrossing.x;
747 *y = event->xcrossing.y;
748 if (state != NULL)
749 *state = event->xcrossing.state;
750 break;
751 default:
752 *x = 0; *y = 0;
753 if (state != NULL)
754 *state = 0;
755 }
756}
757
758 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100759HandleThumb(
760 Widget w,
761 XEvent *event,
762 String *params,
763 Cardinal *num_params)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764{
765 Position x, y, loc;
766 ScrollbarWidget sbw = (ScrollbarWidget) w;
767
768 ExtractPosition(event, &x, &y, (unsigned int *)NULL);
769 loc = PICKLENGTH(sbw, x, y);
770 /* if the motion event puts the pointer in thumb, call Move and Notify */
771 /* also call Move and Notify if we're already in continuous scroll mode */
772 if (sbw->scrollbar.scroll_mode == SMODE_CONT ||
773 (loc >= sbw->scrollbar.topLoc &&
774 loc <= sbw->scrollbar.topLoc + (int)sbw->scrollbar.shownLength))
775 {
776 XtCallActionProc(w, "MoveThumb", event, params, *num_params);
777 XtCallActionProc(w, "NotifyThumb", event, params, *num_params);
778 }
779}
780
Bram Moolenaar071d4272004-06-13 20:20:40 +0000781 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100782RepeatNotify(XtPointer client_data, XtIntervalId *idp UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783{
784 ScrollbarWidget sbw = (ScrollbarWidget) client_data;
785 int call_data;
786 char mode = sbw->scrollbar.scroll_mode;
787 unsigned long rep;
788
789 if (mode == SMODE_NONE || mode == SMODE_CONT)
790 {
791 sbw->scrollbar.timer_id = (XtIntervalId)0;
792 return;
793 }
794
795 if (mode == SMODE_LINE_DOWN || mode == SMODE_LINE_UP)
796 {
797 call_data = ONE_LINE_DATA;
798 rep = LINE_REPEAT;
799 }
800 else
801 {
802 call_data = ONE_PAGE_DATA;
803 rep = PAGE_REPEAT;
804 }
805
806 if (mode == SMODE_PAGE_UP || mode == SMODE_LINE_UP)
807 call_data = -call_data;
808
Bram Moolenaar9d6650f2010-06-06 23:04:47 +0200809 XtCallCallbacks((Widget)sbw, XtNscrollProc, (XtPointer)(long_u)call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810
811 sbw->scrollbar.timer_id =
812 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)sbw),
813 rep,
814 RepeatNotify,
815 client_data);
816}
817
818/*
819 * Same as above, but for floating numbers.
820 */
821 static float
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100822FloatInRange(float num, float small, float big)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823{
824 return (num < small) ? small : ((num > big) ? big : num);
825}
826
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100828ScrollOneLineUp(
829 Widget w,
830 XEvent *event,
831 String *params UNUSED,
832 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000833{
834 ScrollSome(w, event, -ONE_LINE_DATA);
835}
836
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100838ScrollOneLineDown(
839 Widget w,
840 XEvent *event,
841 String *params UNUSED,
842 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843{
844 ScrollSome(w, event, ONE_LINE_DATA);
845}
846
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100848ScrollPageDown(
849 Widget w,
850 XEvent *event,
851 String *params UNUSED,
852 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853{
854 ScrollSome(w, event, ONE_PAGE_DATA);
855}
856
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100858ScrollPageUp(
859 Widget w,
860 XEvent *event,
861 String *params UNUSED,
862 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863{
864 ScrollSome(w, event, -ONE_PAGE_DATA);
865}
866
867 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100868ScrollSome(
869 Widget w,
870 XEvent *event,
871 int call_data)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872{
873 ScrollbarWidget sbw = (ScrollbarWidget) w;
874
875 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */
876 return;
877
878 if (LookAhead(w, event))
879 return;
880
881 sbw->scrollbar.scroll_mode = SMODE_LINE_UP;
Bram Moolenaar9d6650f2010-06-06 23:04:47 +0200882 XtCallCallbacks(w, XtNscrollProc, (XtPointer)(long_u)call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883}
884
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100886NotifyScroll(
887 Widget w,
888 XEvent *event,
889 String *params UNUSED,
890 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891{
892 ScrollbarWidget sbw = (ScrollbarWidget) w;
893 Position x, y, loc;
894 Dimension arrow_size;
895 unsigned long delay = 0;
896 int call_data = 0;
897 unsigned int state;
898
899 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */
900 return;
901
902 if (LookAhead (w, event))
903 return;
904
905 ExtractPosition(event, &x, &y, &state);
906 loc = PICKLENGTH(sbw, x, y);
907
908 if ((int)sbw->scrollbar.thickness * 2 > (int)sbw->scrollbar.length)
909 arrow_size = sbw->scrollbar.length / 2;
910 else
911 arrow_size = sbw->scrollbar.thickness;
912
913 /*
914 * handle CTRL modifier
915 */
916 if (state & ControlMask)
917 {
918 if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength)
919 call_data = END_PAGE_DATA;
920 else
921 call_data = -END_PAGE_DATA;
922 sbw->scrollbar.scroll_mode = SMODE_NONE;
923 }
924 /*
925 * handle first arrow zone
926 */
927 else if (loc < (Position)arrow_size)
928 {
929 call_data = -ONE_LINE_DATA;
930 sbw->scrollbar.scroll_mode = SMODE_LINE_UP;
931 delay = LINE_DELAY;
932 }
933
934 /*
935 * handle last arrow zone
936 */
937 else if (loc > (Position)(sbw->scrollbar.length - arrow_size))
938 {
939 call_data = ONE_LINE_DATA;
940 sbw->scrollbar.scroll_mode = SMODE_LINE_DOWN;
941 delay = LINE_DELAY;
942 }
943
944 /*
945 * handle zone "above" the thumb
946 */
947 else if (loc < sbw->scrollbar.topLoc)
948 {
949 call_data = -ONE_PAGE_DATA;
950 sbw->scrollbar.scroll_mode = SMODE_PAGE_UP;
951 delay = PAGE_DELAY;
952 }
953
954 /*
955 * handle zone "below" the thumb
956 */
957 else if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength)
958 {
959 call_data = ONE_PAGE_DATA;
960 sbw->scrollbar.scroll_mode = SMODE_PAGE_DOWN;
961 delay = PAGE_DELAY;
962 }
963
964 if (call_data)
Bram Moolenaar9d6650f2010-06-06 23:04:47 +0200965 XtCallCallbacks(w, XtNscrollProc, (XtPointer)(long_u)call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966
967 /* establish autoscroll */
968 if (delay)
969 sbw->scrollbar.timer_id =
970 XtAppAddTimeOut(XtWidgetToApplicationContext(w),
971 delay, RepeatNotify, (XtPointer)w);
972}
973
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100975EndScroll(
976 Widget w,
977 XEvent *event UNUSED,
978 String *params UNUSED,
979 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000980{
981 ScrollbarWidget sbw = (ScrollbarWidget) w;
982
983 sbw->scrollbar.scroll_mode = SMODE_NONE;
984 /* no need to remove any autoscroll timeout; it will no-op */
985 /* because the scroll_mode is SMODE_NONE */
986 /* but be sure to remove timeout in destroy proc */
987}
988
989 static float
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100990FractionLoc(ScrollbarWidget sbw, int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000991{
992 int margin;
993 float height, width;
994
995 margin = MARGIN(sbw);
996 x -= margin;
997 y -= margin;
998 height = (float)sbw->core.height - 2 * margin;
999 width = (float)sbw->core.width - 2 * margin;
1000 return PICKLENGTH(sbw, x / width, y / height);
1001}
1002
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001004MoveThumb(
1005 Widget w,
1006 XEvent *event,
1007 String *params UNUSED,
1008 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009{
1010 ScrollbarWidget sbw = (ScrollbarWidget)w;
1011 Position x, y;
1012 float top;
1013 char old_mode = sbw->scrollbar.scroll_mode;
1014
1015 sbw->scrollbar.scroll_mode = SMODE_CONT; /* indicate continuous scroll */
1016
1017 if (LookAhead(w, event))
1018 return;
1019
1020 if (!event->xmotion.same_screen)
1021 return;
1022
1023 ExtractPosition(event, &x, &y, (unsigned int *)NULL);
1024
1025 top = FractionLoc(sbw, x, y);
1026
1027 if (old_mode != SMODE_CONT) /* start dragging: set offset */
1028 {
1029 if (event->xbutton.button == Button2)
1030 sbw->scrollbar.scroll_off = sbw->scrollbar.shown / 2.;
1031 else
1032 sbw->scrollbar.scroll_off = top - sbw->scrollbar.top;
1033 }
1034
1035 top -= sbw->scrollbar.scroll_off;
1036 if (sbw->scrollbar.limit_thumb)
1037 top = FloatInRange(top, 0.0,
1038 sbw->scrollbar.max - sbw->scrollbar.shown + 0.000001);
1039 else
1040 top = FloatInRange(top, 0.0, sbw->scrollbar.max);
1041
1042 sbw->scrollbar.top = top;
1043 PaintThumb(sbw);
1044 XFlush(XtDisplay(w)); /* re-draw it before Notifying */
1045}
1046
1047
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001049NotifyThumb(
1050 Widget w,
1051 XEvent *event,
1052 String *params UNUSED,
1053 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001054{
1055 ScrollbarWidget sbw = (ScrollbarWidget)w;
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00001056 /* Use a union to avoid a warning for the weird conversion from float to
1057 * XtPointer. Comes from Xaw/Scrollbar.c. */
1058 union {
1059 XtPointer xtp;
1060 float xtf;
1061 } xtpf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062
1063 if (LookAhead(w, event))
1064 return;
1065
1066 /* thumbProc is not pretty, but is necessary for backwards
1067 compatibility on those architectures for which it work{s,ed};
1068 the intent is to pass a (truncated) float by value. */
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00001069 xtpf.xtf = sbw->scrollbar.top;
1070 XtCallCallbacks(w, XtNthumbProc, xtpf.xtp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001071 XtCallCallbacks(w, XtNjumpProc, (XtPointer)&sbw->scrollbar.top);
1072}
1073
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001075AllocTopShadowGC(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001076{
1077 ScrollbarWidget sbw = (ScrollbarWidget) w;
1078 XtGCMask valuemask;
1079 XGCValues myXGCV;
1080
1081 valuemask = GCForeground;
1082 myXGCV.foreground = sbw->scrollbar.top_shadow_pixel;
1083 sbw->scrollbar.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
1084}
1085
Bram Moolenaar071d4272004-06-13 20:20:40 +00001086 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001087AllocBotShadowGC(Widget w)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001088{
1089 ScrollbarWidget sbw = (ScrollbarWidget) w;
1090 XtGCMask valuemask;
1091 XGCValues myXGCV;
1092
1093 valuemask = GCForeground;
1094 myXGCV.foreground = sbw->scrollbar.bot_shadow_pixel;
1095 sbw->scrollbar.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
1096}
1097
Bram Moolenaar071d4272004-06-13 20:20:40 +00001098 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001099_Xaw3dDrawShadows(
1100 Widget gw,
1101 XEvent *event UNUSED,
1102 Region region,
1103 int out)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001104{
1105 XPoint pt[6];
1106 ScrollbarWidget sbw = (ScrollbarWidget) gw;
1107 Dimension s = sbw->scrollbar.shadow_width;
1108 /*
1109 * draw the shadows using the core part width and height,
1110 * and the scrollbar part shadow_width.
1111 *
1112 * no point to do anything if the shadow_width is 0 or the
1113 * widget has not been realized.
1114 */
1115 if (s > 0 && XtIsRealized(gw))
1116 {
1117 Dimension h = sbw->core.height;
1118 Dimension w = sbw->core.width;
1119 Dimension wms = w - s;
1120 Dimension hms = h - s;
1121 Display *dpy = XtDisplay (gw);
1122 Window win = XtWindow (gw);
1123 GC top, bot;
1124
1125 if (out)
1126 {
1127 top = sbw->scrollbar.top_shadow_GC;
1128 bot = sbw->scrollbar.bot_shadow_GC;
1129 }
1130 else
1131 {
1132 top = sbw->scrollbar.bot_shadow_GC;
1133 bot = sbw->scrollbar.top_shadow_GC;
1134 }
1135
1136 /* top-left shadow */
1137 if ((region == NULL) ||
1138 (XRectInRegion (region, 0, 0, w, s) != RectangleOut) ||
1139 (XRectInRegion (region, 0, 0, s, h) != RectangleOut))
1140 {
1141 pt[0].x = 0; pt[0].y = h;
1142 pt[1].x = pt[1].y = 0;
1143 pt[2].x = w; pt[2].y = 0;
1144 pt[3].x = wms; pt[3].y = s;
1145 pt[4].x = pt[4].y = s;
1146 pt[5].x = s; pt[5].y = hms;
1147 XFillPolygon (dpy, win, top, pt, 6, Complex, CoordModeOrigin);
1148 }
1149
1150 /* bottom-right shadow */
1151 if ((region == NULL) ||
1152 (XRectInRegion (region, 0, hms, w, s) != RectangleOut) ||
1153 (XRectInRegion (region, wms, 0, s, h) != RectangleOut))
1154 {
1155 pt[0].x = 0; pt[0].y = h;
1156 pt[1].x = w; pt[1].y = h;
1157 pt[2].x = w; pt[2].y = 0;
1158 pt[3].x = wms; pt[3].y = s;
1159 pt[4].x = wms; pt[4].y = hms;
1160 pt[5].x = s; pt[5].y = hms;
1161 XFillPolygon (dpy, win, bot, pt, 6, Complex, CoordModeOrigin);
1162 }
1163 }
1164}
1165
1166
1167/*
1168 * Set the scroll bar to the given location.
1169 */
1170 void
Bram Moolenaar02fdaea2016-01-30 18:13:55 +01001171vim_XawScrollbarSetThumb(Widget w, double top, double shown, double max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172{
1173 ScrollbarWidget sbw = (ScrollbarWidget) w;
1174
1175 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if still thumbing */
1176 return;
1177
1178 sbw->scrollbar.max = (max > 1.0) ? 1.0 :
1179 (max >= 0.0) ? max : sbw->scrollbar.max;
1180
1181 sbw->scrollbar.top = (top > sbw->scrollbar.max) ? sbw->scrollbar.max :
1182 (top >= 0.0) ? top : sbw->scrollbar.top;
1183
1184 sbw->scrollbar.shown = (shown > 1.0) ? 1.0 :
1185 (shown >= 0.0) ? shown : sbw->scrollbar.shown;
1186
1187 PaintThumb(sbw);
1188}