aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pw.112
-rw-r--r--pw.c64
2 files changed, 67 insertions, 9 deletions
diff --git a/pw.1 b/pw.1
index 542099e..c651588 100644
--- a/pw.1
+++ b/pw.1
@@ -392,8 +392,7 @@ interactively.
Many of the issues which follow are easy; patches welcome.
-The program doesn't respond to window size changes. The display format, such
-as the handling of control characters, is hard-coded.
+The display format, such as the handling of control characters, is hard-coded.
The program uses hard-coded ANSI sequences, so it doesn't support interesting
old terminals. On the other hand, it carries no dependency on any
@@ -423,6 +422,15 @@ is still receiving ten lines per second from standard input, and that's where
the timeout is applied. Until that is fixed, the way to get more timely
refresh behavior under heavy filtering is to play with the long interval.
+If the terminal window is resized to a narrower size, many terminals wrap
+any lines that would get truncated by the operation and this makes
+a mess of the display. While
+.I pw
+recovers the display area, wrapped lines get pushed above it and
+remain. This issue is likely unfixable, other than by implementing a
+text-editor-like full screen mode which has no scroll back above the
+display, and which recovers the prior content when exiting.
+
.SH AUTHOR
Kaz Kylheku <kaz@kylheku.com>
diff --git a/pw.c b/pw.c
index a7c62d4..8bb2184 100644
--- a/pw.c
+++ b/pw.c
@@ -74,6 +74,8 @@ static unsigned ncmdhist;
static char **pathist;
static unsigned npathist;
+volatile sig_atomic_t winch;
+
static void panic(const char *fmt, ...)
{
va_list vl;
@@ -520,11 +522,26 @@ static void ttyget(int fd, struct termios *tty)
panic("unable to get TTY parameters");
}
+static void sigwinch(int sig)
+{
+ (void) sig;
+ winch = 1;
+}
+
+static char **resizebuf(char **buf, size_t nlfrom, size_t nlto)
+{
+ if ((buf = realloc(buf, sizeof *buf * nlto)) == 0)
+ panic("out of memory");
+ if (nlfrom < nlto)
+ memset(buf + nlfrom, 0, (nlto - nlfrom) * sizeof *buf);
+ return buf;
+}
+
int main(int argc, char **argv)
{
char *line = 0;
FILE *tty = fopen("/dev/tty", "r+");
- int maxlines = 15, nlines = 0;
+ int maxlines = 15, nlines = 0, maxed = 0;
int opt;
int fd = fileno(stdin);
int ttyfd = tty ? fileno(tty) : -1;
@@ -539,6 +556,9 @@ int main(int argc, char **argv)
int auto_quit = 1;
int exit_status = EXIT_FAILURE;
char cmdbuf[cmdsize], *curcmd = 0, *savedcmd = 0;
+#ifdef SIGWINCH
+ static struct sigaction sa;
+#endif
if (fd < 0)
panic("unable to obtain input file descriptor");
@@ -599,8 +619,10 @@ int main(int argc, char **argv)
}
if (ioctl(ttyfd, TIOCGWINSZ, &ws) == 0 && ws.ws_row != 0) {
- if (maxlines >= ws.ws_row)
+ if (maxlines >= ws.ws_row) {
maxlines = ws.ws_row - 1;
+ maxed = 1;
+ }
columns = ws.ws_col;
}
@@ -622,6 +644,11 @@ int main(int argc, char **argv)
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
panic("unable to set stdin nonblocking");
+#ifdef SIGWINCH
+ sa.sa_handler = sigwinch;
+ sigaction(SIGWINCH, &sa, NULL);
+#endif
+
for (unsigned stat = stat_dirty, hpos = 0,
kbd_state = kbd_cmd, kbd_prev = kbd_cmd, lasttime = ~0U,
work = 1000, histpos = 0;
@@ -695,6 +722,30 @@ int main(int argc, char **argv)
nfds = 1;
}
+ if (winch) {
+ winch = 0;
+ if (ioctl(ttyfd, TIOCGWINSZ, &ws) == 0) {
+ if (maxed) {
+ circbuf = resizebuf(circbuf, maxlines, ws.ws_row - 1);
+ snapshot = resizebuf(snapshot, maxlines, ws.ws_row - 1);
+ maxlines = ws.ws_row - 1;
+ } else {
+ if (maxlines >= ws.ws_row) {
+ maxlines = ws.ws_row - 1;
+ maxed = 1;
+ }
+ }
+
+ if (nlines > maxlines)
+ nlines = maxlines;
+ if (snaplines > maxlines)
+ snaplines = maxlines;
+
+ columns = ws.ws_col;
+ }
+ force = 1;
+ }
+
if ((stat & stat_eof))
pollms = -1;
else if (nfds < 2)
@@ -815,12 +866,11 @@ int main(int argc, char **argv)
case '+':
if (ws.ws_row && maxlines >= ws.ws_row - 1)
break;
+ circbuf = resizebuf(circbuf, maxlines, maxlines + 1);
+ snapshot = resizebuf(snapshot, maxlines, maxlines + 1);
maxlines++;
- if ((circbuf = realloc(circbuf, sizeof *circbuf * maxlines)) == 0)
- panic("out of memory");
- if ((snapshot = realloc(snapshot, sizeof *snapshot * maxlines)) == 0)
- panic("out of memory");
- snapshot[maxlines-1] = circbuf[maxlines-1] = 0;
+ if (maxlines == ws.ws_row - 1)
+ maxed = 1;
break;
}
break;