static int FDECL(keylist_putcmds, (winid, BOOLEAN_P, int, int, boolean *));
static int FDECL(ch2spkeys, (CHAR_P, int, int));
static boolean FDECL(prefix_cmd, (CHAR_P));
+static const char *FDECL(spkey_name, (int));
static int NDECL((*timed_occ_fn));
static char *FDECL(doc_extcmd_flagstr, (winid, const struct ext_func_tab *));
struct ext_func_tab *extcmd;
/* special case: "nothing" is reserved for unbinding */
- if (!strcmp(command, "nothing")) {
+ if (!strcmpi(command, "nothing")) {
g.Cmd.commands[key] = (struct ext_func_tab *) 0;
return TRUE;
}
for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
- if (strcmp(command, extcmd->ef_txt))
+ if (strcmpi(command, extcmd->ef_txt))
continue;
g.Cmd.commands[key] = extcmd;
#if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */
void
dokeylist(VOID_ARGS)
{
- const struct ext_func_tab *extcmd;
- char buf[BUFSZ], buf2[BUFSZ];
- uchar key;
- boolean keys_used[256];
- winid datawin;
- int i;
static const char
run_desc[] = "Prefix: run until something very interesting is seen",
rush_desc[] = "Prefix: rush until something interesting is seen",
"Prefix: move without picking up objects or fighting", FALSE },
{ NHKF_RUN_NOPICKUP,
"Prefix: run without picking up objects or fighting", FALSE },
- { NHKF_DOINV, "view full inventory", TRUE },
- /* NHKF_DOINV2 for num_pad+pcHack_compat isn't implemented */
- /* { NHKF_DOINV2, "view inventory of one class of objects", TRUE }, */
- { NHKF_REQMENU, "Prefix: request a menu", FALSE },
+ { NHKF_REQMENU,
+ "Prefix: request a menu (for some non-movement commands)", FALSE },
{ NHKF_COUNT,
- "Prefix: for digits when prefixing a command with a count", TRUE },
- { NHKF_DOAGAIN , "re-do: perform the previous command again", FALSE },
+ "Prefix: for digits when preceding a command with a count", TRUE },
+ { NHKF_DOINV, "numpad: view full inventory", TRUE },
+ /* NHKF_DOINV2 for num_pad+pcHack_compat isn't implemented */
+ /* { NHKF_DOINV2, "numpad: view inventory of one class of objects",
+ TRUE }, */
+ { NHKF_DOAGAIN , "repeat: perform the previous command again", FALSE },
{ 0, (const char *) 0, FALSE }
};
+ const struct ext_func_tab *extcmd;
+ winid datawin;
+ char buf[BUFSZ], buf2[BUFSZ];
+ uchar key;
+ boolean spkey_gap, keys_used[256], mov_seen[256];
+ int i, j, pfx_seen[256];
(void) memset((genericptr_t) keys_used, 0, sizeof keys_used);
+ (void) memset((genericptr_t) pfx_seen, 0, sizeof pfx_seen);
keys_used[(uchar) g.Cmd.move_NW] = keys_used[(uchar) g.Cmd.move_N]
= keys_used[(uchar) g.Cmd.move_NE] = keys_used[(uchar) g.Cmd.move_W]
= keys_used[(uchar) M('6')] = keys_used[(uchar) M('7')]
= keys_used[(uchar) M('8')] = keys_used[(uchar) M('9')] = TRUE;
}
- for (i = 0; misc_keys[i].desc; ++i) {
- key = (uchar) g.Cmd.spkeys[misc_keys[i].nhkf];
- if (key && ((misc_keys[i].numpad && iflags.num_pad)
- || !misc_keys[i].numpad)) {
- keys_used[key] = TRUE;
- }
- }
#ifndef NO_SIGNAL
- /* this is actually ambiguous; tty raw mode will override SIGINT */
+ /* this is actually ambiguous; tty raw mode will override SIGINT;
+ when enabled, treat it like a movement command since assigning
+ other commands to this keystroke would be unwise... */
key = (uchar) C('c');
keys_used[key] = TRUE;
#endif
+ /* movement keys have been flagged in keys_used[]; clone them */
+ (void) memcpy((genericptr_t) mov_seen, (genericptr_t) keys_used,
+ sizeof mov_seen);
+
+ spkey_gap = FALSE;
+ for (i = 0; misc_keys[i].desc; ++i) {
+ if (misc_keys[i].numpad && !iflags.num_pad)
+ continue;
+ j = misc_keys[i].nhkf;
+ key = (uchar) g.Cmd.spkeys[j];
+ if (key && !mov_seen[key] && (!pfx_seen[key] || j == NHKF_REQMENU)) {
+ keys_used[key] = TRUE;
+ if (j != NHKF_REQMENU)
+ pfx_seen[key] = j;
+ } else
+ spkey_gap = TRUE;
+ }
+
datawin = create_nhwindow(NHW_TEXT);
putstr(datawin, 0, "");
Sprintf(buf, "%7s %s", "", " Full Current Key Bindings List");
putstr(datawin, 0, buf);
for (extcmd = extcmdlist; extcmd->ef_txt; ++extcmd)
- if (!keylist_func_has_key(extcmd, keys_used)) {
+ if (spkey_gap || !keylist_func_has_key(extcmd, keys_used)) {
Sprintf(buf, "%7s %s", "",
"(also commands with no key assignment)");
putstr(datawin, 0, buf);
putstr(datawin, 0, "");
putstr(datawin, 0, "Miscellaneous keys:");
for (i = 0; misc_keys[i].desc; ++i) {
- key = (uchar) g.Cmd.spkeys[misc_keys[i].nhkf];
- if (key && ((misc_keys[i].numpad && iflags.num_pad)
- || !misc_keys[i].numpad)) {
+ if (misc_keys[i].numpad && !iflags.num_pad)
+ continue;
+ j = misc_keys[i].nhkf;
+ key = (uchar) g.Cmd.spkeys[j];
+ if (key && !mov_seen[key]
+ && (pfx_seen[key] == j || j == NHKF_REQMENU)) {
Sprintf(buf, "%-7s %s", key2txt(key, buf2), misc_keys[i].desc);
putstr(datawin, 0, buf);
}
}
-#ifndef NO_SIGNAL
/* (see above) */
key = (uchar) C('c');
- Sprintf(buf, "%-7s %s", key2txt(key, buf2),
- "break out of NetHack (SIGINT)");
- putstr(datawin, 0, buf);
+#ifndef NO_SIGNAL
+ /* last of the special keys */
+ Sprintf(buf, "%-7s", key2txt(key, buf2));
+#else
+ /* first of the keyless commands */
+ Sprintf(buf2, "[%s]", key2txt(key, buf));
+ Sprintf(buf, "%-21s", buf2);
#endif
+ Strcat(buf, " interrupt: break out of NetHack (SIGINT)");
+ putstr(datawin, 0, buf);
+ /* keyless special key commands, if any */
+ if (spkey_gap) {
+ for (i = 0; misc_keys[i].desc; ++i) {
+ if (misc_keys[i].numpad && !iflags.num_pad)
+ continue;
+ j = misc_keys[i].nhkf;
+ key = (uchar) g.Cmd.spkeys[j];
+ if (!key || (pfx_seen[key] != j && j != NHKF_REQMENU)) {
+ Sprintf(buf2, "[%s]", spkey_name(j));
+ /* lines up with the other unassigned commands which use
+ "#%-20s ", but not with the other special keys */
+ Sprintf(buf, "%-21s %s", buf2, misc_keys[i].desc);
+ putstr(datawin, 0, buf);
+ }
+ }
+ }
putstr(datawin, 0, "");
show_menu_controls(datawin, TRUE);
const char *command;
{
int i;
+
for (i = 0; i < SIZE(spkeys_binds); i++) {
if (!spkeys_binds[i].name || strcmp(command, spkeys_binds[i].name))
continue;
return FALSE;
}
+static const char *
+spkey_name(nhkf)
+int nhkf;
+{
+ const char *name = 0;
+ int i;
+
+ for (i = 0; i < SIZE(spkeys_binds); i++) {
+ if (spkeys_binds[i].nhkf == nhkf) {
+ name = (nhkf == NHKF_ESC) ? "escape" : spkeys_binds[i].name;
+ break;
+ }
+ }
+ return name;
+}
+
/* returns a one-byte character from the text; may change txt[] */
uchar
txt2key(txt)