comparison lwlib/xlwscrollbar.c @ 102:a145efe76779 r20-1b3

Import from CVS: tag r20-1b3
author cvs
date Mon, 13 Aug 2007 09:15:49 +0200
parents 1ce6082ce73f
children 6b37e6ddd302
comparison
equal deleted inserted replaced
101:a0ec055d74dd 102:a145efe76779
1 /* Implements a lightweight scrollbar widget. 1 /* Implements a lightweight scrollbar widget.
2 Copyright (C) 1992, 1993, 1994 Lucid, Inc. 2 Copyright (C) 1992, 1993, 1994 Lucid, Inc.
3 Copyright (C) 1997 Sun Microsystems, Inc.
3 4
4 This file is part of the Lucid Widget Library. 5 This file is part of the Lucid Widget Library.
5 6
6 The Lucid Widget Library is free software; you can redistribute it and/or 7 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by 8 modify it under the terms of the GNU General Public License as published by
17 along with XEmacs; see the file COPYING. If not, write to 18 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1307, USA. */
20 21
21 /* Created by Douglas Keller <dkeller@vnet.ibm.com> */ 22 /* Created by Douglas Keller <dkeller@vnet.ibm.com> */
23 /* Lots of hacking by Martin Buchholz */
22 24
23 /* 25 /*
24 * Athena-style scrollbar button bindings added on Sun Dec 24 22:03:57 1995 26 * Athena-style scrollbar button bindings added on Sun Dec 24 22:03:57 1995
25 * by Jonathan Stigelman <Stig@hackvan.com>... Ho ho ho! 27 * by Jonathan Stigelman <Stig@hackvan.com>... Ho ho ho!
26 * 28 *
59 * XmNpageDecrementCallback 61 * XmNpageDecrementCallback
60 * XmNtoTopCallback 62 * XmNtoTopCallback
61 * XmNtoBottomCallback 63 * XmNtoBottomCallback
62 * XmNdragCallback 64 * XmNdragCallback
63 * 65 *
64 * XmNknobStyle - values can be: "plain" or "dimple" 66 * XmNsliderStyle - values can be: "plain" or "dimple"
65 * XmNarrowPosition - values can be: "opposite" or "same" 67 * XmNarrowPosition - values can be: "opposite" or "same"
66 * 68 *
67 */ 69 */
68 70
69 #include <stdio.h> 71 #include <stdio.h>
84 86
85 #define VERT(w) ((w)->sb.orientation == XmVERTICAL) 87 #define VERT(w) ((w)->sb.orientation == XmVERTICAL)
86 88
87 #define SS_MIN 8 89 #define SS_MIN 8
88 90
89 #define ARROW_UP 0 91 typedef enum
90 #define ARROW_DOWN 1 92 {
91 #define ARROW_LEFT 2 93 BUTTON_NONE,
92 #define ARROW_RIGHT 3 94 BUTTON_SLIDER,
93 95 BUTTON_UP_ARROW,
94 #define ARM_NONE 0 96 BUTTON_DOWN_ARROW,
95 #define ARM_KNOB 1 97 BUTTON_TROUGH_ABOVE,
96 #define ARM_UP 2 98 BUTTON_TROUGH_BELOW
97 #define ARM_DOWN 3 99 } button_where;
98 #define ARM_PAGEUP 4 100
99 #define ARM_PAGEDOWN 5 101 typedef enum
100 102 {
101 #define BUTTON_NONE 0 103 SLIDER_PLAIN,
102 #define BUTTON_KNOB 1 104 SLIDER_DIMPLE
103 #define BUTTON_UP_ARROW 2 105 } SliderStyle;
104 #define BUTTON_DOWN_ARROW 3 106
105 #define BUTTON_TROUGH_ABOVE 4 107 /*-------------------------- Resources ----------------------------------*/
106 #define BUTTON_TROUGH_BELOW 5
107
108 #define KNOB_PLAIN 0
109 #define KNOB_DIMPLE 1
110
111 /************************************************************************
112 **
113 ** Resources
114 **
115 */
116 #define offset(field) XtOffset(XlwScrollBarWidget, field) 108 #define offset(field) XtOffset(XlwScrollBarWidget, field)
117 109
118 static XtResource resources[] = { 110 static XtResource resources[] = {
119 { XmNforeground, XmCForeground, XtRPixel, sizeof(Pixel), 111 { XmNforeground, XmCForeground, XtRPixel, sizeof(Pixel),
120 offset(sb.foreground), XtRImmediate, (XtPointer) XtDefaultForeground }, 112 offset(sb.foreground), XtRImmediate, (XtPointer) XtDefaultForeground },
187 { XmNtoBottomCallback, XmCToBottomCallback, XtRCallback, 179 { XmNtoBottomCallback, XmCToBottomCallback, XtRCallback,
188 sizeof(XtPointer), offset(sb.toBottomCBL), XtRCallback, NULL}, 180 sizeof(XtPointer), offset(sb.toBottomCBL), XtRCallback, NULL},
189 { XmNdragCallback, XmCDragCallback, XtRCallback, 181 { XmNdragCallback, XmCDragCallback, XtRCallback,
190 sizeof(XtPointer), offset(sb.dragCBL), XtRCallback, NULL}, 182 sizeof(XtPointer), offset(sb.dragCBL), XtRCallback, NULL},
191 183
184 /* "knob" is obsolete; use "slider" instead. */
185 { XmNsliderStyle, XmCSliderStyle, XtRString, sizeof(char *),
186 offset(sb.sliderStyle), XtRImmediate, NULL},
192 { XmNknobStyle, XmCKnobStyle, XtRString, sizeof(char *), 187 { XmNknobStyle, XmCKnobStyle, XtRString, sizeof(char *),
193 offset(sb.knobStyle), XtRImmediate, NULL}, 188 offset(sb.sliderStyle), XtRImmediate, NULL},
194 189
195 { XmNarrowPosition, XmCArrowPosition, XtRString, 190 { XmNarrowPosition, XmCArrowPosition, XtRString,
196 sizeof(char *), offset(sb.arrowPosition), XtRImmediate, NULL}, 191 sizeof(char *), offset(sb.arrowPosition), XtRImmediate, NULL},
197 }; 192 };
198 193
199 /************************************************************************ 194 /*-------------------------- Prototypes ---------------------------------*/
200 ** 195
201 ** Prototypes 196 /* Actions */
202 ** 197 typedef void Action(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
203 */ 198 static Action Select, PageUpOrLeft, PageDownOrRight, Drag, Release, Jump, Abort;
204 199
205 /* 200 /* Methods */
206 ** Actions
207 */
208 static void Select(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
209 static void PageUpOrLeft(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
210 static void PageDownOrRight(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
211 static void Drag(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
212 static void Release(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
213 static void Jump(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
214 static void Abort(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
215
216 /*
217 ** Methods
218 */
219 static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num_args); 201 static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num_args);
220 static Boolean SetValues(Widget current, Widget request, Widget nw, ArgList args, Cardinal *num_args); 202 static Boolean SetValues(Widget current, Widget request, Widget nw, ArgList args, Cardinal *num_args);
221 static void Destroy(Widget widget); 203 static void Destroy(Widget widget);
222 static void Redisplay(Widget widget, XEvent *event, Region region); 204 static void Redisplay(Widget widget, XEvent *event, Region region);
223 static void Resize(Widget widget); 205 static void Resize(Widget widget);
224 static void Realize(Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr); 206 static void Realize(Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr);
225 207
226 /* 208 /* Private */
227 ** Private 209
228 */ 210 /*-------------------------- Actions Table ------------------------------*/
229 211 static XtActionsRec actions[] =
230 212 {
231 /************************************************************************ 213 {"Select", Select},
232 ** 214 {"PageDownOrRight", PageDownOrRight},
233 ** Actions Table 215 {"PageUpOrLeft", PageUpOrLeft},
234 ** 216 {"Drag", Drag},
235 */ 217 {"Release", Release},
236 static XtActionsRec actions[] = { 218 {"Jump", Jump},
237 {"Select", Select}, 219 {"Abort", Abort},
238 {"PageDownOrRight", PageDownOrRight},
239 {"PageUpOrLeft", PageUpOrLeft},
240 {"Drag", Drag},
241 {"Release", Release},
242 {"Jump", Jump},
243 {"Abort", Abort},
244 }; 220 };
245 221
246 /************************************************************************ 222 /*--------------------- Default Translation Table -----------------------*/
247 **
248 ** Default Translation Table
249 **
250 */
251 static char default_translations[] = 223 static char default_translations[] =
252 "<Btn1Down>: Select()\n" 224 "<Btn1Down>: Select()\n"
253 "<Btn1Motion>: Drag()\n" 225 "<Btn1Motion>: Drag()\n"
254 "<Btn1Up>: Release()\n" 226 "<Btn1Up>: Release()\n"
255 "<Btn2Down>: Jump()\n" 227 "<Btn2Down>: Jump()\n"
256 "<Btn2Motion>: Drag()\n" 228 "<Btn2Motion>: Drag()\n"
257 "<Btn2Up>: Release()\n" 229 "<Btn2Up>: Release()\n"
258 "<Key>Delete: Abort()" 230 "<Key>Delete: Abort()"
259 ; 231 ;
260 232
261 /************************************************************************ 233 /*------------------- Class record initialization -----------------------*/
262 **
263 ** Class record initalization
264 **
265 */
266 XlwScrollBarClassRec xlwScrollBarClassRec = { 234 XlwScrollBarClassRec xlwScrollBarClassRec = {
267 /* core_class fields */ 235 /* core_class fields */
268 { 236 {
269 /* superclass */ (WidgetClass) &coreClassRec, 237 /* superclass */ (WidgetClass) &coreClassRec,
270 /* class_name */ "XlwScrollBar", 238 /* class_name */ "XlwScrollBar",
303 }, 271 },
304 }; 272 };
305 273
306 WidgetClass xlwScrollBarWidgetClass = (WidgetClass) &xlwScrollBarClassRec; 274 WidgetClass xlwScrollBarWidgetClass = (WidgetClass) &xlwScrollBarClassRec;
307 275
308 /************************************************************************ 276 /*-------------------------- Debug Functions ----------------------------*/
309 **
310 ** Debug functions
311 **
312 */
313 277
314 #ifdef SHOW_CLEAR 278 #ifdef SHOW_CLEAR
315 static void 279 static void
316 myXClearArea(Display *dpy, Drawable d, int x, int y, int w, int h, 280 myXClearArea(Display *dpy, Drawable d, int x, int y, int w, int h,
317 Boolean exp, XlwScrollBarWidget widget) 281 Boolean exp, XlwScrollBarWidget widget)
327 291
328 #ifdef CHECK_VALUES 292 #ifdef CHECK_VALUES
329 static void 293 static void
330 check(XlwScrollBarWidget w) 294 check(XlwScrollBarWidget w)
331 { 295 {
332 int height; 296 int height = widget_h (w);
333 297 if (w->sb.showArrows)
334 height= widget_h (w); 298 height -= (2 * arrow_h (w));
335 if (w->sb.showArrows) height -= (2 * arrow_h (w));
336 299
337 if ((w->sb.above + w->sb.ss + w->sb.below > height) || 300 if ((w->sb.above + w->sb.ss + w->sb.below > height) ||
338 (w->sb.value < w->sb.minimum) || 301 (w->sb.value < w->sb.minimum) ||
339 (w->sb.value > w->sb.maximum - w->sb.sliderSize) 302 (w->sb.value > w->sb.maximum - w->sb.sliderSize))
340 )
341 { 303 {
342 printf("above=%d ss=%d below=%d height=%d\n", 304 printf("above=%d ss=%d below=%d height=%d\n",
343 w->sb.above, w->sb.ss, w->sb.below, height); 305 w->sb.above, w->sb.ss, w->sb.below, height);
344 printf("value=%d min=%d max=%d ss=%d max-ss=%d\n", 306 printf("value=%d min=%d max=%d ss=%d max-ss=%d\n",
345 w->sb.value, w->sb.minimum, w->sb.maximum, 307 w->sb.value, w->sb.minimum, w->sb.maximum,
351 # define CHECK(w) check(w) 313 # define CHECK(w) check(w)
352 #else 314 #else
353 # define CHECK(w) 315 # define CHECK(w)
354 #endif 316 #endif
355 317
356 /************************************************************************ 318 /*-------------------------- Static functions ---------------------------*/
357 **
358 ** Static functions
359 **
360 */
361 319
362 static void 320 static void
363 call_callbacks (XlwScrollBarWidget w, int reason, 321 call_callbacks (XlwScrollBarWidget w, int reason,
364 int value, int pixel, XEvent *event) 322 int value, int pixel, XEvent *event)
365 { 323 {
435 cbs.reason = XmCR_VALUE_CHANGED; 393 cbs.reason = XmCR_VALUE_CHANGED;
436 XtCallCallbackList ((Widget) w, w->sb.valueChangedCBL, &cbs); 394 XtCallCallbackList ((Widget) w, w->sb.valueChangedCBL, &cbs);
437 } 395 }
438 } 396 }
439 397
440 /* 398 /* Widget sizes minus the shadow and highlight area */
441 ** Widget sizes minus the shadow and highlight area 399
442 */
443 static int 400 static int
444 widget_x (XlwScrollBarWidget w) 401 widget_x (XlwScrollBarWidget w)
445 { 402 {
446 return w->sb.shadowThickness; 403 return w->sb.shadowThickness;
447 } 404 }
453 } 410 }
454 411
455 static int 412 static int
456 widget_w (XlwScrollBarWidget w) 413 widget_w (XlwScrollBarWidget w)
457 { 414 {
458 int width, x = w->sb.shadowThickness; 415 int x = w->sb.shadowThickness;
459 416 int width = (VERT (w) ? w->core.width : w->core.height) - (2 * x);
460 width = VERT (w) ? w->core.width : w->core.height; 417 return width > 1 ? width : 1;
461
462 if (width <= (2 * x))
463 return 1;
464 else
465 return width - (2 * x);
466 } 418 }
467 419
468 static int 420 static int
469 widget_h (XlwScrollBarWidget w) 421 widget_h (XlwScrollBarWidget w)
470 { 422 {
471 int height, y = w->sb.shadowThickness; 423 int y = w->sb.shadowThickness;
472 424 int height = (VERT (w) ? w->core.height : w->core.width) - (2 * y);
473 height = VERT (w) ? w->core.height : w->core.width; 425
474 426 return height > 1 ? height : 1;
475 if (height <= (2 * y))
476 return 1;
477 else
478 return height - (2 * y);
479 } 427 }
480 428
481 static int 429 static int
482 arrow_h (XlwScrollBarWidget w) 430 arrow_h (XlwScrollBarWidget w)
483 { 431 {
484 int width, height; 432 int width = widget_w (w);
485 433 int minimum_size = ((widget_h (w) - SS_MIN) / 2) - 1;
486 width = widget_w (w); 434 return minimum_size < width ? minimum_size : width;
487 height= widget_h (w);
488
489 if (width > ((height / 2) - (SS_MIN / 2) - 1))
490 return (height / 2) - (SS_MIN / 2) - 1 ;
491 else
492 return width;
493 } 435 }
494 436
495 static int 437 static int
496 event_x (XlwScrollBarWidget w, XEvent *event) 438 event_x (XlwScrollBarWidget w, XEvent *event)
497 { 439 {
502 event_y (XlwScrollBarWidget w, XEvent *event) 444 event_y (XlwScrollBarWidget w, XEvent *event)
503 { 445 {
504 return VERT (w) ? event->xbutton.y : event->xbutton.x; 446 return VERT (w) ? event->xbutton.y : event->xbutton.x;
505 } 447 }
506 448
507 /* 449 /* Safe addition and subtraction */
508 ** Safe addition and subtraction 450 static void
509 */ 451 increment_value (XlwScrollBarWidget w, int diff)
510 static int 452 {
511 safe_add (int a, int b) 453 w->sb.value = w->sb.maximum - diff < w->sb.value ?
512 { 454 w->sb.maximum :
513 if (a > 0 && INT_MAX - a < b) return INT_MAX; 455 w->sb.value + diff;
514 else return a + b; 456 }
515 } 457
516 458 static void
517 static int 459 decrement_value (XlwScrollBarWidget w, int diff)
518 safe_subtract (int a, int b) 460 {
519 { 461 w->sb.value = w->sb.minimum + diff > w->sb.value ?
520 if (a < 0 && -(INT_MIN - a) < b) return INT_MIN; 462 w->sb.minimum :
521 else return a - b; 463 w->sb.value - diff;
522 } 464 }
523 465
524 static int 466 static SliderStyle
525 knob_style (XlwScrollBarWidget w) 467 slider_style (XlwScrollBarWidget w)
526 { 468 {
527 return w->sb.knobStyle && w->sb.knobStyle[0] == 'd' ? 469 return w->sb.sliderStyle && w->sb.sliderStyle[0] == 'd' ?
528 KNOB_DIMPLE : 470 SLIDER_DIMPLE :
529 KNOB_PLAIN; 471 SLIDER_PLAIN;
530 } 472 }
531 473
532 static Boolean 474 static Boolean
533 arrow_same_end (XlwScrollBarWidget w) 475 arrow_same_end (XlwScrollBarWidget w)
534 { 476 {
535 return w->sb.arrowPosition && w->sb.arrowPosition[0] == 's' ? True : False; 477 return w->sb.arrowPosition && w->sb.arrowPosition[0] == 's' ? True : False;
536 } 478 }
537 479
538 /* 480 /*-------------------------- GC and Pixel allocation --------------------*/
539 ** GC and Pixel allocation
540 */
541 static GC 481 static GC
542 get_gc (XlwScrollBarWidget w, Pixel fg, Pixel bg, Pixmap pm) 482 get_gc (XlwScrollBarWidget w, Pixel fg, Pixel bg, Pixmap pm)
543 { 483 {
544 XGCValues values; 484 XGCValues values;
545 XtGCMask mask; 485 XtGCMask mask;
557 497
558 values.foreground = fg; 498 values.foreground = fg;
559 values.background = bg; 499 values.background = bg;
560 values.fill_style = FillOpaqueStippled; 500 values.fill_style = FillOpaqueStippled;
561 values.stipple = pm; 501 values.stipple = pm;
562 mask = GCForeground | GCBackground | 502 mask = GCForeground | GCBackground |
563 (pm == None ? 0 : GCStipple | GCFillStyle); 503 (pm == None ? 0 : GCStipple | GCFillStyle);
564 return XtGetGC((Widget) w, mask, &values); 504 return XtGetGC((Widget) w, mask, &values);
565 } 505 }
566 506
567 /* Replacement for XAllocColor() that tries to return the nearest 507 /* Replacement for XAllocColor() that tries to return the nearest
568 available color if the colormap is full. From FSF Emacs. */ 508 available color if the colormap is full. From FSF Emacs. */
714 { 654 {
715 /* Assume we're in mono. This code should be okay even if we're 655 /* Assume we're in mono. This code should be okay even if we're
716 * really in color but just short on color cells -- We want the 656 * really in color but just short on color cells -- We want the
717 * following behavior, which has been empirically determined to 657 * following behavior, which has been empirically determined to
718 * work well for all fg/bg combinations in mono: If the trough 658 * work well for all fg/bg combinations in mono: If the trough
719 * and thumb are BOTH black, then use a white top shadow and a 659 * and slider are BOTH black, then use a white top shadow and a
720 * grey bottom shadow, otherwise use a grey top shadow and a 660 * grey bottom shadow, otherwise use a grey top shadow and a
721 * black bottom shadow. 661 * black bottom shadow.
722 */ 662 */
723 663
724 Pixel white = WhitePixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w))); 664 Pixel white = WhitePixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w)));
725 Pixel black = BlackPixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w))); 665 Pixel black = BlackPixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w)));
726 666
727 /* Note: core.background_pixel is the color of the thumb ... */ 667 /* Note: core.background_pixel is the color of the slider ... */
728 668
729 if (w->core.background_pixel == black && 669 if (w->core.background_pixel == black &&
730 w->sb.troughColor == black) 670 w->sb.troughColor == black)
731 { 671 {
732 w->sb.topShadowColor = white; 672 w->sb.topShadowColor = white;
757 if (allocate_nearest_color (dpy, cmap, &troughC)) 697 if (allocate_nearest_color (dpy, cmap, &troughC))
758 w->sb.troughColor = troughC.pixel; 698 w->sb.troughColor = troughC.pixel;
759 } 699 }
760 } 700 }
761 701
762 /* 702 /*-------------------------- Draw 3D Border -----------------------------*/
763 ** Draw 3d border
764 */
765 static void 703 static void
766 draw_shadows (Display *dpy, Drawable d, GC shine_gc, GC shadow_gc, 704 draw_shadows (Display *dpy, Drawable d, GC shine_gc, GC shadow_gc,
767 int x, int y, int width, int height, int shadowT) 705 int x, int y, int width, int height, int shadowT)
768 { 706 {
769 XSegment shine[10], shadow[10]; 707 XSegment shine[10], shadow[10];
796 734
797 XDrawSegments (dpy, d, shine_gc, shine, shadowT * 2); 735 XDrawSegments (dpy, d, shine_gc, shine, shadowT * 2);
798 XDrawSegments (dpy, d, shadow_gc, shadow, shadowT * 2); 736 XDrawSegments (dpy, d, shadow_gc, shadow, shadowT * 2);
799 } 737 }
800 738
801 /* 739 /*------------------ Draw 3D Arrows: left, up, down, right --------------*/
802 ** Draw 3d arrows, left, up, down, and right
803 */
804 static int 740 static int
805 make_vert_seg (XSegment *seg, int x1, int y1, int x2, int y2, int shadowT) 741 make_vert_seg (XSegment *seg, int x1, int y1, int x2, int y2, int shadowT)
806 { 742 {
807 int i; 743 int i;
808 744
809 for (i=0; i<shadowT; i++) 745 for (i=0; i<shadowT; i++, seg++)
810 { 746 {
811 seg[i].x1 = x1; 747 seg->x1 = x1;
812 seg[i].y1 = y1 + i; 748 seg->y1 = y1++;
813 seg[i].x2 = x2; 749 seg->x2 = x2;
814 seg[i].y2 = y2 + i; 750 seg->y2 = y2++;
815 } 751 }
816 return shadowT; 752 return shadowT;
817 } 753 }
818 754
819 static int 755 static int
820 make_hor_seg (XSegment *seg, int x1, int y1, int x2, int y2, int shadowT) 756 make_hor_seg (XSegment *seg, int x1, int y1, int x2, int y2, int shadowT)
821 { 757 {
822 int i; 758 int i;
823 759
824 for (i=0; i<shadowT; i++) 760 for (i=0; i<shadowT; i++, seg++)
825 { 761 {
826 seg[i].x1 = x1 + i; 762 seg->x1 = x1++;
827 seg[i].y1 = y1; 763 seg->y1 = y1;
828 seg[i].x2 = x2 + i; 764 seg->x2 = x2++;
829 seg[i].y2 = y2; 765 seg->y2 = y2;
830 } 766 }
831 return shadowT; 767 return shadowT;
832 } 768 }
833 769
834 static void 770 static void
841 777
842 mid = width / 2; 778 mid = width / 2;
843 779
844 if (shadowT > (width / 2)) shadowT = (width / 2); 780 if (shadowT > (width / 2)) shadowT = (width / 2);
845 if (shadowT > (height / 2)) shadowT = (height / 2); 781 if (shadowT > (height / 2)) shadowT = (height / 2);
846 if (shadowT <= 0) shadowT = 0; 782 if (shadowT < 0) shadowT = 0;
847 783
848 /* / */ 784 /* / */
849 make_vert_seg (shine, 785 make_vert_seg (shine,
850 x, y + height - shadowT - 1, 786 x, y + height - shadowT - 1,
851 x + mid, y, shadowT); 787 x + mid, y, shadowT);
852 /* _\ */ 788 /* _\ */
853 make_vert_seg (shadow, 789 make_vert_seg (shadow,
854 x, y + height - shadowT - 1, 790 x, y + height - shadowT - 1,
855 x + width - 1, y + height - shadowT - 1, shadowT); 791 x + width - 1, y + height - shadowT - 1, shadowT);
856 make_vert_seg (shadow + shadowT, 792 make_vert_seg (shadow + shadowT,
857 x + mid, y, 793 x + mid, y,
858 x + width - 1, y + height - shadowT - 1, shadowT); 794 x + width - 1, y + height - shadowT - 1, shadowT);
859 795
860 triangle[0].x = x; 796 triangle[0].x = x;
861 triangle[0].y = y + height - 1; 797 triangle[0].y = y + height - 1;
862 triangle[1].x = x + mid; 798 triangle[1].x = x + mid;
874 draw_arrow_left (Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC, 810 draw_arrow_left (Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC,
875 int x, int y, int width, int height, int shadowT) 811 int x, int y, int width, int height, int shadowT)
876 { 812 {
877 XSegment shine[10], shadow[10]; 813 XSegment shine[10], shadow[10];
878 XPoint triangle[3]; 814 XPoint triangle[3];
879 int mid; 815
880 816 int mid = width / 2;
881 mid = width / 2;
882 817
883 if (shadowT > (width / 2)) shadowT = (width / 2); 818 if (shadowT > (width / 2)) shadowT = (width / 2);
884 if (shadowT > (height / 2)) shadowT = (height / 2); 819 if (shadowT > (height / 2)) shadowT = (height / 2);
885 if (shadowT <= 0) shadowT = 0; 820 if (shadowT < 0) shadowT = 0;
886 821
887 /* / */ 822 /* / */
888 make_hor_seg (shine, 823 make_hor_seg (shine,
889 x, y + mid, 824 x, y + mid,
890 x + width - shadowT - 1, y, shadowT); 825 x + width - shadowT - 1, y, shadowT);
891 /* \| */ 826 /* \| */
892 make_hor_seg (shadow, 827 make_hor_seg (shadow,
893 x, y + mid, 828 x, y + mid,
894 x + width - shadowT - 1, y + height - 1, shadowT); 829 x + width - shadowT - 1, y + height - 1, shadowT);
895 make_hor_seg (shadow + shadowT, 830 make_hor_seg (shadow + shadowT,
896 x + width - shadowT - 1, y, 831 x + width - shadowT - 1, y,
897 x + width - shadowT - 1, y + height - 1, shadowT); 832 x + width - shadowT - 1, y + height - 1, shadowT);
898 833
919 854
920 mid = width / 2; 855 mid = width / 2;
921 856
922 if (shadowT > (width / 2)) shadowT = (width / 2); 857 if (shadowT > (width / 2)) shadowT = (width / 2);
923 if (shadowT > (height / 2)) shadowT = (height / 2); 858 if (shadowT > (height / 2)) shadowT = (height / 2);
924 if (shadowT <= 0) shadowT = 0; 859 if (shadowT < 0) shadowT = 0;
925 860
926 /* \- */ 861 /* \- */
927 make_vert_seg (shine, 862 make_vert_seg (shine,
928 x, y, 863 x, y,
929 x + mid, y + height - shadowT - 1, shadowT); 864 x + mid, y + height - shadowT - 1, shadowT);
930 make_vert_seg (shine + shadowT, 865 make_vert_seg (shine + shadowT,
931 x, y, 866 x, y,
932 x + width - 1, y, shadowT); 867 x + width - 1, y, shadowT);
933 /* / */ 868 /* / */
934 make_vert_seg (shadow, 869 make_vert_seg (shadow,
935 x + width - 1, y, 870 x + width - 1, y,
936 x + mid, y + height - shadowT - 1, shadowT); 871 x + mid, y + height - shadowT - 1, shadowT);
937 872
938 triangle[0].x = x; 873 triangle[0].x = x;
939 triangle[0].y = y; 874 triangle[0].y = y;
940 triangle[1].x = x + mid; 875 triangle[1].x = x + mid;
941 triangle[1].y = y + height - 1; 876 triangle[1].y = y + height - 1;
958 893
959 mid = width / 2; 894 mid = width / 2;
960 895
961 if (shadowT > (width / 2)) shadowT = (width / 2); 896 if (shadowT > (width / 2)) shadowT = (width / 2);
962 if (shadowT > (height / 2)) shadowT = (height / 2); 897 if (shadowT > (height / 2)) shadowT = (height / 2);
963 if (shadowT <= 0) shadowT = 0; 898 if (shadowT < 0) shadowT = 0;
964 899
965 /* |\ */ 900 /* |\ */
966 make_hor_seg (shine, 901 make_hor_seg (shine,
967 x, y, 902 x, y,
968 x + width - shadowT - 1, y + mid, shadowT); 903 x + width - shadowT - 1, y + mid, shadowT);
969 make_hor_seg (shine + shadowT, 904 make_hor_seg (shine + shadowT,
970 x, y, 905 x, y,
971 x, y + height -1, shadowT); 906 x, y + height - 1, shadowT);
972 /* / */ 907 /* / */
973 make_hor_seg (shadow, 908 make_hor_seg (shadow,
974 x, y + height -1, 909 x, y + height - 1,
975 x + width - shadowT - 1, y + mid, shadowT); 910 x + width - shadowT - 1, y + mid, shadowT);
976 911
977 triangle[0].x = x + 1; 912 triangle[0].x = x + 1;
978 triangle[0].y = y + height - 1; 913 triangle[0].y = y + height - 1;
979 triangle[1].x = x + width - 1; 914 triangle[1].x = x + width - 1;
980 triangle[1].y = y + mid; 915 triangle[1].y = y + mid;
981 triangle[2].x = x + 1; 916 triangle[2].x = x + 1;
982 triangle[2].y = y; 917 triangle[2].y = y;
983 918
984 XFillPolygon (dpy, win, bgGC, triangle, 3, Convex, ArcChord); 919 XFillPolygon (dpy, win, bgGC, triangle, 3, Convex, ArcChord);
993 { 928 {
994 XDrawArc (dpy, win, shine, x, y, width, height, 46*64, 180*64); 929 XDrawArc (dpy, win, shine, x, y, width, height, 46*64, 180*64);
995 XDrawArc (dpy, win, shadow, x, y, width, height, 45*64, -179*64); 930 XDrawArc (dpy, win, shadow, x, y, width, height, 45*64, -179*64);
996 } 931 }
997 932
998 /* 933 /*------- Scrollbar values -> pixels, pixels -> scrollbar values --------*/
999 ** Scrollbar values -> pixels, pixels -> scrollbar values
1000 */
1001 934
1002 static void 935 static void
1003 seg_pixel_sizes (XlwScrollBarWidget w, int *above_return, 936 seg_pixel_sizes (XlwScrollBarWidget w, int *above_return,
1004 int *ss_return, int *below_return) 937 int *ss_return, int *below_return)
1005 { 938 {
1017 950
1018 ss = ((height * w->sb.sliderSize + fuz) / total); 951 ss = ((height * w->sb.sliderSize + fuz) / total);
1019 above = ((height * value + fuz) / total); 952 above = ((height * value + fuz) / total);
1020 below = ((height) - (ss + above)); 953 below = ((height) - (ss + above));
1021 954
1022 /* Dont' let knob get smaller than SS_MIN */ 955 /* Don't let slider get smaller than SS_MIN */
1023 if (ss < SS_MIN) 956 if (ss < SS_MIN)
1024 { 957 {
1025 /* add a percent amount for integer rounding */ 958 /* add a percent amount for integer rounding */
1026 float tmp = ((((float) (SS_MIN - ss) * (float) value)) / total) + 0.5; 959 float tmp = ((((float) (SS_MIN - ss) * (float) value)) / total) + 0.5;
1027 960
1028 above -= (int) tmp; 961 above -= (int) tmp;
1029 ss = SS_MIN; 962 ss = SS_MIN;
1030 below = ((height) - (ss + above)); 963 below = ((height) - (ss + above));
1031 964
1032 if (above < 0) 965 if (above < 0)
1033 { 966 {
1034 above = 0; 967 above = 0;
1069 w->sb.increment = total; 1002 w->sb.increment = total;
1070 1003
1071 if (w->sb.value < w->sb.minimum) 1004 if (w->sb.value < w->sb.minimum)
1072 w->sb.value = w->sb.minimum; 1005 w->sb.value = w->sb.minimum;
1073 1006
1074 if (w->sb.value > w->sb.maximum - w->sb.sliderSize) 1007 if (w->sb.value > w->sb.maximum)
1075 w->sb.value = w->sb.maximum - w->sb.sliderSize; 1008 w->sb.value = w->sb.maximum;
1009
1010 if (w->sb.sliderSize > w->sb.maximum - w->sb.value)
1011 w->sb.sliderSize = w->sb.maximum - w->sb.value;
1076 } 1012 }
1077 1013
1078 static int 1014 static int
1079 value_from_pixel (XlwScrollBarWidget w, int above) 1015 value_from_pixel (XlwScrollBarWidget w, int above)
1080 { 1016 {
1081 float total, height, fuz; 1017 float total, height, fuz;
1082 int value, ss; 1018 int value, ss;
1083 1019
1084 height= widget_h (w); 1020 height = widget_h (w);
1085 if (w->sb.showArrows) height -= (2 * arrow_h (w)); 1021 if (w->sb.showArrows)
1022 height -= (2 * arrow_h (w));
1086 1023
1087 total = w->sb.maximum - w->sb.minimum; 1024 total = w->sb.maximum - w->sb.minimum;
1088 fuz = height / 2; 1025 fuz = height / 2;
1089 1026
1090 ss = ((height * w->sb.sliderSize + (total / 2)) / total); 1027 ss = ((height * w->sb.sliderSize + (total / 2)) / total);
1112 1049
1113 static void 1050 static void
1114 redraw_dimple (XlwScrollBarWidget w, Display *dpy, Window win, 1051 redraw_dimple (XlwScrollBarWidget w, Display *dpy, Window win,
1115 int x, int y, int width, int height) 1052 int x, int y, int width, int height)
1116 { 1053 {
1117 GC shine, shadow; 1054 if (SLIDER_DIMPLE == slider_style (w))
1118 int shadowT, size; 1055 {
1119 1056 int size;
1120 if (KNOB_DIMPLE == knob_style (w)) 1057 int slider_p = (w->sb.armed == ARM_SLIDER);
1121 { 1058 GC shine = slider_p ? w->sb.bottomShadowGC : w->sb.topShadowGC;
1122 if (w->sb.armed == ARM_KNOB) 1059 GC shadow = slider_p ? w->sb.topShadowGC : w->sb.bottomShadowGC;
1123 { 1060 int shadowT = w->sb.shadowThickness;
1124 shine = w->sb.bottomShadowGC;
1125 shadow = w->sb.topShadowGC;
1126 }
1127 else
1128 {
1129 shine = w->sb.topShadowGC;
1130 shadow = w->sb.bottomShadowGC;
1131 }
1132
1133 shadowT = w->sb.shadowThickness;
1134 1061
1135 x += shadowT; 1062 x += shadowT;
1136 y += shadowT; 1063 y += shadowT;
1137 width -= 2*shadowT; 1064 width -= 2*shadowT;
1138 height -= 2*shadowT; 1065 height -= 2*shadowT;
1151 size, size); 1078 size, size);
1152 } 1079 }
1153 } 1080 }
1154 1081
1155 static void 1082 static void
1156 draw_knob (XlwScrollBarWidget w, int above, int ss, int below) 1083 draw_slider (XlwScrollBarWidget w, int above, int ss, int below)
1157 { 1084 {
1158 Display *dpy = XtDisplay ((Widget) w); 1085 Display *dpy = XtDisplay ((Widget) w);
1159 Window win = XtWindow ((Widget) w); 1086 Window win = XtWindow ((Widget) w);
1160 int x, y, width, height; 1087
1161 int shadowT; 1088 int x = widget_x (w);
1162 1089 int y = widget_y (w);
1163 x = widget_x (w); 1090 int width = widget_w (w);
1164 y = widget_y (w); 1091 int height = widget_h (w);
1165 width = widget_w (w); 1092 int shadowT = w->sb.shadowThickness;
1166 height = widget_h (w); 1093 int vert_p = VERT (w);
1167
1168 shadowT = w->sb.shadowThickness;
1169 1094
1170 if (shadowT > (width / 2)) shadowT = (width / 2); 1095 if (shadowT > (width / 2)) shadowT = (width / 2);
1171 if (shadowT > (height / 2)) shadowT = (height / 2); 1096 if (shadowT > (height / 2)) shadowT = (height / 2);
1172 if (shadowT <= 0) return; 1097 if (shadowT < 0) shadowT = 0;
1173 1098
1174 if (w->sb.showArrows && !arrow_same_end (w)) y += arrow_h (w); 1099 if (w->sb.showArrows && !arrow_same_end (w))
1175 1100 y += arrow_h (w);
1176 /* trough above knob */ 1101
1102 /* trough above slider */
1177 if (above > 0) 1103 if (above > 0)
1178 { 1104 {
1179 if (VERT (w)) 1105 if (vert_p)
1180 XClearArea (dpy, win, x, y, width, above, False); 1106 XClearArea (dpy, win, x, y, width, above, False);
1181 else 1107 else
1182 XClearArea (dpy, win, y, x, above, width, False); 1108 XClearArea (dpy, win, y, x, above, width, False);
1183 } 1109 }
1184 1110
1185 /* knob */ 1111 /* slider */
1186 if (VERT (w)) 1112 if (vert_p)
1187 { 1113 {
1188 draw_shadows (dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC, 1114 draw_shadows (dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC,
1189 x, y + above, width, ss, shadowT); 1115 x, y + above, width, ss, shadowT);
1190 XFillRectangle (dpy, win, 1116 XFillRectangle (dpy, win, w->sb.backgroundGC,
1191 w->sb.backgroundGC, 1117 x+shadowT, y + above + shadowT,
1192 x+shadowT, y + above + shadowT, width-2*shadowT, ss-2*shadowT); 1118 width-2*shadowT, ss-2*shadowT);
1193 redraw_dimple (w, dpy, win, x, y + above, width, ss); 1119 redraw_dimple (w, dpy, win, x, y + above, width, ss);
1194 } 1120 }
1195 else 1121 else
1196 { 1122 {
1197 draw_shadows (dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC, 1123 draw_shadows (dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC,
1198 y + above, x, ss, width, shadowT); 1124 y + above, x, ss, width, shadowT);
1199 XFillRectangle (dpy, win, 1125 XFillRectangle (dpy, win, w->sb.backgroundGC,
1200 w->sb.backgroundGC, 1126 y + above + shadowT, x+shadowT,
1201 y + above + shadowT, x+shadowT, ss-2*shadowT, width-2*shadowT); 1127 ss-2*shadowT, width-2*shadowT);
1202 redraw_dimple (w, dpy, win, y + above, x, ss, width); 1128 redraw_dimple (w, dpy, win, y + above, x, ss, width);
1203 } 1129 }
1204 1130
1205 /* trough below knob */ 1131 /* trough below slider */
1206 if (below > 0) 1132 if (below > 0)
1207 { 1133 {
1208 if (VERT (w)) 1134 if (vert_p)
1209 XClearArea (dpy, win, x, y + above + ss, width, below, False); 1135 XClearArea (dpy, win, x, y + above + ss, width, below, False);
1210 else 1136 else
1211 XClearArea (dpy, win, y + above + ss, x, below, width, False); 1137 XClearArea (dpy, win, y + above + ss, x, below, width, False);
1212 } 1138 }
1213 1139
1217 static void 1143 static void
1218 redraw_up_arrow (XlwScrollBarWidget w, Boolean armed, Boolean clear_behind) 1144 redraw_up_arrow (XlwScrollBarWidget w, Boolean armed, Boolean clear_behind)
1219 { 1145 {
1220 Display *dpy = XtDisplay ((Widget) w); 1146 Display *dpy = XtDisplay ((Widget) w);
1221 Window win = XtWindow ((Widget) w); 1147 Window win = XtWindow ((Widget) w);
1222 GC bg, shine, shadow; 1148
1223 int x, y, width, height, arrow_height, shadowT; 1149 int x = widget_x (w);
1224 1150 int y = widget_y (w);
1225 x = widget_x (w); 1151 int width = widget_w (w);
1226 y = widget_y (w); 1152 int height = widget_h (w);
1227 width = widget_w (w); 1153 int shadowT = w->sb.shadowThickness;
1228 height = widget_h (w); 1154 int arrow_height = arrow_h (w);
1229 arrow_height = arrow_h (w); 1155
1230 1156 GC bg = w->sb.backgroundGC;
1231 shadowT = w->sb.shadowThickness; 1157 GC shine = armed ? w->sb.bottomShadowGC : w->sb.topShadowGC;
1232 bg = w->sb.backgroundGC; 1158 GC shadow = armed ? w->sb.topShadowGC : w->sb.bottomShadowGC;
1233
1234 if (armed)
1235 {
1236 shine = w->sb.bottomShadowGC;
1237 shadow = w->sb.topShadowGC;
1238 }
1239 else
1240 {
1241 shine = w->sb.topShadowGC;
1242 shadow = w->sb.bottomShadowGC;
1243 }
1244 1159
1245 if (VERT (w)) 1160 if (VERT (w))
1246 { 1161 {
1247 if (arrow_same_end (w)) 1162 if (arrow_same_end (w))
1248 { 1163 y += height - 2 * arrow_height;
1249 y += height - 2 * arrow_h (w) + 2;
1250 }
1251 if (clear_behind) 1164 if (clear_behind)
1252 XClearArea (dpy, win, x, y, width, arrow_height + 1, False); 1165 XClearArea (dpy, win, x, y, width, arrow_height + 1, False);
1253 draw_arrow_up (dpy, win, bg, shine, shadow, 1166 draw_arrow_up (dpy, win, bg, shine, shadow,
1254 x + (width - arrow_height)/2, y, 1167 x + (width - arrow_height)/2, y,
1255 arrow_height, arrow_height, shadowT); 1168 arrow_height, arrow_height, shadowT);
1256 } 1169 }
1257 else 1170 else
1258 { 1171 {
1259 if (arrow_same_end (w)) 1172 if (arrow_same_end (w))
1260 { 1173 y += height - 2 * arrow_height;
1261 y += height - 2 * arrow_h (w);
1262 }
1263 if (clear_behind) 1174 if (clear_behind)
1264 XClearArea (dpy, win, y, x, arrow_height + 1, height, False); 1175 XClearArea (dpy, win, y, x, arrow_height + 1, height, False);
1265 draw_arrow_left (dpy, win, bg, shine, shadow, 1176 draw_arrow_left (dpy, win, bg, shine, shadow,
1266 y, x + (width - arrow_height)/2, 1177 y, x + (width - arrow_height)/2,
1267 arrow_height, arrow_height, shadowT); 1178 arrow_height, arrow_height, shadowT);
1271 static void 1182 static void
1272 redraw_down_arrow (XlwScrollBarWidget w, Boolean armed, Boolean clear_behind) 1183 redraw_down_arrow (XlwScrollBarWidget w, Boolean armed, Boolean clear_behind)
1273 { 1184 {
1274 Display *dpy = XtDisplay ((Widget) w); 1185 Display *dpy = XtDisplay ((Widget) w);
1275 Window win = XtWindow ((Widget) w); 1186 Window win = XtWindow ((Widget) w);
1276 GC bg, shine, shadow; 1187
1277 int x, y, width, height, arrow_height, shadowT; 1188 int x = widget_x (w);
1278 1189 int y = widget_y (w);
1279 x = widget_x (w); 1190 int width = widget_w (w);
1280 y = widget_y (w); 1191 int height = widget_h (w);
1281 width = widget_w (w); 1192 int shadowT = w->sb.shadowThickness;
1282 height = widget_h (w); 1193 int arrow_height = arrow_h (w);
1283 arrow_height = arrow_h (w); 1194
1284 1195 GC bg = w->sb.backgroundGC;
1285 shadowT = w->sb.shadowThickness; 1196 GC shine = armed ? w->sb.bottomShadowGC : w->sb.topShadowGC;
1286 bg = w->sb.backgroundGC; 1197 GC shadow = armed ? w->sb.topShadowGC : w->sb.bottomShadowGC;
1287
1288 if (armed)
1289 {
1290 shine = w->sb.bottomShadowGC;
1291 shadow = w->sb.topShadowGC;
1292 }
1293 else
1294 {
1295 shine = w->sb.topShadowGC;
1296 shadow = w->sb.bottomShadowGC;
1297 }
1298 1198
1299 if (VERT (w)) 1199 if (VERT (w))
1300 { 1200 {
1301 if (clear_behind) 1201 if (clear_behind)
1302 XClearArea (dpy, win, x, y + height - arrow_height, width, 1202 XClearArea (dpy, win, x, y + height - arrow_height, width,
1321 static void 1221 static void
1322 redraw_everything (XlwScrollBarWidget w, Region region, Boolean behind_arrows) 1222 redraw_everything (XlwScrollBarWidget w, Region region, Boolean behind_arrows)
1323 { 1223 {
1324 Display *dpy = XtDisplay ((Widget) w); 1224 Display *dpy = XtDisplay ((Widget) w);
1325 Window win = XtWindow ((Widget) w); 1225 Window win = XtWindow ((Widget) w);
1326 int x, y, width, height, shadowT, tmp;
1327
1328 x = widget_x (w);
1329 y = widget_y (w);
1330 width = widget_w (w);
1331 height = widget_h (w);
1332 shadowT = w->sb.shadowThickness;
1333 1226
1334 if (w->sb.showArrows) 1227 if (w->sb.showArrows)
1335 { 1228 {
1336 if (region == NULL || XRectInRegion (region, x, y, width, width)) 1229 if (region == NULL)
1337 { 1230 {
1338 redraw_up_arrow (w, False, behind_arrows); 1231 redraw_up_arrow (w, False, behind_arrows);
1339 } 1232 redraw_down_arrow (w, False, behind_arrows);
1340 if (VERT (w))
1341 {
1342 y = y + height - width + 1;
1343 } 1233 }
1344 else 1234 else
1345 { 1235 {
1346 tmp = y; 1236 int x = widget_x (w);
1347 y = x; 1237 int y = widget_y (w);
1348 x = tmp + height - width + 1; 1238 int width = widget_w (w);
1349 } 1239 int height = widget_h (w);
1350 if (region == NULL || XRectInRegion (region, x, y, width, width)) 1240 int arrow_height = arrow_h (w);
1351 { 1241 int ax = x, ay = y;
1352 redraw_down_arrow (w, False, behind_arrows); 1242
1353 } 1243 if (arrow_same_end (w))
1354 } 1244 {
1355 1245 if (VERT (w))
1356 draw_shadows (dpy, win, w->sb.bottomShadowGC, w->sb.topShadowGC, 1246 ay = y + height - arrow_height - arrow_height;
1357 0, 0, w->core.width, w->core.height, shadowT); 1247 else
1358 1248 ax = x + height - arrow_height - arrow_height;
1359 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1249 }
1360 1250 if (XRectInRegion (region, ax, ay, width, width))
1361 } 1251 redraw_up_arrow (w, False, behind_arrows);
1362 1252
1363 /************************************************************************ 1253 if (VERT (w))
1364 ** 1254 ay = y + height - arrow_height;
1365 ** Method functions 1255 else
1366 ** 1256 ax = x + height - arrow_height;
1367 */ 1257 if (XRectInRegion (region, ax, ay, width, width))
1258 redraw_down_arrow (w, False, behind_arrows);
1259 }
1260 }
1261
1262 draw_shadows (dpy, win, w->sb.bottomShadowGC, w->sb.topShadowGC, 0, 0,
1263 w->core.width, w->core.height, w->sb.shadowThickness);
1264
1265 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1266 }
1267
1268 /*-------------------------- Method Functions ---------------------------*/
1368 1269
1369 static void 1270 static void
1370 Initialize (Widget treq, Widget tnew, ArgList args, Cardinal *num_args) 1271 Initialize (Widget treq, Widget tnew, ArgList args, Cardinal *num_args)
1371 { 1272 {
1372 XlwScrollBarWidget request = (XlwScrollBarWidget) treq; 1273 XlwScrollBarWidget request = (XlwScrollBarWidget) treq;
1373 XlwScrollBarWidget w = (XlwScrollBarWidget) tnew; 1274 XlwScrollBarWidget w = (XlwScrollBarWidget) tnew;
1374 Display *dpy = XtDisplay ((Widget) w); 1275 Display *dpy = XtDisplay ((Widget) w);
1375 Window win = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); 1276 Window win = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
1376
1377 DBUG (fprintf (stderr, "Initialize\n"));
1378 1277
1379 if (request->core.width == 0) w->core.width += (VERT (w) ? 12 : 25); 1278 if (request->core.width == 0) w->core.width += (VERT (w) ? 12 : 25);
1380 if (request->core.height == 0) w->core.height += (VERT (w) ? 25 : 12); 1279 if (request->core.height == 0) w->core.height += (VERT (w) ? 25 : 12);
1381 1280
1382 verify_values (w); 1281 verify_values (w);
1384 w->sb.lastY = 0; 1283 w->sb.lastY = 0;
1385 w->sb.above = 0; 1284 w->sb.above = 0;
1386 w->sb.ss = 0; 1285 w->sb.ss = 0;
1387 w->sb.below = 0; 1286 w->sb.below = 0;
1388 w->sb.armed = ARM_NONE; 1287 w->sb.armed = ARM_NONE;
1288 w->sb.forced_scroll = FORCED_SCROLL_NONE;
1389 1289
1390 if (w->sb.shadowThickness > 5) w->sb.shadowThickness = 5; 1290 if (w->sb.shadowThickness > 5) w->sb.shadowThickness = 5;
1391 1291
1392 w->sb.grayPixmap = 1292 w->sb.grayPixmap =
1393 XCreatePixmapFromBitmapData (dpy, win, (char *) gray_bits, gray_width, 1293 XCreatePixmapFromBitmapData (dpy, win, (char *) gray_bits, gray_width,
1415 Destroy (Widget widget) 1315 Destroy (Widget widget)
1416 { 1316 {
1417 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1317 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1418 Display *dpy = XtDisplay ((Widget) w); 1318 Display *dpy = XtDisplay ((Widget) w);
1419 1319
1420 DBUG (fprintf (stderr, "Destroy\n"));
1421
1422 XtReleaseGC (widget, w->sb.bottomShadowGC); 1320 XtReleaseGC (widget, w->sb.bottomShadowGC);
1423 XtReleaseGC (widget, w->sb.topShadowGC); 1321 XtReleaseGC (widget, w->sb.topShadowGC);
1424 XtReleaseGC (widget, w->sb.backgroundGC); 1322 XtReleaseGC (widget, w->sb.backgroundGC);
1425 1323
1426 XFreePixmap (dpy, w->sb.grayPixmap); 1324 XFreePixmap (dpy, w->sb.grayPixmap);
1427 1325
1428 if (w->sb.timerActive) 1326 if (w->sb.timerActive)
1429 XtRemoveTimeOut (w->sb.timerId); 1327 {
1328 XtRemoveTimeOut (w->sb.timerId);
1329 w->sb.timerActive = False; /* Should be a no-op, but you never know */
1330 }
1430 } 1331 }
1431 1332
1432 static void 1333 static void
1433 Realize (Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr) 1334 Realize (Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr)
1434 { 1335 {
1435 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1336 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1436 Display *dpy = XtDisplay ((Widget) w); 1337 Display *dpy = XtDisplay ((Widget) w);
1437 Window win; 1338 Window win;
1438 XSetWindowAttributes win_attr; 1339 XSetWindowAttributes win_attr;
1439 1340
1440 DBUG (fprintf (stderr, "Realize\n"));
1441
1442 (*coreClassRec.core_class.realize)(widget, valuemask, attr); 1341 (*coreClassRec.core_class.realize)(widget, valuemask, attr);
1443 1342
1444 win = XtWindow ((Widget) w); 1343 win = XtWindow ((Widget) w);
1445 1344
1446 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1345 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
1447 1346
1448 XSetWindowBackground (dpy, win, w->sb.troughColor); 1347 XSetWindowBackground (dpy, win, w->sb.troughColor);
1449 1348
1450 /* Change bit gravity so widget is not cleared on resize */ 1349 /* Change bit gravity so widget is not cleared on resize */
1451 win_attr.bit_gravity = NorthWestGravity; 1350 win_attr.bit_gravity = NorthWestGravity;
1452 XChangeWindowAttributes (dpy, win, CWBitGravity , &win_attr); 1351 XChangeWindowAttributes (dpy, win, CWBitGravity , &win_attr);
1453 1352
1454 } 1353 }
1455 1354
1456 static void 1355 static void
1464 { 1363 {
1465 DBUG (fprintf (stderr, "Resize = %08lx\n", w)); 1364 DBUG (fprintf (stderr, "Resize = %08lx\n", w));
1466 1365
1467 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1366 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
1468 1367
1469 /*redraw_everything(w, NULL, True);*/ 1368 /* redraw_everything (w, NULL, True); */
1470 1369
1471 w->sb.fullRedrawNext = True; 1370 w->sb.fullRedrawNext = True;
1472 /* Force expose event */ 1371 /* Force expose event */
1473 XClearArea (dpy, win, widget_x(w), widget_y(w), 1, 1, True); 1372 XClearArea (dpy, win, widget_x (w), widget_y (w), 1, 1, True);
1373 }
1374
1375 if (w->sb.timerActive)
1376 {
1377 XtRemoveTimeOut (w->sb.timerId);
1378 w->sb.timerActive = False;
1474 } 1379 }
1475 } 1380 }
1476 1381
1477 static void 1382 static void
1478 Redisplay (Widget widget, XEvent *event, Region region) 1383 Redisplay (Widget widget, XEvent *event, Region region)
1482 DBUG (fprintf (stderr, "Redisplay = %08lx\n", w)); 1387 DBUG (fprintf (stderr, "Redisplay = %08lx\n", w));
1483 1388
1484 if (XtIsRealized (widget)) 1389 if (XtIsRealized (widget))
1485 { 1390 {
1486 if (w->sb.fullRedrawNext) 1391 if (w->sb.fullRedrawNext)
1487 { 1392 redraw_everything (w, NULL, True);
1488 redraw_everything (w, NULL, True);
1489 }
1490 else 1393 else
1491 { 1394 redraw_everything (w, region, False);
1492 redraw_everything (w, region, False);
1493 }
1494 w->sb.fullRedrawNext = False; 1395 w->sb.fullRedrawNext = False;
1495 } 1396 }
1496 } 1397 }
1497 1398
1498 static Boolean 1399 static Boolean
1540 w->sb.bottomShadowPixmap); 1441 w->sb.bottomShadowPixmap);
1541 do_redisplay = True; 1442 do_redisplay = True;
1542 } 1443 }
1543 1444
1544 if (cur->sb.orientation != w->sb.orientation) 1445 if (cur->sb.orientation != w->sb.orientation)
1545 { 1446 do_redisplay = True;
1546 do_redisplay = True;
1547 }
1548 1447
1549 1448
1550 if (cur->sb.minimum != w->sb.minimum || 1449 if (cur->sb.minimum != w->sb.minimum ||
1551 cur->sb.maximum != w->sb.maximum || 1450 cur->sb.maximum != w->sb.maximum ||
1552 cur->sb.sliderSize != w->sb.sliderSize || 1451 cur->sb.sliderSize != w->sb.sliderSize ||
1556 { 1455 {
1557 verify_values (w); 1456 verify_values (w);
1558 if (XtIsRealized ((Widget) w)) 1457 if (XtIsRealized ((Widget) w))
1559 { 1458 {
1560 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1459 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
1561 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1460 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1562 } 1461 }
1563 } 1462 }
1564 1463
1565 if (w->sb.shadowThickness > 5) w->sb.shadowThickness = 5; 1464 if (w->sb.shadowThickness > 5) w->sb.shadowThickness = 5;
1566 1465
1585 void 1484 void
1586 XlwScrollBarSetValues (Widget widget, int value, int sliderSize, 1485 XlwScrollBarSetValues (Widget widget, int value, int sliderSize,
1587 int increment, int pageIncrement, Boolean notify) 1486 int increment, int pageIncrement, Boolean notify)
1588 { 1487 {
1589 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1488 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1590 int last_value;
1591 1489
1592 if (w && XtClass ((Widget) w) == xlwScrollBarWidgetClass && 1490 if (w && XtClass ((Widget) w) == xlwScrollBarWidgetClass &&
1593 (w->sb.value != value || 1491 (w->sb.value != value ||
1594 w->sb.sliderSize != sliderSize || 1492 w->sb.sliderSize != sliderSize ||
1595 w->sb.increment != increment || 1493 w->sb.increment != increment ||
1596 w->sb.pageIncrement != pageIncrement)) 1494 w->sb.pageIncrement != pageIncrement))
1597 { 1495 {
1496 int last_value = w->sb.value;
1497
1598 w->sb.value = value; 1498 w->sb.value = value;
1599 w->sb.sliderSize = sliderSize; 1499 w->sb.sliderSize = sliderSize;
1600 w->sb.increment = increment; 1500 w->sb.increment = increment;
1601 w->sb.pageIncrement = pageIncrement; 1501 w->sb.pageIncrement = pageIncrement;
1602 1502
1603 verify_values (w); 1503 verify_values (w);
1604 1504
1605 if (XtIsRealized (widget)) 1505 if (XtIsRealized (widget))
1606 { 1506 {
1607 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1507 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
1608 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1508 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1609
1610 last_value = w->sb.value;
1611 w->sb.value = value_from_pixel (w, w->sb.above);
1612 verify_values (w);
1613 1509
1614 if (w->sb.value != last_value && notify) 1510 if (w->sb.value != last_value && notify)
1615 { 1511 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, 0, NULL);
1616 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, 0, NULL); 1512 }
1617 } 1513 }
1618 } 1514 }
1619 } 1515
1620 } 1516 /*-------------------------- Action Functions ---------------------------*/
1621
1622 /************************************************************************
1623 **
1624 ** Action functions
1625 **
1626 */
1627 1517
1628 static void 1518 static void
1629 timer (XtPointer data, XtIntervalId *id) 1519 timer (XtPointer data, XtIntervalId *id)
1630 { 1520 {
1631 XlwScrollBarWidget w = (XlwScrollBarWidget) data; 1521 XlwScrollBarWidget w = (XlwScrollBarWidget) data;
1632 int reason, last_value;
1633
1634 w->sb.timerActive = False; 1522 w->sb.timerActive = False;
1635 1523
1636 if (w->sb.armed != ARM_NONE) 1524 if (w->sb.armed != ARM_NONE)
1637 { 1525 {
1638 last_value = w->sb.value; 1526 int last_value = w->sb.value;
1639 reason = XmCR_NONE; 1527 int reason = XmCR_NONE;
1640 1528
1641 switch (w->sb.armed) 1529 switch (w->sb.armed)
1642 { 1530 {
1643 case ARM_PAGEUP: 1531 case ARM_PAGEUP:
1644 w->sb.value = safe_subtract (w->sb.value, w->sb.pageIncrement); 1532 decrement_value (w, w->sb.pageIncrement);
1645 reason = XmCR_PAGE_DECREMENT; 1533 reason = XmCR_PAGE_DECREMENT;
1646 break; 1534 break;
1647 case ARM_PAGEDOWN: 1535 case ARM_PAGEDOWN:
1648 w->sb.value = safe_add (w->sb.value, w->sb.pageIncrement); 1536 increment_value (w, w->sb.pageIncrement);
1649 reason = XmCR_PAGE_INCREMENT; 1537 reason = XmCR_PAGE_INCREMENT;
1650 break; 1538 break;
1651 case ARM_UP: 1539 case ARM_UP:
1652 w->sb.value = safe_subtract (w->sb.value, w->sb.increment); 1540 decrement_value (w, w->sb.increment);
1653 reason = XmCR_DECREMENT; 1541 reason = XmCR_DECREMENT;
1654 break; 1542 break;
1655 case ARM_DOWN: 1543 case ARM_DOWN:
1656 w->sb.value = safe_add (w->sb.value, w->sb.increment); 1544 increment_value (w, w->sb.increment);
1657 reason = XmCR_INCREMENT; 1545 reason = XmCR_INCREMENT;
1658 break; 1546 break;
1659 } 1547 }
1660 1548
1661 verify_values (w); 1549 verify_values (w);
1662 1550
1663 if (last_value != w->sb.value) 1551 if (last_value != w->sb.value)
1664 { 1552 {
1665 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1553 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
1666 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1554 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1667 1555
1668 call_callbacks (w, reason, w->sb.value, 0, NULL); 1556 call_callbacks (w, reason, w->sb.value, 0, NULL);
1669 1557
1670 w->sb.timerId = 1558 w->sb.timerId =
1671 XtAppAddTimeOut (XtWidgetToApplicationContext ((Widget) w), 1559 XtAppAddTimeOut (XtWidgetToApplicationContext ((Widget) w),
1674 w->sb.timerActive = True; 1562 w->sb.timerActive = True;
1675 } 1563 }
1676 } 1564 }
1677 } 1565 }
1678 1566
1679 static int 1567 static button_where
1680 what_button (XlwScrollBarWidget w, int mouse_x, int mouse_y) 1568 what_button (XlwScrollBarWidget w, int mouse_x, int mouse_y)
1681 { 1569 {
1682 int x, y, width, height, arrow_height_top, arrow_height_bottom; 1570 int width = widget_w (w);
1683 int where; 1571 int height = widget_h (w);
1684 1572 int arrow_height = arrow_h (w);
1685 x = widget_x (w); 1573
1686 y = widget_y (w); 1574 mouse_x -= widget_x (w);
1687 width = widget_w (w); 1575 mouse_y -= widget_y (w);
1688 height = widget_h (w); 1576
1689 1577 if (mouse_x < 0 || mouse_x >= width ||
1690 #if 0 1578 mouse_y < 0 || mouse_y >= height)
1691 arrow_height = w->sb.showArrows ? arrow_h (w) : 0; 1579 return BUTTON_NONE;
1692 #endif 1580
1693 if (w->sb.showArrows) 1581 if (w->sb.showArrows)
1694 { 1582 {
1583 if (mouse_y >= (height -= arrow_height))
1584 return BUTTON_DOWN_ARROW;
1585
1695 if (arrow_same_end (w)) 1586 if (arrow_same_end (w))
1696 { 1587 {
1697 arrow_height_top = 0; 1588 if (mouse_y >= (height -= arrow_height))
1698 arrow_height_bottom = 2 * arrow_h (w); 1589 return BUTTON_UP_ARROW;
1699 } 1590 }
1700 else 1591 else
1701 { 1592 if ( (mouse_y -= arrow_height) < 0)
1702 arrow_height_top = arrow_height_bottom = arrow_h (w); 1593 return BUTTON_UP_ARROW;
1703 } 1594 }
1704 } 1595
1705 else 1596 if ( (mouse_y -= w->sb.above) < 0)
1706 { 1597 return BUTTON_TROUGH_ABOVE;
1707 arrow_height_top = arrow_height_bottom = 0; 1598
1708 } 1599 if ( (mouse_y -= w->sb.ss) < 0)
1709 1600 return BUTTON_SLIDER;
1710 where = BUTTON_NONE; 1601
1711 1602 return BUTTON_TROUGH_BELOW;
1712 if (mouse_x > x && mouse_x < (x + width)) 1603 }
1713 {
1714 if (mouse_y > (y + arrow_height_top) &&
1715 mouse_y < (y + height - arrow_height_bottom))
1716 {
1717 if (mouse_y < (y + w->sb.above + arrow_height_top))
1718 {
1719 where = BUTTON_TROUGH_ABOVE;
1720 }
1721 else if (mouse_y > (y + w->sb.above + w->sb.ss + arrow_height_top))
1722 {
1723 where = BUTTON_TROUGH_BELOW;
1724 }
1725 else
1726 {
1727 where = BUTTON_KNOB;
1728 }
1729 }
1730 else if (arrow_same_end (w))
1731 {
1732 if (mouse_y > (y + height - arrow_height_bottom + 1) &&
1733 mouse_y < (y + height))
1734 {
1735 if (mouse_y < (y + height - arrow_height_bottom/2))
1736 {
1737 where = BUTTON_UP_ARROW;
1738 }
1739 else
1740 {
1741 where = BUTTON_DOWN_ARROW;
1742 }
1743 }
1744 }
1745 else
1746 {
1747 if (mouse_y > y && mouse_y < (y + arrow_height_top))
1748 {
1749 where = BUTTON_UP_ARROW;
1750 }
1751 else if (mouse_y > (y + height - arrow_height_bottom + 1) &&
1752 mouse_y < (y + height))
1753 {
1754 where = BUTTON_DOWN_ARROW;
1755 }
1756 }
1757 }
1758 #if 0
1759 if (mouse_x > x && mouse_x < (x + width))
1760 {
1761 if (mouse_y > (y + arrow_height) && mouse_y < (y + height - arrow_height))
1762 {
1763 if (mouse_y < (y+w->sb.above+arrow_height))
1764 {
1765 where = BUTTON_TROUGH_ABOVE;
1766 }
1767 else if (mouse_y > (y + w->sb.above + w->sb.ss + arrow_height))
1768 {
1769 where = BUTTON_TROUGH_BELOW;
1770 }
1771 else
1772 {
1773 where = BUTTON_KNOB;
1774 }
1775 }
1776 else if (mouse_y > y && mouse_y < (y + arrow_height))
1777 {
1778 where = BUTTON_UP_ARROW;
1779 }
1780 else if (mouse_y > (y + height - arrow_height + 1) &&
1781 mouse_y < (y + height))
1782 {
1783 where = BUTTON_DOWN_ARROW;
1784 }
1785 }
1786 #endif
1787 return where;
1788 }
1789
1790 #define FORCED_SCROLL_NONE 0
1791 #define FORCED_SCROLL_DOWNRIGHT 1
1792 #define FORCED_SCROLL_UPLEFT 2
1793
1794 int forced_scroll_flag = FORCED_SCROLL_NONE;
1795 1604
1796 static void 1605 static void
1797 PageDownOrRight (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1606 PageDownOrRight (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
1798 { 1607 {
1799 forced_scroll_flag = FORCED_SCROLL_DOWNRIGHT; 1608 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1609 w->sb.forced_scroll = FORCED_SCROLL_DOWNRIGHT;
1800 Select (widget, event, parms, num_parms); 1610 Select (widget, event, parms, num_parms);
1801 forced_scroll_flag = FORCED_SCROLL_NONE; 1611 w->sb.forced_scroll = FORCED_SCROLL_NONE;
1802 } 1612 }
1803 1613
1804 static void 1614 static void
1805 PageUpOrLeft (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1615 PageUpOrLeft (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
1806 { 1616 {
1807 forced_scroll_flag = FORCED_SCROLL_UPLEFT; 1617 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1618 w->sb.forced_scroll = FORCED_SCROLL_UPLEFT;
1808 Select (widget, event, parms, num_parms); 1619 Select (widget, event, parms, num_parms);
1809 forced_scroll_flag = FORCED_SCROLL_NONE; 1620 w->sb.forced_scroll = FORCED_SCROLL_NONE;
1810 } 1621 }
1811 1622
1812 static void 1623 static void
1813 Select (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1624 Select (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
1814 { 1625 {
1815 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1626 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1816 int mouse_x, mouse_y; 1627 button_where sb_button;
1817 int reason, last_value; 1628
1818 int sb_button; 1629 int mouse_x = event_x (w, event);
1819 1630 int mouse_y = event_y (w, event);
1820 DBUG (fprintf (stderr, "Select:\n")); 1631
1821 1632 int last_value = w->sb.savedValue = w->sb.value;
1822 mouse_x = event_x (w, event); 1633 int reason = XmCR_NONE;
1823 mouse_y = event_y (w, event);
1824
1825 w->sb.savedValue = w->sb.value;
1826
1827 last_value = w->sb.value;
1828 reason = XmCR_NONE;
1829 1634
1830 XtGrabKeyboard ((Widget) w, False, GrabModeAsync, GrabModeAsync, 1635 XtGrabKeyboard ((Widget) w, False, GrabModeAsync, GrabModeAsync,
1831 event->xbutton.time); 1636 event->xbutton.time);
1832 1637
1833 sb_button = what_button (w, mouse_x, mouse_y); 1638 sb_button = what_button (w, mouse_x, mouse_y);
1834 1639
1835 if (forced_scroll_flag != FORCED_SCROLL_NONE) 1640 if (w->sb.forced_scroll != FORCED_SCROLL_NONE)
1836 { 1641 {
1837 switch (sb_button) 1642 switch (sb_button)
1838 { 1643 {
1839 case BUTTON_TROUGH_ABOVE: 1644 case BUTTON_TROUGH_ABOVE:
1840 case BUTTON_TROUGH_BELOW: 1645 case BUTTON_TROUGH_BELOW:
1841 case BUTTON_KNOB: 1646 case BUTTON_SLIDER:
1842 sb_button= BUTTON_NONE; /* cause next switch to fall through */ 1647 sb_button= BUTTON_NONE; /* cause next switch to fall through */
1843 if (forced_scroll_flag == FORCED_SCROLL_UPLEFT) 1648 if (w->sb.forced_scroll == FORCED_SCROLL_UPLEFT)
1844 { 1649 {
1845 w->sb.value = safe_subtract (w->sb.value, w->sb.pageIncrement); 1650 decrement_value (w, w->sb.pageIncrement);
1846 w->sb.armed = ARM_PAGEUP; 1651 w->sb.armed = ARM_PAGEUP;
1847 reason = XmCR_PAGE_DECREMENT; 1652 reason = XmCR_PAGE_DECREMENT;
1848 break; 1653 break;
1849 } 1654 }
1850 else if (forced_scroll_flag == FORCED_SCROLL_DOWNRIGHT) 1655 else if (w->sb.forced_scroll == FORCED_SCROLL_DOWNRIGHT)
1851 { 1656 {
1852 w->sb.value = safe_add (w->sb.value, w->sb.pageIncrement); 1657 increment_value (w, w->sb.pageIncrement);
1853 w->sb.armed = ARM_PAGEDOWN; 1658 w->sb.armed = ARM_PAGEDOWN;
1854 reason = XmCR_PAGE_INCREMENT; 1659 reason = XmCR_PAGE_INCREMENT;
1855 break; 1660 break;
1856 } 1661 }
1857 abort(); 1662 abort();
1859 } 1664 }
1860 1665
1861 switch (sb_button) 1666 switch (sb_button)
1862 { 1667 {
1863 case BUTTON_TROUGH_ABOVE: 1668 case BUTTON_TROUGH_ABOVE:
1864 w->sb.value = safe_subtract (w->sb.value, w->sb.pageIncrement); 1669 decrement_value (w, w->sb.pageIncrement);
1865 w->sb.armed = ARM_PAGEUP; 1670 w->sb.armed = ARM_PAGEUP;
1866 reason = XmCR_PAGE_DECREMENT; 1671 reason = XmCR_PAGE_DECREMENT;
1867 break; 1672 break;
1868 case BUTTON_TROUGH_BELOW: 1673 case BUTTON_TROUGH_BELOW:
1869 w->sb.value = safe_add (w->sb.value, w->sb.pageIncrement); 1674 increment_value (w, w->sb.pageIncrement);
1870 w->sb.armed = ARM_PAGEDOWN; 1675 w->sb.armed = ARM_PAGEDOWN;
1871 reason = XmCR_PAGE_INCREMENT; 1676 reason = XmCR_PAGE_INCREMENT;
1872 break; 1677 break;
1873 case BUTTON_KNOB: 1678 case BUTTON_SLIDER:
1874 w->sb.lastY = mouse_y; 1679 w->sb.lastY = mouse_y;
1875 w->sb.armed = ARM_KNOB; 1680 w->sb.armed = ARM_SLIDER;
1876 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1681 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1877 break; 1682 break;
1878 case BUTTON_UP_ARROW: 1683 case BUTTON_UP_ARROW:
1879 if (event->xbutton.state & ControlMask) 1684 if (event->xbutton.state & ControlMask)
1880 { 1685 {
1881 w->sb.value = INT_MIN; 1686 w->sb.value = w->sb.minimum;
1882 w->sb.armed = ARM_UP;
1883 reason = XmCR_TO_TOP; 1687 reason = XmCR_TO_TOP;
1884 } 1688 }
1885 else 1689 else
1886 { 1690 {
1887 w->sb.value = safe_subtract (w->sb.value, w->sb.increment); 1691 decrement_value (w, w->sb.increment);
1888 w->sb.armed = ARM_UP;
1889 reason = XmCR_DECREMENT; 1692 reason = XmCR_DECREMENT;
1890 } 1693 }
1694 w->sb.armed = ARM_UP;
1891 redraw_up_arrow (w, True, False); 1695 redraw_up_arrow (w, True, False);
1892 break; 1696 break;
1893 case BUTTON_DOWN_ARROW: 1697 case BUTTON_DOWN_ARROW:
1894 if (event->xbutton.state & ControlMask) 1698 if (event->xbutton.state & ControlMask)
1895 { 1699 {
1896 w->sb.value = INT_MAX; 1700 w->sb.value = w->sb.maximum;
1897 w->sb.armed = ARM_DOWN;
1898 reason = XmCR_TO_BOTTOM; 1701 reason = XmCR_TO_BOTTOM;
1899 } 1702 }
1900 else 1703 else
1901 { 1704 {
1902 w->sb.value = safe_add (w->sb.value, w->sb.increment); 1705 increment_value (w, w->sb.increment);
1903 w->sb.armed = ARM_DOWN;
1904 reason = XmCR_INCREMENT; 1706 reason = XmCR_INCREMENT;
1905 } 1707 }
1708 w->sb.armed = ARM_DOWN;
1906 redraw_down_arrow (w, True, False); 1709 redraw_down_arrow (w, True, False);
1907 break; 1710 break;
1908 } 1711 }
1909 1712
1910 verify_values (w); 1713 verify_values (w);
1911 1714
1912 if (last_value != w->sb.value) 1715 if (last_value != w->sb.value)
1913 { 1716 {
1914 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1717 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
1915 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1718 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1916 1719
1917 call_callbacks (w, reason, w->sb.value, mouse_y, event); 1720 call_callbacks (w, reason, w->sb.value, mouse_y, event);
1918 1721
1919 if (w->sb.timerActive) 1722 if (w->sb.timerActive)
1920 XtRemoveTimeOut (w->sb.timerId); 1723 XtRemoveTimeOut (w->sb.timerId);
1931 1734
1932 static void 1735 static void
1933 Drag (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1736 Drag (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
1934 { 1737 {
1935 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1738 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
1936 int diff; 1739
1937 int height, mouse_y; 1740 if (w->sb.armed == ARM_SLIDER)
1938 int last_value, last_above; 1741 {
1939 1742 int mouse_y = event_y (w, event);
1940 DBUG (fprintf (stderr, "Drag:\n")); 1743 int diff = mouse_y - w->sb.lastY;
1941 1744
1942 if (w->sb.armed == ARM_KNOB) 1745 if (diff < -(w->sb.above)) /* up */
1943 { 1746 {
1944 height = widget_h (w); 1747 mouse_y -= (diff + w->sb.above);
1945 if (w->sb.showArrows) height -= (2 * arrow_h (w)); 1748 diff = -(w->sb.above);
1946 1749 }
1947 mouse_y = event_y (w, event); 1750 else if (diff > w->sb.below) /* down */
1948 1751 {
1949 diff = mouse_y - w->sb.lastY; 1752 mouse_y -= (diff - w->sb.below);
1950 1753 diff = w->sb.below;
1951 last_above = w->sb.above; 1754 }
1952 last_value = w->sb.value; 1755
1953 1756 if (diff)
1954 if (diff < 0) 1757 {
1955 { 1758 w->sb.above += diff;
1956 /* up */
1957 w->sb.above -= (-diff);
1958 if (w->sb.above < 0)
1959 {
1960 mouse_y = (mouse_y - w->sb.above);
1961 w->sb.above = 0;
1962 diff = 0;
1963 w->sb.below = height - w->sb.ss;
1964 }
1965 w->sb.below -= diff; 1759 w->sb.below -= diff;
1966 CHECK (w); 1760
1967 } 1761 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
1968 else if (diff > 0)
1969 {
1970 /* down */
1971 w->sb.above += diff;
1972 if (w->sb.above + w->sb.ss > height)
1973 {
1974 mouse_y = height + (mouse_y - (w->sb.above + w->sb.ss));
1975 w->sb.above = height - w->sb.ss;
1976 diff = 0;
1977 w->sb.below = 0;
1978 }
1979 w->sb.below -= diff;
1980 CHECK (w);
1981 }
1982
1983 if (last_above != w->sb.above)
1984 {
1985 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below);
1986 1762
1987 w->sb.lastY = mouse_y; 1763 w->sb.lastY = mouse_y;
1988 1764
1989 w->sb.value = value_from_pixel (w, w->sb.above); 1765 w->sb.value = value_from_pixel (w, w->sb.above);
1990 verify_values (w); 1766 verify_values (w);
1991 CHECK (w); 1767 CHECK (w);
1992 1768
1993 if (w->sb.value != last_value) 1769 call_callbacks (w, XmCR_DRAG, w->sb.value, event_y (w, event), event);
1994 call_callbacks (w, XmCR_DRAG, w->sb.value, event_y (w, event), event);
1995 } 1770 }
1996 } 1771 }
1997 CHECK (w); 1772 CHECK (w);
1998 } 1773 }
1999 1774
2000 static void 1775 static void
2001 Release (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1776 Release (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
2002 { 1777 {
2003 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1778 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
2004 1779
2005 DBUG (fprintf (stderr, "EndDrag:\n"));
2006
2007 switch (w->sb.armed) 1780 switch (w->sb.armed)
2008 { 1781 {
2009 case ARM_KNOB: 1782 case ARM_SLIDER:
2010 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, event_y (w, event), event); 1783 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, event_y (w, event), event);
2011 w->sb.armed = ARM_NONE; 1784 w->sb.armed = ARM_NONE;
2012 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1785 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
2013 break; 1786 break;
2014 case ARM_UP: 1787 case ARM_UP:
2015 redraw_up_arrow (w, False, False); 1788 redraw_up_arrow (w, False, False);
2016 break; 1789 break;
2017 case ARM_DOWN: 1790 case ARM_DOWN:
2026 1799
2027 static void 1800 static void
2028 Jump (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1801 Jump (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
2029 { 1802 {
2030 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1803 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
2031 int x, y, width, height, mouse_x, mouse_y; 1804 int last_value;
2032 int arrow_height; 1805
2033 int last_above, last_value; 1806 int mouse_x = event_x (w, event);
2034 1807 int mouse_y = event_y (w, event);
2035 DBUG (fprintf (stderr, "Jump:\n")); 1808
2036 1809 int scroll_region_y = widget_y (w);
2037 x = widget_x (w); 1810 int scroll_region_h = widget_h (w);
2038 y = widget_y (w);
2039 width = widget_w (w);
2040 height = widget_h (w);
2041 1811
2042 mouse_x = event_x (w, event); 1812 if (w->sb.showArrows)
2043 mouse_y = event_y (w, event); 1813 {
2044 1814 int arrow_height = arrow_h (w);
2045 arrow_height = w->sb.showArrows ? arrow_h (w) : 0; 1815 scroll_region_h -= 2 * arrow_height;
1816 if (!arrow_same_end (w))
1817 scroll_region_y += arrow_height;
1818 }
2046 1819
2047 XtGrabKeyboard ((Widget) w, False, GrabModeAsync, GrabModeAsync, 1820 XtGrabKeyboard ((Widget) w, False, GrabModeAsync, GrabModeAsync,
2048 event->xbutton.time); 1821 event->xbutton.time);
2049 1822
2050 switch (what_button (w, mouse_x, mouse_y)) 1823 switch (what_button (w, mouse_x, mouse_y))
2051 { 1824 {
2052 case BUTTON_TROUGH_ABOVE: 1825 case BUTTON_TROUGH_ABOVE:
2053 case BUTTON_TROUGH_BELOW: 1826 case BUTTON_TROUGH_BELOW:
2054 case BUTTON_KNOB: 1827 case BUTTON_SLIDER:
2055 w->sb.savedValue = w->sb.value; 1828 w->sb.savedValue = w->sb.value;
2056 1829
2057 height -= (2*arrow_height);
2058 y += arrow_height;
2059
2060 last_above = w->sb.above;
2061 last_value = w->sb.value; 1830 last_value = w->sb.value;
2062 1831
2063 w->sb.armed = ARM_KNOB; 1832 w->sb.above = mouse_y - (w->sb.ss / 2) - scroll_region_y;
2064 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below);
2065
2066 w->sb.above = mouse_y - (w->sb.ss / 2) - arrow_height;
2067 if (w->sb.above < 0) 1833 if (w->sb.above < 0)
2068 { 1834 w->sb.above = 0;
2069 w->sb.above = 0; 1835 else if (w->sb.above + w->sb.ss > scroll_region_h)
2070 } 1836 w->sb.above = scroll_region_h - w->sb.ss;
2071 else if (w->sb.above + w->sb.ss > height) 1837
2072 { 1838 w->sb.below = scroll_region_h - w->sb.ss - w->sb.above;
2073 w->sb.above = height - w->sb.ss; 1839
2074 } 1840 w->sb.armed = ARM_SLIDER;
2075 w->sb.below = (height - (w->sb.ss + w->sb.above)); 1841 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
2076 1842
2077 if (last_above != w->sb.above) 1843 w->sb.value = value_from_pixel (w, w->sb.above);
2078 { 1844 verify_values (w);
2079 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1845 CHECK (w);
2080 1846
2081 w->sb.value = value_from_pixel (w, w->sb.above); 1847 w->sb.lastY = mouse_y;
2082 verify_values (w); 1848
2083 CHECK (w); 1849 if (w->sb.value != last_value)
2084 1850 call_callbacks (w, XmCR_DRAG, w->sb.value, mouse_y, event);
2085 w->sb.lastY = mouse_y; 1851
2086 w->sb.lastY = w->sb.above + arrow_height + (w->sb.ss / 2);
2087
2088 if (w->sb.value != last_value)
2089 {
2090 call_callbacks (w, XmCR_DRAG, w->sb.value, event_y (w, event), event);
2091 }
2092 }
2093 break; 1852 break;
2094 } 1853 }
2095 CHECK (w); 1854 CHECK (w);
2096 } 1855 }
2097 1856
2098 static void 1857 static void
2099 Abort (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) 1858 Abort (Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
2100 { 1859 {
2101 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; 1860 XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
2102 1861
2103 DBUG (fprintf (stderr, "Abort:\n"));
2104
2105 if (w->sb.armed != ARM_NONE) 1862 if (w->sb.armed != ARM_NONE)
2106 { 1863 {
2107 if (w->sb.value != w->sb.savedValue) 1864 if (w->sb.value != w->sb.savedValue)
2108 { 1865 {
2109 w->sb.value = w->sb.savedValue; 1866 w->sb.value = w->sb.savedValue;
2110 1867
2111 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); 1868 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below);
2112 draw_knob (w, w->sb.above, w->sb.ss, w->sb.below); 1869 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below);
2113 1870
2114 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, 1871 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value,
2115 event_y (w, event), event); 1872 event_y (w, event), event);
2116 } 1873 }
2117 1874