]> git.ipfire.org Git - thirdparty/newt.git/blob - checkbox.c
sync with 0.52.1
[thirdparty/newt.git] / checkbox.c
1 #include <slang.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "newt.h"
6 #include "newt_pr.h"
7
8 enum type { CHECK, RADIO };
9
10 struct checkbox {
11 char * text;
12 char * seq;
13 char * result;
14 newtComponent prevButton, lastButton;
15 enum type type;
16 char value;
17 int active, inactive;
18 const void * data;
19 int flags;
20 int hasFocus;
21 };
22
23 static void makeActive(newtComponent co);
24
25 static void cbDraw(newtComponent c);
26 static void cbDestroy(newtComponent co);
27 struct eventResult cbEvent(newtComponent co, struct event ev);
28
29 static struct componentOps cbOps = {
30 cbDraw,
31 cbEvent,
32 cbDestroy,
33 newtDefaultPlaceHandler,
34 newtDefaultMappedHandler,
35 } ;
36
37 newtComponent newtRadiobutton(int left, int top, const char * text, int isDefault,
38 newtComponent prevButton) {
39 newtComponent co;
40 newtComponent curr;
41 struct checkbox * rb;
42 char initialValue;
43
44 if (isDefault)
45 initialValue = '*';
46 else
47 initialValue = ' ';
48
49 co = newtCheckbox(left, top, text, initialValue, " *", NULL);
50 rb = co->data;
51 rb->type = RADIO;
52
53 rb->prevButton = prevButton;
54
55 for (curr = co; curr; curr = rb->prevButton) {
56 rb = curr->data;
57 rb->lastButton = co;
58 }
59
60 return co;
61 }
62
63 newtComponent newtRadioGetCurrent(newtComponent setMember) {
64 struct checkbox * rb = setMember->data;
65
66 setMember = rb->lastButton;
67 rb = setMember->data;
68
69 while (rb && rb->value != '*') {
70 setMember = rb->prevButton;
71 if (!setMember)
72 return NULL;
73 rb = setMember->data;
74 }
75
76 return setMember;
77 }
78
79 char newtCheckboxGetValue(newtComponent co) {
80 struct checkbox * cb = co->data;
81
82 return cb->value;
83 }
84
85 void newtCheckboxSetValue(newtComponent co, char value) {
86 struct checkbox * cb = co->data;
87
88 *cb->result = value;
89 cbDraw(co);
90 }
91
92 /*
93 * returns NULL on error.
94 * FIXME: Check all calls.
95 */
96 newtComponent newtCheckbox(int left, int top, const char * text, char defValue,
97 const char * seq, char * result) {
98 newtComponent co;
99 struct checkbox * cb;
100
101 if (!seq) seq = " *";
102
103 co = malloc(sizeof(*co));
104 if (co == NULL)
105 return NULL;
106 cb = malloc(sizeof(struct checkbox));
107 if (cb == NULL) {
108 free(co);
109 return NULL;
110 }
111 co->data = cb;
112 cb->flags = 0;
113 if (result)
114 cb->result = result;
115 else
116 cb->result = &cb->value;
117
118 cb->text = strdup(text);
119 cb->seq = strdup(seq);
120 cb->type = CHECK;
121 cb->hasFocus = 0;
122 cb->inactive = COLORSET_CHECKBOX;
123 cb->active = COLORSET_ACTCHECKBOX;
124 defValue ? (*cb->result = defValue) : (*cb->result = cb->seq[0]);
125
126 co->ops = &cbOps;
127
128 co->callback = NULL;
129 co->height = 1;
130 co->width = wstrlen(text, -1) + 4;
131 co->top = top;
132 co->left = left;
133 co->takesFocus = 1;
134
135 return co;
136 }
137
138 void newtCheckboxSetFlags(newtComponent co, int flags, enum newtFlagsSense sense) {
139 struct checkbox * cb = co->data;
140 int row, col;
141
142 cb->flags = newtSetFlags(cb->flags, flags, sense);
143
144 // If the flag just sets a property (eg. NEWT_FLAG_RETURNEXIT),
145 // don't redraw, etc. as the component might be 'hidden' and not to
146 // be drawn (eg. in a scrolled list)
147 if (flags == NEWT_FLAG_RETURNEXIT)
148 return;
149
150 if (!(cb->flags & NEWT_FLAG_DISABLED))
151 co->takesFocus = 1;
152 else
153 co->takesFocus = 0;
154
155 newtGetrc(&row, &col);
156 cbDraw(co);
157 newtGotorc(row, col);
158 }
159
160 static void cbDraw(newtComponent c) {
161 struct checkbox * cb = c->data;
162
163 if (c->top == -1 || !c->isMapped) return;
164
165 if (cb->flags & NEWT_FLAG_DISABLED) {
166 cb->inactive = NEWT_COLORSET_DISENTRY;
167 cb->active = NEWT_COLORSET_DISENTRY;
168 } else {
169 cb->inactive = COLORSET_CHECKBOX;
170 cb->active = COLORSET_ACTCHECKBOX;
171 }
172
173 SLsmg_set_color(cb->inactive);
174
175 newtGotorc(c->top, c->left);
176
177 switch (cb->type) {
178 case RADIO:
179 SLsmg_write_string("( ) ");
180 break;
181
182 case CHECK:
183 SLsmg_write_string("[ ] ");
184 break;
185
186 default:
187 break;
188 }
189
190 SLsmg_write_string(cb->text);
191
192 if (cb->hasFocus)
193 SLsmg_set_color(cb->active);
194
195 newtGotorc(c->top, c->left + 1);
196 SLsmg_write_char(*cb->result);
197 }
198
199 static void cbDestroy(newtComponent co) {
200 struct checkbox * cb = co->data;
201
202 free(cb->text);
203 free(cb->seq);
204 free(cb);
205 free(co);
206 }
207
208 struct eventResult cbEvent(newtComponent co, struct event ev) {
209 struct checkbox * cb = co->data;
210 struct eventResult er;
211 const char * cur;
212
213 if (ev.when == EV_NORMAL) {
214 switch (ev.event) {
215 case EV_FOCUS:
216 cb->hasFocus = 1;
217 cbDraw(co);
218 er.result = ER_SWALLOWED;
219 break;
220
221 case EV_UNFOCUS:
222 cb->hasFocus = 0;
223 cbDraw(co);
224 er.result = ER_SWALLOWED;
225 break;
226
227 case EV_KEYPRESS:
228 if (ev.u.key == ' ') {
229 if (cb->type == RADIO) {
230 makeActive(co);
231 } else if (cb->type == CHECK) {
232 cur = strchr(cb->seq, *cb->result);
233 if (!cur)
234 *cb->result = *cb->seq;
235 else {
236 cur++;
237 if (! *cur)
238 *cb->result = *cb->seq;
239 else
240 *cb->result = *cur;
241 }
242 cbDraw(co);
243 er.result = ER_SWALLOWED;
244
245 if (co->callback)
246 co->callback(co, co->callbackData);
247 } else {
248 er.result = ER_IGNORED;
249 }
250 } else if(ev.u.key == NEWT_KEY_ENTER) {
251 if (cb->flags & NEWT_FLAG_RETURNEXIT)
252 er.result = ER_EXITFORM;
253 else
254 er.result = ER_IGNORED;
255 } else {
256 er.result = ER_IGNORED;
257 }
258 break;
259 case EV_MOUSE:
260 if (ev.u.mouse.type == MOUSE_BUTTON_DOWN) {
261 if (cb->type == RADIO) {
262 makeActive(co);
263 } else if (cb->type == CHECK) {
264 cur = strchr(cb->seq, *cb->result);
265 if (!cur)
266 *cb->result = *cb->seq;
267 else {
268 cur++;
269 if (! *cur)
270 *cb->result = *cb->seq;
271 else
272 *cb->result = *cur;
273 }
274 cbDraw(co);
275 er.result = ER_SWALLOWED;
276
277 if (co->callback)
278 co->callback(co, co->callbackData);
279 }
280 }
281 }
282 } else
283 er.result = ER_IGNORED;
284
285 return er;
286 }
287
288 static void makeActive(newtComponent co) {
289 struct checkbox * cb = co->data;
290 struct checkbox * rb;
291 newtComponent curr;
292
293 /* find the one that's turned off */
294 curr = cb->lastButton;
295 rb = curr->data;
296 while (curr && rb->value == rb->seq[0]) {
297 curr = rb->prevButton;
298 if (curr) rb = curr->data;
299 }
300 if (curr) {
301 rb->value = rb->seq[0];
302 cbDraw(curr);
303 }
304 cb->value = cb->seq[1];
305 cbDraw(co);
306
307 if (co->callback)
308 co->callback(co, co->callbackData);
309 }