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:
+112
-100
@@ -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,25 +1261,27 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PICK_ANY:
|
case PICK_ANY:
|
||||||
switch (curletter) {
|
if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
|
||||||
case MENU_SELECT_PAGE:
|
switch (curletter) {
|
||||||
(void) menu_operation(win, menu, SELECT, curpage);
|
case MENU_SELECT_PAGE:
|
||||||
break;
|
(void) menu_operation(win, menu, SELECT, curpage);
|
||||||
case MENU_SELECT_ALL:
|
break;
|
||||||
curpage = menu_operation(win, menu, SELECT, 0);
|
case MENU_SELECT_ALL:
|
||||||
break;
|
curpage = menu_operation(win, menu, SELECT, 0);
|
||||||
case MENU_UNSELECT_PAGE:
|
break;
|
||||||
(void) menu_operation(win, menu, DESELECT, curpage);
|
case MENU_UNSELECT_PAGE:
|
||||||
break;
|
(void) menu_operation(win, menu, DESELECT, curpage);
|
||||||
case MENU_UNSELECT_ALL:
|
break;
|
||||||
curpage = menu_operation(win, menu, DESELECT, 0);
|
case MENU_UNSELECT_ALL:
|
||||||
break;
|
curpage = menu_operation(win, menu, DESELECT, 0);
|
||||||
case MENU_INVERT_PAGE:
|
break;
|
||||||
(void) menu_operation(win, menu, INVERT, curpage);
|
case MENU_INVERT_PAGE:
|
||||||
break;
|
(void) menu_operation(win, menu, INVERT, curpage);
|
||||||
case MENU_INVERT_ALL:
|
break;
|
||||||
curpage = menu_operation(win, menu, INVERT, 0);
|
case MENU_INVERT_ALL:
|
||||||
break;
|
curpage = menu_operation(win, menu, INVERT, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*FALLTHRU*/
|
/*FALLTHRU*/
|
||||||
default:
|
default:
|
||||||
@@ -1286,86 +1296,88 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (curletter) {
|
if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
|
||||||
case KEY_ESC:
|
switch (curletter) {
|
||||||
num_selected = -1;
|
case KEY_ESC:
|
||||||
dismiss = TRUE;
|
num_selected = -1;
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
case '\r':
|
|
||||||
dismiss = TRUE;
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
case KEY_NPAGE:
|
|
||||||
case MENU_NEXT_PAGE:
|
|
||||||
case ' ':
|
|
||||||
if (curpage < menu->num_pages) {
|
|
||||||
curpage++;
|
|
||||||
menu_display_page(menu, win, curpage);
|
|
||||||
} else if (curletter == ' ') {
|
|
||||||
dismiss = TRUE;
|
dismiss = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
case '\n':
|
||||||
break;
|
case '\r':
|
||||||
case KEY_LEFT:
|
dismiss = TRUE;
|
||||||
case KEY_PPAGE:
|
|
||||||
case MENU_PREVIOUS_PAGE:
|
|
||||||
if (curpage > 1) {
|
|
||||||
curpage--;
|
|
||||||
menu_display_page(menu, win, curpage);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_END:
|
|
||||||
case MENU_LAST_PAGE:
|
|
||||||
if (curpage != menu->num_pages) {
|
|
||||||
curpage = menu->num_pages;
|
|
||||||
menu_display_page(menu, win, curpage);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_HOME:
|
|
||||||
case MENU_FIRST_PAGE:
|
|
||||||
if (curpage != 1) {
|
|
||||||
curpage = 1;
|
|
||||||
menu_display_page(menu, win, curpage);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MENU_SEARCH:
|
|
||||||
curses_line_input_dialog("Search for:", search_key, BUFSZ);
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
touchwin(win);
|
|
||||||
wrefresh(win);
|
|
||||||
|
|
||||||
if (!*search_key) {
|
|
||||||
break;
|
break;
|
||||||
}
|
case KEY_RIGHT:
|
||||||
|
case KEY_NPAGE:
|
||||||
|
case MENU_NEXT_PAGE:
|
||||||
|
case ' ':
|
||||||
|
if (curpage < menu->num_pages) {
|
||||||
|
curpage++;
|
||||||
|
menu_display_page(menu, win, curpage, selectors);
|
||||||
|
} else if (curletter == ' ') {
|
||||||
|
dismiss = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
case KEY_PPAGE:
|
||||||
|
case MENU_PREVIOUS_PAGE:
|
||||||
|
if (curpage > 1) {
|
||||||
|
curpage--;
|
||||||
|
menu_display_page(menu, win, curpage, selectors);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_END:
|
||||||
|
case MENU_LAST_PAGE:
|
||||||
|
if (curpage != menu->num_pages) {
|
||||||
|
curpage = menu->num_pages;
|
||||||
|
menu_display_page(menu, win, curpage, selectors);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_HOME:
|
||||||
|
case MENU_FIRST_PAGE:
|
||||||
|
if (curpage != 1) {
|
||||||
|
curpage = 1;
|
||||||
|
menu_display_page(menu, win, curpage, selectors);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MENU_SEARCH:
|
||||||
|
search_key[0] = '\0';
|
||||||
|
curses_line_input_dialog("Search for:", search_key, BUFSZ);
|
||||||
|
|
||||||
menu_item_ptr = menu->entries;
|
refresh();
|
||||||
|
touchwin(win);
|
||||||
|
wrefresh(win);
|
||||||
|
|
||||||
while (menu_item_ptr != NULL) {
|
if (!*search_key)
|
||||||
if (menu_item_ptr->identifier.a_void != NULL
|
break;
|
||||||
&& strstri(menu_item_ptr->str, search_key)) {
|
|
||||||
if (how == PICK_ONE) {
|
menu_item_ptr = menu->entries;
|
||||||
menu_clear_selections(menu);
|
|
||||||
menu_select_deselect(win, menu_item_ptr, SELECT);
|
while (menu_item_ptr != NULL) {
|
||||||
num_selected = 1;
|
if (menu_item_ptr->identifier.a_void != NULL
|
||||||
dismiss = TRUE;
|
&& strstri(menu_item_ptr->str, search_key)) {
|
||||||
break;
|
if (how == PICK_ONE) {
|
||||||
} else {
|
menu_clear_selections(menu);
|
||||||
menu_select_deselect(win, menu_item_ptr, INVERT);
|
menu_select_deselect(win, menu_item_ptr, SELECT);
|
||||||
|
num_selected = 1;
|
||||||
|
dismiss = TRUE;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
menu_select_deselect(win, menu_item_ptr, INVERT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menu_item_ptr = menu_item_ptr->next_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_item_ptr = menu_item_ptr->next_item;
|
menu_item_ptr = menu->entries;
|
||||||
}
|
|
||||||
|
|
||||||
menu_item_ptr = menu->entries;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (how == PICK_NONE) {
|
|
||||||
num_selected = 0;
|
|
||||||
dismiss = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
if (how == PICK_NONE) {
|
||||||
|
num_selected = 0;
|
||||||
|
dismiss = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user