top: disable tty scrollback buffer to improve SIGWINCH

A scrollback buffer used in several terminal emulators
could be a real inconvenience to a user following some
resize operations. Extra keystroke(s) would frequently
be required in order to properly render top's display.

After much sleuthing we unearthed two terminfo strings
which have the effect of disabling/restoring that darn
scrollback buffer. They were well hidden under a title
of strings 'to start/end programs using cup'. In turn,
'cup' deals with a tty's cursor addressing capability.

We don't care what you call them or what they refer to
so long as they get the job done. And these really do!
Be advised, however, that there are some side effects,
several of which can even be considered as beneficial:

. enter_ca_mode/smcup/ti disables scrollback buffering
( and that's good, it's what we had always hoped for )

. exit_ca_mode/rmcup/te restores the scrollback buffer
( but also restores screen contents existing pre-top )
( which is different from former program end results )
( where that last rendered screen was left untouched )

. the above screen replacement would impact ^Z suspend
( thus we keep the scrollback buffer disabled during )
( the suspend/resume sequence so that the users will )
( have a visual clue that top is suspended not ended )

If a terminal does not support these terminfo strings,
we will revert to top's former behavior at program end
where we position the cursor at screen bottom and then
output a single newline character. This will prevent a
shell prompt from embedding within top's final screen.

This commit's approach has been tested under a variety
of emulators and window managers, many of which linked
with libvte and others that employed their own scheme.
Examples are: gnome_terminal; kde konsole; lxterminal;
terminator; terminology; urxvt; xfce4-terminal; xterm.

I do now believe that the whole SIGWINCH deal is done!

(everything is perfectly justified plus right margins)
(are completely filled, but of course it must be luck)

Reference(s):
http://www.freelists.org/post/procps/top-won-the-sigwinch-war
http://www.freelists.org/post/procps/top-won-the-sigwinch-war,4

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2013-01-31 00:00:00 -06:00 committed by Craig Small
parent 365a5fa517
commit dedaf6e1a8

View File

@ -330,12 +330,19 @@ static void at_eoj (void) {
if (Ttychanged) {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_original);
if (keypad_local) putp(keypad_local);
putp(tg2(0, Screen_rows));
if (exit_ca_mode)
// this next will also replace top's most recent screen with the
// original display contents that were visible at our invocation
putp(exit_ca_mode);
else {
// but if we can't, we'll simply do it as old top always used to
putp(tg2(0, Screen_rows));
putp("\n");
}
putp(Cap_curs_norm);
#ifndef RMAN_IGNORED
putp(Cap_smam);
#endif
putp("\n");
Ttychanged = 0;
}
fflush(stdout);
@ -564,7 +571,11 @@ static void sig_endpgm (int dont_care_sig) {
/*
* Catches:
* SIGTSTP, SIGTTIN and SIGTTOU */
* SIGTSTP, SIGTTIN and SIGTTOU
* note:
* we don't fiddle with with those enter/exit_ca_mode strings
* because we want to retain most of the last screen contents
* as a visual reminder this program is suspended, not ended! */
static void sig_paused (int dont_care_sig) {
// POSIX.1-2004 async-signal-safe: tcsetattr, tcdrain, raise
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_original))
@ -575,7 +586,10 @@ static void sig_paused (int dont_care_sig) {
#ifndef RMAN_IGNORED
putp(Cap_smam);
#endif
tcdrain(STDOUT_FILENO);
// tcdrain(STDOUT_FILENO) was not reliable prior to ncurses-5.9.20121017,
// so we'll risk POSIX's wrath with good ol' fflush, lest 'Stopped' gets
// co-mingled with our most recent output...
fflush(stdout);
raise(SIGSTOP);
// later, after SIGCONT...
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_raw))
@ -3487,6 +3501,8 @@ static void whack_terminal (void) {
// thanks anyway stdio, but we'll manage buffering at the frame level...
setbuffer(stdout, Stdout_buf, sizeof(Stdout_buf));
#endif
// this has the effect of disabling any troublesome scrollback buffer...
if (enter_ca_mode) putp(enter_ca_mode);
// and don't forget to ask iokey to initialize his tinfo_tab
iokey(1);
} // end: whack_terminal