partial fix for #K3869 - curses: meta characters

Meta-key fix for curses interface running on top of ncurses library.
Previously only digits and lower case letters would produce a meta
character when combined with Alt (or Option on Apple keyboards), now
it should work for any basic character (not arrows or other function
keys).  It only works on terminals that send two characters ESC k
for Alt+k but that is not a change in behavior.

curses interface running on top of PDcurses library uses different
code which isn't fixed by this.  The alt key fixup it does have was
already present in curses_read_char() and recently got duplicated in
curses_convert_keys().  At least one other routine calls the latter
so it was necessary, but curses_read_char() calls that routine so
doesn't need to keep its own copy of the fixup.
This commit is contained in:
PatR
2023-02-28 10:14:25 -08:00
parent 7c0d65718c
commit 6ba11256ba
2 changed files with 34 additions and 62 deletions

View File

@@ -1541,7 +1541,7 @@ menu_get_selections(WINDOW *win, nhmenu *menu, int how)
if (isdigit(curletter) && !groupaccels[curletter]) {
count = curses_get_count(curletter);
/* after count, we know some non-digit is already pending */
curletter = getch();
curletter = curses_getch();
count_letter = (count > 0L) ? curletter : '\0';
/* remove the count wind (erases last line of message wind) */

View File

@@ -44,35 +44,16 @@ int
curses_read_char(void)
{
int ch;
#if defined(ALT_0) || defined(ALT_9) || defined(ALT_A) || defined(ALT_Z)
int tmpch;
#endif
/* cancel message suppression; all messages have had a chance to be read */
curses_got_input();
ch = curses_getch();
#if defined(ALT_0) || defined(ALT_9) || defined(ALT_A) || defined(ALT_Z)
tmpch = ch;
#endif
ch = curses_convert_keys(ch);
if (ch == 0) {
ch = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */
}
#if defined(ALT_0) && defined(ALT_9) /* PDCurses, maybe others */
if ((ch >= ALT_0) && (ch <= ALT_9)) {
tmpch = (ch - ALT_0) + '0';
ch = M(tmpch);
}
#endif
#if defined(ALT_A) && defined(ALT_Z) /* PDCurses, maybe others */
if ((ch >= ALT_A) && (ch <= ALT_Z)) {
tmpch = (ch - ALT_A) + 'a';
ch = M(tmpch);
}
#endif
#ifdef KEY_RESIZE
/* Handle resize events via get_nh_event, not this code */
@@ -882,6 +863,22 @@ curses_convert_keys(int key)
ret = C('H');
/*FALLTHRU*/
default:
#if defined(ALT_A) && defined(ALT_Z)
/* for PDcurses, but doesn't handle Alt+X for upper case X;
ncurses doesn't have ALT_x definitions so we achieve a similar
effect via parse_escape_sequence(), and that works for upper
case and other non-letter, non-digit keys */
if (ret >= ALT_A && ret <= ALT_Z) {
ret = (ret - ALT_A) + 'a';
ret = M(ret);
}
#endif
#if defined(ALT_0) && defined(ALT_9)
if (ret >= ALT_0 && ret <= ALT_9) {
ret = (ret - ALT_0) + '0';
ret = M(ret);
}
#endif
/* use key as-is unless it's out of normal char range */
reject = ((uchar) ret < 1 || ret > 255);
as_is = TRUE;
@@ -939,36 +936,6 @@ curses_convert_keys(int key)
ret = iflags.num_pad ? '5' : 'g';
break;
#endif /* KEY_B2 */
#ifdef PDCURSES
case ALT_A:
case ALT_B:
case ALT_C:
case ALT_D:
case ALT_E:
case ALT_F:
case ALT_G:
case ALT_H:
case ALT_I:
case ALT_J:
case ALT_K:
case ALT_L:
case ALT_M:
case ALT_N:
case ALT_O:
case ALT_P:
case ALT_Q:
case ALT_R:
case ALT_S:
case ALT_T:
case ALT_U:
case ALT_V:
case ALT_W:
case ALT_X:
case ALT_Y:
case ALT_Z:
ret = M((ret - ALT_A) + 'a');
break;
#endif
}
/* phone layout is inverted, 123 on top and 789 on bottom; if player has
@@ -1073,6 +1040,9 @@ curses_mouse_support(int mode) /* 0: off, 1: on, 2: alternate on */
#endif
}
/* caller just got an input character of ESC;
note: curses converts a lot of escape sequences to single values greater
than 255 and those won't look like ESC to caller so won't get here */
static int
parse_escape_sequence(void)
{
@@ -1083,19 +1053,21 @@ parse_escape_sequence(void)
ret = getch();
if (ret != ERR) { /* Likely an escape sequence */
if ((ret >= 'a' && ret <= 'z') || (ret >= '0' && ret <= '9')) {
ret |= 0x80; /* Meta key support for most terminals */
} else if (ret == 'O') { /* Numeric keypad */
ret = getch();
if (ret != ERR && ret >= 112 && ret <= 121) {
ret = ret - 112 + '0'; /* Convert to number */
} else {
ret = '\033'; /* Escape */
}
}
if (ret == 'O') { /* Numeric keypad */
/* ESC O <something> */
ret = getch();
if (ret >= 112 && ret <= 121)
return ret - 112 + '0'; /* Convert to number */
if (ret == ERR)
ret = 'O'; /* there was no third char; treat as ESC O below */
}
if (ret != ERR && ret <= 255) {
/* ESC <something>; effectively 'altmeta' behind player's back */
ret = M(ret); /* Meta key support for most terminals */
} else {
ret = '\033'; /* Just an escape character */
ret = '\033'; /* Just an escape character */
}
timeout(-1);