From 7d7efac7c6bd9635ca7de14450ba9dfc03d0fd5f Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Sun, 27 Jul 2025 15:37:16 +0100 Subject: [PATCH] Move the terminal_supports_utf8, terminal_supports_colour, and checked_colour_support flags out of "control" and into "status", as they are not operator-supplied options, but are program-generated status flags; this will allow "control" to remain read-only for larger parts of the program (#165). --- src/include/pv-internal.h | 11 +++++----- src/pv/display.c | 46 ++++++++++++++++++++++----------------- src/pv/format/barstyle.c | 6 ++--- src/pv/format/sgr.c | 2 +- src/pv/state.c | 2 +- 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 3f5dd68..61fcd4b 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -145,6 +145,9 @@ struct pvstate_s { char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */ int current_input_file; /* index of current file being read */ int exit_status; /* exit status to give (0=OK) */ + bool terminal_supports_utf8; /* whether the terminal supports UTF-8 */ + bool terminal_supports_colour; /* whether the terminal supports colour */ + bool checked_colour_support; /* whether we have checked colour support yet */ } status; /*************** @@ -197,9 +200,6 @@ struct pvstate_s { bool no_splice; /* never use splice() */ bool discard_input; /* write nothing to stdout */ bool show_stats; /* show statistics on exit */ - bool terminal_supports_utf8; /* whether the terminal supports UTF-8 */ - bool terminal_supports_colour; /* whether the terminal supports colour */ - bool checked_colour_support; /* whether we have checked colour support yet */ bool width_set_manually; /* width was set manually, not detected */ bool height_set_manually; /* height was set manually, not detected */ } control; @@ -461,7 +461,8 @@ typedef const struct pvtransferstate_s * readonly_pvtransferstate_t; struct pvformatter_args_s { /*@dependent@*/ pvdisplay_t display; /* the display being updated */ /*@dependent@*/ pvdisplay_segment_t segment; /* the segment of the display */ - /*@dependent@*/ readonly_pvcontrol_t control; /* program control settings */ + /*@dependent@*/ readonly_pvprogramstatus_t status; /* program status */ + /*@dependent@*/ readonly_pvcontrol_t control; /* control settings */ /*@dependent@*/ readonly_pvtransferstate_t transfer; /* transfer state */ /*@dependent@*/ readonly_pvtransfercalc_t calc; /* calculated transfer state */ /*@dependent@*/ char *buffer; /* buffer to write formatted segments into */ @@ -559,7 +560,7 @@ pvdisplay_bytecount_t pv_formatter_previous_line(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_name(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_sgr(pvformatter_args_t); -bool pv_format(pvprogramstatus_t, pvcontrol_t, readonly_pvtransferstate_t, readonly_pvtransfercalc_t, /*@null@*/ const char *, pvdisplay_t, bool, bool); +bool pv_format(pvprogramstatus_t, readonly_pvcontrol_t, readonly_pvtransferstate_t, readonly_pvtransfercalc_t, /*@null@*/ const char *, pvdisplay_t, bool, bool); void pv_display(pvstate_t, bool); ssize_t pv_transfer(pvstate_t, int, bool *, bool *, off_t, long *); int pv_next_file(pvstate_t, unsigned int, int); diff --git a/src/pv/display.c b/src/pv/display.c index f48f74e..7a73133 100644 --- a/src/pv/display.c +++ b/src/pv/display.c @@ -590,10 +590,10 @@ char *pv_format_sequences(void) /* * Initialise the output format structure, based on the current options. * - * May update control->checked_colour_support and - * control->terminal_supports_colour. + * May update status->checked_colour_support and + * status->terminal_supports_colour. */ -static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t transfer, readonly_pvtransfercalc_t calc, +static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_pvtransferstate_t transfer, readonly_pvtransfercalc_t calc, /*@null@ */ const char *format_supplied, pvdisplay_t display) { struct pvdisplay_component_s *format_component_array; @@ -601,6 +601,8 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran size_t strpos; size_t segment; + if (NULL == status) + return; if (NULL == control) return; if (NULL == transfer) @@ -825,6 +827,7 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran formatter_info.display = display; formatter_info.segment = &(display->format[segment]); + formatter_info.status = status; formatter_info.control = control; formatter_info.transfer = transfer; formatter_info.calc = calc; @@ -847,8 +850,8 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran display->format_segment_count++; } - if (display->format_uses_colour && !control->checked_colour_support) { - control->checked_colour_support = true; + if (display->format_uses_colour && !status->checked_colour_support) { + status->checked_colour_support = true; #ifdef ENABLE_NCURSES /* * If we have terminal info support, check whether the @@ -856,7 +859,7 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran * supported if we're forcing output. */ if (true == control->force) { - control->terminal_supports_colour = true; + status->terminal_supports_colour = true; debug("%s", "force mode - assuming terminal supports colour"); } else { char *term_env = NULL; @@ -866,22 +869,22 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran * flawfinder - here we pass responsibility to the * ncurses library to behave OK with $TERM. */ - control->terminal_supports_colour = false; + status->terminal_supports_colour = false; if (NULL != term_env) { int setup_err = 0; if ((0 == setupterm(term_env, STDERR_FILENO, &setup_err)) && (tigetnum("colors") > 1) ) { - control->terminal_supports_colour = true; + status->terminal_supports_colour = true; debug("%s: %s", term_env, "terminal supports colour"); } else { - control->terminal_supports_colour = false; + status->terminal_supports_colour = false; debug("%s: %s", term_env, "terminal does not support colour"); } } else { /* If TERM is unset, disable colour. */ - control->terminal_supports_colour = false; + status->terminal_supports_colour = false; debug("%s", "no TERM variable - disabling colour support"); } } @@ -893,7 +896,7 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran * was supplied, in which case colour support is assumed. */ if (true == control->force) { - control->terminal_supports_colour = true; + status->terminal_supports_colour = true; debug("%s", "force mode - assuming terminal supports colour"); } else { FILE *command_fptr; @@ -909,21 +912,21 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran */ if (NULL == command_fptr) { - control->terminal_supports_colour = false; + status->terminal_supports_colour = false; debug("%s (%s)", "popen failed - disabling colour support", strerror(errno)); } else { int colour_count; if (1 == fscanf(command_fptr, "%d", &colour_count)) { if (colour_count > 1) { - control->terminal_supports_colour = true; + status->terminal_supports_colour = true; debug("%s (%d)", "terminal supports colour", colour_count); } else { - control->terminal_supports_colour = false; + status->terminal_supports_colour = false; debug("%s (%d)", "fewer than 2 colours available - disabling colour support"); } } else { - control->terminal_supports_colour = false; + status->terminal_supports_colour = false; debug("%s", "tput did not produce a number - disabling colour support"); } /*@-unrecog@ *//* splint doesn't know pclose(). */ @@ -936,7 +939,7 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran * Without terminal info support, just assume colour is * available. */ - control->terminal_supports_colour = true; + status->terminal_supports_colour = true; debug("%s", "terminal info support not compiled in - assuming colour support"); #endif /* (! ENABLE_NCURSES) && (! USE_POPEN_TPUTS) */ #endif /* ! ENABLE_NCURSES */ @@ -963,9 +966,9 @@ static void pv__format_init(pvcontrol_t control, readonly_pvtransferstate_t tran * * Updates status->exit_status if buffer allocation fails. * - * See pv__format_init for the adjustments that may be made to "control". + * See pv__format_init for the adjustments that may be made to "status". */ -bool pv_format(pvprogramstatus_t status, pvcontrol_t control, readonly_pvtransferstate_t transfer, +bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_pvtransferstate_t transfer, readonly_pvtransfercalc_t calc, /*@null@ */ const char *format_supplied, pvdisplay_t display, bool reinitialise, bool final) { @@ -982,6 +985,8 @@ bool pv_format(pvprogramstatus_t status, pvcontrol_t control, readonly_pvtransfe display_segments[0] = '\0'; /* Quick safety check for null pointers. */ + if (NULL == status) + return false; if (NULL == control) return false; if (NULL == transfer) @@ -995,6 +1000,7 @@ bool pv_format(pvprogramstatus_t status, pvcontrol_t control, readonly_pvtransfe formatter_info.buffer = display_segments; formatter_info.buffer_size = sizeof(display_segments); formatter_info.offset = 0; + formatter_info.status = status; formatter_info.control = control; formatter_info.transfer = transfer; formatter_info.calc = calc; @@ -1006,7 +1012,7 @@ bool pv_format(pvprogramstatus_t status, pvcontrol_t control, readonly_pvtransfe /* Reinitialise if we were asked to. */ if (reinitialise) - pv__format_init(control, transfer, calc, format_supplied, display); + pv__format_init(status, control, transfer, calc, format_supplied, display); /* The format string is needed for the static segments. */ display_format = NULL == format_supplied ? control->default_format : format_supplied; @@ -1121,7 +1127,7 @@ bool pv_format(pvprogramstatus_t status, pvcontrol_t control, readonly_pvtransfe if (dynamic_segment_count > 1) dynamic_segment_width /= dynamic_segment_count; - debug("control.width=%d static_portion_width=%d dynamic_segment_width=%d dynamic_segment_count=%d", + debug("control->width=%d static_portion_width=%d dynamic_segment_width=%d dynamic_segment_count=%d", control->width, static_portion_width, dynamic_segment_width, dynamic_segment_count); for (segment_idx = 0; segment_idx < display->format_segment_count; segment_idx++) { diff --git a/src/pv/format/barstyle.c b/src/pv/format/barstyle.c index fc24844..223adf8 100644 --- a/src/pv/format/barstyle.c +++ b/src/pv/format/barstyle.c @@ -44,7 +44,7 @@ static bool pv_barstyle(pvformatter_args_t args, pvbarstyle_t style, const char memset(style, 0, sizeof(*style)); - if (args->control->terminal_supports_utf8 && 0 == strcmp(name, "block")) { + if (args->status->terminal_supports_utf8 && 0 == strcmp(name, "block")) { style->style_id = 2; @@ -58,7 +58,7 @@ static bool pv_barstyle(pvformatter_args_t args, pvbarstyle_t style, const char return true; - } else if (args->control->terminal_supports_utf8 && 0 == strcmp(name, "granular")) { + } else if (args->status->terminal_supports_utf8 && 0 == strcmp(name, "granular")) { style->style_id = 3; @@ -79,7 +79,7 @@ static bool pv_barstyle(pvformatter_args_t args, pvbarstyle_t style, const char return true; - } else if (args->control->terminal_supports_utf8 && 0 == strcmp(name, "shaded")) { + } else if (args->status->terminal_supports_utf8 && 0 == strcmp(name, "shaded")) { style->style_id = 4; diff --git a/src/pv/format/sgr.c b/src/pv/format/sgr.c index 5d627c7..e75b801 100644 --- a/src/pv/format/sgr.c +++ b/src/pv/format/sgr.c @@ -109,7 +109,7 @@ pvdisplay_bytecount_t pv_formatter_sgr(pvformatter_args_t args) args->display->format_uses_colour = true; - if (!args->control->terminal_supports_colour) + if (!args->status->terminal_supports_colour) return 0; if (NULL == args->segment->string_parameter) return 0; diff --git a/src/pv/state.c b/src/pv/state.c index c6042d2..2bd726b 100644 --- a/src/pv/state.c +++ b/src/pv/state.c @@ -570,7 +570,7 @@ void pv_state_average_rate_window_set(pvstate_t state, unsigned int val) void pv_state_set_terminal_supports_utf8(pvstate_t state, bool val) { - state->control.terminal_supports_utf8 = val; + state->status.terminal_supports_utf8 = val; } /*