From 1a99270e6d3e6a519b33b4deef749bdd55ccce1c Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 28 Apr 2022 19:03:39 -0700 Subject: Implement Ctrl-Z suspend. --- pw.1 | 14 ++++++++++++-- pw.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/pw.1 b/pw.1 index 5c0240e..7fe38a4 100644 --- a/pw.1 +++ b/pw.1 @@ -217,6 +217,18 @@ recall using the up and down arrow keys or and .BR Ctrl-N . +.IP \fBCtrl-Z\fI +Suspends +.IR pw , +and indeed the entire surrounding process group, to the background +to gain shell access. This requires a job control shell. +When +.IR pw +is foregrounded again, it will refresh the display in a new text area below the +cursor, avoiding overwriting anything in the terminal. Thus suspending and then +immediately foregrounding provides a way to save a snapshot of the window into +the terminal sessions history. + .SH COLON COMMANDS First, some general remarks. Display refresh doesn't pause during the editing @@ -365,8 +377,6 @@ The intervals and number of lines cannot be dynamically adjusted. There is no support for unwrapping long lines, which would be useful for copy and paste. -Ctrl-Z suspend is missing. - During the .B :! command's execution, the TTY settings are not restored. diff --git a/pw.c b/pw.c index f3c4c34..eb4c425 100644 --- a/pw.c +++ b/pw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #define ctrl(ch) ((ch) & 0x1f) @@ -396,6 +397,18 @@ static void execute(char *cmd, unsigned *pstat) fflush(stdout); } +static void ttyset(int fd, struct termios *tty) +{ + if (tcsetattr(fd, TCSANOW, tty) < 0) + panic("unable to set TTY parameters"); +} + +static void ttyget(int fd, struct termios *tty) +{ + if (tcgetattr(fd, tty) < 0) + panic("unable to get TTY parameters"); +} + int main(int argc, char **argv) { char *line = 0; @@ -471,8 +484,7 @@ int main(int argc, char **argv) columns = ws.ws_col; } - if (tcgetattr(ttyfd, &tty_saved) < 0) - panic("unable to get TTY parameters"); + ttyget(ttyfd, &tty_saved); tty_new = tty_saved; @@ -483,8 +495,7 @@ int main(int argc, char **argv) tty_new.c_cc[VMIN] = 1; tty_new.c_cc[VTIME] = 0; - if (tcsetattr(ttyfd, TCSANOW, &tty_new) < 0) - panic("unable to set TTY parameters"); + ttyset(ttyfd, &tty_new); setvbuf(tty, NULL, _IONBF, 0); @@ -614,6 +625,17 @@ int main(int argc, char **argv) if ((pe[0].revents)) { int ch = getc(tty); + if (ch == ctrl('z')) { + ttyset(ttyfd, &tty_saved); + kill(0, SIGTSTP); + ttyset(ttyfd, &tty_new); + for (int i = 0; i < nlines; i++) + puts(""); + redraw(circbuf, nlines, hpos, columns, stat, curcmd); + stat &= ~stat_dirty; + continue; + } + fakecmd: switch (kbd_state) { case kbd_result: @@ -847,7 +869,6 @@ int main(int argc, char **argv) } } - if (tcsetattr(ttyfd, TCSANOW, &tty_saved) < 0) - panic("unable to restore TTY parameters"); + ttyset(ttyfd, &tty_saved); return exit_status; } -- cgit v1.2.3