curses menu: support backspace/delete for counts
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.
This commit is contained in:
@@ -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
|
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
|
more digits typed followed by non-digit); in-out menu was still active
|
||||||
but no longer displayed
|
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
|
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
|
tree contained a space; the issue was within some shell script code
|
||||||
contained within the project
|
contained within the project
|
||||||
|
|||||||
+3
-1
@@ -12,6 +12,8 @@ extern int orig_cursor; /* Preserve initial cursor state */
|
|||||||
extern WINDOW *base_term; /* underlying terminal window */
|
extern WINDOW *base_term; /* underlying terminal window */
|
||||||
extern boolean counting; /* Count window is active */
|
extern boolean counting; /* Count window is active */
|
||||||
extern WINDOW *mapwin, *statuswin, *messagewin; /* Main windows */
|
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 TEXTCOLOR /* Allow color */
|
||||||
#define NHW_END 19
|
#define NHW_END 19
|
||||||
@@ -160,7 +162,7 @@ extern void curses_prehousekeeping(void);
|
|||||||
extern void curses_posthousekeeping(void);
|
extern void curses_posthousekeeping(void);
|
||||||
extern void curses_view_file(const char *filename, boolean must_exist);
|
extern void curses_view_file(const char *filename, boolean must_exist);
|
||||||
extern void curses_rtrim(char *str);
|
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_convert_attr(int attr);
|
||||||
extern int curses_read_attrs(const char *attrs);
|
extern int curses_read_attrs(const char *attrs);
|
||||||
extern char *curses_fmt_attrs(char *);
|
extern char *curses_fmt_attrs(char *);
|
||||||
|
|||||||
@@ -4340,6 +4340,7 @@ click_to_cmd(int x, int y, int mod)
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* gather typed digits into a number in *count; return the next non-digit */
|
||||||
char
|
char
|
||||||
get_count(char *allowchars, char inkey,
|
get_count(char *allowchars, char inkey,
|
||||||
long maxcount, long *count,
|
long maxcount, long *count,
|
||||||
@@ -4363,12 +4364,12 @@ get_count(char *allowchars, char inkey,
|
|||||||
|
|
||||||
if (digit(key)) {
|
if (digit(key)) {
|
||||||
cnt = 10L * cnt + (long) (key - '0');
|
cnt = 10L * cnt + (long) (key - '0');
|
||||||
if (cnt < 0)
|
if (cnt < 0L)
|
||||||
cnt = 0;
|
cnt = 0L;
|
||||||
else if (maxcount > 0 && cnt > maxcount)
|
else if (maxcount > 0L && cnt > maxcount)
|
||||||
cnt = maxcount;
|
cnt = maxcount;
|
||||||
} else if (cnt && (key == '\b' || key == STANDBY_erase_char)) {
|
} else if (cnt && (key == '\b' || key == STANDBY_erase_char)) {
|
||||||
cnt = cnt / 10;
|
cnt = cnt / 10L;
|
||||||
backspaced = TRUE;
|
backspaced = TRUE;
|
||||||
} else if (key == g.Cmd.spkeys[NHKF_ESC]) {
|
} else if (key == g.Cmd.spkeys[NHKF_ESC]) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
+22
-12
@@ -23,18 +23,19 @@ extern char erase_char, kill_char;
|
|||||||
|
|
||||||
/* Dialog windows for curses interface */
|
/* Dialog windows for curses interface */
|
||||||
|
|
||||||
|
WINDOW *activemenu = NULL; /* for count_window refresh handling */
|
||||||
|
|
||||||
/* Private declarations */
|
/* Private declarations */
|
||||||
|
|
||||||
typedef struct nhmi {
|
typedef struct nhmi {
|
||||||
winid wid; /* NetHack window id */
|
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 */
|
anything identifier; /* Value returned if item selected */
|
||||||
char accelerator; /* Character used to select item from menu */
|
char accelerator; /* Character used to select item from menu */
|
||||||
char group_accel; /* Group accelerator for menu item, if any */
|
char group_accel; /* Group accelerator for menu item, if any */
|
||||||
int attr; /* Text attributes for item */
|
int attr; /* Text attributes for item */
|
||||||
const char *str; /* Text of menu 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 */
|
boolean selected; /* Whether item is currently selected */
|
||||||
unsigned itemflags;
|
unsigned itemflags;
|
||||||
int page_num; /* Display page number for entry */
|
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*/) {
|
if (iflags.wc_popup_dialog /*|| curses_stupid_hack*/) {
|
||||||
askwin = curses_create_window(prompt_width, prompt_height, UP);
|
askwin = curses_create_window(prompt_width, prompt_height, UP);
|
||||||
|
activemenu = askwin;
|
||||||
|
|
||||||
for (count = 0; count < prompt_height; count++) {
|
for (count = 0; count < prompt_height; count++) {
|
||||||
linestr = curses_break_str(askstr, maxwidth, count + 1);
|
linestr = curses_break_str(askstr, maxwidth, count + 1);
|
||||||
mvwaddstr(askwin, count + 1, 1, linestr);
|
mvwaddstr(askwin, count + 1, 1, linestr);
|
||||||
@@ -321,11 +324,14 @@ curses_character_input_dialog(const char *prompt, const char *choices,
|
|||||||
if (digit(answer)) {
|
if (digit(answer)) {
|
||||||
if (accept_count) {
|
if (accept_count) {
|
||||||
if (answer != '0') {
|
if (answer != '0') {
|
||||||
yn_number = curses_get_count(answer - '0');
|
yn_number = curses_get_count(answer);
|
||||||
touchwin(askwin);
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (iflags.wc_popup_dialog) {
|
||||||
|
curses_count_window(NULL);
|
||||||
|
touchwin(askwin);
|
||||||
|
wrefresh(askwin);
|
||||||
|
}
|
||||||
|
}
|
||||||
answer = '#';
|
answer = '#';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1434,7 +1440,7 @@ static int
|
|||||||
menu_get_selections(WINDOW *win, nhmenu *menu, int how)
|
menu_get_selections(WINDOW *win, nhmenu *menu, int how)
|
||||||
{
|
{
|
||||||
int curletter, menucmd;
|
int curletter, menucmd;
|
||||||
int count = -1;
|
long count = -1L;
|
||||||
int count_letter = '\0';
|
int count_letter = '\0';
|
||||||
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;
|
||||||
@@ -1442,6 +1448,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
|
|||||||
char selectors[256];
|
char selectors[256];
|
||||||
nhmenu_item *menu_item_ptr = menu->entries;
|
nhmenu_item *menu_item_ptr = menu->entries;
|
||||||
|
|
||||||
|
activemenu = win;
|
||||||
menu_display_page(menu, win, curpage, selectors);
|
menu_display_page(menu, win, curpage, selectors);
|
||||||
|
|
||||||
while (!dismiss) {
|
while (!dismiss) {
|
||||||
@@ -1496,10 +1503,10 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
|
|||||||
/*FALLTHRU*/
|
/*FALLTHRU*/
|
||||||
default:
|
default:
|
||||||
if (isdigit(curletter)) {
|
if (isdigit(curletter)) {
|
||||||
count = curses_get_count(curletter - '0');
|
count = curses_get_count(curletter);
|
||||||
/* after count, we know some non-digit is already pending */
|
/* after count, we know some non-digit is already pending */
|
||||||
curletter = getch();
|
curletter = getch();
|
||||||
count_letter = (count > 0) ? curletter : '\0';
|
count_letter = (count > 0L) ? curletter : '\0';
|
||||||
|
|
||||||
/* remove the count wind (erases last line of message wind) */
|
/* remove the count wind (erases last line of message wind) */
|
||||||
curses_count_window(NULL);
|
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,
|
dismiss = curs_nonselect_menu_action(win, (void *) menu, how,
|
||||||
curletter, &curpage,
|
curletter, &curpage,
|
||||||
selectors, &num_selected);
|
selectors, &num_selected);
|
||||||
if (num_selected == -1)
|
if (num_selected == -1) {
|
||||||
|
activemenu = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_item_ptr = menu->entries;
|
menu_item_ptr = menu->entries;
|
||||||
@@ -1569,6 +1578,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
activemenu = NULL;
|
||||||
return num_selected;
|
return num_selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -460,6 +460,10 @@ curses_count_window(const char *count_text)
|
|||||||
|
|
||||||
mvwprintw(countwin, 0, 0, "%s", count_text);
|
mvwprintw(countwin, 0, 0, "%s", count_text);
|
||||||
wrefresh(countwin);
|
wrefresh(countwin);
|
||||||
|
if (activemenu) {
|
||||||
|
touchwin(activemenu);
|
||||||
|
wrefresh(activemenu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gets a "line" (buffer) of input. */
|
/* Gets a "line" (buffer) of input. */
|
||||||
|
|||||||
+10
-15
@@ -691,30 +691,25 @@ curses_rtrim(char *str)
|
|||||||
/* Read numbers until non-digit is encountered, and return number
|
/* Read numbers until non-digit is encountered, and return number
|
||||||
in int form. */
|
in int form. */
|
||||||
|
|
||||||
int
|
long
|
||||||
curses_get_count(int first_digit)
|
curses_get_count(int first_digit)
|
||||||
{
|
{
|
||||||
long current_count = first_digit;
|
|
||||||
int current_char;
|
int current_char;
|
||||||
|
long current_count = 0L;
|
||||||
|
|
||||||
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;
|
||||||
while (isdigit(current_char)) {
|
curses's message window will display that in count window instead */
|
||||||
current_count = (current_count * 10) + (current_char - '0');
|
current_char = get_count(NULL, (char) first_digit,
|
||||||
if (current_count > LARGEST_INT) {
|
/* 0L => no limit on value unless it wraps
|
||||||
current_count = LARGEST_INT;
|
* to negative;
|
||||||
}
|
* FALSE => suppress from message history */
|
||||||
|
0L, ¤t_count, FALSE);
|
||||||
custompline(SUPPRESS_HISTORY, "Count: %ld", current_count);
|
|
||||||
current_char = curses_read_char();
|
|
||||||
}
|
|
||||||
|
|
||||||
ungetch(current_char);
|
ungetch(current_char);
|
||||||
|
|
||||||
if (current_char == '\033') { /* Cancelled with escape */
|
if (current_char == '\033') { /* Cancelled with escape */
|
||||||
current_count = -1;
|
current_count = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_count;
|
return current_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void curses_prehousekeeping(void);
|
|||||||
void curses_posthousekeeping(void);
|
void curses_posthousekeeping(void);
|
||||||
void curses_view_file(const char *filename, boolean must_exist);
|
void curses_view_file(const char *filename, boolean must_exist);
|
||||||
void curses_rtrim(char *str);
|
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_convert_attr(int attr);
|
||||||
int curses_read_attrs(const char *attrs);
|
int curses_read_attrs(const char *attrs);
|
||||||
char *curses_fmt_attrs(char *);
|
char *curses_fmt_attrs(char *);
|
||||||
|
|||||||
@@ -152,6 +152,8 @@ curses_destroy_win(WINDOW *win)
|
|||||||
werase(win);
|
werase(win);
|
||||||
wrefresh(win);
|
wrefresh(win);
|
||||||
delwin(win);
|
delwin(win);
|
||||||
|
if (win == activemenu)
|
||||||
|
activemenu = NULL;
|
||||||
curses_refresh_nethack_windows();
|
curses_refresh_nethack_windows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user