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
+44 -37
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,20 +1083,17 @@ 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) { if (lastline < maxheight) {
maxheight = lastline; maxheight = lastline;
} }
} }
}
/* avoid a tiny popup window; when it's shown over the endings of /* avoid a tiny popup window; when it's shown over the endings of
old messsages rather than over the map, it is fairly easy for old messsages rather than over the map, it is fairly easy for
@@ -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) {
+5 -3
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 */