Add toggle extended command
Allows the user to configure a key binding to toggle any boolean option, for example: BIND=':toggle(price_quotes) BIND=v:toggle(autodig) The option must be settable in-game.
This commit is contained in:
@@ -1754,6 +1754,18 @@ floor container menu.
|
|||||||
.lp ""
|
.lp ""
|
||||||
Autocompletes.
|
Autocompletes.
|
||||||
Default key is \(oqM-T\(cq.
|
Default key is \(oqM-T\(cq.
|
||||||
|
.lp "#toggle "
|
||||||
|
Toggle a boolean option on or off.
|
||||||
|
Requires a parameter in parenthesis, the name of the option to toggle.
|
||||||
|
The option must be settable in-game.
|
||||||
|
.lp ""
|
||||||
|
For example:
|
||||||
|
.sd
|
||||||
|
.ft CR
|
||||||
|
BIND=':toggle(price_quotes)
|
||||||
|
BIND=@:toggle(autopickup)
|
||||||
|
.ft
|
||||||
|
.ed
|
||||||
.lp "#travel "
|
.lp "#travel "
|
||||||
Travel to a specific location on the map.
|
Travel to a specific location on the map.
|
||||||
Default key is \(oq_\(cq. \" underscore
|
Default key is \(oq_\(cq. \" underscore
|
||||||
|
|||||||
@@ -1826,6 +1826,21 @@ floor container menu.
|
|||||||
\\
|
\\
|
||||||
%.lp ""
|
%.lp ""
|
||||||
Autocompletes. Default key is `\texttt{M-T}'.
|
Autocompletes. Default key is `\texttt{M-T}'.
|
||||||
|
%.lp
|
||||||
|
\item[\#toggle]
|
||||||
|
Toggle a boolean option on or off.
|
||||||
|
Requires a parameter in parenthesis, the name of the option to toggle.
|
||||||
|
The option must be settable in-game.
|
||||||
|
|
||||||
|
%.lp ""
|
||||||
|
For example:
|
||||||
|
%.sd
|
||||||
|
\begin{verbatim}
|
||||||
|
BIND=':toggle(price_quotes)
|
||||||
|
BIND=@:toggle(autopickup)
|
||||||
|
\end{verbatim}
|
||||||
|
%.ed
|
||||||
|
|
||||||
%.lp
|
%.lp
|
||||||
\item[\#travel]
|
\item[\#travel]
|
||||||
Travel to a specific location on the map.
|
Travel to a specific location on the map.
|
||||||
|
|||||||
@@ -2912,6 +2912,7 @@ the game now automatically tracks which sell prices and buy prices you have
|
|||||||
new shields: shield of shock resistance, shield of drain resistance
|
new shields: shield of shock resistance, shield of drain resistance
|
||||||
new wand: wand of stasis
|
new wand: wand of stasis
|
||||||
early-game monsters always miss with their first use of an attack wand
|
early-game monsters always miss with their first use of an attack wand
|
||||||
|
new command #toggle which can be used to toggle a boolean option
|
||||||
|
|
||||||
|
|
||||||
Platform- and/or Interface-Specific New Features
|
Platform- and/or Interface-Specific New Features
|
||||||
|
|||||||
@@ -371,6 +371,7 @@ extern void change_palette(void);
|
|||||||
/* ### cmd.c ### */
|
/* ### cmd.c ### */
|
||||||
|
|
||||||
extern void cmdbind_freeall(void);
|
extern void cmdbind_freeall(void);
|
||||||
|
extern int dotoggleoption(void);
|
||||||
extern void set_move_cmd(int, int);
|
extern void set_move_cmd(int, int);
|
||||||
extern int do_move_west(void);
|
extern int do_move_west(void);
|
||||||
extern int do_move_northwest(void);
|
extern int do_move_northwest(void);
|
||||||
@@ -2285,6 +2286,7 @@ extern char *get_option_value(const char *, boolean) NONNULLARG1;
|
|||||||
extern int doset_simple(void);
|
extern int doset_simple(void);
|
||||||
extern int doset(void);
|
extern int doset(void);
|
||||||
extern int dotogglepickup(void);
|
extern int dotogglepickup(void);
|
||||||
|
extern int toggle_bool_option(const char *);
|
||||||
extern void option_help(void);
|
extern void option_help(void);
|
||||||
extern void all_options_strbuf(strbuf_t *) NONNULLARG1;
|
extern void all_options_strbuf(strbuf_t *) NONNULLARG1;
|
||||||
extern void next_opt(winid, const char *) NONNULLARG2;
|
extern void next_opt(winid, const char *) NONNULLARG2;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#define MOUSECMD 0x0800 /* cmd allowed to be bound to mouse button */
|
#define MOUSECMD 0x0800 /* cmd allowed to be bound to mouse button */
|
||||||
#define CMD_INSANE 0x1000 /* suppress sanity check (for ^P and ^R) */
|
#define CMD_INSANE 0x1000 /* suppress sanity check (for ^P and ^R) */
|
||||||
#define AUTOCOMP_ADJ 0x2000 /* user changed command autocompletion */
|
#define AUTOCOMP_ADJ 0x2000 /* user changed command autocompletion */
|
||||||
|
#define CMD_PARAM 0x4000 /* command requires a param from key bind */
|
||||||
|
|
||||||
/* flags for extcmds_match() */
|
/* flags for extcmds_match() */
|
||||||
#define ECM_NOFLAGS 0
|
#define ECM_NOFLAGS 0
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
struct Cmd_bind {
|
struct Cmd_bind {
|
||||||
uchar key;
|
uchar key;
|
||||||
boolean userbind; /* added by user */
|
boolean userbind; /* added by user */
|
||||||
|
char *param;
|
||||||
const struct ext_func_tab *cmd;
|
const struct ext_func_tab *cmd;
|
||||||
struct Cmd_bind *next;
|
struct Cmd_bind *next;
|
||||||
};
|
};
|
||||||
|
|||||||
106
src/cmd.c
106
src/cmd.c
@@ -1368,6 +1368,21 @@ dolookaround(void)
|
|||||||
return ECMD_OK;
|
return ECMD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* #toggle extended command
|
||||||
|
|
||||||
|
BIND=':toggle(price_quotes)
|
||||||
|
BIND=@:toggle(autopickup) */
|
||||||
|
int
|
||||||
|
dotoggleoption(void)
|
||||||
|
{
|
||||||
|
if (gc.cmd_bind && gc.cmd_bind->param) {
|
||||||
|
return toggle_bool_option(gc.cmd_bind->param);
|
||||||
|
} else {
|
||||||
|
pline("Use #optionsfull to set any option instead.");
|
||||||
|
return ECMD_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_move_cmd(int dir, int run)
|
set_move_cmd(int dir, int run)
|
||||||
{
|
{
|
||||||
@@ -1889,6 +1904,8 @@ struct ext_func_tab extcmdlist[] = {
|
|||||||
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
|
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
|
||||||
{ M('T'), "tip", "empty a container",
|
{ M('T'), "tip", "empty a container",
|
||||||
dotip, AUTOCOMPLETE | CMD_M_PREFIX, NULL },
|
dotip, AUTOCOMPLETE | CMD_M_PREFIX, NULL },
|
||||||
|
{ '\0', "toggle", "toggle boolean option",
|
||||||
|
dotoggleoption, IFBURIED | GENERALCMD | CMD_PARAM, NULL },
|
||||||
{ '_', "travel", "travel to a specific location on the map",
|
{ '_', "travel", "travel to a specific location on the map",
|
||||||
dotravel, CMD_M_PREFIX, NULL },
|
dotravel, CMD_M_PREFIX, NULL },
|
||||||
{ M('t'), "turn", "turn undead away",
|
{ M('t'), "turn", "turn undead away",
|
||||||
@@ -2119,11 +2136,16 @@ cmdbind_add(uchar key, const struct ext_func_tab *extcmd, boolean user)
|
|||||||
if (bind) {
|
if (bind) {
|
||||||
bind->cmd = extcmd;
|
bind->cmd = extcmd;
|
||||||
bind->userbind = user;
|
bind->userbind = user;
|
||||||
|
if (bind->param) {
|
||||||
|
free(bind->param);
|
||||||
|
bind->param = NULL;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
bind = (struct Cmd_bind *) alloc(sizeof(struct Cmd_bind));
|
bind = (struct Cmd_bind *) alloc(sizeof(struct Cmd_bind));
|
||||||
bind->key = key;
|
bind->key = key;
|
||||||
bind->userbind = user;
|
bind->userbind = user;
|
||||||
|
bind->param = NULL;
|
||||||
bind->cmd = extcmd;
|
bind->cmd = extcmd;
|
||||||
bind->next = gc.Cmd.cmdbinds;
|
bind->next = gc.Cmd.cmdbinds;
|
||||||
gc.Cmd.cmdbinds = bind;
|
gc.Cmd.cmdbinds = bind;
|
||||||
@@ -2142,6 +2164,8 @@ cmdbind_remove(uchar key)
|
|||||||
prev->next = bind->next;
|
prev->next = bind->next;
|
||||||
else
|
else
|
||||||
gc.Cmd.cmdbinds = bind->next;
|
gc.Cmd.cmdbinds = bind->next;
|
||||||
|
if (bind->param)
|
||||||
|
free(bind->param);
|
||||||
free(bind);
|
free(bind);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2157,6 +2181,8 @@ cmdbind_freeall(void)
|
|||||||
|
|
||||||
while (gc.Cmd.cmdbinds) {
|
while (gc.Cmd.cmdbinds) {
|
||||||
next = gc.Cmd.cmdbinds->next;
|
next = gc.Cmd.cmdbinds->next;
|
||||||
|
if (gc.Cmd.cmdbinds->param)
|
||||||
|
free(gc.Cmd.cmdbinds->param);
|
||||||
free(gc.Cmd.cmdbinds);
|
free(gc.Cmd.cmdbinds);
|
||||||
gc.Cmd.cmdbinds = next;
|
gc.Cmd.cmdbinds = next;
|
||||||
}
|
}
|
||||||
@@ -2222,9 +2248,15 @@ get_changed_key_binds(strbuf_t *sbuf)
|
|||||||
while (bind) {
|
while (bind) {
|
||||||
keys[bind->key] = 1;
|
keys[bind->key] = 1;
|
||||||
if (bind->userbind && bind->cmd && bind->cmd->key != bind->key) {
|
if (bind->userbind && bind->cmd && bind->cmd->key != bind->key) {
|
||||||
Sprintf(buf, "BIND=%s:%s%s", key2txt(bind->key, buf2),
|
if ((bind->cmd->flags & CMD_PARAM) != 0)
|
||||||
bind->cmd->ef_txt,
|
Sprintf(buf, "BIND=%s:%s(%s)%s", key2txt(bind->key, buf2),
|
||||||
sbuf ? "\n" : "");
|
bind->cmd->ef_txt,
|
||||||
|
bind->param,
|
||||||
|
sbuf ? "\n" : "");
|
||||||
|
else
|
||||||
|
Sprintf(buf, "BIND=%s:%s%s", key2txt(bind->key, buf2),
|
||||||
|
bind->cmd->ef_txt,
|
||||||
|
sbuf ? "\n" : "");
|
||||||
if (sbuf)
|
if (sbuf)
|
||||||
strbuf_append(sbuf, buf);
|
strbuf_append(sbuf, buf);
|
||||||
else
|
else
|
||||||
@@ -2319,18 +2351,31 @@ handler_rebind_keys_add(boolean keyfirst)
|
|||||||
destroy_nhwindow(win);
|
destroy_nhwindow(win);
|
||||||
if (npick > 0) {
|
if (npick > 0) {
|
||||||
struct Cmd_bind *prevcmd;
|
struct Cmd_bind *prevcmd;
|
||||||
const char *cmdstr;
|
char cmdstr[BUFSZ];
|
||||||
|
|
||||||
i = picks->item.a_int;
|
i = picks->item.a_int;
|
||||||
free((genericptr_t) picks);
|
free((genericptr_t) picks);
|
||||||
|
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
ec = NULL;
|
ec = NULL;
|
||||||
cmdstr = "nothing";
|
Strcat(cmdstr, "nothing");
|
||||||
goto bindit;
|
goto bindit;
|
||||||
} else {
|
} else {
|
||||||
ec = &extcmdlist[i-1];
|
ec = &extcmdlist[i-1];
|
||||||
cmdstr = ec->ef_txt;
|
|
||||||
|
if ((ec->flags & CMD_PARAM) != 0) {
|
||||||
|
char parambuf[BUFSZ];
|
||||||
|
char querybuf[BUFSZ];
|
||||||
|
|
||||||
|
parambuf[0] = '\0';
|
||||||
|
Sprintf(querybuf, "Command %s requires a parameter:", ec->ef_txt);
|
||||||
|
getlin(querybuf, parambuf);
|
||||||
|
(void) mungspaces(parambuf);
|
||||||
|
Snprintf(cmdstr, BUFSZ-1, "%s(%s)", ec->ef_txt, parambuf);
|
||||||
|
cmdstr[BUFSZ-1] = '\0';
|
||||||
|
} else {
|
||||||
|
Strcat(cmdstr, ec->ef_txt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bindit:
|
bindit:
|
||||||
if (!key) {
|
if (!key) {
|
||||||
@@ -2615,6 +2660,8 @@ boolean
|
|||||||
bind_key(uchar key, const char *command, boolean user)
|
bind_key(uchar key, const char *command, boolean user)
|
||||||
{
|
{
|
||||||
struct ext_func_tab *extcmd;
|
struct ext_func_tab *extcmd;
|
||||||
|
long len;
|
||||||
|
char *buf, *p = NULL, *lastp = NULL;
|
||||||
|
|
||||||
/* special case: "nothing" is reserved for unbinding */
|
/* special case: "nothing" is reserved for unbinding */
|
||||||
if (!strcmpi(command, "nothing")) {
|
if (!strcmpi(command, "nothing")) {
|
||||||
@@ -2622,12 +2669,46 @@ bind_key(uchar key, const char *command, boolean user)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy command to buf for modification */
|
||||||
|
len = strlen(command) + 1;
|
||||||
|
buf = (char *)alloc(len);
|
||||||
|
(void) strncpy(buf, command, len);
|
||||||
|
|
||||||
|
/* does buf have a parameter in parenthesis? */
|
||||||
|
if ((p = strchr(buf, '(')) != 0
|
||||||
|
&& (lastp = strrchr(buf, ')')) != 0
|
||||||
|
&& (lastp > p)) {
|
||||||
|
*p = '\0';
|
||||||
|
*lastp = '\0';
|
||||||
|
/* p points to the parameter */
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
|
for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
|
||||||
if (strcmpi(command, extcmd->ef_txt))
|
if (strcmpi(buf, extcmd->ef_txt))
|
||||||
continue;
|
continue;
|
||||||
if ((extcmd->flags & INTERNALCMD) != 0)
|
if ((extcmd->flags & INTERNALCMD) != 0)
|
||||||
continue;
|
continue;
|
||||||
cmdbind_add(key, extcmd, user);
|
cmdbind_add(key, extcmd, user);
|
||||||
|
|
||||||
|
if ((extcmd->flags & CMD_PARAM) != 0) {
|
||||||
|
if (!p) {
|
||||||
|
config_error_add("'%s' requires a parameter", buf);
|
||||||
|
} else {
|
||||||
|
struct Cmd_bind *bind = cmdbind_get(key);
|
||||||
|
int maxlen = min(30, strlen(p)) + 1;
|
||||||
|
|
||||||
|
if (maxlen <= 1) {
|
||||||
|
config_error_add("Required parameter cannot be empty");
|
||||||
|
} else {
|
||||||
|
bind->param = (char *) alloc(maxlen);
|
||||||
|
(void) strncpy(bind->param, p, maxlen);
|
||||||
|
bind->param[maxlen-1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (p && strlen(p) > 0)
|
||||||
|
config_error_add("'%s' does not take a parameter", buf);
|
||||||
|
|
||||||
#if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */
|
#if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */
|
||||||
if ((extcmd->flags & CMD_NOT_AVAILABLE) != 0) {
|
if ((extcmd->flags & CMD_NOT_AVAILABLE) != 0) {
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
@@ -2636,9 +2717,11 @@ bind_key(uchar key, const char *command, boolean user)
|
|||||||
config_error_add("%s", buf);
|
config_error_add("%s", buf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
free(buf);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2742,8 +2825,13 @@ keylist_putcmds(winid datawin, boolean docount,
|
|||||||
count++;
|
count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Sprintf(buf, "%-7s %-13s %s", key2txt(key, buf2),
|
if ((bind->cmd->flags & CMD_PARAM) != 0)
|
||||||
bind->cmd->ef_txt, bind->cmd->ef_desc);
|
Sprintf(buf, "%-7s %-13s %s \"%s\"", key2txt(key, buf2),
|
||||||
|
bind->cmd->ef_txt, bind->cmd->ef_desc,
|
||||||
|
bind->param);
|
||||||
|
else
|
||||||
|
Sprintf(buf, "%-7s %-13s %s", key2txt(key, buf2),
|
||||||
|
bind->cmd->ef_txt, bind->cmd->ef_desc);
|
||||||
putstr(datawin, 0, buf);
|
putstr(datawin, 0, buf);
|
||||||
keys_used[i] = TRUE;
|
keys_used[i] = TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,6 +390,7 @@ staticfn boolean parse_role_opt(int, boolean, const char *, char *, char **);
|
|||||||
staticfn char *get_cnf_role_opt(int);
|
staticfn char *get_cnf_role_opt(int);
|
||||||
staticfn unsigned int longest_option_name(int, int);
|
staticfn unsigned int longest_option_name(int, int);
|
||||||
staticfn int doset_simple_menu(void);
|
staticfn int doset_simple_menu(void);
|
||||||
|
staticfn void reset_needed_visuals(void);
|
||||||
staticfn void doset_add_menu(winid, const char *, const char *, int, int);
|
staticfn void doset_add_menu(winid, const char *, const char *, int, int);
|
||||||
staticfn int handle_add_list_remove(const char *, int);
|
staticfn int handle_add_list_remove(const char *, int);
|
||||||
staticfn void all_options_conds(strbuf_t *);
|
staticfn void all_options_conds(strbuf_t *);
|
||||||
@@ -9012,6 +9013,15 @@ doset(void) /* changing options via menu by Per Liboriussen */
|
|||||||
goto rerun;
|
goto rerun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_needed_visuals();
|
||||||
|
return ECMD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef HELP_IDX
|
||||||
|
|
||||||
|
staticfn void
|
||||||
|
reset_needed_visuals(void)
|
||||||
|
{
|
||||||
if (go.opt_need_glyph_reset) {
|
if (go.opt_need_glyph_reset) {
|
||||||
reset_glyphmap(gm_optionchange);
|
reset_glyphmap(gm_optionchange);
|
||||||
}
|
}
|
||||||
@@ -9039,11 +9049,13 @@ doset(void) /* changing options via menu by Per Liboriussen */
|
|||||||
if (disp.botl || disp.botlx) {
|
if (disp.botl || disp.botlx) {
|
||||||
bot();
|
bot();
|
||||||
}
|
}
|
||||||
return ECMD_OK;
|
go.opt_need_redraw = FALSE;
|
||||||
|
go.opt_need_glyph_reset = FALSE;
|
||||||
|
go.opt_reset_customcolors = FALSE;
|
||||||
|
go.opt_reset_customsymbols = FALSE;
|
||||||
|
go.opt_update_basic_palette = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef HELP_IDX
|
|
||||||
|
|
||||||
/* doset(#optionsfull command) menu entries for compound options */
|
/* doset(#optionsfull command) menu entries for compound options */
|
||||||
staticfn void
|
staticfn void
|
||||||
doset_add_menu(
|
doset_add_menu(
|
||||||
@@ -9304,6 +9316,29 @@ dotogglepickup(void)
|
|||||||
return ECMD_OK;
|
return ECMD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* toggle any (settable in-game) boolean option by name */
|
||||||
|
int
|
||||||
|
toggle_bool_option(const char *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int ret = ECMD_FAIL;
|
||||||
|
|
||||||
|
for (i = 0; i < OPTCOUNT; i++)
|
||||||
|
if (!strncmpi(allopt[i].name, p, strlen(p))
|
||||||
|
&& allopt[i].opttyp == BoolOpt
|
||||||
|
&& allopt[i].setwhere == set_in_game
|
||||||
|
&& allopt[i].addr != 0) {
|
||||||
|
char buf[BUFSZ];
|
||||||
|
|
||||||
|
Sprintf(buf, "%s%s", *allopt[i].addr ? "!" : "", allopt[i].name);
|
||||||
|
if (parseoptions(buf, FALSE, FALSE))
|
||||||
|
ret = ECMD_OK;
|
||||||
|
|
||||||
|
reset_needed_visuals();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
add_autopickup_exception(const char *mapping)
|
add_autopickup_exception(const char *mapping)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user