top: extend 'Ctrl' bottom window for focus via tab key

This commit introduces the 'tab' key which can be used
to highlight individual elements in that bottom 'Ctrl'
window. This can really help when reviewing such data.

[ note, normal ongoing monitoring continues unabated ]

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2022-05-12 00:00:00 -05:00 committed by Craig Small
parent c46a60d9c4
commit de22afc4c2
2 changed files with 112 additions and 49 deletions

153
top/top.c
View File

@ -104,20 +104,25 @@ static int Screen_cols, Screen_rows, Max_lines;
// these are for the special separate bottom 'window'
#define SCREEN_ROWS ( Screen_rows - Bot_rsvd )
#define BOT_MAXIMUM 10
#define BOT_DELIMIT -1
#define BOT_MISC_NS +1
#define BOT_MAXIMUM 10 // size of tagged item array
#define BOT_DELIMIT -1 // fenchpost with item array
#define BOT_UNFOCUS -1 // tab focus not established
#define BOT_TAB_YES -1 // tab focus could be active
#define BOT_MISC_NS +1 // data for namespaces req'd
// 1 for horizontal separator
#define BOT_RSVD 1
#define BOT_KEEP Bot_func = NULL
#define BOT_TOSS do { Bot_func = NULL; Bot_item[0] = BOT_DELIMIT; \
Bot_task = Bot_rsvd = Bot_misc = 0; \
Bot_task = Bot_rsvd = Bot_what = 0; \
Bot_indx = BOT_UNFOCUS; \
} while(0)
static int Bot_task,
Bot_misc,
Bot_what,
Bot_rsvd,
Bot_indx = BOT_UNFOCUS,
Bot_item[BOT_MAXIMUM] = { BOT_DELIMIT };
static char *Bot_name;
static char *Bot_name,
Bot_sep;
static void(*Bot_func)(void);
/* This is really the number of lines needed to display the summary
@ -4897,29 +4902,65 @@ static inline const char *forest_display (const WIN_t *q, int idx) {
/*###### Special Separate Bottom Window support ########################*/
/*
* This guy actually draws the bottom window, |
* including the contents passed as a string. | */
static void bot_do_see (const char *str, const char *pgm) {
#define maxRSVD ( Screen_rows - 1 )
char buf[SMLBUFSIZ];
snprintf(buf, sizeof(buf), "%s for pid %d, %s"
, Bot_name, Bot_task, pgm);
if (!str || !*str || !strcmp(str, "-")) str = "n/a";
Bot_rsvd = 1 + BOT_RSVD + (strlen(str) / Screen_cols);
if (Bot_rsvd > maxRSVD) Bot_rsvd = maxRSVD;
putp(fmtmk("%s%s%-*s", tg2(0, SCREEN_ROWS), Curwin->capclr_hdr, Screen_cols, buf));
putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_clr_eos));
putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_norm));
fputs(str, stdout);
#undef maxRSVD
} // end: bot_do_see
* This guy actually draws the parsed strings |
* including adding a highlight if necessary. | */
static void bot_do (const char *str, int focus) {
while (*str == ' ') putchar(*(str++));
putp(fmtmk("%s%s%s"
, focus ? Cap_reverse : Cap_norm
, str
, Cap_norm));
} // end: bot_do
/*
* This guy manages the bottom margin window, |
* This guy draws that bottom window's header |
* then parses/arranges to show the contents. |
* ( returns the number of elements printed ) | */
static int bot_focus (const char *hdr, const char *str) {
#define maxRSVD ( Screen_rows - 1 )
static char sav[BIGBUFSIZ*2];
const char *end, *beg;
char tmp[SCREENMAX];
int n, x;
if (str) {
if (!*str || !strcmp(str, "-")) strcpy(sav, "n/a");
else memccpy(sav, str, '\0', sizeof(sav) - 1);
Bot_rsvd = 1 + BOT_RSVD + (strlen(sav) / Screen_cols);
if (Bot_rsvd > maxRSVD) Bot_rsvd = maxRSVD;
// caller itself may have used fmtmk, so we'll old school it ...
snprintf(tmp, sizeof(tmp), "%s%s%-*s", tg2(0, SCREEN_ROWS), Curwin->capclr_hdr, Screen_cols, hdr);
putp(tmp);
}
// now fmtmk is safe to use ...
putp(fmtmk("%s%s%s", tg2(0, SCREEN_ROWS + 1), Cap_clr_eos, Cap_norm));
beg = &sav[0];
x = BOT_UNFOCUS;
while (*beg) {
if (!(end = strchr(beg, Bot_sep)))
end = beg + strlen(beg);
if ((n = end - beg) >= sizeof(tmp))
n = sizeof(tmp) - 1;
memccpy(tmp, beg, '\0', n);
tmp[n] = '\0';
bot_do(tmp, (++x == Bot_indx));
if (*(beg += n))
putchar(*(beg++));
while (*beg == ' ') putchar(*(beg++));
}
return x;
#undef maxRSVD
} // end: bot_focus
/*
* This guy manages that bottom margin window |
* showing misc stuff based on a single item. | */
static void bot_item_show (void) {
#define mkHDR fmtmk("%s for pid %d, %s", Bot_name, Bot_task, PID_VAL(EU_CMD, str, p))
struct pids_stack *p;
int i;
@ -4929,7 +4970,7 @@ static void bot_item_show (void) {
break;
}
if (i < PIDSmaxt) {
bot_do_see(PID_VAL(Bot_item[0], str, p), PID_VAL(EU_CMD, str, p));
bot_focus(mkHDR, PID_VAL(Bot_item[0], str, p));
}
#ifdef BOT_DEAD_ZAP
else
@ -4937,18 +4978,21 @@ static void bot_item_show (void) {
#else
BOT_KEEP;
#endif
#undef mkHDR
} // end: bot_item_show
/*
* This guy toggles between displaying a Ctrl |
* This guy can toggle between displaying the |
* bottom window or arranging to turn it off. | */
static void bot_item_toggle (enum pflag item, const char *name) {
static void bot_item_toggle (enum pflag item, const char *name, char sep) {
// if already targeted, assume user wants to turn it off ...
if (Bot_item[0] == item) {
BOT_TOSS;
} else {
Bot_misc = 0;
Bot_sep = sep;
Bot_what = BOT_TAB_YES;
Bot_indx = BOT_UNFOCUS;
Bot_item[0] = item;
Bot_item[1] = BOT_DELIMIT;
Bot_name = (char*)name;
@ -4968,20 +5012,26 @@ static struct {
{ EU_NS5, PROCPS_NS_USER }, { EU_NS6, PROCPS_NS_UTS }
};
/*
* A helper function that will gather various |
* stuff for dislay by the bot_misc_show guy. | */
static char *bot_misc_hlp (struct pids_stack *p) {
static char buf[BIGBUFSIZ], *b;
static char tmp[SMLBUFSIZ], buf[BIGBUFSIZ], *b;
int i;
buf[0] = '\0';
switch (Bot_misc) {
switch (Bot_what) {
case BOT_MISC_NS:
b = &buf[0];
for (i = 0; i < MAXTBL(ns_tab); i++)
b = scat(b, fmtmk("%s: %-10lu "
, procps_ns_get_name(ns_tab[i].that), PID_VAL(ns_tab[i].this, ul_int, p)));
for (i = 0; i < MAXTBL(ns_tab); i++) {
// caller itself may have used fmtmk, so we'll old school it ...
snprintf(tmp, sizeof(tmp), "%s: %-10lu"
, procps_ns_get_name(ns_tab[i].that)
, PID_VAL(ns_tab[i].this, ul_int, p));
b = scat(b, tmp);
if (i < (MAXTBL(ns_tab) - 1)) b = scat(b, ", ");
}
break;
default:
break;
@ -4991,9 +5041,10 @@ static char *bot_misc_hlp (struct pids_stack *p) {
/*
* This guy manages the bottom margin window, |
* This guy manages that bottom margin window |
* showing misc data based on multiple items. | */
static void bot_misc_show (void) {
#define mkHDR fmtmk("%s for pid %d, %s", Bot_name, Bot_task, PID_VAL(EU_CMD, str, p))
struct pids_stack *p;
int i;
@ -5003,25 +5054,26 @@ static void bot_misc_show (void) {
break;
}
if (i < PIDSmaxt) {
bot_do_see(bot_misc_hlp(p), PID_VAL(EU_CMD, str, p));
bot_focus(mkHDR, bot_misc_hlp(p));
}
#ifdef BOT_DEATH
#ifdef BOT_DEAD_ZAP
else
BOT_TOSS;
#else
BOT_KEEP;
#endif
#undef mkHDR
} // end: bot_misc_show
/*
* This guy toggles between displaying a Ctrl |
* This guy can toggle between displaying the |
* bottom window or arranging to turn it off. | */
static void bot_misc_toggle (int what) {
static void bot_misc_toggle (int what, char sep) {
int i;
// if already targeted, assume user wants to turn it off ...
if (Bot_misc == what) {
if (Bot_what == what) {
BOT_TOSS;
} else {
switch (what) {
@ -5034,7 +5086,9 @@ static void bot_misc_toggle (int what) {
default:
break;
}
Bot_misc = what;
Bot_sep = sep;
Bot_what = what;
Bot_indx = BOT_UNFOCUS;
Bot_func = bot_misc_show;
Bot_task = PID_VAL(EU_PID, s_int, Curwin->ppt[Curwin->begtask]);
}
@ -5415,16 +5469,23 @@ static void keys_global (int ch) {
#endif
break;
case kbd_CtrlG:
bot_item_toggle(EU_CGR, "control groups");
bot_item_toggle(EU_CGR, "control groups", '/');
break;
case kbd_CtrlI:
if (Bot_what) {
++Bot_indx;
if (Bot_indx > bot_focus(NULL, NULL))
Bot_indx = BOT_UNFOCUS;
}
break;
case kbd_CtrlK:
bot_item_toggle(eu_CMDLINE, "command line");
bot_item_toggle(eu_CMDLINE, "command line", ' ');
break;
case kbd_CtrlN:
bot_item_toggle(EU_ENV, "environment");
bot_item_toggle(EU_ENV, "environment", ' ');
break;
case kbd_CtrlP:
bot_misc_toggle(BOT_MISC_NS);
bot_misc_toggle(BOT_MISC_NS, ',');
break;
case kbd_CtrlR:
if (Secure_mode)
@ -5453,7 +5514,7 @@ static void keys_global (int ch) {
}
break;
case kbd_CtrlU:
bot_item_toggle(EU_SGN, "supplementary groups");
bot_item_toggle(EU_SGN, "supplementary groups", ',');
break;
case kbd_ENTER: // these two have the effect of waking us
case kbd_SPACE: // from 'pselect', refreshing the display
@ -6295,7 +6356,7 @@ static void do_key (int ch) {
{ keys_global,
{ '?', 'B', 'd', 'E', 'e', 'f', 'g', 'H', 'h'
, 'I', 'k', 'r', 's', 'X', 'Y', 'Z', '0'
, kbd_CtrlE, kbd_CtrlG, kbd_CtrlK, kbd_CtrlN, kbd_CtrlP, kbd_CtrlR, kbd_CtrlU
, kbd_CtrlE, kbd_CtrlG, kbd_CtrlI, kbd_CtrlK, kbd_CtrlN, kbd_CtrlP, kbd_CtrlR, kbd_CtrlU
, kbd_ENTER, kbd_SPACE, '\0' } },
{ keys_summary,
{ '!', '1', '2', '3', '4', 'C', 'l', 'm', 't', '\0' } },

View File

@ -173,6 +173,7 @@ char *strcasestr(const char *haystack, const char *needle);
#define kbd_DEL 139
#define kbd_CtrlE '\005'
#define kbd_CtrlG '\007'
#define kbd_CtrlI '\011'
#define kbd_CtrlK '\013'
#define kbd_CtrlN '\016'
#define kbd_CtrlO '\017'
@ -735,12 +736,13 @@ typedef struct WIN_t {
//atic void forest_config (WIN_t *q);
//atic inline const char *forest_display (const WIN_t *q, int idx);
/*------ Special Separate Bottom Window support ------------------------*/
//atic void bot_do_see (const char *str, const char *pgm);
//atic void bot_do (const char *str, int focus);
//atic int bot_focus (const char *hdr, const char *str);
//atic void bot_item_show (void);
//atic void bot_item_toggle (enum pflag item, const char *name);
//atic void bot_item_toggle (enum pflag item, const char *name, char sep);
//atic char *bot_misc_hlp (struct pids_stack *p);
//atic void bot_misc_show (void);
//atic void bot_misc_toggle (int what);
//atic void bot_misc_toggle (int what, char sep);
/*------ Interactive Input Tertiary support ----------------------------*/
//atic inline int find_ofs (const WIN_t *q, const char *buf);
//atic void find_string (int ch);