Browse Source

fix github issue #558 - 'altmeta' input

Setting the 'altmeta' option affects how ESC is handled.  Normally it
is for terminals/emulators which transmit two character sequence ESC c
when the user types Meta+c, but it can also be used to construct meta
characters 'manually' by typing ESC c.  Unfortunately setting this
option has a side-effect of requiring a second character after ESC
before our readchar() will return, so it is only honored when parse()
wants the next command, not for general input.

When readchar() was recently split into two parts, the use of static
variable 'alt_esc' by parse() and readchar() was removed.  That
resulted in requiring the user to type a second character whenever
ESC was typed, instead of just when it was transmitted or typed as
the prefix of a command that uses a meta-character keystroke.

Instead of just putting 'alt_esc' back, do things differently by
adding static 'getting_cmd' flag instead.

Fixes #558
PatR 2 months ago
  1. 2
  2. 15


@ -755,6 +755,8 @@ using bhitpos in flooreffects to handle erosion damage broke its original use
of tracking wand zaps if a teleportation zap hit an object; subsequent
zap traversal was done from object's landing spot rather than from its
zap hit spot, resulting in scrambled wand targetting
restore previous behavior of the 'altmeta' option (only wait for a second
character when getting a command keystroke, not other key input)
curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support


@ -171,6 +171,9 @@ static const char unavailcmd[] = "Unavailable command '%s'.";
/* for rejecting #if !SHELL, !SUSPEND */
static const char cmdnotavail[] = "'%s' command not available.";
/* only needed for #if ALTMETA config but present unconditionally */
static boolean getting_cmd = FALSE; /* True when parse() gets next command */
static int
@ -4475,8 +4478,11 @@ parse(void)
g.context.move = 1;
flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
getting_cmd = TRUE; /* affects readchar() behavior if the 'altmeta'
* option is On; reset to False by readchar() */
if (!g.Cmd.num_pad || (foo = readchar()) == g.Cmd.spkeys[NHKF_COUNT]) {
foo = get_count((char *) 0, '\0', LARGEST_INT, &g.command_count, FALSE);
foo = get_count((char *) 0, '\0', LARGEST_INT,
&g.command_count, FALSE);
g.last_command_count = g.command_count;
@ -4621,8 +4627,9 @@ readchar_core(int *x, int *y, int *mod)
sym = '\033';
#ifdef ALTMETA
} else if (sym == '\033' && iflags.altmeta) {
/* iflags.altmeta: treat two character ``ESC c'' as single `M-c' */
} else if (sym == '\033' && iflags.altmeta && getting_cmd) {
/* iflags.altmeta: treat two character ``ESC c'' as single `M-c' but
only when we're called by parse() [possibly via get_count()] */
sym = *readchar_queue ? *readchar_queue++ : pgetchar();
if (sym == EOF || sym == 0)
sym = '\033';
@ -4634,6 +4641,8 @@ readchar_core(int *x, int *y, int *mod)
readchar_queue = click_to_cmd(*x, *y, *mod);
sym = *readchar_queue++;
getting_cmd = FALSE; /* next readchar() will be for an ordinary char
* unless parse() sets this back to True */
return (char) sym;