]> granicus.if.org Git - nethack/commitdiff
options key parsing
authorPatR <rankin@nethack.org>
Wed, 10 Mar 2021 20:28:09 +0000 (12:28 -0800)
committerPatR <rankin@nethack.org>
Wed, 10 Mar 2021 20:28:09 +0000 (12:28 -0800)
  OPTIONS=menu_previous_page:\mv
  BINDINGS=M-v:menu_previous_page
both worked, but
  OPTIONS=menu_previous_page:M-v
  BINDINGS=\mv:menu_previous_page
both failed.  Make all four variations work.  Tiny change made large
by the need to move some things around.

The option definition for menu_first_page had a couple of its flag
bits swapped.  I didn't try to figure out whether that had any impact.

doc/fixes37.0
include/extern.h
include/global.h
include/optlist.h
src/cmd.c
src/options.c

index fe6096e4adf88790dcf905bf9e5fa8816f6b0f4a..0accbe7780064f4e09db1fc5c379a92b1c90c00d 100644 (file)
@@ -398,6 +398,11 @@ hero would be blinded and stunned by an Archon's radiance (gaze attack) even
 applying a polearm to attempt to attack a hidden monster would report "wait!
        there's a monster hidden there" and display the "remembered, unseen
        monster" glyph but only use a turn if polearm wasn't already wielded
+key parsing during options processing was inconsistent between OPTIONS=foo:k
+       BINDINGS=k:foo where k represents a key designation; the OPTIONS form
+       recognized backslash escape sequences but not M-x meta characters,
+       vice versa for BINDINGS (most noticeable for menu interaction keys
+       such as menu_next_page because those can be set via either directive)
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 1e597124d258f9ce84f322ed600c9331fd660573..90ff05575d041662d3ac29f9e714f198a1abb5aa 100644 (file)
@@ -210,7 +210,6 @@ extern void pushch(char);
 extern void savech(char);
 extern const char *key2extcmddesc(uchar);
 extern boolean bind_specialkey(uchar, const char *);
-extern uchar txt2key(char *);
 extern void parseautocomplete(char *, boolean);
 extern void reset_commands(boolean);
 extern void rhack(char *);
@@ -1784,6 +1783,7 @@ extern int shiny_obj(char);
 /* ### options.c ### */
 
 extern boolean match_optname(const char *, const char *, int, boolean);
+extern uchar txt2key(char *);
 extern void initoptions(void);
 extern void initoptions_init(void);
 extern void initoptions_finish(void);
index 2163e7659b862ff3de733316a51085d4d2405adb..5b6e7e3ace986ab4971ecb46448f7bd61de634ab 100644 (file)
@@ -443,4 +443,23 @@ struct savefile_info {
         (nhassert_failed(#expression, __FILE__, __LINE__), 0))
 #endif
 
+/* Macros for meta and ctrl modifiers:
+ *   M and C return the meta/ctrl code for the given character;
+ *     e.g., (C('c') is ctrl-c
+ */
+#ifndef M
+#ifndef NHSTDC
+#define M(c) (0x80 | (c))
+#else
+#define M(c) ((c) - 128)
+#endif /* NHSTDC */
+#endif
+
+#ifndef C
+#define C(c) (0x1f & (c))
+#endif
+
+#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
+#define unmeta(c) (0x7f & (c))
+
 #endif /* GLOBAL_H */
index fc667ce335e6020307e05256c1bc325586099298..a1b363330c7917bcf976bf036e44ca70c5049e1d 100644 (file)
@@ -263,8 +263,8 @@ opt_##a,
                 NoAlias, "deselect all items in a menu")
     NHOPTC(menu_deselect_page, 4, opt_in, set_in_config, No, Yes, No, No,
                 NoAlias, "deselect all items on this page of a menu")
-    NHOPTC(menu_first_page, 4, opt_in, set_in_config, No, No, Yes, No, NoAlias,
-                "jump to the first page in a menu")
+    NHOPTC(menu_first_page, 4, opt_in, set_in_config, No, Yes, No, No,
+                NoAlias, "jump to the first page in a menu")
     NHOPTC(menu_headings, 4, opt_in, set_in_game, No, Yes, No, Yes, NoAlias,
                 "display style for menu headings")
     NHOPTC(menu_invert_all, 4, opt_in, set_in_config, No, Yes, No, No, NoAlias,
index 6d42dceae6f1b294f3d1d3e5f9e512557e07d3b4..09156831dc9d460e94e04eab10930e24b9950663 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -6,25 +6,6 @@
 #include "hack.h"
 #include "func_tab.h"
 
-/* Macros for meta and ctrl modifiers:
- *   M and C return the meta/ctrl code for the given character;
- *     e.g., (C('c') is ctrl-c
- */
-#ifndef M
-#ifndef NHSTDC
-#define M(c) (0x80 | (c))
-#else
-#define M(c) ((c) - 128)
-#endif /* NHSTDC */
-#endif
-
-#ifndef C
-#define C(c) (0x1f & (c))
-#endif
-
-#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
-#define unmeta(c) (0x7f & (c))
-
 #ifdef ALTMETA
 static boolean alt_esc = FALSE;
 #endif
@@ -3045,96 +3026,6 @@ spkey_name(int nhkf)
     return name;
 }
 
-/* returns a one-byte character from the text; may change txt[] */
-uchar
-txt2key(char *txt)
-{
-    uchar uc;
-    boolean makemeta = FALSE;
-
-    txt = trimspaces(txt);
-    if (!*txt)
-        return '\0';
-
-    /* simple character */
-    if (!txt[1])
-        return (uchar) txt[0];
-
-    /* a few special entries */
-    if (!strcmp(txt, "<enter>"))
-        return '\n';
-    if (!strcmp(txt, "<space>"))
-        return ' ';
-    if (!strcmp(txt, "<esc>"))
-        return '\033';
-
-    /* control and meta keys */
-    if (highc(*txt) == 'M') {
-        /*
-         * M <nothing>             return 'M'
-         * M - <nothing>           return M-'-'
-         * M <other><nothing>      return M-<other>
-         * otherwise M is pending until after ^/C- processing.
-         * Since trailing spaces are discarded, the only way to
-         * specify M-' ' is via "160".
-         */
-        if (!txt[1])
-            return (uchar) *txt;
-        /* skip past 'M' or 'm' and maybe '-' */
-        ++txt;
-        if (*txt == '-' && txt[1])
-            ++txt;
-        if (!txt[1])
-            return M((uchar) *txt);
-        makemeta = TRUE;
-    }
-    if (*txt == '^' || highc(*txt) == 'C') {
-        /*
-         * C <nothing>             return 'C' or M-'C'
-         * C - <nothing>           return '-' or M-'-'
-         * C [-] <other><nothing>  return C-<other> or M-C-<other>
-         * C [-] ?                 return <rubout>
-         * otherwise return C-<other> or M-C-<other>
-         */
-        uc = (uchar) *txt;
-        if (!txt[1])
-            return makemeta ? M(uc) : uc;
-        ++txt;
-        /* unlike M-x, lots of values of x are invalid for C-x;
-           checking and rejecting them is not worthwhile; GIGO;
-           we do accept "^-x" as synonym for "^x" or "C-x" */
-        if (*txt == '-' && txt[1])
-            ++txt;
-        /* and accept ^?, which gets used despite not being a control char */
-        if (*txt == '?')
-            return (uchar) (makemeta ? '\377' : '\177'); /* rubout/delete */
-        uc = C((uchar) *txt);
-        return makemeta ? M(uc) : uc;
-    }
-    if (makemeta && *txt)
-        return M((uchar) *txt);
-
-    /* FIXME: should accept single-quote single-character single-quote
-       and probably single-quote backslash octal-digits single-quote;
-       if we do that, the M- and C- results should be pending until
-       after, so that C-'X' becomes valid for ^X */
-
-    /* ascii codes: must be three-digit decimal */
-    if (*txt >= '0' && *txt <= '9') {
-        uchar key = 0;
-        int i;
-
-        for (i = 0; i < 3; i++) {
-            if (txt[i] < '0' || txt[i] > '9')
-                return '\0';
-            key = 10 * key + txt[i] - '0';
-        }
-        return key;
-    }
-
-    return '\0';
-}
-
 /* returns the text for a one-byte encoding;
  * must be shorter than a tab for proper formatting */
 char *
index 9e662026af7893360f4092d1d87605bece7c7159..9d62633b3d5c86ca8acf0fc72dff42b339873f52 100644 (file)
@@ -4307,10 +4307,7 @@ spcfn_misc_menu_cmd(int midx, int req, boolean negated, char *opts, char *op)
             bad_negation(default_menu_cmd_info[midx].name, FALSE);
             return optn_err;
         } else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
-            char c, op_buf[BUFSZ];
-
-            escapes(op, op_buf);
-            c = *op_buf;
+            char c = txt2key(op);
 
             if (illegal_menu_cmd_key((uchar) c))
                 return optn_err;
@@ -5617,6 +5614,107 @@ escapes(const char *cp, /* might be 'tp', updating in place */
     *tp = '\0';
 }
 
+/* returns a one-byte character from the text; may change txt[];
+   moved from cmd.c in order to get access to escapes() */
+uchar
+txt2key(char *txt)
+{
+    uchar uc;
+    boolean makemeta = FALSE;
+
+    txt = trimspaces(txt);
+    if (!*txt)
+        return '\0';
+
+    /* simple character */
+    if (!txt[1])
+        return (uchar) txt[0];
+
+    /* a few special entries */
+    if (!strcmp(txt, "<enter>"))
+        return '\n';
+    if (!strcmp(txt, "<space>"))
+        return ' ';
+    if (!strcmp(txt, "<esc>"))
+        return '\033';
+
+    /* handle things like \b and \7 and \mX */
+    if (*txt == '\\') {
+        char tbuf[QBUFSZ];
+
+        if (strlen(txt) >= sizeof tbuf)
+            txt[sizeof tbuf - 1] = '\0';
+        escapes(txt, tbuf);
+        return *tbuf;
+    }
+
+    /* control and meta keys */
+    if (highc(*txt) == 'M') {
+        /*
+         * M <nothing>             return 'M'
+         * M - <nothing>           return M-'-'
+         * M <other><nothing>      return M-<other>
+         * otherwise M is pending until after ^/C- processing.
+         * Since trailing spaces are discarded, the only way to
+         * specify M-' ' is via "160".
+         */
+        if (!txt[1])
+            return (uchar) *txt;
+        /* skip past 'M' or 'm' and maybe '-' */
+        ++txt;
+        if (*txt == '-' && txt[1])
+            ++txt;
+        if (!txt[1])
+            return M((uchar) *txt);
+        makemeta = TRUE;
+    }
+    if (*txt == '^' || highc(*txt) == 'C') {
+        /*
+         * C <nothing>             return 'C' or M-'C'
+         * C - <nothing>           return '-' or M-'-'
+         * C [-] <other><nothing>  return C-<other> or M-C-<other>
+         * C [-] ?                 return <rubout>
+         * otherwise return C-<other> or M-C-<other>
+         */
+        uc = (uchar) *txt;
+        if (!txt[1])
+            return makemeta ? M(uc) : uc;
+        ++txt;
+        /* unlike M-x, lots of values of x are invalid for C-x;
+           checking and rejecting them is not worthwhile; GIGO;
+           we do accept "^-x" as synonym for "^x" or "C-x" */
+        if (*txt == '-' && txt[1])
+            ++txt;
+        /* and accept ^?, which gets used despite not being a control char */
+        if (*txt == '?')
+            return (uchar) (makemeta ? '\377' : '\177'); /* rubout/delete */
+        uc = C((uchar) *txt);
+        return makemeta ? M(uc) : uc;
+    }
+    if (makemeta && *txt)
+        return M((uchar) *txt);
+
+    /* FIXME: should accept single-quote single-character single-quote
+       and probably single-quote backslash octal-digits single-quote;
+       if we do that, the M- and C- results should be pending until
+       after, so that C-'X' becomes valid for ^X */
+
+    /* ascii codes: must be three-digit decimal */
+    if (*txt >= '0' && *txt <= '9') {
+        uchar key = 0;
+        int i;
+
+        for (i = 0; i < 3; i++) {
+            if (txt[i] < '0' || txt[i] > '9')
+                return '\0';
+            key = 10 * key + txt[i] - '0';
+        }
+        return key;
+    }
+
+    return '\0';
+}
+
 /*
  **********************************
  *