From 65756674f0fe70a9630c19a829dc1a1f81f722a8 Mon Sep 17 00:00:00 2001 From: gldrk Date: Sun, 7 May 2023 00:33:51 +0300 Subject: top: improve control character handling in line editing terminfo is notoriously unreliable when it comes to the erase character. Use the terminal setting instead. Also hardcode both commonly used characters just to be safe. Do not assign unwanted actions to '\0'. Reference(s): https://gitlab.com/procps-ng/procps/-/issues/278 --- src/top/top.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/top/top.c b/src/top/top.c index 98444fd..07fcb68 100644 --- a/src/top/top.c +++ b/src/top/top.c @@ -1167,6 +1167,7 @@ static int iokey (int action) { { NULL, kbd_PGDN }, { NULL, kbd_PGUP }, { NULL, kbd_END }, { NULL, kbd_BTAB }, // remainder are alternatives for above, just in case... // ( the h,j,k,l entries are the vim cursor motion keys ) + { "\b", kbd_BKSP }, { "\177", kbd_BKSP }, /* backspace */ { "\033h", kbd_LEFT }, { "\033j", kbd_DOWN }, /* meta+ h,j */ { "\033k", kbd_UP }, { "\033l", kbd_RIGHT }, /* meta+ k,l */ { "\033\010", kbd_HOME }, { "\033\012", kbd_PGDN }, /* ctrl+meta+ h,j */ @@ -1177,6 +1178,7 @@ static int iokey (int action) { { "\xC2\x8B", kbd_PGUP }, { "\xC2\x8C", kbd_END }, /* ctrl+meta+ k,l (some xterms) */ { "\033\011", kbd_BTAB } }; + static char erase[2]; #ifdef TERMIOS_ONLY char buf[SMLBUFSIZ], *pb; #else @@ -1187,24 +1189,31 @@ static int iokey (int action) { int i; if (action == IOKEY_INIT) { - #define tOk(s) s ? s : "" - tinfo_tab[0].str = tOk(key_backspace); - tinfo_tab[1].str = tOk(key_ic); - tinfo_tab[2].str = tOk(key_dc); - tinfo_tab[3].str = tOk(key_left); - tinfo_tab[4].str = tOk(key_down); - tinfo_tab[5].str = tOk(key_up); - tinfo_tab[6].str = tOk(key_right); - tinfo_tab[7].str = tOk(key_home); - tinfo_tab[8].str = tOk(key_npage); - tinfo_tab[9].str = tOk(key_ppage); - tinfo_tab[10].str = tOk(key_end); - tinfo_tab[11].str = tOk(back_tab); +#ifndef _POSIX_VDISABLE +#define _POSIX_VDISABLE fpathconf(STDIN_FILENO, _PC_VDISABLE) +#endif + if (Tty_original.c_cc[VERASE] == _POSIX_VDISABLE) + tinfo_tab[0].str = key_backspace; + else { + *erase = Tty_original.c_cc[VERASE]; + tinfo_tab[0].str = erase; + } + tinfo_tab[1].str = key_ic; + tinfo_tab[2].str = key_dc; + tinfo_tab[3].str = key_left; + tinfo_tab[4].str = key_down; + tinfo_tab[5].str = key_up; + tinfo_tab[6].str = key_right; + tinfo_tab[7].str = key_home; + tinfo_tab[8].str = key_npage; + tinfo_tab[9].str = key_ppage; + tinfo_tab[10].str = key_end; + tinfo_tab[11].str = back_tab; // next is critical so returned results match bound terminfo keys - putp(tOk(keypad_xmit)); + if (keypad_xmit) + putp(keypad_xmit); // ( converse keypad_local issued at pause/pgm end, just in case ) return 0; - #undef tOk } if (action == IOKEY_ONCE) { @@ -1234,7 +1243,7 @@ static int iokey (int action) { else if (pb > buf && '\033' == *(pb - 1)) --pb; for (i = 0; i < MAXTBL(tinfo_tab); i++) - if (!strcmp(tinfo_tab[i].str, pb)) + if (tinfo_tab[i].str && !strcmp(tinfo_tab[i].str, pb)) return tinfo_tab[i].key; // no match, so we'll return single non-escaped keystrokes only @@ -4473,8 +4482,6 @@ static void whack_terminal (void) { tmptty.c_oflag &= ~TAB3; tmptty.c_iflag |= BRKINT; tmptty.c_iflag &= ~IGNBRK; - if (key_backspace && 1 == strlen(key_backspace)) - tmptty.c_cc[VERASE] = *key_backspace; #ifdef TERMIOS_ONLY if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty)) error_exit(fmtmk(N_fmt(FAIL_tty_set_fmt), strerror(errno))); -- cgit v1.2.1