options key parsing
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.
This commit is contained in:
@@ -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!
|
applying a polearm to attempt to attack a hidden monster would report "wait!
|
||||||
there's a monster hidden there" and display the "remembered, unseen
|
there's a monster hidden there" and display the "remembered, unseen
|
||||||
monster" glyph but only use a turn if polearm wasn't already wielded
|
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
|
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||||
|
|||||||
+1
-1
@@ -210,7 +210,6 @@ extern void pushch(char);
|
|||||||
extern void savech(char);
|
extern void savech(char);
|
||||||
extern const char *key2extcmddesc(uchar);
|
extern const char *key2extcmddesc(uchar);
|
||||||
extern boolean bind_specialkey(uchar, const char *);
|
extern boolean bind_specialkey(uchar, const char *);
|
||||||
extern uchar txt2key(char *);
|
|
||||||
extern void parseautocomplete(char *, boolean);
|
extern void parseautocomplete(char *, boolean);
|
||||||
extern void reset_commands(boolean);
|
extern void reset_commands(boolean);
|
||||||
extern void rhack(char *);
|
extern void rhack(char *);
|
||||||
@@ -1784,6 +1783,7 @@ extern int shiny_obj(char);
|
|||||||
/* ### options.c ### */
|
/* ### options.c ### */
|
||||||
|
|
||||||
extern boolean match_optname(const char *, const char *, int, boolean);
|
extern boolean match_optname(const char *, const char *, int, boolean);
|
||||||
|
extern uchar txt2key(char *);
|
||||||
extern void initoptions(void);
|
extern void initoptions(void);
|
||||||
extern void initoptions_init(void);
|
extern void initoptions_init(void);
|
||||||
extern void initoptions_finish(void);
|
extern void initoptions_finish(void);
|
||||||
|
|||||||
@@ -443,4 +443,23 @@ struct savefile_info {
|
|||||||
(nhassert_failed(#expression, __FILE__, __LINE__), 0))
|
(nhassert_failed(#expression, __FILE__, __LINE__), 0))
|
||||||
#endif
|
#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 */
|
#endif /* GLOBAL_H */
|
||||||
|
|||||||
+2
-2
@@ -263,8 +263,8 @@ opt_##a,
|
|||||||
NoAlias, "deselect all items in a menu")
|
NoAlias, "deselect all items in a menu")
|
||||||
NHOPTC(menu_deselect_page, 4, opt_in, set_in_config, No, Yes, No, No,
|
NHOPTC(menu_deselect_page, 4, opt_in, set_in_config, No, Yes, No, No,
|
||||||
NoAlias, "deselect all items on this page of a menu")
|
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,
|
NHOPTC(menu_first_page, 4, opt_in, set_in_config, No, Yes, No, No,
|
||||||
"jump to the first page in a menu")
|
NoAlias, "jump to the first page in a menu")
|
||||||
NHOPTC(menu_headings, 4, opt_in, set_in_game, No, Yes, No, Yes, NoAlias,
|
NHOPTC(menu_headings, 4, opt_in, set_in_game, No, Yes, No, Yes, NoAlias,
|
||||||
"display style for menu headings")
|
"display style for menu headings")
|
||||||
NHOPTC(menu_invert_all, 4, opt_in, set_in_config, No, Yes, No, No, NoAlias,
|
NHOPTC(menu_invert_all, 4, opt_in, set_in_config, No, Yes, No, No, NoAlias,
|
||||||
|
|||||||
@@ -6,25 +6,6 @@
|
|||||||
#include "hack.h"
|
#include "hack.h"
|
||||||
#include "func_tab.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
|
#ifdef ALTMETA
|
||||||
static boolean alt_esc = FALSE;
|
static boolean alt_esc = FALSE;
|
||||||
#endif
|
#endif
|
||||||
@@ -3045,96 +3026,6 @@ spkey_name(int nhkf)
|
|||||||
return name;
|
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;
|
/* returns the text for a one-byte encoding;
|
||||||
* must be shorter than a tab for proper formatting */
|
* must be shorter than a tab for proper formatting */
|
||||||
char *
|
char *
|
||||||
|
|||||||
+102
-4
@@ -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);
|
bad_negation(default_menu_cmd_info[midx].name, FALSE);
|
||||||
return optn_err;
|
return optn_err;
|
||||||
} else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
|
} else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
|
||||||
char c, op_buf[BUFSZ];
|
char c = txt2key(op);
|
||||||
|
|
||||||
escapes(op, op_buf);
|
|
||||||
c = *op_buf;
|
|
||||||
|
|
||||||
if (illegal_menu_cmd_key((uchar) c))
|
if (illegal_menu_cmd_key((uchar) c))
|
||||||
return optn_err;
|
return optn_err;
|
||||||
@@ -5617,6 +5614,107 @@ escapes(const char *cp, /* might be 'tp', updating in place */
|
|||||||
*tp = '\0';
|
*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';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**********************************
|
**********************************
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user