162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * checklist.c -- implements the checklist box 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 662306a36Sopenharmony_ci * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension 762306a36Sopenharmony_ci * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two 862306a36Sopenharmony_ci * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "dialog.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic int list_width, check_x, item_x; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* 1662306a36Sopenharmony_ci * Print list item 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_cistatic void print_item(WINDOW * win, int choice, int selected) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci int i; 2162306a36Sopenharmony_ci char *list_item = malloc(list_width + 1); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci strncpy(list_item, item_str(), list_width - item_x); 2462306a36Sopenharmony_ci list_item[list_width - item_x] = '\0'; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci /* Clear 'residue' of last item */ 2762306a36Sopenharmony_ci wattrset(win, dlg.menubox.atr); 2862306a36Sopenharmony_ci wmove(win, choice, 0); 2962306a36Sopenharmony_ci for (i = 0; i < list_width; i++) 3062306a36Sopenharmony_ci waddch(win, ' '); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci wmove(win, choice, check_x); 3362306a36Sopenharmony_ci wattrset(win, selected ? dlg.check_selected.atr 3462306a36Sopenharmony_ci : dlg.check.atr); 3562306a36Sopenharmony_ci if (!item_is_tag(':')) 3662306a36Sopenharmony_ci wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); 3962306a36Sopenharmony_ci mvwaddch(win, choice, item_x, list_item[0]); 4062306a36Sopenharmony_ci wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); 4162306a36Sopenharmony_ci waddstr(win, list_item + 1); 4262306a36Sopenharmony_ci if (selected) { 4362306a36Sopenharmony_ci wmove(win, choice, check_x + 1); 4462306a36Sopenharmony_ci wrefresh(win); 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci free(list_item); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* 5062306a36Sopenharmony_ci * Print the scroll indicators. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistatic void print_arrows(WINDOW * win, int choice, int item_no, int scroll, 5362306a36Sopenharmony_ci int y, int x, int height) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci wmove(win, y, x); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (scroll > 0) { 5862306a36Sopenharmony_ci wattrset(win, dlg.uarrow.atr); 5962306a36Sopenharmony_ci waddch(win, ACS_UARROW); 6062306a36Sopenharmony_ci waddstr(win, "(-)"); 6162306a36Sopenharmony_ci } else { 6262306a36Sopenharmony_ci wattrset(win, dlg.menubox.atr); 6362306a36Sopenharmony_ci waddch(win, ACS_HLINE); 6462306a36Sopenharmony_ci waddch(win, ACS_HLINE); 6562306a36Sopenharmony_ci waddch(win, ACS_HLINE); 6662306a36Sopenharmony_ci waddch(win, ACS_HLINE); 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci y = y + height + 1; 7062306a36Sopenharmony_ci wmove(win, y, x); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if ((height < item_no) && (scroll + choice < item_no - 1)) { 7362306a36Sopenharmony_ci wattrset(win, dlg.darrow.atr); 7462306a36Sopenharmony_ci waddch(win, ACS_DARROW); 7562306a36Sopenharmony_ci waddstr(win, "(+)"); 7662306a36Sopenharmony_ci } else { 7762306a36Sopenharmony_ci wattrset(win, dlg.menubox_border.atr); 7862306a36Sopenharmony_ci waddch(win, ACS_HLINE); 7962306a36Sopenharmony_ci waddch(win, ACS_HLINE); 8062306a36Sopenharmony_ci waddch(win, ACS_HLINE); 8162306a36Sopenharmony_ci waddch(win, ACS_HLINE); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* 8662306a36Sopenharmony_ci * Display the termination buttons 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cistatic void print_buttons(WINDOW * dialog, int height, int width, int selected) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci int x = width / 2 - 11; 9162306a36Sopenharmony_ci int y = height - 2; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci print_button(dialog, "Select", y, x, selected == 0); 9462306a36Sopenharmony_ci print_button(dialog, " Help ", y, x + 14, selected == 1); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci wmove(dialog, y, x + 1 + 14 * selected); 9762306a36Sopenharmony_ci wrefresh(dialog); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* 10162306a36Sopenharmony_ci * Display a dialog box with a list of options that can be turned on or off 10262306a36Sopenharmony_ci * in the style of radiolist (only one option turned on at a time). 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ciint dialog_checklist(const char *title, const char *prompt, int height, 10562306a36Sopenharmony_ci int width, int list_height) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci int i, x, y, box_x, box_y; 10862306a36Sopenharmony_ci int key = 0, button = 0, choice = 0, scroll = 0, max_choice; 10962306a36Sopenharmony_ci WINDOW *dialog, *list; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* which item to highlight */ 11262306a36Sopenharmony_ci item_foreach() { 11362306a36Sopenharmony_ci if (item_is_tag('X')) 11462306a36Sopenharmony_ci choice = item_n(); 11562306a36Sopenharmony_ci if (item_is_selected()) { 11662306a36Sopenharmony_ci choice = item_n(); 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cido_resize: 12262306a36Sopenharmony_ci if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN)) 12362306a36Sopenharmony_ci return -ERRDISPLAYTOOSMALL; 12462306a36Sopenharmony_ci if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN)) 12562306a36Sopenharmony_ci return -ERRDISPLAYTOOSMALL; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci max_choice = MIN(list_height, item_count()); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* center dialog box on screen */ 13062306a36Sopenharmony_ci x = (getmaxx(stdscr) - width) / 2; 13162306a36Sopenharmony_ci y = (getmaxy(stdscr) - height) / 2; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci draw_shadow(stdscr, y, x, height, width); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci dialog = newwin(height, width, y, x); 13662306a36Sopenharmony_ci keypad(dialog, TRUE); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci draw_box(dialog, 0, 0, height, width, 13962306a36Sopenharmony_ci dlg.dialog.atr, dlg.border.atr); 14062306a36Sopenharmony_ci wattrset(dialog, dlg.border.atr); 14162306a36Sopenharmony_ci mvwaddch(dialog, height - 3, 0, ACS_LTEE); 14262306a36Sopenharmony_ci for (i = 0; i < width - 2; i++) 14362306a36Sopenharmony_ci waddch(dialog, ACS_HLINE); 14462306a36Sopenharmony_ci wattrset(dialog, dlg.dialog.atr); 14562306a36Sopenharmony_ci waddch(dialog, ACS_RTEE); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci print_title(dialog, title, width); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci wattrset(dialog, dlg.dialog.atr); 15062306a36Sopenharmony_ci print_autowrap(dialog, prompt, width - 2, 1, 3); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci list_width = width - 6; 15362306a36Sopenharmony_ci box_y = height - list_height - 5; 15462306a36Sopenharmony_ci box_x = (width - list_width) / 2 - 1; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* create new window for the list */ 15762306a36Sopenharmony_ci list = subwin(dialog, list_height, list_width, y + box_y + 1, 15862306a36Sopenharmony_ci x + box_x + 1); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci keypad(list, TRUE); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* draw a box around the list items */ 16362306a36Sopenharmony_ci draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, 16462306a36Sopenharmony_ci dlg.menubox_border.atr, dlg.menubox.atr); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* Find length of longest item in order to center checklist */ 16762306a36Sopenharmony_ci check_x = 0; 16862306a36Sopenharmony_ci item_foreach() 16962306a36Sopenharmony_ci check_x = MAX(check_x, strlen(item_str()) + 4); 17062306a36Sopenharmony_ci check_x = MIN(check_x, list_width); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci check_x = (list_width - check_x) / 2; 17362306a36Sopenharmony_ci item_x = check_x + 4; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci if (choice >= list_height) { 17662306a36Sopenharmony_ci scroll = choice - list_height + 1; 17762306a36Sopenharmony_ci choice -= scroll; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Print the list */ 18162306a36Sopenharmony_ci for (i = 0; i < max_choice; i++) { 18262306a36Sopenharmony_ci item_set(scroll + i); 18362306a36Sopenharmony_ci print_item(list, i, i == choice); 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci print_arrows(dialog, choice, item_count(), scroll, 18762306a36Sopenharmony_ci box_y, box_x + check_x + 5, list_height); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci print_buttons(dialog, height, width, 0); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci wnoutrefresh(dialog); 19262306a36Sopenharmony_ci wnoutrefresh(list); 19362306a36Sopenharmony_ci doupdate(); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci while (key != KEY_ESC) { 19662306a36Sopenharmony_ci key = wgetch(dialog); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci for (i = 0; i < max_choice; i++) { 19962306a36Sopenharmony_ci item_set(i + scroll); 20062306a36Sopenharmony_ci if (toupper(key) == toupper(item_str()[0])) 20162306a36Sopenharmony_ci break; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (i < max_choice || key == KEY_UP || key == KEY_DOWN || 20562306a36Sopenharmony_ci key == '+' || key == '-') { 20662306a36Sopenharmony_ci if (key == KEY_UP || key == '-') { 20762306a36Sopenharmony_ci if (!choice) { 20862306a36Sopenharmony_ci if (!scroll) 20962306a36Sopenharmony_ci continue; 21062306a36Sopenharmony_ci /* Scroll list down */ 21162306a36Sopenharmony_ci if (list_height > 1) { 21262306a36Sopenharmony_ci /* De-highlight current first item */ 21362306a36Sopenharmony_ci item_set(scroll); 21462306a36Sopenharmony_ci print_item(list, 0, FALSE); 21562306a36Sopenharmony_ci scrollok(list, TRUE); 21662306a36Sopenharmony_ci wscrl(list, -1); 21762306a36Sopenharmony_ci scrollok(list, FALSE); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci scroll--; 22062306a36Sopenharmony_ci item_set(scroll); 22162306a36Sopenharmony_ci print_item(list, 0, TRUE); 22262306a36Sopenharmony_ci print_arrows(dialog, choice, item_count(), 22362306a36Sopenharmony_ci scroll, box_y, box_x + check_x + 5, list_height); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci wnoutrefresh(dialog); 22662306a36Sopenharmony_ci wrefresh(list); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci continue; /* wait for another key press */ 22962306a36Sopenharmony_ci } else 23062306a36Sopenharmony_ci i = choice - 1; 23162306a36Sopenharmony_ci } else if (key == KEY_DOWN || key == '+') { 23262306a36Sopenharmony_ci if (choice == max_choice - 1) { 23362306a36Sopenharmony_ci if (scroll + choice >= item_count() - 1) 23462306a36Sopenharmony_ci continue; 23562306a36Sopenharmony_ci /* Scroll list up */ 23662306a36Sopenharmony_ci if (list_height > 1) { 23762306a36Sopenharmony_ci /* De-highlight current last item before scrolling up */ 23862306a36Sopenharmony_ci item_set(scroll + max_choice - 1); 23962306a36Sopenharmony_ci print_item(list, 24062306a36Sopenharmony_ci max_choice - 1, 24162306a36Sopenharmony_ci FALSE); 24262306a36Sopenharmony_ci scrollok(list, TRUE); 24362306a36Sopenharmony_ci wscrl(list, 1); 24462306a36Sopenharmony_ci scrollok(list, FALSE); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci scroll++; 24762306a36Sopenharmony_ci item_set(scroll + max_choice - 1); 24862306a36Sopenharmony_ci print_item(list, max_choice - 1, TRUE); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci print_arrows(dialog, choice, item_count(), 25162306a36Sopenharmony_ci scroll, box_y, box_x + check_x + 5, list_height); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci wnoutrefresh(dialog); 25462306a36Sopenharmony_ci wrefresh(list); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci continue; /* wait for another key press */ 25762306a36Sopenharmony_ci } else 25862306a36Sopenharmony_ci i = choice + 1; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci if (i != choice) { 26162306a36Sopenharmony_ci /* De-highlight current item */ 26262306a36Sopenharmony_ci item_set(scroll + choice); 26362306a36Sopenharmony_ci print_item(list, choice, FALSE); 26462306a36Sopenharmony_ci /* Highlight new item */ 26562306a36Sopenharmony_ci choice = i; 26662306a36Sopenharmony_ci item_set(scroll + choice); 26762306a36Sopenharmony_ci print_item(list, choice, TRUE); 26862306a36Sopenharmony_ci wnoutrefresh(dialog); 26962306a36Sopenharmony_ci wrefresh(list); 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci continue; /* wait for another key press */ 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci switch (key) { 27462306a36Sopenharmony_ci case 'H': 27562306a36Sopenharmony_ci case 'h': 27662306a36Sopenharmony_ci case '?': 27762306a36Sopenharmony_ci button = 1; 27862306a36Sopenharmony_ci /* fall-through */ 27962306a36Sopenharmony_ci case 'S': 28062306a36Sopenharmony_ci case 's': 28162306a36Sopenharmony_ci case ' ': 28262306a36Sopenharmony_ci case '\n': 28362306a36Sopenharmony_ci item_foreach() 28462306a36Sopenharmony_ci item_set_selected(0); 28562306a36Sopenharmony_ci item_set(scroll + choice); 28662306a36Sopenharmony_ci item_set_selected(1); 28762306a36Sopenharmony_ci delwin(list); 28862306a36Sopenharmony_ci delwin(dialog); 28962306a36Sopenharmony_ci return button; 29062306a36Sopenharmony_ci case TAB: 29162306a36Sopenharmony_ci case KEY_LEFT: 29262306a36Sopenharmony_ci case KEY_RIGHT: 29362306a36Sopenharmony_ci button = ((key == KEY_LEFT ? --button : ++button) < 0) 29462306a36Sopenharmony_ci ? 1 : (button > 1 ? 0 : button); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci print_buttons(dialog, height, width, button); 29762306a36Sopenharmony_ci wrefresh(dialog); 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci case 'X': 30062306a36Sopenharmony_ci case 'x': 30162306a36Sopenharmony_ci key = KEY_ESC; 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci case KEY_ESC: 30462306a36Sopenharmony_ci key = on_key_esc(dialog); 30562306a36Sopenharmony_ci break; 30662306a36Sopenharmony_ci case KEY_RESIZE: 30762306a36Sopenharmony_ci delwin(list); 30862306a36Sopenharmony_ci delwin(dialog); 30962306a36Sopenharmony_ci on_key_resize(); 31062306a36Sopenharmony_ci goto do_resize; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* Now, update everything... */ 31462306a36Sopenharmony_ci doupdate(); 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci delwin(list); 31762306a36Sopenharmony_ci delwin(dialog); 31862306a36Sopenharmony_ci return key; /* ESC pressed */ 31962306a36Sopenharmony_ci} 320