curses menu revision

Redo menu sizing to eliminate one of the analyzer hacks.  There's no
need to loop through the menu entries a second time to find the last
one.  The first time can remember it.

Also, some routines were taking arguments with
 some_function(WINDOW *win, nhmenu *menu, ...)
and others with
 other_function(nhmenu *menu, WINDOW *win, ...).
Change them all to have the window pointer 1st and menu pointer 2nd.
This commit is contained in:
PatR
2023-12-29 18:16:14 -08:00
parent 9d32956616
commit d4dfb1765c
2 changed files with 51 additions and 42 deletions

View File

@@ -68,25 +68,27 @@ typedef enum menu_op_type {
INVERT INVERT
} menu_op; } menu_op;
static nhmenu_item *curs_new_menu_item(winid, const char *); static nhmenu_item *curs_new_menu_item(winid, const char *) NONNULL;
static void curs_pad_menu(nhmenu *, boolean); static void curs_pad_menu(nhmenu *, boolean) NONNULLARG1;
static nhmenu *get_menu(winid wid); static nhmenu *get_menu(winid wid); /* might return Null */
static char menu_get_accel(boolean first); static char menu_get_accel(boolean first);
static void menu_determine_pages(nhmenu *menu); static void menu_determine_pages(nhmenu *menu) NONNULLARG1;
static boolean menu_is_multipage(nhmenu *menu, int width, int height); static boolean menu_is_multipage(nhmenu *menu, int width,
static void menu_win_size(nhmenu *menu); int height) NONNULLARG1;
static void menu_win_size(nhmenu *menu) NONNULLARG1;
#ifdef NCURSES_MOUSE_VERSION #ifdef NCURSES_MOUSE_VERSION
static nhmenu_item *get_menuitem_y(nhmenu *menu, WINDOW *win UNUSED, static nhmenu_item *get_menuitem_y(WINDOW *win UNUSED, nhmenu *menu,
int page_num, int liney); int page_num, int liney) NONNULLARG12;
#endif /*NCURSES_MOUSE_VERSION*/ #endif /*NCURSES_MOUSE_VERSION*/
static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num, static void menu_display_page(WINDOW *win, nhmenu *menu, int page_num,
char *, char *); char *, char *) NONNULLARG12;
static int menu_get_selections(WINDOW *win, nhmenu *menu, int how); static int menu_get_selections(WINDOW *win, nhmenu *menu,
int how) NONNULLARG12;
static void menu_select_deselect(WINDOW *win, nhmenu_item *item, static void menu_select_deselect(WINDOW *win, nhmenu_item *item,
menu_op operation, int); menu_op operation, int) NONNULLARG12;
static int menu_operation(WINDOW *win, nhmenu *menu, menu_op operation, static int menu_operation(WINDOW *win, nhmenu *menu, menu_op operation,
int page_num); int page_num) NONNULLARG12;
static void menu_clear_selections(nhmenu *menu); static void menu_clear_selections(nhmenu *menu) NONNULLARG1;
static int menu_max_height(void); static int menu_max_height(void);
static nhmenu *nhmenus = NULL; /* NetHack menu array */ static nhmenu *nhmenus = NULL; /* NetHack menu array */
@@ -248,7 +250,7 @@ curses_character_input_dialog(
choicestr[count + 2] = choices[count]; choicestr[count + 2] = choices[count];
} }
choicestr[count + 2] = ']'; choicestr[count + 2] = ']';
if (((def >= 'A') && (def <= 'Z')) || ((def >= 'a') && (def <= 'z'))) { if ((def >= 'A' && def <= 'Z') || (def >= 'a' && def <= 'z')) {
choicestr[count + 3] = ' '; choicestr[count + 3] = ' ';
choicestr[count + 4] = '('; choicestr[count + 4] = '(';
choicestr[count + 5] = def; choicestr[count + 5] = def;
@@ -700,6 +702,7 @@ curs_menu_set_bottom_heavy(winid wid)
{ {
nhmenu *menu = get_menu(wid); nhmenu *menu = get_menu(wid);
assert(menu != NULL); /* only called when 'wid' is a menu */
/* /*
* Called after end_menu + finalize_nhmenu, * Called after end_menu + finalize_nhmenu,
* before select_menu + display_nhmenu. * before select_menu + display_nhmenu.
@@ -1020,7 +1023,7 @@ menu_win_size(nhmenu *menu)
int maxwidth, maxheight, curentrywidth, lastline; int maxwidth, maxheight, curentrywidth, lastline;
int maxentrywidth = 0; int maxentrywidth = 0;
int maxheaderwidth = menu->prompt ? (int) strlen(menu->prompt) : 0; int maxheaderwidth = menu->prompt ? (int) strlen(menu->prompt) : 0;
nhmenu_item *menu_item_ptr; nhmenu_item *menu_item_ptr, *last_item_ptr = NULL;
if (gp.program_state.gameover) { if (gp.program_state.gameover) {
/* for final inventory disclosure, use full width */ /* for final inventory disclosure, use full width */
@@ -1039,6 +1042,7 @@ menu_win_size(nhmenu *menu)
maxheight = menu_max_height(); maxheight = menu_max_height();
/* First, determine the width of the longest menu entry */ /* First, determine the width of the longest menu entry */
assert(menu->entries != NULL); /* at least one iteration will occur */
for (menu_item_ptr = menu->entries; menu_item_ptr != NULL; for (menu_item_ptr = menu->entries; menu_item_ptr != NULL;
menu_item_ptr = menu_item_ptr->next_item) { menu_item_ptr = menu_item_ptr->next_item) {
curentrywidth = (int) strlen(menu_item_ptr->str); curentrywidth = (int) strlen(menu_item_ptr->str);
@@ -1058,6 +1062,9 @@ menu_win_size(nhmenu *menu)
if (curentrywidth > maxentrywidth) { if (curentrywidth > maxentrywidth) {
maxentrywidth = curentrywidth; maxentrywidth = curentrywidth;
} }
/* might need this later */
last_item_ptr = menu_item_ptr;
} }
/* /*
@@ -1076,18 +1083,15 @@ menu_win_size(nhmenu *menu)
maxwidth = term_cols - 2; maxwidth = term_cols - 2;
} }
/* Possibly reduce height if only 1 page */ /* Possibly reduce height if only 1 page.
Note: menu_is_multipage() populates entry->line_num and
entry->num_lines for all the menu's entries. */
if (!menu_is_multipage(menu, maxwidth, maxheight)) { if (!menu_is_multipage(menu, maxwidth, maxheight)) {
if ((menu_item_ptr = menu->entries) != 0) { assert(last_item_ptr != NULL);
while (menu_item_ptr->next_item != NULL) { lastline = last_item_ptr->line_num + last_item_ptr->num_lines;
menu_item_ptr = menu_item_ptr->next_item;
}
lastline = (menu_item_ptr->line_num) + menu_item_ptr->num_lines; if (lastline < maxheight) {
maxheight = lastline;
if (lastline < maxheight) {
maxheight = lastline;
}
} }
} }
@@ -1104,8 +1108,8 @@ menu_win_size(nhmenu *menu)
#ifdef NCURSES_MOUSE_VERSION #ifdef NCURSES_MOUSE_VERSION
static nhmenu_item * static nhmenu_item *
get_menuitem_y( get_menuitem_y(
nhmenu *menu,
WINDOW *win UNUSED, WINDOW *win UNUSED,
nhmenu *menu,
int page_num, int page_num,
int liney) int liney)
{ {
@@ -1168,7 +1172,8 @@ extern color_attr curses_menu_promptstyle; /*cursmain.c */
static void static void
menu_display_page( menu_display_page(
nhmenu *menu, WINDOW *win, WINDOW *win,
nhmenu *menu,
int page_num, /* page number, 1..n rather than 0..n-1 */ int page_num, /* page number, 1..n rather than 0..n-1 */
char *selectors, /* selection letters on current page */ char *selectors, /* selection letters on current page */
char *groupaccels) /* group accelerator characters on any page */ char *groupaccels) /* group accelerator characters on any page */
@@ -1338,10 +1343,12 @@ menu_display_page(
} }
/* split out from menu_get_selections() so that perm_invent scrolling /* split out from menu_get_selections() so that perm_invent scrolling
can be controlled from outside the normal menu activity */ can be controlled from outside the normal menu activity [groundwork;
ultimately not used that way, only from menu_get_seletions() itself] */
boolean boolean
curs_nonselect_menu_action( curs_nonselect_menu_action(
WINDOW *win, void *menu_v, WINDOW *win,
void *menu_v, /* generic pointer; caller might not know type 'nhmenu' */
int how, int how,
int curletter, int curletter,
int *curpage_p, int *curpage_p,
@@ -1371,7 +1378,7 @@ curs_nonselect_menu_action(
if (wmouse_trafo(win, &mev.y, &mev.x, FALSE)) { if (wmouse_trafo(win, &mev.y, &mev.x, FALSE)) {
int y = mev.y; int y = mev.y;
menu_item_ptr = get_menuitem_y(menu, win, *curpage_p, y); menu_item_ptr = get_menuitem_y(win, menu, *curpage_p, y);
if (menu_item_ptr) { if (menu_item_ptr) {
if (how == PICK_ONE) { if (how == PICK_ONE) {
@@ -1396,7 +1403,7 @@ curs_nonselect_menu_action(
case ' ': case ' ':
if (*curpage_p < menu->num_pages) { if (*curpage_p < menu->num_pages) {
++(*curpage_p); ++(*curpage_p);
menu_display_page(menu, win, *curpage_p, selectors, (char *) 0); menu_display_page(win, menu, *curpage_p, selectors, (char *) 0);
} else if (menucmd == ' ') { } else if (menucmd == ' ') {
dismiss = TRUE; dismiss = TRUE;
break; break;
@@ -1407,21 +1414,21 @@ curs_nonselect_menu_action(
case MENU_PREVIOUS_PAGE: case MENU_PREVIOUS_PAGE:
if (*curpage_p > 1) { if (*curpage_p > 1) {
--(*curpage_p); --(*curpage_p);
menu_display_page(menu, win, *curpage_p, selectors, (char *) 0); menu_display_page(win, menu, *curpage_p, selectors, (char *) 0);
} }
break; break;
case KEY_END: case KEY_END:
case MENU_LAST_PAGE: case MENU_LAST_PAGE:
if (*curpage_p != menu->num_pages) { if (*curpage_p != menu->num_pages) {
*curpage_p = menu->num_pages; *curpage_p = menu->num_pages;
menu_display_page(menu, win, *curpage_p, selectors, (char *) 0); menu_display_page(win, menu, *curpage_p, selectors, (char *) 0);
} }
break; break;
case KEY_HOME: case KEY_HOME:
case MENU_FIRST_PAGE: case MENU_FIRST_PAGE:
if (*curpage_p != 1) { if (*curpage_p != 1) {
*curpage_p = 1; *curpage_p = 1;
menu_display_page(menu, win, *curpage_p, selectors, (char *) 0); menu_display_page(win, menu, *curpage_p, selectors, (char *) 0);
} }
break; break;
case MENU_SEARCH: { case MENU_SEARCH: {
@@ -1484,7 +1491,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
nhmenu_item *menu_item_ptr = menu->entries; nhmenu_item *menu_item_ptr = menu->entries;
activemenu = win; activemenu = win;
menu_display_page(menu, win, curpage, selectors, groupaccels); menu_display_page(win, menu, curpage, selectors, groupaccels);
while (!dismiss) { while (!dismiss) {
curletter = curses_getch(); curletter = curses_getch();
@@ -1574,7 +1581,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
&& curletter == menu_item_ptr->group_accel)) { && curletter == menu_item_ptr->group_accel)) {
if (curpage != menu_item_ptr->page_num) { if (curpage != menu_item_ptr->page_num) {
curpage = menu_item_ptr->page_num; curpage = menu_item_ptr->page_num;
menu_display_page(menu, win, curpage, selectors, menu_display_page(win, menu, curpage, selectors,
(char *) 0); (char *) 0);
} }
@@ -1693,7 +1700,7 @@ menu_operation(
current_page = first_page; current_page = first_page;
if (page_num == 0) { if (page_num == 0) {
menu_display_page(menu, win, current_page, (char *) 0, (char *) 0); menu_display_page(win, menu, current_page, (char *) 0, (char *) 0);
} }
if (menu_item_ptr == NULL) { /* Page not found */ if (menu_item_ptr == NULL) { /* Page not found */
@@ -1708,7 +1715,7 @@ menu_operation(
} }
current_page = menu_item_ptr->page_num; current_page = menu_item_ptr->page_num;
menu_display_page(menu, win, current_page, (char *) 0, (char *) 0); menu_display_page(win, menu, current_page, (char *) 0, (char *) 0);
} }
if (menu_item_ptr->identifier.a_void != NULL) { if (menu_item_ptr->identifier.a_void != NULL) {

View File

@@ -8,9 +8,10 @@
/* Global declarations */ /* Global declarations */
void curses_line_input_dialog(const char *prompt, char *answer, int buffer); void curses_line_input_dialog(const char *prompt, char *answer,
int buffer) NONNULLPTRS;
int curses_character_input_dialog(const char *prompt, const char *choices, int curses_character_input_dialog(const char *prompt, const char *choices,
char def); char def) NONNULLARG1;
int curses_ext_cmd(void); int curses_ext_cmd(void);
void curses_create_nhmenu(winid wid, unsigned long); void curses_create_nhmenu(winid wid, unsigned long);
void curses_add_nhmenu_item(winid wid, const glyph_info *glyphinfo, void curses_add_nhmenu_item(winid wid, const glyph_info *glyphinfo,
@@ -24,6 +25,7 @@ boolean curses_menu_exists(winid wid);
void curses_del_menu(winid, boolean); void curses_del_menu(winid, boolean);
boolean curs_nonselect_menu_action(WINDOW *win, void *menu, int how, boolean curs_nonselect_menu_action(WINDOW *win, void *menu, int how,
int curletter, int *curpage_p, int curletter, int *curpage_p,
char selectors[256], int *num_selected_p); char selectors[256], int *num_selected_p)
NONNULLPTRS;
#endif /* CURSDIAL_H */ #endif /* CURSDIAL_H */