fix github issue #193 - curses: menu search

Fixes #193

Under curses interface, make characters which are both entry selectors
and menu commands function as a selector.  Needed to support using ':'
to look inside a container when applying/looting it via menu, instead
of performing a menu search operation.  (There was another case like
this but I can't remember what the circumstances are.  The fix is
general enough to cover it, whatever it is.)

For menus which don't have ':' as a choice, make sure search prompt
doesn't offer garbage default input when built with EDIT_GETLIN.

Bug?  If player has 'popup_dialog' option On, EDIT_GETLIN is ignored.
Plain curses I/O doesn't seem to offer a way to implement it.
This commit is contained in:
PatR
2019-05-31 10:11:45 -07:00
parent a09973851e
commit cdb4a9e8b3
2 changed files with 113 additions and 100 deletions
+28 -16
View File
@@ -97,7 +97,8 @@ static char menu_get_accel(boolean first);
static void menu_determine_pages(nhmenu *menu); static void menu_determine_pages(nhmenu *menu);
static boolean menu_is_multipage(nhmenu *menu, int width, int height); static boolean menu_is_multipage(nhmenu *menu, int width, int height);
static void menu_win_size(nhmenu *menu); static void menu_win_size(nhmenu *menu);
static void menu_display_page(nhmenu *menu, WINDOW * win, int page_num); static void menu_display_page(nhmenu *menu, WINDOW * win, int page_num,
char *);
static int menu_get_selections(WINDOW * win, nhmenu *menu, int how); static int menu_get_selections(WINDOW * win, nhmenu *menu, int how);
static void menu_select_deselect(WINDOW * win, nhmenu_item *item, static void menu_select_deselect(WINDOW * win, nhmenu_item *item,
menu_op operation); menu_op operation);
@@ -116,7 +117,7 @@ static nhmenu *nhmenus = NULL; /* NetHack menu array */
/* Get a line of text from the player, such as asking for a character name /* Get a line of text from the player, such as asking for a character name
or a wish */ or a wish. Note: EDIT_GETLIN not supported for popup prompting. */
void void
curses_line_input_dialog(const char *prompt, char *answer, int buffer) curses_line_input_dialog(const char *prompt, char *answer, int buffer)
@@ -133,8 +134,8 @@ curses_line_input_dialog(const char *prompt, char *answer, int buffer)
re-activate them now that input is being requested */ re-activate them now that input is being requested */
curses_got_input(); curses_got_input();
if (buffer >= (int) sizeof input) if (buffer > (int) sizeof input)
buffer = (int) sizeof input - 1; buffer = (int) sizeof input;
maxwidth = term_cols - 2; maxwidth = term_cols - 2;
if (iflags.window_inited) { if (iflags.window_inited) {
@@ -1059,7 +1060,7 @@ menu_win_size(nhmenu *menu)
/* Displays menu selections in the given window */ /* Displays menu selections in the given window */
static void static void
menu_display_page(nhmenu *menu, WINDOW * win, int page_num) menu_display_page(nhmenu *menu, WINDOW * win, int page_num, char *selectors)
{ {
nhmenu_item *menu_item_ptr; nhmenu_item *menu_item_ptr;
int count, curletter, entry_cols, start_col, num_lines; int count, curletter, entry_cols, start_col, num_lines;
@@ -1068,6 +1069,10 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num)
int color = NO_COLOR, attr = A_NORMAL; int color = NO_COLOR, attr = A_NORMAL;
boolean menu_color = FALSE; boolean menu_color = FALSE;
/* letters assigned to entries on current page */
if (selectors)
(void) memset((genericptr_t) selectors, 0, 256);
/* Cycle through entries until we are on the correct page */ /* Cycle through entries until we are on the correct page */
menu_item_ptr = menu->entries; menu_item_ptr = menu->entries;
@@ -1117,6 +1122,9 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num)
} }
menu_item_ptr->accelerator = curletter; menu_item_ptr->accelerator = curletter;
} }
/* we have a selector letter; tell caller about it */
if (selectors)
selectors[(unsigned) (curletter & 0xFF)]++;
if (menu_item_ptr->selected) { if (menu_item_ptr->selected) {
curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, ON); curses_toggle_color_attr(win, HIGHLIGHT_COLOR, A_REVERSE, ON);
@@ -1222,10 +1230,10 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
int curpage = !menu->bottom_heavy ? 1 : menu->num_pages; int curpage = !menu->bottom_heavy ? 1 : menu->num_pages;
int num_selected = 0; int num_selected = 0;
boolean dismiss = FALSE; boolean dismiss = FALSE;
char search_key[BUFSZ]; char search_key[BUFSZ], selectors[256];
nhmenu_item *menu_item_ptr = menu->entries; nhmenu_item *menu_item_ptr = menu->entries;
menu_display_page(menu, win, curpage); menu_display_page(menu, win, curpage, selectors);
while (!dismiss) { while (!dismiss) {
curletter = getch(); curletter = getch();
@@ -1253,6 +1261,7 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
} }
break; break;
case PICK_ANY: case PICK_ANY:
if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
switch (curletter) { switch (curletter) {
case MENU_SELECT_PAGE: case MENU_SELECT_PAGE:
(void) menu_operation(win, menu, SELECT, curpage); (void) menu_operation(win, menu, SELECT, curpage);
@@ -1273,6 +1282,7 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
curpage = menu_operation(win, menu, INVERT, 0); curpage = menu_operation(win, menu, INVERT, 0);
break; break;
} }
}
/*FALLTHRU*/ /*FALLTHRU*/
default: default:
if (isdigit(curletter)) { if (isdigit(curletter)) {
@@ -1286,6 +1296,7 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
} }
} }
if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
switch (curletter) { switch (curletter) {
case KEY_ESC: case KEY_ESC:
num_selected = -1; num_selected = -1;
@@ -1301,7 +1312,7 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
case ' ': case ' ':
if (curpage < menu->num_pages) { if (curpage < menu->num_pages) {
curpage++; curpage++;
menu_display_page(menu, win, curpage); menu_display_page(menu, win, curpage, selectors);
} else if (curletter == ' ') { } else if (curletter == ' ') {
dismiss = TRUE; dismiss = TRUE;
break; break;
@@ -1312,33 +1323,33 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
case MENU_PREVIOUS_PAGE: case MENU_PREVIOUS_PAGE:
if (curpage > 1) { if (curpage > 1) {
curpage--; curpage--;
menu_display_page(menu, win, curpage); menu_display_page(menu, win, curpage, selectors);
} }
break; break;
case KEY_END: case KEY_END:
case MENU_LAST_PAGE: case MENU_LAST_PAGE:
if (curpage != menu->num_pages) { if (curpage != menu->num_pages) {
curpage = menu->num_pages; curpage = menu->num_pages;
menu_display_page(menu, win, curpage); menu_display_page(menu, win, curpage, selectors);
} }
break; break;
case KEY_HOME: case KEY_HOME:
case MENU_FIRST_PAGE: case MENU_FIRST_PAGE:
if (curpage != 1) { if (curpage != 1) {
curpage = 1; curpage = 1;
menu_display_page(menu, win, curpage); menu_display_page(menu, win, curpage, selectors);
} }
break; break;
case MENU_SEARCH: case MENU_SEARCH:
search_key[0] = '\0';
curses_line_input_dialog("Search for:", search_key, BUFSZ); curses_line_input_dialog("Search for:", search_key, BUFSZ);
refresh(); refresh();
touchwin(win); touchwin(win);
wrefresh(win); wrefresh(win);
if (!*search_key) { if (!*search_key)
break; break;
}
menu_item_ptr = menu->entries; menu_item_ptr = menu->entries;
@@ -1368,6 +1379,7 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
break; break;
} }
} }
}
menu_item_ptr = menu->entries; menu_item_ptr = menu->entries;
while (menu_item_ptr != NULL) { while (menu_item_ptr != NULL) {
@@ -1379,7 +1391,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); menu_display_page(menu, win, curpage, selectors);
} }
if (how == PICK_ONE) { if (how == PICK_ONE) {
@@ -1479,7 +1491,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op
current_page = first_page; current_page = first_page;
if (page_num == 0) { if (page_num == 0) {
menu_display_page(menu, win, current_page); menu_display_page(menu, win, current_page, (char *) 0);
} }
if (menu_item_ptr == NULL) { /* Page not found */ if (menu_item_ptr == NULL) { /* Page not found */
@@ -1494,7 +1506,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op
} }
current_page = menu_item_ptr->page_num; current_page = menu_item_ptr->page_num;
menu_display_page(menu, win, current_page); menu_display_page(menu, win, current_page, (char *) 0);
} }
if (menu_item_ptr->identifier.a_void != NULL) { if (menu_item_ptr->identifier.a_void != NULL) {
+1
View File
@@ -202,6 +202,7 @@ curses_player_selection()
void void
curses_askname() curses_askname()
{ {
plname[0] = '\0';
curses_line_input_dialog("Who are you?", plname, PL_NSIZ); curses_line_input_dialog("Who are you?", plname, PL_NSIZ);
} }