Mercurial > vim
comparison src/gui_at_sb.c @ 7:3fc0f57ecb91 v7.0001
updated for version 7.0001
author | vimboss |
---|---|
date | Sun, 13 Jun 2004 20:20:40 +0000 |
parents | |
children | f10fe14748e2 |
comparison
equal
deleted
inserted
replaced
6:c2daee826b8f | 7:3fc0f57ecb91 |
---|---|
1 /* 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 | |
16 Copyright (c) 1987, 1988, 1994 X Consortium | |
17 | |
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: | |
24 | |
25 The above copyright notice and this permission notice shall be included in all | |
26 copies or substantial portions of the Software. | |
27 | |
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. | |
34 | |
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. | |
38 | |
39 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. | |
40 | |
41 All Rights Reserved | |
42 | |
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. | |
49 | |
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. | |
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 | |
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()"; | |
86 | |
87 static float floatZero = 0.0; | |
88 | |
89 #define Offset(field) XtOffsetOf(ScrollbarRec, field) | |
90 | |
91 static 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 | |
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 *)); | |
135 | |
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)); | |
149 | |
150 static 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 | |
164 ScrollbarClassRec 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 */ | |
201 /* change_sensitive */ XtInheritChangeSensitive | |
202 }, | |
203 { /* scrollbar fields */ | |
204 /* ignore */ 0 | |
205 } | |
206 }; | |
207 | |
208 WidgetClass vim_scrollbarWidgetClass = (WidgetClass)&vim_scrollbarClassRec; | |
209 | |
210 #define NoButton -1 | |
211 #define PICKLENGTH(widget, x, y) \ | |
212 ((widget->scrollbar.orientation == XtorientHorizontal) ? (x) : (y)) | |
213 #define AT_MIN(x,y) ((x) < (y) ? (x) : (y)) | |
214 #define AT_MAX(x,y) ((x) > (y) ? (x) : (y)) | |
215 | |
216 #define LINE_DELAY 300 | |
217 #define PAGE_DELAY 300 | |
218 #define LINE_REPEAT 50 | |
219 #define PAGE_REPEAT 250 | |
220 | |
221 static void | |
222 ClassInitialize() | |
223 { | |
224 XawInitializeWidgetSet(); | |
225 XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation, | |
226 (XtConvertArgList)NULL, (Cardinal)0 ); | |
227 } | |
228 | |
229 #define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->scrollbar.shadow_width | |
230 | |
231 static void | |
232 FillArea(sbw, top, bottom, fill, draw_shadow) | |
233 ScrollbarWidget sbw; | |
234 Position top, bottom; | |
235 int fill; | |
236 int draw_shadow; | |
237 { | |
238 int tlen = bottom - top; /* length of thumb in pixels */ | |
239 int sw, margin, floor; | |
240 int lx, ly, lw, lh; | |
241 | |
242 if (bottom <= 0 || bottom <= top) | |
243 return; | |
244 if ((sw = sbw->scrollbar.shadow_width) < 0) | |
245 sw = 0; | |
246 margin = MARGIN (sbw); | |
247 floor = sbw->scrollbar.length - margin + 2; | |
248 | |
249 if (sbw->scrollbar.orientation == XtorientHorizontal) | |
250 { | |
251 lx = ((top < margin) ? margin : top); | |
252 ly = sw; | |
253 lw = (((top + tlen) > floor) ? floor - top : tlen); | |
254 lh = sbw->core.height - 2 * sw; | |
255 } | |
256 else | |
257 { | |
258 lx = sw; | |
259 ly = ((top < margin) ? margin : top); | |
260 lw = sbw->core.width - 2 * sw; | |
261 lh = (((top + tlen) > floor) ? floor - top : tlen); | |
262 } | |
263 if (lh <= 0 || lw <= 0) | |
264 return; | |
265 | |
266 if (draw_shadow) | |
267 { | |
268 if (!(sbw->scrollbar.orientation == XtorientHorizontal)) | |
269 { | |
270 /* Top border */ | |
271 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
272 sbw->scrollbar.top_shadow_GC, | |
273 lx, ly, lx + lw - 1, ly); | |
274 | |
275 /* Bottom border */ | |
276 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
277 sbw->scrollbar.bot_shadow_GC, | |
278 lx, ly + lh - 1, lx + lw - 1, ly + lh - 1); | |
279 } | |
280 else | |
281 { | |
282 /* Left border */ | |
283 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
284 sbw->scrollbar.top_shadow_GC, | |
285 lx, ly, lx, ly + lh - 1); | |
286 | |
287 /* Right border */ | |
288 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
289 sbw->scrollbar.bot_shadow_GC, | |
290 lx + lw - 1, ly, lx + lw - 1, ly + lh - 1); | |
291 } | |
292 return; | |
293 } | |
294 | |
295 if (fill) | |
296 { | |
297 XFillRectangle(XtDisplay((Widget) sbw), XtWindow((Widget) sbw), | |
298 sbw->scrollbar.gc, | |
299 lx, ly, (unsigned int) lw, (unsigned int) lh); | |
300 | |
301 if (!(sbw->scrollbar.orientation == XtorientHorizontal)) | |
302 { | |
303 /* Left border */ | |
304 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
305 sbw->scrollbar.top_shadow_GC, | |
306 lx, ly, lx, ly + lh - 1); | |
307 | |
308 /* Right border */ | |
309 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
310 sbw->scrollbar.bot_shadow_GC, | |
311 lx + lw - 1, ly, lx + lw - 1, ly + lh - 1); | |
312 } | |
313 else | |
314 { | |
315 /* Top border */ | |
316 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
317 sbw->scrollbar.top_shadow_GC, | |
318 lx, ly, lx + lw - 1, ly); | |
319 | |
320 /* Bottom border */ | |
321 XDrawLine(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
322 sbw->scrollbar.bot_shadow_GC, | |
323 lx, ly + lh - 1, lx + lw - 1, ly + lh - 1); | |
324 } | |
325 } | |
326 else | |
327 { | |
328 XClearArea(XtDisplay((Widget) sbw), XtWindow((Widget) sbw), | |
329 lx, ly, (unsigned int) lw, (unsigned int) lh, FALSE); | |
330 } | |
331 } | |
332 | |
333 /* Paint the thumb in the area specified by sbw->top and | |
334 sbw->shown. The old area is erased. The painting and | |
335 erasing is done cleverly so that no flickering will occur. | |
336 */ | |
337 | |
338 static void | |
339 PaintThumb(sbw) | |
340 ScrollbarWidget sbw; | |
341 { | |
342 Position oldtop, oldbot, newtop, newbot; | |
343 Dimension margin, tzl; | |
344 | |
345 margin = MARGIN (sbw); | |
346 tzl = sbw->scrollbar.length - 2 * margin; | |
347 newtop = margin + (int)(tzl * sbw->scrollbar.top); | |
348 newbot = newtop + (int)(tzl * sbw->scrollbar.shown) + 1; | |
349 if (newbot < newtop + (int)sbw->scrollbar.min_thumb) | |
350 newbot = newtop + sbw->scrollbar.min_thumb; | |
351 | |
352 oldtop = sbw->scrollbar.topLoc; | |
353 oldbot = oldtop + sbw->scrollbar.shownLength; | |
354 sbw->scrollbar.topLoc = newtop; | |
355 sbw->scrollbar.shownLength = newbot - newtop; | |
356 if (XtIsRealized ((Widget) sbw)) | |
357 { | |
358 if (newtop < oldtop) | |
359 FillArea(sbw, newtop, AT_MIN(newbot, oldtop+1),1,0); | |
360 if (newtop > oldtop) | |
361 FillArea(sbw, oldtop, AT_MIN(newtop, oldbot ),0,0); | |
362 if (newbot < oldbot) | |
363 FillArea(sbw, AT_MAX(newbot, oldtop), oldbot, 0,0); | |
364 if (newbot > oldbot) | |
365 FillArea(sbw, AT_MAX(newtop, oldbot-1), newbot, 1,0); | |
366 | |
367 /* Only draw the missing shadows */ | |
368 FillArea(sbw, newtop, newbot, 0, 1); | |
369 } | |
370 } | |
371 | |
372 static void | |
373 PaintArrows(sbw) | |
374 ScrollbarWidget sbw; | |
375 { | |
376 XPoint point[6]; | |
377 Dimension thickness = sbw->scrollbar.thickness - 1; | |
378 Dimension size; | |
379 Dimension off; | |
380 | |
381 if (XtIsRealized((Widget) sbw)) | |
382 { | |
383 if ((int)thickness * 2 > (int)sbw->scrollbar.length) | |
384 { | |
385 size = sbw->scrollbar.length / 2; | |
386 off = (int)(thickness - size) / 2; | |
387 } | |
388 else | |
389 { | |
390 size = thickness; | |
391 off = 0; | |
392 } | |
393 point[0].x = off + sbw->scrollbar.shadow_width; | |
394 point[0].y = size; | |
395 point[1].x = thickness - off - sbw->scrollbar.shadow_width; | |
396 point[1].y = size; | |
397 point[2].x = thickness / 2; | |
398 point[2].y = sbw->scrollbar.shadow_width; | |
399 | |
400 point[3].x = off + sbw->scrollbar.shadow_width; | |
401 point[3].y = sbw->scrollbar.length - size; | |
402 point[4].x = thickness - off - sbw->scrollbar.shadow_width; | |
403 point[4].y = sbw->scrollbar.length - size; | |
404 point[5].x = thickness / 2; | |
405 point[5].y = sbw->scrollbar.length - sbw->scrollbar.shadow_width - 1; | |
406 | |
407 /* horizontal arrows require that x and y coordinates be swapped */ | |
408 if (sbw->scrollbar.orientation == XtorientHorizontal) | |
409 { | |
410 int n; | |
411 int swap; | |
412 for (n = 0; n < 6; n++) | |
413 { | |
414 swap = point[n].x; | |
415 point[n].x = point[n].y; | |
416 point[n].y = swap; | |
417 } | |
418 } | |
419 /* draw the up/left arrow */ | |
420 XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
421 sbw->scrollbar.gc, | |
422 point, 3, | |
423 Convex, CoordModeOrigin); | |
424 XDrawLines (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
425 sbw->scrollbar.bot_shadow_GC, | |
426 point, 3, | |
427 CoordModeOrigin); | |
428 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
429 sbw->scrollbar.top_shadow_GC, | |
430 point[0].x, point[0].y, | |
431 point[2].x, point[2].y); | |
432 /* draw the down/right arrow */ | |
433 XFillPolygon (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
434 sbw->scrollbar.gc, | |
435 point+3, 3, | |
436 Convex, CoordModeOrigin); | |
437 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
438 sbw->scrollbar.top_shadow_GC, | |
439 point[3].x, point[3].y, | |
440 point[4].x, point[4].y); | |
441 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
442 sbw->scrollbar.top_shadow_GC, | |
443 point[3].x, point[3].y, | |
444 point[5].x, point[5].y); | |
445 XDrawLine (XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw), | |
446 sbw->scrollbar.bot_shadow_GC, | |
447 point[4].x, point[4].y, | |
448 point[5].x, point[5].y); | |
449 } | |
450 } | |
451 | |
452 static void | |
453 Destroy(w) | |
454 Widget w; | |
455 { | |
456 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
457 if (sbw->scrollbar.timer_id != (XtIntervalId) 0) | |
458 XtRemoveTimeOut (sbw->scrollbar.timer_id); | |
459 XtReleaseGC(w, sbw->scrollbar.gc); | |
460 XtReleaseGC(w, sbw->scrollbar.top_shadow_GC); | |
461 XtReleaseGC(w, sbw->scrollbar.bot_shadow_GC); | |
462 } | |
463 | |
464 static void | |
465 CreateGC(w) | |
466 Widget w; | |
467 { | |
468 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
469 XGCValues gcValues; | |
470 XtGCMask mask; | |
471 unsigned int depth = 1; | |
472 | |
473 if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) | |
474 { | |
475 sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w), | |
476 (Pixel) 1, (Pixel) 0, depth); | |
477 } | |
478 else if (sbw->scrollbar.thumb != None) | |
479 { | |
480 Window root; | |
481 int x, y; | |
482 unsigned int width, height, bw; | |
483 | |
484 if (XGetGeometry (XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y, | |
485 &width, &height, &bw, &depth) == 0) | |
486 EMSG(_("Scrollbar Widget: Could not get geometry of thumb pixmap.")); | |
487 } | |
488 | |
489 gcValues.foreground = sbw->scrollbar.foreground; | |
490 gcValues.background = sbw->core.background_pixel; | |
491 mask = GCForeground | GCBackground; | |
492 | |
493 if (sbw->scrollbar.thumb != None) | |
494 { | |
495 gcValues.fill_style = FillSolid; | |
496 mask |= GCFillStyle; | |
497 } | |
498 /* the creation should be non-caching, because */ | |
499 /* we now set and clear clip masks on the gc returned */ | |
500 sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues); | |
501 } | |
502 | |
503 static void | |
504 SetDimensions(sbw) | |
505 ScrollbarWidget sbw; | |
506 { | |
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 | |
519 /* ARGSUSED */ | |
520 static void | |
521 Initialize(request, new, args, num_args) | |
522 Widget request; /* what the client asked for */ | |
523 Widget new; /* what we're going to give him */ | |
524 ArgList args; | |
525 Cardinal *num_args; | |
526 { | |
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 | |
549 Realize(w, valueMask, attributes) | |
550 Widget w; | |
551 Mask *valueMask; | |
552 XSetWindowAttributes *attributes; | |
553 { | |
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 | |
559 /* ARGSUSED */ | |
560 static Boolean | |
561 SetValues(current, request, desired, args, num_args) | |
562 Widget current, /* what I am */ | |
563 request, /* what he wants me to be */ | |
564 desired; /* what I will become */ | |
565 ArgList args; | |
566 Cardinal *num_args; | |
567 { | |
568 ScrollbarWidget sbw = (ScrollbarWidget) current; | |
569 ScrollbarWidget dsbw = (ScrollbarWidget) desired; | |
570 Boolean redraw = FALSE; | |
571 | |
572 /* | |
573 * If these values are outside the acceptable range ignore them... | |
574 */ | |
575 if (dsbw->scrollbar.top < 0.0 || dsbw->scrollbar.top > 1.0) | |
576 dsbw->scrollbar.top = sbw->scrollbar.top; | |
577 | |
578 if (dsbw->scrollbar.shown < 0.0 || dsbw->scrollbar.shown > 1.0) | |
579 dsbw->scrollbar.shown = sbw->scrollbar.shown; | |
580 | |
581 /* | |
582 * Change colors and stuff... | |
583 */ | |
584 if (XtIsRealized(desired)) | |
585 { | |
586 if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground || | |
587 sbw->core.background_pixel != dsbw->core.background_pixel || | |
588 sbw->scrollbar.thumb != dsbw->scrollbar.thumb) | |
589 { | |
590 XtReleaseGC(desired, sbw->scrollbar.gc); | |
591 CreateGC (desired); | |
592 redraw = TRUE; | |
593 } | |
594 if (sbw->scrollbar.top != dsbw->scrollbar.top || | |
595 sbw->scrollbar.shown != dsbw->scrollbar.shown) | |
596 redraw = TRUE; | |
597 } | |
598 return redraw; | |
599 } | |
600 | |
601 static void | |
602 Resize(w) | |
603 Widget w; | |
604 { | |
605 /* ForgetGravity has taken care of background, but thumb may | |
606 * have to move as a result of the new size. */ | |
607 SetDimensions ((ScrollbarWidget) w); | |
608 Redisplay(w, (XEvent*) NULL, (Region)NULL); | |
609 } | |
610 | |
611 | |
612 /* ARGSUSED */ | |
613 static void | |
614 Redisplay(w, event, region) | |
615 Widget w; | |
616 XEvent *event; | |
617 Region region; | |
618 { | |
619 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
620 int x, y; | |
621 unsigned int width, height; | |
622 | |
623 _Xaw3dDrawShadows(w, event, region, FALSE); | |
624 | |
625 if (sbw->scrollbar.orientation == XtorientHorizontal) | |
626 { | |
627 x = sbw->scrollbar.topLoc; | |
628 y = 1; | |
629 width = sbw->scrollbar.shownLength; | |
630 height = sbw->core.height - 2; | |
631 } | |
632 else | |
633 { | |
634 x = 1; | |
635 y = sbw->scrollbar.topLoc; | |
636 width = sbw->core.width - 2; | |
637 height = sbw->scrollbar.shownLength; | |
638 } | |
639 if (region == NULL || | |
640 XRectInRegion (region, x, y, width, height) != RectangleOut) | |
641 { | |
642 /* Forces entire thumb to be painted. */ | |
643 sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1); | |
644 PaintThumb (sbw); | |
645 } | |
646 /* we'd like to be region aware here!!!! */ | |
647 PaintArrows(sbw); | |
648 } | |
649 | |
650 | |
651 static Boolean | |
652 CompareEvents(oldEvent, newEvent) | |
653 XEvent *oldEvent, *newEvent; | |
654 { | |
655 #define Check(field) if (newEvent->field != oldEvent->field) return False; | |
656 | |
657 Check(xany.display); | |
658 Check(xany.type); | |
659 Check(xany.window); | |
660 | |
661 switch (newEvent->type) | |
662 { | |
663 case MotionNotify: | |
664 Check(xmotion.state); | |
665 break; | |
666 case ButtonPress: | |
667 case ButtonRelease: | |
668 Check(xbutton.state); | |
669 Check(xbutton.button); | |
670 break; | |
671 case KeyPress: | |
672 case KeyRelease: | |
673 Check(xkey.state); | |
674 Check(xkey.keycode); | |
675 break; | |
676 case EnterNotify: | |
677 case LeaveNotify: | |
678 Check(xcrossing.mode); | |
679 Check(xcrossing.detail); | |
680 Check(xcrossing.state); | |
681 break; | |
682 } | |
683 #undef Check | |
684 | |
685 return True; | |
686 } | |
687 | |
688 struct EventData | |
689 { | |
690 XEvent *oldEvent; | |
691 int count; | |
692 }; | |
693 | |
694 static Bool | |
695 PeekNotifyEvent(dpy, event, args) | |
696 Display *dpy; | |
697 XEvent *event; | |
698 char *args; | |
699 { | |
700 struct EventData *eventData = (struct EventData*)args; | |
701 | |
702 return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */ | |
703 || CompareEvents(event, eventData->oldEvent)); | |
704 } | |
705 | |
706 | |
707 static Boolean | |
708 LookAhead(w, event) | |
709 Widget w; | |
710 XEvent *event; | |
711 { | |
712 XEvent newEvent; | |
713 struct EventData eventData; | |
714 | |
715 if (QLength (XtDisplay (w)) == 0) | |
716 return False; | |
717 | |
718 eventData.count = 0; | |
719 eventData.oldEvent = event; | |
720 | |
721 XPeekIfEvent (XtDisplay (w), &newEvent, PeekNotifyEvent, (char*)&eventData); | |
722 | |
723 return CompareEvents (event, &newEvent); | |
724 } | |
725 | |
726 | |
727 static void | |
728 ExtractPosition(event, x, y, state) | |
729 XEvent *event; | |
730 Position *x, *y; /* RETURN */ | |
731 unsigned int *state; /* RETURN */ | |
732 { | |
733 switch (event->type) | |
734 { | |
735 case MotionNotify: | |
736 *x = event->xmotion.x; | |
737 *y = event->xmotion.y; | |
738 if (state != NULL) | |
739 *state = event->xmotion.state; | |
740 break; | |
741 case ButtonPress: | |
742 case ButtonRelease: | |
743 *x = event->xbutton.x; | |
744 *y = event->xbutton.y; | |
745 if (state != NULL) | |
746 *state = event->xbutton.state; | |
747 break; | |
748 case KeyPress: | |
749 case KeyRelease: | |
750 *x = event->xkey.x; | |
751 *y = event->xkey.y; | |
752 if (state != NULL) | |
753 *state = event->xkey.state; | |
754 break; | |
755 case EnterNotify: | |
756 case LeaveNotify: | |
757 *x = event->xcrossing.x; | |
758 *y = event->xcrossing.y; | |
759 if (state != NULL) | |
760 *state = event->xcrossing.state; | |
761 break; | |
762 default: | |
763 *x = 0; *y = 0; | |
764 if (state != NULL) | |
765 *state = 0; | |
766 } | |
767 } | |
768 | |
769 static void | |
770 HandleThumb(w, event, params, num_params) | |
771 Widget w; | |
772 XEvent *event; | |
773 String *params; | |
774 Cardinal *num_params; | |
775 { | |
776 Position x, y, loc; | |
777 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
778 | |
779 ExtractPosition(event, &x, &y, (unsigned int *)NULL); | |
780 loc = PICKLENGTH(sbw, x, y); | |
781 /* if the motion event puts the pointer in thumb, call Move and Notify */ | |
782 /* also call Move and Notify if we're already in continuous scroll mode */ | |
783 if (sbw->scrollbar.scroll_mode == SMODE_CONT || | |
784 (loc >= sbw->scrollbar.topLoc && | |
785 loc <= sbw->scrollbar.topLoc + (int)sbw->scrollbar.shownLength)) | |
786 { | |
787 XtCallActionProc(w, "MoveThumb", event, params, *num_params); | |
788 XtCallActionProc(w, "NotifyThumb", event, params, *num_params); | |
789 } | |
790 } | |
791 | |
792 /* ARGSUSED */ | |
793 static void | |
794 RepeatNotify(client_data, idp) | |
795 XtPointer client_data; | |
796 XtIntervalId *idp; | |
797 { | |
798 ScrollbarWidget sbw = (ScrollbarWidget) client_data; | |
799 int call_data; | |
800 char mode = sbw->scrollbar.scroll_mode; | |
801 unsigned long rep; | |
802 | |
803 if (mode == SMODE_NONE || mode == SMODE_CONT) | |
804 { | |
805 sbw->scrollbar.timer_id = (XtIntervalId)0; | |
806 return; | |
807 } | |
808 | |
809 if (mode == SMODE_LINE_DOWN || mode == SMODE_LINE_UP) | |
810 { | |
811 call_data = ONE_LINE_DATA; | |
812 rep = LINE_REPEAT; | |
813 } | |
814 else | |
815 { | |
816 call_data = ONE_PAGE_DATA; | |
817 rep = PAGE_REPEAT; | |
818 } | |
819 | |
820 if (mode == SMODE_PAGE_UP || mode == SMODE_LINE_UP) | |
821 call_data = -call_data; | |
822 | |
823 XtCallCallbacks((Widget)sbw, XtNscrollProc, (XtPointer)call_data); | |
824 | |
825 sbw->scrollbar.timer_id = | |
826 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)sbw), | |
827 rep, | |
828 RepeatNotify, | |
829 client_data); | |
830 } | |
831 | |
832 /* | |
833 * Same as above, but for floating numbers. | |
834 */ | |
835 static float | |
836 FloatInRange(num, small, big) | |
837 float num, small, big; | |
838 { | |
839 return (num < small) ? small : ((num > big) ? big : num); | |
840 } | |
841 | |
842 /* ARGSUSED */ | |
843 static void | |
844 ScrollOneLineUp(w, event, params, num_params) | |
845 Widget w; | |
846 XEvent *event; | |
847 String *params; | |
848 Cardinal *num_params; | |
849 { | |
850 ScrollSome(w, event, -ONE_LINE_DATA); | |
851 } | |
852 | |
853 /* ARGSUSED */ | |
854 static void | |
855 ScrollOneLineDown(w, event, params, num_params) | |
856 Widget w; | |
857 XEvent *event; | |
858 String *params; | |
859 Cardinal *num_params; | |
860 { | |
861 ScrollSome(w, event, ONE_LINE_DATA); | |
862 } | |
863 | |
864 /* ARGSUSED */ | |
865 static void | |
866 ScrollPageDown(w, event, params, num_params) | |
867 Widget w; | |
868 XEvent *event; | |
869 String *params; | |
870 Cardinal *num_params; | |
871 { | |
872 ScrollSome(w, event, ONE_PAGE_DATA); | |
873 } | |
874 | |
875 /* ARGSUSED */ | |
876 static void | |
877 ScrollPageUp(w, event, params, num_params) | |
878 Widget w; | |
879 XEvent *event; | |
880 String *params; | |
881 Cardinal *num_params; | |
882 { | |
883 ScrollSome(w, event, -ONE_PAGE_DATA); | |
884 } | |
885 | |
886 static void | |
887 ScrollSome(w, event, call_data) | |
888 Widget w; | |
889 XEvent *event; | |
890 int call_data; | |
891 { | |
892 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
893 | |
894 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */ | |
895 return; | |
896 | |
897 if (LookAhead(w, event)) | |
898 return; | |
899 | |
900 sbw->scrollbar.scroll_mode = SMODE_LINE_UP; | |
901 XtCallCallbacks(w, XtNscrollProc, (XtPointer)call_data); | |
902 } | |
903 | |
904 /* ARGSUSED */ | |
905 static void | |
906 NotifyScroll(w, event, params, num_params) | |
907 Widget w; | |
908 XEvent *event; | |
909 String *params; | |
910 Cardinal *num_params; | |
911 { | |
912 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
913 Position x, y, loc; | |
914 Dimension arrow_size; | |
915 unsigned long delay = 0; | |
916 int call_data = 0; | |
917 unsigned int state; | |
918 | |
919 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if scroll continuous */ | |
920 return; | |
921 | |
922 if (LookAhead (w, event)) | |
923 return; | |
924 | |
925 ExtractPosition(event, &x, &y, &state); | |
926 loc = PICKLENGTH(sbw, x, y); | |
927 | |
928 if ((int)sbw->scrollbar.thickness * 2 > (int)sbw->scrollbar.length) | |
929 arrow_size = sbw->scrollbar.length / 2; | |
930 else | |
931 arrow_size = sbw->scrollbar.thickness; | |
932 | |
933 /* | |
934 * handle CTRL modifier | |
935 */ | |
936 if (state & ControlMask) | |
937 { | |
938 if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength) | |
939 call_data = END_PAGE_DATA; | |
940 else | |
941 call_data = -END_PAGE_DATA; | |
942 sbw->scrollbar.scroll_mode = SMODE_NONE; | |
943 } | |
944 /* | |
945 * handle first arrow zone | |
946 */ | |
947 else if (loc < (Position)arrow_size) | |
948 { | |
949 call_data = -ONE_LINE_DATA; | |
950 sbw->scrollbar.scroll_mode = SMODE_LINE_UP; | |
951 delay = LINE_DELAY; | |
952 } | |
953 | |
954 /* | |
955 * handle last arrow zone | |
956 */ | |
957 else if (loc > (Position)(sbw->scrollbar.length - arrow_size)) | |
958 { | |
959 call_data = ONE_LINE_DATA; | |
960 sbw->scrollbar.scroll_mode = SMODE_LINE_DOWN; | |
961 delay = LINE_DELAY; | |
962 } | |
963 | |
964 /* | |
965 * handle zone "above" the thumb | |
966 */ | |
967 else if (loc < sbw->scrollbar.topLoc) | |
968 { | |
969 call_data = -ONE_PAGE_DATA; | |
970 sbw->scrollbar.scroll_mode = SMODE_PAGE_UP; | |
971 delay = PAGE_DELAY; | |
972 } | |
973 | |
974 /* | |
975 * handle zone "below" the thumb | |
976 */ | |
977 else if (loc > sbw->scrollbar.topLoc + (Position)sbw->scrollbar.shownLength) | |
978 { | |
979 call_data = ONE_PAGE_DATA; | |
980 sbw->scrollbar.scroll_mode = SMODE_PAGE_DOWN; | |
981 delay = PAGE_DELAY; | |
982 } | |
983 | |
984 if (call_data) | |
985 XtCallCallbacks(w, XtNscrollProc, (XtPointer)call_data); | |
986 | |
987 /* establish autoscroll */ | |
988 if (delay) | |
989 sbw->scrollbar.timer_id = | |
990 XtAppAddTimeOut(XtWidgetToApplicationContext(w), | |
991 delay, RepeatNotify, (XtPointer)w); | |
992 } | |
993 | |
994 /* ARGSUSED */ | |
995 static void | |
996 EndScroll(w, event, params, num_params) | |
997 Widget w; | |
998 XEvent *event; /* unused */ | |
999 String *params; /* unused */ | |
1000 Cardinal *num_params; /* unused */ | |
1001 { | |
1002 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
1003 | |
1004 sbw->scrollbar.scroll_mode = SMODE_NONE; | |
1005 /* no need to remove any autoscroll timeout; it will no-op */ | |
1006 /* because the scroll_mode is SMODE_NONE */ | |
1007 /* but be sure to remove timeout in destroy proc */ | |
1008 } | |
1009 | |
1010 static float | |
1011 FractionLoc(sbw, x, y) | |
1012 ScrollbarWidget sbw; | |
1013 int x, y; | |
1014 { | |
1015 int margin; | |
1016 float height, width; | |
1017 | |
1018 margin = MARGIN(sbw); | |
1019 x -= margin; | |
1020 y -= margin; | |
1021 height = (float)sbw->core.height - 2 * margin; | |
1022 width = (float)sbw->core.width - 2 * margin; | |
1023 return PICKLENGTH(sbw, x / width, y / height); | |
1024 } | |
1025 | |
1026 /* ARGSUSED */ | |
1027 static void | |
1028 MoveThumb(w, event, params, num_params) | |
1029 Widget w; | |
1030 XEvent *event; | |
1031 String *params; /* unused */ | |
1032 Cardinal *num_params; /* unused */ | |
1033 { | |
1034 ScrollbarWidget sbw = (ScrollbarWidget)w; | |
1035 Position x, y; | |
1036 float top; | |
1037 char old_mode = sbw->scrollbar.scroll_mode; | |
1038 | |
1039 sbw->scrollbar.scroll_mode = SMODE_CONT; /* indicate continuous scroll */ | |
1040 | |
1041 if (LookAhead(w, event)) | |
1042 return; | |
1043 | |
1044 if (!event->xmotion.same_screen) | |
1045 return; | |
1046 | |
1047 ExtractPosition(event, &x, &y, (unsigned int *)NULL); | |
1048 | |
1049 top = FractionLoc(sbw, x, y); | |
1050 | |
1051 if (old_mode != SMODE_CONT) /* start dragging: set offset */ | |
1052 { | |
1053 if (event->xbutton.button == Button2) | |
1054 sbw->scrollbar.scroll_off = sbw->scrollbar.shown / 2.; | |
1055 else | |
1056 sbw->scrollbar.scroll_off = top - sbw->scrollbar.top; | |
1057 } | |
1058 | |
1059 top -= sbw->scrollbar.scroll_off; | |
1060 if (sbw->scrollbar.limit_thumb) | |
1061 top = FloatInRange(top, 0.0, | |
1062 sbw->scrollbar.max - sbw->scrollbar.shown + 0.000001); | |
1063 else | |
1064 top = FloatInRange(top, 0.0, sbw->scrollbar.max); | |
1065 | |
1066 sbw->scrollbar.top = top; | |
1067 PaintThumb(sbw); | |
1068 XFlush(XtDisplay(w)); /* re-draw it before Notifying */ | |
1069 } | |
1070 | |
1071 | |
1072 /* ARGSUSED */ | |
1073 static void | |
1074 NotifyThumb(w, event, params, num_params) | |
1075 Widget w; | |
1076 XEvent *event; | |
1077 String *params; /* unused */ | |
1078 Cardinal *num_params; /* unused */ | |
1079 { | |
1080 ScrollbarWidget sbw = (ScrollbarWidget)w; | |
1081 | |
1082 if (LookAhead(w, event)) | |
1083 return; | |
1084 | |
1085 /* thumbProc is not pretty, but is necessary for backwards | |
1086 compatibility on those architectures for which it work{s,ed}; | |
1087 the intent is to pass a (truncated) float by value. */ | |
1088 XtCallCallbacks(w, XtNthumbProc, *(XtPointer*)&sbw->scrollbar.top); | |
1089 XtCallCallbacks(w, XtNjumpProc, (XtPointer)&sbw->scrollbar.top); | |
1090 } | |
1091 | |
1092 /* ARGSUSED */ | |
1093 static void | |
1094 AllocTopShadowGC(w) | |
1095 Widget w; | |
1096 { | |
1097 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
1098 XtGCMask valuemask; | |
1099 XGCValues myXGCV; | |
1100 | |
1101 valuemask = GCForeground; | |
1102 myXGCV.foreground = sbw->scrollbar.top_shadow_pixel; | |
1103 sbw->scrollbar.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV); | |
1104 } | |
1105 | |
1106 /* ARGSUSED */ | |
1107 static void | |
1108 AllocBotShadowGC(w) | |
1109 Widget w; | |
1110 { | |
1111 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
1112 XtGCMask valuemask; | |
1113 XGCValues myXGCV; | |
1114 | |
1115 valuemask = GCForeground; | |
1116 myXGCV.foreground = sbw->scrollbar.bot_shadow_pixel; | |
1117 sbw->scrollbar.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV); | |
1118 } | |
1119 | |
1120 /* ARGSUSED */ | |
1121 static void | |
1122 _Xaw3dDrawShadows(gw, event, region, out) | |
1123 Widget gw; | |
1124 XEvent *event; | |
1125 Region region; | |
1126 int out; | |
1127 { | |
1128 XPoint pt[6]; | |
1129 ScrollbarWidget sbw = (ScrollbarWidget) gw; | |
1130 Dimension s = sbw->scrollbar.shadow_width; | |
1131 /* | |
1132 * draw the shadows using the core part width and height, | |
1133 * and the scrollbar part shadow_width. | |
1134 * | |
1135 * no point to do anything if the shadow_width is 0 or the | |
1136 * widget has not been realized. | |
1137 */ | |
1138 if (s > 0 && XtIsRealized(gw)) | |
1139 { | |
1140 Dimension h = sbw->core.height; | |
1141 Dimension w = sbw->core.width; | |
1142 Dimension wms = w - s; | |
1143 Dimension hms = h - s; | |
1144 Display *dpy = XtDisplay (gw); | |
1145 Window win = XtWindow (gw); | |
1146 GC top, bot; | |
1147 | |
1148 if (out) | |
1149 { | |
1150 top = sbw->scrollbar.top_shadow_GC; | |
1151 bot = sbw->scrollbar.bot_shadow_GC; | |
1152 } | |
1153 else | |
1154 { | |
1155 top = sbw->scrollbar.bot_shadow_GC; | |
1156 bot = sbw->scrollbar.top_shadow_GC; | |
1157 } | |
1158 | |
1159 /* top-left shadow */ | |
1160 if ((region == NULL) || | |
1161 (XRectInRegion (region, 0, 0, w, s) != RectangleOut) || | |
1162 (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) | |
1163 { | |
1164 pt[0].x = 0; pt[0].y = h; | |
1165 pt[1].x = pt[1].y = 0; | |
1166 pt[2].x = w; pt[2].y = 0; | |
1167 pt[3].x = wms; pt[3].y = s; | |
1168 pt[4].x = pt[4].y = s; | |
1169 pt[5].x = s; pt[5].y = hms; | |
1170 XFillPolygon (dpy, win, top, pt, 6, Complex, CoordModeOrigin); | |
1171 } | |
1172 | |
1173 /* bottom-right shadow */ | |
1174 if ((region == NULL) || | |
1175 (XRectInRegion (region, 0, hms, w, s) != RectangleOut) || | |
1176 (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) | |
1177 { | |
1178 pt[0].x = 0; pt[0].y = h; | |
1179 pt[1].x = w; pt[1].y = h; | |
1180 pt[2].x = w; pt[2].y = 0; | |
1181 pt[3].x = wms; pt[3].y = s; | |
1182 pt[4].x = wms; pt[4].y = hms; | |
1183 pt[5].x = s; pt[5].y = hms; | |
1184 XFillPolygon (dpy, win, bot, pt, 6, Complex, CoordModeOrigin); | |
1185 } | |
1186 } | |
1187 } | |
1188 | |
1189 | |
1190 /* | |
1191 * Set the scroll bar to the given location. | |
1192 */ | |
1193 void | |
1194 vim_XawScrollbarSetThumb(w, top, shown, max) | |
1195 Widget w; | |
1196 double top, shown, max; | |
1197 { | |
1198 ScrollbarWidget sbw = (ScrollbarWidget) w; | |
1199 | |
1200 if (sbw->scrollbar.scroll_mode == SMODE_CONT) /* if still thumbing */ | |
1201 return; | |
1202 | |
1203 sbw->scrollbar.max = (max > 1.0) ? 1.0 : | |
1204 (max >= 0.0) ? max : sbw->scrollbar.max; | |
1205 | |
1206 sbw->scrollbar.top = (top > sbw->scrollbar.max) ? sbw->scrollbar.max : | |
1207 (top >= 0.0) ? top : sbw->scrollbar.top; | |
1208 | |
1209 sbw->scrollbar.shown = (shown > 1.0) ? 1.0 : | |
1210 (shown >= 0.0) ? shown : sbw->scrollbar.shown; | |
1211 | |
1212 PaintThumb(sbw); | |
1213 } |