diff pager.c @ 18:1e39a251cbe9

Use libtecla for interactive input
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Thu, 24 Aug 2017 13:10:56 +0200
parents a08ef0674d8e
children 5c6155c8e9b6
line wrap: on
line diff
--- a/pager.c	Sat Aug 12 10:41:52 2017 +0200
+++ b/pager.c	Thu Aug 24 13:10:56 2017 +0200
@@ -28,6 +28,7 @@
 #endif /* HAVE_ERR_H */
 #include <errno.h>
 #include <fcntl.h>
+#include <libtecla.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdio.h>
@@ -46,22 +47,6 @@
 #include "pager.h"
 #include "util.h"
 
-#ifndef	TCSASOFT
-#define	TCSASOFT 0
-#endif /* !TCSASOFT */
-
-#ifndef	_NSIG
-#ifdef NSIG
-#define	_NSIG NSIG
-#else /* NSIG */
-#define	_NSIG 128
-#endif /* NSIG */
-#endif /* !_NSIG */
-
-#ifndef	_PATH_TTY
-#define	_PATH_TTY	"/dev/tty"
-#endif
-
 struct pager {
 	TAILQ_HEAD(lines_head, lines_entry) lines_head;
 	FILE		*fp;
@@ -74,123 +59,22 @@
 	char		*line;
 };
 
-static volatile sig_atomic_t signals[_NSIG];
-
-static void
-sig_handler(int signo)
-{
-	signals[signo] = 1;
-}
-
 static int
-getch_prompt(const char *prompt)
+getch_prompt(GetLine *gl, const char *prompt)
 {
-	int		retval = -1;
-	int		signo;
-	int		fd;
-	struct termios	saved_term;
-	struct termios	term;
-	struct sigaction sa;
-	struct sigaction saved_sa_hup;
-	struct sigaction saved_sa_int;
-	struct sigaction saved_sa_quit;
-	struct sigaction saved_sa_pipe;
-	struct sigaction saved_sa_alrm;
-	struct sigaction saved_sa_term;
-	struct sigaction saved_sa_tstp;
-	struct sigaction saved_sa_ttin;
-	struct sigaction saved_sa_ttou;
-	char		c;
-	int		need_restart = 0;
-
-	printf("%s", prompt);
-	fflush(stdout);
-
-restart:
-	for (signo = 0; signo < _NSIG; signo++) {
-		signals[signo] = 0;
-	}
-
-	fd = open(_PATH_TTY, O_RDONLY);
-	if (fd < 0) {
-		return (-1);
-	}
+	int	c;
+	int	saved_echo_mode;
 
-	if (tcgetattr(fd, &saved_term) != 0) {
-		close(fd);
-		return (-1);
-	}
-	memcpy(&term, &saved_term, sizeof (struct termios));
-
-	/* enter raw mode and turn echo off */
-	term.c_lflag &= ~(ICANON | ECHO);
-	while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT, &term) < 0) &&
-	    (errno != EINTR)) {
-		continue;
-	}
-
-	/* install temporary signal handler */
-	sigemptyset(&sa.sa_mask);
-	sa.sa_flags = 0;
-	sa.sa_handler = sig_handler;
-	sigaction(SIGHUP, &sa, &saved_sa_hup);
-	sigaction(SIGINT, &sa, &saved_sa_int);
-	sigaction(SIGQUIT, &sa, &saved_sa_quit);
-	sigaction(SIGPIPE, &sa, &saved_sa_pipe);
-	sigaction(SIGALRM, &sa, &saved_sa_alrm);
-	sigaction(SIGTERM, &sa, &saved_sa_term);
-	sigaction(SIGTSTP, &sa, &saved_sa_tstp);
-	sigaction(SIGTTIN, &sa, &saved_sa_ttin);
-	sigaction(SIGTTOU, &sa, &saved_sa_ttou);
-
-	/* read key */
-	if (read(fd, &c, 1) == sizeof (c)) {
-		retval = c;
-	}
-
-	/* restore previous mode and echo setting */
-	do {
-		while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT,
-		    &saved_term) < 0) && (errno != EINTR)) {
-			continue;
-		}
-	} while ((tcgetattr(fd, &term) == 0) &&
-	    (term.c_lflag != saved_term.c_lflag));
-
-	/* restore previous signal handlers */
-	sigaction(SIGHUP, &saved_sa_hup, &sa);
-	sigaction(SIGINT, &saved_sa_int, &sa);
-	sigaction(SIGQUIT, &saved_sa_quit, &sa);
-	sigaction(SIGPIPE, &saved_sa_pipe, &sa);
-	sigaction(SIGALRM, &saved_sa_alrm, &sa);
-	sigaction(SIGTERM, &saved_sa_term, &sa);
-	sigaction(SIGTSTP, &saved_sa_tstp, &sa);
-	sigaction(SIGTTIN, &saved_sa_ttin, &sa);
-	sigaction(SIGTTOU, &saved_sa_ttou, &sa);
+	/* prompt with echo off */
+	saved_echo_mode = gl_echo_mode(gl, -1);
+	gl_echo_mode(gl, 0);
+	c = gl_query_char(gl, prompt, '\0');
+	gl_echo_mode(gl, saved_echo_mode);
 
 	/* erase prompt */
 	printf("\r%*s\r", (int)strlen(prompt), "");
-	fflush(stdout);
 
-	while ((close(fd) < 0) && (errno != EINTR)) {
-		continue;
-	}
-
-	/* re-raise signals received */
-	for (signo = 0; signo < _NSIG; signo++) {
-		if (signals[signo]) {
-			raise(signo);
-			if ((signo == SIGTSTP) || (signo == SIGTTIN) ||
-			    (signo == SIGTTOU)) {
-				need_restart = 1;
-			}
-		}
-	}
-	if (need_restart) {
-		goto restart;
-	}
-
-	return (retval);
+	return (c);
 }
 
 struct pager *
@@ -370,6 +254,7 @@
 	struct winsize	ws;
 #endif /* TIOCGWINSZ */
 	unsigned int	row = 0;
+	GetLine		*gl;
 	struct lines_entry *entry;
 
 	is_interactive = (isatty(STDIN_FILENO) && (pager->fp == stdout));
@@ -384,12 +269,18 @@
 	}
 #endif /* TIOCGWINSZ */
 
+	gl = new_GetLine(10, 0);
+	if (gl == NULL) {
+		err(1, "new_GetLine");
+	}
+
 	TAILQ_FOREACH(entry, &pager->lines_head, entry) {
 		if (is_interactive) {
 			mbsnprint(cols, entry->line, pager->fp);
 			row++;
-			if (row == rows - 1) {
-				getch_prompt("--More--");
+			if ((TAILQ_NEXT(entry, entry) != NULL) &&
+			    (row == rows - 1)) {
+				getch_prompt(gl, "--More--");
 				row = 0;
 			}
 		} else {
@@ -397,4 +288,6 @@
 			fflush(pager->fp);
 		}
 	}
+
+	del_GetLine(gl);
 }