command handling for !SHELL and !SUSPEND

Change the command list to always include #shell and #suspend so that
a user's preferred key bindings can span platforms without worrying
about whether those exist or not.  They're still effectively no-ops
when compiled out.

'#?' suppresses them from the list of displayed commands.  Interface-
specific extended command handling may want to check new extcmd.flag
value CMD_NOT_AVAILABLE to do the same, but failing to do so shouldn't
pose a problem.  They behave sanely if executed when not supported.
This commit is contained in:
PatR
2018-12-02 16:43:53 -08:00
parent 7e9bc20c3a
commit 13ef86488a
3 changed files with 69 additions and 36 deletions
+2
View File
@@ -275,6 +275,8 @@ Platform- and/or Interface-Specific Fixes or Features
----------------------------------------------------- -----------------------------------------------------
move 'perm_invent' value from flags to iflags to keep it out of save files; move 'perm_invent' value from flags to iflags to keep it out of save files;
affects X11, win32, and curses affects X11, win32, and curses
always define shell and suspend commands so that key bindings copied from one
platform to another work even if second one disables those commands
windows-gui: In nethackw, there could be conflicts between menu accelerators windows-gui: In nethackw, there could be conflicts between menu accelerators
and an extra choice accelerator to fix H7132. and an extra choice accelerator to fix H7132.
windows-gui: recognize new BL_RESET in status_update; no change in behavior yet windows-gui: recognize new BL_RESET in status_update; no change in behavior yet
+2 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 func_tab.h $NHDT-Date: 1432512775 2015/05/25 00:12:55 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */ /* NetHack 3.6 func_tab.h $NHDT-Date: 1543797823 2018/12/03 00:43:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.11 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2016. */ /*-Copyright (c) Pasi Kallinen, 2016. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -11,6 +11,7 @@
#define AUTOCOMPLETE 0x02 /* command autocompletes */ #define AUTOCOMPLETE 0x02 /* command autocompletes */
#define WIZMODECMD 0x04 /* wizard-mode command */ #define WIZMODECMD 0x04 /* wizard-mode command */
#define GENERALCMD 0x08 /* general command, does not take game time */ #define GENERALCMD 0x08 /* general command, does not take game time */
#define CMD_NOT_AVAILABLE 0x10 /* recognized but non-functional (!SHELL,&c) */
struct ext_func_tab { struct ext_func_tab {
uchar key; uchar key;
+65 -35
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 cmd.c $NHDT-Date: 1543711385 2018/12/02 00:43:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.309 $ */ /* NetHack 3.6 cmd.c $NHDT-Date: 1543797825 2018/12/03 00:43:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.312 $ */
/* 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. */
@@ -126,10 +126,10 @@ extern int NDECL(dozap); /**/
extern int NDECL(doorganize); /**/ extern int NDECL(doorganize); /**/
#endif /* DUMB */ #endif /* DUMB */
static int NDECL(dosuspend_core); /**/
static int NDECL((*timed_occ_fn)); static int NDECL((*timed_occ_fn));
STATIC_PTR int NDECL(dosuspend_core);
STATIC_PTR int NDECL(dosh_core);
STATIC_PTR int NDECL(doherecmdmenu); STATIC_PTR int NDECL(doherecmdmenu);
STATIC_PTR int NDECL(dotherecmdmenu); STATIC_PTR int NDECL(dotherecmdmenu);
STATIC_PTR int NDECL(doprev_message); STATIC_PTR int NDECL(doprev_message);
@@ -194,9 +194,6 @@ STATIC_DCL void FDECL(one_characteristic, (int, int, int));
STATIC_DCL void FDECL(status_enlightenment, (int, int)); STATIC_DCL void FDECL(status_enlightenment, (int, int));
STATIC_DCL void FDECL(attributes_enlightenment, (int, int)); STATIC_DCL void FDECL(attributes_enlightenment, (int, int));
static const char *readchar_queue = "";
static coord clicklook_cc;
STATIC_DCL void FDECL(add_herecmd_menuitem, (winid, int NDECL((*)), STATIC_DCL void FDECL(add_herecmd_menuitem, (winid, int NDECL((*)),
const char *)); const char *));
STATIC_DCL char FDECL(here_cmd_menu, (BOOLEAN_P)); STATIC_DCL char FDECL(here_cmd_menu, (BOOLEAN_P));
@@ -205,6 +202,13 @@ STATIC_DCL char *NDECL(parse);
STATIC_DCL void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P)); STATIC_DCL void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P));
STATIC_DCL boolean FDECL(help_dir, (CHAR_P, int, const char *)); STATIC_DCL boolean FDECL(help_dir, (CHAR_P, int, const char *));
static const char *readchar_queue = "";
static coord clicklook_cc;
/* for rejecting attempts to use wizard mode commands */
static const char unavailcmd[] = "Unavailable command '%s'.";
/* for rejecting #if !SHELL, !SUSPEND */
static const char cmdnotavail[] = "'%s' command not available.";
STATIC_PTR int STATIC_PTR int
doprev_message(VOID_ARGS) doprev_message(VOID_ARGS)
{ {
@@ -438,6 +442,8 @@ doextlist(VOID_ARGS)
for (efp = extcmdlist; efp->ef_txt; efp++) { for (efp = extcmdlist; efp->ef_txt; efp++) {
int wizc; int wizc;
if ((efp->flags & CMD_NOT_AVAILABLE) != 0)
continue;
/* if hiding non-autocomplete commands, skip such */ /* if hiding non-autocomplete commands, skip such */
if (menumode == 1 && (efp->flags & AUTOCOMPLETE) == 0) if (menumode == 1 && (efp->flags & AUTOCOMPLETE) == 0)
continue; continue;
@@ -567,7 +573,8 @@ extcmd_via_menu()
any = zeroany; any = zeroany;
/* populate choices */ /* populate choices */
for (efp = extcmdlist; efp->ef_txt; efp++) { for (efp = extcmdlist; efp->ef_txt; efp++) {
if (!(efp->flags & AUTOCOMPLETE) if ((efp->flags & CMD_NOT_AVAILABLE)
|| !(efp->flags & AUTOCOMPLETE)
|| (!wizard && (efp->flags & WIZMODECMD))) || (!wizard && (efp->flags & WIZMODECMD)))
continue; continue;
if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) { if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
@@ -763,8 +770,7 @@ wiz_wish(VOID_ARGS) /* Unlimited wishes for debug mode by Paul Polderman */
flags.verbose = save_verbose; flags.verbose = save_verbose;
(void) encumber_msg(); (void) encumber_msg();
} else } else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_wish)));
visctrl((int) cmd_from_func(wiz_wish)));
return 0; return 0;
} }
@@ -784,8 +790,7 @@ wiz_identify(VOID_ARGS)
(void) display_inventory((char *) 0, FALSE); (void) display_inventory((char *) 0, FALSE);
iflags.override_ID = 0; iflags.override_ID = 0;
} else } else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_identify)));
visctrl((int) cmd_from_func(wiz_identify)));
return 0; return 0;
} }
@@ -840,8 +845,7 @@ wiz_map(VOID_ARGS)
HConfusion = save_Hconf; HConfusion = save_Hconf;
HHallucination = save_Hhallu; HHallucination = save_Hhallu;
} else } else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_map)));
visctrl((int) cmd_from_func(wiz_map)));
return 0; return 0;
} }
@@ -852,8 +856,7 @@ wiz_genesis(VOID_ARGS)
if (wizard) if (wizard)
(void) create_particular(); (void) create_particular();
else else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_genesis)));
visctrl((int) cmd_from_func(wiz_genesis)));
return 0; return 0;
} }
@@ -864,8 +867,7 @@ wiz_where(VOID_ARGS)
if (wizard) if (wizard)
(void) print_dungeon(FALSE, (schar *) 0, (xchar *) 0); (void) print_dungeon(FALSE, (schar *) 0, (xchar *) 0);
else else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_where)));
visctrl((int) cmd_from_func(wiz_where)));
return 0; return 0;
} }
@@ -876,8 +878,7 @@ wiz_detect(VOID_ARGS)
if (wizard) if (wizard)
(void) findit(); (void) findit();
else else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_detect)));
visctrl((int) cmd_from_func(wiz_detect)));
return 0; return 0;
} }
@@ -888,8 +889,7 @@ wiz_level_tele(VOID_ARGS)
if (wizard) if (wizard)
level_tele(); level_tele();
else else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_level_tele)));
visctrl((int) cmd_from_func(wiz_level_tele)));
return 0; return 0;
} }
@@ -1444,8 +1444,7 @@ wiz_intrinsic(VOID_ARGS)
free((genericptr_t) pick_list); free((genericptr_t) pick_list);
doredraw(); doredraw();
} else } else
pline("Unavailable command '%s'.", pline(unavailcmd, visctrl((int) cmd_from_func(wiz_intrinsic)));
visctrl((int) cmd_from_func(wiz_intrinsic)));
return 0; return 0;
} }
@@ -3304,16 +3303,21 @@ struct ext_func_tab extcmdlist[] = {
{ '^', "seetrap", "show the type of adjacent trap", doidtrap, IFBURIED }, { '^', "seetrap", "show the type of adjacent trap", doidtrap, IFBURIED },
{ WEAPON_SYM, "seeweapon", "show the weapon currently wielded", { WEAPON_SYM, "seeweapon", "show the weapon currently wielded",
doprwep, IFBURIED }, doprwep, IFBURIED },
#ifdef SHELL { '!', "shell", "do a shell escape",
{ '!', "shell", "do a shell escape", dosh, IFBURIED | GENERALCMD }, dosh_core, IFBURIED | GENERALCMD
#ifndef SHELL
| CMD_NOT_AVAILABLE
#endif /* SHELL */ #endif /* SHELL */
},
{ M('s'), "sit", "sit down", dosit, AUTOCOMPLETE }, { M('s'), "sit", "sit down", dosit, AUTOCOMPLETE },
{ '\0', "stats", "show memory statistics", { '\0', "stats", "show memory statistics",
wiz_show_stats, IFBURIED | AUTOCOMPLETE | WIZMODECMD }, wiz_show_stats, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
#ifdef SUSPEND
{ C('z'), "suspend", "suspend the game", { C('z'), "suspend", "suspend the game",
dosuspend_core, IFBURIED | GENERALCMD }, dosuspend_core, IFBURIED | GENERALCMD
#ifndef SUSPEND
| CMD_NOT_AVAILABLE
#endif /* SUSPEND */ #endif /* SUSPEND */
},
{ 'x', "swap", "swap wielded and secondary weapons", doswapweapon }, { 'x', "swap", "swap wielded and secondary weapons", doswapweapon },
{ 'T', "takeoff", "take off one piece of armor", dotakeoff }, { 'T', "takeoff", "take off one piece of armor", dotakeoff },
{ 'A', "takeoffall", "remove all armor", doddoremarm }, { 'A', "takeoffall", "remove all armor", doddoremarm },
@@ -3407,6 +3411,14 @@ const char *command;
if (strcmp(command, extcmd->ef_txt)) if (strcmp(command, extcmd->ef_txt))
continue; continue;
Cmd.commands[key] = extcmd; Cmd.commands[key] = extcmd;
#if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */
if ((extcmd->flags & CMD_NOT_AVAILABLE) != 0) {
char buf[BUFSZ];
Sprintf(buf, cmdnotavail, extcmd->ef_txt);
config_error_add("%s", buf);
}
#endif
return TRUE; return TRUE;
} }
@@ -5504,10 +5516,7 @@ parse()
if (iflags.debug_fuzzer /* if fuzzing, override '!' and ^Z */ if (iflags.debug_fuzzer /* if fuzzing, override '!' and ^Z */
&& (Cmd.commands[foo & 0x0ff] && (Cmd.commands[foo & 0x0ff]
&& (Cmd.commands[foo & 0x0ff]->ef_funct == dosuspend_core && (Cmd.commands[foo & 0x0ff]->ef_funct == dosuspend_core
#ifdef SHELL || Cmd.commands[foo & 0x0ff]->ef_funct == dosh_core)))
|| Cmd.commands[foo & 0x0ff]->ef_funct == dosh
#endif
)))
foo = Cmd.spkeys[NHKF_ESC]; foo = Cmd.spkeys[NHKF_ESC];
if (foo == Cmd.spkeys[NHKF_ESC]) { /* esc cancels count (TH) */ if (foo == Cmd.spkeys[NHKF_ESC]) { /* esc cancels count (TH) */
@@ -5666,15 +5675,22 @@ readchar()
return (char) sym; return (char) sym;
} }
/* '_' command, #travel, via keyboard rather than mouse click */
STATIC_PTR int STATIC_PTR int
dotravel(VOID_ARGS) dotravel(VOID_ARGS)
{ {
/* Keyboard travel command */
static char cmd[2]; static char cmd[2];
coord cc; coord cc;
/* [FIXME? Supporting the ability to disable traveling via mouse
click makes some sense, depending upon overall mouse usage.
Disabling '_' on a user by user basis makes no sense at all since
even if it is typed by accident, aborting when picking a target
destination is trivial. Travel via mouse predates travel via '_',
and this use of OPTION=!travel is probably just a mistake....] */
if (!flags.travelcmd) if (!flags.travelcmd)
return 0; return 0;
cmd[1] = 0; cmd[1] = 0;
cc.x = iflags.travelcc.x; cc.x = iflags.travelcc.x;
cc.y = iflags.travelcc.y; cc.y = iflags.travelcc.y;
@@ -5789,8 +5805,9 @@ const char *prompt;
return confirmed_ok; return confirmed_ok;
} }
int /* ^Z command, #suspend */
dosuspend_core() STATIC_PTR int
dosuspend_core(VOID_ARGS)
{ {
#ifdef SUSPEND #ifdef SUSPEND
/* Does current window system support suspend? */ /* Does current window system support suspend? */
@@ -5799,7 +5816,20 @@ dosuspend_core()
dosuspend(); dosuspend();
} else } else
#endif #endif
Norep("Suspend command not available."); Norep(cmdnotavail, "#suspend");
return 0;
}
/* '!' command, #shell */
STATIC_PTR int
dosh_core(VOID_ARGS)
{
#ifdef SHELL
/* access restrictions, if any, are handled in port code */
dosh();
#else
Norep(cmdnotavail, "#shell");
#endif
return 0; return 0;
} }