diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 33ae2468e..46870f524 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/include/wincurs.h b/include/wincurs.h index f9b70ca06..48173f88f 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -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 *); diff --git a/src/cmd.c b/src/cmd.c index 33ab42e1f..4f2a8c0d0 100644 --- 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; diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index d00a2df88..2d2d5f047 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -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; } diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index 0dbc74bc2..68a8d389f 100644 --- a/win/curses/cursmesg.c +++ b/win/curses/cursmesg.c @@ -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. */ diff --git a/win/curses/cursmisc.c b/win/curses/cursmisc.c index 3e996ed4f..fca63ed05 100644 --- a/win/curses/cursmisc.c +++ b/win/curses/cursmisc.c @@ -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, ¤t_count, FALSE); ungetch(current_char); - if (current_char == '\033') { /* Cancelled with escape */ current_count = -1; } - return current_count; } diff --git a/win/curses/cursmisc.h b/win/curses/cursmisc.h index 51c5aa841..48323565d 100644 --- a/win/curses/cursmisc.h +++ b/win/curses/cursmisc.h @@ -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 *); diff --git a/win/curses/curswins.c b/win/curses/curswins.c index dfcb43fa2..d4d88d414 100644 --- a/win/curses/curswins.c +++ b/win/curses/curswins.c @@ -152,6 +152,8 @@ curses_destroy_win(WINDOW *win) werase(win); wrefresh(win); delwin(win); + if (win == activemenu) + activemenu = NULL; curses_refresh_nethack_windows(); }