fix github issue #426 - binding special commands
Binding 'repeat' (DOAGAIN, or redo) to a different key than ^A didn't work as intended because the code that used it was checking for DOAGAIN (a key value from config.h) instead of g.Cmd.spkeys[NHKF_DOAGAIN] (the key currently bound to repeat). Contrary to the github issue, re-bound prefix keys worked ok for me if followed by a direction. However, they behaved strangely if followed by anything else. If the keystroke was stolen from some other command and that command hadn't been bound to another key, following the prefix with a non-direction could end up executing the command that used to own the key. For example, BIND=d:nopickup to use 'd' to move without auto-pickup would work if you used d<direction> but if you used d<something-else> if would execute the drop command. The NHKF_REQMENU prefix could be bound to some key other than 'm' but it only worked as intended if the new key was a movement prefix. This also makes DOAGAIN be unconditional. If it is deleted or commented out in config.h, the default binding will be '\000' so unusable (freeing up ^A for something), but still be available to be bound to some key (perhaps even ^A). This also includes an unrelated change to mdlib.c. The comments added to config.h will force a full rebuild. Changing mdlib.c now rather than separately will avoid forcing that twice. Fixes #426
This commit is contained in:
+12
-1
@@ -1,4 +1,4 @@
|
|||||||
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.401 $ $NHDT-Date: 1608846067 2020/12/24 21:41:07 $
|
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.402 $ $NHDT-Date: 1608933417 2020/12/25 21:56:57 $
|
||||||
|
|
||||||
General Fixes and Modified Features
|
General Fixes and Modified Features
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
@@ -345,6 +345,15 @@ best possible armor class reduced from -127 to -99; worst from +127 to +99;
|
|||||||
charged or enchanted individual items also capped at +/- 99 (affects
|
charged or enchanted individual items also capped at +/- 99 (affects
|
||||||
wizard mode wishing, negligible effect on normal play)
|
wizard mode wishing, negligible effect on normal play)
|
||||||
fix several inconsistencies for objects at hole locations
|
fix several inconsistencies for objects at hole locations
|
||||||
|
make repeat (^A) work when bound to some other keystroke
|
||||||
|
if a prefix key was bound to some character which ordinarily ran a regular
|
||||||
|
command and that command wasn't bound to another key, typing the
|
||||||
|
prefix followed by a non-movement key behaved strangely: instead
|
||||||
|
of reporting "invalid direction" it would run the other command
|
||||||
|
(actually depended upon relative order of prefix's new and old key)
|
||||||
|
reqmenu (the request-a-menu prefix supported by a handful of non-movement
|
||||||
|
commands) could be bound to some key other than 'm' but it only
|
||||||
|
worked if the new key was also a movement prefix
|
||||||
|
|
||||||
|
|
||||||
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||||
@@ -692,6 +701,8 @@ add 'sortdiscoveries' option to control output of '\' and '`' commands
|
|||||||
include an indication of monsters' health during farlook feedback (including
|
include an indication of monsters' health during farlook feedback (including
|
||||||
/M and autodescribe); also include it in death reason when killed by
|
/M and autodescribe); also include it in death reason when killed by
|
||||||
a monster: "killed by {an uninjured newt,a heavily injured mumak}"
|
a monster: "killed by {an uninjured newt,a heavily injured mumak}"
|
||||||
|
make DOAGAIN (^A) become unconditional; commenting it out in config.h makes
|
||||||
|
it be bound to NUL, a no-op, but allows BIND=k:repeat to set it to k
|
||||||
|
|
||||||
|
|
||||||
Platform- and/or Interface-Specific New Features
|
Platform- and/or Interface-Specific New Features
|
||||||
|
|||||||
+7
-2
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.7 config.h $NHDT-Date: 1596498529 2020/08/03 23:48:49 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.143 $ */
|
/* NetHack 3.7 config.h $NHDT-Date: 1608933417 2020/12/25 21:56:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.146 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/*-Copyright (c) Robert Patrick Rankin, 2016. */
|
/*-Copyright (c) Robert Patrick Rankin, 2016. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
@@ -482,7 +482,12 @@ typedef unsigned char uchar;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DOAGAIN '\001' /* ^A, the "redo" key used in cmd.c and getline.c */
|
/* The "repeat" key used in cmd.c as NHKF_DOAGAIN; if commented out or the
|
||||||
|
* value is changed from C('A') to 0, it won't be bound to any keystroke
|
||||||
|
* unless you use the run-time configuration file's BIND directive for it.
|
||||||
|
* [Note: C() macro isn't defined yet but it will be before DOAGAIN is used.]
|
||||||
|
*/
|
||||||
|
#define DOAGAIN C('A') /* repeat previous command; default is ^A, '\001' */
|
||||||
|
|
||||||
/* CONFIG_ERROR_SECURE: If user makes NETHACKOPTIONS point to a file ...
|
/* CONFIG_ERROR_SECURE: If user makes NETHACKOPTIONS point to a file ...
|
||||||
* TRUE: Show the first error, nothing else.
|
* TRUE: Show the first error, nothing else.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.7 cmd.c $NHDT-Date: 1608233885 2020/12/17 19:38:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.437 $ */
|
/* NetHack 3.7 cmd.c $NHDT-Date: 1608933418 2020/12/25 21:56:58 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.440 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/*-Copyright (c) Robert Patrick Rankin, 2013. */
|
/*-Copyright (c) Robert Patrick Rankin, 2013. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
@@ -2875,6 +2875,10 @@ wiz_migrate_mons()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DOAGAIN /* might have gotten undefined in config.h */
|
||||||
|
#define DOAGAIN '\0' /* undefined => 0, '\0' => no key to activate redo */
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
int nhkf;
|
int nhkf;
|
||||||
uchar key;
|
uchar key;
|
||||||
@@ -3364,7 +3368,9 @@ register char *cmd;
|
|||||||
g.context.move = FALSE;
|
g.context.move = FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (*cmd == DOAGAIN && !g.in_doagain && g.saveq[0]) {
|
/* DOAGAIN might be '\0'; if so, don't execute it even if *cmd is too */
|
||||||
|
if ((*cmd && *cmd == g.Cmd.spkeys[NHKF_DOAGAIN])
|
||||||
|
&& !g.in_doagain && g.saveq[0]) {
|
||||||
g.in_doagain = TRUE;
|
g.in_doagain = TRUE;
|
||||||
g.stail = 0;
|
g.stail = 0;
|
||||||
rhack((char *) 0); /* read and execute command */
|
rhack((char *) 0); /* read and execute command */
|
||||||
@@ -3475,9 +3481,9 @@ register char *cmd;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some special prefix handling */
|
/* after movement--if reqmenu duplicates a prefix, movement takes
|
||||||
/* overload 'm' prefix to mean "request a menu" */
|
precedence; "request a menu" (default 'm') */
|
||||||
if (prefix_seen && cmd[0] == g.Cmd.spkeys[NHKF_REQMENU]) {
|
if (cmd[0] == g.Cmd.spkeys[NHKF_REQMENU]) {
|
||||||
/* (for func_tab cast, see below) */
|
/* (for func_tab cast, see below) */
|
||||||
const struct ext_func_tab *ft = g.Cmd.commands[cmd[1] & 0xff];
|
const struct ext_func_tab *ft = g.Cmd.commands[cmd[1] & 0xff];
|
||||||
int NDECL((*func)) = ft ? ((struct ext_func_tab *) ft)->ef_funct : 0;
|
int NDECL((*func)) = ft ? ((struct ext_func_tab *) ft)->ef_funct : 0;
|
||||||
@@ -3485,6 +3491,9 @@ register char *cmd;
|
|||||||
if (func && accept_menu_prefix(func)) {
|
if (func && accept_menu_prefix(func)) {
|
||||||
iflags.menu_requested = TRUE;
|
iflags.menu_requested = TRUE;
|
||||||
++cmd;
|
++cmd;
|
||||||
|
prefix_seen = FALSE;
|
||||||
|
} else {
|
||||||
|
prefix_seen = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3518,10 +3527,14 @@ register char *cmd;
|
|||||||
g.context.mv = TRUE;
|
g.context.mv = TRUE;
|
||||||
domove();
|
domove();
|
||||||
return;
|
return;
|
||||||
} else if (prefix_seen && cmd[1] == g.Cmd.spkeys[NHKF_ESC]) {
|
} else if (prefix_seen) {
|
||||||
/* <prefix><escape> */
|
if (cmd[1] == g.Cmd.spkeys[NHKF_ESC]) {
|
||||||
/* don't report "unknown command" for change of heart... */
|
/* <prefix><escape> */
|
||||||
bad_command = FALSE;
|
/* don't report "unknown command" for change of heart... */
|
||||||
|
bad_command = FALSE;
|
||||||
|
} else { /* prefix followed by non-movement command */
|
||||||
|
bad_command = TRUE; /* skip cmdlist[] loop */
|
||||||
|
}
|
||||||
} else if (*cmd == ' ' && !flags.rest_on_space) {
|
} else if (*cmd == ' ' && !flags.rest_on_space) {
|
||||||
bad_command = TRUE; /* skip cmdlist[] loop */
|
bad_command = TRUE; /* skip cmdlist[] loop */
|
||||||
|
|
||||||
@@ -3641,7 +3654,8 @@ static boolean
|
|||||||
prefix_cmd(c)
|
prefix_cmd(c)
|
||||||
char c;
|
char c;
|
||||||
{
|
{
|
||||||
return (c == g.Cmd.spkeys[NHKF_RUSH]
|
return (c == g.Cmd.spkeys[NHKF_REQMENU]
|
||||||
|
|| c == g.Cmd.spkeys[NHKF_RUSH]
|
||||||
|| c == g.Cmd.spkeys[NHKF_RUN]
|
|| c == g.Cmd.spkeys[NHKF_RUN]
|
||||||
|| c == g.Cmd.spkeys[NHKF_NOPICKUP]
|
|| c == g.Cmd.spkeys[NHKF_NOPICKUP]
|
||||||
|| c == g.Cmd.spkeys[NHKF_RUN_NOPICKUP]
|
|| c == g.Cmd.spkeys[NHKF_RUN_NOPICKUP]
|
||||||
@@ -4448,7 +4462,7 @@ parse()
|
|||||||
if (foo == g.Cmd.spkeys[NHKF_ESC]) { /* esc cancels count (TH) */
|
if (foo == g.Cmd.spkeys[NHKF_ESC]) { /* esc cancels count (TH) */
|
||||||
clear_nhwindow(WIN_MESSAGE);
|
clear_nhwindow(WIN_MESSAGE);
|
||||||
g.multi = g.last_multi = 0;
|
g.multi = g.last_multi = 0;
|
||||||
} else if (foo == g.Cmd.spkeys[NHKF_DOAGAIN] || g.in_doagain) {
|
} else if ((foo && foo == g.Cmd.spkeys[NHKF_DOAGAIN]) || g.in_doagain) {
|
||||||
g.multi = g.last_multi;
|
g.multi = g.last_multi;
|
||||||
} else {
|
} else {
|
||||||
g.last_multi = g.multi;
|
g.last_multi = g.multi;
|
||||||
|
|||||||
+11
-4
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.7 mdlib.c $NHDT-Date: 1596567095 2020/08/04 18:51:35 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.10 $ */
|
/* NetHack 3.7 mdlib.c $NHDT-Date: 1608933420 2020/12/25 21:57:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.17 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
|
/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
|
||||||
/* Copyright (c) M. Stephenson, 1990, 1991. */
|
/* Copyright (c) M. Stephenson, 1990, 1991. */
|
||||||
@@ -478,6 +478,13 @@ static const char *build_opts[] = {
|
|||||||
#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
|
#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
|
||||||
"external program as a message handler",
|
"external program as a message handler",
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HANGUPHANDLING) && !defined(NO_SIGNAL)
|
||||||
|
#ifdef SAFERHANGUP
|
||||||
|
"deferred handling of hangup signal",
|
||||||
|
#else
|
||||||
|
"immediate handling of hangup signal",
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#ifdef INSURANCE
|
#ifdef INSURANCE
|
||||||
"insurance files for recovering from crashes",
|
"insurance files for recovering from crashes",
|
||||||
#endif
|
#endif
|
||||||
@@ -709,9 +716,9 @@ build_options()
|
|||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
#endif /* !MAKEDEFS_C && FOR_RUNTIME */
|
#endif /* !MAKEDEFS_C && FOR_RUNTIME */
|
||||||
opt_out_words(strcat(strcpy(buf, build_opts[i]),
|
Strcat(strcpy(buf, build_opts[i]),
|
||||||
(i < SIZE(build_opts) - 1) ? "," : "."),
|
(i < SIZE(build_opts) - 1) ? "," : ".");
|
||||||
&length);
|
opt_out_words(buf, &length);
|
||||||
}
|
}
|
||||||
opttext[idxopttext] = strdup(optbuf);
|
opttext[idxopttext] = strdup(optbuf);
|
||||||
if (idxopttext < (MAXOPT - 1))
|
if (idxopttext < (MAXOPT - 1))
|
||||||
|
|||||||
+20
-10
@@ -814,7 +814,8 @@ NetHackQtMainWindow::NetHackQtMainWindow(NetHackQtKeyBuffer& ks) :
|
|||||||
QSignalMapper* sm = new QSignalMapper(this);
|
QSignalMapper* sm = new QSignalMapper(this);
|
||||||
connect(sm, SIGNAL(mapped(const QString&)),
|
connect(sm, SIGNAL(mapped(const QString&)),
|
||||||
this, SLOT(doKeys(const QString&)));
|
this, SLOT(doKeys(const QString&)));
|
||||||
// 'donull' is a placeholder here; AddToolButton() will fix it up
|
// 'donull' is a placeholder here; AddToolButton() will fix it up;
|
||||||
|
// button will be omitted if DOAGAIN is bound to '\0'
|
||||||
AddToolButton(toolbar, sm, "Again", donull, QPixmap(again_xpm));
|
AddToolButton(toolbar, sm, "Again", donull, QPixmap(again_xpm));
|
||||||
// this used to be called "Get" which is confusing to experienced players
|
// this used to be called "Get" which is confusing to experienced players
|
||||||
AddToolButton(toolbar, sm, "Pick up", dopickup, QPixmap(pickup_xpm));
|
AddToolButton(toolbar, sm, "Pick up", dopickup, QPixmap(pickup_xpm));
|
||||||
@@ -888,20 +889,29 @@ NetHackQtMainWindow::NetHackQtMainWindow(NetHackQtKeyBuffer& ks) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add a toolbar button to invoke command 'name' via function '(*func)()'
|
||||||
void NetHackQtMainWindow::AddToolButton(QToolBar *toolbar, QSignalMapper *sm,
|
void NetHackQtMainWindow::AddToolButton(QToolBar *toolbar, QSignalMapper *sm,
|
||||||
const char *name, int NDECL((*func)),
|
const char *name, int NDECL((*func)),
|
||||||
QPixmap xpm)
|
QPixmap xpm)
|
||||||
{
|
{
|
||||||
QToolButton *tb = new SmallToolButton(xpm, QString(name), "Action",
|
char actchar[2];
|
||||||
sm, SLOT(map()), toolbar);
|
uchar key;
|
||||||
char actchar[32];
|
|
||||||
// the ^A command is just a keystroke, not a full blown command function
|
// the ^A command is just a keystroke, not a full blown command function
|
||||||
if (!strcmp(name, "Again"))
|
if (!strcmp(name, "Again")) {
|
||||||
(void) strkitten(actchar, ::g.Cmd.spkeys[NHKF_DOAGAIN]);
|
key = ::g.Cmd.spkeys[NHKF_DOAGAIN];
|
||||||
else
|
} else
|
||||||
Sprintf(actchar, "%c", cmd_from_func(func));
|
key = (uchar) cmd_from_func(func);
|
||||||
sm->setMapping(tb, actchar);
|
|
||||||
toolbar->addWidget(tb);
|
// if key is valid, add a button for it; otherwise omit the command
|
||||||
|
// (won't work as intended if a different command is bound to same key)
|
||||||
|
if (key) {
|
||||||
|
QToolButton *tb = new SmallToolButton(xpm, QString(name), "Action",
|
||||||
|
sm, SLOT(map()), toolbar);
|
||||||
|
actchar[0] = '\0';
|
||||||
|
sm->setMapping(tb, strkitten(actchar, (char) key));
|
||||||
|
toolbar->addWidget(tb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetHackQtMainWindow::zoomMap()
|
void NetHackQtMainWindow::zoomMap()
|
||||||
|
|||||||
Reference in New Issue
Block a user