10c874100SMasahiro Yamada // SPDX-License-Identifier: GPL-2.0+ 26f6046cfSSam Ravnborg /* 36f6046cfSSam Ravnborg * checklist.c -- implements the checklist box 46f6046cfSSam Ravnborg * 56f6046cfSSam Ravnborg * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 66f6046cfSSam Ravnborg * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension 76f6046cfSSam Ravnborg * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two 86f6046cfSSam Ravnborg * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 96f6046cfSSam Ravnborg */ 106f6046cfSSam Ravnborg 116f6046cfSSam Ravnborg #include "dialog.h" 126f6046cfSSam Ravnborg 1300213b17SPetr Baudis static int list_width, check_x, item_x; 146f6046cfSSam Ravnborg 156f6046cfSSam Ravnborg /* 166f6046cfSSam Ravnborg * Print list item 176f6046cfSSam Ravnborg */ 182982de69SSam Ravnborg static void print_item(WINDOW * win, int choice, int selected) 196f6046cfSSam Ravnborg { 206f6046cfSSam Ravnborg int i; 21e7401d83SLi Zefan char *list_item = malloc(list_width + 1); 22e7401d83SLi Zefan 23e7401d83SLi Zefan strncpy(list_item, item_str(), list_width - item_x); 24e7401d83SLi Zefan list_item[list_width - item_x] = '\0'; 256f6046cfSSam Ravnborg 266f6046cfSSam Ravnborg /* Clear 'residue' of last item */ 2798e5a157SSam Ravnborg wattrset(win, dlg.menubox.atr); 286f6046cfSSam Ravnborg wmove(win, choice, 0); 296f6046cfSSam Ravnborg for (i = 0; i < list_width; i++) 306f6046cfSSam Ravnborg waddch(win, ' '); 316f6046cfSSam Ravnborg 326f6046cfSSam Ravnborg wmove(win, choice, check_x); 3398e5a157SSam Ravnborg wattrset(win, selected ? dlg.check_selected.atr 3498e5a157SSam Ravnborg : dlg.check.atr); 35af6c1598SPeter Korsgaard if (!item_is_tag(':')) 362982de69SSam Ravnborg wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); 376f6046cfSSam Ravnborg 3898e5a157SSam Ravnborg wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); 39e7401d83SLi Zefan mvwaddch(win, choice, item_x, list_item[0]); 4098e5a157SSam Ravnborg wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); 41e7401d83SLi Zefan waddstr(win, list_item + 1); 426f6046cfSSam Ravnborg if (selected) { 436f6046cfSSam Ravnborg wmove(win, choice, check_x + 1); 446f6046cfSSam Ravnborg wrefresh(win); 456f6046cfSSam Ravnborg } 46e7401d83SLi Zefan free(list_item); 476f6046cfSSam Ravnborg } 486f6046cfSSam Ravnborg 496f6046cfSSam Ravnborg /* 506f6046cfSSam Ravnborg * Print the scroll indicators. 516f6046cfSSam Ravnborg */ 526f6046cfSSam Ravnborg static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, 536f6046cfSSam Ravnborg int y, int x, int height) 546f6046cfSSam Ravnborg { 556f6046cfSSam Ravnborg wmove(win, y, x); 566f6046cfSSam Ravnborg 576f6046cfSSam Ravnborg if (scroll > 0) { 5898e5a157SSam Ravnborg wattrset(win, dlg.uarrow.atr); 596f6046cfSSam Ravnborg waddch(win, ACS_UARROW); 606f6046cfSSam Ravnborg waddstr(win, "(-)"); 616f6046cfSSam Ravnborg } else { 6298e5a157SSam Ravnborg wattrset(win, dlg.menubox.atr); 636f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 646f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 656f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 666f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 676f6046cfSSam Ravnborg } 686f6046cfSSam Ravnborg 696f6046cfSSam Ravnborg y = y + height + 1; 706f6046cfSSam Ravnborg wmove(win, y, x); 716f6046cfSSam Ravnborg 726f6046cfSSam Ravnborg if ((height < item_no) && (scroll + choice < item_no - 1)) { 7398e5a157SSam Ravnborg wattrset(win, dlg.darrow.atr); 746f6046cfSSam Ravnborg waddch(win, ACS_DARROW); 756f6046cfSSam Ravnborg waddstr(win, "(+)"); 766f6046cfSSam Ravnborg } else { 7798e5a157SSam Ravnborg wattrset(win, dlg.menubox_border.atr); 786f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 796f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 806f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 816f6046cfSSam Ravnborg waddch(win, ACS_HLINE); 826f6046cfSSam Ravnborg } 836f6046cfSSam Ravnborg } 846f6046cfSSam Ravnborg 856f6046cfSSam Ravnborg /* 866f6046cfSSam Ravnborg * Display the termination buttons 876f6046cfSSam Ravnborg */ 886f6046cfSSam Ravnborg static void print_buttons(WINDOW * dialog, int height, int width, int selected) 896f6046cfSSam Ravnborg { 906f6046cfSSam Ravnborg int x = width / 2 - 11; 916f6046cfSSam Ravnborg int y = height - 2; 926f6046cfSSam Ravnborg 93694c49a7SSam Ravnborg print_button(dialog, "Select", y, x, selected == 0); 94694c49a7SSam Ravnborg print_button(dialog, " Help ", y, x + 14, selected == 1); 956f6046cfSSam Ravnborg 966f6046cfSSam Ravnborg wmove(dialog, y, x + 1 + 14 * selected); 976f6046cfSSam Ravnborg wrefresh(dialog); 986f6046cfSSam Ravnborg } 996f6046cfSSam Ravnborg 1006f6046cfSSam Ravnborg /* 1016f6046cfSSam Ravnborg * Display a dialog box with a list of options that can be turned on or off 10200213b17SPetr Baudis * in the style of radiolist (only one option turned on at a time). 1036f6046cfSSam Ravnborg */ 1046f6046cfSSam Ravnborg int dialog_checklist(const char *title, const char *prompt, int height, 1052982de69SSam Ravnborg int width, int list_height) 1066f6046cfSSam Ravnborg { 1076f6046cfSSam Ravnborg int i, x, y, box_x, box_y; 1082982de69SSam Ravnborg int key = 0, button = 0, choice = 0, scroll = 0, max_choice; 1096f6046cfSSam Ravnborg WINDOW *dialog, *list; 1106f6046cfSSam Ravnborg 1112982de69SSam Ravnborg /* which item to highlight */ 1122982de69SSam Ravnborg item_foreach() { 1132982de69SSam Ravnborg if (item_is_tag('X')) 1142982de69SSam Ravnborg choice = item_n(); 1152982de69SSam Ravnborg if (item_is_selected()) { 1162982de69SSam Ravnborg choice = item_n(); 1172982de69SSam Ravnborg break; 1182982de69SSam Ravnborg } 1196f6046cfSSam Ravnborg } 1206f6046cfSSam Ravnborg 121c8dc68adSSam Ravnborg do_resize: 122851f6657SSedat Dilek if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN)) 123c8dc68adSSam Ravnborg return -ERRDISPLAYTOOSMALL; 124851f6657SSedat Dilek if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN)) 125c8dc68adSSam Ravnborg return -ERRDISPLAYTOOSMALL; 126c8dc68adSSam Ravnborg 1272982de69SSam Ravnborg max_choice = MIN(list_height, item_count()); 1286f6046cfSSam Ravnborg 1296f6046cfSSam Ravnborg /* center dialog box on screen */ 1304f2de3e1SDirk Gouders x = (getmaxx(stdscr) - width) / 2; 1314f2de3e1SDirk Gouders y = (getmaxy(stdscr) - height) / 2; 1326f6046cfSSam Ravnborg 1336f6046cfSSam Ravnborg draw_shadow(stdscr, y, x, height, width); 1346f6046cfSSam Ravnborg 1356f6046cfSSam Ravnborg dialog = newwin(height, width, y, x); 1366f6046cfSSam Ravnborg keypad(dialog, TRUE); 1376f6046cfSSam Ravnborg 13898e5a157SSam Ravnborg draw_box(dialog, 0, 0, height, width, 13998e5a157SSam Ravnborg dlg.dialog.atr, dlg.border.atr); 14098e5a157SSam Ravnborg wattrset(dialog, dlg.border.atr); 1416f6046cfSSam Ravnborg mvwaddch(dialog, height - 3, 0, ACS_LTEE); 1426f6046cfSSam Ravnborg for (i = 0; i < width - 2; i++) 1436f6046cfSSam Ravnborg waddch(dialog, ACS_HLINE); 14498e5a157SSam Ravnborg wattrset(dialog, dlg.dialog.atr); 1456f6046cfSSam Ravnborg waddch(dialog, ACS_RTEE); 1466f6046cfSSam Ravnborg 1476f6046cfSSam Ravnborg print_title(dialog, title, width); 1486f6046cfSSam Ravnborg 14998e5a157SSam Ravnborg wattrset(dialog, dlg.dialog.atr); 1506f6046cfSSam Ravnborg print_autowrap(dialog, prompt, width - 2, 1, 3); 1516f6046cfSSam Ravnborg 1526f6046cfSSam Ravnborg list_width = width - 6; 1536f6046cfSSam Ravnborg box_y = height - list_height - 5; 1546f6046cfSSam Ravnborg box_x = (width - list_width) / 2 - 1; 1556f6046cfSSam Ravnborg 1566f6046cfSSam Ravnborg /* create new window for the list */ 1576f6046cfSSam Ravnborg list = subwin(dialog, list_height, list_width, y + box_y + 1, 1586f6046cfSSam Ravnborg x + box_x + 1); 1596f6046cfSSam Ravnborg 1606f6046cfSSam Ravnborg keypad(list, TRUE); 1616f6046cfSSam Ravnborg 1626f6046cfSSam Ravnborg /* draw a box around the list items */ 1636f6046cfSSam Ravnborg draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, 16498e5a157SSam Ravnborg dlg.menubox_border.atr, dlg.menubox.atr); 1656f6046cfSSam Ravnborg 1666f6046cfSSam Ravnborg /* Find length of longest item in order to center checklist */ 1676f6046cfSSam Ravnborg check_x = 0; 1682982de69SSam Ravnborg item_foreach() 1692982de69SSam Ravnborg check_x = MAX(check_x, strlen(item_str()) + 4); 17042ef223cSLi Zefan check_x = MIN(check_x, list_width); 1716f6046cfSSam Ravnborg 1726f6046cfSSam Ravnborg check_x = (list_width - check_x) / 2; 1736f6046cfSSam Ravnborg item_x = check_x + 4; 1746f6046cfSSam Ravnborg 1756f6046cfSSam Ravnborg if (choice >= list_height) { 1766f6046cfSSam Ravnborg scroll = choice - list_height + 1; 1776f6046cfSSam Ravnborg choice -= scroll; 1786f6046cfSSam Ravnborg } 1796f6046cfSSam Ravnborg 1806f6046cfSSam Ravnborg /* Print the list */ 1816f6046cfSSam Ravnborg for (i = 0; i < max_choice; i++) { 1822982de69SSam Ravnborg item_set(scroll + i); 1832982de69SSam Ravnborg print_item(list, i, i == choice); 1846f6046cfSSam Ravnborg } 1856f6046cfSSam Ravnborg 1862982de69SSam Ravnborg print_arrows(dialog, choice, item_count(), scroll, 1876f6046cfSSam Ravnborg box_y, box_x + check_x + 5, list_height); 1886f6046cfSSam Ravnborg 1896f6046cfSSam Ravnborg print_buttons(dialog, height, width, 0); 1906f6046cfSSam Ravnborg 191*ba3b759fSMatthew Bystrin wmove(list, choice, check_x + 1); 192*ba3b759fSMatthew Bystrin wrefresh(list); 1936f6046cfSSam Ravnborg 194f3cbcdc9SSam Ravnborg while (key != KEY_ESC) { 1956f6046cfSSam Ravnborg key = wgetch(dialog); 1966f6046cfSSam Ravnborg 1972982de69SSam Ravnborg for (i = 0; i < max_choice; i++) { 1982982de69SSam Ravnborg item_set(i + scroll); 1992982de69SSam Ravnborg if (toupper(key) == toupper(item_str()[0])) 2006f6046cfSSam Ravnborg break; 2012982de69SSam Ravnborg } 2026f6046cfSSam Ravnborg 2036f6046cfSSam Ravnborg if (i < max_choice || key == KEY_UP || key == KEY_DOWN || 2046f6046cfSSam Ravnborg key == '+' || key == '-') { 2056f6046cfSSam Ravnborg if (key == KEY_UP || key == '-') { 2066f6046cfSSam Ravnborg if (!choice) { 2076f6046cfSSam Ravnborg if (!scroll) 2086f6046cfSSam Ravnborg continue; 2096f6046cfSSam Ravnborg /* Scroll list down */ 2106f6046cfSSam Ravnborg if (list_height > 1) { 2116f6046cfSSam Ravnborg /* De-highlight current first item */ 2122982de69SSam Ravnborg item_set(scroll); 2132982de69SSam Ravnborg print_item(list, 0, FALSE); 2146f6046cfSSam Ravnborg scrollok(list, TRUE); 2156f6046cfSSam Ravnborg wscrl(list, -1); 2166f6046cfSSam Ravnborg scrollok(list, FALSE); 2176f6046cfSSam Ravnborg } 2186f6046cfSSam Ravnborg scroll--; 2192982de69SSam Ravnborg item_set(scroll); 2202982de69SSam Ravnborg print_item(list, 0, TRUE); 2212982de69SSam Ravnborg print_arrows(dialog, choice, item_count(), 2226f6046cfSSam Ravnborg scroll, box_y, box_x + check_x + 5, list_height); 2236f6046cfSSam Ravnborg 224f043ca43SSamuel Thibault wnoutrefresh(dialog); 225f043ca43SSamuel Thibault wrefresh(list); 2266f6046cfSSam Ravnborg 2276f6046cfSSam Ravnborg continue; /* wait for another key press */ 2286f6046cfSSam Ravnborg } else 2296f6046cfSSam Ravnborg i = choice - 1; 2306f6046cfSSam Ravnborg } else if (key == KEY_DOWN || key == '+') { 2316f6046cfSSam Ravnborg if (choice == max_choice - 1) { 2322982de69SSam Ravnborg if (scroll + choice >= item_count() - 1) 2336f6046cfSSam Ravnborg continue; 2346f6046cfSSam Ravnborg /* Scroll list up */ 2356f6046cfSSam Ravnborg if (list_height > 1) { 2366f6046cfSSam Ravnborg /* De-highlight current last item before scrolling up */ 2372982de69SSam Ravnborg item_set(scroll + max_choice - 1); 2382982de69SSam Ravnborg print_item(list, 2392982de69SSam Ravnborg max_choice - 1, 2402982de69SSam Ravnborg FALSE); 2416f6046cfSSam Ravnborg scrollok(list, TRUE); 2426f6046cfSSam Ravnborg wscrl(list, 1); 2436f6046cfSSam Ravnborg scrollok(list, FALSE); 2446f6046cfSSam Ravnborg } 2456f6046cfSSam Ravnborg scroll++; 2462982de69SSam Ravnborg item_set(scroll + max_choice - 1); 2472982de69SSam Ravnborg print_item(list, max_choice - 1, TRUE); 2486f6046cfSSam Ravnborg 2492982de69SSam Ravnborg print_arrows(dialog, choice, item_count(), 2506f6046cfSSam Ravnborg scroll, box_y, box_x + check_x + 5, list_height); 2516f6046cfSSam Ravnborg 252f043ca43SSamuel Thibault wnoutrefresh(dialog); 253f043ca43SSamuel Thibault wrefresh(list); 2546f6046cfSSam Ravnborg 2556f6046cfSSam Ravnborg continue; /* wait for another key press */ 2566f6046cfSSam Ravnborg } else 2576f6046cfSSam Ravnborg i = choice + 1; 2586f6046cfSSam Ravnborg } 2596f6046cfSSam Ravnborg if (i != choice) { 2606f6046cfSSam Ravnborg /* De-highlight current item */ 2612982de69SSam Ravnborg item_set(scroll + choice); 2622982de69SSam Ravnborg print_item(list, choice, FALSE); 2636f6046cfSSam Ravnborg /* Highlight new item */ 2646f6046cfSSam Ravnborg choice = i; 2652982de69SSam Ravnborg item_set(scroll + choice); 2662982de69SSam Ravnborg print_item(list, choice, TRUE); 267f043ca43SSamuel Thibault wnoutrefresh(dialog); 268f043ca43SSamuel Thibault wrefresh(list); 2696f6046cfSSam Ravnborg } 2706f6046cfSSam Ravnborg continue; /* wait for another key press */ 2716f6046cfSSam Ravnborg } 2726f6046cfSSam Ravnborg switch (key) { 2736f6046cfSSam Ravnborg case 'H': 2746f6046cfSSam Ravnborg case 'h': 2756f6046cfSSam Ravnborg case '?': 2762982de69SSam Ravnborg button = 1; 2772982de69SSam Ravnborg /* fall-through */ 2782982de69SSam Ravnborg case 'S': 2792982de69SSam Ravnborg case 's': 2802982de69SSam Ravnborg case ' ': 2812982de69SSam Ravnborg case '\n': 2822982de69SSam Ravnborg item_foreach() 2832982de69SSam Ravnborg item_set_selected(0); 2842982de69SSam Ravnborg item_set(scroll + choice); 2852982de69SSam Ravnborg item_set_selected(1); 2862982de69SSam Ravnborg delwin(list); 2876f6046cfSSam Ravnborg delwin(dialog); 2882982de69SSam Ravnborg return button; 2896f6046cfSSam Ravnborg case TAB: 2906f6046cfSSam Ravnborg case KEY_LEFT: 2916f6046cfSSam Ravnborg case KEY_RIGHT: 2926f6046cfSSam Ravnborg button = ((key == KEY_LEFT ? --button : ++button) < 0) 2936f6046cfSSam Ravnborg ? 1 : (button > 1 ? 0 : button); 2946f6046cfSSam Ravnborg 2956f6046cfSSam Ravnborg print_buttons(dialog, height, width, button); 2966f6046cfSSam Ravnborg wrefresh(dialog); 2976f6046cfSSam Ravnborg break; 2986f6046cfSSam Ravnborg case 'X': 2996f6046cfSSam Ravnborg case 'x': 300f3cbcdc9SSam Ravnborg key = KEY_ESC; 301f3cbcdc9SSam Ravnborg break; 302f3cbcdc9SSam Ravnborg case KEY_ESC: 303f3cbcdc9SSam Ravnborg key = on_key_esc(dialog); 3046f6046cfSSam Ravnborg break; 305c8dc68adSSam Ravnborg case KEY_RESIZE: 306c8dc68adSSam Ravnborg delwin(list); 307c8dc68adSSam Ravnborg delwin(dialog); 308c8dc68adSSam Ravnborg on_key_resize(); 309c8dc68adSSam Ravnborg goto do_resize; 3106f6046cfSSam Ravnborg } 3116f6046cfSSam Ravnborg 3126f6046cfSSam Ravnborg /* Now, update everything... */ 3136f6046cfSSam Ravnborg doupdate(); 3146f6046cfSSam Ravnborg } 3152982de69SSam Ravnborg delwin(list); 3166f6046cfSSam Ravnborg delwin(dialog); 317f3cbcdc9SSam Ravnborg return key; /* ESC pressed */ 3186f6046cfSSam Ravnborg } 319