Re: git: 0595e10ec773 - releng/15.0 - contrib/bsddialog: Import version 1.0.5

From: Colin Percival <cperciva_at_tarsnap.com>
Date: Tue, 04 Nov 2025 19:13:42 UTC
Hi Alfonso,

Not a big issue in this case, but the correct process here was for you to
merge to stable/15 (as you did) and then send an email to re@ asking for
us to cherry-pick the commit to releng/15.0 (rather than merging it there
yourself).

Colin Percival

On 11/4/25 10:31, Alfonso S. Siciliano wrote:
> The branch releng/15.0 has been updated by asiciliano:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=0595e10ec77383a3038c45fbd9fcdb6922c971fe
> 
> commit 0595e10ec77383a3038c45fbd9fcdb6922c971fe
> Author:     Alfonso S. Siciliano <asiciliano@FreeBSD.org>
> AuthorDate: 2025-10-09 15:39:10 +0000
> Commit:     Alfonso S. Siciliano <asiciliano@FreeBSD.org>
> CommitDate: 2025-11-04 18:30:32 +0000
> 
>      contrib/bsddialog: Import version 1.0.5
>      
>      Version for change and feature requests.
>      
>      * Improve documentation for --alternate-screen and --normal-screen.
>        Request: https://bugs.freebsd.org/285459. (This PR is not about
>        bsddialog itself but is used as an example for an official FreeBSD
>        documentation request.)
>      
>      * Reduce the number of screen refreshes to improve performance over a
>        115200 UART connection.
>        Request: https://gitlab.com/alfix/bsddialog/-/issues/8.
>      
>      * Change textbox buttons to return distinct values (previously always
>        returned OK).
>        Request: https://reviews.freebsd.org/D48668; already committed in
>        contrib/ 96a241a35905078bdc5d20bf25943cdb67758dea
>      
>      * Change forms navigation key behavior for ENTER and TAB.
>        Request: https://bugs.freebsd.org/287592.
>      
>      Refer to /usr/src/contrib/bsddialog/CHANGELOG to know more.
>      
>      PR:             287592
>      Reported by:    adrian
>      Approved by:    re (cperciva)
>      Sponsored by:   The FreeBSD Foundation
>      
>      Merge commit '653f765f05b8c7e3908ae92e9bf61522a50cefc9' into YYY
>      
>      (cherry picked from commit 3e42d7194bdcd4fbfd781518258f919d6ac803d3)
>      (cherry picked from commit aa2fe36f5e4b3b907af2ea94945ae9cab7263d0c)
> ---
>   contrib/bsddialog/.gitignore                 |  1 +
>   contrib/bsddialog/CHANGELOG                  | 50 ++++++++++++++++++++-
>   contrib/bsddialog/LICENSE                    |  2 +-
>   contrib/bsddialog/Makefile                   | 13 +++++-
>   contrib/bsddialog/README.md                  |  5 +--
>   contrib/bsddialog/examples_library/compile   |  8 ++--
>   contrib/bsddialog/examples_library/textbox.c | 38 ++++++++++++++++
>   contrib/bsddialog/lib/GNUmakefile            | 19 +++++++-
>   contrib/bsddialog/lib/Makefile               | 21 ++++++++-
>   contrib/bsddialog/lib/barbox.c               | 37 ++++++++--------
>   contrib/bsddialog/lib/bsddialog.3            | 16 +++++--
>   contrib/bsddialog/lib/bsddialog.h            |  5 ++-
>   contrib/bsddialog/lib/bsddialog_theme.h      |  2 +-
>   contrib/bsddialog/lib/datebox.c              | 28 ++++++------
>   contrib/bsddialog/lib/formbox.c              | 48 ++++++++++++++------
>   contrib/bsddialog/lib/lib_util.c             |  3 +-
>   contrib/bsddialog/lib/lib_util.h             |  4 +-
>   contrib/bsddialog/lib/libbsddialog.c         | 14 +++++-
>   contrib/bsddialog/lib/menubox.c              | 18 ++++----
>   contrib/bsddialog/lib/messagebox.c           | 16 +++----
>   contrib/bsddialog/lib/textbox.c              | 16 +++----
>   contrib/bsddialog/lib/theme.c                |  6 +--
>   contrib/bsddialog/lib/timebox.c              | 16 +++----
>   contrib/bsddialog/utility/GNUmakefile        | 11 ++++-
>   contrib/bsddialog/utility/Makefile           | 11 ++++-
>   contrib/bsddialog/utility/bsddialog.1        | 21 ++++++---
>   contrib/bsddialog/utility/bsddialog.c        |  2 +-
>   contrib/bsddialog/utility/util.h             |  2 +-
>   contrib/bsddialog/utility/util_builders.c    | 66 ++++++++++++++--------------
>   contrib/bsddialog/utility/util_cli.c         |  2 +-
>   contrib/bsddialog/utility/util_theme.c       |  4 +-
>   31 files changed, 353 insertions(+), 152 deletions(-)
> 
> diff --git a/contrib/bsddialog/.gitignore b/contrib/bsddialog/.gitignore
> index c8fc68ed8a0e..c9613d477f7f 100644
> --- a/contrib/bsddialog/.gitignore
> +++ b/contrib/bsddialog/.gitignore
> @@ -21,6 +21,7 @@ examples_library/msgbox
>   examples_library/pause
>   examples_library/radiolist
>   examples_library/rangebox
> +examples_library/textbox
>   examples_library/theme
>   examples_library/timebox
>   examples_library/yesno
> diff --git a/contrib/bsddialog/CHANGELOG b/contrib/bsddialog/CHANGELOG
> index a4cf4d01c077..7800098644d7 100644
> --- a/contrib/bsddialog/CHANGELOG
> +++ b/contrib/bsddialog/CHANGELOG
> @@ -1,11 +1,57 @@
> -2024-07-01 1.0.4
> +2025-06-22 Version 1.0.5
> +
> +	Manual:
> +	* fix: "User-friendly documentation for alternate screen"
> +	  https://bugs.freebsd.org/285459.
> +	  Improve bsddialog.1: --alternate-screen and --normal-screen.
> +
> +	NetBSD (tested on amd64) refactoring, no function changes:
> +	* https://gitlab.com/alfix/bsddialog/-/merge_requests/4
> +	  lib: include <stdarg.h> in lib_util.c.
> +	* https://gitlab.com/alfix/bsddialog/-/merge_requests/5
> +	  a call to curses' refresh() is performed, while a local
> +	  variable is also called refresh.
> +	* Makefiles: add install and uninstall targets (both GND and BSD)
> +	  https://gitlab.com/alfix/bsddialog/-/merge_requests/3
> +
> +	MacOS (tested on amd64) refactoring, no function changes:
> +	* https://gitlab.com/alfix/bsddialog/-/merge_requests/6
> +	  utility: replace u_int with unsigned int.
> +
> +	Library:
> +	* fix: useless refreshes, https://gitlab.com/alfix/bsddialog/-/issues/8:
> +	  "It takes lot of time when running over a 115200 UART".
> +	  Not fixed for bsddialog_gauge() because it has to be rewritten.
> +	* change: bsddialog_backtitle() does not update the screen so the
> +	  backtitle is not printed. To use if a dialog is built later.
> +	  Rationale: see "115200 UART" problem above.
> +	* add: bsddialog_backtitle_rf() to print a top title refreshing the
> +	  screen like bsddialog_backtitle() was previously.
> +	* change: forms, ENTER is also a navigation keys in forms fields.
> +	  Request: https://bugs.freebsd.org/287592
> +	  If conf.button.always_active is true the form is closes immediatly.
> +
> +	Library and implicitly utility:
> +	* fix: textbox buttons returned values (was always OK).
> +	  Thanks to https://reviews.freebsd.org/D48668.
> +	* change: TAB is a navigation keys in forms. Previously it directly
> +	  switched form-fields <-> buttons.
> +	  Request: https://bugs.freebsd.org/287592
> +
> +	Utility:
> +	* change: forms, ENTER is a also navigation keys in forms fields.
> +	  Previously it directly closed the form except with --switch-buttons
> +	  Request: https://bugs.freebsd.org/287592
> +
> +
> +2024-07-01 Version 1.0.4
>   
>   	Utility internal refactoring (no functional change):
>   	* change: rename an internal constant to avoid a future conflict
>   	    because FreeBSD is changing headers files for _FORTIFY_SOURCE.
>   	    Reported and fixed by Kyle Evans.
>   
> -2024-05-27 1.0.3
> +2024-05-27 Version 1.0.3
>   
>   	Utility:
>   	change: --form and --mixedform do not print field value to output fd if
> diff --git a/contrib/bsddialog/LICENSE b/contrib/bsddialog/LICENSE
> index 7b36a8dce42e..9ea4a4a62f4b 100644
> --- a/contrib/bsddialog/LICENSE
> +++ b/contrib/bsddialog/LICENSE
> @@ -1,6 +1,6 @@
>   BSD 2-Clause License
>   
> -Copyright (c) 2021-2024, Alfonso Sabato Siciliano
> +Copyright (c) 2021-2025, Alfonso Sabato Siciliano
>   
>   Redistribution and use in source and binary forms, with or without
>   modification, are permitted provided that the following conditions are met:
> diff --git a/contrib/bsddialog/Makefile b/contrib/bsddialog/Makefile
> index a6af8813a48e..335b693470e6 100644
> --- a/contrib/bsddialog/Makefile
> +++ b/contrib/bsddialog/Makefile
> @@ -4,7 +4,7 @@
>   # Written in 2023 by Alfonso Sabato Siciliano
>   
>   OUTPUT = bsddialog
> -export VERSION=1.0.4
> +export VERSION=1.0.5
>   .CURDIR ?= ${CURDIR}
>   LIBPATH = ${.CURDIR}/lib
>   LIBBSDDIALOG = ${LIBPATH}/libbsddialog.so
> @@ -22,7 +22,15 @@ DEBUG ?=
>   export ENABLEDEBUG=${DEBUG}
>   ###################
>   
> -all : ${OUTPUT}
> +all: ${OUTPUT}
> +
> +install: all
> +	${MAKE} -C ${LIBPATH} install
> +	${MAKE} -C ${UTILITYPATH} install
> +
> +uninstall:
> +	${MAKE} -C ${UTILITYPATH} uninstall
> +	${MAKE} -C ${LIBPATH} uninstall
>   
>   ${OUTPUT}: ${LIBBSDDIALOG}
>   	${MAKE} -C ${UTILITYPATH} LIBPATH=${LIBPATH}
> @@ -36,3 +44,4 @@ clean:
>   	${MAKE} -C ${UTILITYPATH} clean
>   	${RM} ${OUTPUT} *.core
>   
> +.PHONY: all install uninstall clean
> diff --git a/contrib/bsddialog/README.md b/contrib/bsddialog/README.md
> index 7b9b6cf8e84d..5a25109775fe 100644
> --- a/contrib/bsddialog/README.md
> +++ b/contrib/bsddialog/README.md
> @@ -1,4 +1,4 @@
> -# BSDDialog 1.0.4
> +# BSDDialog 1.0.5
>   
>   This project provides **bsddialog** and **libbsddialog**, an utility
>   and a library to build scripts and tools with TUI dialogs and widgets.
> @@ -129,7 +129,6 @@ in the _Public Domain_ to build new projects:
>    - implement global buttons handler.
>    - doc: external tutorial, theming guide.
>    - implement menutype.min\_on.
> - - improve refresh at startup, avoid dialog refresh before drawing text.
>    - add debug API: bsddialog\_debug(y,x,refresh,"fmt",...).
>    - add mouse support.
>    - use alarm(2) for bsddialog\_pause.
> @@ -139,4 +138,4 @@ in the _Public Domain_ to build new projects:
>    - fix --mixedform "" 0 0 0 Label 1 0 Init 1 12 0 0 2 (with 0 editable field).
>    - add *text* customization to --hmsg *help-message*
>    - check --passwordform *fieldlen* like --form and --mixedform.
> -
> + - add manuals to Makefiles installe and uninstall targets.
> diff --git a/contrib/bsddialog/examples_library/compile b/contrib/bsddialog/examples_library/compile
> index 9025f35426d9..1a68313090f6 100755
> --- a/contrib/bsddialog/examples_library/compile
> +++ b/contrib/bsddialog/examples_library/compile
> @@ -8,14 +8,16 @@
>   # worldwide. This software is distributed without any warranty, see:
>   #     <http://creativecommons.org/publicdomain/zero/1.0/>.
>   
> +set -x
> +
>   libpath=../lib
>   examples="menu checklist radiolist mixedlist theme infobox yesno msgbox \
> -	datebox form timebox rangebox pause calendar gauge mixedgauge"
> +datebox form timebox rangebox pause calendar gauge mixedgauge textbox"
>   
>   rm -f $examples
>   
>   for e in $examples
>   do
> -	cc -g -Wall -Wextra -I$libpath ${e}.c -o $e -L$libpath -lbsddialog \
> -	-Wl,-rpath=$libpath
> +	cc -g -Wall -Wextra -I$libpath ${e}.c -o $e \
> +	-Wl,-rpath=$libpath -L$libpath -lbsddialog
>   done
> diff --git a/contrib/bsddialog/examples_library/textbox.c b/contrib/bsddialog/examples_library/textbox.c
> new file mode 100644
> index 000000000000..2e76cbb97891
> --- /dev/null
> +++ b/contrib/bsddialog/examples_library/textbox.c
> @@ -0,0 +1,38 @@
> +/*-
> + * SPDX-License-Identifier: CC0-1.0
> + *
> + * Written in 2025 by Alfonso Sabato Siciliano.
> + * To the extent possible under law, the author has dedicated all copyright
> + * and related and neighboring rights to this software to the public domain
> + * worldwide. This software is distributed without any warranty, see:
> + *   <http://creativecommons.org/publicdomain/zero/1.0/>.
> + */
> +
> +#include <bsddialog.h>
> +#include <stdio.h>
> +
> +int main()
> +{
> +	int output;
> +	struct bsddialog_conf conf;
> +
> +	if (bsddialog_init() == BSDDIALOG_ERROR) {
> +		printf("Error: %s\n", bsddialog_geterror());
> +		return (1);
> +	}
> +	bsddialog_initconf(&conf);
> +	conf.title = "textbox";
> +	output = bsddialog_textbox(&conf, "./textbox.c", 20, 80);
> +	bsddialog_end();
> +
> +	switch (output) {
> +	case BSDDIALOG_ERROR:
> +		printf("Error %s\n", bsddialog_geterror());
> +		return (1);
> +	case BSDDIALOG_OK:
> +		printf("[Exit]\n");
> +		break;
> +	}
> +
> +	return (0);
> +}
> diff --git a/contrib/bsddialog/lib/GNUmakefile b/contrib/bsddialog/lib/GNUmakefile
> index 7c7a9bc25ee4..2cb060381a46 100644
> --- a/contrib/bsddialog/lib/GNUmakefile
> +++ b/contrib/bsddialog/lib/GNUmakefile
> @@ -9,6 +9,7 @@ HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
>   SOURCES = barbox.c datebox.c formbox.c libbsddialog.c lib_util.c \
>   	menubox.c messagebox.c textbox.c theme.c timebox.c
>   OBJECTS = $(SOURCES:.c=.o)
> +PREFIX = /usr/local
>   
>   ifneq ($(ENABLEDEBUG),)
>   CFLAGS += -g
> @@ -21,7 +22,21 @@ LIBFLAG = -shared
>   RM = rm -f
>   LN = ln -s -f
>   
> -all : $(LIBRARY)
> +all: $(LIBRARY)
> +
> +install: all
> +	${INSTALL} -m 0644 bsddialog.h ${DESTDIR}${PREFIX}/include/bsddialog.h
> +	${INSTALL} -m 0644 bsddialog_progressview.h ${DESTDIR}${PREFIX}/include/bsddialog_progressview.h
> +	${INSTALL} -m 0644 bsddialog_theme.h ${DESTDIR}${PREFIX}/include/bsddialog_theme.h
> +	${INSTALL} -m 0755 ${LIBRARY_SO}.${VERSION} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}.${VERSION}
> +	${LN} ${LIBRARY_SO}.${VERSION} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}
> +
> +uninstall:
> +	${RM} ${DESTDIR}${PREFIX}/include/bsddialog.h
> +	${RM} ${DESTDIR}${PREFIX}/include/bsddialog_progressview.h
> +	${RM} ${DESTDIR}${PREFIX}/include/bsddialog_theme.h
> +	${RM} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}.${VERSION}
> +	${RM} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}
>   
>   $(LIBRARY): $(OBJECTS)
>   	$(CC) $(LIBFLAG) $^ -o $(LIBRARY_SO).$(VERSION) $(LDFLAGS)
> @@ -32,3 +47,5 @@ $(LIBRARY): $(OBJECTS)
>   
>   clean:
>   	$(RM) $(LIBRARY_SO)* *.o *~
> +
> +.PHONY: all install uninstall ${LIBRARY} clean
> diff --git a/contrib/bsddialog/lib/Makefile b/contrib/bsddialog/lib/Makefile
> index 252b33f79848..c728541a9f7a 100644
> --- a/contrib/bsddialog/lib/Makefile
> +++ b/contrib/bsddialog/lib/Makefile
> @@ -10,6 +10,7 @@ HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h
>   SOURCES = barbox.c datebox.c formbox.c libbsddialog.c lib_util.c \
>   	menubox.c messagebox.c textbox.c theme.c timebox.c
>   OBJECTS = ${SOURCES:.c=.o}
> +PREFIX = /usr/local
>   
>   .if defined(DEBUG)
>   CFLAGS += -g
> @@ -23,7 +24,23 @@ LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \
>   LN = ln -s -f
>   RM = rm -f
>   
> -all : ${LIBRARY}
> +all: ${LIBRARY}
> +
> +install: all
> +	${INSTALL} -m 0644 bsddialog.h ${DESTDIR}${PREFIX}/include/bsddialog.h
> +	${INSTALL} -m 0644 bsddialog_progressview.h ${DESTDIR}${PREFIX}/include/bsddialog_progressview.h
> +	${INSTALL} -m 0644 bsddialog_theme.h ${DESTDIR}${PREFIX}/include/bsddialog_theme.h
> +	${INSTALL} -m 0644 ${LIBRARY_A} ${DESTDIR}${PREFIX}/lib/${LIBRARY_A}
> +	${INSTALL} -m 0755 ${LIBRARY_SO}.${VERSION} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}.${VERSION}
> +	${LN} ${LIBRARY_SO}.${VERSION} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}
> +
> +uninstall:
> +	${RM} ${DESTDIR}${PREFIX}/include/bsddialog.h
> +	${RM} ${DESTDIR}${PREFIX}/include/bsddialog_progressview.h
> +	${RM} ${DESTDIR}${PREFIX}/include/bsddialog_theme.h
> +	${RM} ${DESTDIR}${PREFIX}/lib/${LIBRARY_A}
> +	${RM} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}.${VERSION}
> +	${RM} ${DESTDIR}${PREFIX}/lib/${LIBRARY_SO}
>   
>   ${LIBRARY}: ${LIBRARY_SO} ${LIBRARY_A}
>   
> @@ -42,3 +59,5 @@ ${LIBRARY_A}: ${OBJECTS}
>   
>   clean:
>   	${RM} ${LIBRARY_SO}* *.o *~ *.gz ${LIBRARY_A}
> +
> +.PHONY: all install uninstall ${LIBRARY} clean
> diff --git a/contrib/bsddialog/lib/barbox.c b/contrib/bsddialog/lib/barbox.c
> index 4feea20c6441..51f81ecbca68 100644
> --- a/contrib/bsddialog/lib/barbox.c
> +++ b/contrib/bsddialog/lib/barbox.c
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2024 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -371,7 +371,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
>   	unsigned int i, mainperc, totaltodo;
>   	float readforsec;
>   	const char **minilabels;
> -	time_t tstart, told, tnew, refresh;
> +	time_t tstart, told, tnew, trefresh;
>   
>   	if ((minilabels = calloc(nminibar, sizeof(char*))) == NULL)
>   		RETURN_ERROR("Cannot allocate memory for minilabels");
> @@ -385,7 +385,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
>   		minipercs[i] = minibar[i].status;
>   	}
>   
> -	refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
> +	trefresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1;
>   	retval = BSDDIALOG_OK;
>   	i = 0;
>   	update = true;
> @@ -398,7 +398,7 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
>   			mainperc = (bsddialog_total_progview * 100) / totaltodo;
>   
>   		time(&tnew);
> -		if (update || tnew > told + refresh) {
> +		if (update || tnew > told + trefresh) {
>   			retval = do_mixedgauge(conf, text, rows, cols, mainperc,
>   			    nminibar, minilabels, minipercs, true);
>   			if (retval == BSDDIALOG_ERROR)
> @@ -440,17 +440,18 @@ bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows,
>   	return (retval);
>   }
>   
> -static int rangebox_redraw(struct dialog *d, struct bar *b, int *bigchange)
> +static int
> +rangebox_redraw(struct dialog *d, bool redraw, struct bar *b, int *bigchange)
>   {
> -	if (d->built) {
> +	if (redraw) {
>   		hide_dialog(d);
>   		refresh(); /* Important for decreasing screen */
>   	}
>   	if (dialog_size_position(d, HBOX, MIN_WBOX, NULL) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (draw_dialog(d) != 0)
> +	if (draw_dialog(d) != 0) /* doupdate() in main loop */
>   		return (BSDDIALOG_ERROR);
> -	if (d->built)
> +	if (redraw)
>   		refresh(); /* Important to fix grey lines expanding screen */
>   	TEXTPAD(d, HBOX + HBUTTONS);
>   
> @@ -490,7 +491,7 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
>   		RETURN_ERROR("Cannot build WINDOW bar");
>   	b.y = b.x = 1;
>   	b.fmt = "%d";
> -	if (rangebox_redraw(&d, &b, &bigchange) != 0)
> +	if (rangebox_redraw(&d, false, &b, &bigchange) != 0)
>   		return (BSDDIALOG_ERROR);
>   
>   	loop = true;
> @@ -568,12 +569,12 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
>   				break;
>   			if (f1help_dialog(conf) != 0)
>   				return (BSDDIALOG_ERROR);
> -			if (rangebox_redraw(&d, &b, &bigchange) != 0)
> +			if (rangebox_redraw(&d, true, &b, &bigchange) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		case KEY_CTRL('l'):
>   		case KEY_RESIZE:
> -			if (rangebox_redraw(&d, &b, &bigchange) != 0)
> +			if (rangebox_redraw(&d, true, &b, &bigchange) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		default:
> @@ -594,17 +595,17 @@ bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows,
>   	return (retval);
>   }
>   
> -static int pause_redraw(struct dialog *d, struct bar *b)
> +static int pause_redraw(struct dialog *d, bool redraw, struct bar *b)
>   {
> -	if (d->built) {
> +	if (redraw) {
>   		hide_dialog(d);
>   		refresh(); /* Important for decreasing screen */
>   	}
>   	if (dialog_size_position(d, HBOX, MIN_WBOX, NULL) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (draw_dialog(d) != 0)
> +	if (draw_dialog(d) != 0) /* doupdate() in main loop */
>   		return (BSDDIALOG_ERROR);
> -	if (d->built)
> +	if (redraw)
>   		refresh(); /* Important to fix grey lines expanding screen */
>   	TEXTPAD(d, HBOX + HBUTTONS);
>   
> @@ -633,7 +634,7 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
>   		RETURN_ERROR("Cannot build WINDOW bar");
>   	b.y = b.x = 1;
>   	b.fmt = "%d";
> -	if (pause_redraw(&d, &b) != 0)
> +	if (pause_redraw(&d, false, &b) != 0)
>   		return (BSDDIALOG_ERROR);
>   
>   	tout = *seconds;
> @@ -687,12 +688,12 @@ bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows,
>   				break;
>   			if (f1help_dialog(conf) != 0)
>   				return (BSDDIALOG_ERROR);
> -			if (pause_redraw(&d, &b) != 0)
> +			if (pause_redraw(&d, true, &b) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		case KEY_CTRL('l'):
>   		case KEY_RESIZE:
> -			if (pause_redraw(&d, &b) != 0)
> +			if (pause_redraw(&d, true, &b) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		default:
> diff --git a/contrib/bsddialog/lib/bsddialog.3 b/contrib/bsddialog/lib/bsddialog.3
> index cbf1653a2aca..bbd756661a78 100644
> --- a/contrib/bsddialog/lib/bsddialog.3
> +++ b/contrib/bsddialog/lib/bsddialog.3
> @@ -1,5 +1,5 @@
>   .\"
> -.\" Copyright (c) 2021-2024 Alfonso Sabato Siciliano
> +.\" Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>   .\"
>   .\" Redistribution and use in source and binary forms, with or without
>   .\" modification, are permitted provided that the following conditions
> @@ -22,11 +22,12 @@
>   .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>   .\" SUCH DAMAGE.
>   .\"
> -.Dd March 16, 2024
> +.Dd June 22, 2025
>   .Dt BSDDIALOG 3
>   .Os
>   .Sh NAME
>   .Nm bsddialog_backtitle ,
> +.Nm bsddialog_backtitle_rf ,
>   .Nm bsddialog_calendar ,
>   .Nm bsddialog_clear ,
>   .Nm bsddialog_color ,
> @@ -65,6 +66,8 @@
>   .Ft int
>   .Fn bsddialog_backtitle "struct bsddialog_conf *conf" "const char *backtitle"
>   .Ft int
> +.Fn bsddialog_backtitle_rf "struct bsddialog_conf *conf" "const char *backtitle"
> +.Ft int
>   .Fo bsddialog_calendar
>   .Fa "struct bsddialog_conf *conf"
>   .Fa "const char *text"
> @@ -292,7 +295,7 @@ and before
>   .Dv false
>   otherwise.
>   .Pp
> -.Fn bsddialog_backtitle
> +.Fn bsddialog_backtitle_rf
>   prints
>   .Fa backtitle
>   on the top of the screen.
> @@ -302,6 +305,11 @@ and
>   .Fa conf.no_lines
>   described later.
>   .Pp
> +.Fn bsddialog_backtitle
> +is like
> +.Fn bsddialog_backtitle_rf
> +but it does not update the screen, using if a dialog is built later.
> +.Pp
>   .Fn bsddialog_error
>   returns a string to describe the last error.
>   The function should be called after a
> @@ -902,7 +910,7 @@ provides a dialog for a
>   the labels on buttons are
>   .Dq Yes
>   and
> -.Dq No .
> +.Dq &No .
>   .Ss Keys
>   .Bl -tag -width Ds
>   .It Ctrl-l
> diff --git a/contrib/bsddialog/lib/bsddialog.h b/contrib/bsddialog/lib/bsddialog.h
> index fd0e2bc02580..fc59071c6fa0 100644
> --- a/contrib/bsddialog/lib/bsddialog.h
> +++ b/contrib/bsddialog/lib/bsddialog.h
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2024 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -30,7 +30,7 @@
>   
>   #include <stdbool.h>
>   
> -#define LIBBSDDIALOG_VERSION     "1.0.4"
> +#define LIBBSDDIALOG_VERSION     "1.0.5"
>   
>   /* Return values */
>   #define BSDDIALOG_ERROR          -1
> @@ -179,6 +179,7 @@ int bsddialog_init_notheme(void);
>   bool bsddialog_inmode(void);
>   int bsddialog_end(void);
>   int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle);
> +int bsddialog_backtitle_rf(struct bsddialog_conf *conf, const char *backtitle);
>   int bsddialog_initconf(struct bsddialog_conf *conf);
>   void bsddialog_clear(unsigned int y);
>   void bsddialog_refresh(void);
> diff --git a/contrib/bsddialog/lib/bsddialog_theme.h b/contrib/bsddialog/lib/bsddialog_theme.h
> index 2071896b61f0..77938c65b6ce 100644
> --- a/contrib/bsddialog/lib/bsddialog_theme.h
> +++ b/contrib/bsddialog/lib/bsddialog_theme.h
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> diff --git a/contrib/bsddialog/lib/datebox.c b/contrib/bsddialog/lib/datebox.c
> index ee955471799e..66f36f5f4a99 100644
> --- a/contrib/bsddialog/lib/datebox.c
> +++ b/contrib/bsddialog/lib/datebox.c
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2022-2024 Alfonso Sabato Siciliano
> + * Copyright (c) 2022-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -296,20 +296,20 @@ print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd,
>   }
>   
>   static int
> -calendar_redraw(struct dialog *d, WINDOW *yy_win, WINDOW *mm_win,
> +calendar_draw(struct dialog *d, bool redraw, WINDOW *yy_win, WINDOW *mm_win,
>       WINDOW *dd_win)
>   {
>   	int ycal, xcal;
>   
> -	if (d->built) {
> +	if (redraw) {
>   		hide_dialog(d);
>   		refresh(); /* Important for decreasing screen */
>   	}
>   	if (dialog_size_position(d, MINHCAL, MINWCAL, NULL) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (draw_dialog(d) != 0)
> +	if (draw_dialog(d) != 0) /* doupdate in main loop */
>   		return (BSDDIALOG_ERROR);
> -	if (d->built)
> +	if (redraw)
>   		refresh(); /* Important to fix grey lines expanding screen */
>   	TEXTPAD(d, MINHCAL + HBUTTONS);
>   
> @@ -354,7 +354,7 @@ bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
>   	if ((dd_win = newwin(1, 1, 1, 1)) == NULL)
>   		RETURN_ERROR("Cannot build WINDOW for dd");
>   	wbkgd(dd_win, t.dialog.color);
> -	if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
> +	if (calendar_draw(&d, false, yy_win, mm_win, dd_win) != 0)
>   		return (BSDDIALOG_ERROR);
>   
>   	sel = -1;
> @@ -503,12 +503,12 @@ bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
>   				break;
>   			if (f1help_dialog(conf) != 0)
>   				return (BSDDIALOG_ERROR);
> -			if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
> +			if (calendar_draw(&d, true, yy_win, mm_win, dd_win) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		case KEY_CTRL('l'):
>   		case KEY_RESIZE:
> -			if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
> +			if (calendar_draw(&d, true, yy_win, mm_win, dd_win) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		default:
> @@ -533,11 +533,11 @@ bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
>   	return (retval);
>   }
>   
> -static int datebox_redraw(struct dialog *d, struct dateitem *di)
> +static int datebox_draw(struct dialog *d, bool redraw, struct dateitem *di)
>   {
>   	int y, x;
>   
> -	if (d->built) {
> +	if (redraw) {
>   		hide_dialog(d);
>   		refresh(); /* Important for decreasing screen */
>   	}
> @@ -545,7 +545,7 @@ static int datebox_redraw(struct dialog *d, struct dateitem *di)
>   		return (BSDDIALOG_ERROR);
>   	if (draw_dialog(d) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (d->built)
> +	if (redraw)
>   		refresh(); /* Important to fix grey lines expanding screen */
>   	TEXTPAD(d, 3 /*windows*/ + HBUTTONS);
>   
> @@ -624,7 +624,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
>   	set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
>   	if (build_dateitem(conf->date.format, &yy, &mm, &dd, di) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (datebox_redraw(&d, di) != 0)
> +	if (datebox_draw(&d, false, di) != 0)
>   		return (BSDDIALOG_ERROR);
>   
>   	sel = -1;
> @@ -716,12 +716,12 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
>   				break;
>   			if (f1help_dialog(conf) != 0)
>   				return (BSDDIALOG_ERROR);
> -			if (datebox_redraw(&d, di) != 0)
> +			if (datebox_draw(&d, true, di) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		case KEY_CTRL('l'):
>   		case KEY_RESIZE:
> -			if (datebox_redraw(&d, di) != 0)
> +			if (datebox_draw(&d, true, di) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		default:
> diff --git a/contrib/bsddialog/lib/formbox.c b/contrib/bsddialog/lib/formbox.c
> index ca473356e350..a072461c43e1 100644
> --- a/contrib/bsddialog/lib/formbox.c
> +++ b/contrib/bsddialog/lib/formbox.c
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2024 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -601,11 +601,11 @@ static int form_size_position(struct dialog *d, struct privateform *f)
>   }
>   
>   static int
> -form_redraw(struct dialog *d, struct privateform *f, bool focusinform)
> +form_draw(struct dialog *d, bool redraw, struct privateform *f, bool focusinform)
>   {
>   	unsigned int i;
>   
> -	if (d->built) {
> +	if (redraw) {
>   		hide_dialog(d);
>   		refresh(); /* Important for decreasing screen */
>   	}
> @@ -613,9 +613,9 @@ form_redraw(struct dialog *d, struct privateform *f, bool focusinform)
>   	f->w = f->wmin;
>   	if (form_size_position(d, f) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (draw_dialog(d) != 0)
> +	if (draw_dialog(d) != 0) /* doupdate() in main loop */
>   		return (BSDDIALOG_ERROR);
> -	if (d->built)
> +	if (redraw)
>   		refresh(); /* Important to fix grey lines expanding screen */
>   	TEXTPAD(d, 2 /* box borders */ + f->viewrows + HBUTTONS);
>   
> @@ -707,7 +707,7 @@ bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
>   	}
>   
>   	form.formheight = formheight;
> -	if (form_redraw(&d, &form, focusinform) != 0)
> +	if (form_draw(&d, false, &form, focusinform) != 0)
>   		return (BSDDIALOG_ERROR);
>   
>   	changeitem = switchfocus = false;
> @@ -719,10 +719,16 @@ bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
>   		switch(input) {
>   		case KEY_ENTER:
>   		case 10: /* Enter */
> -			if (focusinform && conf->button.always_active == false)
> -				break;
> -			retval = BUTTONVALUE(d.bs);
> -			loop = false;
> +			if (focusinform && conf->button.always_active == false) {
> +				next = nextitem(form.nitems, form.pritems, form.sel);
> +				if (next > form.sel)
> +					changeitem = true; /* needs next */
> +				else
> +					switchfocus = true;
> +			} else {
> +				retval = BUTTONVALUE(d.bs);
> +				loop = false;
> +			}
>   			break;
>   		case 27: /* Esc */
>   			if (conf->key.enable_esc) {
> @@ -732,7 +738,12 @@ bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
>   			break;
>   		case '\t': /* TAB */
>   			if (focusinform) {
> -				switchfocus = true;
> +				next = nextitem(form.nitems, form.pritems,
> +				    form.sel);
> +				if (next > form.sel)
> +					changeitem = true;  /* needs next */
> +				else
> +					switchfocus = true;
>   			} else {
>   				if (d.bs.curr + 1 < (int)d.bs.nbuttons) {
>   					d.bs.curr++;
> @@ -839,12 +850,12 @@ bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
>   				retval = BSDDIALOG_ERROR;
>   				loop = false;
>   			}
> -			if (form_redraw(&d, &form, focusinform) != 0)
> +			if (form_draw(&d, true, &form, focusinform) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		case KEY_CTRL('l'):
>   		case KEY_RESIZE:
> -			if (form_redraw(&d, &form, focusinform) != 0)
> +			if (form_draw(&d, true, &form, focusinform) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		default:
> @@ -884,11 +895,20 @@ bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows,
>   			    conf->button.always_active || !focusinform,
>   			    !focusinform);
>   			wnoutrefresh(d.widget);
> -			DRAWITEM_TRICK(&form, form.sel, focusinform);
> +			if (focusinform == false)
> +				DRAWITEM_TRICK(&form, form.sel, false);
> +			else {
> +				next = firstitem(form.nitems, form.pritems);
> +				if (next == form.sel)
> +					DRAWITEM_TRICK(&form, form.sel, true);
> +				else
> +					changeitem = true;
> +			}
>   			switchfocus = false;
>   		}
>   
>   		if (changeitem) {
> +			/* useless after if(switchfocus) */
>   			DRAWITEM_TRICK(&form, form.sel, false);
>   			form.sel = next;
>   			item = &form.pritems[form.sel];
> diff --git a/contrib/bsddialog/lib/lib_util.c b/contrib/bsddialog/lib/lib_util.c
> index d673a1a74d72..f042a2832eb9 100644
> --- a/contrib/bsddialog/lib/lib_util.c
> +++ b/contrib/bsddialog/lib/lib_util.c
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -25,6 +25,7 @@
>    * SUCH DAMAGE.
>    */
>   
> +#include <stdarg.h>
>   #include <curses.h>
>   #include <stdlib.h>
>   #include <string.h>
> diff --git a/contrib/bsddialog/lib/lib_util.h b/contrib/bsddialog/lib/lib_util.h
> index 526f65b4bfaa..1adc34f3b80a 100644
> --- a/contrib/bsddialog/lib/lib_util.h
> +++ b/contrib/bsddialog/lib/lib_util.h
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2024 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -62,7 +62,7 @@ extern bool hastermcolors;
>   		RETURN_ERROR("*" #p " is NULL");                               \
>   } while (0)
>   #define CHECK_ARRAY(nitem, a) do {                                             \
> -	if (nitem > 0 && a == NULL)                                             \
> +	if (nitem > 0 && a == NULL)                                            \
>   		RETURN_FMTERROR(#nitem " is %d but *" #a " is NULL", nitem);   \
>   } while (0)
>   /* widget utils */
> diff --git a/contrib/bsddialog/lib/libbsddialog.c b/contrib/bsddialog/lib/libbsddialog.c
> index 555d060ebcbd..cdb5e1e251dc 100644
> --- a/contrib/bsddialog/lib/libbsddialog.c
> +++ b/contrib/bsddialog/lib/libbsddialog.c
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2023 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -114,11 +114,21 @@ int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle)
>   			mvhline_set(1, 1, WACS_HLINE, SCREENCOLS - 2);
>   	}
>   
> -	refresh();
> +	wnoutrefresh(stdscr);
>   
>   	return (BSDDIALOG_OK);
>   }
>   
> +int bsddialog_backtitle_rf(struct bsddialog_conf *conf, const char *backtitle)
> +{
> +	int rv;
> +
> +	rv = bsddialog_backtitle(conf, backtitle);
> +	doupdate();
> +
> +	return (rv);
> +}
> +
>   bool bsddialog_inmode(void)
>   {
>   	return (in_bsddialog_mode);
> diff --git a/contrib/bsddialog/lib/menubox.c b/contrib/bsddialog/lib/menubox.c
> index 896306b2881d..e6e2e7e3e63e 100644
> --- a/contrib/bsddialog/lib/menubox.c
> +++ b/contrib/bsddialog/lib/menubox.c
> @@ -1,7 +1,7 @@
>   /*-
>    * SPDX-License-Identifier: BSD-2-Clause
>    *
> - * Copyright (c) 2021-2024 Alfonso Sabato Siciliano
> + * Copyright (c) 2021-2025 Alfonso Sabato Siciliano
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
> @@ -391,7 +391,7 @@ drawitem(struct bsddialog_conf *conf, struct privatemenu *m, int y, bool focus)
>   			attron(t.menu.bottomdesccolor);
>   			addstr(pritem->bottomdesc);
>   			attroff(t.menu.bottomdesccolor);
> -			refresh();
> +			wnoutrefresh(stdscr);
>   		}
>   	}
>   }
> @@ -454,18 +454,18 @@ static int menu_size_position(struct dialog *d, struct privatemenu *m)
>   	return (0);
>   }
>   
> -static int mixedlist_redraw(struct dialog *d, struct privatemenu *m)
> +static int mixedlist_draw(struct dialog *d, bool redraw, struct privatemenu *m)
>   {
> -	if (d->built) {
> +	if (redraw) {
>   		hide_dialog(d);
>   		refresh(); /* Important for decreasing screen */
>   	}
>   	m->menurows = m->apimenurows;
>   	if (menu_size_position(d, m) != 0)
>   		return (BSDDIALOG_ERROR);
> -	if (draw_dialog(d) != 0)
> +	if (draw_dialog(d) != 0) /* doupdate() in main loop */
>   		return (BSDDIALOG_ERROR);
> -	if (d->built)
> +	if (redraw)
>   		refresh(); /* Important to fix grey lines expanding screen */
>   	TEXTPAD(d, 2/*bmenu*/ + m->menurows + HBUTTONS);
>   
> @@ -532,7 +532,7 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
>   		drawitem(d.conf, &m, m.sel, true);
>   	m.ypad = 0;
>   	m.apimenurows = menurows;
> -	if (mixedlist_redraw(&d, &m) != 0)
> +	if (mixedlist_draw(&d, false, &m) != 0)
>   		return (BSDDIALOG_ERROR);
>   
>   	changeitem = false;
> @@ -575,12 +575,12 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols,
>   				break;
>   			if (f1help_dialog(conf) != 0)
>   				return (BSDDIALOG_ERROR);
> -			if (mixedlist_redraw(&d, &m) != 0)
> +			if (mixedlist_draw(&d, true, &m) != 0)
>   				return (BSDDIALOG_ERROR);
>   			break;
>   		case KEY_CTRL('l'):
> *** 610 LINES SKIPPED ***
> 

-- 
Colin Percival
FreeBSD Release Engineering Lead & EC2 platform maintainer
Founder, Tarsnap | www.tarsnap.com | Online backups for the truly paranoid