freebsd-dev/contrib/bsddialog/bsddialog.c
Alfonso S. Siciliano 84823cc708
contrib/bsddialog: Import version 0.4
Improvements and changes to integrate bsddialog(1) with scripts in BASE.
Overview:

 * New options. --and-widget, --keep-tite, --calendar.
 * Change output format. Menus and --print-maxsize.
 * Redefine sizing. Fixed rows, cols and menurows became at the most.
 * Add DIAGNOSTICS. Error messages for bad arguments and options.
 * Add keys. Space for --menu, fast keys for --msgbox and --yesno.
 * Text. Change default text modification, add --cr-wrap.

See /usr/src/contrib/bsddialog/CHANGELOG '2022-09-24 Version 0.4'
for more detailed information.

Merge commit '9f24fda5a8e7ab8243e71473c7e2dc98b4877e64'
2022-09-25 15:09:16 +02:00

1688 lines
45 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021-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 <sys/ioctl.h>
#include <getopt.h>
#include <locale.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <term.h>
#include <time.h>
#include <unistd.h>
#include <bsddialog.h>
#include <bsddialog_theme.h>
#include "util_theme.h"
enum OPTS {
/* Options */
ALTERNATE_SCREEN = '?' + 1,
AND_DIALOG,
ASCII_LINES,
BACKTITLE,
BEGIN_X,
BEGIN_Y,
BIKESHED,
CANCEL_LABEL,
CLEAR_DIALOG,
CLEAR_SCREEN,
COLORS,
COLUMNS_PER_ROW,
CR_WRAP,
DATE_FORMAT,
DEFAULT_BUTTON,
DEFAULT_ITEM,
DEFAULT_NO,
DISABLE_ESC,
ESC_RETURNCANCEL,
EXIT_LABEL,
EXTRA_BUTTON,
EXTRA_LABEL,
GENERIC_BUTTON1,
GENERIC_BUTTON2,
HELP_BUTTON,
HELP_LABEL,
HELP_PRINT_NAME,
HELP_STATUS,
HFILE,
HLINE,
HMSG,
IGNORE,
INSECURE,
ITEM_BOTTOM_DESC,
ITEM_DEPTH,
ITEM_PREFIX,
LOAD_THEME,
MAX_INPUT,
NO_CANCEL,
NO_DESCRIPTIONS,
NO_LINES,
NO_NAMES,
NO_OK,
NO_SHADOW,
NORMAL_SCREEN,
OK_LABEL,
OUTPUT_FD,
OUTPUT_SEPARATOR,
PRINT_MAXSIZE,
PRINT_SIZE,
PRINT_VERSION,
QUOTED,
SAVE_THEME,
SEPARATE_OUTPUT,
SHADOW,
SINGLE_QUOTED,
SLEEP,
STDERR,
STDOUT,
SWITCH_BUTTONS,
TAB_ESCAPE,
TAB_LEN,
TEXT_UNCHANGED,
THEME,
TIME_FORMAT,
TITLE,
/* Dialogs */
CALENDAR,
CHECKLIST,
DATEBOX,
FORM,
GAUGE,
INFOBOX,
INPUTBOX,
MENU,
MIXEDFORM,
MIXEDGAUGE,
MSGBOX,
PASSWORDBOX,
PASSWORDFORM,
PAUSE,
RADIOLIST,
RANGEBOX,
TEXTBOX,
TIMEBOX,
TREEVIEW,
YESNO
};
/* options descriptor */
static struct option longopts[] = {
/* Options */
{"alternate-screen", no_argument, NULL, ALTERNATE_SCREEN},
{"and-dialog", no_argument, NULL, AND_DIALOG},
{"and-widget", no_argument, NULL, AND_DIALOG},
{"ascii-lines", no_argument, NULL, ASCII_LINES},
{"backtitle", required_argument, NULL, BACKTITLE},
{"begin-x", required_argument, NULL, BEGIN_X},
{"begin-y", required_argument, NULL, BEGIN_Y},
{"bikeshed", no_argument, NULL, BIKESHED},
{"cancel-label", required_argument, NULL, CANCEL_LABEL},
{"clear", no_argument, NULL, CLEAR_SCREEN},
{"clear-dialog", no_argument, NULL, CLEAR_DIALOG},
{"clear-screen", no_argument, NULL, CLEAR_SCREEN},
{"colors", no_argument, NULL, COLORS},
{"columns-per-row", required_argument, NULL, COLUMNS_PER_ROW},
{"cr-wrap", no_argument, NULL, CR_WRAP},
{"date-format", required_argument, NULL, DATE_FORMAT},
{"defaultno", no_argument, NULL, DEFAULT_NO},
{"default-button", required_argument, NULL, DEFAULT_BUTTON},
{"default-item", required_argument, NULL, DEFAULT_ITEM},
{"default-no", no_argument, NULL, DEFAULT_NO},
{"disable-esc", no_argument, NULL, DISABLE_ESC},
{"esc-return-cancel", no_argument, NULL, ESC_RETURNCANCEL},
{"exit-label", required_argument, NULL, EXIT_LABEL},
{"extra-button", no_argument, NULL, EXTRA_BUTTON},
{"extra-label", required_argument, NULL, EXTRA_LABEL},
{"generic-button1", required_argument, NULL, GENERIC_BUTTON1},
{"generic-button2", required_argument, NULL, GENERIC_BUTTON2},
{"help-button", no_argument, NULL, HELP_BUTTON},
{"help-label", required_argument, NULL, HELP_LABEL},
{"help-print-name", no_argument, NULL, HELP_PRINT_NAME},
{"help-status", no_argument, NULL, HELP_STATUS},
{"help-tags", no_argument, NULL, HELP_PRINT_NAME},
{"hfile", required_argument, NULL, HFILE},
{"hline", required_argument, NULL, HLINE},
{"hmsg", required_argument, NULL, HMSG},
{"ignore", no_argument, NULL, IGNORE},
{"insecure", no_argument, NULL, INSECURE},
{"item-bottom-desc", no_argument, NULL, ITEM_BOTTOM_DESC},
{"item-depth", no_argument, NULL, ITEM_DEPTH},
{"item-help", no_argument, NULL, ITEM_BOTTOM_DESC},
{"item-prefix", no_argument, NULL, ITEM_PREFIX},
{"keep-tite", no_argument, NULL, ALTERNATE_SCREEN},
{"load-theme", required_argument, NULL, LOAD_THEME},
{"max-input", required_argument, NULL, MAX_INPUT},
{"no-cancel", no_argument, NULL, NO_CANCEL},
{"nocancel", no_argument, NULL, NO_CANCEL},
{"no-descriptions", no_argument, NULL, NO_DESCRIPTIONS},
{"no-items", no_argument, NULL, NO_DESCRIPTIONS},
{"no-label", required_argument, NULL, CANCEL_LABEL},
{"no-lines", no_argument, NULL, NO_LINES},
{"no-names", no_argument, NULL, NO_NAMES},
{"no-ok", no_argument, NULL, NO_OK},
{"nook ", no_argument, NULL, NO_OK},
{"no-shadow", no_argument, NULL, NO_SHADOW},
{"no-tags", no_argument, NULL, NO_NAMES},
{"normal-screen", no_argument, NULL, NORMAL_SCREEN},
{"ok-label", required_argument, NULL, OK_LABEL},
{"output-fd", required_argument, NULL, OUTPUT_FD},
{"output-separator", required_argument, NULL, OUTPUT_SEPARATOR},
{"print-maxsize", no_argument, NULL, PRINT_MAXSIZE},
{"print-size", no_argument, NULL, PRINT_SIZE},
{"print-version", no_argument, NULL, PRINT_VERSION},
{"quoted", no_argument, NULL, QUOTED},
{"save-theme", required_argument, NULL, SAVE_THEME},
{"separate-output", no_argument, NULL, SEPARATE_OUTPUT},
{"separator", required_argument, NULL, OUTPUT_SEPARATOR},
{"shadow", no_argument, NULL, SHADOW},
{"single-quoted", no_argument, NULL, SINGLE_QUOTED},
{"sleep", required_argument, NULL, SLEEP},
{"stderr", no_argument, NULL, STDERR},
{"stdout", no_argument, NULL, STDOUT},
{"switch-buttons", no_argument, NULL, SWITCH_BUTTONS},
{"tab-escape", no_argument, NULL, TAB_ESCAPE},
{"tab-len", required_argument, NULL, TAB_LEN},
{"text-unchanged", no_argument, NULL, TEXT_UNCHANGED},
{"theme", required_argument, NULL, THEME},
{"time-format", required_argument, NULL, TIME_FORMAT},
{"title", required_argument, NULL, TITLE},
{"yes-label", required_argument, NULL, OK_LABEL},
/* Dialogs */
{"calendar", no_argument, NULL, CALENDAR},
{"checklist", no_argument, NULL, CHECKLIST},
{"datebox", no_argument, NULL, DATEBOX},
{"form", no_argument, NULL, FORM},
{"gauge", no_argument, NULL, GAUGE},
{"infobox", no_argument, NULL, INFOBOX},
{"inputbox", no_argument, NULL, INPUTBOX},
{"menu", no_argument, NULL, MENU},
{"mixedform", no_argument, NULL, MIXEDFORM},
{"mixedgauge", no_argument, NULL, MIXEDGAUGE},
{"msgbox", no_argument, NULL, MSGBOX},
{"passwordbox", no_argument, NULL, PASSWORDBOX},
{"passwordform", no_argument, NULL, PASSWORDFORM},
{"pause", no_argument, NULL, PAUSE},
{"radiolist", no_argument, NULL, RADIOLIST},
{"rangebox", no_argument, NULL, RANGEBOX},
{"textbox", no_argument, NULL, TEXTBOX},
{"timebox", no_argument, NULL, TIMEBOX},
{"treeview", no_argument, NULL, TREEVIEW},
{"yesno", no_argument, NULL, YESNO},
/* END */
{ NULL, 0, NULL, 0}
};
/* Menus options */
static bool item_prefix_opt;
static bool item_bottomdesc_opt;
static bool item_output_sepnl_opt;
static bool item_singlequote_opt;
static bool list_items_on_opt;
static bool item_help_print_name_opt;
static bool item_always_quote_opt;
static bool item_depth_opt;
static char *item_output_sep_opt;
static char *item_default_opt;
/* Date and Time options */
static char *date_fmt_opt;
static char *time_fmt_opt;
/* Forms options */
static int unsigned max_input_form_opt;
/* General options */
static bool esc_return_cancel_opt;
static bool ignore_opt;
static int output_fd_opt;
static int getH_opt;
static int getW_opt;
/* Text option */
static bool cr_wrap_opt;
static bool tab_escape_opt;
static bool text_unchanged_opt;
/* Theme and Screen options*/
static bool bikeshed_opt;
static enum bsddialog_default_theme theme_opt;
static char *backtitle_opt;
static bool clear_screen_opt;
static char *loadthemefile;
static char *savethemefile;
static const char *screen_mode_opt;
/* Functions */
#define UNUSED_PAR(x) UNUSED_ ## x __attribute__((__unused__))
static void custom_text(char *text, char *buf);
static void usage(void);
/* Dialogs */
#define BUILDER_ARGS struct bsddialog_conf *conf, char* text, int rows, \
int cols, int argc, char **argv
static int calendar_builder(BUILDER_ARGS);
static int checklist_builder(BUILDER_ARGS);
static int datebox_builder(BUILDER_ARGS);
static int form_builder(BUILDER_ARGS);
static int gauge_builder(BUILDER_ARGS);
static int infobox_builder(BUILDER_ARGS);
static int inputbox_builder(BUILDER_ARGS);
static int menu_builder(BUILDER_ARGS);
static int mixedform_builder(BUILDER_ARGS);
static int mixedgauge_builder(BUILDER_ARGS);
static int msgbox_builder(BUILDER_ARGS);
static int passwordbox_builder(BUILDER_ARGS);
static int passwordform_builder(BUILDER_ARGS);
static int pause_builder(BUILDER_ARGS);
static int radiolist_builder(BUILDER_ARGS);
static int rangebox_builder(BUILDER_ARGS);
static int textbox_builder(BUILDER_ARGS);
static int timebox_builder(BUILDER_ARGS);
static int treeview_builder(BUILDER_ARGS);
static int yesno_builder(BUILDER_ARGS);
/* init, exit and internals */
static bool in_bsddialog_mode;
static bool mandatory_dialog;
static int (*dialogbuilder)(BUILDER_ARGS);
static void exit_error(const char *errstr, bool with_usage)
{
if (in_bsddialog_mode)
bsddialog_end();
printf("Error: %s.\n\n", errstr);
if (with_usage) {
printf("See \'bsddialog --help\' or \'man 1 bsddialog\' ");
printf("for more information.\n");
}
exit (255);
}
static void sigint_handler(int UNUSED_PAR(sig))
{
bsddialog_end();
exit(255);
}
static void start_bsddialog_mode(void)
{
if (in_bsddialog_mode)
return;
if (bsddialog_init() != BSDDIALOG_OK)
exit_error(bsddialog_geterror(), false);
in_bsddialog_mode = true;
signal(SIGINT, sigint_handler);
}
static void error_args(const char *dialog, int argc, char **argv)
{
int i;
if (in_bsddialog_mode)
bsddialog_end();
printf("Error: %s unexpected argument%s:", dialog,
argc > 1 ? "s" : "");
for (i = 0; i < argc; i++)
printf(" \"%s\"", argv[i]);
printf(".\n\n");
printf("See \'bsddialog --help\' or \'man 1 bsddialog\' ");
printf("for more information.\n");
exit (255);
}
static void usage(void)
{
printf("usage: bsddialog --help\n");
printf(" bsddialog --version\n");
printf(" bsddialog [--<opt>] --<dialog> <text> <rows> <cols> "
"[<arg>]\n");
printf(" bsddialog --<dialog1> ... [--and-dialog --<dialog2> "
"...] ...\n");
printf("\n");
printf("Options:\n");
printf(" --alternate-screen, --ascii-lines, --backtitle <backtitle>,"
" --begin-x <x>,\n --begin-y <y>, --bikeshed, --calendar,"
" --cancel-label <label>, --clear-dialog,\n --clear-screen,"
" --colors, --columns-per-row <columns>, --cr-wrap,\n"
" --date-format <format>, --default-button <label>,"
" --default-item <name>,\n --default-no, --disable-esc,"
" --esc-return-cancel, --exit-label <label>,\n --extra-button,"
" --extra-label <label>, --generic-button1 <label>,\n"
" --generic-button2 <label>, --help-button, --help-label <label>,\n"
" --help-print-name, --help-status, --hfile <file>,"
" --hline <string>,\n --hmsg <string>, --ignore, --insecure,"
" --item-bottom-desc, --item-depth,\n --item-prefix,"
" --load-theme <file>, --max-input <size>, --no-cancel,\n"
" --no-descriptions, --no-label <label>, --no-lines, --no-names,"
" --no-ok,\n --no-shadow, --normal-screen, --ok-label <label>,"
" --output-fd <fd>,\n --output-separator <sep>, --print-maxsize,"
" --print-size, --print-version,\n --quoted, --save-theme <file>,"
" --separate-output, --separator <sep>, --shadow,\n"
" --single-quoted, --sleep <secs>, --stderr, --stdout,"
" --tab-escape,\n --tab-len <spaces>, --text-unchanged,"
" --switch-buttons,\n --theme <blackwhite|bsddialog|flat|dialog>,"
" --time-format <format>,\n --title <title>,"
" --yes-label <label>.\n");
printf("\n");
printf("Dialogs:\n");
printf(" --calendar <text> <rows> <cols> [<dd> <mm> <yy>]\n");
printf(" --checklist <text> <rows> <cols> <menurows> [<name> <desc> "
"<on|off>] ...\n");
printf(" --datebox <text> <rows> <cols> [<dd> <mm> <yy>]\n");
printf(" --form <text> <rows> <cols> <formrows> [<label> <ylabel> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters>] "
"...\n");
printf(" --gauge <text> <rows> <cols> [<perc>]\n");
printf(" --infobox <text> <rows> <cols>\n");
printf(" --inputbox <text> <rows> <cols> [init]\n");
printf(" --menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n");
printf(" --mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
"<xlabel> <init> <yfield> <xfield> <fieldlen> <maxletters> "
"<0|1|2>] ...\n");
printf(" --mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> "
"<miniperc>] ...\n");
printf(" --msgbox <text> <rows> <cols>\n");
printf(" --passwordbox <text> <rows> <cols> [init]\n");
printf(" --passwordform <text> <rows> <cols> <formrows> [<label> "
"<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> "
"<maxletters>] ...\n");
printf(" --pause <text> <rows> <cols> <secs>\n");
printf(" --radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
"<on|off>] ...\n");
printf(" --rangebox <text> <rows> <cols> <min> <max> [<init>]\n");
printf(" --textbox <file> <rows> <cols>\n");
printf(" --timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n");
printf(" --treeview <text> <rows> <cols> <menurows> [<depth> <name> "
"<desc> <on|off>] ...\n");
printf(" --yesno <text> <rows> <cols>\n");
printf("\n");
printf("See 'man 1 bsddialog' for more information.\n");
}
static int parseargs(int argc, char **argv, struct bsddialog_conf *conf)
{
int arg, parsed, i;
struct winsize ws;
bsddialog_initconf(conf);
conf->key.enable_esc = true;
conf->menu.on_without_ok = true;
conf->form.value_without_ok = true;
conf->button.always_active = true;
dialogbuilder = NULL;
backtitle_opt = NULL;
theme_opt = -1;
output_fd_opt = STDERR_FILENO;
ignore_opt = false;
cr_wrap_opt = false;
tab_escape_opt = false;
text_unchanged_opt = false;
esc_return_cancel_opt = false;
bikeshed_opt = false;
savethemefile = NULL;
loadthemefile = NULL;
clear_screen_opt = false;
screen_mode_opt = NULL;
item_output_sepnl_opt = false;
item_singlequote_opt = false;
item_prefix_opt = false;
item_bottomdesc_opt = false;
item_depth_opt = false;
list_items_on_opt = false;
item_help_print_name_opt = false;
item_always_quote_opt = false;
item_output_sep_opt = NULL;
item_default_opt = NULL;
date_fmt_opt = NULL;
time_fmt_opt = NULL;
max_input_form_opt = 2048;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "--and-dialog") == 0 ||
strcmp(argv[i], "--and-widget") == 0) {
argc = i + 1;
break;
}
}
parsed = argc;
while ((arg = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
switch (arg) {
/* Options */
case ALTERNATE_SCREEN:
screen_mode_opt = "smcup";
break;
case AND_DIALOG:
if (dialogbuilder == NULL)
exit_error("--and-dialog without previous "
"--<dialog>", true);
break;
case ASCII_LINES:
conf->ascii_lines = true;
break;
case BACKTITLE:
backtitle_opt = optarg;
if (conf->y == BSDDIALOG_CENTER)
conf->auto_topmargin = 2;
break;
case BEGIN_X:
conf->x = (int)strtol(optarg, NULL, 10);
if (conf->x < BSDDIALOG_CENTER)
exit_error("--begin-x < -1", false);
break;
case BEGIN_Y:
conf->y = (int)strtol(optarg, NULL, 10);
if (conf->y < BSDDIALOG_CENTER)
exit_error("--begin-y < -1", false);
conf->auto_topmargin = 0;
break;
case BIKESHED:
bikeshed_opt = true;
break;
case CANCEL_LABEL:
conf->button.cancel_label = optarg;
break;
case CLEAR_DIALOG:
conf->clear = true;
break;
case CLEAR_SCREEN:
mandatory_dialog = false;
clear_screen_opt = true;
break;
case COLORS:
conf->text.highlight = true;
break;
case COLUMNS_PER_ROW:
conf->text.cols_per_row =
(u_int)strtoul(optarg, NULL, 10);
break;
case CR_WRAP:
cr_wrap_opt = true;
break;
case DATE_FORMAT:
date_fmt_opt = optarg;
break;
case DEFAULT_BUTTON:
conf->button.default_label = optarg;
break;
case DEFAULT_ITEM:
item_default_opt = optarg;
break;
case DEFAULT_NO:
conf->button.default_cancel = true;
break;
case DISABLE_ESC:
conf->key.enable_esc = false;
break;
case ESC_RETURNCANCEL:
esc_return_cancel_opt = true;
break;
case EXIT_LABEL:
conf->button.ok_label = optarg;
break;
case EXTRA_BUTTON:
conf->button.with_extra = true;
break;
case EXTRA_LABEL:
conf->button.extra_label = optarg;
break;
case GENERIC_BUTTON1:
conf->button.generic1_label = optarg;
break;
case GENERIC_BUTTON2:
conf->button.generic2_label = optarg;
break;
case HELP_BUTTON:
conf->button.with_help = true;
break;
case HELP_LABEL:
conf->button.help_label = optarg;
break;
case HELP_PRINT_NAME:
item_help_print_name_opt = true;
break;
case HELP_STATUS:
list_items_on_opt = true;
break;
case HFILE:
conf->key.f1_file = optarg;
break;
case HLINE:
if (optarg[0] != '\0')
conf->bottomtitle = optarg;
break;
case HMSG:
conf->key.f1_message = optarg;
break;
case IGNORE:
ignore_opt = true;
break;
case INSECURE:
conf->form.securech = '*';
break;
case ITEM_BOTTOM_DESC:
item_bottomdesc_opt = true;
break;
case ITEM_DEPTH:
item_depth_opt = true;
break;
case ITEM_PREFIX:
item_prefix_opt = true;
break;
case LOAD_THEME:
loadthemefile = optarg;
break;
case MAX_INPUT:
max_input_form_opt = (u_int)strtoul(optarg, NULL, 10);
break;
case NO_CANCEL:
conf->button.without_cancel = true;
break;
case NO_DESCRIPTIONS:
conf->menu.no_desc = true;
break;
case NO_LINES:
conf->no_lines = true;
break;
case NO_NAMES:
conf->menu.no_name = true;
break;
case NO_OK:
conf->button.without_ok = true;
break;
case NO_SHADOW:
conf->shadow = false;
break;
case NORMAL_SCREEN:
screen_mode_opt = "rmcup";
break;
case OK_LABEL:
conf->button.ok_label = optarg;
break;
case OUTPUT_FD:
output_fd_opt = (int)strtol(optarg, NULL, 10);
break;
case OUTPUT_SEPARATOR:
item_output_sep_opt = optarg;
break;
case QUOTED:
item_always_quote_opt = true;
break;
case PRINT_MAXSIZE:
mandatory_dialog = false;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
dprintf(output_fd_opt, "MaxSize: %d, %d\n",
ws.ws_row, ws.ws_col);
break;
case PRINT_SIZE:
conf->get_height = &getH_opt;
conf->get_width = &getW_opt;
break;
case PRINT_VERSION:
mandatory_dialog = false;
dprintf(output_fd_opt, "Version: %s\n",
LIBBSDDIALOG_VERSION);
break;
case SAVE_THEME:
mandatory_dialog = false;
savethemefile = optarg;
break;
case SEPARATE_OUTPUT:
item_output_sepnl_opt = true;
break;
case SHADOW:
conf->shadow = true;
break;
case SINGLE_QUOTED:
item_singlequote_opt = true;
break;
case SLEEP:
conf->sleep = (u_int)strtoul(optarg, NULL, 10);
break;
case STDERR:
output_fd_opt = STDERR_FILENO;
break;
case STDOUT:
output_fd_opt = STDOUT_FILENO;
break;
case SWITCH_BUTTONS:
conf->button.always_active = false;
break;
case TAB_ESCAPE:
tab_escape_opt = true;
break;
case TAB_LEN:
conf->text.tablen = (u_int)strtoul(optarg, NULL, 10);
break;
case TEXT_UNCHANGED:
text_unchanged_opt = true;
break;
case THEME:
if (strcasecmp(optarg, "bsddialog") == 0)
theme_opt = BSDDIALOG_THEME_BSDDIALOG;
else if (strcasecmp(optarg, "blackwhite") == 0)
theme_opt = BSDDIALOG_THEME_BLACKWHITE;
else if (strcasecmp(optarg, "flat") == 0)
theme_opt = BSDDIALOG_THEME_FLAT;
else if (strcasecmp(optarg, "dialog") == 0)
theme_opt = BSDDIALOG_THEME_DIALOG;
else
exit_error("--theme: <unknown> theme", false);
break;
case TIME_FORMAT:
time_fmt_opt = optarg;
break;
case TITLE:
conf->title = optarg;
break;
/* Dialogs */
case CALENDAR:
if (dialogbuilder != NULL)
exit_error("unexpected --calendar", true);
dialogbuilder = calendar_builder;
break;
case CHECKLIST:
if (dialogbuilder != NULL)
exit_error("unexpected --checklist", true);
dialogbuilder = checklist_builder;
conf->auto_downmargin = 1;
break;
case DATEBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --datebox", true);
dialogbuilder = datebox_builder;
break;
case FORM:
if (dialogbuilder != NULL)
exit_error("unexpected --form", true);
dialogbuilder = form_builder;
conf->auto_downmargin = 1;
break;
case GAUGE:
if (dialogbuilder != NULL)
exit_error("unexpected --gauge", true);
dialogbuilder = gauge_builder;
break;
case INFOBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --infobox", true);
dialogbuilder = infobox_builder;
break;
case INPUTBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --inputbox", true);
dialogbuilder = inputbox_builder;
conf->auto_downmargin = 1;
break;
case MENU:
if (dialogbuilder != NULL)
exit_error("unexpected --menu", true);
dialogbuilder = menu_builder;
conf->auto_downmargin = 1;
break;
case MIXEDFORM:
if (dialogbuilder != NULL)
exit_error("unexpected --mixedform", true);
dialogbuilder = mixedform_builder;
conf->auto_downmargin = 1;
break;
case MIXEDGAUGE:
if (dialogbuilder != NULL)
exit_error("unexpected --mixedgauge", true);
dialogbuilder = mixedgauge_builder;
break;
case MSGBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --msgbox", true);
dialogbuilder = msgbox_builder;
break;
case PAUSE:
if (dialogbuilder != NULL)
exit_error("unexpected --pause", true);
dialogbuilder = pause_builder;
break;
case PASSWORDBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --passwordbox", true);
dialogbuilder = passwordbox_builder;
conf->auto_downmargin = 1;
break;
case PASSWORDFORM:
if (dialogbuilder != NULL)
exit_error("unexpected --passwordform", true);
dialogbuilder = passwordform_builder;
conf->auto_downmargin = 1;
break;
case RADIOLIST:
if (dialogbuilder != NULL)
exit_error("unexpected --radiolist", true);
dialogbuilder = radiolist_builder;
conf->auto_downmargin = 1;
break;
case RANGEBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --rangebox", true);
dialogbuilder = rangebox_builder;
break;
case TEXTBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --textbox", true);
dialogbuilder = textbox_builder;
break;
case TIMEBOX:
if (dialogbuilder != NULL)
exit_error("unexpected --timebox", true);
dialogbuilder = timebox_builder;
break;
case TREEVIEW:
if (dialogbuilder != NULL)
exit_error("unexpected --treeview", true);
dialogbuilder = treeview_builder;
conf->auto_downmargin = 1;
break;
case YESNO:
if (dialogbuilder != NULL)
exit_error("unexpected --yesno", true);
dialogbuilder = yesno_builder;
break;
default: /* Error */
if (ignore_opt == true)
break;
exit_error("--ignore to continue", true);
}
}
return (parsed);
}
int main(int argc, char *argv[argc])
{
int i, rows, cols, retval, parsed, nargc, firstoptind;
char *text, **nargv, *pn;
struct bsddialog_conf conf;
setlocale(LC_ALL, "");
in_bsddialog_mode = false;
mandatory_dialog = true;
firstoptind = optind;
pn = argv[0];
retval = BSDDIALOG_OK;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "--version") == 0) {
printf("Version: %s\n", LIBBSDDIALOG_VERSION);
return (BSDDIALOG_OK);
}
if (strcmp(argv[i], "--help") == 0) {
usage();
return (BSDDIALOG_OK);
}
}
while (true) {
parsed = parseargs(argc, argv, &conf);
nargc = argc - parsed;
nargv = argv + parsed;
argc = parsed - optind;
argv += optind;
if (mandatory_dialog && dialogbuilder == NULL)
exit_error("expected a --<dialog>", true);
if (dialogbuilder == NULL && argc > 0)
error_args("(no --<dialog>)", argc, argv);
/* --print-maxsize or --print-version */
if (mandatory_dialog == false && savethemefile == NULL &&
clear_screen_opt == false)
return (BSDDIALOG_OK);
/* --<dialog>, --save-theme or clear-screen */
if (dialogbuilder != NULL) {
if (argc < 3)
exit_error("expected <text> <rows> <cols>",
true);
if ((text = strdup(argv[0])) == NULL)
exit_error("cannot allocate text", false);
if (dialogbuilder != textbox_builder)
custom_text(argv[0], text);
rows = (int)strtol(argv[1], NULL, 10);
cols = (int)strtol(argv[2], NULL, 10);
argc -= 3;
argv += 3;
}
/* bsddialog terminal mode (first iteration) */
start_bsddialog_mode();
if (screen_mode_opt != NULL) {
screen_mode_opt = tigetstr(screen_mode_opt);
if (screen_mode_opt != NULL &&
screen_mode_opt != (char*)-1) {
tputs(screen_mode_opt, 1, putchar);
fflush(stdout);
/* only to refresh, useless in the library */
bsddialog_clearterminal();
}
}
/* theme */
if (theme_opt >= 0)
bsddialog_set_default_theme(theme_opt);
if (loadthemefile != NULL)
loadtheme(loadthemefile);
if (bikeshed_opt)
bikeshed(&conf);
if (savethemefile != NULL)
savetheme(savethemefile, LIBBSDDIALOG_VERSION);
/* backtitle and dialog */
if (dialogbuilder == NULL)
break;
if (backtitle_opt != NULL)
if(bsddialog_backtitle(&conf, backtitle_opt))
exit_error(bsddialog_geterror(), false);
retval = dialogbuilder(&conf, text, rows, cols, argc, argv);
free(text);
if (retval == BSDDIALOG_ERROR)
exit_error(bsddialog_geterror(), false);
if (retval == BSDDIALOG_ESC && esc_return_cancel_opt)
retval = BSDDIALOG_CANCEL;
if (conf.get_height != NULL && conf.get_width != NULL)
dprintf(output_fd_opt, "DialogSize: %d, %d\n",
*conf.get_height, *conf.get_width);
if (clear_screen_opt)
bsddialog_clearterminal();
clear_screen_opt = false;
/* --and-dialog ends loop with Cancel or ESC */
if (retval == BSDDIALOG_CANCEL || retval == BSDDIALOG_ESC)
break;
argc = nargc;
argv = nargv;
if (argc <= 0)
break;
/* prepare next parseargs() call */
argc++;
argv--;
argv[0] = pn;
optind = firstoptind;
}
if (in_bsddialog_mode) {
/* --clear-screen can be a single option */
if (clear_screen_opt)
bsddialog_clearterminal();
bsddialog_end();
}
/* end bsddialog terminal mode */
return (retval);
}
void custom_text(char *text, char *buf)
{
bool trim, crwrap;
int i, j;
if (strstr(text, "\\n") == NULL) {
/* "hasnl" mode */
trim = true;
crwrap = true;
} else {
trim = false;
crwrap = cr_wrap_opt;
}
if (text_unchanged_opt) {
trim = false;
crwrap = true;
}
i = j = 0;
while (text[i] != '\0') {
switch (text[i]) {
case '\\':
buf[j] = '\\';
switch (text[i+1]) {
case 'n': /* implicitly in "hasnl" mode */
buf[j] = '\n';
i++;
if (text[i+1] == '\n')
i++;
break;
case 't':
if (tab_escape_opt) {
buf[j] = '\t';
} else {
j++;
buf[j] = 't';
}
i++;
break;
}
break;
case '\n':
buf[j] = crwrap ? '\n' : ' ';
break;
case '\t':
buf[j] = text_unchanged_opt ? '\t' : ' ';
break;
default:
buf[j] = text[i];
}
i++;
if (!trim || buf[j] != ' ' || j == 0 || buf[j-1] != ' ')
j++;
}
buf[j] = '\0';
}
/* Dialogs */
int gauge_builder(BUILDER_ARGS)
{
int output;
unsigned int perc;
perc = 0;
if (argc == 1) {
perc = (u_int)strtoul(argv[0], NULL, 10);
perc = perc > 100 ? 100 : perc;
} else if (argc > 1) {
error_args("--gauge", argc - 1, argv + 1);
}
output = bsddialog_gauge(conf, text, rows, cols, perc, STDIN_FILENO,
"XXX");
return (output);
}
int infobox_builder(BUILDER_ARGS)
{
if (argc > 0)
error_args("--infobox", argc, argv);
return (bsddialog_infobox(conf, text, rows, cols));
}
int mixedgauge_builder(BUILDER_ARGS)
{
int output, *minipercs;
unsigned int i, mainperc, nminibars;
const char **minilabels;
if (argc < 1 || (((argc-1) % 2) != 0) )
exit_error("bad --mixedgauge arguments", true);
mainperc = (u_int)strtoul(argv[0], NULL, 10);
mainperc = mainperc > 100 ? 100 : mainperc;
argc--;
argv++;
nminibars = argc / 2;
if ((minilabels = calloc(nminibars, sizeof(char*))) == NULL)
exit_error("Cannot allocate memory for minilabels", false);
if ((minipercs = calloc(nminibars, sizeof(int))) == NULL)
exit_error("Cannot allocate memory for minipercs", false);
for (i = 0; i < nminibars; i++) {
minilabels[i] = argv[i * 2];
minipercs[i] = (int)strtol(argv[i * 2 + 1], NULL, 10);
}
output = bsddialog_mixedgauge(conf, text, rows, cols, mainperc,
nminibars, minilabels, minipercs);
return (output);
}
int msgbox_builder(BUILDER_ARGS)
{
if (argc > 0)
error_args("--msgbox", argc, argv);
return (bsddialog_msgbox(conf, text, rows, cols));
}
int pause_builder(BUILDER_ARGS)
{
int output;
unsigned int secs;
if (argc == 0)
exit_error("--pause missing <seconds>", true);
if (argc > 1)
error_args("--pause", argc - 1, argv + 1);
secs = (u_int)strtoul(argv[0], NULL, 10);
output = bsddialog_pause(conf, text, rows, cols, secs);
return (output);
}
int rangebox_builder(BUILDER_ARGS)
{
int output, min, max, value;
if (argc < 2)
exit_error("--rangebox missing <min> <max> [<init>]", true);
if (argc > 3)
error_args("--rangebox", argc - 3, argv + 3);
min = (int)strtol(argv[0], NULL, 10);
max = (int)strtol(argv[1], NULL, 10);
if (argc == 3) {
value = (int)strtol(argv[2], NULL, 10);
value = value < min ? min : value;
value = value > max ? max : value;
} else
value = min;
output = bsddialog_rangebox(conf, text, rows, cols, min, max, &value);
dprintf(output_fd_opt, "%d", value);
return (output);
}
int textbox_builder(BUILDER_ARGS)
{
if (argc > 0)
error_args("--textbox", argc, argv);
return (bsddialog_textbox(conf, text, rows, cols));
}
int yesno_builder(BUILDER_ARGS)
{
if (argc > 0)
error_args("--yesno", argc, argv);
return (bsddialog_yesno(conf, text, rows, cols));
}
/* CALENDAR, DATE and TIME */
static int date(BUILDER_ARGS, bool is_datebox)
{
int ret;
unsigned int yy, mm, dd;
time_t cal;
struct tm *localtm;
char stringdate[1024];
const char *name;
name = is_datebox ? "--datebox" : "--calendar";
time(&cal);
localtm = localtime(&cal);
yy = localtm->tm_year + 1900;
mm = localtm->tm_mon + 1;
dd = localtm->tm_mday;
if (argc > 3) {
error_args(name, argc - 3, argv + 3);
} else if (argc == 3) {
dd = (u_int)strtoul(argv[0], NULL, 10);
mm = (u_int)strtoul(argv[1], NULL, 10);
yy = (u_int)strtoul(argv[2], NULL, 10);
if (yy < 1900)
yy = 1900;
/* max yy check is in lib */
}
if (is_datebox)
ret = bsddialog_datebox(conf, text, rows, cols, &yy, &mm, &dd);
else
ret = bsddialog_calendar(conf, text, rows, cols, &yy, &mm, &dd);
if (ret != BSDDIALOG_OK)
return (ret);
if (date_fmt_opt != NULL) {
time(&cal);
localtm = localtime(&cal);
localtm->tm_year = yy - 1900;
localtm->tm_mon = mm - 1;
localtm->tm_mday = dd;
strftime(stringdate, 1024, date_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringdate);
} else if (bikeshed_opt && (dd % 2 == 0)) {
dprintf(output_fd_opt, "%u/%u/%u", dd, mm, yy);
} else {
dprintf(output_fd_opt, "%02u/%02u/%u", dd, mm, yy);
}
return (ret);
}
int calendar_builder(BUILDER_ARGS)
{
if (rows == 2) {
/*
* (bsdconfig/share/dialog.subr:1352) f_dialog_calendar_size()
* computes height 2 for `dialog --calendar' in
* (bsdconfig/usermgmt/share/user_input.subr:517)
* f_dialog_input_expire_password() and
* (bsdconfig/usermgmt/share/user_input.subr:660)
* f_dialog_input_expire_account().
* Use height auto-sizing that is min height like dialog,
* documented in bsddialog(1).
*/
rows = 0;
}
return (date(conf, text, rows, cols, argc, argv, false));
}
int datebox_builder(BUILDER_ARGS)
{
return (date(conf, text, rows, cols, argc, argv, true));
}
int timebox_builder(BUILDER_ARGS)
{
int output;
unsigned int hh, mm, ss;
time_t clock;
struct tm *localtm;
char stringtime[1024];
time(&clock);
localtm = localtime(&clock);
hh = localtm->tm_hour;
mm = localtm->tm_min;
ss = localtm->tm_sec;
if (argc > 3) {
error_args("--timebox", argc - 3, argv + 3);
} else if (argc == 3) {
hh = (u_int)strtoul(argv[0], NULL, 10);
mm = (u_int)strtoul(argv[1], NULL, 10);
ss = (u_int)strtoul(argv[2], NULL, 10);
}
output = bsddialog_timebox(conf, text, rows, cols, &hh, &mm, &ss);
if (output != BSDDIALOG_OK)
return (output);
if (time_fmt_opt != NULL) {
time(&clock);
localtm = localtime(&clock);
localtm->tm_hour = hh;
localtm->tm_min = mm;
localtm->tm_sec = ss;
strftime(stringtime, 1024, time_fmt_opt, localtm);
dprintf(output_fd_opt, "%s", stringtime);
} else if (bikeshed_opt && (ss % 2 == 0)) {
dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss);
} else {
dprintf(output_fd_opt, "%02u:%02u:%02u", hh, mm, ss);
}
return (output);
}
/* MENU */
static void
get_menu_items(int argc, char **argv, bool setprefix, bool setdepth,
bool setname, bool setdesc, bool setstatus, bool sethelp,
unsigned int *nitems, struct bsddialog_menuitem **items, int *focusitem)
{
unsigned int i, j, sizeitem;
*focusitem = -1;
sizeitem = 0;
sizeitem += setprefix ? 1 : 0;
sizeitem += setdepth ? 1 : 0;
sizeitem += setname ? 1 : 0;
sizeitem += setdesc ? 1 : 0;
sizeitem += setstatus ? 1 : 0;
sizeitem += sethelp ? 1 : 0;
if ((argc % sizeitem) != 0)
exit_error("\"menu\" bad arguments items number", true);
*nitems = argc / sizeitem;
*items = calloc(*nitems, sizeof(struct bsddialog_menuitem));
if (items == NULL)
exit_error("cannot allocate memory \"menu\" items", false);
j = 0;
for (i = 0; i < *nitems; i++) {
(*items)[i].prefix = setprefix ? argv[j++] : "";
(*items)[i].depth = setdepth ?
(u_int)strtoul(argv[j++], NULL, 0) : 0;
(*items)[i].name = setname ? argv[j++] : "";
(*items)[i].desc = setdesc ? argv[j++] : "";
if (setstatus)
(*items)[i].on = strcmp(argv[j++], "on") == 0 ?
true : false;
else
(*items)[i].on = false;
(*items)[i].bottomdesc = sethelp ? argv[j++] : "";
if (item_default_opt != NULL && *focusitem == -1)
if (strcmp((*items)[i].name, item_default_opt) == 0)
*focusitem = i;
}
}
static void
print_menu_items(int output, int nitems, struct bsddialog_menuitem *items,
int focusitem, bool ismenu)
{
bool sep, sepfirst, seplast, toquote;
int i;
char quotech;
const char *focusname, *sepstr;
sep = false;
quotech = item_singlequote_opt ? '\'' : '"';
if (output == BSDDIALOG_ERROR || output == BSDDIALOG_CANCEL ||
output == BSDDIALOG_ESC)
return;
if (output == BSDDIALOG_HELP) {
dprintf(output_fd_opt, "HELP ");
if (focusitem >= 0) {
focusname = items[focusitem].name;
if (item_bottomdesc_opt &&
item_help_print_name_opt == false)
focusname = items[focusitem].bottomdesc;
toquote = false;
if (strchr(focusname, ' ') != NULL) {
toquote = item_always_quote_opt;
if (ismenu == false &&
item_output_sepnl_opt == false)
toquote = true;
}
if (toquote) {
dprintf(output_fd_opt, "%c%s%c",
quotech, focusname, quotech);
} else
dprintf(output_fd_opt, "%s", focusname);
}
if (ismenu || list_items_on_opt == false)
return;
sep = true;
}
sepfirst = false;
if ((sepstr = item_output_sep_opt) == NULL)
sepstr = item_output_sepnl_opt ? "\n" : " ";
else
sepfirst = true;
seplast = false;
if (item_output_sepnl_opt) {
sepfirst = false;
seplast = true;
}
for (i = 0; i < nitems; i++) {
if (items[i].on == false)
continue;
if (sep || sepfirst)
dprintf(output_fd_opt, "%s", sepstr);
sep = false;
toquote = false;
if (strchr(items[i].name, ' ') != NULL) {
toquote = item_always_quote_opt;
if (ismenu == false && item_output_sepnl_opt == false)
toquote = true;
}
if (toquote)
dprintf(output_fd_opt, "%c%s%c",
quotech, items[i].name, quotech);
else
dprintf(output_fd_opt, "%s", items[i].name);
if (seplast)
dprintf(output_fd_opt, "%s", sepstr);
}
}
int checklist_builder(BUILDER_ARGS)
{
int output, focusitem;
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
if (argc < 1)
exit_error("--checklist missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
get_menu_items(argc-1, argv+1, item_prefix_opt, item_depth_opt, true,
true, true, item_bottomdesc_opt, &nitems, &items, &focusitem);
output = bsddialog_checklist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem, false);
free(items);
return (output);
}
int menu_builder(BUILDER_ARGS)
{
int output, focusitem;
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
if (argc < 1)
exit_error("--menu missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
get_menu_items(argc-1, argv+1, item_prefix_opt, item_depth_opt, true,
true, false, item_bottomdesc_opt, &nitems, &items, &focusitem);
output = bsddialog_menu(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem, true);
free(items);
return (output);
}
int radiolist_builder(BUILDER_ARGS)
{
int output, focusitem;
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
if (argc < 1)
exit_error("--radiolist missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
get_menu_items(argc-1, argv+1, item_prefix_opt, item_depth_opt, true,
true, true, item_bottomdesc_opt, &nitems, &items, &focusitem);
output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem, false);
free(items);
return (output);
}
int treeview_builder(BUILDER_ARGS)
{
int output, focusitem;
unsigned int menurows, nitems;
struct bsddialog_menuitem *items;
if (argc < 1)
exit_error("--treeview missing <menurows>", true);
menurows = (u_int)strtoul(argv[0], NULL, 10);
get_menu_items(argc-1, argv+1, item_prefix_opt, true, true, true, true,
item_bottomdesc_opt, &nitems, &items, &focusitem);
conf->menu.no_name = true;
conf->menu.align_left = true;
output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
items, &focusitem);
print_menu_items(output, nitems, items, focusitem, false);
free(items);
return (output);
}
/* FORM */
static void
print_form_items(int output, int nitems, struct bsddialog_formitem *items)
{
int i;
if (output == BSDDIALOG_ERROR)
return;
for (i = 0; i < nitems; i++) {
dprintf(output_fd_opt, "%s\n", items[i].value);
free(items[i].value);
}
}
int form_builder(BUILDER_ARGS)
{
int output, fieldlen, valuelen;
unsigned int i, j, flags, formheight, nitems, sizeitem;
struct bsddialog_formitem *items;
if (argc < 1)
exit_error("--form missing <formheight>", true);
formheight = (u_int)strtoul(argv[0], NULL, 10);
argc--;
argv++;
sizeitem = item_bottomdesc_opt ? 9 : 8;
if (argc % sizeitem != 0)
exit_error("--form bad number of arguments items", true);
nitems = argc / sizeitem;
if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
exit_error("cannot allocate memory for form items", false);
j = 0;
for (i = 0; i < nitems; i++) {
items[i].label = argv[j++];
items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10);
items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10);
items[i].init = argv[j++];
items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10);
items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10);
fieldlen = (int)strtol(argv[j++], NULL, 10);
items[i].fieldlen = abs(fieldlen);
valuelen = (int)strtol(argv[j++], NULL, 10);
items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
flags = (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
items[i].flags = flags;
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
}
output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items);
print_form_items(output, nitems, items);
free(items);
return (output);
}
int inputbox_builder(BUILDER_ARGS)
{
int output;
struct bsddialog_formitem item;
if (argc > 1)
error_args("--inputbox", argc - 1, argv + 1);
item.label = "";
item.ylabel = 0;
item.xlabel = 0;
item.init = argc > 0 ? argv[0] : "";
item.yfield = 0;
item.xfield = 0;
item.fieldlen = 1;
item.maxvaluelen = max_input_form_opt;
item.flags = BSDDIALOG_FIELDNOCOLOR;
item.flags |= BSDDIALOG_FIELDCURSOREND;
item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = "";
output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item);
return (output);
}
int mixedform_builder(BUILDER_ARGS)
{
int output;
unsigned int i, j, formheight, nitems, sizeitem;
struct bsddialog_formitem *items;
if (argc < 1)
exit_error("--mixedform missing <formheight>", true);
formheight = (u_int)strtoul(argv[0], NULL, 10);
argc--;
argv++;
sizeitem = item_bottomdesc_opt ? 10 : 9;
if (argc % sizeitem != 0)
exit_error("--mixedform bad number of arguments items", true);
nitems = argc / sizeitem;
if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
exit_error("cannot allocate memory for form items", false);
j = 0;
for (i = 0; i < nitems; i++) {
items[i].label = argv[j++];
items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10);
items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10);
items[i].init = argv[j++];
items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10);
items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10);
items[i].fieldlen = (u_int)strtoul(argv[j++], NULL, 10);
items[i].maxvaluelen = (u_int)strtoul(argv[j++], NULL, 10);
items[i].flags = (u_int)strtoul(argv[j++], NULL, 10);
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
}
output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items);
print_form_items(output, nitems, items);
free(items);
return (output);
}
int passwordbox_builder(BUILDER_ARGS)
{
int output;
struct bsddialog_formitem item;
if (argc > 1)
error_args("--passwordbox", argc - 1, argv + 1);
item.label = "";
item.ylabel = 0;
item.xlabel = 0;
item.init = argc > 0 ? argv[0] : "";
item.yfield = 0;
item.xfield = 0;
item.fieldlen = 1;
item.maxvaluelen = max_input_form_opt;
item.flags = BSDDIALOG_FIELDHIDDEN;
item.flags |= BSDDIALOG_FIELDNOCOLOR;
item.flags |= BSDDIALOG_FIELDCURSOREND;
item.flags |= BSDDIALOG_FIELDEXTEND;
item.bottomdesc = "";
output = bsddialog_form(conf, text, rows, cols, 1, 1, &item);
print_form_items(output, 1, &item);
return (output);
}
int passwordform_builder(BUILDER_ARGS)
{
int output, fieldlen, valuelen;
unsigned int i, j, flags, formheight, nitems, sizeitem;
struct bsddialog_formitem *items;
if (argc < 1)
exit_error("--passwordform missing <formheight>", true);
formheight = (u_int)strtoul(argv[0], NULL, 10);
argc--;
argv++;
sizeitem = item_bottomdesc_opt ? 9 : 8;
if (argc % sizeitem != 0)
exit_error("--passwordform bad arguments items number", true);
flags = BSDDIALOG_FIELDHIDDEN;
nitems = argc / sizeitem;
if ((items = calloc(nitems, sizeof(struct bsddialog_formitem))) == NULL)
exit_error("cannot allocate memory for form items", false);
j = 0;
for (i = 0; i < nitems; i++) {
items[i].label = argv[j++];
items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10);
items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10);
items[i].init = argv[j++];
items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10);
items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10);
fieldlen = (int)strtol(argv[j++], NULL, 10);
items[i].fieldlen = abs(fieldlen);
valuelen = (int)strtol(argv[j++], NULL, 10);
items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
items[i].flags = flags;
items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : "";
}
output = bsddialog_form(conf, text, rows, cols, formheight, nitems,
items);
print_form_items(output, nitems, items);
free(items);
return (output);
}