From b7eb3c9e9086d930c8ad675b89af5a3d26efd96d Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Mon, 28 Aug 2023 22:03:14 +0100 Subject: [PATCH] Record whether the width or height were set manually, and refrain from changing a manually set value when the terminal size changes. --- doc/NEWS.md | 7 ++++--- doc/TODO.md | 1 - doc/pv.1 | 7 +++++-- src/include/options.h | 2 ++ src/include/pv-internal.h | 2 ++ src/include/pv.h | 4 ++-- src/main/main.c | 4 ++-- src/main/options.c | 5 +++++ src/main/remote.c | 12 ++++++++---- src/pv/loop.c | 24 ++++++++++++++++++++++-- src/pv/state.c | 6 ++++-- 11 files changed, 56 insertions(+), 18 deletions(-) diff --git a/doc/NEWS.md b/doc/NEWS.md index c6648d7..248589d 100644 --- a/doc/NEWS.md +++ b/doc/NEWS.md @@ -1,12 +1,13 @@ 0.0.20230828-UNRELEASED - * feature: new "`--enable-static`" option to "`configure`" for static builds ([#75](https://codeberg.org/a-j-wood/pv/pull/75)) - * feature: now uses `posix_fadvise()` like `cat`(1) does, to improve efficiency ([#39](https://codeberg.org/a-j-wood/pv/issues/39)) * feature: new "`--discard`" option to discard input as if writing to */dev/null* ([#42](https://codeberg.org/a-j-wood/pv/issues/42)) + * feature: use `posix_fadvise()` like `cat`(1) does, to improve efficiency ([#39](https://codeberg.org/a-j-wood/pv/issues/39)) + * feature: new "`--enable-static`" option to "`configure`" for static builds ([#75](https://codeberg.org/a-j-wood/pv/pull/75)) * security: with "`--pidfile`", write to a temporary file and rename it into place, to improve security * security: keep self-contained copies of name and format string in PV internal state for memory safety - * fix: auto-calculate total line count with "`--line-mode`" when all inputs are regular files * fix: only report errors about missing files when starting to transfer from them, not while calculating size, and behave more like `cat`(1) by skipping them and moving on + * fix: auto-calculate total line count with "`--line-mode`" when all inputs are regular files + * fix: if "`--width`" or "`--height`" were provided, do not change them when the window size changes ([#36](https://codeberg.org/a-j-wood/pv/issues/36)) * cleanup: switched the build system to GNU Automake * cleanup: added a test for terminal width detection to "`make check`" * cleanup: added a test to "`make check`" to ensure that "`make install`" installs everything expected diff --git a/doc/TODO.md b/doc/TODO.md index 8a90e3c..79e8ee6 100644 --- a/doc/TODO.md +++ b/doc/TODO.md @@ -24,7 +24,6 @@ Feature requests * ([#22](https://codeberg.org/a-j-wood/pv/issues/22)) Options to skip input and seek on output (Jason A. Pfeil, Feb 2022) * ([#25](https://codeberg.org/a-j-wood/pv/issues/25)) Normalise progress to 100% on overrun (Andrej Gantvorg) * ([#35](https://codeberg.org/a-j-wood/pv/issues/35)) Allow decimal values for "`-s`", "`-L`", "`-B`" (Thomas Watson - Aug 2020) - * ([#36](https://codeberg.org/a-j-wood/pv/issues/36)) Ignore *SIGWINCH* (window size change) if "`-w`" / "`-H`" provided * ([#37](https://codeberg.org/a-j-wood/pv/issues/37)) Allow "`-E`" to take a block size argument so errors cause a skip to the next block (Anthony DeRobertis - Oct 2016) * ([#38](https://codeberg.org/a-j-wood/pv/issues/38)) Reset ETA on *SIGUSR1* (Jacek Wielemborek - Jan 2019) * ([#40](https://codeberg.org/a-j-wood/pv/issues/40)) Permit "`-c`" with "`-d PID:FD`", reject "`-N`" with "`-d PID`" (Norman Rasmussen - Nov 2020) diff --git a/doc/pv.1 b/doc/pv.1 index 6c91ae5..caeb4b3 100644 --- a/doc/pv.1 +++ b/doc/pv.1 @@ -302,13 +302,16 @@ seconds window for average rate and ETA calculations (default 30s). Assume the terminal is .B WIDTH characters wide, instead of trying to work it out (or assuming 80 if it -cannot be guessed). +cannot be guessed). If this option is used, the output width will not be +adjusted if the width of the terminal changes while the transfer is running. .TP .B \-H HEIGHT, \-\-height HEIGHT Assume the terminal is .B HEIGHT rows high, instead of trying to work it out (or assuming 25 if it -cannot be guessed). +cannot be guessed). If this option is used, the output height will not be +adjusted if the height of the terminal changes while the transfer is +running. .TP .B \-N NAME, \-\-name NAME Prefix the output information with diff --git a/src/include/options.h b/src/include/options.h index d62646d..fca9903 100644 --- a/src/include/options.h +++ b/src/include/options.h @@ -53,6 +53,8 @@ struct opts_s { /* structure describing run-time options */ unsigned int average_rate_window; /* time window in seconds for average rate calculations */ unsigned int width; /* screen width */ unsigned int height; /* screen height */ + bool width_set_manually; /* width was set manually, not detected */ + bool height_set_manually; /* height was set manually, not detected */ /*@keep@*/ /*@null@*/ char *name; /* display name, if any */ /*@keep@*/ /*@null@*/ char *format; /* output format, if any */ /*@keep@*/ /*@null@*/ char *pidfile; /* PID file, if any */ diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 4405ace..2343017 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -107,6 +107,8 @@ struct pvstate_s { int watch_fd; /* fd to watch */ unsigned int width; /* screen width */ unsigned int height; /* screen height */ + bool width_set_manually; /* width was set manually, not detected */ + bool height_set_manually; /* height was set manually, not detected */ /*@null@*/ char *name; /* display name */ char default_format[PV_SIZEOF_DEFAULT_FORMAT]; /* default format string */ char *format_string; /* output format string */ diff --git a/src/include/pv.h b/src/include/pv.h index aefc281..ed9cb29 100644 --- a/src/include/pv.h +++ b/src/include/pv.h @@ -119,8 +119,8 @@ extern void pv_state_no_splice_set(pvstate_t, bool); extern void pv_state_discard_input_set(pvstate_t, bool); extern void pv_state_size_set(pvstate_t, unsigned long long); extern void pv_state_interval_set(pvstate_t, double); -extern void pv_state_width_set(pvstate_t, unsigned int); -extern void pv_state_height_set(pvstate_t, unsigned int); +extern void pv_state_width_set(pvstate_t, unsigned int, bool); +extern void pv_state_height_set(pvstate_t, unsigned int, bool); extern void pv_state_name_set(pvstate_t, /*@null@*/ const char *); extern void pv_state_format_string_set(pvstate_t, /*@null@*/ const char *); extern void pv_state_watch_pid_set(pvstate_t, unsigned int); diff --git a/src/main/main.c b/src/main/main.c index 6671d44..d556f76 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -258,8 +258,8 @@ int main(int argc, char **argv) * Copy parameters from options into main state. */ pv_state_interval_set(state, opts->interval); - pv_state_width_set(state, opts->width); - pv_state_height_set(state, opts->height); + pv_state_width_set(state, opts->width, opts->width_set_manually); + pv_state_height_set(state, opts->height, opts->height_set_manually); pv_state_no_display_set(state, opts->no_display); pv_state_force_set(state, opts->force); pv_state_cursor_set(state, opts->cursor); diff --git a/src/main/options.c b/src/main/options.c index 13a3980..94956e9 100644 --- a/src/main/options.c +++ b/src/main/options.c @@ -238,6 +238,9 @@ opts_t opts_parse(unsigned int argc, char **argv) opts->watch_fd = -1; opts->average_rate_window = 30; + opts->width_set_manually = false; + opts->height_set_manually = false; + do { #ifdef HAVE_GETOPT_LONG c = getopt_long((int) argc, argv, short_options, long_options, &option_index); /* flawfinder: ignore */ @@ -431,9 +434,11 @@ opts_t opts_parse(unsigned int argc, char **argv) break; case 'w': opts->width = pv_getnum_ui(optarg); + opts->width_set_manually = opts->width == 0 ? false : true; break; case 'H': opts->height = pv_getnum_ui(optarg); + opts->height_set_manually = opts->height == 0 ? false : true; break; case 'N': opts->name = xstrdup(optarg); diff --git a/src/main/remote.c b/src/main/remote.c index a669812..4f49089 100644 --- a/src/main/remote.c +++ b/src/main/remote.c @@ -42,6 +42,8 @@ struct remote_msg { double interval; /* interval between updates */ unsigned int width; /* screen width */ unsigned int height; /* screen height */ + bool width_set_manually; /* width was set manually, not detected */ + bool height_set_manually; /* height was set manually, not detected */ char name[256]; /* flawfinder: ignore */ char format[256]; /* flawfinder: ignore */ }; @@ -151,6 +153,8 @@ int pv_remote_set(opts_t opts) msgbuf.interval = opts->interval; msgbuf.width = opts->width; msgbuf.height = opts->height; + msgbuf.width_set_manually = opts->width_set_manually; + msgbuf.height_set_manually = opts->height_set_manually; if (opts->name != NULL) { strncpy(msgbuf.name, opts->name, sizeof(msgbuf.name) - 1); /* flawfinder: ignore */ @@ -295,10 +299,10 @@ void pv_remote_check(pvstate_t state) pv_state_size_set(state, msgbuf.size); if (msgbuf.interval > 0) pv_state_interval_set(state, msgbuf.interval); - if (msgbuf.width > 0) - pv_state_width_set(state, msgbuf.width); - if (msgbuf.height > 0) - pv_state_height_set(state, msgbuf.height); + if (msgbuf.width > 0 && msgbuf.width_set_manually) + pv_state_width_set(state, msgbuf.width, msgbuf.width_set_manually); + if (msgbuf.height > 0 && msgbuf.height_set_manually) + pv_state_height_set(state, msgbuf.height, msgbuf.height_set_manually); if (msgbuf.format[0] != '\0') pv_state_format_string_set(state, msgbuf.format); } diff --git a/src/pv/loop.c b/src/pv/loop.c index 4e16e41..a0a3682 100644 --- a/src/pv/loop.c +++ b/src/pv/loop.c @@ -321,8 +321,18 @@ int pv_main_loop(pvstate_t state) since_last = -1; if (state->pv_sig_newsize) { + unsigned int new_width, new_height; + state->pv_sig_newsize = 0; - pv_screensize(&(state->width), &(state->height)); + + new_width = state->width; + new_height = state->height; + pv_screensize(&new_width, &new_height); + + if (!state->width_set_manually) + state->width = new_width; + if (!state->height_set_manually) + state->height = new_height; } pv_display(state, elapsed, since_last, total_written); @@ -475,8 +485,18 @@ int pv_watchfd_loop(pvstate_t state) since_last = -1; if (state->pv_sig_newsize) { + unsigned int new_width, new_height; + state->pv_sig_newsize = 0; - pv_screensize(&(state->width), &(state->height)); + + new_width = state->width; + new_height = state->height; + pv_screensize(&new_width, &new_height); + + if (!state->width_set_manually) + state->width = new_width; + if (!state->height_set_manually) + state->height = new_height; } pv_display(state, elapsed, since_last, total_written); diff --git a/src/pv/state.c b/src/pv/state.c index 1be482b..bcbf00a 100644 --- a/src/pv/state.c +++ b/src/pv/state.c @@ -253,14 +253,16 @@ void pv_state_interval_set(pvstate_t state, double val) state->interval = val; }; -void pv_state_width_set(pvstate_t state, unsigned int val) +void pv_state_width_set(pvstate_t state, unsigned int val, bool was_set_manually) { state->width = val; + state->width_set_manually = was_set_manually; }; -void pv_state_height_set(pvstate_t state, unsigned int val) +void pv_state_height_set(pvstate_t state, unsigned int val, bool was_set_manually) { state->height = val; + state->height_set_manually = was_set_manually; }; void pv_state_name_set(pvstate_t state, /*@null@ */ const char *val)