Root/
Source at commit 2755 created 8 years 10 months ago. By ifabio, fix allocate space for ascii string zero terminating in device_inject.c (thx Slice and BlackOsx) | |
---|---|
1 | /*␊ |
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 | ␊ |
26 | static int list_width, check_x, item_x;␊ |
27 | ␊ |
28 | /*␊ |
29 | * Print list item␊ |
30 | */␊ |
31 | static void print_item(WINDOW * win, int choice, int selected)␊ |
32 | {␊ |
33 | ␉int i;␊ |
34 | ␉char *list_item = malloc(list_width + 1);␊ |
35 | ␊ |
36 | ␉strncpy(list_item, item_str(), list_width - item_x);␊ |
37 | ␉list_item[list_width - item_x] = '\0';␊ |
38 | ␊ |
39 | ␉/* Clear 'residue' of last item */␊ |
40 | ␉wattrset(win, dlg.menubox.atr);␊ |
41 | ␉wmove(win, choice, 0);␊ |
42 | ␉for (i = 0; i < list_width; i++)␊ |
43 | ␉␉waddch(win, ' ');␊ |
44 | ␊ |
45 | ␉wmove(win, choice, check_x);␊ |
46 | ␉wattrset(win, selected ? dlg.check_selected.atr␊ |
47 | ␉␉ : dlg.check.atr);␊ |
48 | ␉if (!item_is_tag(':'))␊ |
49 | ␉␉wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');␊ |
50 | ␊ |
51 | ␉wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);␊ |
52 | ␉mvwaddch(win, choice, item_x, list_item[0]);␊ |
53 | ␉wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);␊ |
54 | ␉waddstr(win, list_item + 1);␊ |
55 | ␉if (selected) {␊ |
56 | ␉␉wmove(win, choice, check_x + 1);␊ |
57 | ␉␉wrefresh(win);␊ |
58 | ␉}␊ |
59 | ␉free(list_item);␊ |
60 | }␊ |
61 | ␊ |
62 | /*␊ |
63 | * Print the scroll indicators.␊ |
64 | */␊ |
65 | static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,␊ |
66 | ␉ int y, int x, int height)␊ |
67 | {␊ |
68 | ␉wmove(win, y, x);␊ |
69 | ␊ |
70 | ␉if (scroll > 0) {␊ |
71 | ␉␉wattrset(win, dlg.uarrow.atr);␊ |
72 | ␉␉waddch(win, ACS_UARROW);␊ |
73 | ␉␉waddstr(win, "(-)");␊ |
74 | ␉} else {␊ |
75 | ␉␉wattrset(win, dlg.menubox.atr);␊ |
76 | ␉␉waddch(win, ACS_HLINE);␊ |
77 | ␉␉waddch(win, ACS_HLINE);␊ |
78 | ␉␉waddch(win, ACS_HLINE);␊ |
79 | ␉␉waddch(win, ACS_HLINE);␊ |
80 | ␉}␊ |
81 | ␊ |
82 | ␉y = y + height + 1;␊ |
83 | ␉wmove(win, y, x);␊ |
84 | ␊ |
85 | ␉if ((height < item_no) && (scroll + choice < item_no - 1)) {␊ |
86 | ␉␉wattrset(win, dlg.darrow.atr);␊ |
87 | ␉␉waddch(win, ACS_DARROW);␊ |
88 | ␉␉waddstr(win, "(+)");␊ |
89 | ␉} else {␊ |
90 | ␉␉wattrset(win, dlg.menubox_border.atr);␊ |
91 | ␉␉waddch(win, ACS_HLINE);␊ |
92 | ␉␉waddch(win, ACS_HLINE);␊ |
93 | ␉␉waddch(win, ACS_HLINE);␊ |
94 | ␉␉waddch(win, ACS_HLINE);␊ |
95 | ␉}␊ |
96 | }␊ |
97 | ␊ |
98 | /*␊ |
99 | * Display the termination buttons␊ |
100 | */␊ |
101 | static void print_buttons(WINDOW * dialog, int height, int width, int selected)␊ |
102 | {␊ |
103 | ␉int x = width / 2 - 11;␊ |
104 | ␉int y = height - 2;␊ |
105 | ␊ |
106 | ␉print_button(dialog, gettext("Select"), y, x, selected == 0);␊ |
107 | ␉print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);␊ |
108 | ␊ |
109 | ␉wmove(dialog, y, x + 1 + 14 * selected);␊ |
110 | ␉wrefresh(dialog);␊ |
111 | }␊ |
112 | ␊ |
113 | /*␊ |
114 | * Display a dialog box with a list of options that can be turned on or off␊ |
115 | * in the style of radiolist (only one option turned on at a time).␊ |
116 | */␊ |
117 | int dialog_checklist(const char *title, const char *prompt, int height,␊ |
118 | ␉␉ int width, int list_height)␊ |
119 | {␊ |
120 | ␉int i, x, y, box_x, box_y;␊ |
121 | ␉int key = 0, button = 0, choice = 0, scroll = 0, max_choice;␊ |
122 | ␉WINDOW *dialog, *list;␊ |
123 | ␊ |
124 | ␉/* which item to highlight */␊ |
125 | ␉item_foreach() {␊ |
126 | ␉␉if (item_is_tag('X'))␊ |
127 | ␉␉␉choice = item_n();␊ |
128 | ␉␉if (item_is_selected()) {␊ |
129 | ␉␉␉choice = item_n();␊ |
130 | ␉␉␉break;␊ |
131 | ␉␉}␊ |
132 | ␉}␊ |
133 | ␊ |
134 | do_resize:␊ |
135 | ␉if (getmaxy(stdscr) < (height + 6))␊ |
136 | ␉␉return -ERRDISPLAYTOOSMALL;␊ |
137 | ␉if (getmaxx(stdscr) < (width + 6))␊ |
138 | ␉␉return -ERRDISPLAYTOOSMALL;␊ |
139 | ␊ |
140 | ␉max_choice = MIN(list_height, item_count());␊ |
141 | ␊ |
142 | ␉/* center dialog box on screen */␊ |
143 | ␉x = (COLS - width) / 2;␊ |
144 | ␉y = (LINES - height) / 2;␊ |
145 | ␊ |
146 | ␉draw_shadow(stdscr, y, x, height, width);␊ |
147 | ␊ |
148 | ␉dialog = newwin(height, width, y, x);␊ |
149 | ␉keypad(dialog, TRUE);␊ |
150 | ␊ |
151 | ␉draw_box(dialog, 0, 0, height, width,␊ |
152 | ␉␉ dlg.dialog.atr, dlg.border.atr);␊ |
153 | ␉wattrset(dialog, dlg.border.atr);␊ |
154 | ␉mvwaddch(dialog, height - 3, 0, ACS_LTEE);␊ |
155 | ␉for (i = 0; i < width - 2; i++)␊ |
156 | ␉␉waddch(dialog, ACS_HLINE);␊ |
157 | ␉wattrset(dialog, dlg.dialog.atr);␊ |
158 | ␉waddch(dialog, ACS_RTEE);␊ |
159 | ␊ |
160 | ␉print_title(dialog, title, width);␊ |
161 | ␊ |
162 | ␉wattrset(dialog, dlg.dialog.atr);␊ |
163 | ␉print_autowrap(dialog, prompt, width - 2, 1, 3);␊ |
164 | ␊ |
165 | ␉list_width = width - 6;␊ |
166 | ␉box_y = height - list_height - 5;␊ |
167 | ␉box_x = (width - list_width) / 2 - 1;␊ |
168 | ␊ |
169 | ␉/* create new window for the list */␊ |
170 | ␉list = subwin(dialog, list_height, list_width, y + box_y + 1,␊ |
171 | ␉ x + box_x + 1);␊ |
172 | ␊ |
173 | ␉keypad(list, TRUE);␊ |
174 | ␊ |
175 | ␉/* draw a box around the list items */␊ |
176 | ␉draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,␊ |
177 | ␉ dlg.menubox_border.atr, dlg.menubox.atr);␊ |
178 | ␊ |
179 | ␉/* Find length of longest item in order to center checklist */␊ |
180 | ␉check_x = 0;␊ |
181 | ␉item_foreach()␊ |
182 | ␉␉check_x = MAX(check_x, strlen(item_str()) + 4);␊ |
183 | ␉check_x = MIN(check_x, list_width);␊ |
184 | ␊ |
185 | ␉check_x = (list_width - check_x) / 2;␊ |
186 | ␉item_x = check_x + 4;␊ |
187 | ␊ |
188 | ␉if (choice >= list_height) {␊ |
189 | ␉␉scroll = choice - list_height + 1;␊ |
190 | ␉␉choice -= scroll;␊ |
191 | ␉}␊ |
192 | ␊ |
193 | ␉/* Print the list */␊ |
194 | ␉for (i = 0; i < max_choice; i++) {␊ |
195 | ␉␉item_set(scroll + i);␊ |
196 | ␉␉print_item(list, i, i == choice);␊ |
197 | ␉}␊ |
198 | ␊ |
199 | ␉print_arrows(dialog, choice, item_count(), scroll,␊ |
200 | ␉␉ box_y, box_x + check_x + 5, list_height);␊ |
201 | ␊ |
202 | ␉print_buttons(dialog, height, width, 0);␊ |
203 | ␊ |
204 | ␉wnoutrefresh(dialog);␊ |
205 | ␉wnoutrefresh(list);␊ |
206 | ␉doupdate();␊ |
207 | ␊ |
208 | ␉while (key != KEY_ESC) {␊ |
209 | ␉␉key = wgetch(dialog);␊ |
210 | ␊ |
211 | ␉␉for (i = 0; i < max_choice; i++) {␊ |
212 | ␉␉␉item_set(i + scroll);␊ |
213 | ␉␉␉if (toupper(key) == toupper(item_str()[0]))␊ |
214 | ␉␉␉␉break;␊ |
215 | ␉␉}␊ |
216 | ␊ |
217 | ␉␉if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||␊ |
218 | ␉␉ key == '+' || key == '-') {␊ |
219 | ␉␉␉if (key == KEY_UP || key == '-') {␊ |
220 | ␉␉␉␉if (!choice) {␊ |
221 | ␉␉␉␉␉if (!scroll)␊ |
222 | ␉␉␉␉␉␉continue;␊ |
223 | ␉␉␉␉␉/* Scroll list down */␊ |
224 | ␉␉␉␉␉if (list_height > 1) {␊ |
225 | ␉␉␉␉␉␉/* De-highlight current first item */␊ |
226 | ␉␉␉␉␉␉item_set(scroll);␊ |
227 | ␉␉␉␉␉␉print_item(list, 0, FALSE);␊ |
228 | ␉␉␉␉␉␉scrollok(list, TRUE);␊ |
229 | ␉␉␉␉␉␉wscrl(list, -1);␊ |
230 | ␉␉␉␉␉␉scrollok(list, FALSE);␊ |
231 | ␉␉␉␉␉}␊ |
232 | ␉␉␉␉␉scroll--;␊ |
233 | ␉␉␉␉␉item_set(scroll);␊ |
234 | ␉␉␉␉␉print_item(list, 0, TRUE);␊ |
235 | ␉␉␉␉␉print_arrows(dialog, choice, item_count(),␊ |
236 | ␉␉␉␉␉␉ scroll, box_y, box_x + check_x + 5, list_height);␊ |
237 | ␊ |
238 | ␉␉␉␉␉wnoutrefresh(dialog);␊ |
239 | ␉␉␉␉␉wrefresh(list);␊ |
240 | ␊ |
241 | ␉␉␉␉␉continue;␉/* wait for another key press */␊ |
242 | ␉␉␉␉} else␊ |
243 | ␉␉␉␉␉i = choice - 1;␊ |
244 | ␉␉␉} else if (key == KEY_DOWN || key == '+') {␊ |
245 | ␉␉␉␉if (choice == max_choice - 1) {␊ |
246 | ␉␉␉␉␉if (scroll + choice >= item_count() - 1)␊ |
247 | ␉␉␉␉␉␉continue;␊ |
248 | ␉␉␉␉␉/* Scroll list up */␊ |
249 | ␉␉␉␉␉if (list_height > 1) {␊ |
250 | ␉␉␉␉␉␉/* De-highlight current last item before scrolling up */␊ |
251 | ␉␉␉␉␉␉item_set(scroll + max_choice - 1);␊ |
252 | ␉␉␉␉␉␉print_item(list,␊ |
253 | ␉␉␉␉␉␉␉ max_choice - 1,␊ |
254 | ␉␉␉␉␉␉␉ FALSE);␊ |
255 | ␉␉␉␉␉␉scrollok(list, TRUE);␊ |
256 | ␉␉␉␉␉␉wscrl(list, 1);␊ |
257 | ␉␉␉␉␉␉scrollok(list, FALSE);␊ |
258 | ␉␉␉␉␉}␊ |
259 | ␉␉␉␉␉scroll++;␊ |
260 | ␉␉␉␉␉item_set(scroll + max_choice - 1);␊ |
261 | ␉␉␉␉␉print_item(list, max_choice - 1, TRUE);␊ |
262 | ␊ |
263 | ␉␉␉␉␉print_arrows(dialog, choice, item_count(),␊ |
264 | ␉␉␉␉␉␉ scroll, box_y, box_x + check_x + 5, list_height);␊ |
265 | ␊ |
266 | ␉␉␉␉␉wnoutrefresh(dialog);␊ |
267 | ␉␉␉␉␉wrefresh(list);␊ |
268 | ␊ |
269 | ␉␉␉␉␉continue;␉/* wait for another key press */␊ |
270 | ␉␉␉␉} else␊ |
271 | ␉␉␉␉␉i = choice + 1;␊ |
272 | ␉␉␉}␊ |
273 | ␉␉␉if (i != choice) {␊ |
274 | ␉␉␉␉/* De-highlight current item */␊ |
275 | ␉␉␉␉item_set(scroll + choice);␊ |
276 | ␉␉␉␉print_item(list, choice, FALSE);␊ |
277 | ␉␉␉␉/* Highlight new item */␊ |
278 | ␉␉␉␉choice = i;␊ |
279 | ␉␉␉␉item_set(scroll + choice);␊ |
280 | ␉␉␉␉print_item(list, choice, TRUE);␊ |
281 | ␉␉␉␉wnoutrefresh(dialog);␊ |
282 | ␉␉␉␉wrefresh(list);␊ |
283 | ␉␉␉}␊ |
284 | ␉␉␉continue;␉/* wait for another key press */␊ |
285 | ␉␉}␊ |
286 | ␉␉switch (key) {␊ |
287 | ␉␉case 'H':␊ |
288 | ␉␉case 'h':␊ |
289 | ␉␉case '?':␊ |
290 | ␉␉␉button = 1;␊ |
291 | ␉␉␉/* fall-through */␊ |
292 | ␉␉case 'S':␊ |
293 | ␉␉case 's':␊ |
294 | ␉␉case ' ':␊ |
295 | ␉␉case '\n':␊ |
296 | ␉␉␉item_foreach()␊ |
297 | ␉␉␉␉item_set_selected(0);␊ |
298 | ␉␉␉item_set(scroll + choice);␊ |
299 | ␉␉␉item_set_selected(1);␊ |
300 | ␉␉␉delwin(list);␊ |
301 | ␉␉␉delwin(dialog);␊ |
302 | ␉␉␉return button;␊ |
303 | ␉␉case TAB:␊ |
304 | ␉␉case KEY_LEFT:␊ |
305 | ␉␉case KEY_RIGHT:␊ |
306 | ␉␉␉button = ((key == KEY_LEFT ? --button : ++button) < 0)␊ |
307 | ␉␉␉ ? 1 : (button > 1 ? 0 : button);␊ |
308 | ␊ |
309 | ␉␉␉print_buttons(dialog, height, width, button);␊ |
310 | ␉␉␉wrefresh(dialog);␊ |
311 | ␉␉␉break;␊ |
312 | ␉␉case 'X':␊ |
313 | ␉␉case 'x':␊ |
314 | ␉␉␉key = KEY_ESC;␊ |
315 | ␉␉␉break;␊ |
316 | ␉␉case KEY_ESC:␊ |
317 | ␉␉␉key = on_key_esc(dialog);␊ |
318 | ␉␉␉break;␊ |
319 | ␉␉case KEY_RESIZE:␊ |
320 | ␉␉␉delwin(list);␊ |
321 | ␉␉␉delwin(dialog);␊ |
322 | ␉␉␉on_key_resize();␊ |
323 | ␉␉␉goto do_resize;␊ |
324 | ␉␉}␊ |
325 | ␊ |
326 | ␉␉/* Now, update everything... */␊ |
327 | ␉␉doupdate();␊ |
328 | ␉}␊ |
329 | ␉delwin(list);␊ |
330 | ␉delwin(dialog);␊ |
331 | ␉return key;␉␉/* ESC pressed */␊ |
332 | }␊ |
333 |