10f66f451Sopenharmony_ci/* 20f66f451Sopenharmony_ci * checklist.c -- implements the checklist box 30f66f451Sopenharmony_ci * 40f66f451Sopenharmony_ci * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 50f66f451Sopenharmony_ci * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension 60f66f451Sopenharmony_ci * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two 70f66f451Sopenharmony_ci * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 80f66f451Sopenharmony_ci * 90f66f451Sopenharmony_ci * This program is free software; you can redistribute it and/or 100f66f451Sopenharmony_ci * modify it under the terms of the GNU General Public License 110f66f451Sopenharmony_ci * as published by the Free Software Foundation; either version 2 120f66f451Sopenharmony_ci * of the License, or (at your option) any later version. 130f66f451Sopenharmony_ci * 140f66f451Sopenharmony_ci * This program is distributed in the hope that it will be useful, 150f66f451Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 160f66f451Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 170f66f451Sopenharmony_ci * GNU General Public License for more details. 180f66f451Sopenharmony_ci * 190f66f451Sopenharmony_ci * You should have received a copy of the GNU General Public License 200f66f451Sopenharmony_ci * along with this program; if not, write to the Free Software 210f66f451Sopenharmony_ci * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 220f66f451Sopenharmony_ci */ 230f66f451Sopenharmony_ci 240f66f451Sopenharmony_ci#include "dialog.h" 250f66f451Sopenharmony_ci 260f66f451Sopenharmony_cistatic int list_width, check_x, item_x; 270f66f451Sopenharmony_ci 280f66f451Sopenharmony_ci/* 290f66f451Sopenharmony_ci * Print list item 300f66f451Sopenharmony_ci */ 310f66f451Sopenharmony_cistatic void print_item(WINDOW * win, int choice, int selected) 320f66f451Sopenharmony_ci{ 330f66f451Sopenharmony_ci int i; 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_ci /* Clear 'residue' of last item */ 360f66f451Sopenharmony_ci wattrset(win, dlg.menubox.atr); 370f66f451Sopenharmony_ci wmove(win, choice, 0); 380f66f451Sopenharmony_ci for (i = 0; i < list_width; i++) 390f66f451Sopenharmony_ci waddch(win, ' '); 400f66f451Sopenharmony_ci 410f66f451Sopenharmony_ci wmove(win, choice, check_x); 420f66f451Sopenharmony_ci wattrset(win, selected ? dlg.check_selected.atr 430f66f451Sopenharmony_ci : dlg.check.atr); 440f66f451Sopenharmony_ci wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); 450f66f451Sopenharmony_ci 460f66f451Sopenharmony_ci wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); 470f66f451Sopenharmony_ci mvwaddch(win, choice, item_x, item_str()[0]); 480f66f451Sopenharmony_ci wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); 490f66f451Sopenharmony_ci waddstr(win, (char *)item_str() + 1); 500f66f451Sopenharmony_ci if (selected) { 510f66f451Sopenharmony_ci wmove(win, choice, check_x + 1); 520f66f451Sopenharmony_ci wrefresh(win); 530f66f451Sopenharmony_ci } 540f66f451Sopenharmony_ci} 550f66f451Sopenharmony_ci 560f66f451Sopenharmony_ci/* 570f66f451Sopenharmony_ci * Print the scroll indicators. 580f66f451Sopenharmony_ci */ 590f66f451Sopenharmony_cistatic void print_arrows(WINDOW * win, int choice, int item_no, int scroll, 600f66f451Sopenharmony_ci int y, int x, int height) 610f66f451Sopenharmony_ci{ 620f66f451Sopenharmony_ci wmove(win, y, x); 630f66f451Sopenharmony_ci 640f66f451Sopenharmony_ci if (scroll > 0) { 650f66f451Sopenharmony_ci wattrset(win, dlg.uarrow.atr); 660f66f451Sopenharmony_ci waddch(win, ACS_UARROW); 670f66f451Sopenharmony_ci waddstr(win, "(-)"); 680f66f451Sopenharmony_ci } else { 690f66f451Sopenharmony_ci wattrset(win, dlg.menubox.atr); 700f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 710f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 720f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 730f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 740f66f451Sopenharmony_ci } 750f66f451Sopenharmony_ci 760f66f451Sopenharmony_ci y = y + height + 1; 770f66f451Sopenharmony_ci wmove(win, y, x); 780f66f451Sopenharmony_ci 790f66f451Sopenharmony_ci if ((height < item_no) && (scroll + choice < item_no - 1)) { 800f66f451Sopenharmony_ci wattrset(win, dlg.darrow.atr); 810f66f451Sopenharmony_ci waddch(win, ACS_DARROW); 820f66f451Sopenharmony_ci waddstr(win, "(+)"); 830f66f451Sopenharmony_ci } else { 840f66f451Sopenharmony_ci wattrset(win, dlg.menubox_border.atr); 850f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 860f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 870f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 880f66f451Sopenharmony_ci waddch(win, ACS_HLINE); 890f66f451Sopenharmony_ci } 900f66f451Sopenharmony_ci} 910f66f451Sopenharmony_ci 920f66f451Sopenharmony_ci/* 930f66f451Sopenharmony_ci * Display the termination buttons 940f66f451Sopenharmony_ci */ 950f66f451Sopenharmony_cistatic void print_buttons(WINDOW * dialog, int height, int width, int selected) 960f66f451Sopenharmony_ci{ 970f66f451Sopenharmony_ci int x = width / 2 - 11; 980f66f451Sopenharmony_ci int y = height - 2; 990f66f451Sopenharmony_ci 1000f66f451Sopenharmony_ci print_button(dialog, "Select", y, x, selected == 0); 1010f66f451Sopenharmony_ci print_button(dialog, " Help ", y, x + 14, selected == 1); 1020f66f451Sopenharmony_ci 1030f66f451Sopenharmony_ci wmove(dialog, y, x + 1 + 14 * selected); 1040f66f451Sopenharmony_ci wrefresh(dialog); 1050f66f451Sopenharmony_ci} 1060f66f451Sopenharmony_ci 1070f66f451Sopenharmony_ci/* 1080f66f451Sopenharmony_ci * Display a dialog box with a list of options that can be turned on or off 1090f66f451Sopenharmony_ci * in the style of radiolist (only one option turned on at a time). 1100f66f451Sopenharmony_ci */ 1110f66f451Sopenharmony_ciint dialog_checklist(const char *title, const char *prompt, int height, 1120f66f451Sopenharmony_ci int width, int list_height) 1130f66f451Sopenharmony_ci{ 1140f66f451Sopenharmony_ci int i, x, y, box_x, box_y; 1150f66f451Sopenharmony_ci int key = 0, button = 0, choice = 0, scroll = 0, max_choice; 1160f66f451Sopenharmony_ci WINDOW *dialog, *list; 1170f66f451Sopenharmony_ci 1180f66f451Sopenharmony_ci /* which item to highlight */ 1190f66f451Sopenharmony_ci item_foreach() { 1200f66f451Sopenharmony_ci if (item_is_tag('X')) 1210f66f451Sopenharmony_ci choice = item_n(); 1220f66f451Sopenharmony_ci if (item_is_selected()) { 1230f66f451Sopenharmony_ci choice = item_n(); 1240f66f451Sopenharmony_ci break; 1250f66f451Sopenharmony_ci } 1260f66f451Sopenharmony_ci } 1270f66f451Sopenharmony_ci 1280f66f451Sopenharmony_cido_resize: 1290f66f451Sopenharmony_ci if (getmaxy(stdscr) < (height + 6)) 1300f66f451Sopenharmony_ci return -ERRDISPLAYTOOSMALL; 1310f66f451Sopenharmony_ci if (getmaxx(stdscr) < (width + 6)) 1320f66f451Sopenharmony_ci return -ERRDISPLAYTOOSMALL; 1330f66f451Sopenharmony_ci 1340f66f451Sopenharmony_ci max_choice = MIN(list_height, item_count()); 1350f66f451Sopenharmony_ci 1360f66f451Sopenharmony_ci /* center dialog box on screen */ 1370f66f451Sopenharmony_ci x = (COLS - width) / 2; 1380f66f451Sopenharmony_ci y = (LINES - height) / 2; 1390f66f451Sopenharmony_ci 1400f66f451Sopenharmony_ci draw_shadow(stdscr, y, x, height, width); 1410f66f451Sopenharmony_ci 1420f66f451Sopenharmony_ci dialog = newwin(height, width, y, x); 1430f66f451Sopenharmony_ci keypad(dialog, TRUE); 1440f66f451Sopenharmony_ci 1450f66f451Sopenharmony_ci draw_box(dialog, 0, 0, height, width, 1460f66f451Sopenharmony_ci dlg.dialog.atr, dlg.border.atr); 1470f66f451Sopenharmony_ci wattrset(dialog, dlg.border.atr); 1480f66f451Sopenharmony_ci mvwaddch(dialog, height - 3, 0, ACS_LTEE); 1490f66f451Sopenharmony_ci for (i = 0; i < width - 2; i++) 1500f66f451Sopenharmony_ci waddch(dialog, ACS_HLINE); 1510f66f451Sopenharmony_ci wattrset(dialog, dlg.dialog.atr); 1520f66f451Sopenharmony_ci waddch(dialog, ACS_RTEE); 1530f66f451Sopenharmony_ci 1540f66f451Sopenharmony_ci print_title(dialog, title, width); 1550f66f451Sopenharmony_ci 1560f66f451Sopenharmony_ci wattrset(dialog, dlg.dialog.atr); 1570f66f451Sopenharmony_ci print_autowrap(dialog, prompt, width - 2, 1, 3); 1580f66f451Sopenharmony_ci 1590f66f451Sopenharmony_ci list_width = width - 6; 1600f66f451Sopenharmony_ci box_y = height - list_height - 5; 1610f66f451Sopenharmony_ci box_x = (width - list_width) / 2 - 1; 1620f66f451Sopenharmony_ci 1630f66f451Sopenharmony_ci /* create new window for the list */ 1640f66f451Sopenharmony_ci list = subwin(dialog, list_height, list_width, y + box_y + 1, 1650f66f451Sopenharmony_ci x + box_x + 1); 1660f66f451Sopenharmony_ci 1670f66f451Sopenharmony_ci keypad(list, TRUE); 1680f66f451Sopenharmony_ci 1690f66f451Sopenharmony_ci /* draw a box around the list items */ 1700f66f451Sopenharmony_ci draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, 1710f66f451Sopenharmony_ci dlg.menubox_border.atr, dlg.menubox.atr); 1720f66f451Sopenharmony_ci 1730f66f451Sopenharmony_ci /* Find length of longest item in order to center checklist */ 1740f66f451Sopenharmony_ci check_x = 0; 1750f66f451Sopenharmony_ci item_foreach() 1760f66f451Sopenharmony_ci check_x = MAX(check_x, strlen(item_str()) + 4); 1770f66f451Sopenharmony_ci 1780f66f451Sopenharmony_ci check_x = (list_width - check_x) / 2; 1790f66f451Sopenharmony_ci item_x = check_x + 4; 1800f66f451Sopenharmony_ci 1810f66f451Sopenharmony_ci if (choice >= list_height) { 1820f66f451Sopenharmony_ci scroll = choice - list_height + 1; 1830f66f451Sopenharmony_ci choice -= scroll; 1840f66f451Sopenharmony_ci } 1850f66f451Sopenharmony_ci 1860f66f451Sopenharmony_ci /* Print the list */ 1870f66f451Sopenharmony_ci for (i = 0; i < max_choice; i++) { 1880f66f451Sopenharmony_ci item_set(scroll + i); 1890f66f451Sopenharmony_ci print_item(list, i, i == choice); 1900f66f451Sopenharmony_ci } 1910f66f451Sopenharmony_ci 1920f66f451Sopenharmony_ci print_arrows(dialog, choice, item_count(), scroll, 1930f66f451Sopenharmony_ci box_y, box_x + check_x + 5, list_height); 1940f66f451Sopenharmony_ci 1950f66f451Sopenharmony_ci print_buttons(dialog, height, width, 0); 1960f66f451Sopenharmony_ci 1970f66f451Sopenharmony_ci wnoutrefresh(dialog); 1980f66f451Sopenharmony_ci wnoutrefresh(list); 1990f66f451Sopenharmony_ci doupdate(); 2000f66f451Sopenharmony_ci 2010f66f451Sopenharmony_ci while (key != KEY_ESC) { 2020f66f451Sopenharmony_ci key = wgetch(dialog); 2030f66f451Sopenharmony_ci 2040f66f451Sopenharmony_ci for (i = 0; i < max_choice; i++) { 2050f66f451Sopenharmony_ci item_set(i + scroll); 2060f66f451Sopenharmony_ci if (toupper(key) == toupper(item_str()[0])) 2070f66f451Sopenharmony_ci break; 2080f66f451Sopenharmony_ci } 2090f66f451Sopenharmony_ci 2100f66f451Sopenharmony_ci if (i < max_choice || key == KEY_UP || key == KEY_DOWN || 2110f66f451Sopenharmony_ci key == '+' || key == '-') { 2120f66f451Sopenharmony_ci if (key == KEY_UP || key == '-') { 2130f66f451Sopenharmony_ci if (!choice) { 2140f66f451Sopenharmony_ci if (!scroll) 2150f66f451Sopenharmony_ci continue; 2160f66f451Sopenharmony_ci /* Scroll list down */ 2170f66f451Sopenharmony_ci if (list_height > 1) { 2180f66f451Sopenharmony_ci /* De-highlight current first item */ 2190f66f451Sopenharmony_ci item_set(scroll); 2200f66f451Sopenharmony_ci print_item(list, 0, FALSE); 2210f66f451Sopenharmony_ci scrollok(list, TRUE); 2220f66f451Sopenharmony_ci wscrl(list, -1); 2230f66f451Sopenharmony_ci scrollok(list, FALSE); 2240f66f451Sopenharmony_ci } 2250f66f451Sopenharmony_ci scroll--; 2260f66f451Sopenharmony_ci item_set(scroll); 2270f66f451Sopenharmony_ci print_item(list, 0, TRUE); 2280f66f451Sopenharmony_ci print_arrows(dialog, choice, item_count(), 2290f66f451Sopenharmony_ci scroll, box_y, box_x + check_x + 5, list_height); 2300f66f451Sopenharmony_ci 2310f66f451Sopenharmony_ci wnoutrefresh(dialog); 2320f66f451Sopenharmony_ci wrefresh(list); 2330f66f451Sopenharmony_ci 2340f66f451Sopenharmony_ci continue; /* wait for another key press */ 2350f66f451Sopenharmony_ci } else 2360f66f451Sopenharmony_ci i = choice - 1; 2370f66f451Sopenharmony_ci } else if (key == KEY_DOWN || key == '+') { 2380f66f451Sopenharmony_ci if (choice == max_choice - 1) { 2390f66f451Sopenharmony_ci if (scroll + choice >= item_count() - 1) 2400f66f451Sopenharmony_ci continue; 2410f66f451Sopenharmony_ci /* Scroll list up */ 2420f66f451Sopenharmony_ci if (list_height > 1) { 2430f66f451Sopenharmony_ci /* De-highlight current last item before scrolling up */ 2440f66f451Sopenharmony_ci item_set(scroll + max_choice - 1); 2450f66f451Sopenharmony_ci print_item(list, 2460f66f451Sopenharmony_ci max_choice - 1, 2470f66f451Sopenharmony_ci FALSE); 2480f66f451Sopenharmony_ci scrollok(list, TRUE); 2490f66f451Sopenharmony_ci wscrl(list, 1); 2500f66f451Sopenharmony_ci scrollok(list, FALSE); 2510f66f451Sopenharmony_ci } 2520f66f451Sopenharmony_ci scroll++; 2530f66f451Sopenharmony_ci item_set(scroll + max_choice - 1); 2540f66f451Sopenharmony_ci print_item(list, max_choice - 1, TRUE); 2550f66f451Sopenharmony_ci 2560f66f451Sopenharmony_ci print_arrows(dialog, choice, item_count(), 2570f66f451Sopenharmony_ci scroll, box_y, box_x + check_x + 5, list_height); 2580f66f451Sopenharmony_ci 2590f66f451Sopenharmony_ci wnoutrefresh(dialog); 2600f66f451Sopenharmony_ci wrefresh(list); 2610f66f451Sopenharmony_ci 2620f66f451Sopenharmony_ci continue; /* wait for another key press */ 2630f66f451Sopenharmony_ci } else 2640f66f451Sopenharmony_ci i = choice + 1; 2650f66f451Sopenharmony_ci } 2660f66f451Sopenharmony_ci if (i != choice) { 2670f66f451Sopenharmony_ci /* De-highlight current item */ 2680f66f451Sopenharmony_ci item_set(scroll + choice); 2690f66f451Sopenharmony_ci print_item(list, choice, FALSE); 2700f66f451Sopenharmony_ci /* Highlight new item */ 2710f66f451Sopenharmony_ci choice = i; 2720f66f451Sopenharmony_ci item_set(scroll + choice); 2730f66f451Sopenharmony_ci print_item(list, choice, TRUE); 2740f66f451Sopenharmony_ci wnoutrefresh(dialog); 2750f66f451Sopenharmony_ci wrefresh(list); 2760f66f451Sopenharmony_ci } 2770f66f451Sopenharmony_ci continue; /* wait for another key press */ 2780f66f451Sopenharmony_ci } 2790f66f451Sopenharmony_ci switch (key) { 2800f66f451Sopenharmony_ci case 'H': 2810f66f451Sopenharmony_ci case 'h': 2820f66f451Sopenharmony_ci case '?': 2830f66f451Sopenharmony_ci button = 1; 2840f66f451Sopenharmony_ci /* fall-through */ 2850f66f451Sopenharmony_ci case 'S': 2860f66f451Sopenharmony_ci case 's': 2870f66f451Sopenharmony_ci case ' ': 2880f66f451Sopenharmony_ci case '\n': 2890f66f451Sopenharmony_ci item_foreach() 2900f66f451Sopenharmony_ci item_set_selected(0); 2910f66f451Sopenharmony_ci item_set(scroll + choice); 2920f66f451Sopenharmony_ci item_set_selected(1); 2930f66f451Sopenharmony_ci delwin(list); 2940f66f451Sopenharmony_ci delwin(dialog); 2950f66f451Sopenharmony_ci return button; 2960f66f451Sopenharmony_ci case TAB: 2970f66f451Sopenharmony_ci case KEY_LEFT: 2980f66f451Sopenharmony_ci case KEY_RIGHT: 2990f66f451Sopenharmony_ci button = ((key == KEY_LEFT ? --button : ++button) < 0) 3000f66f451Sopenharmony_ci ? 1 : (button > 1 ? 0 : button); 3010f66f451Sopenharmony_ci 3020f66f451Sopenharmony_ci print_buttons(dialog, height, width, button); 3030f66f451Sopenharmony_ci wrefresh(dialog); 3040f66f451Sopenharmony_ci break; 3050f66f451Sopenharmony_ci case 'X': 3060f66f451Sopenharmony_ci case 'x': 3070f66f451Sopenharmony_ci key = KEY_ESC; 3080f66f451Sopenharmony_ci break; 3090f66f451Sopenharmony_ci case KEY_ESC: 3100f66f451Sopenharmony_ci key = on_key_esc(dialog); 3110f66f451Sopenharmony_ci break; 3120f66f451Sopenharmony_ci case KEY_RESIZE: 3130f66f451Sopenharmony_ci delwin(list); 3140f66f451Sopenharmony_ci delwin(dialog); 3150f66f451Sopenharmony_ci on_key_resize(); 3160f66f451Sopenharmony_ci goto do_resize; 3170f66f451Sopenharmony_ci } 3180f66f451Sopenharmony_ci 3190f66f451Sopenharmony_ci /* Now, update everything... */ 3200f66f451Sopenharmony_ci doupdate(); 3210f66f451Sopenharmony_ci } 3220f66f451Sopenharmony_ci delwin(list); 3230f66f451Sopenharmony_ci delwin(dialog); 3240f66f451Sopenharmony_ci return key; /* ESC pressed */ 3250f66f451Sopenharmony_ci} 326