1 /*
2 * wmslib/src/but/checkbox.c, part of wmslib (Library functions)
3 * Copyright (C) 1994-1996 William Shubert.
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <configure.h>
8
9 #ifdef X11_DISP
10
11 #ifdef STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif /* STDC_HEADERS */
15 #include <stdio.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xatom.h>
20 #include <X11/keysym.h>
21 #include <sys/time.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <wms.h>
26 #include <but/but.h>
27 #include <but/box.h>
28 #ifdef _BUT_RADIO_H_
29 LEVELIZATION ERROR
30 #endif
31 #include <but/radio.h>
32
33 typedef struct Radio_struct {
34 int val, maxVal;
35 int pVal; /* The pressed down value. */
36 ButOut (*press)(But *but, int value);
37 } Radio;
38
39 static ButOut mmove(But *but, int x, int y);
40 static ButOut mleave(But *but);
41 static ButOut mpress(But *but, int butnum, int x, int y);
42 static ButOut mrelease(But *but, int butnum, int x, int y);
43 static void draw(But *but, int x, int y, int w, int h);
44 static ButOut destroy(But *but);
45 static void flags(But *but, uint flags);
46 static void redrawOpt(But *but, Radio *radio, int opt);
47
48 static ButAction action = {
49 mmove, mleave, mpress, mrelease,
50 NULL, NULL, draw, destroy, flags, NULL};
51
52
butRadio_create(ButOut (* func)(But * but,bool value),void * packet,ButWin * win,int layer,int flags,int val,int maxVal)53 But *butRadio_create(ButOut (*func)(But *but, bool value), void *packet,
54 ButWin *win, int layer, int flags,
55 int val, int maxVal) {
56 But *but;
57 Radio *radio;
58
59 radio = wms_malloc(sizeof(Radio));
60 but = but_create(win, radio, &action);
61 MAGIC_SET(but);
62 but->uPacket = packet;
63 but->layer = layer;
64 but->flags = flags | BUT_OPAQUE;
65
66 radio->val = val;
67 radio->maxVal = maxVal;
68 radio->pVal = -1;
69 radio->press = func;
70 but_init(but);
71 return(but);
72 }
73
74
butRadio_get(But * but)75 int butRadio_get(But *but) {
76 Radio *radio = but->iPacket;
77
78 assert(but->action == &action);
79 assert(MAGIC(but));
80 return(radio->val);
81 }
82
83
butRadio_set(But * but,int val,bool propagate)84 void butRadio_set(But *but, int val, bool propagate) {
85 Radio *radio = but->iPacket;
86
87 assert(but->action == &action);
88 assert(MAGIC(but));
89 if (radio->val != val) {
90 redrawOpt(but, radio, val);
91 redrawOpt(but, radio, radio->val);
92 radio->val = val;
93 but_draw(but);
94 if (propagate && (radio->press != NULL))
95 radio->press(but, val);
96 }
97 }
98
99
destroy(But * but)100 static ButOut destroy(But *but) {
101 Radio *radio = but->iPacket;
102
103 assert(but->action == &action);
104 assert(MAGIC(but));
105 wms_free(radio);
106 return(0);
107 }
108
109
draw(But * but,int x,int y,int w,int h)110 static void draw(But *but, int x, int y, int w, int h) {
111 ButWin *win = but->win;
112 Radio *radio = but->iPacket;
113 uint flags = but->flags;
114 ButEnv *env = win->env;
115 int i, ix, ix2, iy, iw, ih;
116
117 assert(but->action == &action);
118 assert(MAGIC(but));
119 ix2 = but->x;
120 for (i = 0; i < radio->maxVal; ++i) {
121 ix = ix2;
122 ix2 = but->x + ((i + 1) * but->w + (radio->maxVal>>1)) / radio->maxVal;
123 iy = but->y;
124 iw = ix2 - ix;
125 ih = but->h;
126 but_drawBox(win, ix,iy, iw,ih,
127 (flags & BUT_PRESSED) && (i == radio->pVal), env->stdButBw,
128 BUT_SLEFT|BUT_SRIGHT, BUT_LIT, BUT_SHAD, None, None);
129 if (i == radio->pVal)
130 butEnv_setXFg(env, BUT_PBG);
131 else if (i == radio->val)
132 butEnv_setXFg(env, BUT_CHOICE);
133 else
134 butEnv_setXFg(env, BUT_BG);
135 XFillRectangle(env->dpy, win->win, env->gc,
136 ix + env->stdButBw - win->xOff,
137 iy + env->stdButBw - win->yOff,
138 iw - env->stdButBw * 2, ih - env->stdButBw * 2);
139 }
140 }
141
142
flags(But * but,uint flags)143 static void flags(But *but, uint flags) {
144 uint ofl = but->flags;
145 Radio *radio;
146
147 but->flags = flags;
148 if ((flags & (BUT_PRESSABLE|BUT_DRAWABLE|BUT_PRESSED)) !=
149 (ofl & (BUT_PRESSABLE|BUT_DRAWABLE|BUT_PRESSED))) {
150 radio = but->iPacket;
151 if (radio->pVal >= 0)
152 redrawOpt(but, radio, radio->pVal);
153 }
154 }
155
156
mmove(But * but,int x,int y)157 static ButOut mmove(But *but, int x, int y) {
158 ButOut retval = BUTOUT_CAUGHT;
159 int newflags = but->flags;
160 ButEnv *env = but->win->env;
161
162 if (!(but->flags & BUT_PRESSABLE))
163 return(BUTOUT_CAUGHT);
164 if ((x >= but->x + env->stdButBw) && (y >= but->y + env->stdButBw) &&
165 (x < but->x + but->w - env->stdButBw) &&
166 (y < but->y + but->h - env->stdButBw))
167 newflags |= BUT_TWITCHED;
168 else {
169 newflags &= ~BUT_TWITCHED;
170 if (!(newflags & BUT_LOCKED))
171 retval &= ~BUTOUT_CAUGHT;
172 }
173 if (!(but->flags & BUT_TWITCHED) && (newflags & BUT_TWITCHED))
174 butEnv_setCursor(but->win->env, but, butCur_twitch);
175 else if ((but->flags & BUT_TWITCHED) && !(newflags & BUT_TWITCHED))
176 butEnv_setCursor(but->win->env, but, butCur_idle);
177 if (newflags != but->flags) {
178 but_newFlags(but, newflags);
179 }
180 return(retval);
181 }
182
183
mleave(But * but)184 static ButOut mleave(But *but) {
185 int newflags = but->flags;
186
187 newflags &= ~BUT_TWITCHED;
188 if ((but->flags & BUT_TWITCHED) && !(newflags & BUT_TWITCHED))
189 butEnv_setCursor(but->win->env, but, butCur_idle);
190 if (newflags != but->flags) {
191 but_newFlags(but, newflags);
192 }
193 return(BUTOUT_CAUGHT);
194 }
195
196
mpress(But * but,int butnum,int x,int y)197 static ButOut mpress(But *but, int butnum, int x, int y) {
198 Radio *radio = but->iPacket;
199 ButOut retval = BUTOUT_CAUGHT;
200 int newflags = but->flags;
201
202 if (!newflags & BUT_TWITCHED)
203 retval &= ~BUTOUT_CAUGHT;
204 else {
205 if (butnum == 1) {
206 newflags |= BUT_PRESSED | BUT_LOCKED;
207 radio->pVal = ((x - but->x) * radio->maxVal) / but->w;
208 } else
209 return(BUTOUT_CAUGHT | BUTOUT_ERR);
210 }
211 if (!(but->flags & BUT_PRESSED) && (newflags & BUT_PRESSED))
212 snd_play(&but_downSnd);
213 if (newflags != but->flags)
214 but_newFlags(but, newflags);
215 return(retval);
216 }
217
218
mrelease(But * but,int butnum,int x,int y)219 static ButOut mrelease(But *but, int butnum, int x, int y) {
220 ButOut retval = BUTOUT_CAUGHT;
221 int newflags = but->flags;
222 Radio *radio = but->iPacket;
223 int oldPVal, newPVal;
224
225 oldPVal = radio->pVal;
226 if (oldPVal >= 0)
227 redrawOpt(but, radio, oldPVal);
228 radio->pVal = -1;
229 if (butnum != 1) {
230 if (but->flags & BUT_TWITCHED)
231 return(BUTOUT_CAUGHT);
232 else
233 return(0);
234 }
235 if (!(but->flags & BUT_PRESSED))
236 return(0);
237 if (but->flags & BUT_TWITCHED) {
238 newPVal = ((x - but->x) * radio->maxVal) / but->w;
239 if (newPVal != oldPVal)
240 oldPVal = -1;
241 } else {
242 oldPVal = -1;
243 retval |= BUTOUT_ERR;
244 }
245 newflags &= ~(BUT_PRESSED|BUT_LOCKED);
246 if ((but->flags & BUT_PRESSED) && !(newflags & BUT_PRESSED) &&
247 !(retval & BUTOUT_ERR))
248 snd_play(&but_upSnd);
249 if (newflags != but->flags)
250 but_newFlags(but, newflags);
251 if (oldPVal != -1) {
252 redrawOpt(but, radio, oldPVal);
253 redrawOpt(but, radio, radio->val);
254 radio->val = oldPVal;
255 if (radio->press)
256 radio->press(but, oldPVal);
257 } else
258 retval |= BUTOUT_ERR;
259 return(retval);
260 }
261
262
redrawOpt(But * but,Radio * radio,int opt)263 static void redrawOpt(But *but, Radio *radio, int opt) {
264 int x1, x2;
265
266 if ((opt >= 0) && (opt < radio->maxVal)) {
267 x1 = (but->w * opt + (radio->maxVal >> 1)) / radio->maxVal;
268 x2 = (but->w * (opt + 1) + (radio->maxVal >> 1)) / radio->maxVal;
269 butWin_redraw(but->win, but->x + x1, but->y, x2 - x1, but->h);
270 }
271 }
272
273
274 #endif
275