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