1 /* This file contains routines to manipulate scrollbar widgets (either
2 * horizontal or vertical ones).
3 *
4 * This code is under the GNU Copyleft.
5 *
6 * Dominic Giampaolo
7 * dbg@sgi.com
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include "xstuff.h"
13
14 #ifdef sgi
15 /*
16 * little fixes for the botched up SGI Xaw/Scrollbar.h header file...
17 */
18 #define NeedFunctionPrototypes 1 /* Make DAMN sure we pick up prototypes */
19 #undef NeedWidePrototypes
20 #endif
21
22 #include <X11/Xaw/Scrollbar.h>
23 #include "libsx.h"
24 #include "libsx_private.h"
25
26
27 extern WindowState *lsx_curwin; /* global handle to the current window */
28
29
30
31 /*
32 * this structure maintains some internal state information about each
33 * scrollbar.
34 */
35 typedef struct ScrollInfo
36 {
37 Widget scroll_widget;
38 float max,where_is,size_shown;
39 float val;
40 void (*func)(Widget widg, float val, void *data);
41 void *user_data;
42
43 struct ScrollInfo *next;
44 }ScrollInfo;
45
46 static ScrollInfo *scroll_bars = NULL;
47
48
49 /*
50 * This is called when the user interactively uses the middle mouse
51 * button to move the slider.
52 */
my_jump_proc(Widget scroll_widget,XtPointer client_data,XtPointer percent)53 void my_jump_proc(Widget scroll_widget, XtPointer client_data,
54 XtPointer percent)
55 {
56 ScrollInfo *si = (ScrollInfo *)client_data;
57 float old_val = si->val;
58
59 /* We want the scrollbar to be at 100% when the right edge of the slider
60 * hits the end of the scrollbar, not the left edge. When the right edge
61 * is at 1.0, the left edge is at 1.0 - size_shown. Normalize
62 * accordingly.
63 */
64
65 si->val = (*(float *) percent) * si->max;
66
67
68 if ((si->val + si->size_shown > si->max)
69 && fabs((double)(si->size_shown - si->max)) > 0.01)
70 {
71 si->val = si->max - si->size_shown;
72 XawScrollbarSetThumb(si->scroll_widget, si->val/si->max,
73 si->size_shown / si->max);
74 }
75 else if (si->val <= 0)
76 si->val = 0;
77
78 si->where_is = si->val;
79
80
81 if (si->func && old_val != si->val)
82 (*si->func)(si->scroll_widget, si->val, si->user_data);
83 }
84
85
86 /*
87 * This is called whenever the user uses the left or right mouse buttons
88 */
my_scroll_proc(Widget scroll_widget,XtPointer client_data,XtPointer position)89 void my_scroll_proc(Widget scroll_widget, XtPointer client_data,
90 XtPointer position)
91 {
92 int pos;
93 ScrollInfo *si = (ScrollInfo *)client_data;
94 float old_val = si->val;
95
96 pos = (int)position;
97
98 if (pos < 0) /* button 3 pressed, go up */
99 {
100 si->val -= (0.1 * si->max); /* go up ten percent at a time */
101 }
102 else /* button 2 pressed, go down */
103 {
104 si->val += (0.1 * si->max); /* go down ten percent at a time */
105 }
106
107
108 if (si->size_shown != si->max && (si->val + si->size_shown) >= si->max)
109 si->val = si->max - si->size_shown;
110 else if (si->val >= si->max)
111 si->val = si->max;
112 else if (si->val <= 0.0)
113 si->val = 0.0;
114
115 XawScrollbarSetThumb(scroll_widget,si->val/si->max, si->size_shown/si->max);
116
117 si->where_is = si->val;
118 if (si->func && old_val != si->val)
119 (*si->func)(si->scroll_widget, si->val, si->user_data);
120 }
121
122
123
SetScrollbar(Widget w,float where,float max,float size_shown)124 void SetScrollbar(Widget w, float where, float max, float size_shown)
125 {
126 ScrollInfo *si;
127
128 if (lsx_curwin->toplevel == NULL || w == NULL)
129 return;
130
131
132 /*
133 * Here we have to search for the correct ScrollInfo structure.
134 * This is kind of hackish, but is the easiest way to make the
135 * interfaces to all this easy and consistent with the other
136 * routines.
137 */
138 for(si=scroll_bars; si; si=si->next)
139 {
140 for(; si && si->scroll_widget != w; si=si->next)
141 ;
142
143 if (si == NULL)
144 break;
145 if (XtDisplay(si->scroll_widget) == XtDisplay(w))
146 break;
147 }
148
149 if (si == NULL)
150 return;
151
152
153 si->where_is = where;
154 if (max > -0.0001 && max < 0.0001)
155 max = 0.0001;
156
157 si->max = max;
158 if (fabs((double)max - size_shown) > 0.01)
159 si->max += size_shown;
160 si->size_shown = size_shown;
161 si->val = si->where_is;
162
163 XawScrollbarSetThumb(si->scroll_widget, si->where_is/si->max,
164 si->size_shown/si->max);
165 }
166
167
168 /*
169 * Scrollbar Creation/Manipulation routines.
170 *
171 */
MakeScrollbar(int length,ScrollCB scroll_func,void * data,int orientation)172 static Widget MakeScrollbar(int length, ScrollCB scroll_func, void *data,
173 int orientation)
174 {
175 int n = 0;
176 Arg wargs[5]; /* Used to set widget resources */
177 Widget scroll_widget;
178 ScrollInfo *si;
179
180 if (lsx_curwin->toplevel == NULL && OpenDisplay(0, NULL) == 0)
181 return NULL;
182
183
184 si = (ScrollInfo *)calloc(sizeof(ScrollInfo), 1);
185 if (si == NULL)
186 return NULL;
187
188 si->func = scroll_func;
189 si->user_data = data;
190 si->size_shown = si->max = 1.0;
191 si->val = si->where_is = 0.0;
192
193 n = 0;
194 XtSetArg(wargs[n], XtNorientation, orientation); n++;
195 XtSetArg(wargs[n], XtNlength, length); n++;
196
197 scroll_widget = XtCreateManagedWidget("scrollbar", scrollbarWidgetClass,
198 lsx_curwin->form_widget,wargs,n);
199
200 if (scroll_widget == NULL)
201 {
202 free(si);
203 return NULL;
204 }
205 si->scroll_widget = scroll_widget;
206 si->next = scroll_bars;
207 scroll_bars = si;
208
209 XtAddCallback(scroll_widget, XtNjumpProc, my_jump_proc, si);
210 XtAddCallback(scroll_widget, XtNscrollProc, my_scroll_proc, si);
211
212
213 return scroll_widget;
214 }
215
216
MakeVertScrollbar(int height,ScrollCB scroll_func,void * data)217 Widget MakeVertScrollbar(int height, ScrollCB scroll_func, void *data)
218 {
219 return MakeScrollbar(height, scroll_func, data, XtorientVertical);
220 }
221
222
MakeHorizScrollbar(int length,ScrollCB scroll_func,void * data)223 Widget MakeHorizScrollbar(int length, ScrollCB scroll_func, void *data)
224 {
225 return MakeScrollbar(length, scroll_func, data,
226 XtorientHorizontal);
227 }
228
229
230