xref: /freebsd/contrib/dialog/treeview.c (revision a96ef4501919d7ac08e94e98dc34b0bdd744802b)
12a3e3873SBaptiste Daroussin /*
2*a96ef450SBaptiste Daroussin  *  $Id: treeview.c,v 1.43 2020/11/23 00:38:31 tom Exp $
32a3e3873SBaptiste Daroussin  *
42a3e3873SBaptiste Daroussin  *  treeview.c -- implements the treeview dialog
52a3e3873SBaptiste Daroussin  *
6*a96ef450SBaptiste Daroussin  *  Copyright 2012-2019,2020	Thomas E. Dickey
72a3e3873SBaptiste Daroussin  *
82a3e3873SBaptiste Daroussin  *  This program is free software; you can redistribute it and/or modify
92a3e3873SBaptiste Daroussin  *  it under the terms of the GNU Lesser General Public License, version 2.1
102a3e3873SBaptiste Daroussin  *  as published by the Free Software Foundation.
112a3e3873SBaptiste Daroussin  *
122a3e3873SBaptiste Daroussin  *  This program is distributed in the hope that it will be useful, but
132a3e3873SBaptiste Daroussin  *  WITHOUT ANY WARRANTY; without even the implied warranty of
142a3e3873SBaptiste Daroussin  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
152a3e3873SBaptiste Daroussin  *  Lesser General Public License for more details.
162a3e3873SBaptiste Daroussin  *
172a3e3873SBaptiste Daroussin  *  You should have received a copy of the GNU Lesser General Public
182a3e3873SBaptiste Daroussin  *  License along with this program; if not, write to
192a3e3873SBaptiste Daroussin  *	Free Software Foundation, Inc.
202a3e3873SBaptiste Daroussin  *	51 Franklin St., Fifth Floor
212a3e3873SBaptiste Daroussin  *	Boston, MA 02110, USA.
222a3e3873SBaptiste Daroussin  */
232a3e3873SBaptiste Daroussin 
24*a96ef450SBaptiste Daroussin #include <dlg_internals.h>
252a3e3873SBaptiste Daroussin #include <dlg_keys.h>
262a3e3873SBaptiste Daroussin 
272a3e3873SBaptiste Daroussin #define INDENT 3
282a3e3873SBaptiste Daroussin #define MIN_HIGH  (1 + (5 * MARGIN))
292a3e3873SBaptiste Daroussin 
302a3e3873SBaptiste Daroussin typedef struct {
312a3e3873SBaptiste Daroussin     /* the outer-window */
322a3e3873SBaptiste Daroussin     WINDOW *dialog;
332a3e3873SBaptiste Daroussin     bool is_check;
342a3e3873SBaptiste Daroussin     int box_y;
352a3e3873SBaptiste Daroussin     int box_x;
362a3e3873SBaptiste Daroussin     int check_x;
372a3e3873SBaptiste Daroussin     int item_x;
382a3e3873SBaptiste Daroussin     int use_height;
392a3e3873SBaptiste Daroussin     int use_width;
402a3e3873SBaptiste Daroussin     /* the inner-window */
412a3e3873SBaptiste Daroussin     WINDOW *list;
422a3e3873SBaptiste Daroussin     DIALOG_LISTITEM *items;
432a3e3873SBaptiste Daroussin     int item_no;
442a3e3873SBaptiste Daroussin     int *depths;
452a3e3873SBaptiste Daroussin     const char *states;
462a3e3873SBaptiste Daroussin } ALL_DATA;
472a3e3873SBaptiste Daroussin 
482a3e3873SBaptiste Daroussin /*
492a3e3873SBaptiste Daroussin  * Print list item.  The 'selected' parameter is true if 'choice' is the
502a3e3873SBaptiste Daroussin  * current item.  That one is colored differently from the other items.
512a3e3873SBaptiste Daroussin  */
522a3e3873SBaptiste Daroussin static void
print_item(ALL_DATA * data,DIALOG_LISTITEM * item,const char * states,int depths,int choice,int selected)532a3e3873SBaptiste Daroussin print_item(ALL_DATA * data,
542a3e3873SBaptiste Daroussin 	   DIALOG_LISTITEM * item,
552a3e3873SBaptiste Daroussin 	   const char *states,
562a3e3873SBaptiste Daroussin 	   int depths,
572a3e3873SBaptiste Daroussin 	   int choice,
582a3e3873SBaptiste Daroussin 	   int selected)
592a3e3873SBaptiste Daroussin {
602a3e3873SBaptiste Daroussin     WINDOW *win = data->list;
612a3e3873SBaptiste Daroussin     chtype save = dlg_get_attrs(win);
622a3e3873SBaptiste Daroussin     int i;
632a3e3873SBaptiste Daroussin     bool first = TRUE;
642a3e3873SBaptiste Daroussin     int climit = (getmaxx(win) - data->check_x + 1);
652a3e3873SBaptiste Daroussin     const char *show = (dialog_vars.no_items
662a3e3873SBaptiste Daroussin 			? item->name
672a3e3873SBaptiste Daroussin 			: item->text);
682a3e3873SBaptiste Daroussin 
692a3e3873SBaptiste Daroussin     /* Clear 'residue' of last item */
70f4f33ea0SBaptiste Daroussin     dlg_attrset(win, menubox_attr);
712a3e3873SBaptiste Daroussin     (void) wmove(win, choice, 0);
722a3e3873SBaptiste Daroussin     for (i = 0; i < data->use_width; i++)
732a3e3873SBaptiste Daroussin 	(void) waddch(win, ' ');
742a3e3873SBaptiste Daroussin 
752a3e3873SBaptiste Daroussin     (void) wmove(win, choice, data->check_x);
76f4f33ea0SBaptiste Daroussin     dlg_attrset(win, selected ? check_selected_attr : check_attr);
772a3e3873SBaptiste Daroussin     (void) wprintw(win,
782a3e3873SBaptiste Daroussin 		   data->is_check ? "[%c]" : "(%c)",
792a3e3873SBaptiste Daroussin 		   states[item->state]);
80f4f33ea0SBaptiste Daroussin     dlg_attrset(win, menubox_attr);
812a3e3873SBaptiste Daroussin 
82f4f33ea0SBaptiste Daroussin     dlg_attrset(win, selected ? item_selected_attr : item_attr);
832a3e3873SBaptiste Daroussin     for (i = 0; i < depths; ++i) {
842a3e3873SBaptiste Daroussin 	int j;
852a3e3873SBaptiste Daroussin 	(void) wmove(win, choice, data->item_x + INDENT * i);
862a3e3873SBaptiste Daroussin 	(void) waddch(win, ACS_VLINE);
872a3e3873SBaptiste Daroussin 	for (j = INDENT - 1; j > 0; --j)
882a3e3873SBaptiste Daroussin 	    (void) waddch(win, ' ');
892a3e3873SBaptiste Daroussin     }
902a3e3873SBaptiste Daroussin     (void) wmove(win, choice, data->item_x + INDENT * depths);
912a3e3873SBaptiste Daroussin 
922a3e3873SBaptiste Daroussin     dlg_print_listitem(win, show, climit, first, selected);
932a3e3873SBaptiste Daroussin 
942a3e3873SBaptiste Daroussin     if (selected) {
952a3e3873SBaptiste Daroussin 	dlg_item_help(item->help);
962a3e3873SBaptiste Daroussin     }
97f4f33ea0SBaptiste Daroussin     dlg_attrset(win, save);
982a3e3873SBaptiste Daroussin }
992a3e3873SBaptiste Daroussin 
1002a3e3873SBaptiste Daroussin static void
print_list(ALL_DATA * data,int choice,int scrollamt,int max_choice)1012a3e3873SBaptiste Daroussin print_list(ALL_DATA * data,
1022a3e3873SBaptiste Daroussin 	   int choice,
1032a3e3873SBaptiste Daroussin 	   int scrollamt,
1042a3e3873SBaptiste Daroussin 	   int max_choice)
1052a3e3873SBaptiste Daroussin {
1062a3e3873SBaptiste Daroussin     int i;
1072a3e3873SBaptiste Daroussin     int cur_y, cur_x;
1082a3e3873SBaptiste Daroussin 
1092a3e3873SBaptiste Daroussin     getyx(data->dialog, cur_y, cur_x);
1102a3e3873SBaptiste Daroussin 
1112a3e3873SBaptiste Daroussin     for (i = 0; i < max_choice; i++) {
1122a3e3873SBaptiste Daroussin 	print_item(data,
1132a3e3873SBaptiste Daroussin 		   &data->items[scrollamt + i],
1142a3e3873SBaptiste Daroussin 		   data->states,
1152a3e3873SBaptiste Daroussin 		   data->depths[scrollamt + i],
1162a3e3873SBaptiste Daroussin 		   i, i == choice);
1172a3e3873SBaptiste Daroussin     }
1182a3e3873SBaptiste Daroussin     (void) wnoutrefresh(data->list);
1192a3e3873SBaptiste Daroussin 
1202a3e3873SBaptiste Daroussin     dlg_draw_scrollbar(data->dialog,
1212a3e3873SBaptiste Daroussin 		       (long) (scrollamt),
1222a3e3873SBaptiste Daroussin 		       (long) (scrollamt),
1232a3e3873SBaptiste Daroussin 		       (long) (scrollamt + max_choice),
1242a3e3873SBaptiste Daroussin 		       (long) (data->item_no),
1252a3e3873SBaptiste Daroussin 		       data->box_x + data->check_x,
1262a3e3873SBaptiste Daroussin 		       data->box_x + data->use_width,
1272a3e3873SBaptiste Daroussin 		       data->box_y,
1282a3e3873SBaptiste Daroussin 		       data->box_y + data->use_height + 1,
1292a3e3873SBaptiste Daroussin 		       menubox_border2_attr,
1302a3e3873SBaptiste Daroussin 		       menubox_border_attr);
1312a3e3873SBaptiste Daroussin 
1322a3e3873SBaptiste Daroussin     (void) wmove(data->dialog, cur_y, cur_x);
1332a3e3873SBaptiste Daroussin }
1342a3e3873SBaptiste Daroussin 
1352a3e3873SBaptiste Daroussin static bool
check_hotkey(DIALOG_LISTITEM * items,int choice)1362a3e3873SBaptiste Daroussin check_hotkey(DIALOG_LISTITEM * items, int choice)
1372a3e3873SBaptiste Daroussin {
1382a3e3873SBaptiste Daroussin     bool result = FALSE;
1392a3e3873SBaptiste Daroussin 
1402a3e3873SBaptiste Daroussin     if (dlg_match_char(dlg_last_getc(),
1412a3e3873SBaptiste Daroussin 		       (dialog_vars.no_tags
1422a3e3873SBaptiste Daroussin 			? items[choice].text
1432a3e3873SBaptiste Daroussin 			: items[choice].name))) {
1442a3e3873SBaptiste Daroussin 	result = TRUE;
1452a3e3873SBaptiste Daroussin     }
1462a3e3873SBaptiste Daroussin     return result;
1472a3e3873SBaptiste Daroussin }
1482a3e3873SBaptiste Daroussin 
1492a3e3873SBaptiste Daroussin /*
1502a3e3873SBaptiste Daroussin  * This is an alternate interface to 'treeview' which allows the application
1512a3e3873SBaptiste Daroussin  * to read the list item states back directly without putting them in the
1522a3e3873SBaptiste Daroussin  * output buffer.
1532a3e3873SBaptiste Daroussin  */
1542a3e3873SBaptiste Daroussin int
dlg_treeview(const char * title,const char * cprompt,int height,int width,int list_height,int item_no,DIALOG_LISTITEM * items,const char * states,int * depths,int flag,int * current_item)1552a3e3873SBaptiste Daroussin dlg_treeview(const char *title,
1562a3e3873SBaptiste Daroussin 	     const char *cprompt,
1572a3e3873SBaptiste Daroussin 	     int height,
1582a3e3873SBaptiste Daroussin 	     int width,
1592a3e3873SBaptiste Daroussin 	     int list_height,
1602a3e3873SBaptiste Daroussin 	     int item_no,
1612a3e3873SBaptiste Daroussin 	     DIALOG_LISTITEM * items,
1622a3e3873SBaptiste Daroussin 	     const char *states,
1632a3e3873SBaptiste Daroussin 	     int *depths,
1642a3e3873SBaptiste Daroussin 	     int flag,
1652a3e3873SBaptiste Daroussin 	     int *current_item)
1662a3e3873SBaptiste Daroussin {
1672a3e3873SBaptiste Daroussin     /* *INDENT-OFF* */
1682a3e3873SBaptiste Daroussin     static DLG_KEYS_BINDING binding[] = {
1692a3e3873SBaptiste Daroussin 	HELPKEY_BINDINGS,
1702a3e3873SBaptiste Daroussin 	ENTERKEY_BINDINGS,
1712a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
1722a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
1732a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
1742a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
1752a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_FIRST, KEY_HOME ),
1762a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_LAST,	KEY_END ),
1772a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_LAST,	KEY_LL ),
1782a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	'+' ),
1792a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	KEY_DOWN ),
1802a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  CHR_NEXT ),
1812a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_PREV,	'-' ),
1822a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_PREV,	KEY_UP ),
1832a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_ITEM_PREV,  CHR_PREVIOUS ),
1842a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_PAGE_NEXT,	KEY_NPAGE ),
1852a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_PAGE_NEXT,	DLGK_MOUSE(KEY_NPAGE) ),
1862a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_PAGE_PREV,	KEY_PPAGE ),
1872a3e3873SBaptiste Daroussin 	DLG_KEYS_DATA( DLGK_PAGE_PREV,	DLGK_MOUSE(KEY_PPAGE) ),
188f4f33ea0SBaptiste Daroussin 	TOGGLEKEY_BINDINGS,
1892a3e3873SBaptiste Daroussin 	END_KEYS_BINDING
1902a3e3873SBaptiste Daroussin     };
1912a3e3873SBaptiste Daroussin     /* *INDENT-ON* */
1922a3e3873SBaptiste Daroussin 
1932a3e3873SBaptiste Daroussin #ifdef KEY_RESIZE
1942a3e3873SBaptiste Daroussin     int old_height = height;
1952a3e3873SBaptiste Daroussin     int old_width = width;
1962a3e3873SBaptiste Daroussin #endif
1972a3e3873SBaptiste Daroussin     ALL_DATA all;
1982a3e3873SBaptiste Daroussin     int i, j, key2, found, x, y, cur_y, box_x, box_y;
199*a96ef450SBaptiste Daroussin     int key, fkey;
2002a3e3873SBaptiste Daroussin     int button = dialog_state.visit_items ? -1 : dlg_default_button();
2012a3e3873SBaptiste Daroussin     int choice = dlg_default_listitem(items);
2022a3e3873SBaptiste Daroussin     int scrollamt = 0;
2032a3e3873SBaptiste Daroussin     int max_choice;
2042a3e3873SBaptiste Daroussin     int use_height;
2052a3e3873SBaptiste Daroussin     int use_width, name_width, text_width, tree_width;
2062a3e3873SBaptiste Daroussin     int result = DLG_EXIT_UNKNOWN;
2072a3e3873SBaptiste Daroussin     int num_states;
2082a3e3873SBaptiste Daroussin     WINDOW *dialog, *list;
2092a3e3873SBaptiste Daroussin     char *prompt = dlg_strclone(cprompt);
2102a3e3873SBaptiste Daroussin     const char **buttons = dlg_ok_labels();
2112a3e3873SBaptiste Daroussin     const char *widget_name;
2122a3e3873SBaptiste Daroussin 
2132a3e3873SBaptiste Daroussin     /* we need at least two states */
2142a3e3873SBaptiste Daroussin     if (states == 0 || strlen(states) < 2)
2152a3e3873SBaptiste Daroussin 	states = " *";
2162a3e3873SBaptiste Daroussin     num_states = (int) strlen(states);
2172a3e3873SBaptiste Daroussin 
218f4f33ea0SBaptiste Daroussin     dialog_state.plain_buttons = TRUE;
219f4f33ea0SBaptiste Daroussin 
2202a3e3873SBaptiste Daroussin     memset(&all, 0, sizeof(all));
2212a3e3873SBaptiste Daroussin     all.items = items;
2222a3e3873SBaptiste Daroussin     all.item_no = item_no;
2232a3e3873SBaptiste Daroussin     all.states = states;
2242a3e3873SBaptiste Daroussin     all.depths = depths;
2252a3e3873SBaptiste Daroussin 
2262a3e3873SBaptiste Daroussin     dlg_does_output();
2272a3e3873SBaptiste Daroussin     dlg_tab_correct_str(prompt);
2282a3e3873SBaptiste Daroussin 
2292a3e3873SBaptiste Daroussin     /*
2302a3e3873SBaptiste Daroussin      * If this is a radiobutton list, ensure that no more than one item is
2312a3e3873SBaptiste Daroussin      * selected initially.  Allow none to be selected, since some users may
2322a3e3873SBaptiste Daroussin      * wish to provide this flavor.
2332a3e3873SBaptiste Daroussin      */
2342a3e3873SBaptiste Daroussin     if (flag == FLAG_RADIO) {
2352a3e3873SBaptiste Daroussin 	bool first = TRUE;
2362a3e3873SBaptiste Daroussin 
2372a3e3873SBaptiste Daroussin 	for (i = 0; i < item_no; i++) {
2382a3e3873SBaptiste Daroussin 	    if (items[i].state) {
2392a3e3873SBaptiste Daroussin 		if (first) {
2402a3e3873SBaptiste Daroussin 		    first = FALSE;
2412a3e3873SBaptiste Daroussin 		} else {
2422a3e3873SBaptiste Daroussin 		    items[i].state = 0;
2432a3e3873SBaptiste Daroussin 		}
2442a3e3873SBaptiste Daroussin 	    }
2452a3e3873SBaptiste Daroussin 	}
2462a3e3873SBaptiste Daroussin     } else {
2472a3e3873SBaptiste Daroussin 	all.is_check = TRUE;
2482a3e3873SBaptiste Daroussin     }
2492a3e3873SBaptiste Daroussin     widget_name = "treeview";
2502a3e3873SBaptiste Daroussin #ifdef KEY_RESIZE
2512a3e3873SBaptiste Daroussin   retry:
2522a3e3873SBaptiste Daroussin #endif
2532a3e3873SBaptiste Daroussin 
2542a3e3873SBaptiste Daroussin     use_height = list_height;
2552a3e3873SBaptiste Daroussin     use_width = dlg_calc_list_width(item_no, items) + 10;
2562a3e3873SBaptiste Daroussin     use_width = MAX(26, use_width);
2572a3e3873SBaptiste Daroussin     if (use_height == 0) {
2582a3e3873SBaptiste Daroussin 	/* calculate height without items (4) */
2592a3e3873SBaptiste Daroussin 	dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, use_width);
2602a3e3873SBaptiste Daroussin 	dlg_calc_listh(&height, &use_height, item_no);
2612a3e3873SBaptiste Daroussin     } else {
2622a3e3873SBaptiste Daroussin 	dlg_auto_size(title, prompt, &height, &width, MIN_HIGH + use_height, use_width);
2632a3e3873SBaptiste Daroussin     }
2642a3e3873SBaptiste Daroussin     dlg_button_layout(buttons, &width);
2652a3e3873SBaptiste Daroussin     dlg_print_size(height, width);
2662a3e3873SBaptiste Daroussin     dlg_ctl_size(height, width);
2672a3e3873SBaptiste Daroussin 
2682a3e3873SBaptiste Daroussin     x = dlg_box_x_ordinate(width);
2692a3e3873SBaptiste Daroussin     y = dlg_box_y_ordinate(height);
2702a3e3873SBaptiste Daroussin 
2712a3e3873SBaptiste Daroussin     dialog = dlg_new_window(height, width, y, x);
2722a3e3873SBaptiste Daroussin     dlg_register_window(dialog, widget_name, binding);
2732a3e3873SBaptiste Daroussin     dlg_register_buttons(dialog, widget_name, buttons);
2742a3e3873SBaptiste Daroussin 
2752a3e3873SBaptiste Daroussin     dlg_mouse_setbase(x, y);
2762a3e3873SBaptiste Daroussin 
2772a3e3873SBaptiste Daroussin     dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
2782a3e3873SBaptiste Daroussin     dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
2792a3e3873SBaptiste Daroussin     dlg_draw_title(dialog, title);
2802a3e3873SBaptiste Daroussin 
281f4f33ea0SBaptiste Daroussin     dlg_attrset(dialog, dialog_attr);
2822a3e3873SBaptiste Daroussin     dlg_print_autowrap(dialog, prompt, height, width);
2832a3e3873SBaptiste Daroussin 
2842a3e3873SBaptiste Daroussin     all.use_width = width - 4;
2852a3e3873SBaptiste Daroussin     cur_y = getcury(dialog);
2862a3e3873SBaptiste Daroussin     box_y = cur_y + 1;
2872a3e3873SBaptiste Daroussin     box_x = (width - all.use_width) / 2 - 1;
2882a3e3873SBaptiste Daroussin 
2892a3e3873SBaptiste Daroussin     /*
2902a3e3873SBaptiste Daroussin      * After displaying the prompt, we know how much space we really have.
2912a3e3873SBaptiste Daroussin      * Limit the list to avoid overwriting the ok-button.
2922a3e3873SBaptiste Daroussin      */
2932a3e3873SBaptiste Daroussin     use_height = height - MIN_HIGH - cur_y;
2942a3e3873SBaptiste Daroussin     if (use_height <= 0)
2952a3e3873SBaptiste Daroussin 	use_height = 1;
2962a3e3873SBaptiste Daroussin 
2972a3e3873SBaptiste Daroussin     max_choice = MIN(use_height, item_no);
2982a3e3873SBaptiste Daroussin 
2992a3e3873SBaptiste Daroussin     /* create new window for the list */
3002a3e3873SBaptiste Daroussin     list = dlg_sub_window(dialog, use_height, all.use_width,
3012a3e3873SBaptiste Daroussin 			  y + box_y + 1, x + box_x + 1);
3022a3e3873SBaptiste Daroussin 
3032a3e3873SBaptiste Daroussin     /* draw a box around the list items */
3042a3e3873SBaptiste Daroussin     dlg_draw_box(dialog, box_y, box_x,
3052a3e3873SBaptiste Daroussin 		 use_height + 2 * MARGIN,
3062a3e3873SBaptiste Daroussin 		 all.use_width + 2 * MARGIN,
3072a3e3873SBaptiste Daroussin 		 menubox_border_attr, menubox_border2_attr);
3082a3e3873SBaptiste Daroussin 
3092a3e3873SBaptiste Daroussin     text_width = 0;
3102a3e3873SBaptiste Daroussin     name_width = 0;
3112a3e3873SBaptiste Daroussin     tree_width = 0;
3122a3e3873SBaptiste Daroussin     /* Find length of longest item to center treeview */
3132a3e3873SBaptiste Daroussin     for (i = 0; i < item_no; i++) {
3142a3e3873SBaptiste Daroussin 	tree_width = MAX(tree_width, INDENT * depths[i]);
3152a3e3873SBaptiste Daroussin 	text_width = MAX(text_width, dlg_count_columns(items[i].text));
3162a3e3873SBaptiste Daroussin 	name_width = MAX(name_width, dlg_count_columns(items[i].name));
3172a3e3873SBaptiste Daroussin     }
3182a3e3873SBaptiste Daroussin     if (dialog_vars.no_tags && !dialog_vars.no_items) {
3192a3e3873SBaptiste Daroussin 	tree_width += text_width;
3202a3e3873SBaptiste Daroussin     } else if (dialog_vars.no_items) {
3212a3e3873SBaptiste Daroussin 	tree_width += name_width;
3222a3e3873SBaptiste Daroussin     } else {
3232a3e3873SBaptiste Daroussin 	tree_width += (text_width + name_width);
3242a3e3873SBaptiste Daroussin     }
3252a3e3873SBaptiste Daroussin 
3262a3e3873SBaptiste Daroussin     use_width = (all.use_width - 4);
3272a3e3873SBaptiste Daroussin     tree_width = MIN(tree_width, all.use_width);
3282a3e3873SBaptiste Daroussin 
3292a3e3873SBaptiste Daroussin     all.check_x = (use_width - tree_width) / 2;
3302a3e3873SBaptiste Daroussin     all.item_x = ((dialog_vars.no_tags
3312a3e3873SBaptiste Daroussin 		   ? 0
3322a3e3873SBaptiste Daroussin 		   : (dialog_vars.no_items
3332a3e3873SBaptiste Daroussin 		      ? 0
3342a3e3873SBaptiste Daroussin 		      : (2 + name_width)))
3352a3e3873SBaptiste Daroussin 		  + all.check_x + 4);
3362a3e3873SBaptiste Daroussin 
3372a3e3873SBaptiste Daroussin     /* ensure we are scrolled to show the current choice */
3382a3e3873SBaptiste Daroussin     if (choice >= (max_choice + scrollamt)) {
3392a3e3873SBaptiste Daroussin 	scrollamt = choice - max_choice + 1;
3402a3e3873SBaptiste Daroussin 	choice = max_choice - 1;
3412a3e3873SBaptiste Daroussin     }
3422a3e3873SBaptiste Daroussin 
3432a3e3873SBaptiste Daroussin     /* register the new window, along with its borders */
3442a3e3873SBaptiste Daroussin     dlg_mouse_mkbigregion(box_y + 1, box_x,
3452a3e3873SBaptiste Daroussin 			  use_height, all.use_width + 2,
3462a3e3873SBaptiste Daroussin 			  KEY_MAX, 1, 1, 1 /* by lines */ );
3472a3e3873SBaptiste Daroussin 
3482a3e3873SBaptiste Daroussin     all.dialog = dialog;
3492a3e3873SBaptiste Daroussin     all.box_x = box_x;
3502a3e3873SBaptiste Daroussin     all.box_y = box_y;
3512a3e3873SBaptiste Daroussin     all.use_height = use_height;
3522a3e3873SBaptiste Daroussin     all.list = list;
3532a3e3873SBaptiste Daroussin     print_list(&all, choice, scrollamt, max_choice);
3542a3e3873SBaptiste Daroussin 
3552a3e3873SBaptiste Daroussin     dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
3562a3e3873SBaptiste Daroussin 
3572a3e3873SBaptiste Daroussin     dlg_trace_win(dialog);
358*a96ef450SBaptiste Daroussin 
3592a3e3873SBaptiste Daroussin     while (result == DLG_EXIT_UNKNOWN) {
360*a96ef450SBaptiste Daroussin 	int was_mouse;
361*a96ef450SBaptiste Daroussin 
3622a3e3873SBaptiste Daroussin 	if (button < 0)		/* --visit-items */
3632a3e3873SBaptiste Daroussin 	    wmove(dialog, box_y + choice + 1, box_x + all.check_x + 2);
3642a3e3873SBaptiste Daroussin 
3652a3e3873SBaptiste Daroussin 	key = dlg_mouse_wgetch(dialog, &fkey);
366*a96ef450SBaptiste Daroussin 	if (dlg_result_key(key, fkey, &result)) {
367*a96ef450SBaptiste Daroussin 	    if (!dlg_button_key(result, &button, &key, &fkey))
3682a3e3873SBaptiste Daroussin 		break;
369*a96ef450SBaptiste Daroussin 	}
3702a3e3873SBaptiste Daroussin 
3712a3e3873SBaptiste Daroussin 	was_mouse = (fkey && is_DLGK_MOUSE(key));
3722a3e3873SBaptiste Daroussin 	if (was_mouse)
3732a3e3873SBaptiste Daroussin 	    key -= M_EVENT;
3742a3e3873SBaptiste Daroussin 
3752a3e3873SBaptiste Daroussin 	if (was_mouse && (key >= KEY_MAX)) {
3762a3e3873SBaptiste Daroussin 	    i = (key - KEY_MAX);
3772a3e3873SBaptiste Daroussin 	    if (i < max_choice) {
3782a3e3873SBaptiste Daroussin 		choice = (key - KEY_MAX);
3792a3e3873SBaptiste Daroussin 		print_list(&all, choice, scrollamt, max_choice);
3802a3e3873SBaptiste Daroussin 
381f4f33ea0SBaptiste Daroussin 		key = DLGK_TOGGLE;	/* force the selected item to toggle */
3822a3e3873SBaptiste Daroussin 	    } else {
3832a3e3873SBaptiste Daroussin 		beep();
3842a3e3873SBaptiste Daroussin 		continue;
3852a3e3873SBaptiste Daroussin 	    }
3862a3e3873SBaptiste Daroussin 	    fkey = FALSE;
3872a3e3873SBaptiste Daroussin 	} else if (was_mouse && key >= KEY_MIN) {
3882a3e3873SBaptiste Daroussin 	    key = dlg_lookup_key(dialog, key, &fkey);
3892a3e3873SBaptiste Daroussin 	}
3902a3e3873SBaptiste Daroussin 
3912a3e3873SBaptiste Daroussin 	/*
3922a3e3873SBaptiste Daroussin 	 * A space toggles the item status.
3932a3e3873SBaptiste Daroussin 	 */
394f4f33ea0SBaptiste Daroussin 	if (key == DLGK_TOGGLE) {
3952a3e3873SBaptiste Daroussin 	    int current = scrollamt + choice;
3962a3e3873SBaptiste Daroussin 	    int next = items[current].state + 1;
3972a3e3873SBaptiste Daroussin 
3982a3e3873SBaptiste Daroussin 	    if (next >= num_states)
3992a3e3873SBaptiste Daroussin 		next = 0;
4002a3e3873SBaptiste Daroussin 
4012a3e3873SBaptiste Daroussin 	    if (flag == FLAG_CHECK) {	/* checklist? */
4022a3e3873SBaptiste Daroussin 		items[current].state = next;
4032a3e3873SBaptiste Daroussin 	    } else {
4042a3e3873SBaptiste Daroussin 		for (i = 0; i < item_no; i++) {
4052a3e3873SBaptiste Daroussin 		    if (i != current) {
4062a3e3873SBaptiste Daroussin 			items[i].state = 0;
4072a3e3873SBaptiste Daroussin 		    }
4082a3e3873SBaptiste Daroussin 		}
4092a3e3873SBaptiste Daroussin 		if (items[current].state) {
4102a3e3873SBaptiste Daroussin 		    items[current].state = next ? next : 1;
4112a3e3873SBaptiste Daroussin 		} else {
4122a3e3873SBaptiste Daroussin 		    items[current].state = 1;
4132a3e3873SBaptiste Daroussin 		}
4142a3e3873SBaptiste Daroussin 	    }
4152a3e3873SBaptiste Daroussin 	    print_list(&all, choice, scrollamt, max_choice);
4162a3e3873SBaptiste Daroussin 	    continue;		/* wait for another key press */
4172a3e3873SBaptiste Daroussin 	}
4182a3e3873SBaptiste Daroussin 
4192a3e3873SBaptiste Daroussin 	/*
4202a3e3873SBaptiste Daroussin 	 * Check if key pressed matches first character of any item tag in
4212a3e3873SBaptiste Daroussin 	 * list.  If there is more than one match, we will cycle through
4222a3e3873SBaptiste Daroussin 	 * each one as the same key is pressed repeatedly.
4232a3e3873SBaptiste Daroussin 	 */
4242a3e3873SBaptiste Daroussin 	found = FALSE;
4252a3e3873SBaptiste Daroussin 	if (!fkey) {
4262a3e3873SBaptiste Daroussin 	    if (button < 0 || !dialog_state.visit_items) {
4272a3e3873SBaptiste Daroussin 		for (j = scrollamt + choice + 1; j < item_no; j++) {
4282a3e3873SBaptiste Daroussin 		    if (check_hotkey(items, j)) {
4292a3e3873SBaptiste Daroussin 			found = TRUE;
4302a3e3873SBaptiste Daroussin 			i = j - scrollamt;
4312a3e3873SBaptiste Daroussin 			break;
4322a3e3873SBaptiste Daroussin 		    }
4332a3e3873SBaptiste Daroussin 		}
4342a3e3873SBaptiste Daroussin 		if (!found) {
4352a3e3873SBaptiste Daroussin 		    for (j = 0; j <= scrollamt + choice; j++) {
4362a3e3873SBaptiste Daroussin 			if (check_hotkey(items, j)) {
4372a3e3873SBaptiste Daroussin 			    found = TRUE;
4382a3e3873SBaptiste Daroussin 			    i = j - scrollamt;
4392a3e3873SBaptiste Daroussin 			    break;
4402a3e3873SBaptiste Daroussin 			}
4412a3e3873SBaptiste Daroussin 		    }
4422a3e3873SBaptiste Daroussin 		}
4432a3e3873SBaptiste Daroussin 		if (found)
4442a3e3873SBaptiste Daroussin 		    dlg_flush_getc();
4452a3e3873SBaptiste Daroussin 	    } else if ((j = dlg_char_to_button(key, buttons)) >= 0) {
4462a3e3873SBaptiste Daroussin 		button = j;
4472a3e3873SBaptiste Daroussin 		ungetch('\n');
4482a3e3873SBaptiste Daroussin 		continue;
4492a3e3873SBaptiste Daroussin 	    }
4502a3e3873SBaptiste Daroussin 	}
4512a3e3873SBaptiste Daroussin 
4522a3e3873SBaptiste Daroussin 	/*
4532a3e3873SBaptiste Daroussin 	 * A single digit (1-9) positions the selection to that line in the
4542a3e3873SBaptiste Daroussin 	 * current screen.
4552a3e3873SBaptiste Daroussin 	 */
4562a3e3873SBaptiste Daroussin 	if (!found
4572a3e3873SBaptiste Daroussin 	    && (key <= '9')
4582a3e3873SBaptiste Daroussin 	    && (key > '0')
4592a3e3873SBaptiste Daroussin 	    && (key - '1' < max_choice)) {
4602a3e3873SBaptiste Daroussin 	    found = TRUE;
4612a3e3873SBaptiste Daroussin 	    i = key - '1';
4622a3e3873SBaptiste Daroussin 	}
4632a3e3873SBaptiste Daroussin 
4642a3e3873SBaptiste Daroussin 	if (!found) {
4652a3e3873SBaptiste Daroussin 	    if (fkey) {
4662a3e3873SBaptiste Daroussin 		found = TRUE;
4672a3e3873SBaptiste Daroussin 		switch (key) {
4682a3e3873SBaptiste Daroussin 		case DLGK_ITEM_FIRST:
4692a3e3873SBaptiste Daroussin 		    i = -scrollamt;
4702a3e3873SBaptiste Daroussin 		    break;
4712a3e3873SBaptiste Daroussin 		case DLGK_ITEM_LAST:
4722a3e3873SBaptiste Daroussin 		    i = item_no - 1 - scrollamt;
4732a3e3873SBaptiste Daroussin 		    break;
4742a3e3873SBaptiste Daroussin 		case DLGK_PAGE_PREV:
4752a3e3873SBaptiste Daroussin 		    if (choice)
4762a3e3873SBaptiste Daroussin 			i = 0;
4772a3e3873SBaptiste Daroussin 		    else if (scrollamt != 0)
4782a3e3873SBaptiste Daroussin 			i = -MIN(scrollamt, max_choice);
4792a3e3873SBaptiste Daroussin 		    else
4802a3e3873SBaptiste Daroussin 			continue;
4812a3e3873SBaptiste Daroussin 		    break;
4822a3e3873SBaptiste Daroussin 		case DLGK_PAGE_NEXT:
4832a3e3873SBaptiste Daroussin 		    i = MIN(choice + max_choice, item_no - scrollamt - 1);
4842a3e3873SBaptiste Daroussin 		    break;
4852a3e3873SBaptiste Daroussin 		case DLGK_ITEM_PREV:
4862a3e3873SBaptiste Daroussin 		    i = choice - 1;
4872a3e3873SBaptiste Daroussin 		    if (choice == 0 && scrollamt == 0)
4882a3e3873SBaptiste Daroussin 			continue;
4892a3e3873SBaptiste Daroussin 		    break;
4902a3e3873SBaptiste Daroussin 		case DLGK_ITEM_NEXT:
4912a3e3873SBaptiste Daroussin 		    i = choice + 1;
4922a3e3873SBaptiste Daroussin 		    if (scrollamt + choice >= item_no - 1)
4932a3e3873SBaptiste Daroussin 			continue;
4942a3e3873SBaptiste Daroussin 		    break;
4952a3e3873SBaptiste Daroussin 		default:
4962a3e3873SBaptiste Daroussin 		    found = FALSE;
4972a3e3873SBaptiste Daroussin 		    break;
4982a3e3873SBaptiste Daroussin 		}
4992a3e3873SBaptiste Daroussin 	    }
5002a3e3873SBaptiste Daroussin 	}
5012a3e3873SBaptiste Daroussin 
5022a3e3873SBaptiste Daroussin 	if (found) {
5032a3e3873SBaptiste Daroussin 	    if (i != choice) {
5042a3e3873SBaptiste Daroussin 		if (i < 0 || i >= max_choice) {
5052a3e3873SBaptiste Daroussin 		    if (i < 0) {
5062a3e3873SBaptiste Daroussin 			scrollamt += i;
5072a3e3873SBaptiste Daroussin 			choice = 0;
5082a3e3873SBaptiste Daroussin 		    } else {
5092a3e3873SBaptiste Daroussin 			choice = max_choice - 1;
5102a3e3873SBaptiste Daroussin 			scrollamt += (i - max_choice + 1);
5112a3e3873SBaptiste Daroussin 		    }
5122a3e3873SBaptiste Daroussin 		    print_list(&all, choice, scrollamt, max_choice);
5132a3e3873SBaptiste Daroussin 		} else {
5142a3e3873SBaptiste Daroussin 		    choice = i;
5152a3e3873SBaptiste Daroussin 		    print_list(&all, choice, scrollamt, max_choice);
5162a3e3873SBaptiste Daroussin 		}
5172a3e3873SBaptiste Daroussin 	    }
5182a3e3873SBaptiste Daroussin 	    continue;		/* wait for another key press */
5192a3e3873SBaptiste Daroussin 	}
5202a3e3873SBaptiste Daroussin 
5212a3e3873SBaptiste Daroussin 	if (fkey) {
5222a3e3873SBaptiste Daroussin 	    switch (key) {
5232a3e3873SBaptiste Daroussin 	    case DLGK_ENTER:
5242a3e3873SBaptiste Daroussin 		result = dlg_enter_buttoncode(button);
5252a3e3873SBaptiste Daroussin 		break;
526*a96ef450SBaptiste Daroussin 	    case DLGK_LEAVE:
527*a96ef450SBaptiste Daroussin 		result = dlg_ok_buttoncode(button);
528*a96ef450SBaptiste Daroussin 		break;
5292a3e3873SBaptiste Daroussin 	    case DLGK_FIELD_PREV:
5302a3e3873SBaptiste Daroussin 		button = dlg_prev_button(buttons, button);
5312a3e3873SBaptiste Daroussin 		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
5322a3e3873SBaptiste Daroussin 				 FALSE, width);
5332a3e3873SBaptiste Daroussin 		break;
5342a3e3873SBaptiste Daroussin 	    case DLGK_FIELD_NEXT:
5352a3e3873SBaptiste Daroussin 		button = dlg_next_button(buttons, button);
5362a3e3873SBaptiste Daroussin 		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
5372a3e3873SBaptiste Daroussin 				 FALSE, width);
5382a3e3873SBaptiste Daroussin 		break;
5392a3e3873SBaptiste Daroussin #ifdef KEY_RESIZE
5402a3e3873SBaptiste Daroussin 	    case KEY_RESIZE:
541f4f33ea0SBaptiste Daroussin 		dlg_will_resize(dialog);
5422a3e3873SBaptiste Daroussin 		/* reset data */
5432a3e3873SBaptiste Daroussin 		height = old_height;
5442a3e3873SBaptiste Daroussin 		width = old_width;
5452a3e3873SBaptiste Daroussin 		/* repaint */
546*a96ef450SBaptiste Daroussin 		_dlg_resize_cleanup(dialog);
5472a3e3873SBaptiste Daroussin 		goto retry;
5482a3e3873SBaptiste Daroussin #endif
5492a3e3873SBaptiste Daroussin 	    default:
5502a3e3873SBaptiste Daroussin 		if (was_mouse) {
5512a3e3873SBaptiste Daroussin 		    if ((key2 = dlg_ok_buttoncode(key)) >= 0) {
5522a3e3873SBaptiste Daroussin 			result = key2;
5532a3e3873SBaptiste Daroussin 			break;
5542a3e3873SBaptiste Daroussin 		    }
5552a3e3873SBaptiste Daroussin 		    beep();
5562a3e3873SBaptiste Daroussin 		}
5572a3e3873SBaptiste Daroussin 	    }
558*a96ef450SBaptiste Daroussin 	} else if (key > 0) {
5592a3e3873SBaptiste Daroussin 	    beep();
5602a3e3873SBaptiste Daroussin 	}
5612a3e3873SBaptiste Daroussin     }
5622a3e3873SBaptiste Daroussin 
5632a3e3873SBaptiste Daroussin     dlg_del_window(dialog);
5642a3e3873SBaptiste Daroussin     dlg_mouse_free_regions();
5652a3e3873SBaptiste Daroussin     free(prompt);
5662a3e3873SBaptiste Daroussin     *current_item = (scrollamt + choice);
5672a3e3873SBaptiste Daroussin     return result;
5682a3e3873SBaptiste Daroussin }
5692a3e3873SBaptiste Daroussin 
5702a3e3873SBaptiste Daroussin /*
5712a3e3873SBaptiste Daroussin  * Display a set of items as a tree.
5722a3e3873SBaptiste Daroussin  */
5732a3e3873SBaptiste Daroussin int
dialog_treeview(const char * title,const char * cprompt,int height,int width,int list_height,int item_no,char ** items,int flag)5742a3e3873SBaptiste Daroussin dialog_treeview(const char *title,
5752a3e3873SBaptiste Daroussin 		const char *cprompt,
5762a3e3873SBaptiste Daroussin 		int height,
5772a3e3873SBaptiste Daroussin 		int width,
5782a3e3873SBaptiste Daroussin 		int list_height,
5792a3e3873SBaptiste Daroussin 		int item_no,
5802a3e3873SBaptiste Daroussin 		char **items,
5812a3e3873SBaptiste Daroussin 		int flag)
5822a3e3873SBaptiste Daroussin {
5832a3e3873SBaptiste Daroussin     int result;
5842a3e3873SBaptiste Daroussin     int i, j;
5852a3e3873SBaptiste Daroussin     DIALOG_LISTITEM *listitems;
5862a3e3873SBaptiste Daroussin     int *depths;
5872a3e3873SBaptiste Daroussin     bool show_status = FALSE;
5882a3e3873SBaptiste Daroussin     int current = 0;
589febdb468SDevin Teske     char *help_result;
5902a3e3873SBaptiste Daroussin 
591f4f33ea0SBaptiste Daroussin     DLG_TRACE(("# treeview args:\n"));
592f4f33ea0SBaptiste Daroussin     DLG_TRACE2S("title", title);
593f4f33ea0SBaptiste Daroussin     DLG_TRACE2S("message", cprompt);
594f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("height", height);
595f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("width", width);
596f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("lheight", list_height);
597f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("llength", item_no);
598f4f33ea0SBaptiste Daroussin     /* FIXME dump the items[][] too */
599f4f33ea0SBaptiste Daroussin     DLG_TRACE2N("flag", flag);
600f4f33ea0SBaptiste Daroussin 
6012a3e3873SBaptiste Daroussin     listitems = dlg_calloc(DIALOG_LISTITEM, (size_t) item_no + 1);
6022a3e3873SBaptiste Daroussin     assert_ptr(listitems, "dialog_treeview");
6032a3e3873SBaptiste Daroussin 
6042a3e3873SBaptiste Daroussin     depths = dlg_calloc(int, (size_t) item_no + 1);
6052a3e3873SBaptiste Daroussin     assert_ptr(depths, "dialog_treeview");
6062a3e3873SBaptiste Daroussin 
6072a3e3873SBaptiste Daroussin     for (i = j = 0; i < item_no; ++i) {
6082a3e3873SBaptiste Daroussin 	listitems[i].name = items[j++];
6092a3e3873SBaptiste Daroussin 	listitems[i].text = (dialog_vars.no_items
6102a3e3873SBaptiste Daroussin 			     ? dlg_strempty()
6112a3e3873SBaptiste Daroussin 			     : items[j++]);
6122a3e3873SBaptiste Daroussin 	listitems[i].state = !dlg_strcmp(items[j++], "on");
6132a3e3873SBaptiste Daroussin 	depths[i] = atoi(items[j++]);
6142a3e3873SBaptiste Daroussin 	listitems[i].help = ((dialog_vars.item_help)
6152a3e3873SBaptiste Daroussin 			     ? items[j++]
6162a3e3873SBaptiste Daroussin 			     : dlg_strempty());
6172a3e3873SBaptiste Daroussin     }
6182a3e3873SBaptiste Daroussin     dlg_align_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no);
6192a3e3873SBaptiste Daroussin 
6202a3e3873SBaptiste Daroussin     result = dlg_treeview(title,
6212a3e3873SBaptiste Daroussin 			  cprompt,
6222a3e3873SBaptiste Daroussin 			  height,
6232a3e3873SBaptiste Daroussin 			  width,
6242a3e3873SBaptiste Daroussin 			  list_height,
6252a3e3873SBaptiste Daroussin 			  item_no,
6262a3e3873SBaptiste Daroussin 			  listitems,
6272a3e3873SBaptiste Daroussin 			  NULL,
6282a3e3873SBaptiste Daroussin 			  depths,
6292a3e3873SBaptiste Daroussin 			  flag,
6302a3e3873SBaptiste Daroussin 			  &current);
6312a3e3873SBaptiste Daroussin 
6322a3e3873SBaptiste Daroussin     switch (result) {
6332a3e3873SBaptiste Daroussin     case DLG_EXIT_OK:		/* FALLTHRU */
6342a3e3873SBaptiste Daroussin     case DLG_EXIT_EXTRA:
6352a3e3873SBaptiste Daroussin 	show_status = TRUE;
6362a3e3873SBaptiste Daroussin 	break;
6372a3e3873SBaptiste Daroussin     case DLG_EXIT_HELP:
638febdb468SDevin Teske 	dlg_add_help_listitem(&result, &help_result, &listitems[current]);
639febdb468SDevin Teske 	if ((show_status = dialog_vars.help_status)) {
6402a3e3873SBaptiste Daroussin 	    if (dialog_vars.separate_output) {
641febdb468SDevin Teske 		dlg_add_string(help_result);
6422a3e3873SBaptiste Daroussin 		dlg_add_separator();
6432a3e3873SBaptiste Daroussin 	    } else {
644febdb468SDevin Teske 		dlg_add_quoted(help_result);
6452a3e3873SBaptiste Daroussin 	    }
6462a3e3873SBaptiste Daroussin 	} else {
647febdb468SDevin Teske 	    dlg_add_string(help_result);
6482a3e3873SBaptiste Daroussin 	}
6492a3e3873SBaptiste Daroussin 	break;
6502a3e3873SBaptiste Daroussin     }
6512a3e3873SBaptiste Daroussin 
6522a3e3873SBaptiste Daroussin     if (show_status) {
6532a3e3873SBaptiste Daroussin 	for (i = 0; i < item_no; i++) {
6542a3e3873SBaptiste Daroussin 	    if (listitems[i].state) {
6552a3e3873SBaptiste Daroussin 		if (dlg_need_separator())
6562a3e3873SBaptiste Daroussin 		    dlg_add_separator();
657*a96ef450SBaptiste Daroussin 		if (dialog_vars.separate_output) {
658*a96ef450SBaptiste Daroussin 		    dlg_add_string(listitems[i].name);
659*a96ef450SBaptiste Daroussin 		} else {
6602a3e3873SBaptiste Daroussin 		    if (flag == FLAG_CHECK)
6612a3e3873SBaptiste Daroussin 			dlg_add_quoted(listitems[i].name);
6622a3e3873SBaptiste Daroussin 		    else
6632a3e3873SBaptiste Daroussin 			dlg_add_string(listitems[i].name);
6642a3e3873SBaptiste Daroussin 		}
6652a3e3873SBaptiste Daroussin 	    }
6662a3e3873SBaptiste Daroussin 	}
667*a96ef450SBaptiste Daroussin 	AddLastKey();
6682a3e3873SBaptiste Daroussin     }
6692a3e3873SBaptiste Daroussin 
6702a3e3873SBaptiste Daroussin     dlg_free_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no);
6712a3e3873SBaptiste Daroussin     free(depths);
6722a3e3873SBaptiste Daroussin     free(listitems);
6732a3e3873SBaptiste Daroussin     return result;
6742a3e3873SBaptiste Daroussin }
675