xref: /dragonfly/contrib/dialog/menubox.c (revision a8e38dc0)
15382d832SPeter Avalos /*
2*a8e38dc0SAntonio Huete Jimenez  *  $Id: menubox.c,v 1.175 2022/04/05 00:14:56 tom Exp $
35382d832SPeter Avalos  *
45382d832SPeter Avalos  *  menubox.c -- implements the menu box
55382d832SPeter Avalos  *
6*a8e38dc0SAntonio Huete Jimenez  *  Copyright 2000-2021,2022	Thomas E. Dickey
75382d832SPeter Avalos  *
85382d832SPeter Avalos  *  This program is free software; you can redistribute it and/or modify
95382d832SPeter Avalos  *  it under the terms of the GNU Lesser General Public Licens, version 2.1e
105382d832SPeter Avalos  *  as published by the Free Software Foundation.
115382d832SPeter Avalos  *
125382d832SPeter Avalos  *  This program is distributed in the hope that it will be useful, but
135382d832SPeter Avalos  *  WITHOUT ANY WARRANTY; without even the implied warranty of
145382d832SPeter Avalos  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
155382d832SPeter Avalos  *  Lesser General Public License for more details.
165382d832SPeter Avalos  *
175382d832SPeter Avalos  *  You should have received a copy of the GNU Lesser General Public
185382d832SPeter Avalos  *  License along with this program; if not, write to
195382d832SPeter Avalos  *	Free Software Foundation, Inc.
205382d832SPeter Avalos  *	51 Franklin St., Fifth Floor
215382d832SPeter Avalos  *	Boston, MA 02110, USA.
225382d832SPeter Avalos  *
235382d832SPeter Avalos  *  An earlier version of this program lists as authors
245382d832SPeter Avalos  *	Savio Lam (lam836@cs.cuhk.hk)
255382d832SPeter Avalos  */
265382d832SPeter Avalos 
275940c9abSDaniel Fojt #include <dlg_internals.h>
285382d832SPeter Avalos #include <dlg_keys.h>
295382d832SPeter Avalos 
305382d832SPeter Avalos typedef enum {
315382d832SPeter Avalos     Unselected = 0,
325382d832SPeter Avalos     Selected,
335382d832SPeter Avalos     Editing
345382d832SPeter Avalos } Mode;
355382d832SPeter Avalos 
365382d832SPeter Avalos typedef struct {
375382d832SPeter Avalos     /* the outer-window */
385382d832SPeter Avalos     WINDOW *dialog;
395382d832SPeter Avalos     int box_y;
405382d832SPeter Avalos     int box_x;
415382d832SPeter Avalos     int tag_x;
425382d832SPeter Avalos     int item_x;
435382d832SPeter Avalos     int menu_height;
445382d832SPeter Avalos     int menu_width;
455382d832SPeter Avalos     /* the inner-window */
465382d832SPeter Avalos     WINDOW *menu;
475382d832SPeter Avalos     DIALOG_LISTITEM *items;
485382d832SPeter Avalos     int item_no;
495382d832SPeter Avalos } ALL_DATA;
505382d832SPeter Avalos 
515382d832SPeter Avalos #define MIN_HIGH  (1 + (5 * MARGIN))
525382d832SPeter Avalos 
535382d832SPeter Avalos #define INPUT_ROWS     3	/* rows per inputmenu entry */
545382d832SPeter Avalos 
555382d832SPeter Avalos #define RowHeight(i) (is_inputmenu ? ((i) * INPUT_ROWS) : ((i) * 1))
565382d832SPeter Avalos #define ItemToRow(i) (is_inputmenu ? ((i) * INPUT_ROWS + 1) : (i))
575382d832SPeter Avalos #define RowToItem(i) (is_inputmenu ? ((i) / INPUT_ROWS + 0) : (i))
585382d832SPeter Avalos 
595382d832SPeter Avalos /*
605382d832SPeter Avalos  * Print menu item
615382d832SPeter Avalos  */
625382d832SPeter Avalos static void
print_item(ALL_DATA * data,WINDOW * win,DIALOG_LISTITEM * item,int choice,Mode selected,bool is_inputmenu)635382d832SPeter Avalos print_item(ALL_DATA * data,
645382d832SPeter Avalos 	   WINDOW *win,
655382d832SPeter Avalos 	   DIALOG_LISTITEM * item,
665382d832SPeter Avalos 	   int choice,
675382d832SPeter Avalos 	   Mode selected,
685382d832SPeter Avalos 	   bool is_inputmenu)
695382d832SPeter Avalos {
705382d832SPeter Avalos     chtype save = dlg_get_attrs(win);
715382d832SPeter Avalos     int climit = (data->item_x - data->tag_x - GUTTER);
725382d832SPeter Avalos     int my_width = data->menu_width;
735382d832SPeter Avalos     int my_x = data->item_x;
745382d832SPeter Avalos     int my_y = ItemToRow(choice);
755382d832SPeter Avalos     bool both = (!dialog_vars.no_tags && !dialog_vars.no_items);
765382d832SPeter Avalos     bool first = TRUE;
775382d832SPeter Avalos     chtype bordchar;
785382d832SPeter Avalos     const char *show = (dialog_vars.no_items
795382d832SPeter Avalos 			? item->name
805382d832SPeter Avalos 			: item->text);
815382d832SPeter Avalos 
825382d832SPeter Avalos     switch (selected) {
835382d832SPeter Avalos     default:
845382d832SPeter Avalos     case Unselected:
855382d832SPeter Avalos 	bordchar = item_attr;
865382d832SPeter Avalos 	break;
875382d832SPeter Avalos     case Selected:
885382d832SPeter Avalos 	bordchar = item_selected_attr;
895382d832SPeter Avalos 	break;
905382d832SPeter Avalos     case Editing:
915382d832SPeter Avalos 	bordchar = dialog_attr;
925382d832SPeter Avalos 	break;
935382d832SPeter Avalos     }
945382d832SPeter Avalos 
955382d832SPeter Avalos     /* Clear 'residue' of last item and mark current current item */
965382d832SPeter Avalos     if (is_inputmenu) {
975940c9abSDaniel Fojt 	int n;
985940c9abSDaniel Fojt 
995940c9abSDaniel Fojt 	dlg_attrset(win, (selected != Unselected) ? item_selected_attr : item_attr);
1005382d832SPeter Avalos 	for (n = my_y - 1; n < my_y + INPUT_ROWS - 1; n++) {
1015382d832SPeter Avalos 	    wmove(win, n, 0);
1025382d832SPeter Avalos 	    wprintw(win, "%*s", my_width, " ");
1035382d832SPeter Avalos 	}
1045382d832SPeter Avalos     } else {
1055940c9abSDaniel Fojt 	dlg_attrset(win, menubox_attr);
1065382d832SPeter Avalos 	wmove(win, my_y, 0);
1075382d832SPeter Avalos 	wprintw(win, "%*s", my_width, " ");
1085382d832SPeter Avalos     }
1095382d832SPeter Avalos 
1105382d832SPeter Avalos     /* highlight first char of the tag to be special */
1115382d832SPeter Avalos     if (both) {
1125382d832SPeter Avalos 	(void) wmove(win, my_y, data->tag_x);
1135382d832SPeter Avalos 	dlg_print_listitem(win, item->name, climit, first, selected);
1145382d832SPeter Avalos 	first = FALSE;
1155382d832SPeter Avalos     }
1165382d832SPeter Avalos 
1175382d832SPeter Avalos     /* Draw the input field box (only for inputmenu) */
1185382d832SPeter Avalos     (void) wmove(win, my_y, my_x);
1195382d832SPeter Avalos     if (is_inputmenu) {
1205382d832SPeter Avalos 	my_width -= 1;
1215382d832SPeter Avalos 	dlg_draw_box(win, my_y - 1, my_x, INPUT_ROWS, my_width - my_x - data->tag_x,
1225382d832SPeter Avalos 		     bordchar,
1235382d832SPeter Avalos 		     bordchar);
1245382d832SPeter Avalos 	my_width -= 1;
1255382d832SPeter Avalos 	++my_x;
1265382d832SPeter Avalos     }
1275382d832SPeter Avalos 
1285382d832SPeter Avalos     /* print actual item */
1295382d832SPeter Avalos     wmove(win, my_y, my_x);
1305382d832SPeter Avalos     dlg_print_listitem(win, show, my_width - my_x, first, selected);
1315382d832SPeter Avalos 
1325382d832SPeter Avalos     if (selected) {
1335382d832SPeter Avalos 	dlg_item_help(item->help);
1345382d832SPeter Avalos     }
1355940c9abSDaniel Fojt     dlg_attrset(win, save);
1365382d832SPeter Avalos }
1375382d832SPeter Avalos 
1385382d832SPeter Avalos /*
1395382d832SPeter Avalos  * Allow the user to edit the text of a menu entry.
1405382d832SPeter Avalos  */
1415382d832SPeter Avalos static int
input_menu_edit(ALL_DATA * data,DIALOG_LISTITEM * items,int choice,char ** resultp)1425382d832SPeter Avalos input_menu_edit(ALL_DATA * data,
1435382d832SPeter Avalos 		DIALOG_LISTITEM * items,
1445382d832SPeter Avalos 		int choice,
1455382d832SPeter Avalos 		char **resultp)
1465382d832SPeter Avalos {
1475382d832SPeter Avalos     chtype save = dlg_get_attrs(data->menu);
1485382d832SPeter Avalos     char *result;
1495382d832SPeter Avalos     int offset = 0;
1505382d832SPeter Avalos     int key = 0, fkey = 0;
1515940c9abSDaniel Fojt     bool first = TRUE;
1525382d832SPeter Avalos     /* see above */
1535382d832SPeter Avalos     bool is_inputmenu = TRUE;
1545382d832SPeter Avalos     int y = ItemToRow(choice);
1555382d832SPeter Avalos     int code = TRUE;
1565382d832SPeter Avalos     int max_len = dlg_max_input(MAX((int) strlen(items->text) + 1, MAX_LEN));
1575382d832SPeter Avalos 
1585382d832SPeter Avalos     result = dlg_malloc(char, (size_t) max_len);
1595382d832SPeter Avalos     assert_ptr(result, "input_menu_edit");
1605382d832SPeter Avalos 
1615382d832SPeter Avalos     /* original item is used to initialize the input string. */
1625382d832SPeter Avalos     result[0] = '\0';
1635382d832SPeter Avalos     strcpy(result, items->text);
1645382d832SPeter Avalos 
1655382d832SPeter Avalos     print_item(data, data->menu, items, choice, Editing, TRUE);
1665382d832SPeter Avalos 
1675382d832SPeter Avalos     /* taken out of inputbox.c - but somewhat modified */
1685382d832SPeter Avalos     for (;;) {
1695940c9abSDaniel Fojt 	if (!first) {
1705940c9abSDaniel Fojt 	    int check = DLG_EXIT_UNKNOWN;
1715382d832SPeter Avalos 	    key = dlg_mouse_wgetch(data->menu, &fkey);
1725940c9abSDaniel Fojt 	    if (dlg_result_key(key, fkey, &check)) {
1735940c9abSDaniel Fojt 		if (check == DLG_EXIT_CANCEL) {
1745940c9abSDaniel Fojt 		    code = FALSE;
1755940c9abSDaniel Fojt 		    break;
1765940c9abSDaniel Fojt 		} else {
1775940c9abSDaniel Fojt 		    flash();
1785940c9abSDaniel Fojt 		}
1795940c9abSDaniel Fojt 	    }
1805940c9abSDaniel Fojt 	}
1815382d832SPeter Avalos 	if (dlg_edit_string(result, &offset, key, fkey, first)) {
1825382d832SPeter Avalos 	    dlg_show_string(data->menu, result, offset, inputbox_attr,
1835382d832SPeter Avalos 			    y,
1845382d832SPeter Avalos 			    data->item_x + 1,
1855382d832SPeter Avalos 			    data->menu_width - data->item_x - 3,
1865382d832SPeter Avalos 			    FALSE, first);
1875382d832SPeter Avalos 	    first = FALSE;
1885382d832SPeter Avalos 	} else if (key == ESC || key == TAB) {
1895382d832SPeter Avalos 	    code = FALSE;
1905382d832SPeter Avalos 	    break;
1915382d832SPeter Avalos 	} else {
1925382d832SPeter Avalos 	    break;
1935382d832SPeter Avalos 	}
1945382d832SPeter Avalos     }
1955382d832SPeter Avalos     print_item(data, data->menu, items, choice, Selected, TRUE);
1965940c9abSDaniel Fojt     dlg_attrset(data->menu, save);
1975382d832SPeter Avalos 
1985382d832SPeter Avalos     *resultp = result;
1995382d832SPeter Avalos     return code;
2005382d832SPeter Avalos }
2015382d832SPeter Avalos 
2025382d832SPeter Avalos static int
handle_button(int code,DIALOG_LISTITEM * items,int choice)2035382d832SPeter Avalos handle_button(int code, DIALOG_LISTITEM * items, int choice)
2045382d832SPeter Avalos {
2051ef6786aSJohn Marino     char *help_result;
2061ef6786aSJohn Marino 
2075382d832SPeter Avalos     switch (code) {
2085382d832SPeter Avalos     case DLG_EXIT_OK:		/* FALLTHRU */
2095382d832SPeter Avalos     case DLG_EXIT_EXTRA:
2105382d832SPeter Avalos 	dlg_add_string(items[choice].name);
2115382d832SPeter Avalos 	break;
2125382d832SPeter Avalos     case DLG_EXIT_HELP:
2131ef6786aSJohn Marino 	dlg_add_help_listitem(&code, &help_result, &items[choice]);
2141ef6786aSJohn Marino 	dlg_add_string(help_result);
2155382d832SPeter Avalos 	break;
2165382d832SPeter Avalos     }
2175940c9abSDaniel Fojt     AddLastKey();
2185382d832SPeter Avalos     return code;
2195382d832SPeter Avalos }
2205382d832SPeter Avalos 
2215382d832SPeter Avalos int
dlg_renamed_menutext(DIALOG_LISTITEM * items,int current,char * newtext)2225382d832SPeter Avalos dlg_renamed_menutext(DIALOG_LISTITEM * items, int current, char *newtext)
2235382d832SPeter Avalos {
2245382d832SPeter Avalos     if (dialog_vars.input_result)
2255382d832SPeter Avalos 	dialog_vars.input_result[0] = '\0';
2265382d832SPeter Avalos     dlg_add_result("RENAMED ");
2275382d832SPeter Avalos     dlg_add_string(items[current].name);
2285382d832SPeter Avalos     dlg_add_result(" ");
2295382d832SPeter Avalos     dlg_add_string(newtext);
2305940c9abSDaniel Fojt     AddLastKey();
2315382d832SPeter Avalos     return DLG_EXIT_EXTRA;
2325382d832SPeter Avalos }
2335382d832SPeter Avalos 
2345382d832SPeter Avalos int
dlg_dummy_menutext(DIALOG_LISTITEM * items,int current,char * newtext)2355382d832SPeter Avalos dlg_dummy_menutext(DIALOG_LISTITEM * items, int current, char *newtext)
2365382d832SPeter Avalos {
2375382d832SPeter Avalos     (void) items;
2385382d832SPeter Avalos     (void) current;
2395382d832SPeter Avalos     (void) newtext;
2405382d832SPeter Avalos     return DLG_EXIT_ERROR;
2415382d832SPeter Avalos }
2425382d832SPeter Avalos 
2435382d832SPeter Avalos static void
print_menu(ALL_DATA * data,int choice,int scrollamt,int max_choice,int max_items,bool is_inputmenu)244*a8e38dc0SAntonio Huete Jimenez print_menu(ALL_DATA * data,
245*a8e38dc0SAntonio Huete Jimenez 	   int choice,
246*a8e38dc0SAntonio Huete Jimenez 	   int scrollamt,
247*a8e38dc0SAntonio Huete Jimenez 	   int max_choice,
248*a8e38dc0SAntonio Huete Jimenez 	   int max_items,
249*a8e38dc0SAntonio Huete Jimenez 	   bool is_inputmenu)
2505382d832SPeter Avalos {
2515382d832SPeter Avalos     int i;
2525382d832SPeter Avalos 
2535382d832SPeter Avalos     for (i = 0; i < max_choice; i++) {
254*a8e38dc0SAntonio Huete Jimenez 	int ii = i + scrollamt;
255*a8e38dc0SAntonio Huete Jimenez 	if (ii < max_items)
2565382d832SPeter Avalos 	    print_item(data,
2575382d832SPeter Avalos 		       data->menu,
258*a8e38dc0SAntonio Huete Jimenez 		       &data->items[ii],
2595382d832SPeter Avalos 		       i,
2605382d832SPeter Avalos 		       (i == choice) ? Selected : Unselected,
2615382d832SPeter Avalos 		       is_inputmenu);
2625382d832SPeter Avalos     }
2635382d832SPeter Avalos 
2645382d832SPeter Avalos     /* Clean bottom lines */
2655382d832SPeter Avalos     if (is_inputmenu) {
2665382d832SPeter Avalos 	int spare_lines, x_count;
2675382d832SPeter Avalos 	spare_lines = data->menu_height % INPUT_ROWS;
2685940c9abSDaniel Fojt 	dlg_attrset(data->menu, menubox_attr);
2695382d832SPeter Avalos 	for (; spare_lines; spare_lines--) {
2705382d832SPeter Avalos 	    wmove(data->menu, data->menu_height - spare_lines, 0);
2715382d832SPeter Avalos 	    for (x_count = 0; x_count < data->menu_width;
2725382d832SPeter Avalos 		 x_count++) {
2735382d832SPeter Avalos 		waddch(data->menu, ' ');
2745382d832SPeter Avalos 	    }
2755382d832SPeter Avalos 	}
2765382d832SPeter Avalos     }
2775382d832SPeter Avalos 
2785382d832SPeter Avalos     (void) wnoutrefresh(data->menu);
2795382d832SPeter Avalos 
2805382d832SPeter Avalos     dlg_draw_scrollbar(data->dialog,
2815382d832SPeter Avalos 		       scrollamt,
2825382d832SPeter Avalos 		       scrollamt,
2835382d832SPeter Avalos 		       scrollamt + max_choice,
2845382d832SPeter Avalos 		       data->item_no,
2855382d832SPeter Avalos 		       data->box_x,
2865382d832SPeter Avalos 		       data->box_x + data->menu_width,
2875382d832SPeter Avalos 		       data->box_y,
2885382d832SPeter Avalos 		       data->box_y + data->menu_height + 1,
2895382d832SPeter Avalos 		       menubox_border2_attr,
2905382d832SPeter Avalos 		       menubox_border_attr);
2915382d832SPeter Avalos }
2925382d832SPeter Avalos 
2935382d832SPeter Avalos static bool
check_hotkey(DIALOG_LISTITEM * items,int choice)2945382d832SPeter Avalos check_hotkey(DIALOG_LISTITEM * items, int choice)
2955382d832SPeter Avalos {
2965382d832SPeter Avalos     bool result = FALSE;
2975382d832SPeter Avalos 
2985382d832SPeter Avalos     if (dlg_match_char(dlg_last_getc(),
2995382d832SPeter Avalos 		       (dialog_vars.no_tags
3005382d832SPeter Avalos 			? items[choice].text
3015382d832SPeter Avalos 			: items[choice].name))) {
3025382d832SPeter Avalos 	result = TRUE;
3035382d832SPeter Avalos     }
3045382d832SPeter Avalos     return result;
3055382d832SPeter Avalos }
3065382d832SPeter Avalos 
3075382d832SPeter Avalos /*
3085382d832SPeter Avalos  * This is an alternate interface to 'menu' which allows the application
3095382d832SPeter Avalos  * to read the list item states back directly without putting them in the
3105382d832SPeter Avalos  * output buffer.
3115382d832SPeter Avalos  */
3125382d832SPeter Avalos int
dlg_menu(const char * title,const char * cprompt,int height,int width,int menu_height,int item_no,DIALOG_LISTITEM * items,int * current_item,DIALOG_INPUTMENU rename_menutext)3135382d832SPeter Avalos dlg_menu(const char *title,
3145382d832SPeter Avalos 	 const char *cprompt,
3155382d832SPeter Avalos 	 int height,
3165382d832SPeter Avalos 	 int width,
3175382d832SPeter Avalos 	 int menu_height,
3185382d832SPeter Avalos 	 int item_no,
3195382d832SPeter Avalos 	 DIALOG_LISTITEM * items,
3205382d832SPeter Avalos 	 int *current_item,
3215382d832SPeter Avalos 	 DIALOG_INPUTMENU rename_menutext)
3225382d832SPeter Avalos {
3235382d832SPeter Avalos     /* *INDENT-OFF* */
3245382d832SPeter Avalos     static DLG_KEYS_BINDING binding[] = {
3255382d832SPeter Avalos 	HELPKEY_BINDINGS,
3265382d832SPeter Avalos 	ENTERKEY_BINDINGS,
3275940c9abSDaniel Fojt 	TOGGLEKEY_BINDINGS,
3285382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	KEY_RIGHT ),
3295382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	TAB ),
3305382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_BTAB ),
3315382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_LEFT ),
3325382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	'+' ),
3335382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	KEY_DOWN ),
3345382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  CHR_NEXT ),
3355382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_ITEM_PREV,	'-' ),
3365382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_ITEM_PREV,	KEY_UP ),
3375382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_ITEM_PREV,  CHR_PREVIOUS ),
3385382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_PAGE_FIRST,	KEY_HOME ),
3395382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_PAGE_LAST,	KEY_END ),
3405382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_PAGE_LAST,	KEY_LL ),
3415382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_PAGE_NEXT,	KEY_NPAGE ),
3425382d832SPeter Avalos 	DLG_KEYS_DATA( DLGK_PAGE_PREV,	KEY_PPAGE ),
3435382d832SPeter Avalos 	END_KEYS_BINDING
3445382d832SPeter Avalos     };
3455382d832SPeter Avalos     static DLG_KEYS_BINDING binding2[] = {
3465382d832SPeter Avalos 	INPUTSTR_BINDINGS,
3475382d832SPeter Avalos 	HELPKEY_BINDINGS,
3485382d832SPeter Avalos 	ENTERKEY_BINDINGS,
3495382d832SPeter Avalos 	END_KEYS_BINDING
3505382d832SPeter Avalos     };
3515382d832SPeter Avalos     /* *INDENT-ON* */
3525382d832SPeter Avalos 
3535382d832SPeter Avalos #ifdef KEY_RESIZE
3545940c9abSDaniel Fojt     int old_LINES = LINES;
3555940c9abSDaniel Fojt     int old_COLS = COLS;
3565382d832SPeter Avalos     int old_height = height;
3575382d832SPeter Avalos     int old_width = width;
3585382d832SPeter Avalos #endif
3595382d832SPeter Avalos     ALL_DATA all;
3605382d832SPeter Avalos     int i, j, x, y, cur_x, cur_y;
3615940c9abSDaniel Fojt     int fkey;
3625382d832SPeter Avalos     int button = dialog_state.visit_items ? -1 : dlg_default_button();
3635382d832SPeter Avalos     int choice = dlg_default_listitem(items);
3645382d832SPeter Avalos     int result = DLG_EXIT_UNKNOWN;
3655382d832SPeter Avalos     int scrollamt = 0;
3665382d832SPeter Avalos     int max_choice;
3675382d832SPeter Avalos     int use_width, name_width, text_width, list_width;
3685382d832SPeter Avalos     WINDOW *dialog, *menu;
3695940c9abSDaniel Fojt     char *prompt = 0;
3705382d832SPeter Avalos     const char **buttons = dlg_ok_labels();
3715382d832SPeter Avalos     bool is_inputmenu = ((rename_menutext != 0)
3725382d832SPeter Avalos 			 && (rename_menutext != dlg_dummy_menutext));
3735382d832SPeter Avalos 
3745940c9abSDaniel Fojt     DLG_TRACE(("# menubox args:\n"));
3755940c9abSDaniel Fojt     DLG_TRACE2S("title", title);
3765940c9abSDaniel Fojt     DLG_TRACE2S("message", cprompt);
3775940c9abSDaniel Fojt     DLG_TRACE2N("height", height);
3785940c9abSDaniel Fojt     DLG_TRACE2N("width", width);
3795940c9abSDaniel Fojt     DLG_TRACE2N("lheight", menu_height);
3805940c9abSDaniel Fojt     DLG_TRACE2N("llength", item_no);
3815940c9abSDaniel Fojt     /* FIXME dump the items[][] too */
3825940c9abSDaniel Fojt     DLG_TRACE2N("rename", rename_menutext != 0);
3835940c9abSDaniel Fojt 
3841ef6786aSJohn Marino     dialog_state.plain_buttons = TRUE;
3851ef6786aSJohn Marino 
3865382d832SPeter Avalos     all.items = items;
3875382d832SPeter Avalos     all.item_no = item_no;
3885382d832SPeter Avalos 
3895382d832SPeter Avalos     dlg_does_output();
3905382d832SPeter Avalos 
3915382d832SPeter Avalos #ifdef KEY_RESIZE
3925382d832SPeter Avalos   retry:
3935382d832SPeter Avalos #endif
3945382d832SPeter Avalos 
3955940c9abSDaniel Fojt     prompt = dlg_strclone(cprompt);
3965940c9abSDaniel Fojt     dlg_tab_correct_str(prompt);
3975940c9abSDaniel Fojt 
3985382d832SPeter Avalos     all.menu_height = menu_height;
3995382d832SPeter Avalos     use_width = dlg_calc_list_width(item_no, items) + 10;
4005382d832SPeter Avalos     use_width = MAX(26, use_width);
4015382d832SPeter Avalos     if (all.menu_height == 0) {
4025382d832SPeter Avalos 	/* calculate height without items (4) */
4035382d832SPeter Avalos 	dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, use_width);
4045382d832SPeter Avalos 	dlg_calc_listh(&height, &all.menu_height, item_no);
4055382d832SPeter Avalos     } else {
4065382d832SPeter Avalos 	dlg_auto_size(title, prompt,
4075382d832SPeter Avalos 		      &height, &width,
4085382d832SPeter Avalos 		      MIN_HIGH + all.menu_height, use_width);
4095382d832SPeter Avalos     }
4105382d832SPeter Avalos     dlg_button_layout(buttons, &width);
4115382d832SPeter Avalos     dlg_print_size(height, width);
4125382d832SPeter Avalos     dlg_ctl_size(height, width);
4135382d832SPeter Avalos 
4145382d832SPeter Avalos     x = dlg_box_x_ordinate(width);
4155382d832SPeter Avalos     y = dlg_box_y_ordinate(height);
4165382d832SPeter Avalos 
4175382d832SPeter Avalos     dialog = dlg_new_window(height, width, y, x);
4185382d832SPeter Avalos     all.dialog = dialog;
4195382d832SPeter Avalos 
4205382d832SPeter Avalos     dlg_register_window(dialog, "menubox", binding);
4215382d832SPeter Avalos     dlg_register_buttons(dialog, "menubox", buttons);
4225382d832SPeter Avalos 
4235382d832SPeter Avalos     dlg_mouse_setbase(x, y);
4245382d832SPeter Avalos 
4255382d832SPeter Avalos     dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
4265382d832SPeter Avalos     dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
4275382d832SPeter Avalos     dlg_draw_title(dialog, title);
4285382d832SPeter Avalos 
4295940c9abSDaniel Fojt     dlg_attrset(dialog, dialog_attr);
4305382d832SPeter Avalos     dlg_print_autowrap(dialog, prompt, height, width);
4315382d832SPeter Avalos 
4325382d832SPeter Avalos     all.menu_width = width - 6;
4335382d832SPeter Avalos     getyx(dialog, cur_y, cur_x);
4345382d832SPeter Avalos     all.box_y = cur_y + 1;
4355382d832SPeter Avalos     all.box_x = (width - all.menu_width) / 2 - 1;
4365382d832SPeter Avalos 
4375382d832SPeter Avalos     /*
4385382d832SPeter Avalos      * After displaying the prompt, we know how much space we really have.
4395382d832SPeter Avalos      * Limit the list to avoid overwriting the ok-button.
4405382d832SPeter Avalos      */
4415382d832SPeter Avalos     all.menu_height = height - MIN_HIGH - cur_y;
4425382d832SPeter Avalos     if (all.menu_height <= 0)
4435382d832SPeter Avalos 	all.menu_height = 1;
4445382d832SPeter Avalos 
4455382d832SPeter Avalos     /* Find out maximal number of displayable items at once. */
4465382d832SPeter Avalos     max_choice = MIN(all.menu_height,
4475382d832SPeter Avalos 		     RowHeight(item_no));
4485382d832SPeter Avalos     if (is_inputmenu)
4495382d832SPeter Avalos 	max_choice /= INPUT_ROWS;
4505382d832SPeter Avalos 
4515382d832SPeter Avalos     /* create new window for the menu */
4525382d832SPeter Avalos     menu = dlg_sub_window(dialog, all.menu_height, all.menu_width,
4535382d832SPeter Avalos 			  y + all.box_y + 1,
4545382d832SPeter Avalos 			  x + all.box_x + 1);
4555382d832SPeter Avalos     all.menu = menu;
4565382d832SPeter Avalos 
4575382d832SPeter Avalos     dlg_register_window(menu, "menu", binding2);
4585382d832SPeter Avalos     dlg_register_buttons(menu, "menu", buttons);
4595382d832SPeter Avalos 
4605382d832SPeter Avalos     /* draw a box around the menu items */
4615382d832SPeter Avalos     dlg_draw_box(dialog,
4625382d832SPeter Avalos 		 all.box_y, all.box_x,
4635382d832SPeter Avalos 		 all.menu_height + 2, all.menu_width + 2,
4645382d832SPeter Avalos 		 menubox_border_attr, menubox_border2_attr);
4655382d832SPeter Avalos 
4665382d832SPeter Avalos     name_width = 0;
4675382d832SPeter Avalos     text_width = 0;
4685382d832SPeter Avalos 
4695382d832SPeter Avalos     /* Find length of longest item to center menu  *
4705382d832SPeter Avalos      * only if --menu was given, using --inputmenu *
4715382d832SPeter Avalos      * won't be centered.                         */
4725382d832SPeter Avalos     for (i = 0; i < item_no; i++) {
4735382d832SPeter Avalos 	name_width = MAX(name_width, dlg_count_columns(items[i].name));
4745382d832SPeter Avalos 	text_width = MAX(text_width, dlg_count_columns(items[i].text));
4755382d832SPeter Avalos     }
4765382d832SPeter Avalos 
4775382d832SPeter Avalos     /* If the name+text is wider than the list is allowed, then truncate
4785382d832SPeter Avalos      * one or both of them.  If the name is no wider than 30% of the list,
4795382d832SPeter Avalos      * leave it intact.
4805382d832SPeter Avalos      *
4815382d832SPeter Avalos      * FIXME: the gutter width and name/list ratio should be configurable.
4825382d832SPeter Avalos      */
4835382d832SPeter Avalos     use_width = (all.menu_width - GUTTER);
4845382d832SPeter Avalos     if (dialog_vars.no_tags) {
4855382d832SPeter Avalos 	list_width = MIN(use_width, text_width);
4865382d832SPeter Avalos     } else if (dialog_vars.no_items) {
4875382d832SPeter Avalos 	list_width = MIN(use_width, name_width);
4885382d832SPeter Avalos     } else {
4895382d832SPeter Avalos 	if (text_width >= 0
4905382d832SPeter Avalos 	    && name_width >= 0
4915382d832SPeter Avalos 	    && use_width > 0
4925382d832SPeter Avalos 	    && text_width + name_width > use_width) {
4935382d832SPeter Avalos 	    int need = (int) (0.30 * use_width);
4945382d832SPeter Avalos 	    if (name_width > need) {
4955382d832SPeter Avalos 		int want = (int) (use_width
4965382d832SPeter Avalos 				  * ((double) name_width)
4975382d832SPeter Avalos 				  / (text_width + name_width));
4985382d832SPeter Avalos 		name_width = (want > need) ? want : need;
4995382d832SPeter Avalos 	    }
5005382d832SPeter Avalos 	    text_width = use_width - name_width;
5015382d832SPeter Avalos 	}
5025382d832SPeter Avalos 	list_width = (text_width + name_width);
5035382d832SPeter Avalos     }
5045382d832SPeter Avalos 
5055382d832SPeter Avalos     all.tag_x = (is_inputmenu
5065382d832SPeter Avalos 		 ? 0
5075382d832SPeter Avalos 		 : (use_width - list_width) / 2);
5085382d832SPeter Avalos     all.item_x = ((dialog_vars.no_tags
5095382d832SPeter Avalos 		   ? 0
5105382d832SPeter Avalos 		   : (dialog_vars.no_items
5115382d832SPeter Avalos 		      ? 0
5125382d832SPeter Avalos 		      : (GUTTER + name_width)))
5135382d832SPeter Avalos 		  + all.tag_x);
5145382d832SPeter Avalos 
5155382d832SPeter Avalos     if (choice - scrollamt >= max_choice) {
5165382d832SPeter Avalos 	scrollamt = choice - (max_choice - 1);
5175382d832SPeter Avalos 	choice = max_choice - 1;
5185382d832SPeter Avalos     }
519*a8e38dc0SAntonio Huete Jimenez #define PrintMenu() \
520*a8e38dc0SAntonio Huete Jimenez     print_menu(&all, choice, scrollamt, max_choice, item_no, is_inputmenu)
521*a8e38dc0SAntonio Huete Jimenez     PrintMenu();
5225382d832SPeter Avalos 
5235382d832SPeter Avalos     /* register the new window, along with its borders */
5245382d832SPeter Avalos     dlg_mouse_mkbigregion(all.box_y + 1, all.box_x,
5255382d832SPeter Avalos 			  all.menu_height + 2, all.menu_width + 2,
5265382d832SPeter Avalos 			  KEY_MAX, 1, 1, 1 /* by lines */ );
5275382d832SPeter Avalos 
5285382d832SPeter Avalos     dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
5295382d832SPeter Avalos 
5305382d832SPeter Avalos     dlg_trace_win(dialog);
5315940c9abSDaniel Fojt 
5325382d832SPeter Avalos     while (result == DLG_EXIT_UNKNOWN) {
5335940c9abSDaniel Fojt 	int key, found;
5345940c9abSDaniel Fojt 
5355382d832SPeter Avalos 	if (button < 0)		/* --visit-items */
5365382d832SPeter Avalos 	    wmove(dialog,
5375382d832SPeter Avalos 		  all.box_y + ItemToRow(choice) + 1,
5385382d832SPeter Avalos 		  all.box_x + all.tag_x + 1);
5395382d832SPeter Avalos 
5405382d832SPeter Avalos 	key = dlg_mouse_wgetch(dialog, &fkey);
5415940c9abSDaniel Fojt 	if (dlg_result_key(key, fkey, &result)) {
5425940c9abSDaniel Fojt 	    if (!dlg_button_key(result, &button, &key, &fkey))
5435382d832SPeter Avalos 		break;
5445940c9abSDaniel Fojt 	}
5455382d832SPeter Avalos 
5465382d832SPeter Avalos 	found = FALSE;
5475382d832SPeter Avalos 	if (fkey) {
5485382d832SPeter Avalos 	    /*
5495382d832SPeter Avalos 	     * Allow a mouse-click on a box to switch selection to that box.
5505382d832SPeter Avalos 	     * Handling a button click is a little more complicated, since we
5515382d832SPeter Avalos 	     * push a KEY_ENTER back onto the input stream so we'll put the
5525382d832SPeter Avalos 	     * cursor at the right place before handling the "keypress".
5535382d832SPeter Avalos 	     */
5545382d832SPeter Avalos 	    if (key >= DLGK_MOUSE(KEY_MAX)) {
5555382d832SPeter Avalos 		key -= DLGK_MOUSE(KEY_MAX);
5565382d832SPeter Avalos 		i = RowToItem(key);
5575382d832SPeter Avalos 		if (i < max_choice) {
5585382d832SPeter Avalos 		    found = TRUE;
5595382d832SPeter Avalos 		} else {
5605382d832SPeter Avalos 		    beep();
5615382d832SPeter Avalos 		    continue;
5625382d832SPeter Avalos 		}
5635382d832SPeter Avalos 	    } else if (is_DLGK_MOUSE(key)
5645382d832SPeter Avalos 		       && dlg_ok_buttoncode(key - M_EVENT) >= 0) {
5655382d832SPeter Avalos 		button = (key - M_EVENT);
5665382d832SPeter Avalos 		ungetch('\n');
5675382d832SPeter Avalos 		continue;
5685382d832SPeter Avalos 	    }
5695382d832SPeter Avalos 	} else {
5705382d832SPeter Avalos 	    /*
5715382d832SPeter Avalos 	     * Check if key pressed matches first character of any item tag in
5725382d832SPeter Avalos 	     * list.  If there is more than one match, we will cycle through
5735382d832SPeter Avalos 	     * each one as the same key is pressed repeatedly.
5745382d832SPeter Avalos 	     */
5755382d832SPeter Avalos 	    if (button < 0 || !dialog_state.visit_items) {
5765382d832SPeter Avalos 		for (j = scrollamt + choice + 1; j < item_no; j++) {
5775382d832SPeter Avalos 		    if (check_hotkey(items, j)) {
5785382d832SPeter Avalos 			found = TRUE;
5795382d832SPeter Avalos 			i = j - scrollamt;
5805382d832SPeter Avalos 			break;
5815382d832SPeter Avalos 		    }
5825382d832SPeter Avalos 		}
5835382d832SPeter Avalos 		if (!found) {
5845382d832SPeter Avalos 		    for (j = 0; j <= scrollamt + choice; j++) {
5855382d832SPeter Avalos 			if (check_hotkey(items, j)) {
5865382d832SPeter Avalos 			    found = TRUE;
5875382d832SPeter Avalos 			    i = j - scrollamt;
5885382d832SPeter Avalos 			    break;
5895382d832SPeter Avalos 			}
5905382d832SPeter Avalos 		    }
5915382d832SPeter Avalos 		}
5925382d832SPeter Avalos 		if (found)
5935382d832SPeter Avalos 		    dlg_flush_getc();
5945382d832SPeter Avalos 	    } else if ((j = dlg_char_to_button(key, buttons)) >= 0) {
5955382d832SPeter Avalos 		button = j;
5965382d832SPeter Avalos 		ungetch('\n');
5975382d832SPeter Avalos 		continue;
5985382d832SPeter Avalos 	    }
5995382d832SPeter Avalos 
6005382d832SPeter Avalos 	    /*
6015382d832SPeter Avalos 	     * A single digit (1-9) positions the selection to that line in the
6025382d832SPeter Avalos 	     * current screen.
6035382d832SPeter Avalos 	     */
6045382d832SPeter Avalos 	    if (!found
6055382d832SPeter Avalos 		&& (key <= '9')
6065382d832SPeter Avalos 		&& (key > '0')
6075382d832SPeter Avalos 		&& (key - '1' < max_choice)) {
6085382d832SPeter Avalos 		found = TRUE;
6095382d832SPeter Avalos 		i = key - '1';
6105382d832SPeter Avalos 	    }
6115382d832SPeter Avalos 	}
6125382d832SPeter Avalos 
6135382d832SPeter Avalos 	if (!found && fkey) {
6145382d832SPeter Avalos 	    found = TRUE;
6155382d832SPeter Avalos 	    switch (key) {
6165382d832SPeter Avalos 	    case DLGK_PAGE_FIRST:
6175382d832SPeter Avalos 		i = -scrollamt;
6185382d832SPeter Avalos 		break;
6195382d832SPeter Avalos 	    case DLGK_PAGE_LAST:
6205382d832SPeter Avalos 		i = item_no - 1 - scrollamt;
6215382d832SPeter Avalos 		break;
6225382d832SPeter Avalos 	    case DLGK_MOUSE(KEY_PPAGE):
6235382d832SPeter Avalos 	    case DLGK_PAGE_PREV:
6245382d832SPeter Avalos 		if (choice)
6255382d832SPeter Avalos 		    i = 0;
6265382d832SPeter Avalos 		else if (scrollamt != 0)
6275382d832SPeter Avalos 		    i = -MIN(scrollamt, max_choice);
6285382d832SPeter Avalos 		else
6295382d832SPeter Avalos 		    continue;
6305382d832SPeter Avalos 		break;
6315382d832SPeter Avalos 	    case DLGK_MOUSE(KEY_NPAGE):
6325382d832SPeter Avalos 	    case DLGK_PAGE_NEXT:
6335382d832SPeter Avalos 		i = MIN(choice + max_choice, item_no - scrollamt - 1);
6345382d832SPeter Avalos 		break;
6355382d832SPeter Avalos 	    case DLGK_ITEM_PREV:
6365382d832SPeter Avalos 		i = choice - 1;
6375382d832SPeter Avalos 		if (choice == 0 && scrollamt == 0)
6385382d832SPeter Avalos 		    continue;
6395382d832SPeter Avalos 		break;
6405382d832SPeter Avalos 	    case DLGK_ITEM_NEXT:
6415382d832SPeter Avalos 		i = choice + 1;
6425382d832SPeter Avalos 		if (scrollamt + choice >= item_no - 1)
6435382d832SPeter Avalos 		    continue;
6445382d832SPeter Avalos 		break;
6455382d832SPeter Avalos 	    default:
6465382d832SPeter Avalos 		found = FALSE;
6475382d832SPeter Avalos 		break;
6485382d832SPeter Avalos 	    }
6495382d832SPeter Avalos 	}
6505382d832SPeter Avalos 
6515382d832SPeter Avalos 	if (found) {
6525382d832SPeter Avalos 	    if (i != choice) {
6535382d832SPeter Avalos 		getyx(dialog, cur_y, cur_x);
6545382d832SPeter Avalos 		if (i < 0 || i >= max_choice) {
6555382d832SPeter Avalos 		    if (i < 0) {
6565382d832SPeter Avalos 			scrollamt += i;
6575382d832SPeter Avalos 			choice = 0;
6585382d832SPeter Avalos 		    } else {
6595382d832SPeter Avalos 			choice = max_choice - 1;
6605382d832SPeter Avalos 			scrollamt += (i - max_choice + 1);
6615382d832SPeter Avalos 		    }
662*a8e38dc0SAntonio Huete Jimenez 		    PrintMenu();
6635382d832SPeter Avalos 		} else {
6645382d832SPeter Avalos 		    choice = i;
665*a8e38dc0SAntonio Huete Jimenez 		    PrintMenu();
6665382d832SPeter Avalos 		    (void) wmove(dialog, cur_y, cur_x);
6675382d832SPeter Avalos 		    wrefresh(dialog);
6685382d832SPeter Avalos 		}
6695382d832SPeter Avalos 	    }
6705382d832SPeter Avalos 	    continue;		/* wait for another key press */
6715382d832SPeter Avalos 	}
6725382d832SPeter Avalos 
6735382d832SPeter Avalos 	if (fkey) {
6745382d832SPeter Avalos 	    switch (key) {
6755382d832SPeter Avalos 	    case DLGK_FIELD_PREV:
6765382d832SPeter Avalos 		button = dlg_prev_button(buttons, button);
6775382d832SPeter Avalos 		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
6785382d832SPeter Avalos 				 FALSE, width);
6795382d832SPeter Avalos 		break;
680*a8e38dc0SAntonio Huete Jimenez 
6815382d832SPeter Avalos 	    case DLGK_FIELD_NEXT:
6825382d832SPeter Avalos 		button = dlg_next_button(buttons, button);
6835382d832SPeter Avalos 		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
6845382d832SPeter Avalos 				 FALSE, width);
6855382d832SPeter Avalos 		break;
686*a8e38dc0SAntonio Huete Jimenez 
6875940c9abSDaniel Fojt 	    case DLGK_TOGGLE:
6885382d832SPeter Avalos 	    case DLGK_ENTER:
689*a8e38dc0SAntonio Huete Jimenez 	    case DLGK_LEAVE:
690*a8e38dc0SAntonio Huete Jimenez 		result = ((key == DLGK_LEAVE)
691*a8e38dc0SAntonio Huete Jimenez 			  ? dlg_ok_buttoncode(button)
692*a8e38dc0SAntonio Huete Jimenez 			  : dlg_enter_buttoncode(button));
6935382d832SPeter Avalos 
6945382d832SPeter Avalos 		/*
6955382d832SPeter Avalos 		 * If dlg_menu() is called from dialog_menu(), we want to
6965382d832SPeter Avalos 		 * capture the results into dialog_vars.input_result.
6975382d832SPeter Avalos 		 */
6985382d832SPeter Avalos 		if (result == DLG_EXIT_ERROR) {
6995382d832SPeter Avalos 		    result = DLG_EXIT_UNKNOWN;
7005382d832SPeter Avalos 		} else if (is_inputmenu
7015382d832SPeter Avalos 			   || rename_menutext == dlg_dummy_menutext) {
7025382d832SPeter Avalos 		    result = handle_button(result,
7035382d832SPeter Avalos 					   items,
7045382d832SPeter Avalos 					   scrollamt + choice);
7055382d832SPeter Avalos 		}
7065382d832SPeter Avalos 
7075382d832SPeter Avalos 		/*
7085382d832SPeter Avalos 		 * If we have a rename_menutext function, interpret the Extra
7095382d832SPeter Avalos 		 * button as a request to rename the menu's text.  If that
7105382d832SPeter Avalos 		 * function doesn't return "Unknown", we will exit from this
7115382d832SPeter Avalos 		 * function.  Usually that is done for dialog_menu(), so the
7125382d832SPeter Avalos 		 * shell script can use the updated value.  If it does return
7135382d832SPeter Avalos 		 * "Unknown", update the list item only.  A direct caller of
7145382d832SPeter Avalos 		 * dlg_menu() can free the renamed value - we cannot.
7155382d832SPeter Avalos 		 */
7165382d832SPeter Avalos 		if (is_inputmenu && result == DLG_EXIT_EXTRA) {
7175382d832SPeter Avalos 		    char *tmp;
7185382d832SPeter Avalos 
7195382d832SPeter Avalos 		    if (input_menu_edit(&all,
7205382d832SPeter Avalos 					&items[scrollamt + choice],
7215382d832SPeter Avalos 					choice,
7225382d832SPeter Avalos 					&tmp)) {
7235382d832SPeter Avalos 			result = rename_menutext(items, scrollamt + choice, tmp);
7245382d832SPeter Avalos 			if (result == DLG_EXIT_UNKNOWN) {
7255382d832SPeter Avalos 			    items[scrollamt + choice].text = tmp;
7265382d832SPeter Avalos 			} else {
7275382d832SPeter Avalos 			    free(tmp);
7285382d832SPeter Avalos 			}
7295382d832SPeter Avalos 		    } else {
7305382d832SPeter Avalos 			result = DLG_EXIT_UNKNOWN;
7315382d832SPeter Avalos 			print_item(&all,
7325382d832SPeter Avalos 				   menu,
7335382d832SPeter Avalos 				   &items[scrollamt + choice],
7345382d832SPeter Avalos 				   choice,
7355382d832SPeter Avalos 				   Selected,
7365382d832SPeter Avalos 				   is_inputmenu);
7375382d832SPeter Avalos 			(void) wnoutrefresh(menu);
7385382d832SPeter Avalos 			free(tmp);
7395382d832SPeter Avalos 		    }
7405382d832SPeter Avalos 
7415382d832SPeter Avalos 		    if (result == DLG_EXIT_UNKNOWN) {
7425382d832SPeter Avalos 			dlg_draw_buttons(dialog, height - 2, 0,
7435382d832SPeter Avalos 					 buttons, button, FALSE, width);
7445382d832SPeter Avalos 		    }
7455382d832SPeter Avalos 		}
7465382d832SPeter Avalos 		break;
7475382d832SPeter Avalos #ifdef KEY_RESIZE
7485382d832SPeter Avalos 	    case KEY_RESIZE:
7495940c9abSDaniel Fojt 		dlg_will_resize(dialog);
7505382d832SPeter Avalos 		/* reset data */
7515940c9abSDaniel Fojt 		resizeit(height, LINES);
7525940c9abSDaniel Fojt 		resizeit(width, COLS);
7535940c9abSDaniel Fojt 		free(prompt);
7545940c9abSDaniel Fojt 		_dlg_resize_cleanup(dialog);
755*a8e38dc0SAntonio Huete Jimenez 		dlg_unregister_window(menu);
756*a8e38dc0SAntonio Huete Jimenez 		dlg_unregister_window(dialog);
757*a8e38dc0SAntonio Huete Jimenez 		/* keep position */
758*a8e38dc0SAntonio Huete Jimenez 		choice += scrollamt;
759*a8e38dc0SAntonio Huete Jimenez 		scrollamt = 0;
7605382d832SPeter Avalos 		/* repaint */
7615382d832SPeter Avalos 		goto retry;
7625382d832SPeter Avalos #endif
7635382d832SPeter Avalos 	    default:
7645382d832SPeter Avalos 		flash();
7655382d832SPeter Avalos 		break;
7665382d832SPeter Avalos 	    }
7675382d832SPeter Avalos 	}
7685382d832SPeter Avalos     }
7695382d832SPeter Avalos 
7705382d832SPeter Avalos     dlg_mouse_free_regions();
7715382d832SPeter Avalos     dlg_unregister_window(menu);
7725382d832SPeter Avalos     dlg_del_window(dialog);
7735382d832SPeter Avalos     free(prompt);
7745382d832SPeter Avalos 
7755382d832SPeter Avalos     *current_item = scrollamt + choice;
7765940c9abSDaniel Fojt 
7775940c9abSDaniel Fojt     DLG_TRACE2N("current", *current_item);
7785382d832SPeter Avalos     return result;
7795382d832SPeter Avalos }
7805382d832SPeter Avalos 
7815382d832SPeter Avalos /*
7825382d832SPeter Avalos  * Display a menu for choosing among a number of options
7835382d832SPeter Avalos  */
7845382d832SPeter Avalos int
dialog_menu(const char * title,const char * cprompt,int height,int width,int menu_height,int item_no,char ** items)7855382d832SPeter Avalos dialog_menu(const char *title,
7865382d832SPeter Avalos 	    const char *cprompt,
7875382d832SPeter Avalos 	    int height,
7885382d832SPeter Avalos 	    int width,
7895382d832SPeter Avalos 	    int menu_height,
7905382d832SPeter Avalos 	    int item_no,
7915382d832SPeter Avalos 	    char **items)
7925382d832SPeter Avalos {
7935382d832SPeter Avalos     int result;
7945382d832SPeter Avalos     int choice;
7955382d832SPeter Avalos     int i, j;
7965382d832SPeter Avalos     DIALOG_LISTITEM *listitems;
7975382d832SPeter Avalos 
7985382d832SPeter Avalos     listitems = dlg_calloc(DIALOG_LISTITEM, (size_t) item_no + 1);
7995382d832SPeter Avalos     assert_ptr(listitems, "dialog_menu");
8005382d832SPeter Avalos 
8015382d832SPeter Avalos     for (i = j = 0; i < item_no; ++i) {
8025382d832SPeter Avalos 	listitems[i].name = items[j++];
8035382d832SPeter Avalos 	listitems[i].text = (dialog_vars.no_items
8045382d832SPeter Avalos 			     ? dlg_strempty()
8055382d832SPeter Avalos 			     : items[j++]);
8065382d832SPeter Avalos 	listitems[i].help = ((dialog_vars.item_help)
8075382d832SPeter Avalos 			     ? items[j++]
8085382d832SPeter Avalos 			     : dlg_strempty());
8095382d832SPeter Avalos     }
8105382d832SPeter Avalos     dlg_align_columns(&listitems[0].text, sizeof(DIALOG_LISTITEM), item_no);
8115382d832SPeter Avalos 
8125382d832SPeter Avalos     result = dlg_menu(title,
8135382d832SPeter Avalos 		      cprompt,
8145382d832SPeter Avalos 		      height,
8155382d832SPeter Avalos 		      width,
8165382d832SPeter Avalos 		      menu_height,
8175382d832SPeter Avalos 		      item_no,
8185382d832SPeter Avalos 		      listitems,
8195382d832SPeter Avalos 		      &choice,
8205382d832SPeter Avalos 		      (dialog_vars.input_menu
8215382d832SPeter Avalos 		       ? dlg_renamed_menutext
8225382d832SPeter Avalos 		       : dlg_dummy_menutext));
8235382d832SPeter Avalos 
8245382d832SPeter Avalos     dlg_free_columns(&listitems[0].text, sizeof(DIALOG_LISTITEM), item_no);
8255382d832SPeter Avalos     free(listitems);
8265382d832SPeter Avalos     return result;
8275382d832SPeter Avalos }
828