]> git.ipfire.org Git - thirdparty/newt.git/blob - checkbox.c
handle component destruction
[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->destroyCallback = NULL;
130 co->height = 1;
131 co->width = wstrlen(text, -1) + 4;
132 co->top = top;
133 co->left = left;
134 co->takesFocus = 1;
135 co->isMapped = 0;
136
137 return co;
138 }
139
140 void newtCheckboxSetFlags(newtComponent co, int flags, enum newtFlagsSense sense) {
141 struct checkbox * cb = co->data;
142 int row, col;
143
144 cb->flags = newtSetFlags(cb->flags, flags, sense);
145
146 // If the flag just sets a property (eg. NEWT_FLAG_RETURNEXIT),
147 // don't redraw, etc. as the component might be 'hidden' and not to
148 // be drawn (eg. in a scrolled list)
149 if (flags == NEWT_FLAG_RETURNEXIT)
150 return;
151
152 if (!(cb->flags & NEWT_FLAG_DISABLED))
153 co->takesFocus = 1;
154 else
155 co->takesFocus = 0;
156
157 newtGetrc(&row, &col);
158 cbDraw(co);
159 newtGotorc(row, col);
160 }
161
162 static void cbDraw(newtComponent c) {
163 struct checkbox * cb = c->data;
164
165 if (c->top == -1 || !c->isMapped) return;
166
167 if (cb->flags & NEWT_FLAG_DISABLED) {
168 cb->inactive = NEWT_COLORSET_DISENTRY;
169 cb->active = NEWT_COLORSET_DISENTRY;
170 } else {
171 cb->inactive = COLORSET_CHECKBOX;
172 cb->active = COLORSET_ACTCHECKBOX;
173 }
174
175 SLsmg_set_color(cb->inactive);
176
177 newtGotorc(c->top, c->left);
178
179 switch (cb->type) {
180 case RADIO:
181 SLsmg_write_string("( ) ");
182 break;
183
184 case CHECK:
185 SLsmg_write_string("[ ] ");
186 break;
187
188 default:
189 break;
190 }
191
192 SLsmg_write_string(cb->text);
193
194 if (cb->hasFocus)
195 SLsmg_set_color(cb->active);
196
197 newtGotorc(c->top, c->left + 1);
198 SLsmg_write_char(*cb->result);
199 newtGotorc(c->top, c->left + 4);
200 }
201
202 static void cbDestroy(newtComponent co) {
203 struct checkbox * cb = co->data;
204
205 free(cb->text);
206 free(cb->seq);
207 free(cb);
208 free(co);
209 }
210
211 struct eventResult cbEvent(newtComponent co, struct event ev) {
212 struct checkbox * cb = co->data;
213 struct eventResult er;
214 const char * cur;
215
216 er.result = ER_IGNORED;
217
218 if (ev.when == EV_NORMAL) {
219 switch (ev.event) {
220 case EV_FOCUS:
221 cb->hasFocus = 1;
222 cbDraw(co);
223 er.result = ER_SWALLOWED;
224 break;
225
226 case EV_UNFOCUS:
227 cb->hasFocus = 0;
228 cbDraw(co);
229 er.result = ER_SWALLOWED;
230 break;
231
232 case EV_KEYPRESS:
233 if (ev.u.key == ' ') {
234 if (cb->type == RADIO) {
235 makeActive(co);
236 } else if (cb->type == CHECK) {
237 cur = strchr(cb->seq, *cb->result);
238 if (!cur)
239 *cb->result = *cb->seq;
240 else {
241 cur++;
242 if (! *cur)
243 *cb->result = *cb->seq;
244 else
245 *cb->result = *cur;
246 }
247 cbDraw(co);
248 er.result = ER_SWALLOWED;
249
250 if (co->callback)
251 co->callback(co, co->callbackData);
252 } else {
253 er.result = ER_IGNORED;
254 }
255 } else if(ev.u.key == NEWT_KEY_ENTER) {
256 if (cb->flags & NEWT_FLAG_RETURNEXIT)
257 er.result = ER_EXITFORM;
258 else
259 er.result = ER_IGNORED;
260 } else {
261 er.result = ER_IGNORED;
262 }
263 break;
264 case EV_MOUSE:
265 if (ev.u.mouse.type == MOUSE_BUTTON_DOWN) {
266 if (cb->type == RADIO) {
267 makeActive(co);
268 } else if (cb->type == CHECK) {
269 cur = strchr(cb->seq, *cb->result);
270 if (!cur)
271 *cb->result = *cb->seq;
272 else {
273 cur++;
274 if (! *cur)
275 *cb->result = *cb->seq;
276 else
277 *cb->result = *cur;
278 }
279 cbDraw(co);
280 er.result = ER_SWALLOWED;
281
282 if (co->callback)
283 co->callback(co, co->callbackData);
284 }
285 }
286 }
287 }
288
289 return er;
290 }
291
292 static void makeActive(newtComponent co) {
293 struct checkbox * cb = co->data;
294 struct checkbox * rb;
295 newtComponent curr;
296
297 /* find the one that's turned off */
298 curr = cb->lastButton;
299 rb = curr->data;
300 while (curr && rb->value == rb->seq[0]) {
301 curr = rb->prevButton;
302 if (curr) rb = curr->data;
303 }
304 if (curr) {
305 rb->value = rb->seq[0];
306 cbDraw(curr);
307 }
308 cb->value = cb->seq[1];
309 cbDraw(co);
310
311 if (co->callback)
312 co->callback(co, co->callbackData);
313 }