/* X11slider - slider/scroll items for X11 dialogs */
/* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
/* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
/* You may give out copies of this software; for conditions see the */
/* file COPYING included with this distribution. */
/***********************************************************************/
/** **/
/** General Includes and Definitions **/
/** **/
/***********************************************************************/
#include "dialogs.h"
extern Display *StX11Display();
extern Point DialogStringSize();
extern LVAL StX11ItemObject();
extern char *checkstring();
extern LVAL s_window_id;
typedef struct {
unsigned long fore, back;
} ColorPair;
/* layout defines */
# define BUTTON_SIZE 16
# define MIN_SLIDER_HEIGHT 16
# define MIN_SLIDER_WIDTH 250
# define THUMB_WIDTH BUTTON_SIZE / 2
/* forward declarations */
LOCAL VOID check_value _((LVAL item));
/***********************************************************************/
/** **/
/** Global Variables **/
/** **/
/***********************************************************************/
/* configuration parameters - should be set using the defaults database */
extern XFontStruct *DialogFont;
extern unsigned long DialogBorderColor;
extern ColorPair DialogC;
extern unsigned int dialog_border_width;
extern int min_slider_width;
extern GC DialogGC, DialogRGC;
extern XContext ObjectContext, Button1Context,
Button2Context, ThumbContext;
extern Pixmap LeftSliderPM, RightSliderPM;
extern Cursor DoubleArrowCursor, RightArrowCursor, LeftArrowCursor,
ArrowCursor;
/***********************************************************************/
/** **/
/** Slider Items **/
/** **/
/***********************************************************************/
static VOID adjust_slider(item)
LVAL item;
{
Display *dpy = StX11Display();
LVAL win_id;
Window win, thumb;
Point size;
int left, low, high, val, width;
double x;
win_id = slot_value(item, s_window_id);
if (fixp(win_id)) {
win = (Window) getfixnum(win_id);
size = ListToPoint(slot_value(item, s_size));
low = getfixnum(slot_value(item, s_min_value));
high = getfixnum(slot_value(item, s_max_value));
val = getfixnum(slot_value(item, s_value));
width = size.h - 2 * BUTTON_SIZE - THUMB_WIDTH;
if (low < high) {
x = ((double) (val - low)) / ((double) (high - low));
left = BUTTON_SIZE + x * width;
left = max(BUTTON_SIZE, min(left, width + BUTTON_SIZE));
}
else left = BUTTON_SIZE;
if (XFindContext(dpy, win, ThumbContext, (caddr_t *) &thumb) != 0)
xlfail("can't find thumb context");
XMoveWindow(dpy, thumb, left, 0);
}
}
static VOID track_thumb(dpy, win, report, item)
Display *dpy;
Window win;
XEvent report;
LVAL item;
{
Point size;
int low, high, val, old_val, width, page, up, done = FALSE;
double x;
size = ListToPoint(slot_value(item, s_size));
low = getfixnum(slot_value(item, s_min_value));
high = getfixnum(slot_value(item, s_max_value));
width = size.h - 2 * BUTTON_SIZE - THUMB_WIDTH;
switch (report.xbutton.button) {
case Button1:
case Button3:
up = (report.xbutton.button == Button3) ? TRUE : FALSE;
XDefineCursor(dpy, win, (up) ? RightArrowCursor : LeftArrowCursor);
old_val = low - 1; /* an "impossible" value */
while (! done) {
if (XCheckTypedEvent(dpy, ButtonRelease, &report)) done = TRUE;
else{
val = getfixnum(slot_value(item, s_value));
page = getfixnum(slot_value(item, s_page_increment));
if (up) val += page;
else val -= page;
val = max(low, min(val, high));
DialogScrollItemValue(item, TRUE, val);
if (val != old_val) send_message(item, sk_scroll_action);
old_val = val;
XSync(dpy, FALSE);
}
}
break;
case Button2:
if (width > 0)
x = ((double) report.xbutton.x - BUTTON_SIZE) / ((double) width);
else x = 0.0;
val = low + x * (high - low);
val = max(low, min(val, high));
DialogScrollItemValue(item, TRUE, val);
#ifdef DODO
XGrabPointer(dpy, win, TRUE, ButtonMotionMask,
GrabModeAsync, GrabModeAsync, win,
DoubleArrowCursor, CurrentTime);
#endif /* DODO */
while (! done) {
XNextEvent(dpy, &report);
switch (report.type) {
case ButtonRelease:
done = TRUE;
break;
case MotionNotify:
x = ((double) report.xmotion.x - BUTTON_SIZE) / ((double) width);
val = low + x * (high - low);
val = max(low, min(val, high));
DialogScrollItemValue(item, TRUE, val);
break;
default:
break;
}
}
#ifdef DODO
XUngrabPointer(dpy, CurrentTime);
#endif /* DODO */
send_message(item, sk_do_action);
XSync(dpy, FALSE);
break;
}
XDefineCursor(dpy, win, DoubleArrowCursor);
}
static LVAL slider_handler(report, modal)
XEvent report;
int modal;
{
Display *dpy = StX11Display();
Window win;
LVAL item;
LVAL result = NIL;
win = report.xany.window;
item = StX11ItemObject(dpy, win);
if (item != NIL) {
switch (report.type) {
case Expose:
break;
case ButtonPress:
track_thumb(dpy, win, report, item);
/*
if (! modal) {
send_message(item, sk_do_action);
XSync(dpy, FALSE);
}
*/
/* send_message(item, sk_do_action);*/
XSync(dpy, FALSE);
break;
case ButtonRelease:
break;
default:
break;
}
}
return(result);
}
static LVAL button_handler(report, is_right)
XEvent report;
int is_right;
{
Display *dpy = StX11Display();
Window win;
LVAL item;
LVAL result = NIL;
int low, high, val, done, old_val;
win = report.xany.window;
item = StX11ItemObject(dpy, win);
if (item != NIL) {
switch (report.type) {
case ButtonPress:
done = FALSE;
low = getfixnum(slot_value(item, s_min_value));
high = getfixnum(slot_value(item, s_max_value));
old_val = low - 1; /* an "impossible" value */
while (! done) {
if (XCheckTypedEvent(dpy, ButtonRelease, &report)) done = TRUE;
else {
val = getfixnum(slot_value(item, s_value));
if (is_right) val++;
else val--;
val = max(low, min(val, high));
DialogScrollItemValue(item, TRUE, val);
if (val != old_val) send_message(item, sk_scroll_action);
old_val = val;
XSync(dpy, FALSE);
}
}
/* send_message(item, sk_do_action); */
break;
default:
break;
}
}
return(result);
}
static LVAL left_button_handler(report, modal)
XEvent report;
int modal;
{
return(button_handler(report, FALSE));
}
static LVAL right_button_handler(report, modal)
XEvent report;
int modal;
{
return(button_handler(report, TRUE));
}
VOID InstallScrollItem(win, item)
Window win;
LVAL item;
{
Display *dpy = StX11Display();
Point loc, size;
Window slider, button1, button2, thumb;
check_value(item);
loc = ListToPoint(slot_value(item, s_location));
size = ListToPoint(slot_value(item, s_size));
size.v = BUTTON_SIZE;
slider = XCreateSimpleWindow(dpy, win, loc.h, loc.v, size.h, size.v,
dialog_border_width,
DialogBorderColor, DialogC.back);
XSelectInput(dpy, slider,
ExposureMask | ButtonMotionMask |
ButtonPressMask | ButtonReleaseMask);
XDefineCursor(dpy, slider, DoubleArrowCursor);
button1 = XCreateSimpleWindow(dpy, slider,
-dialog_border_width, -dialog_border_width,
BUTTON_SIZE, BUTTON_SIZE,
dialog_border_width,
DialogBorderColor, DialogC.back);
XSelectInput(dpy, button1,
ExposureMask | ButtonPressMask | ButtonReleaseMask);
XSetWindowBackgroundPixmap(dpy, button1, LeftSliderPM);
#ifdef DODO
XDefineCursor(dpy, button1, LeftArrowCursor);
#endif /* DODO */
XDefineCursor(dpy, button1, ArrowCursor);
button2 = XCreateSimpleWindow(dpy, slider,
size.h - BUTTON_SIZE, -dialog_border_width,
BUTTON_SIZE, BUTTON_SIZE,
dialog_border_width,
DialogBorderColor, DialogC.back);
XSelectInput(dpy, button2,
ExposureMask | ButtonPressMask | ButtonReleaseMask);
XSetWindowBackgroundPixmap(dpy, button2, RightSliderPM);
#ifdef DODO
XDefineCursor(dpy, button2, RightArrowCursor);
#endif /* DODO */
XDefineCursor(dpy, button2, ArrowCursor);
thumb = XCreateSimpleWindow(dpy, slider, BUTTON_SIZE, 0,
THUMB_WIDTH, BUTTON_SIZE,
0, DialogBorderColor, DialogC.fore);
set_slot_value(item, s_window_id, cvfixnum((FIXTYPE) slider));
install_dialog_item_handler(dpy, slider, slider_handler, item);
if (XSaveContext(dpy, slider, ObjectContext, (caddr_t) item) != 0)
xlfail("could not install object in window");
if (XSaveContext(dpy, slider, ThumbContext, (caddr_t) thumb) != 0)
xlfail("could not install thumb in slider");
if (XSaveContext(dpy, slider, Button1Context, (caddr_t) button1) != 0)
xlfail("could not install left button in slider");
install_dialog_item_handler(dpy, button1, left_button_handler, item);
if (XSaveContext(dpy, button1, ObjectContext, (caddr_t) item) != 0)
xlfail("could not install object in window");
if (XSaveContext(dpy, slider, Button2Context, (caddr_t) button2) != 0)
xlfail("could not install right button in slider");
install_dialog_item_handler(dpy, button2, right_button_handler, item);
if (XSaveContext(dpy, button2, ObjectContext, (caddr_t) item) != 0)
xlfail("could not install object in window");
adjust_slider(item);
XMapSubwindows(dpy, slider);
}
VOID DeleteScrollItem(win, item)
Window win;
LVAL item;
{
Display *dpy = StX11Display();
Window slider, button1, button2;
slider = (Window) getfixnum(slot_value(item, s_window_id));
delete_dialog_item_handler(dpy, slider);
if (XDeleteContext(dpy, slider, ObjectContext) != 0)
xlfail("could not delete object context");
if (XDeleteContext(dpy, slider, ThumbContext) != 0)
xlfail("could not delete thumb context");
if (XFindContext(dpy, slider, Button1Context, (caddr_t *) &button1) != 0)
xlfail("can't find left button context");
if (XDeleteContext(dpy, slider, Button1Context) != 0)
xlfail("could not delete left button context");
delete_dialog_item_handler(dpy, button1);
if (XDeleteContext(dpy, button1, ObjectContext) != 0)
xlfail("could not delete object context");
if (XFindContext(dpy, slider, Button2Context, (caddr_t *) &button2) != 0)
xlfail("can't find right button context");
if (XDeleteContext(dpy, slider, Button2Context) != 0)
xlfail("could not delete right button context");
delete_dialog_item_handler(dpy, button2);
if (XDeleteContext(dpy, button2, ObjectContext) != 0)
xlfail("could not delete object context");
set_slot_value(item, s_window_id, NIL);
}
VOID DialogScrollGetDefaultSize(item, width, height)
LVAL item;
int *width, *height;
{
if (width != NULL) *width = MIN_SLIDER_WIDTH;
if (height != NULL) *height = MIN_SLIDER_HEIGHT;
}
LVAL DialogScrollItemValue(item, set, value)
LVAL item;
int set, value;
{
if (set) {
set_slot_value(item, s_value, cvfixnum((FIXTYPE) value));
check_value(item);
adjust_slider(item);
}
else check_value(item);
return(slot_value(item, s_value));
}
LVAL DialogScrollItemMin(item, set, value)
LVAL item;
int set, value;
{
if (set) {
set_slot_value(item, s_min_value, cvfixnum((FIXTYPE) value));
check_value(item);
adjust_slider(item);
}
return(slot_value(item, s_min_value));
}
LVAL DialogScrollItemMax(item, set, value)
LVAL item;
int set, value;
{
if (set) {
set_slot_value(item, s_max_value, cvfixnum((FIXTYPE) value));
check_value(item);
adjust_slider(item);
}
return(slot_value(item, s_max_value));
}
LOCAL VOID check_value(item)
LVAL item;
{
LVAL low, high, value;
int ilow, ihigh, ivalue;
low = slot_value(item, s_min_value);
high = slot_value(item, s_max_value);
value = slot_value(item, s_value);
ilow = (fixp(low)) ? getfixnum(low): 0;
ihigh = (fixp(high)) ? getfixnum(high) : 100;
ivalue = (fixp(value)) ? getfixnum(value) : ilow;
if (ilow >= ihigh) ihigh = ilow + 1;
ivalue = max(ilow, min(ihigh, ivalue));
if (! fixp(low) || ilow != getfixnum(low))
set_slot_value(item, s_min_value, cvfixnum((FIXTYPE) ilow));
if (! fixp(high) || ihigh != getfixnum(high))
set_slot_value(item, s_max_value, cvfixnum((FIXTYPE) ihigh));
if (! fixp(value) || ivalue != getfixnum(value))
set_slot_value(item, s_value, cvfixnum((FIXTYPE) ivalue));
}
syntax highlighted by Code2HTML, v. 0.9.1