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 /***********************************************************************/
9 /** General Includes and Definitions **/
11 /***********************************************************************/
15 extern Display
*StX11Display();
16 extern Point
DialogStringSize();
17 extern LVAL
StX11ItemObject();
18 extern char *checkstring();
19 extern LVAL s_window_id
;
22 unsigned long fore
, back
;
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 /***********************************************************************/
36 /** Global Variables **/
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
,
56 /***********************************************************************/
60 /***********************************************************************/
62 static VOID
adjust_slider(item
)
65 Display
*dpy
= StX11Display();
69 int left
, low
, high
, val
, width
;
72 win_id
= slot_value(item
, s_window_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
;
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
)
99 int low
, high
, val
, old_val
, width
, page
, up
, done
= FALSE
;
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
) {
110 up
= (report
.xbutton
.button
== Button3
) ? TRUE
: FALSE
;
111 XDefineCursor(dpy
, win
, (up
) ? RightArrowCursor
: LeftArrowCursor
);
112 old_val
= low
- 1; /* an "impossible" value */
114 if (XCheckTypedEvent(dpy
, ButtonRelease
, &report
)) done
= TRUE
;
116 val
= getfixnum(slot_value(item
, s_value
));
117 page
= getfixnum(slot_value(item
, s_page_increment
));
120 val
= max(low
, min(val
, high
));
121 DialogScrollItemValue(item
, TRUE
, val
);
122 if (val
!= old_val
) send_message(item
, sk_scroll_action
);
130 x
= ((double) report
.xbutton
.x
- BUTTON_SIZE
) / ((double) width
);
132 val
= low
+ x
* (high
- low
);
133 val
= max(low
, min(val
, high
));
134 DialogScrollItemValue(item
, TRUE
, val
);
136 XGrabPointer(dpy
, win
, TRUE
, ButtonMotionMask
,
137 GrabModeAsync
, GrabModeAsync
, win
,
138 DoubleArrowCursor
, CurrentTime
);
141 XNextEvent(dpy
, &report
);
142 switch (report
.type
) {
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
);
157 XUngrabPointer(dpy
, CurrentTime
);
159 send_message(item
, sk_do_action
);
164 XDefineCursor(dpy
, win
, DoubleArrowCursor
);
167 static LVAL
slider_handler(report
, modal
)
171 Display
*dpy
= StX11Display();
176 win
= report
.xany
.window
;
177 item
= StX11ItemObject(dpy
, win
);
179 switch (report
.type
) {
183 track_thumb(dpy
, win
, report
, item
);
186 send_message(item, sk_do_action);
190 /* send_message(item, sk_do_action);*/
202 static LVAL
button_handler(report
, is_right
)
206 Display
*dpy
= StX11Display();
210 int low
, high
, val
, done
, old_val
;
212 win
= report
.xany
.window
;
213 item
= StX11ItemObject(dpy
, win
);
215 switch (report
.type
) {
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 */
222 if (XCheckTypedEvent(dpy
, ButtonRelease
, &report
)) done
= TRUE
;
224 val
= getfixnum(slot_value(item
, s_value
));
227 val
= max(low
, min(val
, high
));
228 DialogScrollItemValue(item
, TRUE
, val
);
229 if (val
!= old_val
) send_message(item
, sk_scroll_action
);
234 /* send_message(item, sk_do_action); */
243 static LVAL
left_button_handler(report
, modal
)
247 return(button_handler(report
, FALSE
));
250 static LVAL
right_button_handler(report
, modal
)
254 return(button_handler(report
, TRUE
));
257 VOID
InstallScrollItem(win
, item
)
261 Display
*dpy
= StX11Display();
263 Window slider
, button1
, button2
, thumb
;
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
,
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
,
281 DialogBorderColor
, DialogC
.back
);
282 XSelectInput(dpy
, button1
,
283 ExposureMask
| ButtonPressMask
| ButtonReleaseMask
);
284 XSetWindowBackgroundPixmap(dpy
, button1
, LeftSliderPM
);
286 XDefineCursor(dpy
, button1
, LeftArrowCursor
);
288 XDefineCursor(dpy
, button1
, ArrowCursor
);
290 button2
= XCreateSimpleWindow(dpy
, slider
,
291 size
.h
- BUTTON_SIZE
, -dialog_border_width
,
292 BUTTON_SIZE
, BUTTON_SIZE
,
294 DialogBorderColor
, DialogC
.back
);
295 XSelectInput(dpy
, button2
,
296 ExposureMask
| ButtonPressMask
| ButtonReleaseMask
);
297 XSetWindowBackgroundPixmap(dpy
, button2
, RightSliderPM
);
299 XDefineCursor(dpy
, button2
, RightArrowCursor
);
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");
329 XMapSubwindows(dpy
, slider
);
332 VOID
DeleteScrollItem(win
, 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
)
370 if (width
!= NULL
) *width
= MIN_SLIDER_WIDTH
;
371 if (height
!= NULL
) *height
= MIN_SLIDER_HEIGHT
;
374 LVAL
DialogScrollItemValue(item
, set
, value
)
379 set_slot_value(item
, s_value
, cvfixnum((FIXTYPE
) value
));
383 else check_value(item
);
385 return(slot_value(item
, s_value
));
388 LVAL
DialogScrollItemMin(item
, set
, value
)
393 set_slot_value(item
, s_min_value
, cvfixnum((FIXTYPE
) value
));
397 return(slot_value(item
, s_min_value
));
400 LVAL
DialogScrollItemMax(item
, set
, value
)
405 set_slot_value(item
, s_max_value
, cvfixnum((FIXTYPE
) value
));
409 return(slot_value(item
, s_max_value
));
412 LOCAL VOID
check_value(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
));