[schilytools] [PATCH] bsh: implement ^L support

Robert Clausecker fuz at fuz.su
Mon Jul 4 03:14:19 CEST 2022


Typing ^L in bsh will now clear the screen as already supported in a
number of other shells.

This patch is based on a submission by Nico Sonack, but has been
thoroughly reworked to be portable to any terminal.

Issue:		#10
Co-authored-by:	Nico Sonack <nsonack at herrhotzenplotz.de>
---
 bsh/inputc.c | 61 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 9 deletions(-)

diff --git a/bsh/inputc.c b/bsh/inputc.c
index e043e915..8bfeeb4d 100644
--- a/bsh/inputc.c
+++ b/bsh/inputc.c
@@ -146,6 +146,7 @@ typedef struct {
 #define	BACKSPACE	8	/* ^H Mode Cursor one position to the left  */
 #define	TAB		9	/* ^I TAB is an alias for EXPAND	    */
 				/* ^J New Line				    */
+#define	FORMFEED	12	/* ^L Clear screen			    */
 #define	DOWNWARD	14	/* ^N Scroll down to next line in history   */
 #define	UPWARD		16	/* ^P Scroll up to previous line in history */
 #define	RETYPE		18	/* ^R Redisplay current edit line	    */
@@ -230,6 +231,7 @@ EXPORT	char	*match_hist	__PR((char *pattern));
 LOCAL	HISTPTR match		__PR((HISTPTR cur_line, wchar_t *pattern,
 						BOOL up));
 LOCAL	int	edit_line	__PR((HISTPTR cur_line));
+LOCAL	void	_redisp		__PR((wchar_t *lp, wchar_t *cp));
 LOCAL	void	redisp		__PR((wchar_t *lp, wchar_t *cp));
 LOCAL	wchar_t	*insert		__PR((wchar_t *cp, wchar_t *s,
 						unsigned int *lenp));
@@ -266,6 +268,7 @@ EXPORT	void	readhistory	__PR((MYFILE *f));
 LOCAL	void	term_init	__PR((void));
 LOCAL	void	tty_init	__PR((void));
 LOCAL	void	tty_term	__PR((void));
+LOCAL	void	tty_clear	__PR((void));
 #ifdef	DO_DEBUG
 LOCAL	void	cdbg		__PR((char *fmt, ...))	__printflike__(1, 2);
 #endif
@@ -1523,6 +1526,11 @@ edit_line(cur_line)
 			printf("ctlc: %d\r\n", ctlc);
 #endif
 			return ('\n');
+		case FORMFEED:
+			tty_clear();
+			bflush();
+			_redisp(lp, cp);
+			break;
 		case RETYPE:
 			redisp(lp, cp);
 			break;
@@ -1691,19 +1699,31 @@ edit_line(cur_line)
 
 
 /*
- * Redisplay current line.
+ * Redisplay current line without a leading newline.
  */
 LOCAL void
-redisp(lp, cp)
+_redisp(lp, cp)
 	wchar_t	*lp;
 	wchar_t	*cp;
 {
-	(void) fprintf(stderr, "\r\n%s", iprompt);
+	(void) fprintf(stderr, "%s", iprompt);
 	(void) fflush(stderr);
 	writews(lp);
 	backspace(linelen(cp));
 }
 
+/*
+ * Redisplay current line.
+ */
+LOCAL void
+redisp(lp, cp)
+	wchar_t	*lp;
+	wchar_t	*cp;
+{
+	(void) fprintf(stderr, "\r\n");
+	_redisp(lp, cp);
+}
+
 
 /*
  * Insert a string a current cursor position.
@@ -2870,24 +2890,28 @@ LOCAL	char	*KS;		/* Keypad start transmit mode	"ks"	*/
 LOCAL	char	*VE;		/* Visual end sequence		"ve"	*/
 LOCAL	char	*VS;		/* Visual start sequence	"vs"	*/
 
+LOCAL	char	*CL;		/* Clear screen and home cursor	"cl"	*/
+LOCAL	char	*CD;		/* Clear to end of screen	"cd"	*/
+LOCAL	char	*HO;		/* Home cursor			"ho"	*/
+LOCAL	int	 LI;		/* Number of lines		"li"	*/
+
 LOCAL	char	**tstrs[] = {
-		&KE, &KS, &VE, &VS,
+		&KE, &KS, &VE, &VS, &CL, &CD, &HO
 };
 
 LOCAL void
 term_init()
 {
-	register char	*np = "keksvevs";
+	register char	*np = "keksvevsclcdho";
 	register char	***sp = tstrs;
 
-	if (KE) free(KE);
-	if (KS) free(KS);
-	if (VE) free(VE);
-	if (VS) free(VS);
 	do {
+		if (**sp) free(**sp);
 		*(*sp++) = tgetstr(np, NULL);
 		np += 2;
 	} while (*np);
+
+	LI = tgetnum("li");
 }
 
 #define	f_putch		((int (*)__PR((int)))putch)
@@ -2907,6 +2931,25 @@ tty_term()
 	bflush();
 }
 
+/*
+ * Clear screen and home cursor.
+ * If this cannot be done, just go to the next line.
+ */
+LOCAL void
+tty_clear()
+{
+	/* algorithm from libeditline */
+	if (CL)
+		tputs(CL, LI, f_putch);
+	else if (HO && CD) {
+		tputs(HO, 1, f_putch);
+		tputs(CD, LI, f_putch);
+	} else {
+		/* cannot clear screen (hardcopy terminal?) */
+		putch('\r');
+		putch('\n');
+	}
+}
 
 #ifdef	DO_DEBUG
 #include <schily/varargs.h>
-- 
2.36.1



More information about the schilytools mailing list