16f6046cfSSam Ravnborg /* 26f6046cfSSam Ravnborg * checklist.c -- implements the checklist box 36f6046cfSSam Ravnborg * 46f6046cfSSam Ravnborg * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 56f6046cfSSam Ravnborg * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension 66f6046cfSSam Ravnborg * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two 76f6046cfSSam Ravnborg * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 86f6046cfSSam Ravnborg * 96f6046cfSSam Ravnborg * This program is free software; you can redistribute it and/or 106f6046cfSSam Ravnborg * modify it under the terms of the GNU General Public License 116f6046cfSSam Ravnborg * as published by the Free Software Foundation; either version 2 126f6046cfSSam Ravnborg * of the License, or (at your option) any later version. 136f6046cfSSam Ravnborg * 146f6046cfSSam Ravnborg * This program is distributed in the hope that it will be useful, 156f6046cfSSam Ravnborg * but WITHOUT ANY WARRANTY; without even the implied warranty of 166f6046cfSSam Ravnborg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 176f6046cfSSam Ravnborg * GNU General Public License for more details. 186f6046cfSSam Ravnborg * 196f6046cfSSam Ravnborg * You should have received a copy of the GNU General Public License 206f6046cfSSam Ravnborg * along with this program; if not, write to the Free Software 216f6046cfSSam Ravnborg * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 226f6046cfSSam Ravnborg */ 236f6046cfSSam Ravnborg 246f6046cfSSam Ravnborg #include "dialog.h" 256f6046cfSSam Ravnborg 26*00213b17SPetr Baudis static int list_width, check_x, item_x; 276f6046cfSSam Ravnborg 286f6046cfSSam Ravnborg /* 296f6046cfSSam Ravnborg * Print list item 306f6046cfSSam Ravnborg */ 316f6046cfSSam Ravnborg static void print_item(WINDOW * win, const char *item, int status, int choice, 326f6046cfSSam Ravnborg int selected) 336f6046cfSSam Ravnborg { 346f6046cfSSam Ravnborg int i; 356f6046cfSSam Ravnborg 366f6046cfSSam Ravnborg /* Clear 'residue' of last item */ 376f6046cfSSam Ravnborg wattrset(win, menubox_attr); 386f6046cfSSam Ravnborg wmove(win, choice, 0); 396f6046cfSSam Ravnborg for (i = 0; i < list_width; i++) 406f6046cfSSam Ravnborg waddch(win, ' '); 416f6046cfSSam Ravnborg 426f6046cfSSam Ravnborg wmove(win, choice, check_x); 436f6046cfSSam Ravnborg wattrset(win, selected ? check_selected_attr : check_attr); 446f6046cfSSam Ravnborg wprintw(win, "(%c)", status ? 'X' : ' '); 456f6046cfSSam Ravnborg 466f6046cfSSam Ravnborg wattrset(win, selected ? tag_selected_attr : tag_attr); 476f6046cfSSam Ravnborg mvwaddch(win, choice, item_x, item[0]); 486f6046cfSSam Ravnborg wattrset(win, selected ? item_selected_attr : item_attr); 496f6046cfSSam Ravnborg waddstr(win, (char *)item + 1); 506f6046cfSSam Ravnborg if (selected) { 516f6046cfSSam Ravnborg wmove(win, choice, check_x + 1); 526f6046cfSSam Ravnborg wrefresh(win); 536f6046cfSSam Ravnborg } 546f6046cfSSam Ravnborg } 556f6046cfSSam Ravnborg 566f6046cfSSam Ravnborg /* 576f6046cfSSam Ravnborg * Print the scroll indicators. 586f6046cfSSam Ravnborg */ 596f6046cfSSam Ravnborg static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, 606f6046cfSSam Ravnborg int y, int x, int height) 616f6046cfSSam Ravnborg { 626f6046cfSSam Ravnborg wmove(win, y, x); 636f6046cfSSam Ravnborg 646f6046cfSSam Ravnborg if (scroll > 0) { 656f6046cfSSam Ravnborg wattrset(win, uarrow_attr); 666f6046cfSSam Ravnborg waddch(win, ACS_UARROW); 676f6046cfSSam Ravnborg waddstr(win, "(-)"); 686f6046cfSSam Ravnborg } else { 696f6046cfSSam Ravnborg wattrset(win, menubox_attr); 706f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 716f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 726f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 736f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 746f6046cfSSam Ravnborg } 756f6046cfSSam Ravnborg 766f6046cfSSam Ravnborg y = y + height + 1; 776f6046cfSSam Ravnborg wmove(win, y, x); 786f6046cfSSam Ravnborg 796f6046cfSSam Ravnborg if ((height < item_no) && (scroll + choice < item_no - 1)) { 806f6046cfSSam Ravnborg wattrset(win, darrow_attr); 816f6046cfSSam Ravnborg waddch(win, ACS_DARROW); 826f6046cfSSam Ravnborg waddstr(win, "(+)"); 836f6046cfSSam Ravnborg } else { 846f6046cfSSam Ravnborg wattrset(win, menubox_border_attr); 856f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 866f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 876f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 886f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 896f6046cfSSam Ravnborg } 906f6046cfSSam Ravnborg } 916f6046cfSSam Ravnborg 926f6046cfSSam Ravnborg /* 936f6046cfSSam Ravnborg * Display the termination buttons 946f6046cfSSam Ravnborg */ 956f6046cfSSam Ravnborg static void print_buttons(WINDOW * dialog, int height, int width, int selected) 966f6046cfSSam Ravnborg { 976f6046cfSSam Ravnborg int x = width / 2 - 11; 986f6046cfSSam Ravnborg int y = height - 2; 996f6046cfSSam Ravnborg 1006f6046cfSSam Ravnborg print_button(dialog, "Select", y, x, selected == 0); 1016f6046cfSSam Ravnborg print_button(dialog, " Help ", y, x + 14, selected == 1); 1026f6046cfSSam Ravnborg 1036f6046cfSSam Ravnborg wmove(dialog, y, x + 1 + 14 * selected); 1046f6046cfSSam Ravnborg wrefresh(dialog); 1056f6046cfSSam Ravnborg } 1066f6046cfSSam Ravnborg 1076f6046cfSSam Ravnborg /* 1086f6046cfSSam Ravnborg * Display a dialog box with a list of options that can be turned on or off 109*00213b17SPetr Baudis * in the style of radiolist (only one option turned on at a time). 1106f6046cfSSam Ravnborg */ 1116f6046cfSSam Ravnborg int dialog_checklist(const char *title, const char *prompt, int height, 1126f6046cfSSam Ravnborg int width, int list_height, int item_no, 113*00213b17SPetr Baudis const char *const *items) 1146f6046cfSSam Ravnborg { 1156f6046cfSSam Ravnborg int i, x, y, box_x, box_y; 1166f6046cfSSam Ravnborg int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; 1176f6046cfSSam Ravnborg WINDOW *dialog, *list; 1186f6046cfSSam Ravnborg 1196f6046cfSSam Ravnborg /* Allocate space for storing item on/off status */ 1206f6046cfSSam Ravnborg if ((status = malloc(sizeof(int) * item_no)) == NULL) { 1216f6046cfSSam Ravnborg endwin(); 1226f6046cfSSam Ravnborg fprintf(stderr, 1236f6046cfSSam Ravnborg "\nCan't allocate memory in dialog_checklist().\n"); 1246f6046cfSSam Ravnborg exit(-1); 1256f6046cfSSam Ravnborg } 1266f6046cfSSam Ravnborg 1276f6046cfSSam Ravnborg /* Initializes status */ 1286f6046cfSSam Ravnborg for (i = 0; i < item_no; i++) { 1296f6046cfSSam Ravnborg status[i] = !strcasecmp(items[i * 3 + 2], "on"); 1306f6046cfSSam Ravnborg if ((!choice && status[i]) 1316f6046cfSSam Ravnborg || !strcasecmp(items[i * 3 + 2], "selected")) 1326f6046cfSSam Ravnborg choice = i + 1; 1336f6046cfSSam Ravnborg } 1346f6046cfSSam Ravnborg if (choice) 1356f6046cfSSam Ravnborg choice--; 1366f6046cfSSam Ravnborg 1376f6046cfSSam Ravnborg max_choice = MIN(list_height, item_no); 1386f6046cfSSam Ravnborg 1396f6046cfSSam Ravnborg /* center dialog box on screen */ 1406f6046cfSSam Ravnborg x = (COLS - width) / 2; 1416f6046cfSSam Ravnborg y = (LINES - height) / 2; 1426f6046cfSSam Ravnborg 1436f6046cfSSam Ravnborg draw_shadow(stdscr, y, x, height, width); 1446f6046cfSSam Ravnborg 1456f6046cfSSam Ravnborg dialog = newwin(height, width, y, x); 1466f6046cfSSam Ravnborg keypad(dialog, TRUE); 1476f6046cfSSam Ravnborg 1486f6046cfSSam Ravnborg draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 1496f6046cfSSam Ravnborg wattrset(dialog, border_attr); 1506f6046cfSSam Ravnborg mvwaddch(dialog, height - 3, 0, ACS_LTEE); 1516f6046cfSSam Ravnborg for (i = 0; i < width - 2; i++) 1526f6046cfSSam Ravnborg waddch(dialog, ACS_HLINE); 1536f6046cfSSam Ravnborg wattrset(dialog, dialog_attr); 1546f6046cfSSam Ravnborg waddch(dialog, ACS_RTEE); 1556f6046cfSSam Ravnborg 1566f6046cfSSam Ravnborg print_title(dialog, title, width); 1576f6046cfSSam Ravnborg 1586f6046cfSSam Ravnborg wattrset(dialog, dialog_attr); 1596f6046cfSSam Ravnborg print_autowrap(dialog, prompt, width - 2, 1, 3); 1606f6046cfSSam Ravnborg 1616f6046cfSSam Ravnborg list_width = width - 6; 1626f6046cfSSam Ravnborg box_y = height - list_height - 5; 1636f6046cfSSam Ravnborg box_x = (width - list_width) / 2 - 1; 1646f6046cfSSam Ravnborg 1656f6046cfSSam Ravnborg /* create new window for the list */ 1666f6046cfSSam Ravnborg list = subwin(dialog, list_height, list_width, y + box_y + 1, 1676f6046cfSSam Ravnborg x + box_x + 1); 1686f6046cfSSam Ravnborg 1696f6046cfSSam Ravnborg keypad(list, TRUE); 1706f6046cfSSam Ravnborg 1716f6046cfSSam Ravnborg /* draw a box around the list items */ 1726f6046cfSSam Ravnborg draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, 1736f6046cfSSam Ravnborg menubox_border_attr, menubox_attr); 1746f6046cfSSam Ravnborg 1756f6046cfSSam Ravnborg /* Find length of longest item in order to center checklist */ 1766f6046cfSSam Ravnborg check_x = 0; 1776f6046cfSSam Ravnborg for (i = 0; i < item_no; i++) 1786f6046cfSSam Ravnborg check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4); 1796f6046cfSSam Ravnborg 1806f6046cfSSam Ravnborg check_x = (list_width - check_x) / 2; 1816f6046cfSSam Ravnborg item_x = check_x + 4; 1826f6046cfSSam Ravnborg 1836f6046cfSSam Ravnborg if (choice >= list_height) { 1846f6046cfSSam Ravnborg scroll = choice - list_height + 1; 1856f6046cfSSam Ravnborg choice -= scroll; 1866f6046cfSSam Ravnborg } 1876f6046cfSSam Ravnborg 1886f6046cfSSam Ravnborg /* Print the list */ 1896f6046cfSSam Ravnborg for (i = 0; i < max_choice; i++) { 1906f6046cfSSam Ravnborg print_item(list, items[(scroll + i) * 3 + 1], 1916f6046cfSSam Ravnborg status[i + scroll], i, i == choice); 1926f6046cfSSam Ravnborg } 1936f6046cfSSam Ravnborg 1946f6046cfSSam Ravnborg print_arrows(dialog, choice, item_no, scroll, 1956f6046cfSSam Ravnborg box_y, box_x + check_x + 5, list_height); 1966f6046cfSSam Ravnborg 1976f6046cfSSam Ravnborg print_buttons(dialog, height, width, 0); 1986f6046cfSSam Ravnborg 1996f6046cfSSam Ravnborg wnoutrefresh(list); 2006f6046cfSSam Ravnborg wnoutrefresh(dialog); 2016f6046cfSSam Ravnborg doupdate(); 2026f6046cfSSam Ravnborg 2036f6046cfSSam Ravnborg while (key != ESC) { 2046f6046cfSSam Ravnborg key = wgetch(dialog); 2056f6046cfSSam Ravnborg 2066f6046cfSSam Ravnborg for (i = 0; i < max_choice; i++) 2076f6046cfSSam Ravnborg if (toupper(key) == 2086f6046cfSSam Ravnborg toupper(items[(scroll + i) * 3 + 1][0])) 2096f6046cfSSam Ravnborg break; 2106f6046cfSSam Ravnborg 2116f6046cfSSam Ravnborg if (i < max_choice || key == KEY_UP || key == KEY_DOWN || 2126f6046cfSSam Ravnborg key == '+' || key == '-') { 2136f6046cfSSam Ravnborg if (key == KEY_UP || key == '-') { 2146f6046cfSSam Ravnborg if (!choice) { 2156f6046cfSSam Ravnborg if (!scroll) 2166f6046cfSSam Ravnborg continue; 2176f6046cfSSam Ravnborg /* Scroll list down */ 2186f6046cfSSam Ravnborg if (list_height > 1) { 2196f6046cfSSam Ravnborg /* De-highlight current first item */ 2206f6046cfSSam Ravnborg print_item(list, items[scroll * 3 + 1], 2216f6046cfSSam Ravnborg status[scroll], 0, FALSE); 2226f6046cfSSam Ravnborg scrollok(list, TRUE); 2236f6046cfSSam Ravnborg wscrl(list, -1); 2246f6046cfSSam Ravnborg scrollok(list, FALSE); 2256f6046cfSSam Ravnborg } 2266f6046cfSSam Ravnborg scroll--; 2276f6046cfSSam Ravnborg print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE); 2286f6046cfSSam Ravnborg wnoutrefresh(list); 2296f6046cfSSam Ravnborg 2306f6046cfSSam Ravnborg print_arrows(dialog, choice, item_no, 2316f6046cfSSam Ravnborg scroll, box_y, box_x + check_x + 5, list_height); 2326f6046cfSSam Ravnborg 2336f6046cfSSam Ravnborg wrefresh(dialog); 2346f6046cfSSam Ravnborg 2356f6046cfSSam Ravnborg continue; /* wait for another key press */ 2366f6046cfSSam Ravnborg } else 2376f6046cfSSam Ravnborg i = choice - 1; 2386f6046cfSSam Ravnborg } else if (key == KEY_DOWN || key == '+') { 2396f6046cfSSam Ravnborg if (choice == max_choice - 1) { 2406f6046cfSSam Ravnborg if (scroll + choice >= item_no - 1) 2416f6046cfSSam Ravnborg continue; 2426f6046cfSSam Ravnborg /* Scroll list up */ 2436f6046cfSSam Ravnborg if (list_height > 1) { 2446f6046cfSSam Ravnborg /* De-highlight current last item before scrolling up */ 2456f6046cfSSam Ravnborg print_item(list, items[(scroll + max_choice - 1) * 3 + 1], 2466f6046cfSSam Ravnborg status[scroll + max_choice - 1], 2476f6046cfSSam Ravnborg max_choice - 1, FALSE); 2486f6046cfSSam Ravnborg scrollok(list, TRUE); 2496f6046cfSSam Ravnborg wscrl(list, 1); 2506f6046cfSSam Ravnborg scrollok(list, FALSE); 2516f6046cfSSam Ravnborg } 2526f6046cfSSam Ravnborg scroll++; 2536f6046cfSSam Ravnborg print_item(list, items[(scroll + max_choice - 1) * 3 + 1], 2546f6046cfSSam Ravnborg status[scroll + max_choice - 1], max_choice - 1, TRUE); 2556f6046cfSSam Ravnborg wnoutrefresh(list); 2566f6046cfSSam Ravnborg 2576f6046cfSSam Ravnborg print_arrows(dialog, choice, item_no, 2586f6046cfSSam Ravnborg scroll, box_y, box_x + check_x + 5, list_height); 2596f6046cfSSam Ravnborg 2606f6046cfSSam Ravnborg wrefresh(dialog); 2616f6046cfSSam Ravnborg 2626f6046cfSSam Ravnborg continue; /* wait for another key press */ 2636f6046cfSSam Ravnborg } else 2646f6046cfSSam Ravnborg i = choice + 1; 2656f6046cfSSam Ravnborg } 2666f6046cfSSam Ravnborg if (i != choice) { 2676f6046cfSSam Ravnborg /* De-highlight current item */ 2686f6046cfSSam Ravnborg print_item(list, items[(scroll + choice) * 3 + 1], 2696f6046cfSSam Ravnborg status[scroll + choice], choice, FALSE); 2706f6046cfSSam Ravnborg /* Highlight new item */ 2716f6046cfSSam Ravnborg choice = i; 2726f6046cfSSam Ravnborg print_item(list, items[(scroll + choice) * 3 + 1], 2736f6046cfSSam Ravnborg status[scroll + choice], choice, TRUE); 2746f6046cfSSam Ravnborg wnoutrefresh(list); 2756f6046cfSSam Ravnborg wrefresh(dialog); 2766f6046cfSSam Ravnborg } 2776f6046cfSSam Ravnborg continue; /* wait for another key press */ 2786f6046cfSSam Ravnborg } 2796f6046cfSSam Ravnborg switch (key) { 2806f6046cfSSam Ravnborg case 'H': 2816f6046cfSSam Ravnborg case 'h': 2826f6046cfSSam Ravnborg case '?': 2836f6046cfSSam Ravnborg fprintf(stderr, "%s", items[(scroll + choice) * 3]); 2846f6046cfSSam Ravnborg delwin(dialog); 2856f6046cfSSam Ravnborg free(status); 2866f6046cfSSam Ravnborg return 1; 2876f6046cfSSam Ravnborg case TAB: 2886f6046cfSSam Ravnborg case KEY_LEFT: 2896f6046cfSSam Ravnborg case KEY_RIGHT: 2906f6046cfSSam Ravnborg button = ((key == KEY_LEFT ? --button : ++button) < 0) 2916f6046cfSSam Ravnborg ? 1 : (button > 1 ? 0 : button); 2926f6046cfSSam Ravnborg 2936f6046cfSSam Ravnborg print_buttons(dialog, height, width, button); 2946f6046cfSSam Ravnborg wrefresh(dialog); 2956f6046cfSSam Ravnborg break; 2966f6046cfSSam Ravnborg case 'S': 2976f6046cfSSam Ravnborg case 's': 2986f6046cfSSam Ravnborg case ' ': 2996f6046cfSSam Ravnborg case '\n': 3006f6046cfSSam Ravnborg if (!button) { 3016f6046cfSSam Ravnborg if (!status[scroll + choice]) { 3026f6046cfSSam Ravnborg for (i = 0; i < item_no; i++) 3036f6046cfSSam Ravnborg status[i] = 0; 3046f6046cfSSam Ravnborg status[scroll + choice] = 1; 3056f6046cfSSam Ravnborg for (i = 0; i < max_choice; i++) 3066f6046cfSSam Ravnborg print_item(list, items[(scroll + i) * 3 + 1], 3076f6046cfSSam Ravnborg status[scroll + i], i, i == choice); 3086f6046cfSSam Ravnborg } 3096f6046cfSSam Ravnborg wnoutrefresh(list); 3106f6046cfSSam Ravnborg wrefresh(dialog); 3116f6046cfSSam Ravnborg 312*00213b17SPetr Baudis for (i = 0; i < item_no; i++) 313*00213b17SPetr Baudis if (status[i]) 3146f6046cfSSam Ravnborg fprintf(stderr, "%s", items[i * 3]); 3156f6046cfSSam Ravnborg } else 3166f6046cfSSam Ravnborg fprintf(stderr, "%s", items[(scroll + choice) * 3]); 3176f6046cfSSam Ravnborg delwin(dialog); 3186f6046cfSSam Ravnborg free(status); 3196f6046cfSSam Ravnborg return button; 3206f6046cfSSam Ravnborg case 'X': 3216f6046cfSSam Ravnborg case 'x': 3226f6046cfSSam Ravnborg key = ESC; 3236f6046cfSSam Ravnborg case ESC: 3246f6046cfSSam Ravnborg break; 3256f6046cfSSam Ravnborg } 3266f6046cfSSam Ravnborg 3276f6046cfSSam Ravnborg /* Now, update everything... */ 3286f6046cfSSam Ravnborg doupdate(); 3296f6046cfSSam Ravnborg } 3306f6046cfSSam Ravnborg 3316f6046cfSSam Ravnborg delwin(dialog); 3326f6046cfSSam Ravnborg free(status); 3336f6046cfSSam Ravnborg return -1; /* ESC pressed */ 3346f6046cfSSam Ravnborg } 335