]> granicus.if.org Git - nethack/commitdiff
curses menu: support backspace/delete for counts
authorPatR <rankin@nethack.org>
Sun, 6 Jun 2021 12:54:53 +0000 (05:54 -0700)
committerPatR <rankin@nethack.org>
Sun, 6 Jun 2021 12:54:53 +0000 (05:54 -0700)
Have curses call the core get_count() routine instead rolling its
own so that backspace and delete are supported.  That part was
trivial to accomplish.  Unfortunately it brought the disappearing
menu phenomenon back so it became more complicated overall.

doc/fixes37.0
include/wincurs.h
src/cmd.c
win/curses/cursdial.c
win/curses/cursmesg.c
win/curses/cursmisc.c
win/curses/cursmisc.h
win/curses/curswins.c

index 33ae2468e344b3d543afb64acb0c5e0b0959520c..46870f52458ec5c4b33484ab7353747f220ca286 100644 (file)
@@ -758,6 +758,7 @@ curses: sometimes entering a count during menu selection caused the menu to
        disappear (example was apply/loot in-out container menu with two or
        more digits typed followed by non-digit); in-out menu was still active
        but no longer displayed
+curses: support backspace/delete when entering a count during menu selection
 macOS: Xcode project was failing to build if the path to the NetHack source
        tree contained a space; the issue was within some shell script code
        contained within the project
index f9b70ca066554291ae32fa69422a7537c7403882..48173f88f7d2ce09c284e7e9edf3b805b55de31b 100644 (file)
@@ -12,6 +12,8 @@ extern int orig_cursor;            /* Preserve initial cursor state */
 extern WINDOW *base_term;          /* underlying terminal window    */
 extern boolean counting;           /* Count window is active        */
 extern WINDOW *mapwin, *statuswin, *messagewin;    /* Main windows  */
+extern WINDOW *activemenu;         /* curses window for menu requesting a
+                                    * count; affects count_window refresh */
 
 #define TEXTCOLOR   /* Allow color */
 #define NHW_END 19
@@ -160,7 +162,7 @@ extern void curses_prehousekeeping(void);
 extern void curses_posthousekeeping(void);
 extern void curses_view_file(const char *filename, boolean must_exist);
 extern void curses_rtrim(char *str);
-extern int curses_get_count(int first_digit);
+extern long curses_get_count(int first_digit);
 extern int curses_convert_attr(int attr);
 extern int curses_read_attrs(const char *attrs);
 extern char *curses_fmt_attrs(char *);
index 33ab42e1f06545fffe71ee2e4a56d23bf59c8713..4f2a8c0d0ee85fc536072cebc660668d25d03a89 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -4340,6 +4340,7 @@ click_to_cmd(int x, int y, int mod)
     return cmd;
 }
 
+/* gather typed digits into a number in *count; return the next non-digit */
 char
 get_count(char *allowchars, char inkey,
           long maxcount, long *count,
@@ -4363,12 +4364,12 @@ get_count(char *allowchars, char inkey,
 
         if (digit(key)) {
             cnt = 10L * cnt + (long) (key - '0');
-            if (cnt < 0)
-                cnt = 0;
-            else if (maxcount > 0 && cnt > maxcount)
+            if (cnt < 0L)
+                cnt = 0L;
+            else if (maxcount > 0L && cnt > maxcount)
                 cnt = maxcount;
         } else if (cnt && (key == '\b' || key == STANDBY_erase_char)) {
-            cnt = cnt / 10;
+            cnt = cnt / 10L;
             backspaced = TRUE;
         } else if (key == g.Cmd.spkeys[NHKF_ESC]) {
             break;
index d00a2df885fa59d15b50d627d1fa052bab37e104..2d2d5f04791ed8bb59137e334385b5b5d5fecd84 100644 (file)
@@ -23,18 +23,19 @@ extern char erase_char, kill_char;
 
 /* Dialog windows for curses interface */
 
+WINDOW *activemenu = NULL; /* for count_window refresh handling */
 
 /* Private declarations */
 
 typedef struct nhmi {
     winid wid;                  /* NetHack window id */
-    glyph_info glyphinfo;       /* holds menu glyph and additional glyph info */
+    glyph_info glyphinfo;       /* holds menu glyph and additional info */
     anything identifier;        /* Value returned if item selected */
-    char accelerator;         /* Character used to select item from menu */
-    char group_accel;         /* Group accelerator for menu item, if any */
+    char accelerator;           /* Character used to select item from menu */
+    char group_accel;           /* Group accelerator for menu item, if any */
     int attr;                   /* Text attributes for item */
     const char *str;            /* Text of menu item */
-    boolean presel;           /* Whether menu item should be preselected */
+    boolean presel;             /* Whether menu item should be preselected */
     boolean selected;           /* Whether item is currently selected */
     unsigned itemflags;
     int page_num;               /* Display page number for entry */
@@ -269,6 +270,8 @@ curses_character_input_dialog(const char *prompt, const char *choices,
 
     if (iflags.wc_popup_dialog /*|| curses_stupid_hack*/) {
         askwin = curses_create_window(prompt_width, prompt_height, UP);
+        activemenu = askwin;
+
         for (count = 0; count < prompt_height; count++) {
             linestr = curses_break_str(askstr, maxwidth, count + 1);
             mvwaddstr(askwin, count + 1, 1, linestr);
@@ -321,11 +324,14 @@ curses_character_input_dialog(const char *prompt, const char *choices,
         if (digit(answer)) {
             if (accept_count) {
                 if (answer != '0') {
-                    yn_number = curses_get_count(answer - '0');
-                    touchwin(askwin);
-                    refresh();
-                }
+                    yn_number = curses_get_count(answer);
 
+                    if (iflags.wc_popup_dialog) {
+                        curses_count_window(NULL);
+                        touchwin(askwin);
+                        wrefresh(askwin);
+                    }
+                }
                 answer = '#';
                 break;
             }
@@ -1434,7 +1440,7 @@ static int
 menu_get_selections(WINDOW *win, nhmenu *menu, int how)
 {
     int curletter, menucmd;
-    int count = -1;
+    long count = -1L;
     int count_letter = '\0';
     int curpage = !menu->bottom_heavy ? 1 : menu->num_pages;
     int num_selected = 0;
@@ -1442,6 +1448,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
     char selectors[256];
     nhmenu_item *menu_item_ptr = menu->entries;
 
+    activemenu = win;
     menu_display_page(menu, win, curpage, selectors);
 
     while (!dismiss) {
@@ -1496,10 +1503,10 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
             /*FALLTHRU*/
         default:
             if (isdigit(curletter)) {
-                count = curses_get_count(curletter - '0');
+                count = curses_get_count(curletter);
                 /* after count, we know some non-digit is already pending */
                 curletter = getch();
-                count_letter = (count > 0) ? curletter : '\0';
+                count_letter = (count > 0L) ? curletter : '\0';
 
                 /* remove the count wind (erases last line of message wind) */
                 curses_count_window(NULL);
@@ -1513,8 +1520,10 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
             dismiss = curs_nonselect_menu_action(win, (void *) menu, how,
                                                  curletter, &curpage,
                                                  selectors, &num_selected);
-            if (num_selected == -1)
+            if (num_selected == -1) {
+                activemenu = NULL;
                 return -1;
+            }
         }
 
         menu_item_ptr = menu->entries;
@@ -1569,6 +1578,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
         }
     }
 
+    activemenu = NULL;
     return num_selected;
 }
 
index 0dbc74bc2d36e7713334ad7c1f614af62019cd89..68a8d389f1cfb10a42e5dcb0db54e90f86d6b6ee 100644 (file)
@@ -460,6 +460,10 @@ curses_count_window(const char *count_text)
 
     mvwprintw(countwin, 0, 0, "%s", count_text);
     wrefresh(countwin);
+    if (activemenu) {
+        touchwin(activemenu);
+        wrefresh(activemenu);
+    }
 }
 
 /* Gets a "line" (buffer) of input. */
index 3e996ed4f5727cad789b5c583dc5e1811d5954c9..fca63ed056722a07ee579847c568ab7d644ffb19 100644 (file)
@@ -691,30 +691,25 @@ curses_rtrim(char *str)
 /* Read numbers until non-digit is encountered, and return number
 in int form. */
 
-int
+long
 curses_get_count(int first_digit)
 {
-    long current_count = first_digit;
     int current_char;
+    long current_count = 0L;
 
-    current_char = curses_read_char();
-
-    while (isdigit(current_char)) {
-        current_count = (current_count * 10) + (current_char - '0');
-        if (current_count > LARGEST_INT) {
-            current_count = LARGEST_INT;
-        }
-
-        custompline(SUPPRESS_HISTORY, "Count: %ld", current_count);
-        current_char = curses_read_char();
-    }
+    /* use core's count routine; we have the first digit; if any more
+       are typed, get_count() will send "Count:123" to the message window;
+       curses's message window will display that in count window instead */
+    current_char = get_count(NULL, (char) first_digit,
+                             /* 0L => no limit on value unless it wraps
+                              * to negative;
+                              * FALSE => suppress from message history */
+                             0L, &current_count, FALSE);
 
     ungetch(current_char);
-
     if (current_char == '\033') {     /* Cancelled with escape */
         current_count = -1;
     }
-
     return current_count;
 }
 
index 51c5aa8419c877cd5644f70d3c2769f1c8a691b2..48323565de0f0e081ab40c8197354fa3ea30c869 100644 (file)
@@ -25,7 +25,7 @@ void curses_prehousekeeping(void);
 void curses_posthousekeeping(void);
 void curses_view_file(const char *filename, boolean must_exist);
 void curses_rtrim(char *str);
-int curses_get_count(int first_digit);
+long curses_get_count(int first_digit);
 int curses_convert_attr(int attr);
 int curses_read_attrs(const char *attrs);
 char *curses_fmt_attrs(char *);
index dfcb43fa21c70dea1b90a2fc6cd87cccd269c558..d4d88d414c57530770e78d1bb4ea7f58a2aa6402 100644 (file)
@@ -152,6 +152,8 @@ curses_destroy_win(WINDOW *win)
     werase(win);
     wrefresh(win);
     delwin(win);
+    if (win == activemenu)
+        activemenu = NULL;
     curses_refresh_nethack_windows();
 }