/* 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_MAXIMUM 10 // Bot_item array's max size
-#define BOT_DELIMIT -1 // fencepost with item array
+#define BOT_ITEMMAX 10 // Bot_item array's max size
+#define BOT_MSGSMAX 10 // total entries for Msg_tab
#define BOT_UNFOCUS -1 // tab focus not established
- // a negative 'item' won't be seen by build_headers() ...
+ // negative 'item' values won't be seen by build_headers() ...
+#define BOT_DELIMIT -1 // fencepost with item array
#define BOT_ITEM_NS -2 // data for namespaces req'd
+#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
Bot_what,
Bot_rsvd,
Bot_indx = BOT_UNFOCUS,
- Bot_item[BOT_MAXIMUM] = { BOT_DELIMIT };
+ Bot_item[BOT_ITEMMAX] = { BOT_DELIMIT };
static char Bot_sep,
*Bot_head,
Bot_buf[BOTBUFSIZ]; // the 'environ' can be huge
} // 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
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;
static void *bot_item_hlp (struct pids_stack *p) {
static char buf[BIGBUFSIZ];
char tmp[SMLBUFSIZ], *b;
+ struct msg_node *m;
int i;
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 BOT_ITEM_NS:
*(b = &buf[0]) = '\0';
for (i = 0; i < MAXTBL(ns_tab); i++) {
// with string vectors, the 'separator' may serve a different purpose
bot_item_toggle(eu_CMDLINE_V, 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(eu_ENVIRON_V, 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_CtrlR, 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_RESTRICTED_txt, X_SEMAPHORES_fmt, X_THREADINGS_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, X_RESTRICTED_txt, X_SEMAPHORES_fmt,
+ X_THREADINGS_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,