]> granicus.if.org Git - nethack/commitdiff
fix github issue #193 - curses: menu search
authorPatR <rankin@nethack.org>
Fri, 31 May 2019 17:11:45 +0000 (10:11 -0700)
committerPatR <rankin@nethack.org>
Fri, 31 May 2019 17:11:45 +0000 (10:11 -0700)
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.

win/curses/cursdial.c
win/curses/cursmain.c

index 18eaec465cef9ae70e6150e35db889826a4614de..2f2f5fccecd26eee324b85762423b238fa7a3552 100644 (file)
@@ -97,7 +97,8 @@ static char menu_get_accel(boolean first);
 static void menu_determine_pages(nhmenu *menu);
 static boolean menu_is_multipage(nhmenu *menu, int width, int height);
 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 void menu_select_deselect(WINDOW * win, nhmenu_item *item,
                                  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
-   or a wish */
+   or a wish.  Note: EDIT_GETLIN not supported for popup prompting. */
 
 void
 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 */
     curses_got_input();
 
-    if (buffer >= (int) sizeof input)
-         buffer = (int) sizeof input - 1;
+    if (buffer > (int) sizeof input)
+         buffer = (int) sizeof input;
     maxwidth = term_cols - 2;
 
     if (iflags.window_inited) {
@@ -1059,7 +1060,7 @@ menu_win_size(nhmenu *menu)
 /* Displays menu selections in the given window */
 
 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;
     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;
     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 */
 
     menu_item_ptr = menu->entries;
@@ -1117,6 +1122,9 @@ menu_display_page(nhmenu *menu, WINDOW * win, int page_num)
                 }
                 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) {
                 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 num_selected = 0;
     boolean dismiss = FALSE;
-    char search_key[BUFSZ];
+    char search_key[BUFSZ], selectors[256];
     nhmenu_item *menu_item_ptr = menu->entries;
 
-    menu_display_page(menu, win, curpage);
+    menu_display_page(menu, win, curpage, selectors);
 
     while (!dismiss) {
         curletter = getch();
@@ -1253,25 +1261,27 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
             }
             break;
         case PICK_ANY:
-            switch (curletter) {
-            case MENU_SELECT_PAGE:
-                (void) menu_operation(win, menu, SELECT, curpage);
-                break;
-            case MENU_SELECT_ALL:
-                curpage = menu_operation(win, menu, SELECT, 0);
-                break;
-            case MENU_UNSELECT_PAGE:
-                (void) menu_operation(win, menu, DESELECT, curpage);
-                break;
-            case MENU_UNSELECT_ALL:
-                curpage = menu_operation(win, menu, DESELECT, 0);
-                break;
-            case MENU_INVERT_PAGE:
-                (void) menu_operation(win, menu, INVERT, curpage);
-                break;
-            case MENU_INVERT_ALL:
-                curpage = menu_operation(win, menu, INVERT, 0);
-                break;
+            if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
+                switch (curletter) {
+                case MENU_SELECT_PAGE:
+                    (void) menu_operation(win, menu, SELECT, curpage);
+                    break;
+                case MENU_SELECT_ALL:
+                    curpage = menu_operation(win, menu, SELECT, 0);
+                    break;
+                case MENU_UNSELECT_PAGE:
+                    (void) menu_operation(win, menu, DESELECT, curpage);
+                    break;
+                case MENU_UNSELECT_ALL:
+                    curpage = menu_operation(win, menu, DESELECT, 0);
+                    break;
+                case MENU_INVERT_PAGE:
+                    (void) menu_operation(win, menu, INVERT, curpage);
+                    break;
+                case MENU_INVERT_ALL:
+                    curpage = menu_operation(win, menu, INVERT, 0);
+                    break;
+                }
             }
             /*FALLTHRU*/
         default:
@@ -1286,86 +1296,88 @@ menu_get_selections(WINDOW * win, nhmenu *menu, int how)
             }
         }
 
-        switch (curletter) {
-        case KEY_ESC:
-            num_selected = -1;
-            dismiss = TRUE;
-            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 == ' ') {
+        if (curletter <= 0 || curletter >= 256 || !selectors[curletter]) {
+            switch (curletter) {
+            case KEY_ESC:
+                num_selected = -1;
                 dismiss = TRUE;
                 break;
-            }
-            break;
-        case KEY_LEFT:
-        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) {
+            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, 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 (menu_item_ptr->identifier.a_void != NULL
-                    && strstri(menu_item_ptr->str, search_key)) {
-                    if (how == PICK_ONE) {
-                        menu_clear_selections(menu);
-                        menu_select_deselect(win, menu_item_ptr, SELECT);
-                        num_selected = 1;
-                        dismiss = TRUE;
-                        break;
-                    } else {
-                        menu_select_deselect(win, menu_item_ptr, INVERT);
+                if (!*search_key)
+                    break;
+
+                menu_item_ptr = menu->entries;
+
+                while (menu_item_ptr != NULL) {
+                    if (menu_item_ptr->identifier.a_void != NULL
+                        && strstri(menu_item_ptr->str, search_key)) {
+                        if (how == PICK_ONE) {
+                            menu_clear_selections(menu);
+                            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;
-            break;
-        default:
-            if (how == PICK_NONE) {
-                num_selected = 0;
-                dismiss = TRUE;
+                menu_item_ptr = menu->entries;
                 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)) {
                     if (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) {
@@ -1479,7 +1491,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op
     current_page = first_page;
 
     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 */
@@ -1494,7 +1506,7 @@ menu_operation(WINDOW * win, nhmenu *menu, menu_op
             }
 
             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) {
index ada703de415ec9e025229b7ed7f10fc5347035e4..931de9569eafa2856ca5a271ec6ed41e50f29050 100644 (file)
@@ -202,6 +202,7 @@ curses_player_selection()
 void
 curses_askname()
 {
+    plname[0] = '\0';
     curses_line_input_dialog("Who are you?", plname, PL_NSIZ);
 }