^A/#repeat vs extended commands

Fix '#repeat' for tty; both it and ^A can repeat an extended command.

Fix both for curses; they can repeat an extended command instead of
just repeating the initial '#' to start getting an extended command.

X11 (tested), Qt (tested), and probably Windows GUI (not tested)
behave the same as before:  ^A (or #repeat) after an extended command
just repeats the # to run the dialog to get an extended command.

I hope this introduces fewer bugs than it fixes but I don't think I'd
bet on that....
This commit is contained in:
PatR
2022-04-16 01:52:12 -07:00
parent 4485515872
commit 31affa0722
8 changed files with 116 additions and 30 deletions
+1
View File
@@ -499,6 +499,7 @@ struct cmd {
const char *alphadirchars; /* same as dirchars if !numpad */ const char *alphadirchars; /* same as dirchars if !numpad */
const struct ext_func_tab *commands[256]; /* indexed by input character */ const struct ext_func_tab *commands[256]; /* indexed by input character */
char spkeys[NUM_NHKF]; char spkeys[NUM_NHKF];
char extcmd_char; /* key that starts an extended command ('#') */
}; };
+2
View File
@@ -260,6 +260,8 @@ extern void cmdq_clear(void);
extern char pgetchar(void); extern char pgetchar(void);
extern void pushch(char); extern void pushch(char);
extern void savech(char); extern void savech(char);
extern void savech_extcmd(const char *, boolean);
extern char extcmd_initiator(void);
extern int doextcmd(void); extern int doextcmd(void);
extern struct ext_func_tab *extcmds_getentry(int); extern struct ext_func_tab *extcmds_getentry(int);
extern int extcmds_match(const char *, int, int **); extern int extcmds_match(const char *, int, int **);
+51 -5
View File
@@ -400,6 +400,43 @@ savech(char ch)
return; return;
} }
/* perform savech() for the characters of an extended command name;
inserts the '#' first because rhack() no longer does that one
while processing do_extcmd();
'str' might be the full command name or maybe just enough to be
unambiguous depending on how the interface handles that--we don't
care as long as ^A feeds back what the interface expects to see */
void
savech_extcmd(const char *str, boolean addnewline)
{
int j;
/* this debuging line might be immediately erased and need ^P to read */
debugpline1("savech_extcmd(\"%s\")", str);
if (!g.in_doagain && strcmp(str, "repeat")) {
uchar c = (g.shead > 0) ? (uchar) (g.saveq[g.shead - 1] & 0xff) : 0;
/* reset saveq unless it holds a prefix */
if (!c || !g.Cmd.commands[c]
|| (g.Cmd.commands[c]->flags & PREFIXCMD) == 0)
savech(0);
savech(g.Cmd.extcmd_char);
for (j = 0; str[j]; j++)
savech(str[j]);
if (addnewline)
savech('\n');
}
}
/* '#' or whatever has been bound to do_extcmd() in its place */
char
extcmd_initiator(void)
{
return g.Cmd.extcmd_char;
}
static boolean static boolean
can_do_extcmd(const struct ext_func_tab *extcmd) can_do_extcmd(const struct ext_func_tab *extcmd)
{ {
@@ -3683,7 +3720,8 @@ reset_commands(boolean initial)
if (backed_dir_cmd) { if (backed_dir_cmd) {
for (dir = 0; dir < N_DIRS; dir++) { for (dir = 0; dir < N_DIRS; dir++) {
for (mode = 0; mode < N_MOVEMODES; mode++) { for (mode = 0; mode < N_MOVEMODES; mode++) {
g.Cmd.commands[back_dir_key[dir][mode]] = back_dir_cmd[dir][mode]; g.Cmd.commands[back_dir_key[dir][mode]]
= back_dir_cmd[dir][mode];
} }
} }
} }
@@ -3766,7 +3804,8 @@ reset_commands(boolean initial)
else if (mode == MV_RUSH) di = M(di); else if (mode == MV_RUSH) di = M(di);
} }
back_dir_key[dir][mode] = di; back_dir_key[dir][mode] = di;
back_dir_cmd[dir][mode] = (struct ext_func_tab *) g.Cmd.commands[di]; back_dir_cmd[dir][mode]
= (struct ext_func_tab *) g.Cmd.commands[di];
g.Cmd.commands[di] = (struct ext_func_tab *) 0; g.Cmd.commands[di] = (struct ext_func_tab *) 0;
} }
} }
@@ -3776,15 +3815,17 @@ reset_commands(boolean initial)
for (i = 0; i < N_DIRS; i++) { for (i = 0; i < N_DIRS; i++) {
(void) bind_key_fn(g.Cmd.dirchars[i], move_funcs[i][MV_WALK]); (void) bind_key_fn(g.Cmd.dirchars[i], move_funcs[i][MV_WALK]);
if (!g.Cmd.num_pad) { if (!g.Cmd.num_pad) {
(void) bind_key_fn(highc(g.Cmd.dirchars[i]), move_funcs[i][MV_RUN]); (void) bind_key_fn(highc(g.Cmd.dirchars[i]),
move_funcs[i][MV_RUN]);
(void) bind_key_fn(C(g.Cmd.dirchars[i]), move_funcs[i][MV_RUSH]); (void) bind_key_fn(C(g.Cmd.dirchars[i]), move_funcs[i][MV_RUSH]);
} else { } else {
/* M(number) works when altmeta is on */ /* M(number) works when altmeta is on */
(void) bind_key_fn(M(g.Cmd.dirchars[i]), move_funcs[i][MV_RUN]); (void) bind_key_fn(M(g.Cmd.dirchars[i]), move_funcs[i][MV_RUN]);
/* can't bind highc() or C() of numbers. just use the 5 prefix. */ /* can't bind highc() or C() of digits. just use the 5 prefix. */
} }
} }
update_rest_on_space(); update_rest_on_space();
g.Cmd.extcmd_char = cmd_from_func(doextcmd);
} }
/* called when 'rest_on_space' is toggled, also called by reset_commands() /* called when 'rest_on_space' is toggled, also called by reset_commands()
@@ -5170,7 +5211,12 @@ parse(void)
} else if (g.in_doagain) { } else if (g.in_doagain) {
g.command_count = g.last_command_count; g.command_count = g.last_command_count;
} else if (foo && g.Cmd.commands[foo & 0xff] } else if (foo && g.Cmd.commands[foo & 0xff]
&& g.Cmd.commands[foo & 0xff]->ef_funct == do_repeat) { /* these shouldn't go into the do-again buffer */
&& (g.Cmd.commands[foo & 0xff]->ef_funct == do_repeat
|| g.Cmd.commands[foo & 0xff]->ef_funct == doprev_message
/* this one might get put into the do-again buffer but
only if the interface code tells the core to do it */
|| g.Cmd.commands[foo & 0xff]->ef_funct == doextcmd)) {
/* g.command_count will be set again when we /* g.command_count will be set again when we
re-enter with g.in_doagain set true */ re-enter with g.in_doagain set true */
g.command_count = g.last_command_count; g.command_count = g.last_command_count;
+9 -1
View File
@@ -581,7 +581,15 @@ int NetHackQtExtCmdRequestor::get()
} }
if (result() == xcmdNone) if (result() == xcmdNone)
exec(); exec();
return result() - 1;
int ret = result() - 1;
if (!::g.in_doagain) {
if (ret >= 0)
savech_extcmd(::extcmdlist[ret].ef_txt, FALSE);
else
savech(0);
}
return ret;
} }
// Enable only buttons that match the current prompt string // Enable only buttons that match the current prompt string
+6 -1
View File
@@ -1556,8 +1556,13 @@ X11_get_ext_cmd(void)
/* The callbacks will enable the event loop exit. */ /* The callbacks will enable the event loop exit. */
(void) x_event(EXIT_ON_EXIT); (void) x_event(EXIT_ON_EXIT);
if (extended_cmd_selected < 0) if (extended_cmd_selected < 0) {
if (!g.in_doagain)
savech(0);
return -1; return -1;
}
if (!g.in_doagain)
savech_extcmd(command_list[extended_cmd_selected], TRUE);
return command_indx[extended_cmd_selected]; return command_indx[extended_cmd_selected];
} }
+18 -3
View File
@@ -437,7 +437,7 @@ curses_ext_cmd(void)
curs_set(1); curs_set(1);
wrefresh(extwin); wrefresh(extwin);
letter = getch(); letter = pgetchar(); /* pgetchar(cmd.c) implements do-again */
curs_set(0); curs_set(0);
prompt_width = (int) strlen(cur_choice); prompt_width = (int) strlen(cur_choice);
matches = 0; matches = 0;
@@ -494,8 +494,23 @@ curses_ext_cmd(void)
curses_destroy_win(extwin); curses_destroy_win(extwin);
if (extwin2) if (extwin2)
curses_destroy_win(extwin2); curses_destroy_win(extwin2);
if (ret == -1 && *cur_choice)
pline("%s: unknown extended command.", cur_choice); if (ret != -1) {
if (!g.in_doagain)
savech_extcmd(cur_choice, TRUE);
} else {
char extcmd_char = extcmd_initiator();
if (*cur_choice)
pline("%s%s: unknown extended command.",
visctrl(extcmd_char), cur_choice);
if (!g.in_doagain) {
savech(0); /* reset do-again buffer */
if (letter != '\033')
savech(extcmd_char);
}
}
return ret; return ret;
} }
+13 -14
View File
@@ -271,6 +271,8 @@ tty_get_ext_cmd(void)
char buf[BUFSZ]; char buf[BUFSZ];
int nmatches; int nmatches;
int *ecmatches; int *ecmatches;
boolean (*no_hook)(char *base) = (boolean (*)(char *)) 0;
char extcmd_char[2];
if (iflags.extmenu) if (iflags.extmenu)
return extcmd_via_menu(); return extcmd_via_menu();
@@ -282,27 +284,24 @@ tty_get_ext_cmd(void)
* ? ext_cmd_getlin_hook * ? ext_cmd_getlin_hook
* : (getlin_hook_proc) 0); * : (getlin_hook_proc) 0);
*/ */
extcmd_char[0] = extcmd_initiator(), extcmd_char[1] = '\0';
buf[0] = '\0'; buf[0] = '\0';
hooked_tty_getlin("#", buf, g.in_doagain ? (getlin_hook_proc) 0 hooked_tty_getlin(extcmd_char, buf,
: ext_cmd_getlin_hook); !g.in_doagain ? ext_cmd_getlin_hook : no_hook);
(void) mungspaces(buf); (void) mungspaces(buf);
if (buf[0] == 0 || buf[0] == '\033')
return -1;
nmatches = extcmds_match(buf, ECM_IGNOREAC|ECM_EXACTMATCH, &ecmatches);
if (!g.in_doagain) {
int j;
for (j = 0; buf[j]; j++)
savech(buf[j]);
savech('\n');
}
nmatches = (buf[0] == '\0' || buf[0] == '\033') ? -1
: extcmds_match(buf, ECM_IGNOREAC | ECM_EXACTMATCH, &ecmatches);
if (nmatches != 1) { if (nmatches != 1) {
pline("%s: unknown extended command.", buf); if (nmatches != -1)
pline("%s%.60s: unknown extended command.",
visctrl(extcmd_char[0]), buf);
savech(0); /* reset do-again buffer */
savech(extcmd_char[0]);
return -1; return -1;
} }
savech_extcmd(buf, TRUE); /* savech() for extcmd_char+buf[...]+'\n' */
return ecmatches[0]; return ecmatches[0];
} }
+16 -6
View File
@@ -1750,12 +1750,12 @@ int get_ext_cmd(void)
int int
mswin_get_ext_cmd(void) mswin_get_ext_cmd(void)
{ {
char cmd[BUFSZ];
int ret; int ret;
logDebug("mswin_get_ext_cmd()\n"); logDebug("mswin_get_ext_cmd()\n");
if (!iflags.wc_popup_dialog) { if (!iflags.wc_popup_dialog) {
char c; char c;
char cmd[BUFSZ];
int i, len; int i, len;
int createcaret; int createcaret;
@@ -1784,7 +1784,8 @@ mswin_get_ext_cmd(void)
break; break;
if (extcmdlist[i].ef_txt == (char *) 0) { if (extcmdlist[i].ef_txt == (char *) 0) {
pline("%s: unknown extended command.", cmd); pline("%s%s: unknown extended command.",
visctrl(extcmd_initiator()), cmd);
i = -1; i = -1;
} }
break; break;
@@ -1825,13 +1826,22 @@ mswin_get_ext_cmd(void)
createcaret = 0; createcaret = 0;
SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_MSNH_COMMAND, SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_MSNH_COMMAND,
(WPARAM) MSNH_MSG_CARET, (LPARAM) &createcaret); (WPARAM) MSNH_MSG_CARET, (LPARAM) &createcaret);
return i; ret = i;
} else { } else {
if (mswin_ext_cmd_window(&ret) == IDCANCEL) cmd[0] = '\0';
return -1; if (mswin_ext_cmd_window(&ret) != IDCANCEL)
Strcpy(cmd, extcmdlist[ret].ef_txt);
else else
return ret; ret = -1;
} }
if (!g.in_doagain) {
if (ret >= 0)
savech_extcmd(cmd, TRUE);
else
savech(0);
}
return ret;
} }
/* /*