diff --git a/top/top.c b/top/top.c index ed1792cb..2e45199f 100644 --- a/top/top.c +++ b/top/top.c @@ -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' } }, diff --git a/top/top.h b/top/top.h index bbee25fa..3299dd3d 100644 --- a/top/top.h +++ b/top/top.h @@ -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);