14c8945a0SNathan Whitehorn /* 2*febdb468SDevin Teske * $Id: checklist.c,v 1.153 2013/09/02 17:01:02 tom Exp $ 34c8945a0SNathan Whitehorn * 44c8945a0SNathan Whitehorn * checklist.c -- implements the checklist box 54c8945a0SNathan Whitehorn * 62a3e3873SBaptiste Daroussin * Copyright 2000-2012,2013 Thomas E. Dickey 74c8945a0SNathan Whitehorn * 84c8945a0SNathan Whitehorn * This program is free software; you can redistribute it and/or modify 94c8945a0SNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 104c8945a0SNathan Whitehorn * as published by the Free Software Foundation. 114c8945a0SNathan Whitehorn * 124c8945a0SNathan Whitehorn * This program is distributed in the hope that it will be useful, but 134c8945a0SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 144c8945a0SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 154c8945a0SNathan Whitehorn * Lesser General Public License for more details. 164c8945a0SNathan Whitehorn * 174c8945a0SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public 184c8945a0SNathan Whitehorn * License along with this program; if not, write to 194c8945a0SNathan Whitehorn * Free Software Foundation, Inc. 204c8945a0SNathan Whitehorn * 51 Franklin St., Fifth Floor 214c8945a0SNathan Whitehorn * Boston, MA 02110, USA. 224c8945a0SNathan Whitehorn * 234c8945a0SNathan Whitehorn * An earlier version of this program lists as authors: 244c8945a0SNathan Whitehorn * Savio Lam (lam836@cs.cuhk.hk) 254c8945a0SNathan Whitehorn * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension 264c8945a0SNathan Whitehorn * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two 274c8945a0SNathan Whitehorn */ 284c8945a0SNathan Whitehorn 294c8945a0SNathan Whitehorn #include <dialog.h> 304c8945a0SNathan Whitehorn #include <dlg_keys.h> 314c8945a0SNathan Whitehorn 324c8945a0SNathan Whitehorn #define MIN_HIGH (1 + (5 * MARGIN)) 334c8945a0SNathan Whitehorn 342a3e3873SBaptiste Daroussin typedef struct { 352a3e3873SBaptiste Daroussin /* the outer-window */ 362a3e3873SBaptiste Daroussin WINDOW *dialog; 372a3e3873SBaptiste Daroussin int box_y; 382a3e3873SBaptiste Daroussin int box_x; 392a3e3873SBaptiste Daroussin int check_x; 402a3e3873SBaptiste Daroussin int item_x; 412a3e3873SBaptiste Daroussin int checkflag; 422a3e3873SBaptiste Daroussin int use_height; 432a3e3873SBaptiste Daroussin int use_width; 442a3e3873SBaptiste Daroussin /* the inner-window */ 452a3e3873SBaptiste Daroussin WINDOW *list; 462a3e3873SBaptiste Daroussin DIALOG_LISTITEM *items; 472a3e3873SBaptiste Daroussin int item_no; 482a3e3873SBaptiste Daroussin const char *states; 492a3e3873SBaptiste Daroussin } ALL_DATA; 504c8945a0SNathan Whitehorn 514c8945a0SNathan Whitehorn /* 524c8945a0SNathan Whitehorn * Print list item. The 'selected' parameter is true if 'choice' is the 534c8945a0SNathan Whitehorn * current item. That one is colored differently from the other items. 544c8945a0SNathan Whitehorn */ 554c8945a0SNathan Whitehorn static void 562a3e3873SBaptiste Daroussin print_item(ALL_DATA * data, 572a3e3873SBaptiste Daroussin WINDOW *win, 584c8945a0SNathan Whitehorn DIALOG_LISTITEM * item, 594c8945a0SNathan Whitehorn const char *states, 604c8945a0SNathan Whitehorn int choice, 614c8945a0SNathan Whitehorn int selected) 624c8945a0SNathan Whitehorn { 637a1c0d96SNathan Whitehorn chtype save = dlg_get_attrs(win); 644c8945a0SNathan Whitehorn int i; 652a3e3873SBaptiste Daroussin bool both = (!dialog_vars.no_tags && !dialog_vars.no_items); 662a3e3873SBaptiste Daroussin bool first = TRUE; 672a3e3873SBaptiste Daroussin int climit = (getmaxx(win) - data->check_x + 1); 682a3e3873SBaptiste Daroussin const char *show = (dialog_vars.no_items 692a3e3873SBaptiste Daroussin ? item->name 702a3e3873SBaptiste Daroussin : item->text); 714c8945a0SNathan Whitehorn 724c8945a0SNathan Whitehorn /* Clear 'residue' of last item */ 732a3e3873SBaptiste Daroussin (void) wattrset(win, menubox_attr); 744c8945a0SNathan Whitehorn (void) wmove(win, choice, 0); 752a3e3873SBaptiste Daroussin for (i = 0; i < data->use_width; i++) 764c8945a0SNathan Whitehorn (void) waddch(win, ' '); 774c8945a0SNathan Whitehorn 782a3e3873SBaptiste Daroussin (void) wmove(win, choice, data->check_x); 792a3e3873SBaptiste Daroussin (void) wattrset(win, selected ? check_selected_attr : check_attr); 804c8945a0SNathan Whitehorn (void) wprintw(win, 812a3e3873SBaptiste Daroussin (data->checkflag == FLAG_CHECK) ? "[%c]" : "(%c)", 824c8945a0SNathan Whitehorn states[item->state]); 832a3e3873SBaptiste Daroussin (void) wattrset(win, menubox_attr); 844c8945a0SNathan Whitehorn (void) waddch(win, ' '); 854c8945a0SNathan Whitehorn 862a3e3873SBaptiste Daroussin if (both) { 872a3e3873SBaptiste Daroussin dlg_print_listitem(win, item->name, climit, first, selected); 882a3e3873SBaptiste Daroussin first = FALSE; 894c8945a0SNathan Whitehorn } 904c8945a0SNathan Whitehorn 912a3e3873SBaptiste Daroussin (void) wmove(win, choice, data->item_x); 922a3e3873SBaptiste Daroussin dlg_print_listitem(win, show, climit, first, selected); 934c8945a0SNathan Whitehorn 944c8945a0SNathan Whitehorn if (selected) { 954c8945a0SNathan Whitehorn dlg_item_help(item->help); 964c8945a0SNathan Whitehorn } 972a3e3873SBaptiste Daroussin (void) wattrset(win, save); 982a3e3873SBaptiste Daroussin } 992a3e3873SBaptiste Daroussin 1002a3e3873SBaptiste Daroussin static void 1012a3e3873SBaptiste Daroussin print_list(ALL_DATA * data, int choice, int scrollamt, int max_choice) 1022a3e3873SBaptiste Daroussin { 1032a3e3873SBaptiste Daroussin int i; 1042a3e3873SBaptiste Daroussin int cur_y, cur_x; 1052a3e3873SBaptiste Daroussin 1062a3e3873SBaptiste Daroussin getyx(data->dialog, cur_y, cur_x); 1072a3e3873SBaptiste Daroussin for (i = 0; i < max_choice; i++) { 1082a3e3873SBaptiste Daroussin print_item(data, 1092a3e3873SBaptiste Daroussin data->list, 1102a3e3873SBaptiste Daroussin &data->items[i + scrollamt], 1112a3e3873SBaptiste Daroussin data->states, 1122a3e3873SBaptiste Daroussin i, i == choice); 1132a3e3873SBaptiste Daroussin } 1142a3e3873SBaptiste Daroussin (void) wnoutrefresh(data->list); 1152a3e3873SBaptiste Daroussin 1162a3e3873SBaptiste Daroussin dlg_draw_scrollbar(data->dialog, 1172a3e3873SBaptiste Daroussin (long) (scrollamt), 1182a3e3873SBaptiste Daroussin (long) (scrollamt), 1192a3e3873SBaptiste Daroussin (long) (scrollamt + max_choice), 1202a3e3873SBaptiste Daroussin (long) (data->item_no), 1212a3e3873SBaptiste Daroussin data->box_x + data->check_x, 1222a3e3873SBaptiste Daroussin data->box_x + data->use_width, 1232a3e3873SBaptiste Daroussin data->box_y, 1242a3e3873SBaptiste Daroussin data->box_y + data->use_height + 1, 1252a3e3873SBaptiste Daroussin menubox_border2_attr, 1262a3e3873SBaptiste Daroussin menubox_border_attr); 1272a3e3873SBaptiste Daroussin 1282a3e3873SBaptiste Daroussin (void) wmove(data->dialog, cur_y, cur_x); 1292a3e3873SBaptiste Daroussin } 1302a3e3873SBaptiste Daroussin 1312a3e3873SBaptiste Daroussin static bool 1322a3e3873SBaptiste Daroussin check_hotkey(DIALOG_LISTITEM * items, int choice) 1332a3e3873SBaptiste Daroussin { 1342a3e3873SBaptiste Daroussin bool result = FALSE; 1352a3e3873SBaptiste Daroussin 1362a3e3873SBaptiste Daroussin if (dlg_match_char(dlg_last_getc(), 1372a3e3873SBaptiste Daroussin (dialog_vars.no_tags 1382a3e3873SBaptiste Daroussin ? items[choice].text 1392a3e3873SBaptiste Daroussin : items[choice].name))) { 1402a3e3873SBaptiste Daroussin result = TRUE; 1412a3e3873SBaptiste Daroussin } 1422a3e3873SBaptiste Daroussin return result; 1434c8945a0SNathan Whitehorn } 1444c8945a0SNathan Whitehorn 1454c8945a0SNathan Whitehorn /* 1464c8945a0SNathan Whitehorn * This is an alternate interface to 'checklist' which allows the application 1474c8945a0SNathan Whitehorn * to read the list item states back directly without putting them in the 1484c8945a0SNathan Whitehorn * output buffer. It also provides for more than two states over which the 1494c8945a0SNathan Whitehorn * check/radio box can display. 1504c8945a0SNathan Whitehorn */ 1514c8945a0SNathan Whitehorn int 1524c8945a0SNathan Whitehorn dlg_checklist(const char *title, 1534c8945a0SNathan Whitehorn const char *cprompt, 1544c8945a0SNathan Whitehorn int height, 1554c8945a0SNathan Whitehorn int width, 1564c8945a0SNathan Whitehorn int list_height, 1574c8945a0SNathan Whitehorn int item_no, 1584c8945a0SNathan Whitehorn DIALOG_LISTITEM * items, 1594c8945a0SNathan Whitehorn const char *states, 1604c8945a0SNathan Whitehorn int flag, 1614c8945a0SNathan Whitehorn int *current_item) 1624c8945a0SNathan Whitehorn { 1634c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 1644c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 165682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 1664c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 1674c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ), 1684c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 1694c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 1704c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ), 1714c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_FIRST, KEY_HOME ), 1724c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_LAST, KEY_END ), 1734c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_LAST, KEY_LL ), 1744c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, '+' ), 1754c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ), 1764c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ), 1774c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, '-' ), 1784c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ), 1794c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ), 1804c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), 1814c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, DLGK_MOUSE(KEY_NPAGE) ), 1824c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ), 1834c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, DLGK_MOUSE(KEY_PPAGE) ), 1844c8945a0SNathan Whitehorn END_KEYS_BINDING 1854c8945a0SNathan Whitehorn }; 1864c8945a0SNathan Whitehorn /* *INDENT-ON* */ 1874c8945a0SNathan Whitehorn 1884c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 1894c8945a0SNathan Whitehorn int old_height = height; 1904c8945a0SNathan Whitehorn int old_width = width; 1914c8945a0SNathan Whitehorn #endif 1922a3e3873SBaptiste Daroussin ALL_DATA all; 1932a3e3873SBaptiste Daroussin int i, j, key2, found, x, y, cur_x, cur_y; 1944c8945a0SNathan Whitehorn int key = 0, fkey; 1952a3e3873SBaptiste Daroussin int button = dialog_state.visit_items ? -1 : dlg_default_button(); 1964c8945a0SNathan Whitehorn int choice = dlg_default_listitem(items); 1974c8945a0SNathan Whitehorn int scrollamt = 0; 1984c8945a0SNathan Whitehorn int max_choice; 1994c8945a0SNathan Whitehorn int was_mouse; 2002a3e3873SBaptiste Daroussin int use_width, list_width, name_width, text_width; 2014c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 2024c8945a0SNathan Whitehorn int num_states; 2032a3e3873SBaptiste Daroussin WINDOW *dialog; 2044c8945a0SNathan Whitehorn char *prompt = dlg_strclone(cprompt); 2054c8945a0SNathan Whitehorn const char **buttons = dlg_ok_labels(); 2062a3e3873SBaptiste Daroussin const char *widget_name; 2072a3e3873SBaptiste Daroussin 2082a3e3873SBaptiste Daroussin memset(&all, 0, sizeof(all)); 2092a3e3873SBaptiste Daroussin all.items = items; 2102a3e3873SBaptiste Daroussin all.item_no = item_no; 2114c8945a0SNathan Whitehorn 2124c8945a0SNathan Whitehorn dlg_does_output(); 2134c8945a0SNathan Whitehorn dlg_tab_correct_str(prompt); 2144c8945a0SNathan Whitehorn 215682c9e0fSNathan Whitehorn /* 216682c9e0fSNathan Whitehorn * If this is a radiobutton list, ensure that no more than one item is 217682c9e0fSNathan Whitehorn * selected initially. Allow none to be selected, since some users may 218682c9e0fSNathan Whitehorn * wish to provide this flavor. 219682c9e0fSNathan Whitehorn */ 220682c9e0fSNathan Whitehorn if (flag == FLAG_RADIO) { 221682c9e0fSNathan Whitehorn bool first = TRUE; 222682c9e0fSNathan Whitehorn 223682c9e0fSNathan Whitehorn for (i = 0; i < item_no; i++) { 224682c9e0fSNathan Whitehorn if (items[i].state) { 225682c9e0fSNathan Whitehorn if (first) { 226682c9e0fSNathan Whitehorn first = FALSE; 227682c9e0fSNathan Whitehorn } else { 228682c9e0fSNathan Whitehorn items[i].state = 0; 229682c9e0fSNathan Whitehorn } 230682c9e0fSNathan Whitehorn } 231682c9e0fSNathan Whitehorn } 2322a3e3873SBaptiste Daroussin widget_name = "radiolist"; 2332a3e3873SBaptiste Daroussin } else { 2342a3e3873SBaptiste Daroussin widget_name = "checklist"; 235682c9e0fSNathan Whitehorn } 2364c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 2374c8945a0SNathan Whitehorn retry: 2384c8945a0SNathan Whitehorn #endif 2394c8945a0SNathan Whitehorn 2402a3e3873SBaptiste Daroussin all.use_height = list_height; 24119718649SNathan Whitehorn use_width = dlg_calc_list_width(item_no, items) + 10; 2422a3e3873SBaptiste Daroussin use_width = MAX(26, use_width); 2432a3e3873SBaptiste Daroussin if (all.use_height == 0) { 2444c8945a0SNathan Whitehorn /* calculate height without items (4) */ 2452a3e3873SBaptiste Daroussin dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, use_width); 2462a3e3873SBaptiste Daroussin dlg_calc_listh(&height, &all.use_height, item_no); 2474c8945a0SNathan Whitehorn } else { 2482a3e3873SBaptiste Daroussin dlg_auto_size(title, prompt, 2492a3e3873SBaptiste Daroussin &height, &width, 2502a3e3873SBaptiste Daroussin MIN_HIGH + all.use_height, use_width); 2514c8945a0SNathan Whitehorn } 2524c8945a0SNathan Whitehorn dlg_button_layout(buttons, &width); 2534c8945a0SNathan Whitehorn dlg_print_size(height, width); 2544c8945a0SNathan Whitehorn dlg_ctl_size(height, width); 2554c8945a0SNathan Whitehorn 2564c8945a0SNathan Whitehorn /* we need at least two states */ 2574c8945a0SNathan Whitehorn if (states == 0 || strlen(states) < 2) 2584c8945a0SNathan Whitehorn states = " *"; 2594c8945a0SNathan Whitehorn num_states = (int) strlen(states); 2602a3e3873SBaptiste Daroussin all.states = states; 2614c8945a0SNathan Whitehorn 2622a3e3873SBaptiste Daroussin all.checkflag = flag; 2634c8945a0SNathan Whitehorn 2644c8945a0SNathan Whitehorn x = dlg_box_x_ordinate(width); 2654c8945a0SNathan Whitehorn y = dlg_box_y_ordinate(height); 2664c8945a0SNathan Whitehorn 2674c8945a0SNathan Whitehorn dialog = dlg_new_window(height, width, y, x); 2682a3e3873SBaptiste Daroussin all.dialog = dialog; 2692a3e3873SBaptiste Daroussin dlg_register_window(dialog, widget_name, binding); 2702a3e3873SBaptiste Daroussin dlg_register_buttons(dialog, widget_name, buttons); 2714c8945a0SNathan Whitehorn 2724c8945a0SNathan Whitehorn dlg_mouse_setbase(x, y); 2734c8945a0SNathan Whitehorn 2742a3e3873SBaptiste Daroussin dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 2752a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 2764c8945a0SNathan Whitehorn dlg_draw_title(dialog, title); 2774c8945a0SNathan Whitehorn 2782a3e3873SBaptiste Daroussin (void) wattrset(dialog, dialog_attr); 2794c8945a0SNathan Whitehorn dlg_print_autowrap(dialog, prompt, height, width); 2804c8945a0SNathan Whitehorn 2812a3e3873SBaptiste Daroussin all.use_width = width - 6; 2824c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); 2832a3e3873SBaptiste Daroussin all.box_y = cur_y + 1; 2842a3e3873SBaptiste Daroussin all.box_x = (width - all.use_width) / 2 - 1; 2854c8945a0SNathan Whitehorn 2864c8945a0SNathan Whitehorn /* 2874c8945a0SNathan Whitehorn * After displaying the prompt, we know how much space we really have. 2884c8945a0SNathan Whitehorn * Limit the list to avoid overwriting the ok-button. 2894c8945a0SNathan Whitehorn */ 2902a3e3873SBaptiste Daroussin if (all.use_height + MIN_HIGH > height - cur_y) 2912a3e3873SBaptiste Daroussin all.use_height = height - MIN_HIGH - cur_y; 2922a3e3873SBaptiste Daroussin if (all.use_height <= 0) 2932a3e3873SBaptiste Daroussin all.use_height = 1; 2944c8945a0SNathan Whitehorn 2952a3e3873SBaptiste Daroussin max_choice = MIN(all.use_height, item_no); 2962a3e3873SBaptiste Daroussin max_choice = MAX(max_choice, 1); 2974c8945a0SNathan Whitehorn 2984c8945a0SNathan Whitehorn /* create new window for the list */ 2992a3e3873SBaptiste Daroussin all.list = dlg_sub_window(dialog, all.use_height, all.use_width, 3002a3e3873SBaptiste Daroussin y + all.box_y + 1, x + all.box_x + 1); 3014c8945a0SNathan Whitehorn 3024c8945a0SNathan Whitehorn /* draw a box around the list items */ 3032a3e3873SBaptiste Daroussin dlg_draw_box(dialog, all.box_y, all.box_x, 3042a3e3873SBaptiste Daroussin all.use_height + 2 * MARGIN, 3052a3e3873SBaptiste Daroussin all.use_width + 2 * MARGIN, 3062a3e3873SBaptiste Daroussin menubox_border_attr, menubox_border2_attr); 3074c8945a0SNathan Whitehorn 3084c8945a0SNathan Whitehorn text_width = 0; 3094c8945a0SNathan Whitehorn name_width = 0; 3104c8945a0SNathan Whitehorn /* Find length of longest item to center checklist */ 3114c8945a0SNathan Whitehorn for (i = 0; i < item_no; i++) { 3124c8945a0SNathan Whitehorn text_width = MAX(text_width, dlg_count_columns(items[i].text)); 3134c8945a0SNathan Whitehorn name_width = MAX(name_width, dlg_count_columns(items[i].name)); 3144c8945a0SNathan Whitehorn } 3154c8945a0SNathan Whitehorn 3164c8945a0SNathan Whitehorn /* If the name+text is wider than the list is allowed, then truncate 3174c8945a0SNathan Whitehorn * one or both of them. If the name is no wider than 1/4 of the list, 3184c8945a0SNathan Whitehorn * leave it intact. 3194c8945a0SNathan Whitehorn */ 3202a3e3873SBaptiste Daroussin use_width = (all.use_width - 6); 3212a3e3873SBaptiste Daroussin if (dialog_vars.no_tags) { 3222a3e3873SBaptiste Daroussin list_width = MIN(all.use_width, text_width); 3232a3e3873SBaptiste Daroussin } else if (dialog_vars.no_items) { 3242a3e3873SBaptiste Daroussin list_width = MIN(all.use_width, name_width); 3252a3e3873SBaptiste Daroussin } else { 3262a3e3873SBaptiste Daroussin if (text_width >= 0 3272a3e3873SBaptiste Daroussin && name_width >= 0 3282a3e3873SBaptiste Daroussin && use_width > 0 3292a3e3873SBaptiste Daroussin && text_width + name_width > use_width) { 3304c8945a0SNathan Whitehorn int need = (int) (0.25 * use_width); 3314c8945a0SNathan Whitehorn if (name_width > need) { 3324c8945a0SNathan Whitehorn int want = (int) (use_width * ((double) name_width) / 3334c8945a0SNathan Whitehorn (text_width + name_width)); 3344c8945a0SNathan Whitehorn name_width = (want > need) ? want : need; 3354c8945a0SNathan Whitehorn } 3364c8945a0SNathan Whitehorn text_width = use_width - name_width; 3374c8945a0SNathan Whitehorn } 3382a3e3873SBaptiste Daroussin list_width = (text_width + name_width); 3392a3e3873SBaptiste Daroussin } 3404c8945a0SNathan Whitehorn 3412a3e3873SBaptiste Daroussin all.check_x = (use_width - list_width) / 2; 3422a3e3873SBaptiste Daroussin all.item_x = ((dialog_vars.no_tags 3432a3e3873SBaptiste Daroussin ? 0 3442a3e3873SBaptiste Daroussin : (dialog_vars.no_items 3452a3e3873SBaptiste Daroussin ? 0 3462a3e3873SBaptiste Daroussin : (2 + name_width))) 3472a3e3873SBaptiste Daroussin + all.check_x + 4); 3484c8945a0SNathan Whitehorn 3494c8945a0SNathan Whitehorn /* ensure we are scrolled to show the current choice */ 3502a3e3873SBaptiste Daroussin scrollamt = MIN(scrollamt, max_choice + item_no - 1); 3512a3e3873SBaptiste Daroussin if (choice >= (max_choice + scrollamt - 1)) { 3522a3e3873SBaptiste Daroussin scrollamt = MAX(0, choice - max_choice + 1); 3534c8945a0SNathan Whitehorn choice = max_choice - 1; 3544c8945a0SNathan Whitehorn } 3552a3e3873SBaptiste Daroussin print_list(&all, choice, scrollamt, max_choice); 3564c8945a0SNathan Whitehorn 3574c8945a0SNathan Whitehorn /* register the new window, along with its borders */ 3582a3e3873SBaptiste Daroussin dlg_mouse_mkbigregion(all.box_y + 1, all.box_x, 3592a3e3873SBaptiste Daroussin all.use_height, all.use_width + 2, 3604c8945a0SNathan Whitehorn KEY_MAX, 1, 1, 1 /* by lines */ ); 3614c8945a0SNathan Whitehorn 3624c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); 3634c8945a0SNathan Whitehorn 3642a3e3873SBaptiste Daroussin dlg_trace_win(dialog); 3654c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 3664c8945a0SNathan Whitehorn if (button < 0) /* --visit-items */ 3672a3e3873SBaptiste Daroussin wmove(dialog, all.box_y + choice + 1, all.box_x + all.check_x + 2); 3684c8945a0SNathan Whitehorn 3694c8945a0SNathan Whitehorn key = dlg_mouse_wgetch(dialog, &fkey); 3704c8945a0SNathan Whitehorn if (dlg_result_key(key, fkey, &result)) 3714c8945a0SNathan Whitehorn break; 3724c8945a0SNathan Whitehorn 3734c8945a0SNathan Whitehorn was_mouse = (fkey && is_DLGK_MOUSE(key)); 3744c8945a0SNathan Whitehorn if (was_mouse) 3754c8945a0SNathan Whitehorn key -= M_EVENT; 3764c8945a0SNathan Whitehorn 3774c8945a0SNathan Whitehorn if (was_mouse && (key >= KEY_MAX)) { 3784c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); 3794c8945a0SNathan Whitehorn i = (key - KEY_MAX); 3804c8945a0SNathan Whitehorn if (i < max_choice) { 3814c8945a0SNathan Whitehorn choice = (key - KEY_MAX); 3822a3e3873SBaptiste Daroussin print_list(&all, choice, scrollamt, max_choice); 3834c8945a0SNathan Whitehorn 3844c8945a0SNathan Whitehorn key = ' '; /* force the selected item to toggle */ 3854c8945a0SNathan Whitehorn } else { 3864c8945a0SNathan Whitehorn beep(); 3874c8945a0SNathan Whitehorn continue; 3884c8945a0SNathan Whitehorn } 3894c8945a0SNathan Whitehorn fkey = FALSE; 3904c8945a0SNathan Whitehorn } else if (was_mouse && key >= KEY_MIN) { 3914c8945a0SNathan Whitehorn key = dlg_lookup_key(dialog, key, &fkey); 3924c8945a0SNathan Whitehorn } 3934c8945a0SNathan Whitehorn 3944c8945a0SNathan Whitehorn /* 3954c8945a0SNathan Whitehorn * A space toggles the item status. We handle either a checklist 3964c8945a0SNathan Whitehorn * (any number of items can be selected) or radio list (zero or one 3974c8945a0SNathan Whitehorn * items can be selected). 3984c8945a0SNathan Whitehorn */ 3994c8945a0SNathan Whitehorn if (key == ' ') { 4004c8945a0SNathan Whitehorn int current = scrollamt + choice; 4014c8945a0SNathan Whitehorn int next = items[current].state + 1; 4024c8945a0SNathan Whitehorn 4034c8945a0SNathan Whitehorn if (next >= num_states) 4044c8945a0SNathan Whitehorn next = 0; 4054c8945a0SNathan Whitehorn 4064c8945a0SNathan Whitehorn if (flag == FLAG_CHECK) { /* checklist? */ 4072a3e3873SBaptiste Daroussin getyx(dialog, cur_y, cur_x); 4084c8945a0SNathan Whitehorn items[current].state = next; 4092a3e3873SBaptiste Daroussin print_item(&all, all.list, 4104c8945a0SNathan Whitehorn &items[scrollamt + choice], 4114c8945a0SNathan Whitehorn states, 4124c8945a0SNathan Whitehorn choice, TRUE); 4132a3e3873SBaptiste Daroussin (void) wnoutrefresh(all.list); 4142a3e3873SBaptiste Daroussin (void) wmove(dialog, cur_y, cur_x); 4154c8945a0SNathan Whitehorn } else { /* radiolist */ 4164c8945a0SNathan Whitehorn for (i = 0; i < item_no; i++) { 4174c8945a0SNathan Whitehorn if (i != current) { 4184c8945a0SNathan Whitehorn items[i].state = 0; 4194c8945a0SNathan Whitehorn } 4204c8945a0SNathan Whitehorn } 4214c8945a0SNathan Whitehorn if (items[current].state) { 4222a3e3873SBaptiste Daroussin getyx(dialog, cur_y, cur_x); 4234c8945a0SNathan Whitehorn items[current].state = next ? next : 1; 4242a3e3873SBaptiste Daroussin print_item(&all, all.list, 4254c8945a0SNathan Whitehorn &items[current], 4264c8945a0SNathan Whitehorn states, 4274c8945a0SNathan Whitehorn choice, TRUE); 4282a3e3873SBaptiste Daroussin (void) wnoutrefresh(all.list); 4292a3e3873SBaptiste Daroussin (void) wmove(dialog, cur_y, cur_x); 4304c8945a0SNathan Whitehorn } else { 4314c8945a0SNathan Whitehorn items[current].state = 1; 4322a3e3873SBaptiste Daroussin print_list(&all, choice, scrollamt, max_choice); 4334c8945a0SNathan Whitehorn } 4344c8945a0SNathan Whitehorn } 4354c8945a0SNathan Whitehorn continue; /* wait for another key press */ 4364c8945a0SNathan Whitehorn } 4374c8945a0SNathan Whitehorn 4384c8945a0SNathan Whitehorn /* 4394c8945a0SNathan Whitehorn * Check if key pressed matches first character of any item tag in 4404c8945a0SNathan Whitehorn * list. If there is more than one match, we will cycle through 4414c8945a0SNathan Whitehorn * each one as the same key is pressed repeatedly. 4424c8945a0SNathan Whitehorn */ 4434c8945a0SNathan Whitehorn found = FALSE; 4444c8945a0SNathan Whitehorn if (!fkey) { 4454c8945a0SNathan Whitehorn if (button < 0 || !dialog_state.visit_items) { 4464c8945a0SNathan Whitehorn for (j = scrollamt + choice + 1; j < item_no; j++) { 4472a3e3873SBaptiste Daroussin if (check_hotkey(items, j)) { 4484c8945a0SNathan Whitehorn found = TRUE; 4494c8945a0SNathan Whitehorn i = j - scrollamt; 4504c8945a0SNathan Whitehorn break; 4514c8945a0SNathan Whitehorn } 4524c8945a0SNathan Whitehorn } 4534c8945a0SNathan Whitehorn if (!found) { 4544c8945a0SNathan Whitehorn for (j = 0; j <= scrollamt + choice; j++) { 4552a3e3873SBaptiste Daroussin if (check_hotkey(items, j)) { 4564c8945a0SNathan Whitehorn found = TRUE; 4574c8945a0SNathan Whitehorn i = j - scrollamt; 4584c8945a0SNathan Whitehorn break; 4594c8945a0SNathan Whitehorn } 4604c8945a0SNathan Whitehorn } 4614c8945a0SNathan Whitehorn } 4624c8945a0SNathan Whitehorn if (found) 4634c8945a0SNathan Whitehorn dlg_flush_getc(); 4644c8945a0SNathan Whitehorn } else if ((j = dlg_char_to_button(key, buttons)) >= 0) { 4654c8945a0SNathan Whitehorn button = j; 4664c8945a0SNathan Whitehorn ungetch('\n'); 4674c8945a0SNathan Whitehorn continue; 4684c8945a0SNathan Whitehorn } 4694c8945a0SNathan Whitehorn } 4704c8945a0SNathan Whitehorn 4714c8945a0SNathan Whitehorn /* 4724c8945a0SNathan Whitehorn * A single digit (1-9) positions the selection to that line in the 4734c8945a0SNathan Whitehorn * current screen. 4744c8945a0SNathan Whitehorn */ 4754c8945a0SNathan Whitehorn if (!found 4764c8945a0SNathan Whitehorn && (key <= '9') 4774c8945a0SNathan Whitehorn && (key > '0') 4784c8945a0SNathan Whitehorn && (key - '1' < max_choice)) { 4794c8945a0SNathan Whitehorn found = TRUE; 4804c8945a0SNathan Whitehorn i = key - '1'; 4814c8945a0SNathan Whitehorn } 4824c8945a0SNathan Whitehorn 4834c8945a0SNathan Whitehorn if (!found) { 4844c8945a0SNathan Whitehorn if (fkey) { 4854c8945a0SNathan Whitehorn found = TRUE; 4864c8945a0SNathan Whitehorn switch (key) { 4874c8945a0SNathan Whitehorn case DLGK_ITEM_FIRST: 4884c8945a0SNathan Whitehorn i = -scrollamt; 4894c8945a0SNathan Whitehorn break; 4904c8945a0SNathan Whitehorn case DLGK_ITEM_LAST: 4914c8945a0SNathan Whitehorn i = item_no - 1 - scrollamt; 4924c8945a0SNathan Whitehorn break; 4934c8945a0SNathan Whitehorn case DLGK_PAGE_PREV: 4944c8945a0SNathan Whitehorn if (choice) 4954c8945a0SNathan Whitehorn i = 0; 4964c8945a0SNathan Whitehorn else if (scrollamt != 0) 4974c8945a0SNathan Whitehorn i = -MIN(scrollamt, max_choice); 4984c8945a0SNathan Whitehorn else 4994c8945a0SNathan Whitehorn continue; 5004c8945a0SNathan Whitehorn break; 5014c8945a0SNathan Whitehorn case DLGK_PAGE_NEXT: 5024c8945a0SNathan Whitehorn i = MIN(choice + max_choice, item_no - scrollamt - 1); 5034c8945a0SNathan Whitehorn break; 5044c8945a0SNathan Whitehorn case DLGK_ITEM_PREV: 5054c8945a0SNathan Whitehorn i = choice - 1; 5064c8945a0SNathan Whitehorn if (choice == 0 && scrollamt == 0) 5074c8945a0SNathan Whitehorn continue; 5084c8945a0SNathan Whitehorn break; 5094c8945a0SNathan Whitehorn case DLGK_ITEM_NEXT: 5104c8945a0SNathan Whitehorn i = choice + 1; 5114c8945a0SNathan Whitehorn if (scrollamt + choice >= item_no - 1) 5124c8945a0SNathan Whitehorn continue; 5134c8945a0SNathan Whitehorn break; 5144c8945a0SNathan Whitehorn default: 5154c8945a0SNathan Whitehorn found = FALSE; 5164c8945a0SNathan Whitehorn break; 5174c8945a0SNathan Whitehorn } 5184c8945a0SNathan Whitehorn } 5194c8945a0SNathan Whitehorn } 5204c8945a0SNathan Whitehorn 5214c8945a0SNathan Whitehorn if (found) { 5224c8945a0SNathan Whitehorn if (i != choice) { 5234c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); 5244c8945a0SNathan Whitehorn if (i < 0 || i >= max_choice) { 5254c8945a0SNathan Whitehorn if (i < 0) { 5264c8945a0SNathan Whitehorn scrollamt += i; 5274c8945a0SNathan Whitehorn choice = 0; 5284c8945a0SNathan Whitehorn } else { 5294c8945a0SNathan Whitehorn choice = max_choice - 1; 5304c8945a0SNathan Whitehorn scrollamt += (i - max_choice + 1); 5314c8945a0SNathan Whitehorn } 5322a3e3873SBaptiste Daroussin print_list(&all, choice, scrollamt, max_choice); 5334c8945a0SNathan Whitehorn } else { 5344c8945a0SNathan Whitehorn choice = i; 5352a3e3873SBaptiste Daroussin print_list(&all, choice, scrollamt, max_choice); 5364c8945a0SNathan Whitehorn } 5374c8945a0SNathan Whitehorn } 5384c8945a0SNathan Whitehorn continue; /* wait for another key press */ 5394c8945a0SNathan Whitehorn } 5404c8945a0SNathan Whitehorn 5414c8945a0SNathan Whitehorn if (fkey) { 5424c8945a0SNathan Whitehorn switch (key) { 5434c8945a0SNathan Whitehorn case DLGK_ENTER: 544682c9e0fSNathan Whitehorn result = dlg_enter_buttoncode(button); 5454c8945a0SNathan Whitehorn break; 5464c8945a0SNathan Whitehorn case DLGK_FIELD_PREV: 5474c8945a0SNathan Whitehorn button = dlg_prev_button(buttons, button); 5484c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, button, 5494c8945a0SNathan Whitehorn FALSE, width); 5504c8945a0SNathan Whitehorn break; 5514c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT: 5524c8945a0SNathan Whitehorn button = dlg_next_button(buttons, button); 5534c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, button, 5544c8945a0SNathan Whitehorn FALSE, width); 5554c8945a0SNathan Whitehorn break; 5564c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5574c8945a0SNathan Whitehorn case KEY_RESIZE: 5584c8945a0SNathan Whitehorn /* reset data */ 5594c8945a0SNathan Whitehorn height = old_height; 5604c8945a0SNathan Whitehorn width = old_width; 5614c8945a0SNathan Whitehorn /* repaint */ 5624c8945a0SNathan Whitehorn dlg_clear(); 5634c8945a0SNathan Whitehorn dlg_del_window(dialog); 5644c8945a0SNathan Whitehorn refresh(); 5654c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 5664c8945a0SNathan Whitehorn goto retry; 5674c8945a0SNathan Whitehorn #endif 5684c8945a0SNathan Whitehorn default: 5694c8945a0SNathan Whitehorn if (was_mouse) { 5704c8945a0SNathan Whitehorn if ((key2 = dlg_ok_buttoncode(key)) >= 0) { 5714c8945a0SNathan Whitehorn result = key2; 5724c8945a0SNathan Whitehorn break; 5734c8945a0SNathan Whitehorn } 5744c8945a0SNathan Whitehorn beep(); 5754c8945a0SNathan Whitehorn } 5764c8945a0SNathan Whitehorn } 5774c8945a0SNathan Whitehorn } else { 5784c8945a0SNathan Whitehorn beep(); 5794c8945a0SNathan Whitehorn } 5804c8945a0SNathan Whitehorn } 5814c8945a0SNathan Whitehorn 5824c8945a0SNathan Whitehorn dlg_del_window(dialog); 5834c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 5844c8945a0SNathan Whitehorn free(prompt); 5854c8945a0SNathan Whitehorn *current_item = (scrollamt + choice); 5864c8945a0SNathan Whitehorn return result; 5874c8945a0SNathan Whitehorn } 5884c8945a0SNathan Whitehorn 5894c8945a0SNathan Whitehorn /* 5904c8945a0SNathan Whitehorn * Display a dialog box with a list of options that can be turned on or off 5914c8945a0SNathan Whitehorn * The `flag' parameter is used to select between radiolist and checklist. 5924c8945a0SNathan Whitehorn */ 5934c8945a0SNathan Whitehorn int 5944c8945a0SNathan Whitehorn dialog_checklist(const char *title, 5954c8945a0SNathan Whitehorn const char *cprompt, 5964c8945a0SNathan Whitehorn int height, 5974c8945a0SNathan Whitehorn int width, 5984c8945a0SNathan Whitehorn int list_height, 5994c8945a0SNathan Whitehorn int item_no, 6004c8945a0SNathan Whitehorn char **items, 6014c8945a0SNathan Whitehorn int flag) 6024c8945a0SNathan Whitehorn { 6034c8945a0SNathan Whitehorn int result; 6042a3e3873SBaptiste Daroussin int i, j; 6054c8945a0SNathan Whitehorn DIALOG_LISTITEM *listitems; 6064c8945a0SNathan Whitehorn bool separate_output = ((flag == FLAG_CHECK) 6074c8945a0SNathan Whitehorn && (dialog_vars.separate_output)); 6084c8945a0SNathan Whitehorn bool show_status = FALSE; 6094c8945a0SNathan Whitehorn int current = 0; 610*febdb468SDevin Teske char *help_result; 6114c8945a0SNathan Whitehorn 6124c8945a0SNathan Whitehorn listitems = dlg_calloc(DIALOG_LISTITEM, (size_t) item_no + 1); 6134c8945a0SNathan Whitehorn assert_ptr(listitems, "dialog_checklist"); 6144c8945a0SNathan Whitehorn 6152a3e3873SBaptiste Daroussin for (i = j = 0; i < item_no; ++i) { 6162a3e3873SBaptiste Daroussin listitems[i].name = items[j++]; 6172a3e3873SBaptiste Daroussin listitems[i].text = (dialog_vars.no_items 6182a3e3873SBaptiste Daroussin ? dlg_strempty() 6192a3e3873SBaptiste Daroussin : items[j++]); 6202a3e3873SBaptiste Daroussin listitems[i].state = !dlg_strcmp(items[j++], "on"); 6214c8945a0SNathan Whitehorn listitems[i].help = ((dialog_vars.item_help) 6222a3e3873SBaptiste Daroussin ? items[j++] 6234c8945a0SNathan Whitehorn : dlg_strempty()); 6244c8945a0SNathan Whitehorn } 6257a1c0d96SNathan Whitehorn dlg_align_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no); 6264c8945a0SNathan Whitehorn 6274c8945a0SNathan Whitehorn result = dlg_checklist(title, 6284c8945a0SNathan Whitehorn cprompt, 6294c8945a0SNathan Whitehorn height, 6304c8945a0SNathan Whitehorn width, 6314c8945a0SNathan Whitehorn list_height, 6324c8945a0SNathan Whitehorn item_no, 6334c8945a0SNathan Whitehorn listitems, 6344c8945a0SNathan Whitehorn NULL, 6354c8945a0SNathan Whitehorn flag, 6364c8945a0SNathan Whitehorn ¤t); 6374c8945a0SNathan Whitehorn 6384c8945a0SNathan Whitehorn switch (result) { 6394c8945a0SNathan Whitehorn case DLG_EXIT_OK: /* FALLTHRU */ 6404c8945a0SNathan Whitehorn case DLG_EXIT_EXTRA: 6414c8945a0SNathan Whitehorn show_status = TRUE; 6424c8945a0SNathan Whitehorn break; 6434c8945a0SNathan Whitehorn case DLG_EXIT_HELP: 644*febdb468SDevin Teske dlg_add_help_listitem(&result, &help_result, &listitems[current]); 645*febdb468SDevin Teske if ((show_status = dialog_vars.help_status)) { 6464c8945a0SNathan Whitehorn if (separate_output) { 647*febdb468SDevin Teske dlg_add_string(help_result); 6484c8945a0SNathan Whitehorn dlg_add_separator(); 6494c8945a0SNathan Whitehorn } else { 650*febdb468SDevin Teske dlg_add_quoted(help_result); 6514c8945a0SNathan Whitehorn } 6524c8945a0SNathan Whitehorn } else { 653*febdb468SDevin Teske dlg_add_string(help_result); 6544c8945a0SNathan Whitehorn } 6554c8945a0SNathan Whitehorn break; 6564c8945a0SNathan Whitehorn } 6574c8945a0SNathan Whitehorn 6584c8945a0SNathan Whitehorn if (show_status) { 6594c8945a0SNathan Whitehorn for (i = 0; i < item_no; i++) { 6604c8945a0SNathan Whitehorn if (listitems[i].state) { 6614c8945a0SNathan Whitehorn if (separate_output) { 6624c8945a0SNathan Whitehorn dlg_add_string(listitems[i].name); 6634c8945a0SNathan Whitehorn dlg_add_separator(); 6644c8945a0SNathan Whitehorn } else { 6654c8945a0SNathan Whitehorn if (dlg_need_separator()) 6664c8945a0SNathan Whitehorn dlg_add_separator(); 6672a3e3873SBaptiste Daroussin if (flag == FLAG_CHECK) 6682a3e3873SBaptiste Daroussin dlg_add_quoted(listitems[i].name); 6692a3e3873SBaptiste Daroussin else 6704c8945a0SNathan Whitehorn dlg_add_string(listitems[i].name); 6714c8945a0SNathan Whitehorn } 6724c8945a0SNathan Whitehorn } 6734c8945a0SNathan Whitehorn } 6742a3e3873SBaptiste Daroussin dlg_add_last_key(separate_output); 6754c8945a0SNathan Whitehorn } 6764c8945a0SNathan Whitehorn 6777a1c0d96SNathan Whitehorn dlg_free_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no); 6784c8945a0SNathan Whitehorn free(listitems); 6794c8945a0SNathan Whitehorn return result; 6804c8945a0SNathan Whitehorn } 681