git: 50e244964e9b - main - bsdinstall/partedit: Replace libdialog with libbsddialog

From: Alfonso S. Siciliano <asiciliano_at_FreeBSD.org>
Date: Mon, 04 Apr 2022 00:05:43 UTC
The branch main has been updated by asiciliano:

URL: https://cgit.FreeBSD.org/src/commit/?id=50e244964e9b06528b84720e09da7bdf8cec6d32

commit 50e244964e9b06528b84720e09da7bdf8cec6d32
Author:     Alfonso S. Siciliano <asiciliano@FreeBSD.org>
AuthorDate: 2022-04-03 23:52:00 +0000
Commit:     Alfonso S. Siciliano <asiciliano@FreeBSD.org>
CommitDate: 2022-04-04 00:05:00 +0000

    bsdinstall/partedit: Replace libdialog with libbsddialog
    
    bsdinstall/partedit: Replace (LGPL) libdialog with (BSD-2-Clause)
    libbsddialog. Rewrite diskeditor.c and rename diskmenu.c because
    it uses an API for menu totally incompatible with libbsddialog.
    This is a User Interface change everything else is unchanged.
    
    Approved by:            bapt (mentor)
    Differential Revision:  https://reviews.freebsd.org/D34639
---
 usr.sbin/bsdinstall/partedit/Makefile              |   5 +-
 usr.sbin/bsdinstall/partedit/diskeditor.c          | 292 -------------
 usr.sbin/bsdinstall/partedit/diskmenu.c            |  90 ++++
 .../partedit/{diskeditor.h => diskmenu.h}          |  15 +-
 usr.sbin/bsdinstall/partedit/gpart_ops.c           | 478 ++++++++++++---------
 usr.sbin/bsdinstall/partedit/part_wizard.c         |  85 ++--
 usr.sbin/bsdinstall/partedit/partedit.c            | 169 ++++----
 7 files changed, 526 insertions(+), 608 deletions(-)

diff --git a/usr.sbin/bsdinstall/partedit/Makefile b/usr.sbin/bsdinstall/partedit/Makefile
index a250302a1962..f89a1d374fb8 100644
--- a/usr.sbin/bsdinstall/partedit/Makefile
+++ b/usr.sbin/bsdinstall/partedit/Makefile
@@ -5,7 +5,8 @@ PROG=	partedit
 LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \
        ${BINDIR}/partedit ${BINDIR}/scriptedpart
 SYMLINKS= ../libexec/bsdinstall/partedit /usr/sbin/sade
-LIBADD+=	geom ncursesw util dialog m
+CFLAGS+=	-I${SRCTOP}/contrib/bsddialog/lib
+LIBADD+=	geom util bsddialog
 
 PARTEDIT_ARCH= ${MACHINE}
 .if ${MACHINE} == "i386" || ${MACHINE} == "amd64"
@@ -17,7 +18,7 @@ PARTEDIT_ARCH= efi
 PARTEDIT_ARCH= generic
 .endif
 
-SRCS=	diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
+SRCS=	diskmenu.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
 	part_wizard.c scripted.c
 
 WARNS?=	3
diff --git a/usr.sbin/bsdinstall/partedit/diskeditor.c b/usr.sbin/bsdinstall/partedit/diskeditor.c
deleted file mode 100644
index 1679def32a19..000000000000
--- a/usr.sbin/bsdinstall/partedit/diskeditor.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 Nathan Whitehorn
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <libutil.h>
-#include <dialog.h>
-#include <dlg_keys.h>
-
-#include "diskeditor.h"
-
-static void
-print_partedit_item(WINDOW *partitions, struct partedit_item *items,
-    int item, int nscroll, int selected)
-{
-	chtype attr = A_NORMAL;
-	char sizetext[16];
-	int y = item - nscroll + 1;
-
-	wattrset(partitions, selected ? item_selected_attr : item_attr);
-	wmove(partitions, y, MARGIN + items[item].indentation*2);
-	dlg_print_text(partitions, items[item].name, 10, &attr);
-	wmove(partitions, y, 17);
-	wattrset(partitions, item_attr);
-
-	humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,
-	    HN_DECIMAL);
-	dlg_print_text(partitions, sizetext, 8, &attr);
-	wmove(partitions, y, 25);
-	dlg_print_text(partitions, items[item].type, 15, &attr);
-	wmove(partitions, y, 40);
-	if (items[item].mountpoint != NULL)
-		dlg_print_text(partitions, items[item].mountpoint, 8, &attr);
-}
-
-int
-diskeditor_show(const char *title, const char *cprompt,
-    struct partedit_item *items, int nitems, int *selected, int *nscroll)
-{
-	WINDOW *dialog, *partitions;
-	char *prompt;
-	const char *buttons[] =
-	    { "Create", "Delete", "Modify", "Revert", "Auto", "Finish", NULL };
-	const char *help_text[] = {
-	    "Add a new partition", "Delete selected partition or partitions",
-	    "Change partition type or mountpoint",
-	    "Revert changes to disk setup", "Use guided partitioning tool",
-	    "Exit partitioner (will ask whether to save changes)", NULL };
-	int x, y;
-	int i;
-	int height, width, min_width;
-	int partlist_height, partlist_width;
-	int cur_scroll = 0;
-	int key, fkey;
-	int cur_button = 5, cur_part = 0;
-	int result = DLG_EXIT_UNKNOWN;
-
-	static DLG_KEYS_BINDING binding[] = {
-		ENTERKEY_BINDINGS,
-		DLG_KEYS_DATA( DLGK_ENTER,      ' ' ),
-		DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
-		DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
-		DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
-		DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
-		DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
-		DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
-
-		SCROLLKEY_BINDINGS,
-		END_KEYS_BINDING
-	};
-
-	static DLG_KEYS_BINDING binding2[] = {
-		INPUTSTR_BINDINGS,
-		ENTERKEY_BINDINGS,
-		DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
-		DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
-		DLG_KEYS_DATA( DLGK_ITEM_NEXT,  CHR_NEXT ),
-		DLG_KEYS_DATA( DLGK_ITEM_NEXT,  KEY_DOWN ),
-		DLG_KEYS_DATA( DLGK_ITEM_NEXT,  KEY_NEXT ),
-		DLG_KEYS_DATA( DLGK_ITEM_PREV,  CHR_PREVIOUS ),
-		DLG_KEYS_DATA( DLGK_ITEM_PREV,  KEY_PREVIOUS ),
-		DLG_KEYS_DATA( DLGK_ITEM_PREV,  KEY_UP ),
-		DLG_KEYS_DATA( DLGK_PAGE_NEXT,  KEY_NPAGE ),
-		DLG_KEYS_DATA( DLGK_PAGE_PREV,  KEY_PPAGE ),
-		END_KEYS_BINDING
-	};
-
-	/*
-	 * Set up editor window.
-	 */
-	prompt = dlg_strclone(cprompt);
-
-	min_width = 50;
-	height = width = 0;
-	partlist_height = 10;
-	dlg_tab_correct_str(prompt);
-	dlg_button_layout(buttons, &min_width);
-	dlg_auto_size(title, prompt, &height, &width, 2, min_width);
-	height += partlist_height;
-	partlist_width = width - 2*MARGIN;
-	dlg_print_size(height, width);
-	dlg_ctl_size(height, width);
-
-	x = dlg_box_x_ordinate(width);
-	y = dlg_box_y_ordinate(height);
-
-	dialog = dlg_new_window(height, width, y, x);
-	dlg_register_window(dialog, "diskeditorbox", binding);
-	dlg_register_buttons(dialog, "diskeditorbox", buttons);
-
-	dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
-	dlg_draw_bottom_box(dialog);
-	dlg_draw_title(dialog, title);
-	wattrset(dialog, dialog_attr);
-
-	/* Partition list sub-window */
-	partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
-	    y + 3, x + 1);
-	dlg_register_window(partitions, "partlist", binding2);
-	dlg_register_buttons(partitions, "partlist", buttons);
-	wattrset(partitions, menubox_attr);
-
-	dlg_item_help(help_text[cur_button]);
-	dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
-	    cur_button, FALSE, width);
-	dlg_print_autowrap(dialog, prompt, height, width);
-
-	if (selected != NULL)
-		cur_part = *selected;
-	if (nscroll != NULL)
-		cur_scroll = *nscroll;
-	if (cur_part - cur_scroll >= partlist_height - 2 ||
-	    cur_part - cur_scroll < 0)
-		cur_scroll = cur_part;
-
-repaint:
-	dlg_draw_box(dialog, 3, 1,  partlist_height, partlist_width,
-	    menubox_border_attr, menubox_attr);
-	for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
-	    i++)
-		print_partedit_item(partitions, items, i, cur_scroll,
-		    i == cur_part);
-	if (nitems > partlist_height - 2)
-		dlg_draw_arrows(partitions, cur_scroll > 0,
-		    nitems > cur_scroll + partlist_height - 2,
-		    partlist_width - 5, 0, partlist_height - 1);
-	wrefresh(partitions);
-
-	while (result == DLG_EXIT_UNKNOWN) {
-		key = dlg_mouse_wgetch(dialog, &fkey);
-		if ((i = dlg_char_to_button(key, buttons)) >= 0) {
-			cur_button = i;
-			dlg_item_help(help_text[cur_button]);
-			dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
-			    cur_button, FALSE, width);
-			break;
-		}
-
-		if (!fkey)
-			continue;
-
-		switch (key) {
-		case DLGK_FIELD_NEXT:
-			cur_button = dlg_next_button(buttons, cur_button);
-			if (cur_button < 0)
-				cur_button = 0;
-			dlg_item_help(help_text[cur_button]);
-			dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
-			    cur_button, FALSE, width);
-			break;
-		case DLGK_FIELD_PREV:
-			cur_button = dlg_prev_button(buttons, cur_button);
-			if (cur_button < 0)
-				cur_button = 0;
-			dlg_item_help(help_text[cur_button]);
-			dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
-			    cur_button, FALSE, width);
-			break;
-		case DLGK_ITEM_NEXT:
-			if (cur_part == nitems - 1)
-				break; /* End of list */
-
-			/* Deselect old item */
-			print_partedit_item(partitions, items, cur_part,
-			    cur_scroll, 0);
-			/* Select new item */
-			cur_part++;
-			if (cur_part - cur_scroll >= partlist_height - 2) {
-				cur_scroll = cur_part;
-				goto repaint;
-			}
-			print_partedit_item(partitions, items, cur_part,
-			    cur_scroll, 1);
-			wrefresh(partitions);
-			break;
-		case DLGK_ITEM_PREV:
-			if (cur_part == 0)
-				break; /* Start of list */
-
-			/* Deselect old item */
-			print_partedit_item(partitions, items, cur_part,
-			    cur_scroll, 0);
-			/* Select new item */
-			cur_part--;
-			if (cur_part - cur_scroll < 0) {
-				cur_scroll = cur_part;
-				goto repaint;
-			}
-			print_partedit_item(partitions, items, cur_part,
-			    cur_scroll, 1);
-			wrefresh(partitions);
-			break;
-		case DLGK_PAGE_NEXT:
-			cur_scroll += (partlist_height - 2);
-			if (cur_scroll + partlist_height - 2 >= nitems)
-				cur_scroll = nitems - (partlist_height - 2);
-			if (cur_scroll < 0)
-				cur_scroll = 0;
-			if (cur_part < cur_scroll)
-				cur_part = cur_scroll;
-			goto repaint;
-		case DLGK_PAGE_PREV:
-			cur_scroll -= (partlist_height - 2);
-			if (cur_scroll < 0)
-				cur_scroll = 0;
-			if (cur_part >= cur_scroll + partlist_height - 2)
-				cur_part = cur_scroll;
-			goto repaint;
-		case DLGK_PAGE_FIRST:
-			cur_scroll = 0;
-			cur_part = cur_scroll;
-			goto repaint;
-		case DLGK_PAGE_LAST:
-			cur_scroll = nitems - (partlist_height - 2);
-			if (cur_scroll < 0)
-				cur_scroll = 0;
-			cur_part = cur_scroll;
-			goto repaint;
-		case DLGK_ENTER:
-			goto done;
-		default:
-			if (is_DLGK_MOUSE(key)) {
-				cur_button = key - M_EVENT;
-				dlg_item_help(help_text[cur_button]);
-				dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
-				    buttons, cur_button, FALSE, width);
-				goto done;
-			}
-			break;
-		}
-	}
-
-done:
-	if (selected != NULL)
-		*selected = cur_part;
-	if (nscroll != NULL)
-		*nscroll = cur_scroll;
-
-	dlg_del_window(partitions);
-	dlg_del_window(dialog);
-	dlg_mouse_free_regions();
-
-	return (cur_button);
-}
-
diff --git a/usr.sbin/bsdinstall/partedit/diskmenu.c b/usr.sbin/bsdinstall/partedit/diskmenu.c
new file mode 100644
index 000000000000..9e16ef96171a
--- /dev/null
+++ b/usr.sbin/bsdinstall/partedit/diskmenu.c
@@ -0,0 +1,90 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Alfonso Sabato Siciliano
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsddialog.h>
+#include <libutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "diskmenu.h"
+
+int
+diskmenu_show(const char *title, const char *text, struct partedit_item *items,
+    int nitems, int *focusitem)
+{
+	int i, output;
+	char size[16], *mp;
+	struct bsddialog_menuitem *bsditems;
+	struct bsddialog_conf conf;
+
+	bsditems = malloc(nitems * sizeof(struct bsddialog_menuitem));
+	if (bsditems == NULL)
+		return BSDDIALOG_ERROR;
+	for (i = 0; i < nitems; i++) {
+		bsditems[i].prefix = "";
+		bsditems[i].on = false;
+		bsditems[i].depth = items[i].indentation;
+		/* old menu sets max namelen to 10 */
+		bsditems[i].name = items[i].name;
+		humanize_number(size, 7, items[i].size, "B",
+		    HN_AUTOSCALE, HN_DECIMAL);
+		mp = items[i].mountpoint != NULL ? items[i].mountpoint : "";
+		asprintf(__DECONST(char**, &bsditems[i].desc), "%s %-15s %-10s",
+		    size, items[i].type, mp);
+		bsditems[i].bottomdesc = "";
+	}
+
+	bsddialog_initconf(&conf);
+	conf.title = title;
+	conf.menu.align_left = true;
+	conf.text.highlight = true;
+	conf.key.f1_message="[\\Z1\\ZbC\\Znreate]: a new partition.\n"
+		"[\\Z1\\ZbD\\Znelete]: selected partition(s).\n"
+		"[\\Z1\\ZbC\\Znhange]: partition type or mountpoint.\n"
+		"[\\Z1\\ZbR\\Znevert]: changes to disk setup.\n"
+		"[\\Z1\\ZbA\\Znuto]:   guided partitioning tool.\n"
+		"[\\Z1\\ZbF\\Zninish]: will ask to apply changes.";
+	conf.menu.shortcut_buttons = true;
+	conf.button.ok_label       = "Create";
+	conf.button.with_extra     = true;
+	conf.button.extra_label    = "Delete";
+	conf.button.cancel_label   = "Modify";
+	conf.button.with_help      = true;
+	conf.button.help_label     = "Revert";
+	conf.button.generic1_label = "Auto";
+	conf.button.generic2_label = "Finish";
+	conf.button.default_label  = "Finish";
+	output = bsddialog_menu(&conf, text, 20, 0, 10, nitems, bsditems,
+	    focusitem);
+
+	for (i = 0; i < nitems; i++)
+		free((char *)bsditems[i].desc);
+	free(bsditems);
+
+	return output;
+}
diff --git a/usr.sbin/bsdinstall/partedit/diskeditor.h b/usr.sbin/bsdinstall/partedit/diskmenu.h
similarity index 79%
rename from usr.sbin/bsdinstall/partedit/diskeditor.h
rename to usr.sbin/bsdinstall/partedit/diskmenu.h
index 186dc3146ced..77077c8c1e05 100644
--- a/usr.sbin/bsdinstall/partedit/diskeditor.h
+++ b/usr.sbin/bsdinstall/partedit/diskmenu.h
@@ -28,10 +28,15 @@
  * $FreeBSD$
  */
 
-#ifndef _PARTEDIT_DISKEDITOR_H
-#define _PARTEDIT_DISKEDITOR_H
+#ifndef _PARTEDIT_DISKMENU_H
+#define _PARTEDIT_DISKMENU_H
 
-#include <inttypes.h>
+#define BUTTON_CREATE BSDDIALOG_OK
+#define BUTTON_DELETE BSDDIALOG_EXTRA
+#define BUTTON_MODIFY BSDDIALOG_CANCEL
+#define BUTTON_REVERT BSDDIALOG_HELP
+#define BUTTON_AUTO   BSDDIALOG_GENERIC1
+#define BUTTON_FINISH BSDDIALOG_GENERIC2
 
 struct partedit_item {
 	int indentation;
@@ -43,7 +48,7 @@ struct partedit_item {
 	void *cookie;
 };
 
-int diskeditor_show(const char *title, const char *prompt,
-    struct partedit_item *items, int nitems, int *selected, int *scroll);
+int diskmenu_show(const char *title, const char *text,
+    struct partedit_item *items, int nitems, int *selected);
 
 #endif
diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c
index f95cc514903b..65cda247e146 100644
--- a/usr.sbin/bsdinstall/partedit/gpart_ops.c
+++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c
@@ -30,14 +30,19 @@
 
 #include <sys/param.h>
 #include <sys/stat.h>
+
+#include <bsddialog.h>
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libutil.h>
 #include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 
 #include <libgeom.h>
-#include <dialog.h>
-#include <dlg_keys.h>
 
 #include "partedit.h"
 
@@ -49,6 +54,7 @@ gpart_show_error(const char *title, const char *explanation, const char *errstr)
 	char *errmsg;
 	char message[512];
 	int error;
+	struct bsddialog_conf conf;
 
 	if (explanation == NULL)
 		explanation = "";
@@ -66,7 +72,9 @@ gpart_show_error(const char *title, const char *explanation, const char *errstr)
 		sprintf(message, "%s%s", explanation, errmsg);
 	}
 
-	dialog_msgbox(title, message, 0, 0, TRUE);
+	bsddialog_initconf(&conf);
+	conf.title = title;
+	bsddialog_msgbox(&conf, message, 0, 0);
 }
 
 static int
@@ -83,34 +91,38 @@ scheme_supports_labels(const char *scheme)
 static void
 newfs_command(const char *fstype, char *command, int use_default)
 {
+	struct bsddialog_conf conf;
+
+	bsddialog_initconf(&conf);
+
 	if (strcmp(fstype, "freebsd-ufs") == 0) {
 		int i;
-		DIALOG_LISTITEM items[] = {
-			{"UFS1", "UFS Version 1",
+		struct bsddialog_menuitem items[] = {
+			{"", false, 0, "UFS1", "UFS Version 1",
 			    "Use version 1 of the UFS file system instead "
-			    "of version 2 (not recommended)", 0 },
-			{"SU", "Softupdates",
-			    "Enable softupdates (default)", 1 },
-			{"SUJ", "Softupdates journaling",
+			    "of version 2 (not recommended)"},
+			{"", true, 0, "SU", "Softupdates",
+			    "Enable softupdates (default)"},
+			{"", true, 0, "SUJ", "Softupdates journaling",
 			    "Enable file system journaling (default - "
-			    "turn off for SSDs)", 1 },
-			{"TRIM", "Enable SSD TRIM support",
-			    "Enable TRIM support, useful on solid-state drives",
-			    0 },
+			    "turn off for SSDs)"},
+			{"", false, 0, "TRIM", "Enable SSD TRIM support",
+			    "Enable TRIM support, useful on solid-state "
+			    "drives" },
 		};
 
 		if (!use_default) {
 			int choice;
-			choice = dlg_checklist("UFS Options", "", 0, 0, 0,
-			    nitems(items), items, NULL,
-			    FLAG_CHECK, &i);
-			if (choice == 1) /* Cancel */
+			conf.title = "UFS Options";
+			choice = bsddialog_checklist(&conf, "", 0, 0, 0,
+			    nitems(items), items, NULL);
+			if (choice == BSDDIALOG_CANCEL)
 				return;
 		}
 
 		strcpy(command, "newfs ");
 		for (i = 0; i < (int)nitems(items); i++) {
-			if (items[i].state == 0)
+			if (items[i].on == false)
 				continue;
 			if (strcmp(items[i].name, "UFS1") == 0)
 				strcat(command, "-O1 ");
@@ -123,26 +135,26 @@ newfs_command(const char *fstype, char *command, int use_default)
 		}
 	} else if (strcmp(fstype, "freebsd-zfs") == 0) {
 		int i;
-		DIALOG_LISTITEM items[] = {
-			{"fletcher4", "checksum algorithm: fletcher4",
+		struct bsddialog_menuitem items[] = {
+			{"", 0, true, "fletcher4", "checksum algorithm: fletcher4",
 			    "Use fletcher4 for data integrity checking. "
-			    "(default)", 1 },
-			{"fletcher2", "checksum algorithm: fletcher2",
+			    "(default)"},
+			{"", 0, false, "fletcher2", "checksum algorithm: fletcher2",
 			    "Use fletcher2 for data integrity checking. "
-			    "(not recommended)", 0 },
-			{"sha256", "checksum algorithm: sha256",
+			    "(not recommended)"},
+			{"", 0, false, "sha256", "checksum algorithm: sha256",
 			    "Use sha256 for data integrity checking. "
-			    "(not recommended)", 0 },
-			{"atime", "Update atimes for files",
-			    "Disable atime update", 0 },
+			    "(not recommended)"},
+			{"", 0, false, "atime", "Update atimes for files",
+			    "Disable atime update"},
 		};
 
 		if (!use_default) {
 			int choice;
-			choice = dlg_checklist("ZFS Options", "", 0, 0, 0,
-			    nitems(items), items, NULL,
-			    FLAG_CHECK, &i);
-			if (choice == 1) /* Cancel */
+			conf.title = "ZFS Options";
+			choice = bsddialog_checklist(&conf, "", 0, 0, 0,
+			    nitems(items), items, NULL);
+			if (choice == BSDDIALOG_CANCEL)
 				return;
 		}
 
@@ -157,7 +169,7 @@ newfs_command(const char *fstype, char *command, int use_default)
 			    command, zfsboot_path);
 		}
 		for (i = 0; i < (int)nitems(items); i++) {
-			if (items[i].state == 0)
+			if (items[i].on == false)
 				continue;
 			if (strcmp(items[i].name, "fletcher4") == 0)
 				strcat(command, "-O checksum=fletcher4 ");
@@ -171,27 +183,27 @@ newfs_command(const char *fstype, char *command, int use_default)
 	} else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0 ||
 	     strcmp(fstype, "ms-basic-data") == 0) {
 		int i;
-		DIALOG_LISTITEM items[] = {
-			{"FAT32", "FAT Type 32",
-			    "Create a FAT32 filesystem (default)", 1 },
-			{"FAT16", "FAT Type 16",
-			    "Create a FAT16 filesystem", 0 },
-			{"FAT12", "FAT Type 12",
-			    "Create a FAT12 filesystem", 0 },
+		struct bsddialog_menuitem items[] = {
+			{"", 0, true, "FAT32", "FAT Type 32",
+			    "Create a FAT32 filesystem (default)"},
+			{"", 0, false, "FAT16", "FAT Type 16",
+			    "Create a FAT16 filesystem"},
+			{"", 0, false, "FAT12", "FAT Type 12",
+			    "Create a FAT12 filesystem"},
 		};
 
 		if (!use_default) {
 			int choice;
-			choice = dlg_checklist("FAT Options", "", 0, 0, 0,
-			    nitems(items), items, NULL,
-			    FLAG_RADIO, &i);
-			if (choice == 1) /* Cancel */
+			conf.title = "FAT Options";
+			choice = bsddialog_radiolist(&conf, "", 0, 0, 0,
+			    nitems(items), items, NULL);
+			if (choice == BSDDIALOG_CANCEL)
 				return;
 		}
 
 		strcpy(command, "newfs_msdos ");
 		for (i = 0; i < (int)nitems(items); i++) {
-			if (items[i].state == 0)
+			if (items[i].on == false)
 				continue;
 			if (strcmp(items[i].name, "FAT32") == 0)
 				strcat(command, "-F 32 -c 1");
@@ -201,9 +213,11 @@ newfs_command(const char *fstype, char *command, int use_default)
 				strcat(command, "-F 12 ");
 		}
 	} else {
-		if (!use_default)
-			dialog_msgbox("Error", "No configurable options exist "
-			    "for this filesystem.", 0, 0, TRUE);
+		if (!use_default) {
+			conf.title = "Error";
+			bsddialog_msgbox(&conf, "No configurable options exist "
+			    "for this filesystem.", 0, 0);
+		}
 		command[0] = '\0';
 	}
 }
@@ -211,28 +225,34 @@ newfs_command(const char *fstype, char *command, int use_default)
 const char *
 choose_part_type(const char *def_scheme)
 {
-	int cancel, choice;
+	int button, choice, i;
 	const char *scheme = NULL;
-
-	DIALOG_LISTITEM items[] = {
-		{"APM", "Apple Partition Map",
-		    "Bootable on PowerPC Apple Hardware", 0 },
-		{"BSD", "BSD Labels",
-		    "Bootable on most x86 systems", 0 },
-		{"GPT", "GUID Partition Table",
-		    "Bootable on most x86 systems and EFI aware ARM64", 0 },
-		{"MBR", "DOS Partitions",
-		    "Bootable on most x86 systems", 0 },
+	struct bsddialog_conf conf;
+
+	struct bsddialog_menuitem items[] = {
+		{"", false, 0, "APM", "Apple Partition Map",
+		    "Bootable on PowerPC Apple Hardware" },
+		{"", false, 0, "BSD", "BSD Labels",
+		    "Bootable on most x86 systems" },
+		{"", false, 0, "GPT", "GUID Partition Table",
+		    "Bootable on most x86 systems and EFI aware ARM64" },
+		{"", false, 0, "MBR", "DOS Partitions",
+		    "Bootable on most x86 systems" },
 	};
 
+	for (i = 0; i < (int)nitems(items); i++)
+		if (strcmp(items[i].name, def_scheme) == 0)
+			choice = i;
+
+	bsddialog_initconf(&conf);
+
 parttypemenu:
-	dialog_vars.default_item = __DECONST(char *, def_scheme);
-	cancel = dlg_menu("Partition Scheme",
+	conf.title = "Partition Scheme";
+	button = bsddialog_menu(&conf,
 	    "Select a partition scheme for this volume:", 0, 0, 0,
-	    nitems(items), items, &choice, NULL);
-	dialog_vars.default_item = NULL;
+	    nitems(items), items, &choice);
 
-	if (cancel)
+	if (button == BSDDIALOG_CANCEL)
 		return NULL;
 
 	if (!is_scheme_bootable(items[choice].name)) {
@@ -240,10 +260,11 @@ parttypemenu:
 		sprintf(message, "This partition scheme (%s) is not "
 		    "bootable on this platform. Are you sure you want "
 		    "to proceed?", items[choice].name);
-		dialog_vars.defaultno = TRUE;
-		cancel = dialog_yesno("Warning", message, 0, 0);
-		dialog_vars.defaultno = FALSE;
-		if (cancel) /* cancel */
+		conf.button.default_cancel = true;
+		conf.title = "Warning";
+		button = bsddialog_yesno(&conf, message, 0, 0);
+		conf.button.default_cancel = false;
+		if (button == BSDDIALOG_NO)
 			goto parttypemenu;
 	}
 
@@ -255,9 +276,12 @@ parttypemenu:
 int
 gpart_partition(const char *lg_name, const char *scheme)
 {
-	int cancel;
+	int button;
 	struct gctl_req *r;
 	const char *errstr;
+	struct bsddialog_conf conf;
+
+	bsddialog_initconf(&conf);
 
 schememenu:
 	if (scheme == NULL) {
@@ -271,10 +295,11 @@ schememenu:
 			sprintf(message, "This partition scheme (%s) is not "
 			    "bootable on this platform. Are you sure you want "
 			    "to proceed?", scheme);
-			dialog_vars.defaultno = TRUE;
-			cancel = dialog_yesno("Warning", message, 0, 0);
-			dialog_vars.defaultno = FALSE;
-			if (cancel) { /* cancel */
+			conf.button.default_cancel = true;
+			conf.title = "Warning";
+			button = bsddialog_yesno(&conf, message, 0, 0);
+			conf.button.default_cancel = false;
+			if (button == BSDDIALOG_NO) {
 				/* Reset scheme so user can choose another */
 				scheme = NULL;
 				goto schememenu;
@@ -379,6 +404,7 @@ gpart_bootcode(struct ggeom *gp)
 	uint8_t *boot;
 	size_t bootsize, bytes;
 	int bootfd;
+	struct bsddialog_conf conf;
 
 	/*
 	 * Write default bootcode to the newly partitioned disk, if that
@@ -397,8 +423,9 @@ gpart_bootcode(struct ggeom *gp)
 
 	bootfd = open(bootcode, O_RDONLY);
 	if (bootfd < 0) {
-		dialog_msgbox("Bootcode Error", strerror(errno), 0, 0,
-		    TRUE);
+		bsddialog_initconf(&conf);
+		conf.title = "Bootcode Error";
+		bsddialog_msgbox(&conf, strerror(errno), 0, 0);
 		return;
 	}
 
@@ -430,6 +457,7 @@ gpart_partcode(struct gprovider *pp, const char *fstype)
 	const char *scheme;
 	const char *indexstr;
 	char message[255], command[255];
+	struct bsddialog_conf conf;
 
 	LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) {
 		if (strcmp(gc->lg_name, "scheme") == 0) {
@@ -455,7 +483,9 @@ gpart_partcode(struct gprovider *pp, const char *fstype)
 	if (system(command) != 0) {
 		sprintf(message, "Error installing partcode on partition %s",
 		    pp->lg_name);
-		dialog_msgbox("Error", message, 0, 0, TRUE);
+		bsddialog_initconf(&conf);
+		conf.title = "Error";
+		bsddialog_msgbox(&conf, message, 0, 0);
 	}
 }
 
@@ -513,24 +543,26 @@ gpart_edit(struct gprovider *pp)
 	char sizestr[32];
 	char newfs[255];
 	intmax_t idx;
-	int hadlabel, choice, junk, nitems;
+	int hadlabel, choice, nitems;
 	unsigned i;
-
-	DIALOG_FORMITEM items[] = {
-		{0, "Type:", 5, 0, 0, FALSE, "", 11, 0, 12, 15, 0,
-		    FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
-		    "freebsd-swap)", FALSE},
-		{0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 0, 0,
-		    FALSE, "Partition size. Append K, M, G for kilobytes, "
-		    "megabytes or gigabytes.", FALSE},
-		{0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0,
-		    FALSE, "Path at which to mount this partition (leave blank "
-		    "for swap, set to / for root filesystem)", FALSE},
-		{0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE,
-		    "Partition name. Not all partition schemes support this.",
-		    FALSE},
+	struct bsddialog_conf conf;
+
+	struct bsddialog_formitem items[] = {
+		{ "Type:", 1, 1, "", 1, 12, 12, 15, NULL, 0,
+		    "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
+		    "freebsd-swap)"},
+		{ "Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0,
+		    "Partition size. Append K, M, G for kilobytes, "
+		    "megabytes or gigabytes."},
+		{ "Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0,
+		    "Path at which to mount this partition (leave blank "
+		    "for swap, set to / for root filesystem)"},
+		{ "Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0,
+		    "Partition name. Not all partition schemes support this."},
 	};
 
+	bsddialog_initconf(&conf);
+
 	/*
 	 * Find the PART geom we are manipulating. This may be a consumer of
 	 * this provider, or its parent. Check the consumer case first.
@@ -586,11 +618,11 @@ gpart_edit(struct gprovider *pp)
 	LIST_FOREACH(gc, &pp->lg_config, lg_config) {
 		if (strcmp(gc->lg_name, "type") == 0) {
 			oldtype = gc->lg_val;
-			items[0].text = gc->lg_val;
+			items[0].init = gc->lg_val;
 		}
 		if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) {
 			hadlabel = 1;
-			items[3].text = gc->lg_val;
+			items[3].init = gc->lg_val;
 		}
 		if (strcmp(gc->lg_name, "index") == 0)
 			idx = atoi(gc->lg_val);
@@ -599,39 +631,43 @@ gpart_edit(struct gprovider *pp)
 	TAILQ_FOREACH(md, &part_metadata, metadata) {
 		if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) {
 			if (md->fstab != NULL)
-				items[2].text = md->fstab->fs_file;
+				items[2].init = md->fstab->fs_file;
 			break;
 		}
 	}
 
 	humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE,
 	    HN_NOSPACE | HN_DECIMAL);
-	items[1].text = sizestr;
+	items[1].init = sizestr;
 
 editpart:
-	choice = dlg_form("Edit Partition", "", 0, 0, 0, nitems, items, &junk);
+	conf.form.value_without_ok = true;
+	conf.title = "Edit Partition";
+	choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items);
 
-	if (choice) /* Cancel pressed */
+	if (choice == BSDDIALOG_CANCEL)
 		goto endedit;
 
 	/* If this is the root partition, check that this fs is bootable */
-	if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
-	    items[0].text)) {
+	if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme,
+	    items[0].value)) {
 		char message[512];
 		sprintf(message, "This file system (%s) is not bootable "
 		    "on this system. Are you sure you want to proceed?",
-		    items[0].text);
-		dialog_vars.defaultno = TRUE;
-		choice = dialog_yesno("Warning", message, 0, 0);
-		dialog_vars.defaultno = FALSE;
-		if (choice == 1) /* cancel */
+		    items[0].value);
+		conf.button.default_cancel = true;
+		conf.title = "Warning";
+		choice = bsddialog_yesno(&conf, message, 0, 0);
+		conf.button.default_cancel = false;
+		if (choice == BSDDIALOG_CANCEL)
 			goto editpart;
 	}
 
 	/* Check if the label has a / in it */
-	if (strchr(items[3].text, '/') != NULL) {
-		dialog_msgbox("Error", "Label contains a /, which is not an "
-		    "allowed character.", 0, 0, TRUE);
+	if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) {
+		conf.title = "Error";
+		bsddialog_msgbox(&conf, "Label contains a /, which is not an "
+		    "allowed character.", 0, 0);
 		goto editpart;
 	}
 
@@ -641,9 +677,9 @@ editpart:
 	gctl_ro_param(r, "flags", -1, GPART_FLAGS);
 	gctl_ro_param(r, "verb", -1, "modify");
 	gctl_ro_param(r, "index", sizeof(idx), &idx);
-	if (hadlabel || items[3].text[0] != '\0')
-		gctl_ro_param(r, "label", -1, items[3].text);
-	gctl_ro_param(r, "type", -1, items[0].text);
+	if (items[3].value != NULL && (hadlabel || items[3].value[0] != '\0'))
+		gctl_ro_param(r, "label", -1, items[3].value);
+	gctl_ro_param(r, "type", -1, items[0].value);
 	errstr = gctl_issue(r);
 	if (errstr != NULL && errstr[0] != '\0') {
 		gpart_show_error("Error", NULL, errstr);
@@ -652,21 +688,21 @@ editpart:
 	}
 	gctl_free(r);
 
-	newfs_command(items[0].text, newfs, 1);
-	set_default_part_metadata(pp->lg_name, scheme, items[0].text,
-	    items[2].text, (strcmp(oldtype, items[0].text) != 0) ?
+	newfs_command(items[0].value, newfs, 1);
+	set_default_part_metadata(pp->lg_name, scheme, items[0].value,
+	    items[2].value, (strcmp(oldtype, items[0].value) != 0) ?
 	    newfs : NULL);
 
 endedit:
-	if (strcmp(oldtype, items[0].text) != 0 && cp != NULL)
+	if (strcmp(oldtype, items[0].value) != 0 && cp != NULL)
 		gpart_destroy(cp->lg_geom);
-	if (strcmp(oldtype, items[0].text) != 0 && strcmp(items[0].text,
+	if (strcmp(oldtype, items[0].value) != 0 && strcmp(items[0].value,
 	    "freebsd") == 0)
 		gpart_partition(pp->lg_name, "BSD");
 
 	for (i = 0; i < nitems(items); i++)
-		if (items[i].text_free)
-			free(items[i].text);
+		if (items[i].value != NULL)
+			free(items[i].value);
 }
 
 void
@@ -894,6 +930,7 @@ add_boot_partition(struct ggeom *geom, struct gprovider *pp,
 	struct gconfig *gc;
 	struct gprovider *ppi;
 	int choice;
+	struct bsddialog_conf conf;
 
 	/* Check for existing freebsd-boot partition */
 	LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) {
@@ -931,15 +968,18 @@ add_boot_partition(struct ggeom *geom, struct gprovider *pp,
 		return (0);
*** 970 LINES SKIPPED ***