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, struct dialog_list_item ** items, 122 int flag) 123 124{ 125 int i, x, y, box_x, box_y; 126 int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; 127 WINDOW *dialog, *list; 128 129 checkflag = flag; 130 131 /* Allocate space for storing item on/off status */ 132 if ((status = malloc (sizeof (int) * item_no)) == NULL) { 133 endwin (); 134 fprintf (stderr, 135 "\nCan't allocate memory in dialog_checklist().\n"); 136 exit (-1); 137 } 138 139 /* Initializes status */ 140 for (i = 0; i < item_no; i++) { 141 status[i] = items[i]->selected; 142 if (!choice && status[i]) 143 choice = i; 144 } 145 146 max_choice = MIN (list_height, item_no); 147 148 /* center dialog box on screen */ 149 x = (COLS - width) / 2; 150 y = (LINES - height) / 2; 151 152 draw_shadow (stdscr, y, x, height, width); 153 154 dialog = newwin (height, width, y, x); 155 keypad (dialog, TRUE); 156 157 draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); 158 wattrset (dialog, border_attr); 159 mvwaddch (dialog, height-3, 0, ACS_LTEE); 160 for (i = 0; i < width - 2; i++) 161 waddch (dialog, ACS_HLINE); 162 wattrset (dialog, dialog_attr); 163 waddch (dialog, ACS_RTEE); 164 165 if (title != NULL && strlen(title) >= width-2 ) { 166 /* truncate long title -- mec */ 167 char * title2 = malloc(width-2+1); 168 memcpy( title2, title, width-2 ); 169 title2[width-2] = '\0'; 170 title = title2; 171 } 172 173 if (title != NULL) { 174 wattrset (dialog, title_attr); 175 mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); 176 waddstr (dialog, (char *)title); 177 waddch (dialog, ' '); 178 } 179 180 wattrset (dialog, dialog_attr); 181 print_autowrap (dialog, prompt, width - 2, 1, 3); 182 183 list_width = width - 6; 184 box_y = height - list_height - 5; 185 box_x = (width - list_width) / 2 - 1; 186 187 /* create new window for the list */ 188 list = subwin (dialog, list_height, list_width, y+box_y+1, 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]->name) + 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]->name, 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) == toupper(items[scroll + i]->name[0])) 229 break; 230 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, items[scroll]->name, 242 status[scroll], 0, FALSE); 243 scrollok (list, TRUE); 244 wscrl (list, -1); 245 scrollok (list, FALSE); 246 } 247 scroll--; 248 print_item (list, items[scroll]->name, 249 status[scroll], 0, TRUE); 250 wnoutrefresh (list); 251 252 print_arrows(dialog, choice, item_no, scroll, 253 box_y, box_x + check_x + 5, list_height); 254 255 wrefresh (dialog); 256 257 continue; /* wait for another key press */ 258 } else 259 i = choice - 1; 260 } else if (key == KEY_DOWN || key == '+') { 261 if (choice == max_choice - 1) { 262 if (scroll + choice >= item_no - 1) 263 continue; 264 /* Scroll list up */ 265 if (list_height > 1) { 266 /* De-highlight current last item before scrolling up */ 267 print_item (list, items[scroll + max_choice - 1]->name, 268 status[scroll + max_choice - 1], 269 max_choice - 1, FALSE); 270 scrollok (list, TRUE); 271 scroll (list); 272 scrollok (list, FALSE); 273 } 274 scroll++; 275 print_item (list, items[scroll + max_choice - 1]->name, 276 status[scroll + max_choice - 1], 277 max_choice - 1, TRUE); 278 wnoutrefresh (list); 279 280 print_arrows(dialog, choice, item_no, scroll, 281 box_y, box_x + check_x + 5, list_height); 282 283 wrefresh (dialog); 284 285 continue; /* wait for another key press */ 286 } else 287 i = choice + 1; 288 } 289 if (i != choice) { 290 /* De-highlight current item */ 291 print_item (list, items[scroll + choice]->name, 292 status[scroll + choice], choice, FALSE); 293 /* Highlight new item */ 294 choice = i; 295 print_item (list, items[scroll + choice]->name, 296 status[scroll + choice], choice, TRUE); 297 wnoutrefresh (list); 298 wrefresh (dialog); 299 } 300 continue; /* wait for another key press */ 301 } 302 switch (key) { 303 case 'H': 304 case 'h': 305 case '?': 306 delwin (dialog); 307 free (status); 308 return 1; 309 case TAB: 310 case KEY_LEFT: 311 case KEY_RIGHT: 312 button = ((key == KEY_LEFT ? --button : ++button) < 0) 313 ? 1 : (button > 1 ? 0 : button); 314 315 print_buttons(dialog, height, width, button); 316 wrefresh (dialog); 317 break; 318 case 'S': 319 case 's': 320 case ' ': 321 case '\n': 322 if (!button) { 323 if (flag == FLAG_CHECK) { 324 status[scroll + choice] = !status[scroll + choice]; 325 wmove (list, choice, check_x); 326 wattrset (list, check_selected_attr); 327 wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); 328 } else { 329 if (!status[scroll + choice]) { 330 for (i = 0; i < item_no; i++) 331 status[i] = 0; 332 status[scroll + choice] = 1; 333 for (i = 0; i < max_choice; i++) 334 print_item (list, items[scroll + i]->name, 335 status[scroll + i], i, i == choice); 336 } 337 } 338 wnoutrefresh (list); 339 wrefresh (dialog); 340 341 for (i = 0; i < item_no; i++) { 342 items[i]->selected = status[i]; 343 } 344 } 345 delwin (dialog); 346 free (status); 347 return button; 348 case 'X': 349 case 'x': 350 key = ESC; 351 case ESC: 352 break; 353 } 354 355 /* Now, update everything... */ 356 doupdate (); 357 } 358 359 360 delwin (dialog); 361 free (status); 362 return -1; /* ESC pressed */ 363} 364