blob: 1857c5378ce8c3c21f51f3bb4860ecd35295eda9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * checklist.c -- implements the checklist box
3 *
4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5 * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
6 * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
7 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include "dialog.h"
25
26static int list_width, check_x, item_x, checkflag;
27
28/*
29 * Print list item
30 */
31static void
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010032print_item(WINDOW * win, const char *item, int status, int choice, int selected)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010034 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010036 /* Clear 'residue' of last item */
37 wattrset(win, menubox_attr);
38 wmove(win, choice, 0);
39 for (i = 0; i < list_width; i++)
40 waddch(win, ' ');
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010042 wmove(win, choice, check_x);
43 wattrset(win, selected ? check_selected_attr : check_attr);
44 if (checkflag == FLAG_CHECK)
45 wprintw(win, "[%c]", status ? 'X' : ' ');
46 else
47 wprintw(win, "(%c)", status ? 'X' : ' ');
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010049 wattrset(win, selected ? tag_selected_attr : tag_attr);
50 mvwaddch(win, choice, item_x, item[0]);
51 wattrset(win, selected ? item_selected_attr : item_attr);
52 waddstr(win, (char *)item + 1);
53 if (selected) {
54 wmove(win, choice, check_x + 1);
55 wrefresh(win);
56 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070057}
58
59/*
60 * Print the scroll indicators.
61 */
62static void
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010063print_arrows(WINDOW * win, int choice, int item_no, int scroll,
64 int y, int x, int height)
Linus Torvalds1da177e2005-04-16 15:20:36 -070065{
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010066 wmove(win, y, x);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010068 if (scroll > 0) {
69 wattrset(win, uarrow_attr);
70 waddch(win, ACS_UARROW);
71 waddstr(win, "(-)");
72 } else {
73 wattrset(win, menubox_attr);
74 waddch(win, ACS_HLINE);
75 waddch(win, ACS_HLINE);
76 waddch(win, ACS_HLINE);
77 waddch(win, ACS_HLINE);
78 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010080 y = y + height + 1;
81 wmove(win, y, x);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010083 if ((height < item_no) && (scroll + choice < item_no - 1)) {
84 wattrset(win, darrow_attr);
85 waddch(win, ACS_DARROW);
86 waddstr(win, "(+)");
87 } else {
88 wattrset(win, menubox_border_attr);
89 waddch(win, ACS_HLINE);
90 waddch(win, ACS_HLINE);
91 waddch(win, ACS_HLINE);
92 waddch(win, ACS_HLINE);
93 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070094}
95
96/*
97 * Display the termination buttons
98 */
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +010099static void print_buttons(WINDOW * dialog, int height, int width, int selected)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100{
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100101 int x = width / 2 - 11;
102 int y = height - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100104 print_button(dialog, "Select", y, x, selected == 0);
105 print_button(dialog, " Help ", y, x + 14, selected == 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100107 wmove(dialog, y, x + 1 + 14 * selected);
108 wrefresh(dialog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109}
110
111/*
112 * Display a dialog box with a list of options that can be turned on or off
113 * The `flag' parameter is used to select between radiolist and checklist.
114 */
115int
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100116dialog_checklist(const char *title, const char *prompt, int height, int width,
117 int list_height, int item_no, const char *const *items,
118 int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119{
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100120 int i, x, y, box_x, box_y;
121 int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
122 WINDOW *dialog, *list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100124 checkflag = flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100126 /* Allocate space for storing item on/off status */
127 if ((status = malloc(sizeof(int) * item_no)) == NULL) {
128 endwin();
129 fprintf(stderr,
130 "\nCan't allocate memory in dialog_checklist().\n");
131 exit(-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100134 /* Initializes status */
135 for (i = 0; i < item_no; i++) {
136 status[i] = !strcasecmp(items[i * 3 + 2], "on");
137 if ((!choice && status[i])
138 || !strcasecmp(items[i * 3 + 2], "selected"))
139 choice = i + 1;
140 }
141 if (choice)
142 choice--;
143
144 max_choice = MIN(list_height, item_no);
145
146 /* center dialog box on screen */
147 x = (COLS - width) / 2;
148 y = (LINES - height) / 2;
149
150 draw_shadow(stdscr, y, x, height, width);
151
152 dialog = newwin(height, width, y, x);
153 keypad(dialog, TRUE);
154
155 draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
156 wattrset(dialog, border_attr);
157 mvwaddch(dialog, height - 3, 0, ACS_LTEE);
158 for (i = 0; i < width - 2; i++)
159 waddch(dialog, ACS_HLINE);
160 wattrset(dialog, dialog_attr);
161 waddch(dialog, ACS_RTEE);
162
163 if (title != NULL && strlen(title) >= width - 2) {
164 /* truncate long title -- mec */
165 char *title2 = malloc(width - 2 + 1);
166 memcpy(title2, title, width - 2);
167 title2[width - 2] = '\0';
168 title = title2;
169 }
170
171 if (title != NULL) {
172 wattrset(dialog, title_attr);
173 mvwaddch(dialog, 0, (width - strlen(title)) / 2 - 1, ' ');
174 waddstr(dialog, (char *)title);
175 waddch(dialog, ' ');
176 }
177
178 wattrset(dialog, dialog_attr);
179 print_autowrap(dialog, prompt, width - 2, 1, 3);
180
181 list_width = width - 6;
182 box_y = height - list_height - 5;
183 box_x = (width - list_width) / 2 - 1;
184
185 /* create new window for the list */
186 list =
187 subwin(dialog, list_height, list_width, y + box_y + 1,
188 x + box_x + 1);
189
190 keypad(list, TRUE);
191
192 /* draw a box around the list items */
193 draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
194 menubox_border_attr, menubox_attr);
195
196 /* Find length of longest item in order to center checklist */
197 check_x = 0;
198 for (i = 0; i < item_no; i++)
199 check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4);
200
201 check_x = (list_width - check_x) / 2;
202 item_x = check_x + 4;
203
204 if (choice >= list_height) {
205 scroll = choice - list_height + 1;
206 choice -= scroll;
207 }
208
209 /* Print the list */
210 for (i = 0; i < max_choice; i++) {
211 print_item(list, items[(scroll + i) * 3 + 1],
212 status[i + scroll], i, i == choice);
213 }
214
215 print_arrows(dialog, choice, item_no, scroll,
216 box_y, box_x + check_x + 5, list_height);
217
218 print_buttons(dialog, height, width, 0);
219
220 wnoutrefresh(list);
221 wnoutrefresh(dialog);
222 doupdate();
223
224 while (key != ESC) {
225 key = wgetch(dialog);
226
227 for (i = 0; i < max_choice; i++)
228 if (toupper(key) ==
229 toupper(items[(scroll + i) * 3 + 1][0]))
230 break;
231
232 if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
233 key == '+' || key == '-') {
234 if (key == KEY_UP || key == '-') {
235 if (!choice) {
236 if (!scroll)
237 continue;
238 /* Scroll list down */
239 if (list_height > 1) {
240 /* De-highlight current first item */
241 print_item(list,
242 items[scroll * 3 +
243 1],
244 status[scroll], 0,
245 FALSE);
246 scrollok(list, TRUE);
247 wscrl(list, -1);
248 scrollok(list, FALSE);
249 }
250 scroll--;
251 print_item(list, items[scroll * 3 + 1],
252 status[scroll], 0, TRUE);
253 wnoutrefresh(list);
254
255 print_arrows(dialog, choice, item_no,
256 scroll, box_y,
257 box_x + check_x + 5,
258 list_height);
259
260 wrefresh(dialog);
261
262 continue; /* wait for another key press */
263 } else
264 i = choice - 1;
265 } else if (key == KEY_DOWN || key == '+') {
266 if (choice == max_choice - 1) {
267 if (scroll + choice >= item_no - 1)
268 continue;
269 /* Scroll list up */
270 if (list_height > 1) {
271 /* De-highlight current last item before scrolling up */
272 print_item(list,
273 items[(scroll +
274 max_choice -
275 1) * 3 + 1],
276 status[scroll +
277 max_choice -
278 1],
279 max_choice - 1,
280 FALSE);
281 scrollok(list, TRUE);
282 wscrl(list, 1);
283 scrollok(list, FALSE);
284 }
285 scroll++;
286 print_item(list,
287 items[(scroll + max_choice -
288 1) * 3 + 1],
289 status[scroll + max_choice -
290 1], max_choice - 1,
291 TRUE);
292 wnoutrefresh(list);
293
294 print_arrows(dialog, choice, item_no,
295 scroll, box_y,
296 box_x + check_x + 5,
297 list_height);
298
299 wrefresh(dialog);
300
301 continue; /* wait for another key press */
302 } else
303 i = choice + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 }
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100305 if (i != choice) {
306 /* De-highlight current item */
307 print_item(list,
308 items[(scroll + choice) * 3 + 1],
309 status[scroll + choice], choice,
310 FALSE);
311 /* Highlight new item */
312 choice = i;
313 print_item(list,
314 items[(scroll + choice) * 3 + 1],
315 status[scroll + choice], choice,
316 TRUE);
317 wnoutrefresh(list);
318 wrefresh(dialog);
319 }
320 continue; /* wait for another key press */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 }
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100322 switch (key) {
323 case 'H':
324 case 'h':
325 case '?':
326 fprintf(stderr, "%s", items[(scroll + choice) * 3]);
327 delwin(dialog);
328 free(status);
329 return 1;
330 case TAB:
331 case KEY_LEFT:
332 case KEY_RIGHT:
333 button = ((key == KEY_LEFT ? --button : ++button) < 0)
334 ? 1 : (button > 1 ? 0 : button);
335
336 print_buttons(dialog, height, width, button);
337 wrefresh(dialog);
338 break;
339 case 'S':
340 case 's':
341 case ' ':
342 case '\n':
343 if (!button) {
344 if (flag == FLAG_CHECK) {
345 status[scroll + choice] =
346 !status[scroll + choice];
347 wmove(list, choice, check_x);
348 wattrset(list, check_selected_attr);
349 wprintw(list, "[%c]",
350 status[scroll +
351 choice] ? 'X' : ' ');
352 } else {
353 if (!status[scroll + choice]) {
354 for (i = 0; i < item_no; i++)
355 status[i] = 0;
356 status[scroll + choice] = 1;
357 for (i = 0; i < max_choice; i++)
358 print_item(list,
359 items[(scroll
360 +
361 i) *
362 3 + 1],
363 status[scroll
364 + i],
365 i,
366 i == choice);
367 }
368 }
369 wnoutrefresh(list);
370 wrefresh(dialog);
371
372 for (i = 0; i < item_no; i++) {
373 if (status[i]) {
374 if (flag == FLAG_CHECK) {
375 fprintf(stderr,
376 "\"%s\" ",
377 items[i * 3]);
378 } else {
379 fprintf(stderr, "%s",
380 items[i * 3]);
381 }
382
383 }
384 }
385 } else
386 fprintf(stderr, "%s",
387 items[(scroll + choice) * 3]);
388 delwin(dialog);
389 free(status);
390 return button;
391 case 'X':
392 case 'x':
393 key = ESC;
394 case ESC:
395 break;
396 }
397
398 /* Now, update everything... */
399 doupdate();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 }
401
Sam Ravnborgb1c5f1c2005-11-19 19:13:34 +0100402 delwin(dialog);
403 free(status);
404 return -1; /* ESC pressed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}