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