diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-04-29 07:22:41 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-04-29 07:22:41 -0700 |
commit | 5d9e3f697908de66eb45a2af446de8365d2467df (patch) | |
tree | 462f7bada5acec9874a254df5fee731a30ade76d | |
parent | 32d84fb2925e6f511fb8f8762ee02cb567095215 (diff) | |
download | pw-5d9e3f697908de66eb45a2af446de8365d2467df.tar.gz pw-5d9e3f697908de66eb45a2af446de8365d2467df.tar.bz2 pw-5d9e3f697908de66eb45a2af446de8365d2467df.zip |
Handle terminal resizing.
-rw-r--r-- | pw.1 | 12 | ||||
-rw-r--r-- | pw.c | 64 |
2 files changed, 67 insertions, 9 deletions
@@ -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> @@ -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; |