]> granicus.if.org Git - nethack/commitdiff
txt2key() - parsing key binding specifications
authorPatR <rankin@nethack.org>
Thu, 10 Dec 2020 00:52:54 +0000 (16:52 -0800)
committerPatR <rankin@nethack.org>
Thu, 10 Dec 2020 00:52:54 +0000 (16:52 -0800)
While testing some addtional ?i (list of key assignments)
changes, I wanted to give every key a binding.  When I tried
BIND=M-^A:exploremode
the text to key conversion didn't like that.  This adds support
for M-^x and M-C-x plus variations where dashes are omitted.

This adds support for ^? even though that isn't really a
control character.  I bound #terrain to it and surprising--to
me at least--the <delete> key worked to invoke that command.

Also changes 'char txt2key(...)' to be 'uchar txt2key(...)'.

include/extern.h
src/cmd.c
src/options.c

index 4fc957d3059516b354507b8b50c147be778e5bef..bbb2fd88d693cb5cdfd06b0f55a9dbeeff3c8979 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 extern.h        $NHDT-Date: 1606919254 2020/12/02 14:27:34 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.886 $ */
+/* NetHack 3.7 extern.h        $NHDT-Date: 1607561572 2020/12/10 00:52:52 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.928 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -229,7 +229,7 @@ E void FDECL(pushch, (CHAR_P));
 E void FDECL(savech, (CHAR_P));
 E const char *FDECL(key2extcmddesc, (UCHAR_P));
 E boolean FDECL(bind_specialkey, (UCHAR_P, const char *));
-E char FDECL(txt2key, (char *));
+E uchar FDECL(txt2key, (char *));
 E void FDECL(parseautocomplete, (char *, BOOLEAN_P));
 E void FDECL(reset_commands, (BOOLEAN_P));
 E void FDECL(rhack, (char *));
index bd348ae8dbe8d1b7b92f28165a1144975de74644..bc50986ec7ad8a3943ec33e7445a67f996413dbc 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 cmd.c   $NHDT-Date: 1607471879 2020/12/08 23:57:59 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.429 $ */
+/* NetHack 3.7 cmd.c   $NHDT-Date: 1607561570 2020/12/10 00:52:50 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.430 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -379,7 +379,7 @@ const struct ext_func_tab *efp; /* if Null, add a footnote to the menu */
     }
 }
 
-/* here after #? - now list all full-word commands and provid
+/* here after #? - now list all full-word commands and provide
    some navigation capability through the long list */
 int
 doextlist(VOID_ARGS)
@@ -2858,19 +2858,21 @@ const char *command;
     return FALSE;
 }
 
-/* returns a one-byte character from the text (it may massacre the txt
- * buffer) */
-char
+/* returns a one-byte character from the text; may change txt[] */
+uchar
 txt2key(txt)
 char *txt;
 {
+    uchar uc;
+    boolean makemeta = FALSE;
+
     txt = trimspaces(txt);
     if (!*txt)
         return '\0';
 
     /* simple character */
     if (!txt[1])
-        return txt[0];
+        return (uchar) txt[0];
 
     /* a few special entries */
     if (!strcmp(txt, "<enter>"))
@@ -2881,25 +2883,55 @@ char *txt;
         return '\033';
 
     /* control and meta keys */
-    switch (*txt) {
-    case 'm': /* can be mx, Mx, m-x, M-x */
-    case 'M':
-        txt++;
+    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 '\0';
-        return M(*txt);
-    case 'c': /* can be cx, Cx, ^x, c-x, C-x, ^-x */
-    case 'C':
-    case '^':
-        txt++;
+            ++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++;
-        if (txt[1])
-            return '\0';
-        return C(*txt);
+            ++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') {
@@ -2929,9 +2961,9 @@ char *txt; /* sufficiently long buffer */
     if (c == ' ')
         Sprintf(txt, "<space>");
     else if (c == '\033')
-        Sprintf(txt, "<esc>");
+        Sprintf(txt, "<esc>"); /* "<escape>" won't fit */
     else if (c == '\n')
-        Sprintf(txt, "<enter>");
+        Sprintf(txt, "<enter>"); /* "<return>" won't fit */
     else if (c == '\177')
         Sprintf(txt, "<del>"); /* "<delete>" won't fit */
     else
index e82877b5a0883ab6379a18e1ae1b578657f03284..f4a008c9beba7babb88bcba08334f91d0a20632c 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 options.c       $NHDT-Date: 1606445249 2020/11/27 02:47:29 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.482 $ */
+/* NetHack 3.7 options.c       $NHDT-Date: 1607561571 2020/12/10 00:52:51 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.484 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Michael Allison, 2008. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -281,7 +281,7 @@ static boolean FDECL(is_wc2_option, (const char *));
 static boolean FDECL(wc2_supported, (const char *));
 static void FDECL(wc_set_font_name, (int, char *));
 static int FDECL(wc_set_window_colors, (char *));
-static boolean FDECL(illegal_menu_cmd_key, (CHAR_P));
+static boolean FDECL(illegal_menu_cmd_key, (UCHAR_P));
 #ifndef CHANGE_COLOR
 int FDECL(optfn_palette, (int, int, BOOLEAN_P, char *, char *));
 #endif
@@ -4664,7 +4664,7 @@ char *op;
             escapes(op, op_buf);
             c = *op_buf;
 
-            if (illegal_menu_cmd_key(c))
+            if (illegal_menu_cmd_key((uchar) c))
                 return optn_err;
             add_menu_cmd_alias(c, default_menu_cmd_info[midx].cmd);
         }
@@ -6362,10 +6362,10 @@ const char *optn;
 /* parse key:command */
 boolean
 parsebindings(bindings)
-charbindings;
+char *bindings;
 {
     char *bind;
-    char key;
+    uchar key;
     int i;
     boolean ret = FALSE;
 
@@ -6400,7 +6400,7 @@ char* bindings;
                 config_error_add("Bad menu key %s:%s", visctrl(key), bind);
                 return FALSE;
             } else
-                add_menu_cmd_alias(key, default_menu_cmd_info[i].cmd);
+                add_menu_cmd_alias((char) key, default_menu_cmd_info[i].cmd);
             return TRUE;
         }
     }
@@ -7151,18 +7151,19 @@ char **opp;
 /* Check if character c is illegal as a menu command key */
 boolean
 illegal_menu_cmd_key(c)
-char c;
+uchar c;
 {
-    if (c == 0 || c == '\r' || c == '\n' || c == '\033'
-        || c == ' ' || digit(c) || (letter(c) && c != '@')) {
-        config_error_add("Reserved menu command key '%s'", visctrl(c));
+    if (c == 0 || c == '\r' || c == '\n' || c == '\033' || c == ' '
+        || digit((char) c) || (letter((char) c) && c != '@')) {
+        config_error_add("Reserved menu command key '%s'", visctrl((char) c));
         return TRUE;
     } else { /* reject default object class symbols */
         int j;
+
         for (j = 1; j < MAXOCLASSES; j++)
-            if (c == def_oc_syms[j].sym) {
+            if (c == (uchar) def_oc_syms[j].sym) {
                 config_error_add("Menu command key '%s' is an object class",
-                                 visctrl(c));
+                                 visctrl((char) c));
                 return TRUE;
             }
     }