Mercurial > hg > xemacs-beta
annotate lwlib/xlwscrollbar.c @ 4709:db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
are missing. This is done with Bill Perry's stated permission, in private
email to me.
author | Jerry James <james@xemacs.org> |
---|---|
date | Mon, 05 Oct 2009 11:08:59 -0600 |
parents | 726060ee587c |
children | ade4c7e2c6cb |
rev | line source |
---|---|
428 | 1 /* Implements a lightweight scrollbar widget. |
2 Copyright (C) 1992, 1993, 1994 Lucid, Inc. | |
3 Copyright (C) 1997 Sun Microsystems, Inc. | |
4 | |
5 This file is part of the Lucid Widget Library. | |
6 | |
7 The Lucid Widget Library is free software; you can redistribute it and/or | |
8 modify it under the terms of the GNU General Public License as published by | |
9 the Free Software Foundation; either version 2, or (at your option) | |
10 any later version. | |
11 | |
12 The Lucid Widget Library is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Created by Douglas Keller <dkeller@vnet.ibm.com> */ | |
23 /* Lots of hacking by Martin Buchholz */ | |
24 | |
25 /* | |
26 * Athena-style scrollbar button bindings added on Sun Dec 24 22:03:57 1995 | |
27 * by Jonathan Stigelman <Stig@hackvan.com>... Ho ho ho! | |
28 * | |
1389 | 29 * To use them, put this resource in your .Xresources |
428 | 30 * |
31 * Emacs*XlwScrollBar.translations: #override \n\ | |
32 * <Btn1Down>: PageDownOrRight() \n\ | |
766 | 33 * <Btn3Down>: PageUpOrLeft() \n\ |
34 * <Btn3Up>: Release() | |
428 | 35 * |
36 */ | |
37 | |
38 /* | |
39 * Resources Supported: | |
40 * XmNforeground | |
41 * XmNbackground | |
42 * XmNtopShadowColor | |
43 * XmNtopShadowPixmap | |
44 * XmNbottomShadowColor | |
45 * XmNbottomShadowPixmap | |
46 * XmNtroughColor | |
47 * XmNshadowThickness | |
48 * XmNshowArrows | |
49 * XmNorientation | |
50 * XmNborderWidth | |
51 * | |
52 * XmNminimum | |
53 * XmNmaximum | |
54 * XmNvalue | |
55 * XmNincrement | |
56 * XmNpageIncrement | |
57 * | |
58 * XmNvalueChangedCallback | |
59 * XmNincrementCallback | |
60 * XmNdecrementCallback | |
61 * XmNpageIncrementCallback | |
62 * XmNpageDecrementCallback | |
63 * XmNtoTopCallback | |
64 * XmNtoBottomCallback | |
65 * XmNdragCallback | |
66 * | |
67 * XmNsliderStyle - values can be: "plain" or "dimple" | |
68 * XmNarrowPosition - values can be: "opposite" or "same" | |
69 * | |
70 */ | |
71 | |
72 #include <config.h> | |
73 #include <stdio.h> | |
74 #include <stdlib.h> | |
75 #include <limits.h> | |
76 | |
77 #include <X11/IntrinsicP.h> | |
78 #include <X11/StringDefs.h> | |
79 #include <X11/bitmaps/gray> | |
80 | |
3094 | 81 #include "lwlib-colors.h" |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
82 #include "xt-wrappers.h" |
3094 | 83 |
428 | 84 #include "xlwscrollbarP.h" |
85 #include "xlwscrollbar.h" | |
86 | |
87 #ifdef USE_DEBUG_MALLOC | |
88 #include <dmalloc.h> | |
89 #endif | |
90 | |
91 #define DBUG(x) | |
92 | |
93 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ | |
94 ? ((unsigned long) (x)) : ((unsigned long) (y))) | |
95 | |
96 #define VERT(w) ((w)->sb.orientation == XmVERTICAL) | |
97 | |
98 #define SS_MIN 8 | |
99 | |
100 typedef enum | |
101 { | |
102 BUTTON_NONE, | |
103 BUTTON_SLIDER, | |
104 BUTTON_UP_ARROW, | |
105 BUTTON_DOWN_ARROW, | |
106 BUTTON_TROUGH_ABOVE, | |
107 BUTTON_TROUGH_BELOW | |
108 } button_where; | |
109 | |
110 typedef enum | |
111 { | |
112 SLIDER_PLAIN, | |
113 SLIDER_DIMPLE | |
114 } SliderStyle; | |
115 | |
116 /*-------------------------- Resources ----------------------------------*/ | |
117 | |
118 static XtResource resources[] = { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
119 #define offset(field) XtOffset(XlwScrollBarWidget, field) |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
120 #define res(name,_class,intrepr,type,member,extrepr,value) \ |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
121 Xt_RESOURCE (name, _class, intrepr, type, offset(sb.member), extrepr, value) |
428 | 122 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
123 res (XmNforeground, XmCForeground, XtRPixel, Pixel, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
124 foreground, XtRImmediate, XtDefaultForeground), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
125 res (XmNtopShadowColor, XmCTopShadowColor, XtRPixel, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
126 Pixel, topShadowColor, XtRImmediate, ~0), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
127 res (XmNbottomShadowColor, XmCBottomShadowColor, XtRPixel, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
128 Pixel, bottomShadowColor, XtRImmediate, ~0), |
428 | 129 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
130 res (XmNtopShadowPixmap, XmCTopShadowPixmap, XtRPixmap, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
131 Pixmap, topShadowPixmap, XtRImmediate, None), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
132 res (XmNbottomShadowPixmap, XmCBottomShadowPixmap, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
133 XtRPixmap, Pixmap, bottomShadowPixmap, XtRImmediate, None), |
428 | 134 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
135 res (XmNtroughColor, XmCTroughColor, XtRPixel, Pixel, troughColor, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
136 XtRImmediate, ~0), |
428 | 137 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
138 res (XmNshadowThickness, XmCShadowThickness, XtRInt, int, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
139 shadowThickness, XtRImmediate, 2), |
428 | 140 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
141 Xt_RESOURCE (XmNborderWidth, XmCBorderWidth, XtRDimension, Dimension, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
142 offset(core.border_width), XtRImmediate, 0), |
428 | 143 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
144 res (XmNshowArrows, XmCShowArrows, XtRBoolean, Boolean, showArrows, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
145 XtRImmediate, True), |
428 | 146 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
147 res (XmNinitialDelay, XmCInitialDelay, XtRInt, int, initialDelay, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
148 XtRImmediate, 250), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
149 res (XmNrepeatDelay, XmCRepeatDelay, XtRInt, int, repeatDelay, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
150 XtRImmediate, 50), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
151 |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
152 res (XmNorientation, XmCOrientation, XtROrientation, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
153 unsigned char, orientation, XtRImmediate, XmVERTICAL), |
428 | 154 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
155 res (XmNminimum, XmCMinimum, XtRInt, int, minimum, XtRImmediate, 0), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
156 res (XmNmaximum, XmCMaximum, XtRInt, int, maximum, XtRImmediate, 100), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
157 res (XmNvalue, XmCValue, XtRInt, int, value, XtRImmediate, 0), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
158 res (XmNsliderSize, XmCSliderSize, XtRInt, int, sliderSize, XtRImmediate, 10), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
159 res (XmNincrement, XmCIncrement, XtRInt, int, increment, XtRImmediate, 1), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
160 res (XmNpageIncrement, XmCPageIncrement, XtRInt, int, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
161 pageIncrement, XtRImmediate, 10), |
428 | 162 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
163 res (XmNvalueChangedCallback, XmCValueChangedCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
164 XtRCallback, XtPointer, valueChangedCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
165 res (XmNincrementCallback, XmCIncrementCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
166 XtRCallback, XtPointer, incrementCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
167 res (XmNdecrementCallback, XmCDecrementCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
168 XtRCallback, XtPointer, decrementCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
169 res (XmNpageIncrementCallback, XmCPageIncrementCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
170 XtRCallback, XtPointer, pageIncrementCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
171 res (XmNpageDecrementCallback, XmCPageDecrementCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
172 XtRCallback, XtPointer, pageDecrementCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
173 res (XmNtoTopCallback, XmCToTopCallback, XtRCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
174 XtPointer, toTopCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
175 res (XmNtoBottomCallback, XmCToBottomCallback, XtRCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
176 XtPointer, toBottomCBL, XtRCallback, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
177 res (XmNdragCallback, XmCDragCallback, XtRCallback, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
178 XtPointer, dragCBL, XtRCallback, NULL), |
428 | 179 |
180 /* "knob" is obsolete; use "slider" instead. */ | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
181 res (XmNsliderStyle, XmCSliderStyle, XtRString, char *, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
182 sliderStyle, XtRImmediate, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
183 res (XmNknobStyle, XmCKnobStyle, XtRString, char *, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
184 knobStyle, XtRImmediate, NULL), |
428 | 185 |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
186 res (XmNarrowPosition, XmCArrowPosition, XtRString, char *, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
187 arrowPosition, XtRImmediate, NULL), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
188 #undef offset |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
189 #undef res |
428 | 190 }; |
191 | |
192 /*-------------------------- Prototypes ---------------------------------*/ | |
193 | |
194 /* Actions */ | |
195 typedef void Action(Widget w, XEvent *event, String *parms, Cardinal *num_parms); | |
196 static Action Select, PageUpOrLeft, PageDownOrRight, Drag, Release, Jump, Abort; | |
197 | |
198 /* Methods */ | |
199 static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num_args); | |
200 static Boolean SetValues(Widget current, Widget request, Widget nw, ArgList args, Cardinal *num_args); | |
201 static void Destroy(Widget widget); | |
202 static void Redisplay(Widget widget, XEvent *event, Region region); | |
203 static void Resize(Widget widget); | |
204 static void Realize(Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr); | |
205 | |
206 /* Private */ | |
207 | |
208 /*-------------------------- Actions Table ------------------------------*/ | |
209 static XtActionsRec actions[] = | |
210 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
211 { (String) "Select", Select}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
212 { (String) "PageDownOrRight", PageDownOrRight}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
213 { (String) "PageUpOrLeft", PageUpOrLeft}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
214 { (String) "Drag", Drag}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
215 { (String) "Release", Release}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
216 { (String) "Jump", Jump}, |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
217 { (String) "Abort", Abort}, |
428 | 218 }; |
219 | |
220 /*--------------------- Default Translation Table -----------------------*/ | |
221 static char default_translations[] = | |
222 "<Btn1Down>: Select()\n" | |
223 "<Btn1Motion>: Drag()\n" | |
224 "<Btn1Up>: Release()\n" | |
225 "<Btn2Down>: Jump()\n" | |
226 "<Btn2Motion>: Drag()\n" | |
227 "<Btn2Up>: Release()\n" | |
228 "<Key>Delete: Abort()" | |
229 ; | |
230 | |
231 /*------------------- Class record initialization -----------------------*/ | |
232 XlwScrollBarClassRec xlwScrollBarClassRec = { | |
233 /* core_class fields */ | |
234 { | |
235 /* superclass */ (WidgetClass) &coreClassRec, | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
236 /* class_name */ (String) "XlwScrollBar", |
428 | 237 /* widget_size */ sizeof(XlwScrollBarRec), |
238 /* class_initialize */ NULL, | |
239 /* class_part_init */ NULL, | |
240 /* class_inited */ False, | |
241 /* initialize */ Initialize, | |
242 /* initialize_hook */ NULL, | |
243 /* realize */ Realize, | |
244 /* actions */ actions, | |
245 /* num_actions */ XtNumber(actions), | |
246 /* resources */ resources, | |
247 /* num_resources */ XtNumber(resources), | |
248 /* xrm_class */ NULLQUARK, | |
249 /* compress_motion */ True, | |
250 /* compress_exposure */ XtExposeCompressMultiple, | |
251 /* compress_enterleave */ True, | |
252 /* visible_interest */ False, | |
253 /* destroy */ Destroy, | |
254 /* resize */ Resize, | |
255 /* expose */ Redisplay, | |
256 /* set_values */ SetValues, | |
257 /* set_values_hook */ NULL, | |
258 /* set_values_almost */ XtInheritSetValuesAlmost, | |
259 /* get_values_hook */ NULL, | |
260 /* accept_focus */ NULL, | |
261 /* version */ XtVersionDontCheck, | |
262 /* callback_private */ NULL, | |
263 /* tm_table */ default_translations, | |
264 /* query_geometry */ NULL, | |
265 }, | |
266 /* scrollbar_class fields */ | |
267 { | |
268 /* dummy_field */ 0, | |
269 }, | |
270 }; | |
271 | |
272 WidgetClass xlwScrollBarWidgetClass = (WidgetClass) &xlwScrollBarClassRec; | |
273 | |
274 /*-------------------------- Debug Functions ----------------------------*/ | |
275 | |
276 #ifdef SHOW_CLEAR | |
277 static void | |
278 myXClearArea(Display *dpy, Drawable d, int x, int y, int w, int h, | |
279 Boolean exp, XlwScrollBarWidget widget) | |
280 { | |
281 XFillRectangle (dpy, d, widget->sb.topShadowGC, x, y, w, h); | |
282 XSync (dpy, False); | |
283 sleep (2); | |
284 XClearArea (dpy, d, x, y, w, h, exp); | |
285 } | |
286 | |
287 #define XClearArea(dpy,win,x,y,width,height,exp) myXClearArea(dpy,win,x,y,width,height,exp,w) | |
288 #endif | |
289 | |
290 #ifdef CHECK_VALUES | |
291 static void | |
292 check(XlwScrollBarWidget w) | |
293 { | |
294 int height = widget_h (w); | |
295 if (w->sb.showArrows) | |
296 height -= (2 * arrow_h (w)); | |
297 | |
298 if ((w->sb.above + w->sb.ss + w->sb.below > height) || | |
299 (w->sb.value < w->sb.minimum) || | |
300 (w->sb.value > w->sb.maximum - w->sb.sliderSize)) | |
301 { | |
302 printf("above=%d ss=%d below=%d height=%d\n", | |
303 w->sb.above, w->sb.ss, w->sb.below, height); | |
304 printf("value=%d min=%d max=%d ss=%d max-ss=%d\n", | |
305 w->sb.value, w->sb.minimum, w->sb.maximum, | |
306 w->sb.sliderSize, w->sb.maximum - w->sb.sliderSize); | |
307 abort(); | |
308 } | |
309 } | |
310 | |
311 # define CHECK(w) check(w) | |
312 #else | |
313 # define CHECK(w) | |
314 #endif | |
315 | |
316 /*-------------------------- Static functions ---------------------------*/ | |
317 | |
318 static void | |
319 call_callbacks (XlwScrollBarWidget w, int reason, | |
320 int value, int pixel, XEvent *event) | |
321 { | |
322 XlwScrollBarCallbackStruct cbs; | |
323 Boolean called_anything; | |
324 | |
325 cbs.reason = reason; | |
326 cbs.event = event; | |
327 cbs.value = value; | |
328 cbs.pixel = pixel; | |
329 | |
330 called_anything = False; | |
331 | |
332 switch (reason) | |
333 { | |
334 case XmCR_VALUE_CHANGED: | |
335 XtCallCallbackList ((Widget) w, w->sb.valueChangedCBL, &cbs); | |
336 called_anything = True; | |
337 break; | |
338 case XmCR_INCREMENT: | |
339 if (w->sb.incrementCBL) | |
340 { | |
341 XtCallCallbackList ((Widget) w, w->sb.incrementCBL, &cbs); | |
342 called_anything = True; | |
343 } | |
344 break; | |
345 case XmCR_DECREMENT: | |
346 if (w->sb.decrementCBL) | |
347 { | |
348 XtCallCallbackList ((Widget) w, w->sb.decrementCBL, &cbs); | |
349 called_anything = True; | |
350 } | |
351 break; | |
352 case XmCR_PAGE_INCREMENT: | |
353 if (w->sb.incrementCBL) | |
354 { | |
355 XtCallCallbackList ((Widget) w, w->sb.pageIncrementCBL, &cbs); | |
356 called_anything = True; | |
357 } | |
358 break; | |
359 case XmCR_PAGE_DECREMENT: | |
360 if (w->sb.decrementCBL) | |
361 { | |
362 XtCallCallbackList ((Widget) w, w->sb.pageDecrementCBL, &cbs); | |
363 called_anything = True; | |
364 } | |
365 break; | |
366 case XmCR_TO_TOP: | |
367 if (w->sb.toTopCBL) | |
368 { | |
369 XtCallCallbackList ((Widget) w, w->sb.toTopCBL, &cbs); | |
370 called_anything = True; | |
371 } | |
372 break; | |
373 case XmCR_TO_BOTTOM: | |
374 if (w->sb.toBottomCBL) | |
375 { | |
376 XtCallCallbackList ((Widget) w, w->sb.toBottomCBL, &cbs); | |
377 called_anything = True; | |
378 } | |
379 break; | |
380 case XmCR_DRAG: | |
381 if (w->sb.dragCBL) | |
382 { | |
383 XtCallCallbackList ((Widget) w, w->sb.dragCBL, &cbs); | |
384 } | |
385 called_anything = True; /* Special Case */ | |
386 break; | |
387 } | |
388 | |
389 if (!called_anything) | |
390 { | |
391 cbs.reason = XmCR_VALUE_CHANGED; | |
392 XtCallCallbackList ((Widget) w, w->sb.valueChangedCBL, &cbs); | |
393 } | |
394 } | |
395 | |
396 /* Widget sizes minus the shadow and highlight area */ | |
397 | |
398 static int | |
399 widget_x (XlwScrollBarWidget w) | |
400 { | |
401 return w->sb.shadowThickness; | |
402 } | |
403 | |
404 static int | |
405 widget_y (XlwScrollBarWidget w) | |
406 { | |
407 return w->sb.shadowThickness; | |
408 } | |
409 | |
410 static int | |
411 widget_w (XlwScrollBarWidget w) | |
412 { | |
413 int x = w->sb.shadowThickness; | |
414 int width = (VERT (w) ? w->core.width : w->core.height) - (2 * x); | |
415 return width > 1 ? width : 1; | |
416 } | |
417 | |
418 static int | |
419 widget_h (XlwScrollBarWidget w) | |
420 { | |
421 int y = w->sb.shadowThickness; | |
422 int height = (VERT (w) ? w->core.height : w->core.width) - (2 * y); | |
423 | |
424 return height > 1 ? height : 1; | |
425 } | |
426 | |
427 static int | |
428 arrow_h (XlwScrollBarWidget w) | |
429 { | |
430 int width = widget_w (w); | |
431 int minimum_size = ((widget_h (w) - SS_MIN) / 2) - 1; | |
432 return minimum_size < width ? minimum_size : width; | |
433 } | |
434 | |
435 static int | |
436 event_x (XlwScrollBarWidget w, XEvent *event) | |
437 { | |
438 return VERT (w) ? event->xbutton.x : event->xbutton.y; | |
439 } | |
440 | |
441 static int | |
442 event_y (XlwScrollBarWidget w, XEvent *event) | |
443 { | |
444 return VERT (w) ? event->xbutton.y : event->xbutton.x; | |
445 } | |
446 | |
447 /* Safe addition and subtraction */ | |
448 static void | |
449 increment_value (XlwScrollBarWidget w, int diff) | |
450 { | |
451 w->sb.value = w->sb.maximum - diff < w->sb.value ? | |
452 w->sb.maximum : | |
453 w->sb.value + diff; | |
454 } | |
455 | |
456 static void | |
457 decrement_value (XlwScrollBarWidget w, int diff) | |
458 { | |
459 w->sb.value = w->sb.minimum + diff > w->sb.value ? | |
460 w->sb.minimum : | |
461 w->sb.value - diff; | |
462 } | |
463 | |
464 static SliderStyle | |
465 slider_style (XlwScrollBarWidget w) | |
466 { | |
467 return (w->sb.sliderStyle ? w->sb.sliderStyle[0] == 'd' : | |
468 w->sb.knobStyle ? w->sb.knobStyle[0] == 'd' : | |
469 0) ? | |
470 SLIDER_DIMPLE : | |
471 SLIDER_PLAIN; | |
472 } | |
473 | |
474 static Boolean | |
475 arrow_same_end (XlwScrollBarWidget w) | |
476 { | |
477 return w->sb.arrowPosition && w->sb.arrowPosition[0] == 's' ? True : False; | |
478 } | |
479 | |
480 /*-------------------------- GC and Pixel allocation --------------------*/ | |
481 #ifndef XmUNSPECIFIED_PIXMAP | |
482 #define XmUNSPECIFIED_PIXMAP 2 | |
483 #endif | |
484 | |
485 static GC | |
486 get_gc (XlwScrollBarWidget w, Pixel fg, Pixel bg, Pixmap pm) | |
487 { | |
488 XGCValues values; | |
489 XtGCMask mask; | |
490 | |
491 if (pm == w->sb.grayPixmap) | |
492 { | |
493 /* If we're using the gray pixmap, guarantee white on black ... | |
494 * otherwise, we could end up with something odd like grey on white | |
495 * when we're on a color display that ran out of color cells | |
496 */ | |
497 | |
498 fg = WhitePixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w))); | |
499 bg = BlackPixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w))); | |
500 } | |
501 | |
502 values.foreground = fg; | |
503 values.background = bg; | |
504 values.fill_style = FillOpaqueStippled; | |
505 values.stipple = pm; | |
506 /* mask = GCForeground | GCBackground | | |
507 (pm == None ? 0 : GCStipple | GCFillStyle); gtb */ | |
508 if (pm != None && pm != 0 && pm != XmUNSPECIFIED_PIXMAP) | |
509 values.stipple = pm; | |
510 else | |
511 values.stipple = None; | |
512 mask = GCForeground | GCBackground | | |
513 (values.stipple == None ? 0 : GCStipple | GCFillStyle); | |
514 | |
515 return XtGetGC((Widget) w, mask, &values); | |
516 } | |
517 | |
518 static void | |
519 make_shadow_pixels (XlwScrollBarWidget w) | |
520 { | |
3094 | 521 Display *dpy = XtDisplay ((Widget) w); |
428 | 522 Colormap cmap = w->core.colormap; |
523 XColor topc, botc; | |
524 int top_frobbed, bottom_frobbed; | |
525 Pixel bg, fg; | |
3094 | 526 Visual *visual; |
527 int ignored; | |
528 | |
529 visual_info_from_widget ((Widget) w, &visual, &ignored); | |
530 /* #### Apparently this is called before any shell has a visual? | |
531 or maybe the widget doesn't have a parent yet? */ | |
532 if (visual == CopyFromParent) | |
533 { | |
534 Screen *screen = DefaultScreenOfDisplay (dpy); | |
535 visual = DefaultVisualOfScreen (screen); | |
536 } | |
428 | 537 |
538 top_frobbed = bottom_frobbed = 0; | |
539 | |
540 bg = w->core.background_pixel; | |
541 fg = w->sb.foreground; | |
542 | |
543 if (w->sb.topShadowColor == (Pixel)~0) w->sb.topShadowColor = bg; | |
544 if (w->sb.bottomShadowColor == (Pixel)~0) w->sb.bottomShadowColor = fg; | |
545 | |
546 if (w->sb.topShadowColor == bg || w->sb.topShadowColor == fg) | |
547 { | |
548 topc.pixel = bg; | |
549 XQueryColor (dpy, cmap, &topc); | |
3094 | 550 /* #### can we use a (generalized) xft_convert_color here? */ |
428 | 551 /* don't overflow/wrap! */ |
552 topc.red = MINL(65535, topc.red * 1.2); | |
553 topc.green = MINL(65535, topc.green * 1.2); | |
554 topc.blue = MINL(65535, topc.blue * 1.2); | |
3094 | 555 if (x_allocate_nearest_color (dpy, cmap, visual, &topc)) |
428 | 556 { |
557 if (topc.pixel == bg) | |
558 { | |
559 XFreeColors (dpy, cmap, &topc.pixel, 1, 0); | |
560 topc.red = MINL(65535, topc.red + 0x8000); | |
561 topc.green = MINL(65535, topc.green + 0x8000); | |
562 topc.blue = MINL(65535, topc.blue + 0x8000); | |
3094 | 563 if (x_allocate_nearest_color (dpy, cmap, visual, &topc)) |
428 | 564 { |
565 w->sb.topShadowColor = topc.pixel; | |
566 } | |
567 } | |
568 else | |
569 { | |
570 w->sb.topShadowColor = topc.pixel; | |
571 } | |
572 | |
573 top_frobbed = 1; | |
574 } | |
575 } | |
576 | |
577 if (w->sb.bottomShadowColor == fg || w->sb.bottomShadowColor == bg) | |
578 { | |
579 botc.pixel = bg; | |
580 XQueryColor (dpy, cmap, &botc); | |
581 botc.red = (botc.red * 3) / 5; | |
582 botc.green = (botc.green * 3) / 5; | |
583 botc.blue = (botc.blue * 3) / 5; | |
3094 | 584 if (x_allocate_nearest_color (dpy, cmap, visual, &botc)) |
428 | 585 { |
586 if (botc.pixel == bg) | |
587 { | |
588 XFreeColors (dpy, cmap, &botc.pixel, 1, 0); | |
589 botc.red = MINL(65535, botc.red + 0x4000); | |
590 botc.green = MINL(65535, botc.green + 0x4000); | |
591 botc.blue = MINL(65535, botc.blue + 0x4000); | |
3094 | 592 if (x_allocate_nearest_color (dpy, cmap, visual, &botc)) |
428 | 593 { |
594 w->sb.bottomShadowColor = botc.pixel; | |
595 } | |
596 } | |
597 else | |
598 { | |
599 w->sb.bottomShadowColor = botc.pixel; | |
600 } | |
601 bottom_frobbed = 1; | |
602 } | |
603 } | |
604 | |
605 if (top_frobbed && bottom_frobbed) | |
606 { | |
607 int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3)); | |
608 int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3)); | |
609 if (bot_avg > top_avg) | |
610 { | |
611 Pixel tmp = w->sb.topShadowColor; | |
612 w->sb.topShadowColor = w->sb.bottomShadowColor; | |
613 w->sb.bottomShadowColor = tmp; | |
614 } | |
615 else if (topc.pixel == botc.pixel) | |
616 { | |
617 if (botc.pixel == bg) | |
618 w->sb.topShadowColor = bg; | |
619 else | |
620 w->sb.bottomShadowColor = fg; | |
621 } | |
622 } | |
623 | |
624 if (w->sb.topShadowColor == w->core.background_pixel || | |
625 w->sb.bottomShadowColor == w->core.background_pixel) | |
626 { | |
627 /* Assume we're in mono. This code should be okay even if we're | |
628 * really in color but just short on color cells -- We want the | |
629 * following behavior, which has been empirically determined to | |
630 * work well for all fg/bg combinations in mono: If the trough | |
631 * and slider are BOTH black, then use a white top shadow and a | |
632 * grey bottom shadow, otherwise use a grey top shadow and a | |
633 * black bottom shadow. | |
634 */ | |
635 | |
636 Pixel white = WhitePixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w))); | |
637 Pixel black = BlackPixelOfScreen (DefaultScreenOfDisplay (XtDisplay (w))); | |
638 | |
639 /* Note: core.background_pixel is the color of the slider ... */ | |
640 | |
641 if (w->core.background_pixel == black && | |
642 w->sb.troughColor == black) | |
643 { | |
644 w->sb.topShadowColor = white; | |
645 w->sb.bottomShadowPixmap = w->sb.grayPixmap; | |
646 } else { | |
647 w->sb.topShadowPixmap = w->sb.grayPixmap; | |
648 w->sb.bottomShadowColor = black; | |
649 } | |
650 } | |
651 } | |
652 | |
653 static void | |
654 make_trough_pixel (XlwScrollBarWidget w) | |
655 { | |
656 Display *dpy = XtDisplay((Widget) w); | |
657 Colormap cmap = w->core.colormap; | |
658 XColor troughC; | |
3094 | 659 Visual *visual; |
660 int ignored; | |
661 | |
662 visual_info_from_widget ((Widget) w, &visual, &ignored); | |
663 /* #### Apparently this is called before any shell has a visual? | |
664 or maybe the widget doesn't have a parent yet? */ | |
665 if (visual == CopyFromParent) | |
666 { | |
667 Screen *screen = DefaultScreenOfDisplay (dpy); | |
668 visual = DefaultVisualOfScreen (screen); | |
669 } | |
428 | 670 |
671 if (w->sb.troughColor == (Pixel)~0) w->sb.troughColor = w->core.background_pixel; | |
672 | |
673 if (w->sb.troughColor == w->core.background_pixel) | |
674 { | |
675 troughC.pixel = w->core.background_pixel; | |
676 XQueryColor (dpy, cmap, &troughC); | |
677 troughC.red = (troughC.red * 4) / 5; | |
678 troughC.green = (troughC.green * 4) / 5; | |
679 troughC.blue = (troughC.blue * 4) / 5; | |
3094 | 680 if (x_allocate_nearest_color (dpy, cmap, visual, &troughC)) |
428 | 681 w->sb.troughColor = troughC.pixel; |
682 } | |
683 } | |
684 | |
685 /*-------------------------- Draw 3D Border -----------------------------*/ | |
686 static void | |
687 draw_shadows (Display *dpy, Drawable d, GC shine_gc, GC shadow_gc, | |
688 int x, int y, int width, int height, int shadowT) | |
689 { | |
690 XSegment shine[10], shadow[10]; | |
691 int i; | |
692 | |
693 if (shadowT > (width / 2)) shadowT = (width / 2); | |
694 if (shadowT > (height / 2)) shadowT = (height / 2); | |
695 if (shadowT <= 0) return; | |
696 | |
697 for (i = 0; i < shadowT; i++) | |
698 { | |
699 /* Top segments */ | |
700 shine[i].x1 = x; | |
701 shine[i].y2 = shine[i].y1 = y + i; | |
702 shine[i].x2 = x + width - i - 1; | |
703 /* Left segments */ | |
704 shine[i + shadowT].x2 = shine[i + shadowT].x1 = x + i; | |
705 shine[i + shadowT].y1 = y + shadowT; | |
706 shine[i + shadowT].y2 = y + height - i - 1; | |
707 | |
708 /* Bottom segments */ | |
709 shadow[i].x1 = x + i; | |
710 shadow[i].y2 = shadow[i].y1 = y + height - i - 1; | |
711 shadow[i].x2 = x + width - 1 ; | |
712 /* Right segments */ | |
713 shadow[i + shadowT].x2 = shadow[i + shadowT].x1 = x + width - i - 1; | |
714 shadow[i + shadowT].y1 = y + i + 1; | |
715 shadow[i + shadowT].y2 = y + height - 1 ; | |
716 } | |
717 | |
718 XDrawSegments (dpy, d, shine_gc, shine, shadowT * 2); | |
719 XDrawSegments (dpy, d, shadow_gc, shadow, shadowT * 2); | |
720 } | |
721 | |
722 /*------------------ Draw 3D Arrows: left, up, down, right --------------*/ | |
723 static int | |
724 make_vert_seg (XSegment *seg, int x1, int y1, int x2, int y2, int shadowT) | |
725 { | |
726 int i; | |
727 | |
728 for (i=0; i<shadowT; i++, seg++) | |
729 { | |
730 seg->x1 = x1; | |
731 seg->y1 = y1++; | |
732 seg->x2 = x2; | |
733 seg->y2 = y2++; | |
734 } | |
735 return shadowT; | |
736 } | |
737 | |
738 static int | |
739 make_hor_seg (XSegment *seg, int x1, int y1, int x2, int y2, int shadowT) | |
740 { | |
741 int i; | |
742 | |
743 for (i=0; i<shadowT; i++, seg++) | |
744 { | |
745 seg->x1 = x1++; | |
746 seg->y1 = y1; | |
747 seg->x2 = x2++; | |
748 seg->y2 = y2; | |
749 } | |
750 return shadowT; | |
751 } | |
752 | |
753 static void | |
754 draw_arrow_up (Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC, | |
755 int x, int y, int width, int height, int shadowT) | |
756 { | |
757 XSegment shine[10], shadow[10]; | |
758 XPoint triangle[3]; | |
759 int mid; | |
760 | |
761 mid = width / 2; | |
762 | |
763 if (shadowT > (width / 2)) shadowT = (width / 2); | |
764 if (shadowT > (height / 2)) shadowT = (height / 2); | |
765 if (shadowT < 0) shadowT = 0; | |
766 | |
767 /* / */ | |
768 make_vert_seg (shine, | |
769 x, y + height - shadowT - 1, | |
770 x + mid, y, shadowT); | |
771 /* _\ */ | |
772 make_vert_seg (shadow, | |
773 x, y + height - shadowT - 1, | |
774 x + width - 1, y + height - shadowT - 1, shadowT); | |
775 make_vert_seg (shadow + shadowT, | |
776 x + mid, y, | |
777 x + width - 1, y + height - shadowT - 1, shadowT); | |
778 | |
779 triangle[0].x = x; | |
780 triangle[0].y = y + height - 1; | |
781 triangle[1].x = x + mid; | |
782 triangle[1].y = y; | |
783 triangle[2].x = x + width - 1; | |
784 triangle[2].y = y + height - 1; | |
785 | |
786 XFillPolygon (dpy, win, bgGC, triangle, 3, Convex, ArcChord); | |
787 | |
788 XDrawSegments (dpy, win, shadowGC, shadow, shadowT * 2); | |
789 XDrawSegments (dpy, win, shineGC, shine, shadowT); | |
790 } | |
791 | |
792 static void | |
793 draw_arrow_left (Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC, | |
794 int x, int y, int width, int height, int shadowT) | |
795 { | |
796 XSegment shine[10], shadow[10]; | |
797 XPoint triangle[3]; | |
798 | |
799 int mid = width / 2; | |
800 | |
801 if (shadowT > (width / 2)) shadowT = (width / 2); | |
802 if (shadowT > (height / 2)) shadowT = (height / 2); | |
803 if (shadowT < 0) shadowT = 0; | |
804 | |
805 /* / */ | |
806 make_hor_seg (shine, | |
807 x, y + mid, | |
808 x + width - shadowT - 1, y, shadowT); | |
809 /* \| */ | |
810 make_hor_seg (shadow, | |
811 x, y + mid, | |
812 x + width - shadowT - 1, y + height - 1, shadowT); | |
813 make_hor_seg (shadow + shadowT, | |
814 x + width - shadowT - 1, y, | |
815 x + width - shadowT - 1, y + height - 1, shadowT); | |
816 | |
817 triangle[0].x = x + width - 1; | |
818 triangle[0].y = y + height - 1; | |
819 triangle[1].x = x; | |
820 triangle[1].y = y + mid; | |
821 triangle[2].x = x + width - 1; | |
822 triangle[2].y = y; | |
823 | |
824 XFillPolygon (dpy, win, bgGC, triangle, 3, Convex, ArcChord); | |
825 | |
826 XDrawSegments (dpy, win, shadowGC, shadow, shadowT * 2); | |
827 XDrawSegments (dpy, win, shineGC, shine, shadowT); | |
828 } | |
829 | |
830 static void | |
831 draw_arrow_down (Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC, | |
832 int x, int y, int width, int height, int shadowT) | |
833 { | |
834 XSegment shine[10], shadow[10]; | |
835 XPoint triangle[3]; | |
836 int mid; | |
837 | |
838 mid = width / 2; | |
839 | |
840 if (shadowT > (width / 2)) shadowT = (width / 2); | |
841 if (shadowT > (height / 2)) shadowT = (height / 2); | |
842 if (shadowT < 0) shadowT = 0; | |
843 | |
844 /* \- */ | |
845 make_vert_seg (shine, | |
846 x, y, | |
847 x + mid, y + height - shadowT - 1, shadowT); | |
848 make_vert_seg (shine + shadowT, | |
849 x, y, | |
850 x + width - 1, y, shadowT); | |
851 /* / */ | |
852 make_vert_seg (shadow, | |
853 x + width - 1, y, | |
854 x + mid, y + height - shadowT - 1, shadowT); | |
855 | |
856 triangle[0].x = x; | |
857 triangle[0].y = y; | |
858 triangle[1].x = x + mid; | |
859 triangle[1].y = y + height - 1; | |
860 triangle[2].x = x + width - 1; | |
861 triangle[2].y = y; | |
862 | |
863 XFillPolygon (dpy, win, bgGC, triangle, 3, Convex, ArcChord); | |
864 | |
865 XDrawSegments (dpy, win, shadowGC, shadow, shadowT); | |
866 XDrawSegments (dpy, win, shineGC, shine, shadowT * 2); | |
867 } | |
868 | |
869 static void | |
870 draw_arrow_right (Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC, | |
871 int x, int y, int width, int height, int shadowT) | |
872 { | |
873 XSegment shine[10], shadow[10]; | |
874 XPoint triangle[3]; | |
875 int mid; | |
876 | |
877 mid = width / 2; | |
878 | |
879 if (shadowT > (width / 2)) shadowT = (width / 2); | |
880 if (shadowT > (height / 2)) shadowT = (height / 2); | |
881 if (shadowT < 0) shadowT = 0; | |
882 | |
883 /* |\ */ | |
884 make_hor_seg (shine, | |
885 x, y, | |
886 x + width - shadowT - 1, y + mid, shadowT); | |
887 make_hor_seg (shine + shadowT, | |
888 x, y, | |
889 x, y + height - 1, shadowT); | |
890 /* / */ | |
891 make_hor_seg (shadow, | |
892 x, y + height - 1, | |
893 x + width - shadowT - 1, y + mid, shadowT); | |
894 | |
895 triangle[0].x = x + 1; | |
896 triangle[0].y = y + height - 1; | |
897 triangle[1].x = x + width - 1; | |
898 triangle[1].y = y + mid; | |
899 triangle[2].x = x + 1; | |
900 triangle[2].y = y; | |
901 | |
902 XFillPolygon (dpy, win, bgGC, triangle, 3, Convex, ArcChord); | |
903 | |
904 XDrawSegments (dpy, win, shadowGC, shadow, shadowT); | |
905 XDrawSegments (dpy, win, shineGC, shine, shadowT * 2); | |
906 } | |
907 | |
908 static void | |
909 draw_dimple (Display *dpy, Drawable win, GC shine, GC shadow, | |
910 int x, int y, int width, int height) | |
911 { | |
912 XDrawArc (dpy, win, shine, x, y, width, height, 46*64, 180*64); | |
913 XDrawArc (dpy, win, shadow, x, y, width, height, 45*64, -179*64); | |
914 } | |
915 | |
916 /*------- Scrollbar values -> pixels, pixels -> scrollbar values --------*/ | |
917 | |
918 static void | |
919 seg_pixel_sizes (XlwScrollBarWidget w, int *above_return, | |
920 int *ss_return, int *below_return) | |
921 { | |
922 float total, height, fuz; | |
923 int value, above, ss, below; | |
924 | |
925 height = widget_h (w); | |
926 if (w->sb.showArrows) height -= (2 * arrow_h (w)); | |
927 | |
928 value = w->sb.value - w->sb.minimum; | |
929 | |
930 total = w->sb.maximum - w->sb.minimum; | |
931 fuz = total / 2; | |
932 | |
933 ss = (int) ((height * w->sb.sliderSize + fuz) / total); | |
934 above = (int) ((height * value + fuz) / total); | |
935 below = (int) ((height) - (ss + above)); | |
936 | |
937 /* Don't let slider get smaller than SS_MIN */ | |
938 if (ss < SS_MIN) | |
939 { | |
940 /* add a percent amount for integer rounding */ | |
434 | 941 float tmp = (((float) (SS_MIN - ss) * (float) value) / total) + 0.5; |
428 | 942 |
943 above -= (int) tmp; | |
944 ss = SS_MIN; | |
945 below = (int) ((height) - (ss + above)); | |
946 | |
947 if (above < 0) | |
948 { | |
949 above = 0; | |
950 below = (int) (height - ss); | |
951 } | |
952 if (below < 0) | |
953 { | |
954 above = (int) (height - ss); | |
955 below = 0; | |
956 } | |
957 if (ss > height) | |
958 { | |
959 above = 0; | |
960 ss = (int) height; | |
961 below = 0; | |
962 } | |
963 } | |
964 | |
965 *above_return = above; | |
966 *ss_return = ss; | |
967 *below_return = below; | |
968 | |
969 CHECK (w); | |
970 } | |
971 | |
972 static void | |
973 verify_values (XlwScrollBarWidget w) | |
974 { | |
975 int total = w->sb.maximum - w->sb.minimum; | |
976 | |
977 if (w->sb.sliderSize > total) | |
978 w->sb.sliderSize = total; | |
979 | |
980 if (w->sb.pageIncrement > total) | |
981 w->sb.pageIncrement = total; | |
982 | |
983 if (w->sb.increment > total) | |
984 w->sb.increment = total; | |
985 | |
986 if (w->sb.value < w->sb.minimum) | |
987 w->sb.value = w->sb.minimum; | |
988 | |
989 if (w->sb.value > w->sb.maximum) | |
990 w->sb.value = w->sb.maximum; | |
991 | |
992 if (w->sb.sliderSize > w->sb.maximum - w->sb.value) | |
993 w->sb.sliderSize = w->sb.maximum - w->sb.value; | |
994 } | |
995 | |
996 static int | |
997 value_from_pixel (XlwScrollBarWidget w, int above) | |
998 { | |
999 float total, height, fuz; | |
1000 int value, ss; | |
1001 | |
1002 height = widget_h (w); | |
1003 if (w->sb.showArrows) | |
1004 height -= (2 * arrow_h (w)); | |
1005 | |
1006 total = w->sb.maximum - w->sb.minimum; | |
1007 fuz = height / 2; | |
1008 | |
1009 ss = (int) ((height * w->sb.sliderSize + (total / 2)) / total); | |
1010 | |
1011 if (ss < SS_MIN) | |
1012 { | |
1013 /* add a percent amount for integer rounding */ | |
1014 above += (int) ((((SS_MIN - ss) * above) + fuz) / height); | |
1015 } | |
1016 | |
1017 { | |
1018 /* Prevent SIGFPE's that would occur if we don't truncate the value. */ | |
1019 float floatval = w->sb.minimum + ((float)(above * total + fuz) / height); | |
1020 if (floatval >= (float) INT_MAX) | |
1021 value = INT_MAX; | |
1022 else if (floatval <= (float) INT_MIN) | |
1023 value = INT_MIN; | |
1024 else | |
1025 value = (int) floatval; | |
1026 } | |
1027 | |
1028 return value; | |
1029 } | |
1030 | |
1031 | |
1032 static void | |
1033 redraw_dimple (XlwScrollBarWidget w, Display *dpy, Window win, | |
1034 int x, int y, int width, int height) | |
1035 { | |
1036 if (SLIDER_DIMPLE == slider_style (w)) | |
1037 { | |
1038 int size; | |
1039 int slider_p = (w->sb.armed == ARM_SLIDER); | |
1040 GC shine = slider_p ? w->sb.bottomShadowGC : w->sb.topShadowGC; | |
1041 GC shadow = slider_p ? w->sb.topShadowGC : w->sb.bottomShadowGC; | |
1042 int shadowT = w->sb.shadowThickness; | |
1043 | |
1044 x += shadowT; | |
1045 y += shadowT; | |
1046 width -= 2*shadowT; | |
1047 height -= 2*shadowT; | |
1048 | |
1049 size = (width < height ? width : height) * 3 / 4; | |
1050 | |
1051 if (size%2 != (width < height ? width : height)%2) size--; | |
1052 | |
1053 DBUG (fprintf (stderr, "%d %d\n", | |
1054 x + (width / 2) - (size / 2) - 2*shadowT, | |
1055 width - size - shadowT)); | |
1056 | |
1057 draw_dimple (dpy, win, shine, shadow, | |
1058 x + (width / 2) - (size / 2), | |
1059 y + (height / 2) - (size / 2), | |
1060 size, size); | |
1061 } | |
1062 } | |
1063 | |
1064 static void | |
1065 draw_slider (XlwScrollBarWidget w, int above, int ss, int below) | |
1066 { | |
1067 Display *dpy = XtDisplay ((Widget) w); | |
1068 Window win = XtWindow ((Widget) w); | |
1069 | |
1070 int x = widget_x (w); | |
1071 int y = widget_y (w); | |
1072 int width = widget_w (w); | |
1073 int height = widget_h (w); | |
1074 int shadowT = w->sb.shadowThickness; | |
1075 int vert_p = VERT (w); | |
1076 | |
1077 if (shadowT > (width / 2)) shadowT = (width / 2); | |
1078 if (shadowT > (height / 2)) shadowT = (height / 2); | |
1079 if (shadowT < 0) shadowT = 0; | |
1080 | |
1081 if (w->sb.showArrows && !arrow_same_end (w)) | |
1082 y += arrow_h (w); | |
1083 | |
1084 /* trough above slider */ | |
1085 if (above > 0) | |
1086 { | |
1087 if (vert_p) | |
1088 XClearArea (dpy, win, x, y, width, above, False); | |
1089 else | |
1090 XClearArea (dpy, win, y, x, above, width, False); | |
1091 } | |
1092 | |
1093 /* slider */ | |
1094 if (vert_p) | |
1095 { | |
1096 draw_shadows (dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC, | |
1097 x, y + above, width, ss, shadowT); | |
1098 XFillRectangle (dpy, win, w->sb.backgroundGC, | |
1099 x+shadowT, y + above + shadowT, | |
1100 width-2*shadowT, ss-2*shadowT); | |
1101 redraw_dimple (w, dpy, win, x, y + above, width, ss); | |
1102 } | |
1103 else | |
1104 { | |
1105 draw_shadows (dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC, | |
1106 y + above, x, ss, width, shadowT); | |
1107 XFillRectangle (dpy, win, w->sb.backgroundGC, | |
1108 y + above + shadowT, x+shadowT, | |
1109 ss-2*shadowT, width-2*shadowT); | |
1110 redraw_dimple (w, dpy, win, y + above, x, ss, width); | |
1111 } | |
1112 | |
1113 /* trough below slider */ | |
1114 if (below > 0) | |
1115 { | |
1116 if (vert_p) | |
1117 XClearArea (dpy, win, x, y + above + ss, width, below, False); | |
1118 else | |
1119 XClearArea (dpy, win, y + above + ss, x, below, width, False); | |
1120 } | |
1121 | |
1122 CHECK (w); | |
1123 } | |
1124 | |
1125 static void | |
1126 redraw_up_arrow (XlwScrollBarWidget w, Boolean armed, Boolean clear_behind) | |
1127 { | |
1128 Display *dpy = XtDisplay ((Widget) w); | |
1129 Window win = XtWindow ((Widget) w); | |
1130 | |
1131 int x = widget_x (w); | |
1132 int y = widget_y (w); | |
1133 int width = widget_w (w); | |
1134 int height = widget_h (w); | |
1135 int shadowT = w->sb.shadowThickness; | |
1136 int arrow_height = arrow_h (w); | |
1137 | |
1138 GC bg = w->sb.backgroundGC; | |
1139 GC shine = armed ? w->sb.bottomShadowGC : w->sb.topShadowGC; | |
1140 GC shadow = armed ? w->sb.topShadowGC : w->sb.bottomShadowGC; | |
1141 | |
1142 if (VERT (w)) | |
1143 { | |
1144 if (arrow_same_end (w)) | |
1145 y += height - 2 * arrow_height; | |
1146 if (clear_behind) | |
1147 XClearArea (dpy, win, x, y, width, arrow_height + 1, False); | |
1148 draw_arrow_up (dpy, win, bg, shine, shadow, | |
1149 x + (width - arrow_height)/2, y, | |
1150 arrow_height, arrow_height, shadowT); | |
1151 } | |
1152 else | |
1153 { | |
1154 if (arrow_same_end (w)) | |
1155 y += height - 2 * arrow_height; | |
1156 if (clear_behind) | |
1157 XClearArea (dpy, win, y, x, arrow_height + 1, height, False); | |
1158 draw_arrow_left (dpy, win, bg, shine, shadow, | |
1159 y, x + (width - arrow_height)/2, | |
1160 arrow_height, arrow_height, shadowT); | |
1161 } | |
1162 } | |
1163 | |
1164 static void | |
1165 redraw_down_arrow (XlwScrollBarWidget w, Boolean armed, Boolean clear_behind) | |
1166 { | |
1167 Display *dpy = XtDisplay ((Widget) w); | |
1168 Window win = XtWindow ((Widget) w); | |
1169 | |
1170 int x = widget_x (w); | |
1171 int y = widget_y (w); | |
1172 int width = widget_w (w); | |
1173 int height = widget_h (w); | |
1174 int shadowT = w->sb.shadowThickness; | |
1175 int arrow_height = arrow_h (w); | |
1176 | |
1177 GC bg = w->sb.backgroundGC; | |
1178 GC shine = armed ? w->sb.bottomShadowGC : w->sb.topShadowGC; | |
1179 GC shadow = armed ? w->sb.topShadowGC : w->sb.bottomShadowGC; | |
1180 | |
1181 if (VERT (w)) | |
1182 { | |
1183 if (clear_behind) | |
1184 XClearArea (dpy, win, x, y + height - arrow_height, width, | |
1185 arrow_height + 1, False); | |
1186 draw_arrow_down (dpy, win, bg, shine, shadow, | |
1187 x + (width - arrow_height)/2, | |
1188 y + height - arrow_height + 1, | |
1189 arrow_height, arrow_height, shadowT); | |
1190 } | |
1191 else | |
1192 { | |
1193 if (clear_behind) | |
1194 XClearArea (dpy, win, y + height - arrow_height, x, | |
1195 arrow_height + 1, height, False); | |
1196 draw_arrow_right (dpy, win, bg, shine, shadow, | |
1197 y + height - arrow_height + 1, | |
1198 x + (width - arrow_height)/2, | |
1199 arrow_height, arrow_height, shadowT); | |
1200 } | |
1201 } | |
1202 | |
1203 static void | |
1204 redraw_everything (XlwScrollBarWidget w, Region region, Boolean behind_arrows) | |
1205 { | |
1206 Display *dpy = XtDisplay ((Widget) w); | |
1207 Window win = XtWindow ((Widget) w); | |
1208 | |
1209 if (w->sb.showArrows) | |
1210 { | |
1211 if (region == NULL) | |
1212 { | |
1213 redraw_up_arrow (w, False, behind_arrows); | |
1214 redraw_down_arrow (w, False, behind_arrows); | |
1215 } | |
1216 else | |
1217 { | |
1218 int x = widget_x (w); | |
1219 int y = widget_y (w); | |
1220 int width = widget_w (w); | |
1221 int height = widget_h (w); | |
1222 int arrow_height = arrow_h (w); | |
1223 int ax = x, ay = y; | |
1224 | |
1225 if (arrow_same_end (w)) | |
1226 { | |
1227 if (VERT (w)) | |
1228 ay = y + height - arrow_height - arrow_height; | |
1229 else | |
1230 ax = x + height - arrow_height - arrow_height; | |
1231 } | |
1232 if (XRectInRegion (region, ax, ay, width, width)) | |
1233 redraw_up_arrow (w, False, behind_arrows); | |
1234 | |
1235 if (VERT (w)) | |
1236 ay = y + height - arrow_height; | |
1237 else | |
1238 ax = x + height - arrow_height; | |
1239 if (XRectInRegion (region, ax, ay, width, width)) | |
1240 redraw_down_arrow (w, False, behind_arrows); | |
1241 } | |
1242 } | |
1243 | |
1244 draw_shadows (dpy, win, w->sb.bottomShadowGC, w->sb.topShadowGC, 0, 0, | |
1245 w->core.width, w->core.height, w->sb.shadowThickness); | |
1246 | |
1247 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1248 } | |
1249 | |
1250 /*-------------------------- Method Functions ---------------------------*/ | |
1251 | |
1252 static void | |
2286 | 1253 Initialize (Widget treq, Widget tnew, ArgList UNUSED (args), |
1254 Cardinal *UNUSED (num_args)) | |
428 | 1255 { |
1256 XlwScrollBarWidget request = (XlwScrollBarWidget) treq; | |
1257 XlwScrollBarWidget w = (XlwScrollBarWidget) tnew; | |
1258 Display *dpy = XtDisplay ((Widget) w); | |
1259 Window win = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); | |
1260 | |
1261 if (request->core.width == 0) w->core.width += (VERT (w) ? 12 : 25); | |
1262 if (request->core.height == 0) w->core.height += (VERT (w) ? 25 : 12); | |
1263 | |
1264 verify_values (w); | |
1265 | |
1266 w->sb.lastY = 0; | |
1267 w->sb.above = 0; | |
1268 w->sb.ss = 0; | |
1269 w->sb.below = 0; | |
1270 w->sb.armed = ARM_NONE; | |
1271 w->sb.forced_scroll = FORCED_SCROLL_NONE; | |
1272 | |
1273 if (w->sb.shadowThickness > 5) w->sb.shadowThickness = 5; | |
1274 | |
1275 w->sb.grayPixmap = | |
1276 XCreatePixmapFromBitmapData (dpy, win, (char *) gray_bits, gray_width, | |
1277 gray_height, 1, 0, 1); | |
1278 | |
1279 make_trough_pixel (w); | |
1280 | |
1281 make_shadow_pixels (w); | |
1282 | |
1283 w->sb.backgroundGC = | |
1284 get_gc (w, w->core.background_pixel, w->core.background_pixel, None); | |
1285 w->sb.topShadowGC = | |
1286 get_gc (w, w->sb.topShadowColor, w->core.background_pixel, | |
1287 w->sb.topShadowPixmap); | |
1288 w->sb.bottomShadowGC = | |
1289 get_gc (w, w->sb.bottomShadowColor, w->core.background_pixel, | |
1290 w->sb.bottomShadowPixmap); | |
1291 | |
1292 w->sb.fullRedrawNext = True; | |
1293 | |
1294 w->sb.timerActive = False; | |
1295 } | |
1296 | |
1297 static void | |
1298 Destroy (Widget widget) | |
1299 { | |
1300 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1301 Display *dpy = XtDisplay ((Widget) w); | |
1302 | |
1303 XtReleaseGC (widget, w->sb.bottomShadowGC); | |
1304 XtReleaseGC (widget, w->sb.topShadowGC); | |
1305 XtReleaseGC (widget, w->sb.backgroundGC); | |
1306 | |
1307 XFreePixmap (dpy, w->sb.grayPixmap); | |
1308 | |
1309 if (w->sb.timerActive) | |
1310 { | |
1311 XtRemoveTimeOut (w->sb.timerId); | |
1312 w->sb.timerActive = False; /* Should be a no-op, but you never know */ | |
1313 } | |
1314 } | |
1315 | |
1316 static void | |
1317 Realize (Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr) | |
1318 { | |
1319 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1320 Display *dpy = XtDisplay ((Widget) w); | |
1321 Window win; | |
1322 XSetWindowAttributes win_attr; | |
1323 | |
1324 (*coreClassRec.core_class.realize)(widget, valuemask, attr); | |
1325 | |
1326 win = XtWindow ((Widget) w); | |
1327 | |
1328 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1329 | |
1330 XSetWindowBackground (dpy, win, w->sb.troughColor); | |
1331 | |
1332 /* Change bit gravity so widget is not cleared on resize */ | |
1333 win_attr.bit_gravity = NorthWestGravity; | |
1334 XChangeWindowAttributes (dpy, win, CWBitGravity , &win_attr); | |
1335 | |
1336 } | |
1337 | |
1338 static void | |
1339 Resize (Widget widget) | |
1340 { | |
1341 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1342 Display *dpy = XtDisplay ((Widget) w); | |
1343 Window win = XtWindow ((Widget) w); | |
1344 | |
1345 if (XtIsRealized (widget)) | |
1346 { | |
1347 DBUG (fprintf (stderr, "Resize = %08lx\n", w)); | |
1348 | |
1349 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1350 | |
1351 /* redraw_everything (w, NULL, True); */ | |
1352 | |
1353 w->sb.fullRedrawNext = True; | |
1354 /* Force expose event */ | |
1355 XClearArea (dpy, win, widget_x (w), widget_y (w), 1, 1, True); | |
1356 } | |
1357 | |
1358 if (w->sb.timerActive) | |
1359 { | |
1360 XtRemoveTimeOut (w->sb.timerId); | |
1361 w->sb.timerActive = False; | |
1362 } | |
1363 } | |
1364 | |
1365 static void | |
2286 | 1366 Redisplay (Widget widget, XEvent *UNUSED (event), Region region) |
428 | 1367 { |
1368 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1369 | |
1370 DBUG (fprintf (stderr, "Redisplay = %08lx\n", w)); | |
1371 | |
1372 if (XtIsRealized (widget)) | |
1373 { | |
1374 if (w->sb.fullRedrawNext) | |
1375 redraw_everything (w, NULL, True); | |
1376 else | |
1377 redraw_everything (w, region, False); | |
1378 w->sb.fullRedrawNext = False; | |
1379 } | |
1380 } | |
1381 | |
1382 static Boolean | |
2286 | 1383 SetValues (Widget current, Widget UNUSED (request), Widget neww, |
1384 ArgList UNUSED (args), Cardinal *UNUSED (num_args)) | |
428 | 1385 { |
1386 XlwScrollBarWidget cur = (XlwScrollBarWidget) current; | |
1387 XlwScrollBarWidget w = (XlwScrollBarWidget) neww; | |
1388 Boolean do_redisplay = False; | |
1389 | |
1390 if (cur->sb.troughColor != w->sb.troughColor) | |
1391 { | |
1392 if (XtIsRealized ((Widget) w)) | |
1393 { | |
1394 XSetWindowBackground (XtDisplay((Widget) w), XtWindow ((Widget) w), | |
1395 w->sb.troughColor); | |
1396 do_redisplay = True; | |
1397 } | |
1398 } | |
1399 | |
1400 if (cur->core.background_pixel != w->core.background_pixel) | |
1401 { | |
1402 XtReleaseGC ((Widget)cur, cur->sb.backgroundGC); | |
1403 w->sb.backgroundGC = | |
1404 get_gc (w, w->core.background_pixel, w->core.background_pixel, None); | |
1405 do_redisplay = True; | |
1406 } | |
1407 | |
1408 if (cur->sb.topShadowColor != w->sb.topShadowColor || | |
1409 cur->sb.topShadowPixmap != w->sb.topShadowPixmap) | |
1410 { | |
1411 XtReleaseGC ((Widget)cur, cur->sb.topShadowGC); | |
1412 w->sb.topShadowGC = | |
1413 get_gc (w, w->sb.topShadowColor, w->core.background_pixel, | |
1414 w->sb.topShadowPixmap); | |
1415 do_redisplay = True; | |
1416 } | |
1417 | |
1418 if (cur->sb.bottomShadowColor != w->sb.bottomShadowColor || | |
1419 cur->sb.bottomShadowPixmap != w->sb.bottomShadowPixmap) | |
1420 { | |
1421 XtReleaseGC ((Widget)cur, cur->sb.bottomShadowGC); | |
1422 w->sb.bottomShadowGC = | |
1423 get_gc (w, w->sb.bottomShadowColor, w->core.background_pixel, | |
1424 w->sb.bottomShadowPixmap); | |
1425 do_redisplay = True; | |
1426 } | |
1427 | |
1428 if (cur->sb.orientation != w->sb.orientation) | |
1429 do_redisplay = True; | |
1430 | |
1431 | |
1432 if (cur->sb.minimum != w->sb.minimum || | |
1433 cur->sb.maximum != w->sb.maximum || | |
1434 cur->sb.sliderSize != w->sb.sliderSize || | |
1435 cur->sb.value != w->sb.value || | |
1436 cur->sb.pageIncrement != w->sb.pageIncrement || | |
1437 cur->sb.increment != w->sb.increment) | |
1438 { | |
1439 verify_values (w); | |
1440 if (XtIsRealized ((Widget) w)) | |
1441 { | |
1442 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1443 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1444 } | |
1445 } | |
1446 | |
1447 if (w->sb.shadowThickness > 5) w->sb.shadowThickness = 5; | |
1448 | |
1449 return do_redisplay; | |
1450 } | |
1451 | |
1452 void | |
1453 XlwScrollBarGetValues (Widget widget, int *value, int *sliderSize, | |
1454 int *increment, int *pageIncrement) | |
1455 { | |
1456 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1457 | |
1458 if (w && XtClass ((Widget) w) == xlwScrollBarWidgetClass) | |
1459 { | |
1460 if (value) *value = w->sb.value; | |
1461 if (sliderSize) *sliderSize = w->sb.sliderSize; | |
1462 if (increment) *increment = w->sb.increment; | |
1463 if (pageIncrement) *pageIncrement = w->sb.pageIncrement; | |
1464 } | |
1465 } | |
1466 | |
1467 void | |
1468 XlwScrollBarSetValues (Widget widget, int value, int sliderSize, | |
1469 int increment, int pageIncrement, Boolean notify) | |
1470 { | |
1471 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1472 | |
1473 if (w && XtClass ((Widget) w) == xlwScrollBarWidgetClass && | |
1474 (w->sb.value != value || | |
1475 w->sb.sliderSize != sliderSize || | |
1476 w->sb.increment != increment || | |
1477 w->sb.pageIncrement != pageIncrement)) | |
1478 { | |
1479 int last_value = w->sb.value; | |
1480 | |
1481 w->sb.value = value; | |
1482 w->sb.sliderSize = sliderSize; | |
1483 w->sb.increment = increment; | |
1484 w->sb.pageIncrement = pageIncrement; | |
1485 | |
1486 verify_values (w); | |
1487 | |
1488 if (XtIsRealized (widget)) | |
1489 { | |
1490 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1491 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1492 | |
1493 if (w->sb.value != last_value && notify) | |
1494 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, 0, NULL); | |
1495 } | |
1496 } | |
1497 } | |
1498 | |
1499 /*-------------------------- Action Functions ---------------------------*/ | |
1500 | |
1501 static void | |
2286 | 1502 timer (XtPointer data, XtIntervalId *UNUSED (id)) |
428 | 1503 { |
1504 XlwScrollBarWidget w = (XlwScrollBarWidget) data; | |
1505 w->sb.timerActive = False; | |
1506 | |
1507 if (w->sb.armed != ARM_NONE) | |
1508 { | |
1509 int last_value = w->sb.value; | |
1510 int reason; | |
1511 | |
1512 switch (w->sb.armed) | |
1513 { | |
1514 case ARM_PAGEUP: | |
1515 decrement_value (w, w->sb.pageIncrement); | |
1516 reason = XmCR_PAGE_DECREMENT; | |
1517 break; | |
1518 case ARM_PAGEDOWN: | |
1519 increment_value (w, w->sb.pageIncrement); | |
1520 reason = XmCR_PAGE_INCREMENT; | |
1521 break; | |
1522 case ARM_UP: | |
1523 decrement_value (w, w->sb.increment); | |
1524 reason = XmCR_DECREMENT; | |
1525 break; | |
1526 case ARM_DOWN: | |
1527 increment_value (w, w->sb.increment); | |
1528 reason = XmCR_INCREMENT; | |
1529 break; | |
1530 default: | |
1531 reason = XmCR_NONE; | |
1532 } | |
1533 | |
1534 verify_values (w); | |
1535 | |
1536 if (last_value != w->sb.value) | |
1537 { | |
1538 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1539 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1540 | |
1541 call_callbacks (w, reason, w->sb.value, 0, NULL); | |
1542 | |
1543 w->sb.timerId = | |
1544 XtAppAddTimeOut (XtWidgetToApplicationContext ((Widget) w), | |
1545 (unsigned long) w->sb.repeatDelay, | |
1546 timer, (XtPointer) w); | |
1547 w->sb.timerActive = True; | |
1548 } | |
1549 } | |
1550 } | |
1551 | |
1552 static button_where | |
1553 what_button (XlwScrollBarWidget w, int mouse_x, int mouse_y) | |
1554 { | |
1555 int width = widget_w (w); | |
1556 int height = widget_h (w); | |
1557 int arrow_height = arrow_h (w); | |
1558 | |
1559 mouse_x -= widget_x (w); | |
1560 mouse_y -= widget_y (w); | |
1561 | |
1562 if (mouse_x < 0 || mouse_x >= width || | |
1563 mouse_y < 0 || mouse_y >= height) | |
1564 return BUTTON_NONE; | |
1565 | |
1566 if (w->sb.showArrows) | |
1567 { | |
1568 if (mouse_y >= (height -= arrow_height)) | |
1569 return BUTTON_DOWN_ARROW; | |
1570 | |
1571 if (arrow_same_end (w)) | |
1572 { | |
1573 if (mouse_y >= (height -= arrow_height)) | |
1574 return BUTTON_UP_ARROW; | |
1575 } | |
1576 else | |
1577 if ( (mouse_y -= arrow_height) < 0) | |
1578 return BUTTON_UP_ARROW; | |
1579 } | |
1580 | |
1581 if ( (mouse_y -= w->sb.above) < 0) | |
1582 return BUTTON_TROUGH_ABOVE; | |
1583 | |
1584 if ( (mouse_y -= w->sb.ss) < 0) | |
1585 return BUTTON_SLIDER; | |
1586 | |
1587 return BUTTON_TROUGH_BELOW; | |
1588 } | |
1589 | |
1590 static void | |
2286 | 1591 Select (Widget widget, XEvent *event, String *UNUSED (parms), |
1592 Cardinal *UNUSED (num_parms)) | |
428 | 1593 { |
1594 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1595 button_where sb_button; | |
1596 | |
1597 int mouse_x = event_x (w, event); | |
1598 int mouse_y = event_y (w, event); | |
1599 | |
1600 int last_value = w->sb.savedValue = w->sb.value; | |
1601 int reason = XmCR_NONE; | |
1602 | |
1603 XtGrabKeyboard ((Widget) w, False, GrabModeAsync, GrabModeAsync, | |
1604 event->xbutton.time); | |
1605 | |
1606 sb_button = what_button (w, mouse_x, mouse_y); | |
1607 | |
1608 if (w->sb.forced_scroll != FORCED_SCROLL_NONE) | |
1609 { | |
1610 switch (sb_button) | |
1611 { | |
1612 case BUTTON_TROUGH_ABOVE: | |
1613 case BUTTON_TROUGH_BELOW: | |
1614 case BUTTON_SLIDER: | |
1615 sb_button= BUTTON_NONE; /* cause next switch to fall through */ | |
1616 if (w->sb.forced_scroll == FORCED_SCROLL_UPLEFT) | |
1617 { | |
1618 decrement_value (w, w->sb.pageIncrement); | |
1619 w->sb.armed = ARM_PAGEUP; | |
1620 reason = XmCR_PAGE_DECREMENT; | |
1621 break; | |
1622 } | |
1623 else if (w->sb.forced_scroll == FORCED_SCROLL_DOWNRIGHT) | |
1624 { | |
1625 increment_value (w, w->sb.pageIncrement); | |
1626 w->sb.armed = ARM_PAGEDOWN; | |
1627 reason = XmCR_PAGE_INCREMENT; | |
1628 break; | |
1629 } | |
1630 abort(); | |
1631 default: | |
1632 ; /* Do nothing */ | |
1633 } | |
1634 } | |
1635 | |
1636 switch (sb_button) | |
1637 { | |
1638 case BUTTON_TROUGH_ABOVE: | |
1639 decrement_value (w, w->sb.pageIncrement); | |
1640 w->sb.armed = ARM_PAGEUP; | |
1641 reason = XmCR_PAGE_DECREMENT; | |
1642 break; | |
1643 case BUTTON_TROUGH_BELOW: | |
1644 increment_value (w, w->sb.pageIncrement); | |
1645 w->sb.armed = ARM_PAGEDOWN; | |
1646 reason = XmCR_PAGE_INCREMENT; | |
1647 break; | |
1648 case BUTTON_SLIDER: | |
1649 w->sb.lastY = mouse_y; | |
1650 w->sb.armed = ARM_SLIDER; | |
1651 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1652 break; | |
1653 case BUTTON_UP_ARROW: | |
1654 if (event->xbutton.state & ControlMask) | |
1655 { | |
1656 w->sb.value = w->sb.minimum; | |
1657 reason = XmCR_TO_TOP; | |
1658 } | |
1659 else | |
1660 { | |
1661 decrement_value (w, w->sb.increment); | |
1662 reason = XmCR_DECREMENT; | |
1663 } | |
1664 w->sb.armed = ARM_UP; | |
1665 redraw_up_arrow (w, True, False); | |
1666 break; | |
1667 case BUTTON_DOWN_ARROW: | |
1668 if (event->xbutton.state & ControlMask) | |
1669 { | |
1670 w->sb.value = w->sb.maximum; | |
1671 reason = XmCR_TO_BOTTOM; | |
1672 } | |
1673 else | |
1674 { | |
1675 increment_value (w, w->sb.increment); | |
1676 reason = XmCR_INCREMENT; | |
1677 } | |
1678 w->sb.armed = ARM_DOWN; | |
1679 redraw_down_arrow (w, True, False); | |
1680 break; | |
1681 case BUTTON_NONE: | |
1682 ; /* Do nothing */ | |
1683 } | |
1684 | |
1685 verify_values (w); | |
1686 | |
1687 if (last_value != w->sb.value) | |
1688 { | |
1689 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1690 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1691 | |
1692 call_callbacks (w, reason, w->sb.value, mouse_y, event); | |
1693 | |
1694 if (w->sb.timerActive) | |
1695 XtRemoveTimeOut (w->sb.timerId); | |
1696 | |
1697 w->sb.timerId = | |
1698 XtAppAddTimeOut (XtWidgetToApplicationContext ((Widget) w), | |
1699 (unsigned long) w->sb.initialDelay, | |
1700 timer, (XtPointer) w); | |
1701 w->sb.timerActive = True; | |
1702 } | |
1703 | |
1704 CHECK (w); | |
1705 } | |
1706 | |
1707 static void | |
1708 PageDownOrRight (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) | |
1709 { | |
1710 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1711 w->sb.forced_scroll = FORCED_SCROLL_DOWNRIGHT; | |
1712 Select (widget, event, parms, num_parms); | |
1713 w->sb.forced_scroll = FORCED_SCROLL_NONE; | |
1714 } | |
1715 | |
1716 static void | |
1717 PageUpOrLeft (Widget widget, XEvent *event, String *parms, Cardinal *num_parms) | |
1718 { | |
1719 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1720 w->sb.forced_scroll = FORCED_SCROLL_UPLEFT; | |
1721 Select (widget, event, parms, num_parms); | |
1722 w->sb.forced_scroll = FORCED_SCROLL_NONE; | |
1723 } | |
1724 | |
1725 static void | |
2286 | 1726 Drag (Widget widget, XEvent *event, String *UNUSED (parms), |
1727 Cardinal *UNUSED (num_parms)) | |
428 | 1728 { |
1729 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1730 | |
1731 if (w->sb.armed == ARM_SLIDER) | |
1732 { | |
1733 int mouse_y = event_y (w, event); | |
1734 int diff = mouse_y - w->sb.lastY; | |
1735 | |
1736 if (diff < -(w->sb.above)) /* up */ | |
1737 { | |
1738 mouse_y -= (diff + w->sb.above); | |
1739 diff = -(w->sb.above); | |
1740 } | |
1741 else if (diff > w->sb.below) /* down */ | |
1742 { | |
1743 mouse_y -= (diff - w->sb.below); | |
1744 diff = w->sb.below; | |
1745 } | |
1746 | |
1747 if (diff) | |
1748 { | |
1749 w->sb.above += diff; | |
1750 w->sb.below -= diff; | |
1751 | |
1752 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1753 | |
1754 w->sb.lastY = mouse_y; | |
1755 | |
1756 w->sb.value = value_from_pixel (w, w->sb.above); | |
1757 verify_values (w); | |
1758 CHECK (w); | |
1759 | |
1760 call_callbacks (w, XmCR_DRAG, w->sb.value, event_y (w, event), event); | |
1761 } | |
1762 } | |
1763 CHECK (w); | |
1764 } | |
1765 | |
1766 static void | |
2286 | 1767 Release (Widget widget, XEvent *event, String *UNUSED (parms), |
1768 Cardinal *UNUSED (num_parms)) | |
428 | 1769 { |
1770 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1771 | |
1772 switch (w->sb.armed) | |
1773 { | |
1774 case ARM_SLIDER: | |
1775 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, event_y (w, event), event); | |
1776 w->sb.armed = ARM_NONE; | |
1777 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1778 break; | |
1779 case ARM_UP: | |
1780 redraw_up_arrow (w, False, False); | |
1781 break; | |
1782 case ARM_DOWN: | |
1783 redraw_down_arrow (w, False, False); | |
1784 break; | |
1785 default: | |
1786 ; /* Do nothing */ | |
1787 } | |
1788 | |
1789 XtUngrabKeyboard ((Widget) w, event->xbutton.time); | |
1790 | |
1791 w->sb.armed = ARM_NONE; | |
1792 } | |
1793 | |
1794 static void | |
2286 | 1795 Jump (Widget widget, XEvent *event, String *UNUSED (parms), |
1796 Cardinal *UNUSED (num_parms)) | |
428 | 1797 { |
1798 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1799 int last_value; | |
1800 | |
1801 int mouse_x = event_x (w, event); | |
1802 int mouse_y = event_y (w, event); | |
1803 | |
1804 int scroll_region_y = widget_y (w); | |
1805 int scroll_region_h = widget_h (w); | |
1806 | |
1807 if (w->sb.showArrows) | |
1808 { | |
1809 int arrow_height = arrow_h (w); | |
1810 scroll_region_h -= 2 * arrow_height; | |
1811 if (!arrow_same_end (w)) | |
1812 scroll_region_y += arrow_height; | |
1813 } | |
1814 | |
1815 XtGrabKeyboard ((Widget) w, False, GrabModeAsync, GrabModeAsync, | |
1816 event->xbutton.time); | |
1817 | |
1818 switch (what_button (w, mouse_x, mouse_y)) | |
1819 { | |
1820 case BUTTON_TROUGH_ABOVE: | |
1821 case BUTTON_TROUGH_BELOW: | |
1822 case BUTTON_SLIDER: | |
1823 w->sb.savedValue = w->sb.value; | |
1824 | |
1825 last_value = w->sb.value; | |
1826 | |
1827 w->sb.above = mouse_y - (w->sb.ss / 2) - scroll_region_y; | |
1828 if (w->sb.above < 0) | |
1829 w->sb.above = 0; | |
1830 else if (w->sb.above + w->sb.ss > scroll_region_h) | |
1831 w->sb.above = scroll_region_h - w->sb.ss; | |
1832 | |
1833 w->sb.below = scroll_region_h - w->sb.ss - w->sb.above; | |
1834 | |
1835 w->sb.armed = ARM_SLIDER; | |
1836 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1837 | |
1838 w->sb.value = value_from_pixel (w, w->sb.above); | |
1839 verify_values (w); | |
1840 CHECK (w); | |
1841 | |
1842 w->sb.lastY = mouse_y; | |
1843 | |
1844 if (w->sb.value != last_value) | |
1845 call_callbacks (w, XmCR_DRAG, w->sb.value, mouse_y, event); | |
1846 | |
1847 break; | |
1848 default: | |
1849 ; /* Do nothing */ | |
1850 } | |
1851 CHECK (w); | |
1852 } | |
1853 | |
1854 static void | |
2286 | 1855 Abort (Widget widget, XEvent *event, String *UNUSED (parms), |
1856 Cardinal *UNUSED (num_parms)) | |
428 | 1857 { |
1858 XlwScrollBarWidget w = (XlwScrollBarWidget) widget; | |
1859 | |
1860 if (w->sb.armed != ARM_NONE) | |
1861 { | |
1862 if (w->sb.value != w->sb.savedValue) | |
1863 { | |
1864 w->sb.value = w->sb.savedValue; | |
1865 | |
1866 seg_pixel_sizes (w, &w->sb.above, &w->sb.ss, &w->sb.below); | |
1867 draw_slider (w, w->sb.above, w->sb.ss, w->sb.below); | |
1868 | |
1869 call_callbacks (w, XmCR_VALUE_CHANGED, w->sb.value, | |
1870 event_y (w, event), event); | |
1871 } | |
1872 | |
1873 switch (w->sb.armed) | |
1874 { | |
1875 case ARM_UP: redraw_up_arrow (w, False, False); break; | |
1876 case ARM_DOWN: redraw_down_arrow (w, False, False); break; | |
1877 default: ; /* Do nothing */ | |
1878 } | |
1879 | |
1880 w->sb.armed = ARM_NONE; | |
1881 | |
1882 XtUngrabKeyboard ((Widget) w, event->xbutton.time); | |
1883 } | |
1884 } |