/* These 'SCREEN_ROWS', 'BOT_ and 'Bot_' guys are used
in managing the special separate bottom 'window' ... */
#define SCREEN_ROWS ( Screen_rows - Bot_rsvd )
+#define BOT_MSGSMAX 10 // total entries for Msg_tab
#define BOT_UNFOCUS -1 // tab focus not established
+ // negative 'item' values won't be seen by build_headers() ...
+#define BOT_MSG_LOG -3 // show the most recent msgs
// next 4 are used when toggling window contents
#define BOT_SEP_CMA ','
#define BOT_SEP_SLS '/'
+#define BOT_SEP_SMI ';'
#define BOT_SEP_SPC ' '
// 1 for horizontal separator
#define BOT_RSVD 1
} // end: capsmk
+static struct msg_node {
+ char msg[SMLBUFSIZ];
+ struct msg_node *prev;
+} Msg_tab[BOT_MSGSMAX];
+
+static struct msg_node *Msg_this = Msg_tab;
+
/*
* Show an error message (caller may include '\a' for sound) */
static void show_msg (const char *str) {
+ STRLCPY(Msg_this->msg, str);
+ if (++Msg_this > &Msg_tab[BOT_MSGSMAX - 1]) Msg_this = Msg_tab;
+
PUTT("%s%s %.*s %s%s%s"
, tg2(0, Msg_row)
, Curwin->capclr_msg
// for 'U' filtering we need the other user ids too
if (w->usrseltyp == 'U') Frames_libflags |= L_status;
- // lastly, accommodate any special non-display 'tagged' needs...
- Frames_libflags |= Bot_what;
} // end: VIZISw(w)
if (Rc.mode_altscr) w = w->next;
} while (w != Curwin);
+ // lastly, accommodate any special bottom window needs...
+ if (Bot_what > 0)
+ Frames_libflags |= Bot_what;
+
#ifdef EQUCOLHDRYES
/* now we can finally even out column header lengths
(we're assuming entire columnhdr was memset to '\0') */
Winstk[GROUPSMAX - 1].next = &Winstk[0];
Winstk[0].prev = &Winstk[GROUPSMAX - 1];
Curwin = Winstk;
+
+ for (i = 1; i < BOT_MSGSMAX; i++)
+ Msg_tab[i].prev = &Msg_tab[i - 1];
+ Msg_tab[0].prev = &Msg_tab[BOT_MSGSMAX -1];
} // end: wins_stage_1
* ( returns relative # of elements printed ) | */
static int bot_focus_str (const char *hdr, const char *str) {
#define maxRSVD ( Screen_rows - 1 )
- const char *end, *beg;
+ char *beg, *end;
char tmp[BIGBUFSIZ];
int n, x;
IPCNS, MNTNS, NETNS, PIDNS, USERNS, UTSNS };
static char buf[BIGBUFSIZ];
char tmp[SMLBUFSIZ], *b;
+ struct msg_node *m;
int i;
buf[0] = '\0';
switch (Bot_what) {
+ case BOT_MSG_LOG:
+ *(b = &buf[0]) = '\0';
+ m = Msg_this->prev;
+ do {
+ if (m->msg[0]) {
+ b = scat(b, m->msg);
+ if (m != Msg_this && m->prev->msg[0]) {
+ // caller itself may have used fmtmk, so we'll old school it ...
+ snprintf(tmp, sizeof(tmp), "%c ", BOT_SEP_SMI);
+ b = scat(b, tmp);
+ }
+ }
+ m = m->prev;
+ } while (m != Msg_this->prev);
+ return buf;
case (L_NS):
b = &buf[0];
for (i = 0; i < MAXTBL(ns_tab); i++) {
// with string vectors, the 'separator' may serve a different purpose
bot_item_toggle(PROC_FILLARG, N_fmt(X_BOT_cmdlin_fmt), BOT_SEP_SPC);
break;
+ case kbd_CtrlL:
+ bot_item_toggle(BOT_MSG_LOG, N_txt(X_BOT_msglog_txt), BOT_SEP_SMI);
+ break;
case kbd_CtrlN:
// with string vectors, the 'separator' may serve a different purpose
bot_item_toggle(PROC_FILLENV, N_fmt(X_BOT_envirn_fmt), BOT_SEP_SPC);
{ keys_global,
{ '?', 'B', 'd', 'E', 'e', 'f', 'g', 'H', 'h'
, 'I', 'k', 'r', 's', 'X', 'Y', 'Z', '0'
- , kbd_CtrlE, kbd_CtrlG, kbd_CtrlI, kbd_CtrlK
+ , kbd_CtrlE, kbd_CtrlG, kbd_CtrlI, kbd_CtrlK, kbd_CtrlL
, kbd_CtrlN, kbd_CtrlP, kbd_CtrlU
, kbd_ENTER, kbd_SPACE, kbd_BTAB, '\0' } },
{ keys_summary,
WORD_process_txt, WORD_threads_txt, WRITE_rcfile_fmt, WRONG_switch_fmt,
XTRA_badflds_fmt, XTRA_fixwide_fmt, XTRA_modebad_txt, XTRA_size2up_txt,
XTRA_vforest_fmt, XTRA_warncfg_txt, XTRA_warnold_txt, XTRA_winsize_txt,
- X_BOT_cmdlin_fmt, X_BOT_ctlgrp_fmt, X_BOT_envirn_fmt, X_BOT_namesp_fmt,
- X_BOT_supgrp_fmt,
+ X_BOT_cmdlin_fmt, X_BOT_ctlgrp_fmt, X_BOT_envirn_fmt, X_BOT_msglog_txt,
+ X_BOT_namesp_fmt, X_BOT_supgrp_fmt,
YINSP_demo01_txt, YINSP_demo02_txt, YINSP_demo03_txt, YINSP_deqfmt_txt,
YINSP_deqtyp_txt, YINSP_dstory_txt,
YINSP_failed_fmt, YINSP_noent1_txt, YINSP_noent2_txt, YINSP_pidbad_fmt,