Initial commit, 3-52-19 alpha
[cls.git] / src / c / X11slider.c
blob7777ce5b09ccfca8060efcfef2cbc3fca11b4bab
1 /* X11slider - slider/scroll items for X11 dialogs */
2 /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
3 /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
4 /* You may give out copies of this software; for conditions see the */
5 /* file COPYING included with this distribution. */
7 /***********************************************************************/
8 /** **/
9 /** General Includes and Definitions **/
10 /** **/
11 /***********************************************************************/
13 #include "dialogs.h"
15 extern Display *StX11Display();
16 extern Point DialogStringSize();
17 extern LVAL StX11ItemObject();
18 extern char *checkstring();
19 extern LVAL s_window_id;
21 typedef struct {
22 unsigned long fore, back;
23 } ColorPair;
25 /* layout defines */
26 # define BUTTON_SIZE 16
27 # define MIN_SLIDER_HEIGHT 16
28 # define MIN_SLIDER_WIDTH 250
29 # define THUMB_WIDTH BUTTON_SIZE / 2
31 /* forward declarations */
32 LOCAL VOID check_value _((LVAL item));
34 /***********************************************************************/
35 /** **/
36 /** Global Variables **/
37 /** **/
38 /***********************************************************************/
40 /* configuration parameters - should be set using the defaults database */
41 extern XFontStruct *DialogFont;
42 extern unsigned long DialogBorderColor;
43 extern ColorPair DialogC;
44 extern unsigned int dialog_border_width;
45 extern int min_slider_width;
47 extern GC DialogGC, DialogRGC;
49 extern XContext ObjectContext, Button1Context,
50 Button2Context, ThumbContext;
52 extern Pixmap LeftSliderPM, RightSliderPM;
53 extern Cursor DoubleArrowCursor, RightArrowCursor, LeftArrowCursor,
54 ArrowCursor;
56 /***********************************************************************/
57 /** **/
58 /** Slider Items **/
59 /** **/
60 /***********************************************************************/
62 static VOID adjust_slider(item)
63 LVAL item;
65 Display *dpy = StX11Display();
66 LVAL win_id;
67 Window win, thumb;
68 Point size;
69 int left, low, high, val, width;
70 double x;
72 win_id = slot_value(item, s_window_id);
73 if (fixp(win_id)) {
74 win = (Window) getfixnum(win_id);
75 size = ListToPoint(slot_value(item, s_size));
76 low = getfixnum(slot_value(item, s_min_value));
77 high = getfixnum(slot_value(item, s_max_value));
78 val = getfixnum(slot_value(item, s_value));
79 width = size.h - 2 * BUTTON_SIZE - THUMB_WIDTH;
80 if (low < high) {
81 x = ((double) (val - low)) / ((double) (high - low));
82 left = BUTTON_SIZE + x * width;
83 left = max(BUTTON_SIZE, min(left, width + BUTTON_SIZE));
85 else left = BUTTON_SIZE;
86 if (XFindContext(dpy, win, ThumbContext, (caddr_t *) &thumb) != 0)
87 xlfail("can't find thumb context");
88 XMoveWindow(dpy, thumb, left, 0);
92 static VOID track_thumb(dpy, win, report, item)
93 Display *dpy;
94 Window win;
95 XEvent report;
96 LVAL item;
98 Point size;
99 int low, high, val, old_val, width, page, up, done = FALSE;
100 double x;
102 size = ListToPoint(slot_value(item, s_size));
103 low = getfixnum(slot_value(item, s_min_value));
104 high = getfixnum(slot_value(item, s_max_value));
105 width = size.h - 2 * BUTTON_SIZE - THUMB_WIDTH;
107 switch (report.xbutton.button) {
108 case Button1:
109 case Button3:
110 up = (report.xbutton.button == Button3) ? TRUE : FALSE;
111 XDefineCursor(dpy, win, (up) ? RightArrowCursor : LeftArrowCursor);
112 old_val = low - 1; /* an "impossible" value */
113 while (! done) {
114 if (XCheckTypedEvent(dpy, ButtonRelease, &report)) done = TRUE;
115 else{
116 val = getfixnum(slot_value(item, s_value));
117 page = getfixnum(slot_value(item, s_page_increment));
118 if (up) val += page;
119 else val -= page;
120 val = max(low, min(val, high));
121 DialogScrollItemValue(item, TRUE, val);
122 if (val != old_val) send_message(item, sk_scroll_action);
123 old_val = val;
124 XSync(dpy, FALSE);
127 break;
128 case Button2:
129 if (width > 0)
130 x = ((double) report.xbutton.x - BUTTON_SIZE) / ((double) width);
131 else x = 0.0;
132 val = low + x * (high - low);
133 val = max(low, min(val, high));
134 DialogScrollItemValue(item, TRUE, val);
135 #ifdef DODO
136 XGrabPointer(dpy, win, TRUE, ButtonMotionMask,
137 GrabModeAsync, GrabModeAsync, win,
138 DoubleArrowCursor, CurrentTime);
139 #endif /* DODO */
140 while (! done) {
141 XNextEvent(dpy, &report);
142 switch (report.type) {
143 case ButtonRelease:
144 done = TRUE;
145 break;
146 case MotionNotify:
147 x = ((double) report.xmotion.x - BUTTON_SIZE) / ((double) width);
148 val = low + x * (high - low);
149 val = max(low, min(val, high));
150 DialogScrollItemValue(item, TRUE, val);
151 break;
152 default:
153 break;
156 #ifdef DODO
157 XUngrabPointer(dpy, CurrentTime);
158 #endif /* DODO */
159 send_message(item, sk_do_action);
160 XSync(dpy, FALSE);
161 break;
164 XDefineCursor(dpy, win, DoubleArrowCursor);
167 static LVAL slider_handler(report, modal)
168 XEvent report;
169 int modal;
171 Display *dpy = StX11Display();
172 Window win;
173 LVAL item;
174 LVAL result = NIL;
176 win = report.xany.window;
177 item = StX11ItemObject(dpy, win);
178 if (item != NIL) {
179 switch (report.type) {
180 case Expose:
181 break;
182 case ButtonPress:
183 track_thumb(dpy, win, report, item);
185 if (! modal) {
186 send_message(item, sk_do_action);
187 XSync(dpy, FALSE);
190 /* send_message(item, sk_do_action);*/
191 XSync(dpy, FALSE);
192 break;
193 case ButtonRelease:
194 break;
195 default:
196 break;
199 return(result);
202 static LVAL button_handler(report, is_right)
203 XEvent report;
204 int is_right;
206 Display *dpy = StX11Display();
207 Window win;
208 LVAL item;
209 LVAL result = NIL;
210 int low, high, val, done, old_val;
212 win = report.xany.window;
213 item = StX11ItemObject(dpy, win);
214 if (item != NIL) {
215 switch (report.type) {
216 case ButtonPress:
217 done = FALSE;
218 low = getfixnum(slot_value(item, s_min_value));
219 high = getfixnum(slot_value(item, s_max_value));
220 old_val = low - 1; /* an "impossible" value */
221 while (! done) {
222 if (XCheckTypedEvent(dpy, ButtonRelease, &report)) done = TRUE;
223 else {
224 val = getfixnum(slot_value(item, s_value));
225 if (is_right) val++;
226 else val--;
227 val = max(low, min(val, high));
228 DialogScrollItemValue(item, TRUE, val);
229 if (val != old_val) send_message(item, sk_scroll_action);
230 old_val = val;
231 XSync(dpy, FALSE);
234 /* send_message(item, sk_do_action); */
235 break;
236 default:
237 break;
240 return(result);
243 static LVAL left_button_handler(report, modal)
244 XEvent report;
245 int modal;
247 return(button_handler(report, FALSE));
250 static LVAL right_button_handler(report, modal)
251 XEvent report;
252 int modal;
254 return(button_handler(report, TRUE));
257 VOID InstallScrollItem(win, item)
258 Window win;
259 LVAL item;
261 Display *dpy = StX11Display();
262 Point loc, size;
263 Window slider, button1, button2, thumb;
265 check_value(item);
266 loc = ListToPoint(slot_value(item, s_location));
267 size = ListToPoint(slot_value(item, s_size));
268 size.v = BUTTON_SIZE;
269 slider = XCreateSimpleWindow(dpy, win, loc.h, loc.v, size.h, size.v,
270 dialog_border_width,
271 DialogBorderColor, DialogC.back);
272 XSelectInput(dpy, slider,
273 ExposureMask | ButtonMotionMask |
274 ButtonPressMask | ButtonReleaseMask);
275 XDefineCursor(dpy, slider, DoubleArrowCursor);
277 button1 = XCreateSimpleWindow(dpy, slider,
278 -dialog_border_width, -dialog_border_width,
279 BUTTON_SIZE, BUTTON_SIZE,
280 dialog_border_width,
281 DialogBorderColor, DialogC.back);
282 XSelectInput(dpy, button1,
283 ExposureMask | ButtonPressMask | ButtonReleaseMask);
284 XSetWindowBackgroundPixmap(dpy, button1, LeftSliderPM);
285 #ifdef DODO
286 XDefineCursor(dpy, button1, LeftArrowCursor);
287 #endif /* DODO */
288 XDefineCursor(dpy, button1, ArrowCursor);
290 button2 = XCreateSimpleWindow(dpy, slider,
291 size.h - BUTTON_SIZE, -dialog_border_width,
292 BUTTON_SIZE, BUTTON_SIZE,
293 dialog_border_width,
294 DialogBorderColor, DialogC.back);
295 XSelectInput(dpy, button2,
296 ExposureMask | ButtonPressMask | ButtonReleaseMask);
297 XSetWindowBackgroundPixmap(dpy, button2, RightSliderPM);
298 #ifdef DODO
299 XDefineCursor(dpy, button2, RightArrowCursor);
300 #endif /* DODO */
301 XDefineCursor(dpy, button2, ArrowCursor);
303 thumb = XCreateSimpleWindow(dpy, slider, BUTTON_SIZE, 0,
304 THUMB_WIDTH, BUTTON_SIZE,
305 0, DialogBorderColor, DialogC.fore);
307 set_slot_value(item, s_window_id, cvfixnum((FIXTYPE) slider));
309 install_dialog_item_handler(dpy, slider, slider_handler, item);
310 if (XSaveContext(dpy, slider, ObjectContext, (caddr_t) item) != 0)
311 xlfail("could not install object in window");
312 if (XSaveContext(dpy, slider, ThumbContext, (caddr_t) thumb) != 0)
313 xlfail("could not install thumb in slider");
315 if (XSaveContext(dpy, slider, Button1Context, (caddr_t) button1) != 0)
316 xlfail("could not install left button in slider");
317 install_dialog_item_handler(dpy, button1, left_button_handler, item);
318 if (XSaveContext(dpy, button1, ObjectContext, (caddr_t) item) != 0)
319 xlfail("could not install object in window");
321 if (XSaveContext(dpy, slider, Button2Context, (caddr_t) button2) != 0)
322 xlfail("could not install right button in slider");
323 install_dialog_item_handler(dpy, button2, right_button_handler, item);
324 if (XSaveContext(dpy, button2, ObjectContext, (caddr_t) item) != 0)
325 xlfail("could not install object in window");
327 adjust_slider(item);
329 XMapSubwindows(dpy, slider);
332 VOID DeleteScrollItem(win, item)
333 Window win;
334 LVAL item;
336 Display *dpy = StX11Display();
337 Window slider, button1, button2;
339 slider = (Window) getfixnum(slot_value(item, s_window_id));
341 delete_dialog_item_handler(dpy, slider);
342 if (XDeleteContext(dpy, slider, ObjectContext) != 0)
343 xlfail("could not delete object context");
344 if (XDeleteContext(dpy, slider, ThumbContext) != 0)
345 xlfail("could not delete thumb context");
347 if (XFindContext(dpy, slider, Button1Context, (caddr_t *) &button1) != 0)
348 xlfail("can't find left button context");
349 if (XDeleteContext(dpy, slider, Button1Context) != 0)
350 xlfail("could not delete left button context");
351 delete_dialog_item_handler(dpy, button1);
352 if (XDeleteContext(dpy, button1, ObjectContext) != 0)
353 xlfail("could not delete object context");
355 if (XFindContext(dpy, slider, Button2Context, (caddr_t *) &button2) != 0)
356 xlfail("can't find right button context");
357 if (XDeleteContext(dpy, slider, Button2Context) != 0)
358 xlfail("could not delete right button context");
359 delete_dialog_item_handler(dpy, button2);
360 if (XDeleteContext(dpy, button2, ObjectContext) != 0)
361 xlfail("could not delete object context");
363 set_slot_value(item, s_window_id, NIL);
366 VOID DialogScrollGetDefaultSize(item, width, height)
367 LVAL item;
368 int *width, *height;
370 if (width != NULL) *width = MIN_SLIDER_WIDTH;
371 if (height != NULL) *height = MIN_SLIDER_HEIGHT;
374 LVAL DialogScrollItemValue(item, set, value)
375 LVAL item;
376 int set, value;
378 if (set) {
379 set_slot_value(item, s_value, cvfixnum((FIXTYPE) value));
380 check_value(item);
381 adjust_slider(item);
383 else check_value(item);
385 return(slot_value(item, s_value));
388 LVAL DialogScrollItemMin(item, set, value)
389 LVAL item;
390 int set, value;
392 if (set) {
393 set_slot_value(item, s_min_value, cvfixnum((FIXTYPE) value));
394 check_value(item);
395 adjust_slider(item);
397 return(slot_value(item, s_min_value));
400 LVAL DialogScrollItemMax(item, set, value)
401 LVAL item;
402 int set, value;
404 if (set) {
405 set_slot_value(item, s_max_value, cvfixnum((FIXTYPE) value));
406 check_value(item);
407 adjust_slider(item);
409 return(slot_value(item, s_max_value));
412 LOCAL VOID check_value(item)
413 LVAL item;
415 LVAL low, high, value;
416 int ilow, ihigh, ivalue;
418 low = slot_value(item, s_min_value);
419 high = slot_value(item, s_max_value);
420 value = slot_value(item, s_value);
422 ilow = (fixp(low)) ? getfixnum(low): 0;
423 ihigh = (fixp(high)) ? getfixnum(high) : 100;
424 ivalue = (fixp(value)) ? getfixnum(value) : ilow;
426 if (ilow >= ihigh) ihigh = ilow + 1;
427 ivalue = max(ilow, min(ihigh, ivalue));
429 if (! fixp(low) || ilow != getfixnum(low))
430 set_slot_value(item, s_min_value, cvfixnum((FIXTYPE) ilow));
431 if (! fixp(high) || ihigh != getfixnum(high))
432 set_slot_value(item, s_max_value, cvfixnum((FIXTYPE) ihigh));
433 if (! fixp(value) || ivalue != getfixnum(value))
434 set_slot_value(item, s_value, cvfixnum((FIXTYPE) ivalue));