top: preserve current screen when receiving a SIGWINCH

Prior to this commit, top has always taken the easiest
(safest?) approach when dealing with those troublesome
SIGWINCH interrupts. Whenever the user was on a screen
other than the main display, any signal received would
force an immediate exit, returning to the main screen.

With these changes, top will retain the user's current
position regardless of what screen he/she was viewing.

In support the following additional changes were made:
* the initial help screen requires an explicit end key
` not 'any other key' formerly used to request an exit
* the colors mapping screen instructions were improved
* ^Z response was made immediate, eliminating the flag
* the sigaction's SA_RESTART flag had to be eliminated
* sigprocmask logic was normailize to the bare minimum
* the POSIX.1-2004 async-signal safe functions used in
` the signal handlers were acknowledged and documented

(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/unwanted-topinspect-window-enclosure-with-the-terminal-size-change

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2013-01-16 00:00:00 -06:00 committed by Craig Small
parent 5856919e83
commit ba9092ad83
4 changed files with 161 additions and 126 deletions

235
top/top.c
View File

@ -123,6 +123,7 @@ static char Cap_clr_eol [CAPBUFSIZ] = "", // global and/or static vars
Cap_curs_norm [CAPBUFSIZ] = "", // cost nothing but DO serve Cap_curs_norm [CAPBUFSIZ] = "", // cost nothing but DO serve
Cap_curs_huge [CAPBUFSIZ] = "", // to remind people of those Cap_curs_huge [CAPBUFSIZ] = "", // to remind people of those
Cap_curs_hide [CAPBUFSIZ] = "", // batch requirements! Cap_curs_hide [CAPBUFSIZ] = "", // batch requirements!
Cap_clr_eos [CAPBUFSIZ] = "",
Cap_home [CAPBUFSIZ] = "", Cap_home [CAPBUFSIZ] = "",
Cap_norm [CAPBUFSIZ] = "", Cap_norm [CAPBUFSIZ] = "",
Cap_reverse [CAPBUFSIZ] = "", Cap_reverse [CAPBUFSIZ] = "",
@ -161,9 +162,6 @@ static WIN_t *Curwin;
and/or that are simply more efficiently handled as globals and/or that are simply more efficiently handled as globals
[ 'Frames_...' (plural) stuff persists beyond 1 frame ] [ 'Frames_...' (plural) stuff persists beyond 1 frame ]
[ or are used in response to async signals received ! ] */ [ or are used in response to async signals received ! ] */
// Frames_paused set by sig_paused(), unset by pause_pgm()
static volatile int Frames_paused; // become a paused background job
// Frames_resize set by do_key() & sig_resize(), unset by calibrate_fields()
static volatile int Frames_resize; // time to rebuild all column headers static volatile int Frames_resize; // time to rebuild all column headers
static int Frames_libflags; // PROC_FILLxxx flags static int Frames_libflags; // PROC_FILLxxx flags
@ -324,8 +322,8 @@ static const char *tg2 (int x, int y) {
* Reset the tty, if necessary */ * Reset the tty, if necessary */
static void at_eoj (void) { static void at_eoj (void) {
if (Ttychanged) { if (Ttychanged) {
if (keypad_local) putp(keypad_local);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_original); tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_original);
if (keypad_local) putp(keypad_local);
putp(tg2(0, Screen_rows)); putp(tg2(0, Screen_rows));
putp(Cap_curs_norm); putp(Cap_curs_norm);
#ifndef RMAN_IGNORED #ifndef RMAN_IGNORED
@ -335,7 +333,7 @@ static void at_eoj (void) {
Ttychanged = 0; Ttychanged = 0;
} }
fflush(stdout); fflush(stdout);
} // end: } // end: at_eoj
/* /*
@ -526,32 +524,12 @@ static void library_err (const char *fmts, ...) {
} // end: library_err } // end: library_err
/*
* Called in response to Frames_paused (tku: sig_paused) */
static void pause_pgm (void) {
Frames_paused = 0;
// reset terminal (maybe)
if (Ttychanged) tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_original);
putp(tg2(0, Screen_rows));
putp(Cap_curs_norm);
#ifndef RMAN_IGNORED
putp(Cap_smam);
#endif
fflush(stdout);
raise(SIGSTOP);
// later, after SIGCONT...
if (Ttychanged) tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_raw);
#ifndef RMAN_IGNORED
putp(Cap_rmam);
#endif
} // end: pause_pgm
/* /*
* Catches all remaining signals not otherwise handled */ * Catches all remaining signals not otherwise handled */
static void sig_abexit (int sig) { static void sig_abexit (int sig) {
sigset_t ss; sigset_t ss;
// POSIX.1-2004 async-signal-safe: sigfillset, sigprocmask, signal, raise
sigfillset(&ss); sigfillset(&ss);
sigprocmask(SIG_BLOCK, &ss, NULL); sigprocmask(SIG_BLOCK, &ss, NULL);
at_eoj(); // restore tty in preparation for exit at_eoj(); // restore tty in preparation for exit
@ -570,6 +548,7 @@ static void sig_endpgm (int dont_care_sig) NORETURN;
static void sig_endpgm (int dont_care_sig) { static void sig_endpgm (int dont_care_sig) {
sigset_t ss; sigset_t ss;
// POSIX.1-2004 async-signal-safe: sigfillset, sigprocmask
sigfillset(&ss); sigfillset(&ss);
sigprocmask(SIG_BLOCK, &ss, NULL); sigprocmask(SIG_BLOCK, &ss, NULL);
bye_bye(NULL); bye_bye(NULL);
@ -581,8 +560,26 @@ static void sig_endpgm (int dont_care_sig) {
* Catches: * Catches:
* SIGTSTP, SIGTTIN and SIGTTOU */ * SIGTSTP, SIGTTIN and SIGTTOU */
static void sig_paused (int dont_care_sig) { 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))
error_exit(fmtmk(N_fmt(FAIL_tty_set_fmt), strerror(errno)));
if (keypad_local) putp(keypad_local);
putp(tg2(0, Screen_rows));
putp(Cap_curs_norm);
#ifndef RMAN_IGNORED
putp(Cap_smam);
#endif
tcdrain(STDOUT_FILENO);
raise(SIGSTOP);
// later, after SIGCONT...
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_raw))
error_exit(fmtmk(N_fmt(FAIL_tty_set_fmt), strerror(errno)));
#ifndef RMAN_IGNORED
putp(Cap_rmam);
#endif
if (keypad_xmit) putp(keypad_xmit);
Frames_resize = RESIZ_sig;
(void)dont_care_sig; (void)dont_care_sig;
Frames_paused = 1;
} // end: sig_paused } // end: sig_paused
@ -590,8 +587,10 @@ static void sig_paused (int dont_care_sig) {
* Catches: * Catches:
* SIGCONT and SIGWINCH */ * SIGCONT and SIGWINCH */
static void sig_resize (int dont_care_sig) { static void sig_resize (int dont_care_sig) {
// POSIX.1-2004 async-signal-safe: tcdrain
tcdrain(STDOUT_FILENO);
Frames_resize = RESIZ_sig;
(void)dont_care_sig; (void)dont_care_sig;
Frames_resize = 2;
} // end: sig_resize } // end: sig_resize
/*###### Misc Color/Display support ####################################*/ /*###### Misc Color/Display support ####################################*/
@ -612,6 +611,7 @@ static void capsmk (WIN_t *q) {
// these are the unchangeable puppies, so we only do 'em once // these are the unchangeable puppies, so we only do 'em once
if (!capsdone) { if (!capsdone) {
STRLCPY(Cap_clr_eol, tIF(clr_eol)) STRLCPY(Cap_clr_eol, tIF(clr_eol))
STRLCPY(Cap_clr_eos, tIF(clr_eos))
STRLCPY(Cap_clr_scr, tIF(clear_screen)) STRLCPY(Cap_clr_scr, tIF(clear_screen))
// due to the leading newline, the following must be used with care // due to the leading newline, the following must be used with care
snprintf(Cap_nl_clreos, sizeof(Cap_nl_clreos), "\n%s", tIF(clr_eos)); snprintf(Cap_nl_clreos, sizeof(Cap_nl_clreos), "\n%s", tIF(clr_eos));
@ -876,7 +876,6 @@ static int chin (int ech, char *buf, unsigned cnt) {
fd_set fs; fd_set fs;
int rc = -1; int rc = -1;
fflush(stdout);
#ifndef TERMIO_PROXY #ifndef TERMIO_PROXY
if (ech) { if (ech) {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_tweaked); tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_tweaked);
@ -956,7 +955,7 @@ static int keyin (int init) {
STRLCPY(buf15, fmtmk("\033%s", tOk(key_right))); STRLCPY(buf15, fmtmk("\033%s", tOk(key_right)));
// next is critical so returned results match bound terminfo keys // next is critical so returned results match bound terminfo keys
putp(tOk(keypad_xmit)); putp(tOk(keypad_xmit));
// ( see the converse keypad_local at program end, just in case ) // ( converse keypad_local issued at pause/pgm end, just in case )
return 0; return 0;
#undef tOk #undef tOk
} }
@ -1027,7 +1026,8 @@ static char *linein (const char *prompt) {
memset(buf, '\0', sizeof(buf)); memset(buf, '\0', sizeof(buf));
do { do {
len = strlen(buf); len = strlen(buf);
switch (key = keyin(0)) { key = keyin(0);
switch (key) {
case kbd_ESC: case kbd_ESC:
buf[0] = '\0'; // fall through ! buf[0] = '\0'; // fall through !
case kbd_ENTER: case kbd_ENTER:
@ -1063,7 +1063,7 @@ static char *linein (const char *prompt) {
putp(fmtmk("%s%s%s", tg2(beg, Msg_row), Cap_clr_eol, buf)); putp(fmtmk("%s%s%s", tg2(beg, Msg_row), Cap_clr_eol, buf));
putp(tg2(beg+pos, Msg_row)); putp(tg2(beg+pos, Msg_row));
fflush(stdout); fflush(stdout);
} while (key && key != kbd_ENTER && key != kbd_ESC); } while (key != kbd_ENTER && key != kbd_ESC);
return buf; return buf;
#undef sqzSTR #undef sqzSTR
@ -1590,9 +1590,11 @@ static void adj_geometry (void) {
pseudo_max = Pseudo_size; pseudo_max = Pseudo_size;
Pseudo_screen = alloc_r(Pseudo_screen, pseudo_max); Pseudo_screen = alloc_r(Pseudo_screen, pseudo_max);
} }
// ensure each row is repainted and, if SIGWINCH, clear the screen // ensure each row is repainted (just in case)
PSU_CLREOS(0); PSU_CLREOS(0);
if (Frames_resize > 1) putp(Cap_clr_scr);
fflush(stdout);
Frames_resize = RESIZ_clr;
} // end: adj_geometry } // end: adj_geometry
@ -1689,19 +1691,12 @@ static void build_headers (void) {
* of each visible window's columns headers and the library flags * of each visible window's columns headers and the library flags
* required for the openproc interface. */ * required for the openproc interface. */
static void calibrate_fields (void) { static void calibrate_fields (void) {
sigset_t newss, oldss;
FLG_t f; FLG_t f;
char *s; char *s;
const char *h; const char *h;
WIN_t *w = Curwin; WIN_t *w = Curwin;
int i, varcolcnt, len; int i, varcolcnt, len;
// block SIGWINCH signals while we do our thing...
sigemptyset(&newss);
sigaddset(&newss, SIGWINCH);
if (-1 == sigprocmask(SIG_BLOCK, &newss, &oldss))
error_exit(fmtmk(N_fmt(FAIL_sigstop_fmt), strerror(errno)));
adj_geometry(); adj_geometry();
do { do {
@ -1779,10 +1774,6 @@ static void calibrate_fields (void) {
build_headers(); build_headers();
if (CHKw(Curwin, View_SCROLL)) if (CHKw(Curwin, View_SCROLL))
updt_scroll_msg(); updt_scroll_msg();
Frames_resize = 0;
if (-1 == sigprocmask(SIG_SETMASK, &oldss, NULL))
error_exit(fmtmk(N_fmt(FAIL_sigmask_fmt), strerror(errno)));
} // end: calibrate_fields } // end: calibrate_fields
@ -1828,7 +1819,6 @@ static void display_fields (int focus, int extend) {
int cmax = Screen_cols; // total data column width int cmax = Screen_cols; // total data column width
int rmax = Screen_rows - yRSVD; // total useable rows int rmax = Screen_rows - yRSVD; // total useable rows
fflush(stdout);
i = (P_MAXPFLGS % mxCOL) ? 1 : 0; i = (P_MAXPFLGS % mxCOL) ? 1 : 0;
if (rmax < i + (P_MAXPFLGS / mxCOL)) error_exit("++rows"); // nls_maybe if (rmax < i + (P_MAXPFLGS / mxCOL)) error_exit("++rows"); // nls_maybe
i = P_MAXPFLGS / rmax; i = P_MAXPFLGS / rmax;
@ -1839,16 +1829,16 @@ static void display_fields (int focus, int extend) {
if (smax < 0) error_exit("++cols"); // nls_maybe if (smax < 0) error_exit("++cols"); // nls_maybe
for (i = 0; i < P_MAXPFLGS; ++i) { for (i = 0; i < P_MAXPFLGS; ++i) {
char sbuf[xSUFX+1]; int b = FLDviz(w, i), x = (i / rmax) * cmax, y = (i % rmax) + yRSVD;
int b = FLDviz(w, i);
FLG_t f = FLDget(w, i);
const char *e = (i == focus && extend) ? w->capclr_hdr : ""; const char *e = (i == focus && extend) ? w->capclr_hdr : "";
FLG_t f = FLDget(w, i);
char sbuf[xSUFX+1];
// prep sacrificial suffix // prep sacrificial suffix
snprintf(sbuf, sizeof(sbuf), "= %s", N_fld(f)); snprintf(sbuf, sizeof(sbuf), "= %s", N_fld(f));
PUTT("%s%c%s%s %s%-7.7s%s%s%s %-*.*s%s" PUTT("%s%c%s%s %s%-7.7s%s%s%s %-*.*s%s%s"
, tg2((i / rmax) * cmax, (i % rmax) + yRSVD) , tg2(x, y)
, b ? '*' : ' ' , b ? '*' : ' '
, b ? w->cap_bold : Cap_norm , b ? w->cap_bold : Cap_norm
, e , e
@ -1859,7 +1849,8 @@ static void display_fields (int focus, int extend) {
, e , e
, smax, smax , smax, smax
, sbuf , sbuf
, Cap_norm); , Cap_norm
, !x ? Cap_clr_eol : "");
} }
putp(Caps_off); putp(Caps_off);
@ -1890,17 +1881,26 @@ static void fields_utility (void) {
int i, key; int i, key;
FLG_t f; FLG_t f;
putp(Cap_clr_scr);
spewFI spewFI
signify_that:
putp(Cap_clr_scr);
putp(Cap_curs_hide);
adj_geometry();
do { do {
if (!h) h = N_col(f); if (!h) h = N_col(f);
display_fields(i, (p != NULL));
putp(Cap_home); putp(Cap_home);
show_special(1, fmtmk(N_unq(FIELD_header_fmt) show_special(1, fmtmk(N_unq(FIELD_header_fmt)
, w->grpname, CHKw(w, Show_FOREST) ? N_txt(FOREST_views_txt) : h)); , w->grpname, CHKw(w, Show_FOREST) ? N_txt(FOREST_views_txt) : h));
putp(Cap_nl_clreos);
fflush(stdout);
display_fields(i, (p != NULL));
fflush(stdout);
switch (key = keyin(0)) { key = keyin(0);
if (key < 1) goto signify_that;
switch (key) {
case kbd_UP: case kbd_UP:
if (i > 0) { --i; if (p) swapEM } if (i > 0) { --i; if (p) swapEM }
break; break;
@ -1942,7 +1942,7 @@ static void fields_utility (void) {
default: // keep gcc happy default: // keep gcc happy
break; break;
} }
} while (key && key != 'q' && key != kbd_ESC); } while (key != 'q' && key != kbd_ESC);
#undef unSCRL #undef unSCRL
#undef swapEM #undef swapEM
#undef spewFI #undef spewFI
@ -2445,14 +2445,13 @@ static struct I_ent *Insp_sel; // currently selected Inspect entry
putp(tg2(0, (Msg_row = 3))); \ putp(tg2(0, (Msg_row = 3))); \
PUTT("%s%.*s", Curwin->capclr_hdr, Screen_cols -1 \ PUTT("%s%.*s", Curwin->capclr_hdr, Screen_cols -1 \
, fmtmk("%-*.*s%s", _sz, _sz, txt, Cap_clr_eol)); \ , fmtmk("%-*.*s%s", _sz, _sz, txt, Cap_clr_eol)); \
putp(Caps_off); } putp(Caps_off); fflush(stdout); }
// Our 'row length' macro, equivalent to a strlen() call // Our 'row length' macro, equivalent to a strlen() call
#define INSP_RLEN(idx) (int)(Insp_p[idx +1] - Insp_p[idx] -1) #define INSP_RLEN(idx) (int)(Insp_p[idx +1] - Insp_p[idx] -1)
// Our 'busy' (wait please) macro // Our 'busy' (wait please) macro
#define INSP_BUSY { INSP_MKSL(0, N_txt(YINSP_workin_txt)); \ #define INSP_BUSY { INSP_MKSL(0, N_txt(YINSP_workin_txt)); }
fflush(stdout); }
/* /*
@ -2731,9 +2730,14 @@ static int insp_view_choice (proc_t *obj) {
snprintf(dst, sizeof(dst), "%s", Insp_sel->fstr); \ snprintf(dst, sizeof(dst), "%s", Insp_sel->fstr); \
else snprintf(dst, sizeof(dst), "%.19s...", Insp_sel->fstr); } else snprintf(dst, sizeof(dst), "%.19s...", Insp_sel->fstr); }
char buf[SMLBUFSIZ]; char buf[SMLBUFSIZ];
int key, curlin, curcol; int key, curlin = 0, curcol = 0;
for (curlin = curcol = 0;;) { signify_that:
putp(Cap_clr_scr);
putp(Cap_curs_hide);
adj_geometry();
for (;;) {
char pid[6], cmd[9], usr[9]; char pid[6], cmd[9], usr[9];
if (curcol < 0) curcol = 0; if (curcol < 0) curcol = 0;
@ -2747,17 +2751,19 @@ static int insp_view_choice (proc_t *obj) {
show_special(1, fmtmk(N_unq(INSP_hdrview_fmt) show_special(1, fmtmk(N_unq(INSP_hdrview_fmt)
, pid, cmd, usr, (Insp_sel->fstr[0]) ? buf : " N/A ")); // nls_maybe , pid, cmd, usr, (Insp_sel->fstr[0]) ? buf : " N/A ")); // nls_maybe
insp_show_pgs(curcol, curlin, maxLN); insp_show_pgs(curcol, curlin, maxLN);
fflush(stdout);
/* fflush(stdin) didn't do the trick, so we'll just dip a little deeper /* fflush(stdin) didn't do the trick, so we'll just dip a little deeper
lest repeated <Enter> keys produce immediate re-selection in caller */ lest repeated <Enter> keys produce immediate re-selection in caller */
tcflush(STDIN_FILENO, TCIFLUSH); tcflush(STDIN_FILENO, TCIFLUSH);
key = keyin(0); key = keyin(0);
if (key < 1) goto signify_that;
switch (key) { switch (key) {
case kbd_ENTER: // must force new keyin() case kbd_ENTER: // must force new keyin()
key = -1; // fall through ! key = INT_MAX; // fall through !
case kbd_ESC: case kbd_ESC:
case 'q': case 'q':
case 0:
putp(Cap_clr_scr); putp(Cap_clr_scr);
return key; return key;
case kbd_LEFT: case kbd_LEFT:
@ -2799,8 +2805,8 @@ static int insp_view_choice (proc_t *obj) {
case '=': case '=':
snprintf(buf, sizeof(buf), "%s: %s", Insp_sel->type, Insp_sel->fmts); snprintf(buf, sizeof(buf), "%s: %s", Insp_sel->type, Insp_sel->fmts);
INSP_MKSL(1, buf); // show an extended SL INSP_MKSL(1, buf); // show an extended SL
key = keyin(0); if (keyin(0) < 1)
if (!key) return key; // oops, we got signaled goto signify_that;
break; break;
default: // keep gcc happy default: // keep gcc happy
break; break;
@ -2840,9 +2846,12 @@ static void inspection_utility (int pid) {
show_msg(fmtmk(N_fmt(YINSP_pidbad_fmt), pid)); show_msg(fmtmk(N_fmt(YINSP_pidbad_fmt), pid));
return; return;
} }
signify_that:
putp(Cap_clr_scr); putp(Cap_clr_scr);
key = -1; putp(Cap_curs_hide);
adj_geometry();
key = INT_MAX;
do { do {
mkSEL(sels); mkSEL(sels);
putp(Cap_home); putp(Cap_home);
@ -2851,9 +2860,10 @@ static void inspection_utility (int pid) {
, pid, p->cmd, p->euser, sels)); , pid, p->cmd, p->euser, sels));
INSP_MKSL(0, " "); INSP_MKSL(0, " ");
if (-1 == key) key = keyin(0); if (key == INT_MAX) key = keyin(0);
if (key < 1) goto signify_that;
switch (key) { switch (key) {
case 0:
case 'q': case 'q':
case kbd_ESC: case kbd_ESC:
break; break;
@ -2861,13 +2871,13 @@ static void inspection_utility (int pid) {
sel = 0; // fall through ! sel = 0; // fall through !
case kbd_LEFT: case kbd_LEFT:
if (--sel < 0) sel = Inspect.total -1; if (--sel < 0) sel = Inspect.total -1;
key = -1; key = INT_MAX;
break; break;
case kbd_HOME: case kbd_HOME:
sel = Inspect.total; // fall through ! sel = Inspect.total; // fall through !
case kbd_RIGHT: case kbd_RIGHT:
if (++sel >= Inspect.total) sel = 0; if (++sel >= Inspect.total) sel = 0;
key = -1; key = INT_MAX;
break; break;
case kbd_ENTER: case kbd_ENTER:
INSP_BUSY; INSP_BUSY;
@ -2877,11 +2887,10 @@ static void inspection_utility (int pid) {
free(Insp_buf); free(Insp_buf);
free(Insp_p); free(Insp_p);
break; break;
default: // keep gcc happy default:
key = -1; goto signify_that;
break;
} }
} while (key && key != 'q' && key != kbd_ESC); } while (key != 'q' && key != kbd_ESC);
#undef mkSEL #undef mkSEL
} // end: inspection_utility } // end: inspection_utility
@ -2941,7 +2950,8 @@ static void before (char *me) {
#endif #endif
// lastly, establish a robust signals environment // lastly, establish a robust signals environment
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; // with user position perserved through SIGWINCH, we must avoid SA_RESTART
sa.sa_flags = 0;
for (i = SIGRTMAX; i; i--) { for (i = SIGRTMAX; i; i--) {
switch (i) { switch (i) {
case SIGALRM: case SIGHUP: case SIGINT: case SIGALRM: case SIGHUP: case SIGINT:
@ -3145,7 +3155,6 @@ static void configs_read (void) {
, &Rc.fixed_widest, &Rc.summ_mscale, &Rc.task_mscale, &Rc.zero_suppress); , &Rc.fixed_widest, &Rc.summ_mscale, &Rc.task_mscale, &Rc.zero_suppress);
try_inspect_entries: try_inspect_entries:
// we'll start off Inspect stuff with 1 'potential' blank line // we'll start off Inspect stuff with 1 'potential' blank line
// ( only realized if we end up with Inspect.total > 0 ) // ( only realized if we end up with Inspect.total > 0 )
for (i = 0, Inspect.raw = strdup("\n");;) { for (i = 0, Inspect.raw = strdup("\n");;) {
@ -3429,7 +3438,7 @@ static void whack_terminal (void) {
tmptty.c_cc[VERASE] = *key_backspace; tmptty.c_cc[VERASE] = *key_backspace;
#ifndef TERMIO_PROXY #ifndef TERMIO_PROXY
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty)) if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty))
error_exit(fmtmk(N_fmt(FAIL_tty_mod_fmt), strerror(errno))); error_exit(fmtmk(N_fmt(FAIL_tty_set_fmt), strerror(errno)));
tcgetattr(STDIN_FILENO, &Tty_tweaked); tcgetattr(STDIN_FILENO, &Tty_tweaked);
#endif #endif
// lastly, a nearly raw mode for unsolicited single keystrokes // lastly, a nearly raw mode for unsolicited single keystrokes
@ -3437,14 +3446,13 @@ static void whack_terminal (void) {
tmptty.c_cc[VMIN] = 1; tmptty.c_cc[VMIN] = 1;
tmptty.c_cc[VTIME] = 0; tmptty.c_cc[VTIME] = 0;
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty)) if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &tmptty))
error_exit(fmtmk(N_fmt(FAIL_tty_raw_fmt), strerror(errno))); error_exit(fmtmk(N_fmt(FAIL_tty_set_fmt), strerror(errno)));
tcgetattr(STDIN_FILENO, &Tty_raw); tcgetattr(STDIN_FILENO, &Tty_raw);
#ifndef OFF_STDIOLBF #ifndef OFF_STDIOLBF
// thanks anyway stdio, but we'll manage buffering at the frame level... // thanks anyway stdio, but we'll manage buffering at the frame level...
setbuffer(stdout, Stdout_buf, sizeof(Stdout_buf)); setbuffer(stdout, Stdout_buf, sizeof(Stdout_buf));
#endif #endif
// and don't forget to ask keyin to initialize his tinfo_tab // and don't forget to ask keyin to initialize his tinfo_tab
keyin(1); keyin(1);
} // end: whack_terminal } // end: whack_terminal
@ -3542,11 +3550,14 @@ static void wins_colors (void) {
return; return;
} }
wins_clrhlp(w, 1); wins_clrhlp(w, 1);
signify_that:
putp(Cap_clr_scr); putp(Cap_clr_scr);
putp(Cap_curs_huge); putp(Cap_curs_hide);
adj_geometry();
do { do {
putp(Cap_home); putp(Cap_home);
putp(Cap_curs_hide);
// this string is well above ISO C89's minimum requirements! // this string is well above ISO C89's minimum requirements!
show_special(1, fmtmk(N_unq(COLOR_custom_fmt) show_special(1, fmtmk(N_unq(COLOR_custom_fmt)
, procps_version, w->grpname , procps_version, w->grpname
@ -3554,8 +3565,12 @@ static void wins_colors (void) {
, CHKw(w, Show_COLORS) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt) , CHKw(w, Show_COLORS) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
, CHKw(w, Show_HIBOLD) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt) , CHKw(w, Show_HIBOLD) ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
, tgt, clr, w->grpname)); , tgt, clr, w->grpname));
putp(Cap_clr_eos);
fflush(stdout);
key = keyin(0); key = keyin(0);
if (key < 1) goto signify_that;
switch (key) { switch (key) {
case 'S': case 'S':
pclr = &w->rc.summclr; pclr = &w->rc.summclr;
@ -3597,15 +3612,16 @@ static void wins_colors (void) {
clr = w->rc.taskclr, pclr = &w->rc.taskclr; clr = w->rc.taskclr, pclr = &w->rc.taskclr;
tgt = 'T'; tgt = 'T';
break; break;
default: // keep gcc happy default:
break; break; // keep gcc happy
} }
capsmk(w); capsmk(w);
} while (key && key != kbdAPPLY && key != kbdABORT); } while (key != kbdAPPLY && key != kbdABORT);
if (key == kbdABORT) wins_clrhlp(w, 0); if (key == kbdABORT) wins_clrhlp(w, 0);
putp(Cap_curs_norm); putp(Cap_curs_norm);
putp(Cap_clr_scr);
#undef kbdABORT #undef kbdABORT
#undef kbdAPPLY #undef kbdAPPLY
} // end: wins_colors } // end: wins_colors
@ -3807,10 +3823,12 @@ static void find_string (int ch) {
static void help_view (void) { static void help_view (void) {
WIN_t *w = Curwin; // avoid gcc bloat with a local copy WIN_t *w = Curwin; // avoid gcc bloat with a local copy
int ch; char key = 1;
signify_that:
putp(Cap_clr_scr); putp(Cap_clr_scr);
putp(Cap_curs_huge); putp(Cap_curs_hide);
adj_geometry();
show_special(1, fmtmk(N_unq(KEYS_helpbas_fmt) show_special(1, fmtmk(N_unq(KEYS_helpbas_fmt)
, procps_version , procps_version
@ -3819,20 +3837,35 @@ static void help_view (void) {
, Rc.delay_time , Rc.delay_time
, Secure_mode ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt) , Secure_mode ? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)
, Secure_mode ? "" : N_unq(KEYS_helpext_fmt))); , Secure_mode ? "" : N_unq(KEYS_helpext_fmt)));
putp(Cap_clr_eos);
fflush(stdout);
ch = keyin(0); key = keyin(0);
if (ch == '?' || ch == 'h' || ch == 'H') { if (key < 1) goto signify_that;
do {
putp(Cap_clr_scr); switch (key) {
show_special(1, fmtmk(N_unq(WINDOWS_help_fmt) case kbd_ESC: case 'q':
, w->grpname break;
, Winstk[0].rc.winname, Winstk[1].rc.winname case '?': case 'h': case 'H':
, Winstk[2].rc.winname, Winstk[3].rc.winname)); do {
if (0 < (ch = keyin(0))) w = win_select(ch); putp(Cap_home);
} while (ch && ch != kbd_ENTER && ch != kbd_ESC); show_special(1, fmtmk(N_unq(WINDOWS_help_fmt)
, w->grpname
, Winstk[0].rc.winname, Winstk[1].rc.winname
, Winstk[2].rc.winname, Winstk[3].rc.winname));
putp(Cap_clr_eos);
fflush(stdout);
key = keyin(0);
if (key < 1) adj_geometry();
else w = win_select(key);
} while (key != kbd_ENTER && key != kbd_ESC);
break;
default:
goto signify_that;
} }
putp(Cap_curs_norm); putp(Cap_curs_norm);
putp(Cap_clr_scr);
} // end: help_view } // end: help_view
@ -4435,7 +4468,7 @@ static void do_key (int ch) {
for (i = 0; i < MAXTBL(key_tab); ++i) for (i = 0; i < MAXTBL(key_tab); ++i)
if (strchr(key_tab[i].keys, ch)) { if (strchr(key_tab[i].keys, ch)) {
key_tab[i].func(ch); key_tab[i].func(ch);
Frames_resize = 1; Frames_resize = RESIZ_kbd;
return; return;
} }
}; };
@ -4944,10 +4977,12 @@ static void frame_make (void) {
WIN_t *w = Curwin; // avoid gcc bloat with a local copy WIN_t *w = Curwin; // avoid gcc bloat with a local copy
int i, scrlins; int i, scrlins;
// deal with potential signals since the last time around... // deal with potential signal(s) since the last time around...
if (Frames_paused) pause_pgm(); if (Frames_resize) {
if (Frames_resize) zap_fieldstab(); if (Frames_resize > RESIZ_kbd)
putp(Cap_clr_scr);
zap_fieldstab();
}
// whoa either first time or thread/task mode change, (re)prime the pump... // whoa either first time or thread/task mode change, (re)prime the pump...
if (Pseudo_row == PROC_XTRA) { if (Pseudo_row == PROC_XTRA) {
procs_refresh(); procs_refresh();

View File

@ -96,8 +96,8 @@ char *strcasestr(const char *haystack, const char *needle);
/* Length of time a message is displayed and the duration /* Length of time a message is displayed and the duration
of a 'priming' wait during library startup (in microseconds) */ of a 'priming' wait during library startup (in microseconds) */
#define MSG_USLEEP (useconds_t)1250000 #define MSG_USLEEP 1250000
#define LIB_USLEEP (useconds_t)150000 #define LIB_USLEEP 150000
/* Specific process id monitoring support (command line only) */ /* Specific process id monitoring support (command line only) */
#define MONPIDMAX 20 #define MONPIDMAX 20
@ -197,6 +197,11 @@ enum scale_enum {
SK_Kb, SK_Mb, SK_Gb, SK_Tb, SK_Pb, SK_Eb, SK_SENTINEL SK_Kb, SK_Mb, SK_Gb, SK_Tb, SK_Pb, SK_Eb, SK_SENTINEL
}; };
/* Used to manipulate (and document) the Frames_resize states */
enum resize_states {
RESIZ_clr, RESIZ_kbd, RESIZ_sig
};
/* This typedef just ensures consistent 'process flags' handling */ /* This typedef just ensures consistent 'process flags' handling */
typedef unsigned char FLG_t; typedef unsigned char FLG_t;
@ -611,7 +616,6 @@ typedef struct WIN_t {
//atic void bye_bye (const char *str); //atic void bye_bye (const char *str);
//atic void error_exit (const char *str); //atic void error_exit (const char *str);
//atic void library_err (const char *fmts, ...); //atic void library_err (const char *fmts, ...);
//atic void pause_pgm (void);
//atic void sig_abexit (int sig); //atic void sig_abexit (int sig);
//atic void sig_endpgm (int dont_care_sig); //atic void sig_endpgm (int dont_care_sig);
//atic void sig_paused (int dont_care_sig); //atic void sig_paused (int dont_care_sig);

View File

@ -303,8 +303,7 @@ static void build_norm_nlstab (void) {
Norm_nlstab[FAIL_statget_txt] = _("failed /proc/stat read"); Norm_nlstab[FAIL_statget_txt] = _("failed /proc/stat read");
Norm_nlstab[FOREST_modes_fmt] = _("Forest mode %s"); Norm_nlstab[FOREST_modes_fmt] = _("Forest mode %s");
Norm_nlstab[FAIL_tty_get_txt] = _("failed tty get"); Norm_nlstab[FAIL_tty_get_txt] = _("failed tty get");
Norm_nlstab[FAIL_tty_mod_fmt] = _("failed Tty_tweaked set: %s"); Norm_nlstab[FAIL_tty_set_fmt] = _("failed tty set: %s");
Norm_nlstab[FAIL_tty_raw_fmt] = _("failed Tty_raw set: %s");
Norm_nlstab[CHOOSE_group_txt] = _("Choose field group (1 - 4)"); Norm_nlstab[CHOOSE_group_txt] = _("Choose field group (1 - 4)");
Norm_nlstab[DISABLED_cmd_txt] = _("Command disabled, 'A' mode required"); Norm_nlstab[DISABLED_cmd_txt] = _("Command disabled, 'A' mode required");
Norm_nlstab[DISABLED_win_fmt] = _("Command disabled, activate %s with '-' or '_'"); Norm_nlstab[DISABLED_win_fmt] = _("Command disabled, activate %s with '-' or '_'");
@ -333,8 +332,6 @@ static void build_norm_nlstab (void) {
Norm_nlstab[FAIL_alloc_r_txt] = _("failed memory re-allocate"); Norm_nlstab[FAIL_alloc_r_txt] = _("failed memory re-allocate");
Norm_nlstab[BAD_numfloat_txt] = _("Unacceptable floating point"); Norm_nlstab[BAD_numfloat_txt] = _("Unacceptable floating point");
Norm_nlstab[BAD_username_txt] = _("Invalid user"); Norm_nlstab[BAD_username_txt] = _("Invalid user");
Norm_nlstab[FAIL_sigstop_fmt] = _("failed sigprocmask, SIG_BLOCK: %s");
Norm_nlstab[FAIL_sigmask_fmt] = _("failed sigprocmask, SIG_SETMASK: %s");
Norm_nlstab[FOREST_views_txt] = _("forest view"); Norm_nlstab[FOREST_views_txt] = _("forest view");
Norm_nlstab[FAIL_widepid_txt] = _("failed pid maximum size test"); Norm_nlstab[FAIL_widepid_txt] = _("failed pid maximum size test");
Norm_nlstab[FAIL_widecpu_txt] = _("failed number of cpus test"); Norm_nlstab[FAIL_widecpu_txt] = _("failed number of cpus test");
@ -483,7 +480,7 @@ static void build_uniq_nlstab (void) {
" q Quit\n" " q Quit\n"
" ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n" " ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n"
"Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n" "Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n"
"any other key to continue "); "Type 'q' or <Esc> to continue ");
/* Translation Hint: As is true for the text above, the "keys" shown to the left and /* Translation Hint: As is true for the text above, the "keys" shown to the left and
. also imbedded in the translatable text (along with escape seqs) . also imbedded in the translatable text (along with escape seqs)
@ -557,16 +554,16 @@ static void build_uniq_nlstab (void) {
" available toggles: ~1B~2 =disable bold globally (~1%s~2),\n" " available toggles: ~1B~2 =disable bold globally (~1%s~2),\n"
" ~1z~2 =color/mono (~1%s~2), ~1b~2 =tasks \"bold\"/reverse (~1%s~2)\n" " ~1z~2 =color/mono (~1%s~2), ~1b~2 =tasks \"bold\"/reverse (~1%s~2)\n"
"\n" "\n"
"Select ~1target~2 as upper case letter:\n" "1) Select a ~1target~2 as an upper case letter, ~1current target~2 is ~1 %c ~4:\n"
" S~2 = Summary Data,~1 M~2 = Messages/Prompts,\n" " S~2 = Summary Data,~1 M~2 = Messages/Prompts,\n"
" H~2 = Column Heads,~1 T~2 = Task Information\n" " H~2 = Column Heads,~1 T~2 = Task Information\n"
"Select ~1color~2 as number:\n" "2) Select a ~1color~2 as a number, ~1current color~2 is ~1 %d ~4:\n"
" 0~2 = black,~1 1~2 = red, ~1 2~2 = green,~1 3~2 = yellow,\n" " 0~2 = black,~1 1~2 = red, ~1 2~2 = green,~1 3~2 = yellow,\n"
" 4~2 = blue, ~1 5~2 = magenta,~1 6~2 = cyan, ~1 7~2 = white\n" " 4~2 = blue, ~1 5~2 = magenta,~1 6~2 = cyan, ~1 7~2 = white\n"
"\n" "\n"
"Selected: ~1target~2 ~1 %c ~4; ~1color~2 ~1 %d ~4\n" "3) Then use these keys when finished:\n"
" press 'q' to abort changes to window '~1%s~2'\n" " 'q' to abort changes to window '~1%s~2'\n"
" press 'a' or 'w' to commit & change another, <Enter> to commit and end "); " 'a' or 'w' to commit & change another, <Enter> to commit and end ");
Uniq_nlstab[FIELD_header_fmt] = _("" Uniq_nlstab[FIELD_header_fmt] = _(""
"Fields Management~2 for window ~1%s~6, whose current sort field is ~1%s~2\n" "Fields Management~2 for window ~1%s~6, whose current sort field is ~1%s~2\n"

View File

@ -69,19 +69,18 @@ enum norm_nls {
COLORS_nomap_txt, DELAY_badarg_txt, DELAY_change_fmt, DELAY_secure_txt, COLORS_nomap_txt, DELAY_badarg_txt, DELAY_change_fmt, DELAY_secure_txt,
DISABLED_cmd_txt, DISABLED_win_fmt, EXIT_signals_fmt, FAIL_alloc_c_txt, DISABLED_cmd_txt, DISABLED_win_fmt, EXIT_signals_fmt, FAIL_alloc_c_txt,
FAIL_alloc_r_txt, FAIL_openlib_fmt, FAIL_rc_open_fmt, FAIL_re_nice_fmt, FAIL_alloc_r_txt, FAIL_openlib_fmt, FAIL_rc_open_fmt, FAIL_re_nice_fmt,
FAIL_sigmask_fmt, FAIL_signals_fmt, FAIL_sigstop_fmt, FAIL_statget_txt, FAIL_signals_fmt, FAIL_statget_txt, FAIL_statopn_fmt, FAIL_tty_get_txt,
FAIL_statopn_fmt, FAIL_tty_get_txt, FAIL_tty_mod_fmt, FAIL_tty_raw_fmt, FAIL_tty_set_fmt, FAIL_widecpu_txt, FAIL_widepid_txt, FIND_no_find_fmt,
FAIL_widecpu_txt, FAIL_widepid_txt, FIND_no_find_fmt, FIND_no_next_txt, FIND_no_next_txt, FOREST_modes_fmt, FOREST_views_txt, GET_find_str_txt,
FOREST_modes_fmt, FOREST_views_txt, GET_find_str_txt, GET_max_task_fmt, GET_max_task_fmt, GET_nice_num_fmt, GET_pid2kill_fmt, GET_pid2nice_fmt,
GET_nice_num_fmt, GET_pid2kill_fmt, GET_pid2nice_fmt, GET_sigs_num_fmt, GET_sigs_num_fmt, GET_user_ids_txt, HELP_cmdline_fmt, HILIGHT_cant_txt,
GET_user_ids_txt, HELP_cmdline_fmt, HILIGHT_cant_txt, IRIX_curmode_fmt, IRIX_curmode_fmt, LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt,
LIMIT_exceed_fmt, MISSING_args_fmt, NAME_windows_fmt, NOT_onsecure_txt, NOT_onsecure_txt, NOT_smp_cpus_txt, OFF_one_word_txt, ON_word_only_txt,
NOT_smp_cpus_txt, OFF_one_word_txt, ON_word_only_txt, RC_bad_entry_fmt, RC_bad_entry_fmt, RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt,
RC_bad_files_fmt, SCROLL_coord_fmt, SELECT_clash_txt, THREADS_show_fmt, THREADS_show_fmt, TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt,
TIME_accumed_fmt, UNKNOWN_cmds_txt, UNKNOWN_opts_fmt, USAGE_abbrev_txt, USAGE_abbrev_txt, WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt,
WORD_allcpus_txt, WORD_another_txt, WORD_eachcpu_fmt, WORD_process_txt, WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt, XTRA_fixwide_fmt, XTRA_fixwide_fmt, XTRA_sortopt_fmt, XTRA_warncfg_txt,
XTRA_sortopt_fmt, XTRA_warncfg_txt,
#ifndef INSP_OFFDEMO #ifndef INSP_OFFDEMO
YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt, YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
YINSP_deqtyp_txt, YINSP_dstory_txt, YINSP_deqtyp_txt, YINSP_dstory_txt,