Index | Thread | Search

From:
Dante Catalfamo <dante@lambda.cx>
Subject:
mg: add *Messages* buffer
To:
tech@openbsd.org
Date:
Sun, 29 Jun 2025 02:23:37 -0400

Download raw body.

Thread
  • Dante Catalfamo:

    mg: add *Messages* buffer

Hi,

This patch adds the *Messages* buffer to mg and uses it to log all 
messages shown in the echo area, similar to Emacs. I find it helpful in 
cases where something gets shows and you accidentally press a key before 
you have a chance to read it. It will also re-create the buffer if it 
gets destroyed.

Thanks

diff --git a/usr.bin/mg/Makefile b/usr.bin/mg/Makefile
index fc3899772ec..02238b99605 100644
--- a/usr.bin/mg/Makefile
+++ b/usr.bin/mg/Makefile
@@ -15,7 +15,7 @@ CFLAGS+=-Wall -DREGEX
  
  SRCS=	autoexec.c basic.c bell.c buffer.c cinfo.c dir.c display.c \
  	echo.c extend.c file.c fileio.c funmap.c help.c kbd.c keymap.c \
-	line.c macro.c main.c match.c modes.c paragraph.c \
+	line.c macro.c main.c match.c modes.c msg.c paragraph.c \
  	re_search.c region.c search.c spawn.c tty.c ttyio.c ttykbd.c \
  	undo.c util.c version.c window.c word.c yank.c
  
diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h
index 403635036ce..3b5505e92ac 100644
--- a/usr.bin/mg/def.h
+++ b/usr.bin/mg/def.h
@@ -681,6 +681,10 @@ int		 notabmode(int, int);
  int		 overwrite_mode(int, int);
  int		 set_default_mode(int,int);
  
+/* msg.c X */
+int		msgchr(int);
+int		msgflush(void);
+
  #ifdef REGEX
  /* re_search.c X */
  int		 re_forwsearch(int, int);
@@ -776,3 +780,4 @@ extern int		 tceeol;
  extern int		 tcinsl;
  extern int		 tcdell;
  extern int		 rptcount;	/* successive invocation count */
+extern int		 nomsg;
diff --git a/usr.bin/mg/echo.c b/usr.bin/mg/echo.c
index 9b90aaa5ef7..e083b03206f 100644
--- a/usr.bin/mg/echo.c
+++ b/usr.bin/mg/echo.c
@@ -63,7 +63,9 @@ eyorn(const char *sp)
  	if (inmacro)
  		return (TRUE);
  
+	nomsg = 1;
  	ewprintf("%s? (y or n) ", sp);
+	nomsg = 0;
  	for (;;) {
  		s = getkey(FALSE);
  		if (s == 'y' || s == 'Y' || s == ' ') {
@@ -97,7 +99,9 @@ eynorr(const char *sp)
  	if (inmacro)
  		return (TRUE);
  
+	nomsg = 1;
  	ewprintf("%s? (y, n or r) ", sp);
+	nomsg = 0;
  	for (;;) {
  		s = getkey(FALSE);
  		if (s == 'y' || s == 'Y' || s == ' ') {
@@ -177,9 +181,11 @@ eread(const char *fmt, char *buf, size_t nbuf, int flag, ...)
  	va_list	 ap;
  	char	*rep;
  
+	nomsg = 1;
  	va_start(ap, flag);
  	rep = veread(fmt, buf, nbuf, flag, ap);
  	va_end(ap);
+	nomsg = 0;
  	return (rep);
  }
  
@@ -842,7 +848,7 @@ ewprintf(const char *fmt, ...)
   * Printf style formatting. This is called by "ewprintf" to provide
   * formatting services to its clients.  The move to the start of the
   * echo line, and the erase to the end of the echo line, is done by
- * the caller.
+ * the caller.
   * %c prints the "name" of the supplied character.
   * %k prints the name of the current key (and takes no arguments).
   * %d prints a decimal integer
@@ -916,6 +922,7 @@ eformat(const char *fp, va_list ap)
  			}
  		}
  	}
+	msgflush();
  }
  
  /*
@@ -977,6 +984,7 @@ eputc(char c)
  			c = CCHR(c);
  		}
  		ttputc(c);
+		msgchr(c);
  		++ttcol;
  	}
  }
diff --git a/usr.bin/mg/main.c b/usr.bin/mg/main.c
index 56ef7d9a042..c02fd703416 100644
--- a/usr.bin/mg/main.c
+++ b/usr.bin/mg/main.c
@@ -36,6 +36,7 @@ int		 dovisiblebell;			/* visible bell toggle	*/
  int		 dblspace;			/* sentence end #spaces	*/
  int		 allbro;			/* all buffs read-only	*/
  int		 batch;				/* for regress tests	*/
+int		 nomsg;				/* message buffer	*/
  struct buffer	*curbp;				/* current buffer	*/
  struct buffer	*bheadp;			/* BUFFER list head	*/
  struct mgwin	*curwp;				/* current window	*/
diff --git a/usr.bin/mg/msg.c b/usr.bin/mg/msg.c
new file mode 100644
index 00000000000..e6019245af3
--- /dev/null
+++ b/usr.bin/mg/msg.c
@@ -0,0 +1,48 @@
+#include <sys/queue.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "def.h"
+
+#define NOMSGBUF 512
+size_t	nomsgbuf;
+char	msgbuf[NOMSGBUF];
+
+int
+msgchr(int c)
+{
+	if (nomsg)
+		return 0;
+
+	if (nomsgbuf >= NOMSGBUF-1) {
+		msgflush();
+	}
+	msgbuf[nomsgbuf++] = c;
+
+	return (c);
+}
+
+int
+msgflush(void)
+{
+        struct buffer *bp;
+	struct mgwin *wp;
+
+	if (nomsgbuf == 0)
+		return 0;
+
+        if ((bp = bfind("*Messages*", TRUE)) == NULL) {
+		panic("out of memory in msg");
+	}
+
+	msgbuf[nomsgbuf] = '\0';
+	addline(bp, msgbuf);
+	nomsgbuf = 0;
+
+	for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
+		if (wp->w_bufp == bp)
+			wp->w_rflag |= WFFULL;
+	}
+
+	return 0;
+}