root/scripts/kconfig/lxdialog/checklist.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. print_item
  2. print_arrows
  3. print_buttons
  4. dialog_checklist

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

/* [<][>][^][v][top][bottom][index][help] */