at v2.6.13-rc2 373 lines 10 kB view raw
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 26static int list_width, check_x, item_x, checkflag; 27 28/* 29 * Print list item 30 */ 31static void 32print_item (WINDOW * win, const char *item, int status, 33 int choice, int selected) 34{ 35 int i; 36 37 /* Clear 'residue' of last item */ 38 wattrset (win, menubox_attr); 39 wmove (win, choice, 0); 40 for (i = 0; i < list_width; i++) 41 waddch (win, ' '); 42 43 wmove (win, choice, check_x); 44 wattrset (win, selected ? check_selected_attr : check_attr); 45 if (checkflag == FLAG_CHECK) 46 wprintw (win, "[%c]", status ? 'X' : ' '); 47 else 48 wprintw (win, "(%c)", status ? 'X' : ' '); 49 50 wattrset (win, selected ? tag_selected_attr : tag_attr); 51 mvwaddch(win, choice, item_x, item[0]); 52 wattrset (win, selected ? item_selected_attr : item_attr); 53 waddstr (win, (char *)item+1); 54 if (selected) { 55 wmove (win, choice, check_x+1); 56 wrefresh (win); 57 } 58} 59 60/* 61 * Print the scroll indicators. 62 */ 63static void 64print_arrows (WINDOW * win, int choice, int item_no, int scroll, 65 int y, int x, int height) 66{ 67 wmove(win, y, x); 68 69 if (scroll > 0) { 70 wattrset (win, uarrow_attr); 71 waddch (win, ACS_UARROW); 72 waddstr (win, "(-)"); 73 } 74 else { 75 wattrset (win, menubox_attr); 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, darrow_attr); 87 waddch (win, ACS_DARROW); 88 waddstr (win, "(+)"); 89 } 90 else { 91 wattrset (win, menubox_border_attr); 92 waddch (win, ACS_HLINE); 93 waddch (win, ACS_HLINE); 94 waddch (win, ACS_HLINE); 95 waddch (win, ACS_HLINE); 96 } 97} 98 99/* 100 * Display the termination buttons 101 */ 102static void 103print_buttons( WINDOW *dialog, int height, int width, int selected) 104{ 105 int x = width / 2 - 11; 106 int y = height - 2; 107 108 print_button (dialog, "Select", y, x, selected == 0); 109 print_button (dialog, " Help ", y, x + 14, selected == 1); 110 111 wmove(dialog, y, x+1 + 14*selected); 112 wrefresh (dialog); 113} 114 115/* 116 * Display a dialog box with a list of options that can be turned on or off 117 * The `flag' parameter is used to select between radiolist and checklist. 118 */ 119int 120dialog_checklist (const char *title, const char *prompt, int height, int width, 121 int list_height, int item_no, const char * const * items, int flag) 122 123{ 124 int i, x, y, box_x, box_y; 125 int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; 126 WINDOW *dialog, *list; 127 128 checkflag = flag; 129 130 /* Allocate space for storing item on/off status */ 131 if ((status = malloc (sizeof (int) * item_no)) == NULL) { 132 endwin (); 133 fprintf (stderr, 134 "\nCan't allocate memory in dialog_checklist().\n"); 135 exit (-1); 136 } 137 138 /* Initializes status */ 139 for (i = 0; i < item_no; i++) { 140 status[i] = !strcasecmp (items[i * 3 + 2], "on"); 141 if ((!choice && status[i]) || !strcasecmp (items[i * 3 + 2], "selected")) 142 choice = i + 1; 143 } 144 if (choice) 145 choice--; 146 147 max_choice = MIN (list_height, item_no); 148 149 /* center dialog box on screen */ 150 x = (COLS - width) / 2; 151 y = (LINES - height) / 2; 152 153 draw_shadow (stdscr, y, x, height, width); 154 155 dialog = newwin (height, width, y, x); 156 keypad (dialog, TRUE); 157 158 draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); 159 wattrset (dialog, border_attr); 160 mvwaddch (dialog, height-3, 0, ACS_LTEE); 161 for (i = 0; i < width - 2; i++) 162 waddch (dialog, ACS_HLINE); 163 wattrset (dialog, dialog_attr); 164 waddch (dialog, ACS_RTEE); 165 166 if (title != NULL && strlen(title) >= width-2 ) { 167 /* truncate long title -- mec */ 168 char * title2 = malloc(width-2+1); 169 memcpy( title2, title, width-2 ); 170 title2[width-2] = '\0'; 171 title = title2; 172 } 173 174 if (title != NULL) { 175 wattrset (dialog, title_attr); 176 mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); 177 waddstr (dialog, (char *)title); 178 waddch (dialog, ' '); 179 } 180 181 wattrset (dialog, dialog_attr); 182 print_autowrap (dialog, prompt, width - 2, 1, 3); 183 184 list_width = width - 6; 185 box_y = height - list_height - 5; 186 box_x = (width - list_width) / 2 - 1; 187 188 /* create new window for the list */ 189 list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1); 190 191 keypad (list, TRUE); 192 193 /* draw a box around the list items */ 194 draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2, 195 menubox_border_attr, menubox_attr); 196 197 /* Find length of longest item in order to center checklist */ 198 check_x = 0; 199 for (i = 0; i < item_no; i++) 200 check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4); 201 202 check_x = (list_width - check_x) / 2; 203 item_x = check_x + 4; 204 205 if (choice >= list_height) { 206 scroll = choice - list_height + 1; 207 choice -= scroll; 208 } 209 210 /* Print the list */ 211 for (i = 0; i < max_choice; i++) { 212 print_item (list, items[(scroll+i) * 3 + 1], 213 status[i+scroll], i, i == choice); 214 } 215 216 print_arrows(dialog, choice, item_no, scroll, 217 box_y, box_x + check_x + 5, list_height); 218 219 print_buttons(dialog, height, width, 0); 220 221 wnoutrefresh (list); 222 wnoutrefresh (dialog); 223 doupdate (); 224 225 while (key != ESC) { 226 key = wgetch (dialog); 227 228 for (i = 0; i < max_choice; i++) 229 if (toupper(key) == toupper(items[(scroll+i)*3+1][0])) 230 break; 231 232 233 if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || 234 key == '+' || key == '-' ) { 235 if (key == KEY_UP || key == '-') { 236 if (!choice) { 237 if (!scroll) 238 continue; 239 /* Scroll list down */ 240 if (list_height > 1) { 241 /* De-highlight current first item */ 242 print_item (list, items[scroll * 3 + 1], 243 status[scroll], 0, FALSE); 244 scrollok (list, TRUE); 245 wscrl (list, -1); 246 scrollok (list, FALSE); 247 } 248 scroll--; 249 print_item (list, items[scroll * 3 + 1], 250 status[scroll], 0, TRUE); 251 wnoutrefresh (list); 252 253 print_arrows(dialog, choice, item_no, scroll, 254 box_y, box_x + check_x + 5, list_height); 255 256 wrefresh (dialog); 257 258 continue; /* wait for another key press */ 259 } else 260 i = choice - 1; 261 } else if (key == KEY_DOWN || key == '+') { 262 if (choice == max_choice - 1) { 263 if (scroll + choice >= item_no - 1) 264 continue; 265 /* Scroll list up */ 266 if (list_height > 1) { 267 /* De-highlight current last item before scrolling up */ 268 print_item (list, items[(scroll + max_choice - 1) * 3 + 1], 269 status[scroll + max_choice - 1], 270 max_choice - 1, FALSE); 271 scrollok (list, TRUE); 272 wscrl (list, 1); 273 scrollok (list, FALSE); 274 } 275 scroll++; 276 print_item (list, items[(scroll + max_choice - 1) * 3 + 1], 277 status[scroll + max_choice - 1], 278 max_choice - 1, TRUE); 279 wnoutrefresh (list); 280 281 print_arrows(dialog, choice, item_no, scroll, 282 box_y, box_x + check_x + 5, list_height); 283 284 wrefresh (dialog); 285 286 continue; /* wait for another key press */ 287 } else 288 i = choice + 1; 289 } 290 if (i != choice) { 291 /* De-highlight current item */ 292 print_item (list, items[(scroll + choice) * 3 + 1], 293 status[scroll + choice], choice, FALSE); 294 /* Highlight new item */ 295 choice = i; 296 print_item (list, items[(scroll + choice) * 3 + 1], 297 status[scroll + choice], choice, TRUE); 298 wnoutrefresh (list); 299 wrefresh (dialog); 300 } 301 continue; /* wait for another key press */ 302 } 303 switch (key) { 304 case 'H': 305 case 'h': 306 case '?': 307 fprintf (stderr, "%s", items[(scroll + choice) * 3]); 308 delwin (dialog); 309 free (status); 310 return 1; 311 case TAB: 312 case KEY_LEFT: 313 case KEY_RIGHT: 314 button = ((key == KEY_LEFT ? --button : ++button) < 0) 315 ? 1 : (button > 1 ? 0 : button); 316 317 print_buttons(dialog, height, width, button); 318 wrefresh (dialog); 319 break; 320 case 'S': 321 case 's': 322 case ' ': 323 case '\n': 324 if (!button) { 325 if (flag == FLAG_CHECK) { 326 status[scroll + choice] = !status[scroll + choice]; 327 wmove (list, choice, check_x); 328 wattrset (list, check_selected_attr); 329 wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); 330 } else { 331 if (!status[scroll + choice]) { 332 for (i = 0; i < item_no; i++) 333 status[i] = 0; 334 status[scroll + choice] = 1; 335 for (i = 0; i < max_choice; i++) 336 print_item (list, items[(scroll + i) * 3 + 1], 337 status[scroll + i], i, i == choice); 338 } 339 } 340 wnoutrefresh (list); 341 wrefresh (dialog); 342 343 for (i = 0; i < item_no; i++) { 344 if (status[i]) { 345 if (flag == FLAG_CHECK) { 346 fprintf (stderr, "\"%s\" ", items[i * 3]); 347 } else { 348 fprintf (stderr, "%s", items[i * 3]); 349 } 350 351 } 352 } 353 } else 354 fprintf (stderr, "%s", items[(scroll + choice) * 3]); 355 delwin (dialog); 356 free (status); 357 return button; 358 case 'X': 359 case 'x': 360 key = ESC; 361 case ESC: 362 break; 363 } 364 365 /* Now, update everything... */ 366 doupdate (); 367 } 368 369 370 delwin (dialog); 371 free (status); 372 return -1; /* ESC pressed */ 373}