diff options
author | Alfonso S. Siciliano <asiciliano@FreeBSD.org> | 2022-09-25 13:04:33 +0000 |
---|---|---|
committer | Alfonso S. Siciliano <asiciliano@FreeBSD.org> | 2022-09-25 13:04:33 +0000 |
commit | 9f24fda5a8e7ab8243e71473c7e2dc98b4877e64 (patch) | |
tree | cf0c83c2ef1a564eb8bd492fde38c52a9fcdfca0 | |
parent | 2c9fd7655ba54e7239f528e1af9fe09662de9b03 (diff) |
contrib/bsddialog: Import version 0.4vendor/bsddialog/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.
-rw-r--r-- | .gitignore | 27 | ||||
-rw-r--r-- | CHANGELOG | 70 | ||||
-rw-r--r-- | GNUMakefile | 4 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README.md | 26 | ||||
-rw-r--r-- | bsddialog.1 | 170 | ||||
-rw-r--r-- | bsddialog.c | 1353 | ||||
-rw-r--r-- | examples_library/calendar.c | 55 | ||||
-rwxr-xr-x | examples_library/compile | 2 | ||||
-rw-r--r-- | examples_library/form.c | 4 | ||||
-rw-r--r-- | examples_utility/calendar.sh | 34 | ||||
-rwxr-xr-x | examples_utility/timebox.sh | 3 | ||||
-rw-r--r-- | lib/GNUMakefile | 10 | ||||
-rw-r--r-- | lib/Makefile | 6 | ||||
-rw-r--r-- | lib/barbox.c | 2 | ||||
-rw-r--r-- | lib/bsddialog.3 | 33 | ||||
-rw-r--r-- | lib/bsddialog.h | 10 | ||||
-rw-r--r-- | lib/calendarbox.c | 520 | ||||
-rw-r--r-- | lib/formbox.c | 29 | ||||
-rw-r--r-- | lib/lib_util.c | 14 | ||||
-rw-r--r-- | lib/lib_util.h | 3 | ||||
-rw-r--r-- | lib/libbsddialog.c | 4 | ||||
-rw-r--r-- | lib/menubox.c | 50 | ||||
-rw-r--r-- | lib/messagebox.c | 42 | ||||
-rw-r--r-- | lib/theme.c | 1 | ||||
-rw-r--r-- | lib/timebox.c | 20 | ||||
-rw-r--r-- | util_theme.c | 79 | ||||
-rw-r--r-- | util_theme.h | 7 |
28 files changed, 1735 insertions, 847 deletions
diff --git a/.gitignore b/.gitignore index 10a6663fbb47..8b8ec9d4ae0b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,24 @@ bsddialog +.depend* *.o -*~ +*.so* *.a -examples_library/buildlist +*.gz +*.core +*~ +BSDDIALOG.geany +BSDDIALOG.tags +examples_library/calendar examples_library/checklist examples_library/datebox examples_library/form -examples_library/formw -examples_library/margin +examples_library/infobox examples_library/menu examples_library/mixedlist -examples_library/radiolist -examples_library/theme -examples_library/treeview -examples_library/infobox examples_library/msgbox examples_library/pause +examples_library/radiolist examples_library/rangebox -examples_library/sade +examples_library/theme examples_library/timebox examples_library/yesno -examples_library/u_msgbox -*.gz -lib/libbsddialog.so* -BSDDIALOG.geany -BSDDIALOG.tags -*.core -freebsd-lab/ diff --git a/CHANGELOG b/CHANGELOG index d6de6928c111..883fe1016d01 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,17 +1,68 @@ +2022-09-24 Version 0.4 + + Utility: + * add: --normal-screen to set normal mode. + * add: --alternate-screen to set alternate mode. + * add: --keep-tite as --alternate-screen alias. + * add: --and-dialog to build other dialogs. + * add: --and-widget as --and-dialog alias. + * add: --no-names (--no-tags becames its alias). + * add: --no-descriptions (--no-items becames its alias). + * add: --help-print-name (--help-tags becames its alias). + * add: --item-bottom-desc (--item-help becames its alias). + * add: --cr-wrap (was partially implemented) to keep '\n' with "\n". + * add: --text-unchanged to avoid default modification. + * add: --tab-escape enables "\t" in text. + * add: --clear-screen to clear the screen. + * add: --clear-dialog to clear the dialog (was --clear). + * add: --calendar dialog to select a date. + * add: DIAGNOSTICS messages for bad arguments number. + * add: DIAGNOSTICS messages for missing and unexpected options. + * change: --clear becames alias for --clear-screen. + * change: --print-maxsize format output. + * change: --menu, --radiolist, --checklist and --treeview output. + - no printed items with Cancel or ESC. + - --separator prints <sepstr> before each item except HELP. + - --separator and --separate-output print <sepstr> after each item. + - quoted item name/desc only when needed. + - --menu avoids to print selected item after focused HELP item. + * change: text default modification. + - without a "\n": '\t' -> space, '\n' -> '\n', trim spaces. + - with a "\n": '\t' -> space, '\n' -> space, "\n" -> '\n', no trim. + - delete '\n' after "\n" (also with --cr-wrap). + * change: --datebox input and output format yy/mm/dd -> dd/mm/yy. + * delete: --no-collapse (partially implemented). + * delete: --no-nl-expand (partially implemented). + * delete: --trim (partially implemented). + + Library: + * add: bsddialog_msgbox() HOME, END, PPAGE and NPAGE keys. + * add: bsddialog_yesno() HOME, END, PPAGE and NPAGE keys. + * add: bsddialog_menu() SPACE key (equivalent to ENTER). + * add: bsddialog_calendar() to select a date. + * change: rename enum bsddialog_grouptype -> enum bsddialog_menutype. + * change: fixed-menurows becames at most menurows (depending on text). + * change: fixed-rows becames at most rows, min(rows, screenH - shadow). + * change: fixed-cols becames at most cols, min(cols, screenW - shadow). + * delete: undocumented internal bsddialog_menuitem.depth factor (was 2). + + 2022-08-29 Version 0.3 Utility: * add: --textbox accepts options for the first button. - * add: --columns-per-row option for text autosizing. - * add: --load-theme option to read and set a custom theme at runtime. - * add: --save-theme option to save current theme. - * add: --bikeshed option for random settings. + * add: --columns-per-row for text autosizing. + * add: --load-theme to read and set a custom theme at runtime. + * add: --save-theme to save current theme. + * add: --bikeshed for random settings. * add: --switch-buttons enables focus switching: buttons / input components. Available for: --form, --inputbox, --mixedform, --passwordform, --passwordbox, --timebox and --datebox. * change: rename --esc-cancelvalue to --esc-return-cancel. * change: form field value is printed like multibyte charachter string, previously widechar string. + * change: --timebox output with zero padding. + * change: --datebox output mm and dd with zero padding. * fix: --hline with empty string. * fix: avoid to overlay the backtitle by setting a top margin. * fix: avoid to overlay down shadow with menus and forms bottomdesc @@ -25,8 +76,8 @@ * add: conf.text.cols_per_row to set a ratio for text autosizing. * add: timebox and datebox arrows and focus background for boxes. * add: timebox and datebox UP key to switch focus. - * add: bsddialog_init_notheme() in bsddialo_theme.h. - * add: bsddialog_hascolors() in bsddialo_theme.h. + * add: bsddialog_init_notheme() in bsddialog.h. + * add: bsddialog_hascolors() in bsddialog_theme.h. * add: theme.form.bottomdesccolor and theme.menu.bottomdesccolor. * add: conf.button.always_active to disable buttons/input-boxes switch. * add: dynamic buttons margin. @@ -60,8 +111,8 @@ - add: formheight autosizing. - add: dynamic item position. * fix: bsddialog_gauge() with fd < 0. - * fix: internal segmentation fault with disabled shadow. * fix: bsddialog_gauge() refresh new text. + * fix: internal segmentation fault with disabled shadow. * fix: center position without shadow. * fix: bsddialog_infobox() with zero text length. * fix: text wrapping with more than 1024 words. @@ -92,7 +143,7 @@ * change: theme.button.[left|right]ch -> theme.button.[left|right]delim. * change: theme.button.space -> theme.button.hmargin. * change: theme.menu.arrowcolor -> theme.dialog.arrowcolor. - * change: default menu item depth 4 -> 2. + * change: internal bsddialog_menuitem.depth factor 4 -> 2. * fix: disable HOME, PPAGE, END and NPAGE keys in bsddialog_form(). * fix: visible cursor for timebox.c and form.c in VM VirtualBox. * fix: mixedlist, center position of separator with big pad. @@ -106,7 +157,7 @@ 2022-01-27 Version 0.1 - * Common-Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>, + * Options: --ascii-lines, --backtitle <backtitle>, --begin-x <x>, --begin-y <y>, --cancel-label <label>, --clear, --colors, --cr-wrap, --date-format <format>, --defaultno, --default-button <label>, --default-no, --default-item <name>, --disable-esc, @@ -131,4 +182,3 @@ --passwordbox, --passwordform, --pause, --radiolist, --rangebox, --textbox, --timebox, --treeview, --yesno. * Manuals: bsddialog.1, bsddialog.3. - diff --git a/GNUMakefile b/GNUMakefile index d57c6248d02d..7da4d64deecf 100644 --- a/GNUMakefile +++ b/GNUMakefile @@ -8,8 +8,8 @@ SOURCES= bsddialog.c util_theme.c OBJECTS= $(SOURCES:.c=.o) LIBPATH= ./lib LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so -CFLAGS= -Wall -Wextra -Wno-unused-parameter -I$(LIBPATH) -LDFLAGS= -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog +CFLAGS= -Wall -Wextra -I$(LIBPATH) +LDFLAGS= -ltinfo -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog RM = rm -f all : $(OUTPUT) @@ -9,13 +9,13 @@ OBJECTS= ${SOURCES:.c=.o} LIBPATH= ${.CURDIR}/lib LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so -CFLAGS+= -I${LIBPATH} -std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter +CFLAGS+= -I${LIBPATH} -std=gnu99 -Wall -Wextra -Werror # `make -DDEBUG` .if defined(DEBUG) CFLAGS= -g -Wall -I${LIBPATH} LIBDEBUG= -DDEBUG .endif -LDFLAGS+= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog +LDFLAGS+= -ltinfow -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog BINDIR= /usr/local/bin MAN= ${OUTPUT}.1 diff --git a/README.md b/README.md index 016995b232ae..59af7072e7f5 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,8 @@ -# BSDDialog 0.3 +# BSDDialog 0.4 This project provides **bsddialog** and **libbsddialog**, an utility and a library to build scripts and tools with TUI dialogs and widgets. - - -## Intro - -Briefly: -<https://www.freebsd.org/status/report-2021-04-2021-06/bsddialog/> - -Utility: -<https://alfonsosiciliano.gitlab.io/posts/2021-12-07-bsddialog.html> - -Library: -<https://alfonsosiciliano.gitlab.io/posts/2022-01-16-libbsddialog.html> - -Screenshots: -<https://www.flickr.com/photos/alfonsosiciliano/albums/72157720215006074> +[Screenshots](https://www.flickr.com/photos/alfonsosiciliano/albums/72157720215006074). ## Getting Started @@ -48,9 +34,9 @@ Output: **Dialogs:** ---checklist, --datebox, --form, --gauge, --inputbox, --menu, --mixedform, ---mixedgauge, --msgbox, --passwordbox, --passwordform, --pause, --radiolist, ---rangebox, --textbox, --timebox, --treeview, --yesno. +--calendar, --checklist, --datebox, --form, --gauge, --infobox, --inputbox, +--menu, --mixedform, --mixedgauge, --msgbox, --passwordbox, --passwordform, +--pause, --radiolist, --rangebox, --textbox, --timebox, --treeview, --yesno. **Manual** @@ -72,6 +58,7 @@ Output: and [Examples](https://gitlab.com/alfix/bsddialog/-/tree/main/examples_utility) in the _Public Domain_ to build new projects: ``` +% sh ./examples_utility/calendar.sh % sh ./examples_utility/checklist.sh % sh ./examples_utility/form.sh % sh ./examples_utility/gauge.sh @@ -109,6 +96,7 @@ in the _Public Domain_ to build new projects: ``` % cd examples_library % sh compile +% ./calendar % ./checklist % ./datebox % ./form diff --git a/bsddialog.1 b/bsddialog.1 index 0bf8dd9dc3af..759fe6dc3fff 100644 --- a/bsddialog.1 +++ b/bsddialog.1 @@ -1,4 +1,5 @@ .\" +.\" .\" Copyright (c) 2021-2022 Alfonso Sabato Siciliano .\" .\" Redistribution and use in source and binary forms, with or without @@ -22,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 29, 2022 +.Dd September 23, 2022 .Dt BSDDIALOG 1 .Os .Sh NAME @@ -34,12 +35,19 @@ .Nm .Fl Fl version .Nm -.Op Fl Fl common-option +.Op Fl Fl option .Fl Fl dialog .Ar text .Ar rows .Ar cols -.Op Ar dialog-parameter +.Op Ar dialog-argument +.Nm +.Fl Fl dialog1 +.Ar ... +.Oo Fl Fl and-dialog +.Fl Fl dialog2 +.Ar ... +.Oc ... .Sh DESCRIPTION The .Nm bsddialog @@ -51,21 +59,24 @@ The options and .Fl Fl version print the list of options and the version, respectively, then exit. +.Fl Fl and-dialog +builds another dialog unless the previous one returns Error, ESC or Cancel. .Pp -The following options are available for each dialog. .Ar text -is a message printed inside the dialog, except for -.Fl Fl textbox -described later. +is a message printed inside the dialog. .Ar rows and .Ar cols are the height and width, 0 for autosize and -1 for fullscreen. +.Pp The possible input got from the user interface is printed to standard error. -.Ss Common options +.Ss Options The following options can change the default behavior of the utility and are common to some dialog. .Bl -tag -width Ds +.It Fl Fl alternate-screen +If available set alternate screen mode, see +.Xr terminfo 5 . .It Fl Fl ascii-lines Ascii characters to draw lines. .It Fl Fl backtitle Ar backtitle @@ -85,8 +96,10 @@ Zero padding with time or date output. Label for the .Dq Cancel button. -.It Fl Fl clear +.It Fl Fl clear-dialog Hide the dialog at exit. +.It Fl Fl clear-screen +Clear the screen, after the dialog exit if a dialog is built. .It Fl Fl colors Enable highlights for text, the following sequences are considered escapes: .Bl -column -compact @@ -125,13 +138,19 @@ restore normal text. Try to set the number of columns for a row of text with autosizing; default .Dv 10 . .It Fl Fl cr-wrap -Replace new line with a space in -.Ar text . +Keep new line in +.Ar text +also if it constains a +.Dq \en , +see +.Fl Fl text-unchanged . .It Fl Fl date-format Ar format String accepted by .Xr strftime 3 to customize the output of -.Fl Fl datebox . +.Fl Fl datebox +and +.Fl Fl calendar .It Fl Fl default-button Ar label Focus on the button with .Ar label @@ -146,18 +165,12 @@ Focus on or .Dq \&No button on startup. -.It Fl Fl defaultno -Equivalent to -.Fl Fl default-no . .It Fl Fl disable-esc Disable ESC key to quit. .It Fl Fl esc-return-cancel -Exits with the +ESC key returns .Dq Cancel -button value if the ESC key is pressed. -.It Fl Fl exit-label Ar label -Equivalent to -.Fl Fl ok-label . +button value. .It Fl Fl extra-button Add a button with .Dq Extra @@ -184,14 +197,14 @@ Set for .Dq Help button. +.It Fl Fl help-print-name +Print the name of the focused item if the Help button is pressed also +with +.Fl Fl item-bottom-desc . .It Fl Fl help-status Print also the selected items if the .Dq Help button is pressed. -.It Fl Fl help-tags -Print the name of the focused item if the Help button is pressed also -with -.Fl Fl item-help . .It Fl Fl hfile Ar filename Open .Ar filename @@ -208,11 +221,11 @@ Do not exit with unknown options. Print .Sq * to hide passwords while typing; whitespace otherwise. +.It Fl Fl item-bottom-desc +Set a help string for each item of a Checklist, Form, Menu, Mixedform, +Passwordform, Radiolist and Treeview to display at the bottom screen side. .It Fl Fl item-depth Specify a margin for items, available for Checklist, Menu and Radiolist. -.It Fl Fl item-help -Set a help string for each element of a Checklist, Form, Menu, Mixedform, -Passwordform, Radiolist and Treeview to display at the bottom screen side. .It Fl Fl item-prefix Set a string to prefix each item of a Checklist, Menu, Radiolist or Treeview. .It Fl Fl load-theme Ar file @@ -228,59 +241,46 @@ default 2048. Do not show .Dq Cancel button. -.It Fl Fl no-collapse -Do not replace a TAB character with a space in -.Ar text . -.It Fl Fl no-items +.It Fl Fl no-descriptions Do not display items desciption, for Checklist, Menu, Radiolist or Treeview. -.It Fl Fl no-label Ar label -Equivalent to -.Fl Fl cancel-label . .It Fl Fl no-lines Do not draw borders and lines. -.It Fl Fl no-nl-expand -do not consider the sequence -.Dq \en -like new line. +.It Fl Fl no-names +Do not display items name, for Checklist, Menu and Radiolist. .It Fl Fl no-ok Do not draw .Dq OK button. .It Fl Fl no-shadow No not draw the shadow of the dialog. -.It Fl Fl no-tags -Do not display items name, for Checklist, Menu and Radiolist. -.It Fl Fl nocancel -Equivalent to -.Fl Fl no-cancel . -.It Fl Fl nook -Equivalent to -.Fl Fl no-ok . .It Fl Fl ok-label Ar label Set .Ar label for .Dq OK button. +.It Fl Fl normal-screen +If available set normal screen mode, see +.Xr terminfo 5 . .It Fl Fl output-fd Ar fd Print input from user interface to the specified file descriptor. .It Fl Fl output-separator Ar sep Set a sepator for the items in output, default whitespace. .It Fl Fl print-maxsize Screen size. +This option can be used without a dialog. .It Fl Fl print-size Print Dialog height and widget at exit. .It Fl Fl print-version Print version. +This option can be used without a dialog. .It Fl Fl quoted Quote items in output, default only when necessary. .It Fl Fl save-theme Ar file Save the current theme. +This option can be used without a dialog. .It Fl Fl separate-output Separate selected items with a new line and avoid to quote. -.It Fl Fl separator Ar sep -Equivalent to -.Fl Fl output-separator . .It Fl Fl shadow Show a pseudo shadow for the dialog, enabled by default. .It Fl Fl single-quoted @@ -302,12 +302,29 @@ Suitable for: .Fl Fl mixedform , .Fl Fl passwordbox , .Fl Fl passwordform , -.Fl Fl timebox +.Fl Fl timebox , +.Fl Fl calendar and .Fl Fl datebox . +.It Fl Fl tab-escape +Replace +.Dq \et +with a tab in +.Ar text . .It Fl Fl tab-len Ar spaces Number of spaces to print a TAB in .Ar text . +.It Fl Fl text-unchanged +By default the +.Ar text +is changed before to be printed. +If it contains at least a +.Dq \en +each new line and TAB is converted to a space, subsequent spaces are merged. +Otherwise new line characters are preserved and a TAB becomes a space. +This option disable the +.Ar text +modification. .It Fl Fl theme Ar theme Set a graphical style: blackwhite, bsddialog, flat or dialog. .It Fl Fl time-format Ar format @@ -317,16 +334,12 @@ to customize the output of .Fl Fl timebox . .It Fl Fl title Ar title Dialog title. -.It Fl Fl trim -remove consecutive spaces in -.Ar text . -.It Fl Fl yes-label Ar label -Equivalent to -.Fl Fl ok-label . .El .Ss Dialogs The following dialogs are available: .Bl -tag -width Ds +.It Fl Fl calendar Ar text Ar rows Ar cols Op Ar day Ar month Ar year +Dialog to select a date. .It Fl Fl checklist Ar text Ar rows Ar cols Ar menurows Oo Ar name Ar desc \ Ar status Oc ... Checklist to select some item from a list via the SPACE key. @@ -342,7 +355,7 @@ or The names of the selected items are printed to standard error. .Ar menurows is the graphical height of the list, 0 for autosize. -.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar year Ar month Ar day +.It Fl Fl datebox Ar text Ar rows Ar cols Op Ar day Ar month Ar year Dialog to select a date. .It Fl Fl form Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \ Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxletters Oc ... @@ -393,7 +406,7 @@ Dialog to get a string in input, .Ar init is the default value. .It Fl Fl menu Ar text Ar rows Ar cols Ar menurows Oo Ar name desc Oc ... -Builds a menu to select an item from a list. +Builds a menu to select an item from a list, Space key is equivalent to Enter. An item has a .Ar name and a @@ -461,6 +474,7 @@ a blank line, Dialog to diplay a message without the .Dq Cancel button. +UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate the text. .It Fl Fl passwordbox Ar text Ar rows Ar cols Op Ar init Dialog to get a password, .Ar init @@ -522,6 +536,7 @@ buttons are renamed .Dq Yes and .Dq \&No . +UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate the text. .El .Sh EXIT STATUS The @@ -574,6 +589,10 @@ Checklist: Form: .Dl bsddialog --form Form 0 0 0 L1: 0 0 X 0 4 20 25 L2: 1 0 Y 1 4 20 25 .Pp +Multi-dialog: +.Dl bsddialog --normal-screen --begin-y 1 --yesno Continue? 0 0 \e \ +--and-dialog --begin-y 10 --infobox Yes 0 0 +.Pp Bikeshed: .Dl bsddialog --bikeshed --inputbox Example 0 0 .Pp @@ -614,6 +633,27 @@ do i=`expr $i + 1` done | bsddialog --title Gauge --gauge "Starting..." 10 70 .Ed +.Sh COMPATIBILITY +Outdated options are retained for compatibility, properly equivalent options are +used: +.Bd -literal -offset indent -compact +Obsolete Equivalent +--and-widget --and-dialog +--calendar <text> 2 <cols> --calendar <text> 0 <cols> +--clear --clear-screen +--defaultno --default-no +--exit-label --ok-label +--help-tags --help-print-name +--item-help --item-bottom-desc +--keep-tite --alternate-screen +--no-items --no-descriptions +--no-label --cancel-label +--no-tags --no-names +--nocancel --no-cancel +--nook --no-ok +--separator --output-separator +--yes-label --ok-label +.Ed .Sh SEE ALSO .Xr bsddialog 3 .Sh HISTORY @@ -633,7 +673,8 @@ provides a subset of the functionality described in the manual. The following features were reimplemented: .Pp -Common options: +Options: +.Fl Fl and-widget , .Fl Fl ascii-lines , .Fl Fl backtitle , .Fl Fl cancel-label , @@ -658,14 +699,13 @@ Common options: .Fl Fl ignore , .Fl Fl insecure , .Fl Fl item-help , +.Fl Fl keep-tite , .Fl Fl max-input , .Fl Fl no-cancel , .Fl Fl nocancel , -.Fl Fl no-collapse , .Fl Fl no-items , .Fl Fl no-label , .Fl Fl no-lines , -.Fl Fl no-nl-expand , .Fl Fl no-ok , .Fl Fl nook , .Fl Fl no-shadow , @@ -687,11 +727,11 @@ Common options: .Fl Fl tab-len , .Fl Fl time-format , .Fl Fl title , -.Fl Fl trim , .Fl Fl version , .Fl Fl yes-label . .Pp Dialogs: +.Fl Fl calendar , .Fl Fl checklist , .Fl Fl form , .Fl Fl gauge , @@ -715,8 +755,10 @@ Some feature differs in input, output, or behavior. Compatibility is not a priority for future development. .Sh THANKS TO .An Baptiste Daroussin -.Aq Mt bapt@FreeBSD.org -and +.Aq Mt bapt@FreeBSD.org , .An \&Ed Maste .Aq Mt emaste@FreeBSD.org +and +.An Juraj Lutter +.Aq Mt otis@FreeBSD.org for suggestions, help, and testing. diff --git a/bsddialog.c b/bsddialog.c index bfd6d8dbc5b7..b9b2810dc62f 100644 --- a/bsddialog.c +++ b/bsddialog.c @@ -33,6 +33,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <term.h> #include <time.h> #include <unistd.h> @@ -41,17 +42,18 @@ #include "util_theme.h" -#define BSDDIALOG_VERSION "0.3" - enum OPTS { - /* Common options */ - ASCII_LINES = '?' + 1, + /* Options */ + ALTERNATE_SCREEN = '?' + 1, + AND_DIALOG, + ASCII_LINES, BACKTITLE, BEGIN_X, BEGIN_Y, BIKESHED, CANCEL_LABEL, - CLEAR, + CLEAR_DIALOG, + CLEAR_SCREEN, COLORS, COLUMNS_PER_ROW, CR_WRAP, @@ -66,29 +68,27 @@ enum OPTS { EXTRA_LABEL, GENERIC_BUTTON1, GENERIC_BUTTON2, - HELP, HELP_BUTTON, HELP_LABEL, + HELP_PRINT_NAME, HELP_STATUS, - HELP_TAGS, HFILE, HLINE, HMSG, IGNORE, INSECURE, + ITEM_BOTTOM_DESC, ITEM_DEPTH, - ITEM_HELP, ITEM_PREFIX, LOAD_THEME, MAX_INPUT, NO_CANCEL, - NO_COLLAPSE, - NO_ITEMS, + NO_DESCRIPTIONS, NO_LINES, - NO_NL_EXPAND, + NO_NAMES, NO_OK, NO_SHADOW, - NO_TAGS, + NORMAL_SCREEN, OK_LABEL, OUTPUT_FD, OUTPUT_SEPARATOR, @@ -104,13 +104,14 @@ enum OPTS { STDERR, STDOUT, SWITCH_BUTTONS, + TAB_ESCAPE, TAB_LEN, + TEXT_UNCHANGED, THEME, TIME_FORMAT, TITLE, - TRIM, - VERSION, /* Dialogs */ + CALENDAR, CHECKLIST, DATEBOX, FORM, @@ -132,28 +133,156 @@ enum OPTS { 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, item_bottomdesc_opt, item_output_sepnl_opt; -static bool item_singlequote_opt, list_items_on_opt, item_tag_help_opt; -static bool item_always_quote_opt, item_depth_opt; -static char *item_output_sep_opt, *item_default_opt; +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, *time_fmt_opt; +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; -bool bikeshed_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 */ -static void sigint_handler(int sig); -static void -custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim, - char *text, char *buf); -static void errorexit(char *errbuf); +#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, char *errbuf + 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); @@ -174,258 +303,233 @@ 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 [--<common-opts>] --<dialog> <text> <rows> " - "<cols> [--<dialog-opts>]\n"); + printf(" bsddialog [--<opt>] --<dialog> <text> <rows> <cols> " + "[<arg>]\n"); + printf(" bsddialog --<dialog1> ... [--and-dialog --<dialog2> " + "...] ...\n"); printf("\n"); - printf("Common Options:\n"); - printf("--ascii-lines, --backtitle <backtitle>, --begin-x <x>, " - "--begin-y <y>, --bikeshed, --cancel-label <label>, --clear, " - "--colors, --columns-per-row <columns>, --cr-wrap, " - "--date-format <format>, --default-button <label>, " - "--default-item <name>, --default-no, --disable-esc, " - "--esc-return-cancel, --exit-label <label>, --extra-button, " - "--extra-label <label>, --generic-button1 <label>, " - "--generic-button2 <label>, --help, --help-button, " - "--help-label <label>, --help-status, --help-tags, --hfile <file>, " - "--hline <string>, --hmsg <string>, --ignore, --insecure, " - "--item-depth, --item-help, --item-prefix, --load-theme <file>, " - "--max-input <size>, --no-cancel, --no-collapse, --no-items, " - "--no-label <label>, --no-lines, --no-nl-expand, --no-ok, " - "--no-shadow, --no-tags, --ok-label <label>, --output-fd <fd>, " - "--output-separator <sep>, --print-maxsize, --print-size, " - "--print-version, --quoted, --save-theme <file>, " - "--separate-output, --separator <sep>, --shadow, --single-quoted, " - "--sleep <secs>, --stderr, --stdout, --tab-len <spaces>, " - "--switch-buttons, --theme <blackwhite|bsddialog|flat|dialog>, " - "--time-format <format>, --title <title>, --trim, --version, " - "--yes-label <label>.\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("--checklist <text> <rows> <cols> <menurows> [<name> <desc> " + 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> [<yy> <mm> <dd>]\n"); - printf("--form <text> <rows> <cols> <formrows> [<label> <ylabel> " + 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> " + 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> " + 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> " + 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> " + 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> " + 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(" --yesno <text> <rows> <cols>\n"); printf("\n"); printf("See 'man 1 bsddialog' for more information.\n"); } -int main(int argc, char *argv[argc]) +static int parseargs(int argc, char **argv, struct bsddialog_conf *conf) { - bool cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, trim_opt; - bool esc_return_cancel_opt, ignore_opt, print_maxsize_opt; - bool textfromfile; - int input, rows, cols, retval, getH, getW; - int (*dialogbuilder)(BUILDER_ARGS) = NULL; - enum bsddialog_default_theme theme_opt; - char *text, *backtitle_opt, *loadthemefile, *savethemefile; - char errorbuilder[1024]; + int arg, parsed, i; struct winsize ws; - struct bsddialog_conf conf; - setlocale(LC_ALL, ""); + 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; - 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 = BSDDIALOG_THEME_FLAT; + theme_opt = -1; output_fd_opt = STDERR_FILENO; - print_maxsize_opt = false; ignore_opt = false; - cr_wrap_opt = no_collapse_opt = no_nl_expand_opt = trim_opt = false; + cr_wrap_opt = false; + tab_escape_opt = false; + text_unchanged_opt = false; esc_return_cancel_opt = false; - textfromfile = false; bikeshed_opt = false; - errorbuilder[0] = '\0'; savethemefile = NULL; loadthemefile = NULL; - - item_output_sepnl_opt = item_singlequote_opt = false; - item_prefix_opt = item_bottomdesc_opt = item_depth_opt = false; - list_items_on_opt = item_tag_help_opt = false; + 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 = time_fmt_opt = NULL; - - max_input_form_opt = 0; - - /* options descriptor */ - struct option longopts[] = { - /* common options */ - {"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}, - {"colors", no_argument, NULL, COLORS}, - {"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", no_argument, NULL, HELP}, - {"help-button", no_argument, NULL, HELP_BUTTON}, - {"help-label", required_argument, NULL, HELP_LABEL}, - {"help-status", no_argument, NULL, HELP_STATUS}, - {"help-tags", no_argument, NULL, HELP_TAGS}, - {"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-depth", no_argument, NULL, ITEM_DEPTH}, - {"item-help", no_argument, NULL, ITEM_HELP}, - {"item-prefix", no_argument, NULL, ITEM_PREFIX}, - {"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-collapse", no_argument, NULL, NO_COLLAPSE}, - {"no-items", no_argument, NULL, NO_ITEMS}, - {"no-label", required_argument, NULL, CANCEL_LABEL}, - {"no-lines", no_argument, NULL, NO_LINES}, - {"no-nl-expand", no_argument, NULL, NO_NL_EXPAND}, - {"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_TAGS}, - {"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}, - {"columns-per-row", required_argument, NULL, COLUMNS_PER_ROW}, - {"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-len", required_argument, NULL, TAB_LEN}, - {"theme", required_argument, NULL, THEME}, - {"time-format", required_argument, NULL, TIME_FORMAT}, - {"title", required_argument, NULL, TITLE}, - {"trim", no_argument, NULL, TRIM}, - {"version", no_argument, NULL, VERSION}, - {"yes-label", required_argument, NULL, OK_LABEL}, - /* Dialogs */ - {"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} - }; - - while ((input = getopt_long(argc, argv, "", longopts, NULL)) != -1) { - switch (input) { - /* Common options */ + 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; + conf->ascii_lines = true; break; case BACKTITLE: backtitle_opt = optarg; - if (conf.y == BSDDIALOG_CENTER) - conf.auto_topmargin = 2; + 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) { - printf("Error: --begin-x %d < %d", - conf.x, BSDDIALOG_CENTER); - return (255); - } + 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) { - printf("Error: --begin-y %d < %d", - conf.y, BSDDIALOG_CENTER); - return (255); - } - conf.auto_topmargin = 0; + 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; + conf->button.cancel_label = optarg; break; - case CLEAR: - conf.clear = true; + case CLEAR_DIALOG: + conf->clear = true; + break; + case CLEAR_SCREEN: + mandatory_dialog = false; + clear_screen_opt = true; break; case COLORS: - conf.text.highlight = true; + conf->text.highlight = true; break; case COLUMNS_PER_ROW: - conf.text.cols_per_row = + conf->text.cols_per_row = (u_int)strtoul(optarg, NULL, 10); break; case CR_WRAP: @@ -435,72 +539,69 @@ int main(int argc, char *argv[argc]) date_fmt_opt = optarg; break; case DEFAULT_BUTTON: - conf.button.default_label = optarg; + conf->button.default_label = optarg; break; case DEFAULT_ITEM: item_default_opt = optarg; break; case DEFAULT_NO: - conf.button.default_cancel = true; + conf->button.default_cancel = true; break; case DISABLE_ESC: - conf.key.enable_esc = false; + conf->key.enable_esc = false; break; case ESC_RETURNCANCEL: esc_return_cancel_opt = true; break; case EXIT_LABEL: - conf.button.ok_label = optarg; + conf->button.ok_label = optarg; break; case EXTRA_BUTTON: - conf.button.with_extra = true; + conf->button.with_extra = true; break; case EXTRA_LABEL: - conf.button.extra_label = optarg; + conf->button.extra_label = optarg; break; case GENERIC_BUTTON1: - conf.button.generic1_label = optarg; + conf->button.generic1_label = optarg; break; case GENERIC_BUTTON2: - conf.button.generic2_label = optarg; + conf->button.generic2_label = optarg; break; - case HELP: - usage(); - return (BSDDIALOG_OK); case HELP_BUTTON: - conf.button.with_help = true; + conf->button.with_help = true; break; case HELP_LABEL: - conf.button.help_label = optarg; + 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 HELP_TAGS: - item_tag_help_opt = true; - break; case HFILE: - conf.key.f1_file = optarg; + conf->key.f1_file = optarg; break; case HLINE: if (optarg[0] != '\0') - conf.bottomtitle = optarg; + conf->bottomtitle = optarg; break; case HMSG: - conf.key.f1_message = optarg; + conf->key.f1_message = optarg; break; case IGNORE: ignore_opt = true; break; case INSECURE: - conf.form.securech = '*'; + conf->form.securech = '*'; + break; + case ITEM_BOTTOM_DESC: + item_bottomdesc_opt = true; break; case ITEM_DEPTH: item_depth_opt = true; break; - case ITEM_HELP: - item_bottomdesc_opt = true; - break; case ITEM_PREFIX: item_prefix_opt = true; break; @@ -510,32 +611,29 @@ int main(int argc, char *argv[argc]) case MAX_INPUT: max_input_form_opt = (u_int)strtoul(optarg, NULL, 10); break; - case NO_ITEMS: - conf.menu.no_desc = true; - break; case NO_CANCEL: - conf.button.without_cancel = true; + conf->button.without_cancel = true; break; - case NO_COLLAPSE: - no_collapse_opt = true; + case NO_DESCRIPTIONS: + conf->menu.no_desc = true; break; case NO_LINES: - conf.no_lines = true; + conf->no_lines = true; break; - case NO_NL_EXPAND: - no_nl_expand_opt = true; + case NO_NAMES: + conf->menu.no_name = true; break; case NO_OK: - conf.button.without_ok = true; - break; - case NO_TAGS: - conf.menu.no_name = true; + conf->button.without_ok = true; break; case NO_SHADOW: - conf.shadow = false; + conf->shadow = false; + break; + case NORMAL_SCREEN: + screen_mode_opt = "rmcup"; break; case OK_LABEL: - conf.button.ok_label = optarg; + conf->button.ok_label = optarg; break; case OUTPUT_FD: output_fd_opt = (int)strtol(optarg, NULL, 10); @@ -547,29 +645,35 @@ int main(int argc, char *argv[argc]) item_always_quote_opt = true; break; case PRINT_MAXSIZE: - print_maxsize_opt = true; + 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; - conf.get_width = &getW; + conf->get_height = &getH_opt; + conf->get_width = &getW_opt; break; case PRINT_VERSION: - printf("bsddialog version %s\n", BSDDIALOG_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; + conf->shadow = true; break; case SINGLE_QUOTED: item_singlequote_opt = true; break; case SLEEP: - conf.sleep = (u_int)strtoul(optarg, NULL, 10); + conf->sleep = (u_int)strtoul(optarg, NULL, 10); break; case STDERR: output_fd_opt = STDERR_FILENO; @@ -578,10 +682,16 @@ int main(int argc, char *argv[argc]) output_fd_opt = STDOUT_FILENO; break; case SWITCH_BUTTONS: - conf.button.always_active = false; + 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); + 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) @@ -592,245 +702,313 @@ int main(int argc, char *argv[argc]) theme_opt = BSDDIALOG_THEME_FLAT; else if (strcasecmp(optarg, "dialog") == 0) theme_opt = BSDDIALOG_THEME_DIALOG; - else { - printf("Error: unknown theme\n"); - return (255); - } + else + exit_error("--theme: <unknown> theme", false); break; case TIME_FORMAT: time_fmt_opt = optarg; break; case TITLE: - conf.title = optarg; - break; - case TRIM: - trim_opt = true; + conf->title = optarg; break; - case VERSION: - printf("bsddialog %s (libbsddialog %s)\n", - BSDDIALOG_VERSION, LIBBSDDIALOG_VERSION); - return (BSDDIALOG_OK); /* 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; + 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; + 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; + conf->auto_downmargin = 1; break; case MENU: + if (dialogbuilder != NULL) + exit_error("unexpected --menu", true); dialogbuilder = menu_builder; - conf.auto_downmargin = 1; + conf->auto_downmargin = 1; break; case MIXEDFORM: + if (dialogbuilder != NULL) + exit_error("unexpected --mixedform", true); dialogbuilder = mixedform_builder; - conf.auto_downmargin = 1; + 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; + conf->auto_downmargin = 1; break; case PASSWORDFORM: + if (dialogbuilder != NULL) + exit_error("unexpected --passwordform", true); dialogbuilder = passwordform_builder; - conf.auto_downmargin = 1; + conf->auto_downmargin = 1; break; case RADIOLIST: + if (dialogbuilder != NULL) + exit_error("unexpected --radiolist", true); dialogbuilder = radiolist_builder; - conf.auto_downmargin = 1; + 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; - textfromfile = true; 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; + conf->auto_downmargin = 1; break; case YESNO: + if (dialogbuilder != NULL) + exit_error("unexpected --yesno", true); dialogbuilder = yesno_builder; break; - /* Error */ - default: + default: /* Error */ if (ignore_opt == true) break; - usage(); - return (255); + exit_error("--ignore to continue", true); } } - argc -= optind; - argv += optind; - - if (print_maxsize_opt) { - ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); - dprintf(output_fd_opt, "Screen size: (%d - %d)\n", - ws.ws_row, ws.ws_col); - if (argc == 0) - return (BSDDIALOG_OK); - } - if (argc < 3) { - usage(); - return (255); - } - if (textfromfile) /* textbox */ - text = argv[0]; - else { - if ((text = malloc(strlen(argv[0]) + 1)) == NULL) { - printf("Error: cannot allocate memory for text\n"); - return (255); - } - custom_text(cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, - trim_opt, argv[0], text); - } - rows = (int)strtol(argv[1], NULL, 10); - cols = (int)strtol(argv[2], NULL, 10); - argc -= 3; - argv += 3; - - /* bsddialog terminal mode */ - if (bsddialog_init() != 0) { - printf("Error: %s\n", bsddialog_geterror()); - return (255); - } + return (parsed); +} - signal(SIGINT, sigint_handler); +int main(int argc, char *argv[argc]) +{ + int i, rows, cols, retval, parsed, nargc, firstoptind; + char *text, **nargv, *pn; + struct bsddialog_conf conf; - if (theme_opt != BSDDIALOG_THEME_FLAT) - if (bsddialog_set_default_theme(theme_opt) != BSDDIALOG_OK) - errorexit(NULL); - if (loadthemefile != NULL) - if (loadtheme(loadthemefile, errorbuilder) != BSDDIALOG_OK) - errorexit(errorbuilder); - if (bikeshed_opt) - if (bikeshed(&conf, errorbuilder) != BSDDIALOG_OK) - errorexit(errorbuilder); - - if (backtitle_opt != NULL) - if( bsddialog_backtitle(&conf, backtitle_opt)) - errorexit(NULL); - - if (dialogbuilder != NULL) { - retval = dialogbuilder(&conf, text, rows, cols, argc, argv, - errorbuilder); - if (retval == BSDDIALOG_ERROR) - errorexit(errorbuilder); - } else - retval = BSDDIALOG_OK; + setlocale(LC_ALL, ""); - if (savethemefile != NULL) - if (savetheme(savethemefile, errorbuilder, BSDDIALOG_VERSION) != - BSDDIALOG_OK) - errorexit(errorbuilder); + in_bsddialog_mode = false; + mandatory_dialog = true; + firstoptind = optind; + pn = argv[0]; + retval = BSDDIALOG_OK; - bsddialog_end(); - /* end bsddialog terminal mode */ + 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); + } + } - if (textfromfile == false) - free(text); + while (true) { + parsed = parseargs(argc, argv, &conf); + nargc = argc - parsed; + nargv = argv + parsed; + argc = parsed - optind; + argv += optind; - if (conf.get_height != NULL && conf.get_width != NULL) - dprintf(output_fd_opt, "Dialog size: (%d - %d)\n", - *conf.get_height, *conf.get_width); + if (mandatory_dialog && dialogbuilder == NULL) + exit_error("expected a --<dialog>", true); - if (retval == BSDDIALOG_ESC && esc_return_cancel_opt) - retval = BSDDIALOG_CANCEL; + if (dialogbuilder == NULL && argc > 0) + error_args("(no --<dialog>)", argc, argv); - return (retval); -} + /* --print-maxsize or --print-version */ + if (mandatory_dialog == false && savethemefile == NULL && + clear_screen_opt == false) + return (BSDDIALOG_OK); -void sigint_handler(int sig) -{ - bsddialog_end(); + /* --<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; + } - exit(255); -} + /* 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(); + } + } -void errorexit(char *errbuf) -{ - bsddialog_end(); + /* 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 (errbuf != NULL && errbuf[0] != '\0') - printf("Error: %s\n", errbuf); - else - printf("Error: %s\n", bsddialog_geterror()); + if (in_bsddialog_mode) { + /* --clear-screen can be a single option */ + if (clear_screen_opt) + bsddialog_clearterminal(); + bsddialog_end(); + } + /* end bsddialog terminal mode */ - exit(255); + return (retval); } -void -custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim, - char *text, char *buf) +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 '\\': - i++; - break; - case 'n': - if (no_nl_expand) { - j++; - buf[j] = 'n'; - } else - buf[j] = '\n'; + case 'n': /* implicitly in "hasnl" mode */ + buf[j] = '\n'; i++; + if (text[i+1] == '\n') + i++; break; case 't': - if (no_collapse) { + if (tab_escape_opt) { + buf[j] = '\t'; + } else { j++; buf[j] = 't'; - } else - buf[j] = '\t'; + } i++; break; } break; case '\n': - buf[j] = cr_wrap ? ' ' : '\n'; + buf[j] = crwrap ? '\n' : ' '; break; case '\t': - buf[j] = no_collapse ? '\t' : ' '; + buf[j] = text_unchanged_opt ? '\t' : ' '; break; default: buf[j] = text[i]; } i++; - j += (buf[j] == ' ' && trim && j > 0 && buf[j-1] == ' ') ? - 0 : 1; + if (!trim || buf[j] != ' ' || j == 0 || buf[j-1] != ' ') + j++; } buf[j] = '\0'; } @@ -841,12 +1019,13 @@ int gauge_builder(BUILDER_ARGS) int output; unsigned int perc; - if (argc > 0) { - perc = argc > 0 ? (u_int)strtoul(argv[0], NULL, 10) : 0; + 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); } - else - perc = 0; output = bsddialog_gauge(conf, text, rows, cols, perc, STDIN_FILENO, "XXX"); @@ -856,11 +1035,10 @@ int gauge_builder(BUILDER_ARGS) int infobox_builder(BUILDER_ARGS) { - int output; - - output = bsddialog_infobox(conf, text, rows, cols); + if (argc > 0) + error_args("--infobox", argc, argv); - return (output); + return (bsddialog_infobox(conf, text, rows, cols)); } int mixedgauge_builder(BUILDER_ARGS) @@ -869,10 +1047,8 @@ int mixedgauge_builder(BUILDER_ARGS) unsigned int i, mainperc, nminibars; const char **minilabels; - if (argc < 1 || (((argc-1) % 2) != 0) ) { - strcpy(errbuf, "bad --mixedgauge arguments\n"); - return (BSDDIALOG_ERROR); - } + 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; @@ -880,14 +1056,10 @@ int mixedgauge_builder(BUILDER_ARGS) argv++; nminibars = argc / 2; - if ((minilabels = calloc(nminibars, sizeof(char*))) == NULL) { - strcpy(errbuf, "Cannot allocate memory for minilabels\n"); - return BSDDIALOG_ERROR; - } - if ((minipercs = calloc(nminibars, sizeof(int))) == NULL) { - strcpy(errbuf, "Cannot allocate memory for minipercs\n"); - return BSDDIALOG_ERROR; - } + 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]; @@ -902,11 +1074,10 @@ int mixedgauge_builder(BUILDER_ARGS) int msgbox_builder(BUILDER_ARGS) { - int output; + if (argc > 0) + error_args("--msgbox", argc, argv); - output = bsddialog_msgbox(conf, text, rows, cols); - - return (output); + return (bsddialog_msgbox(conf, text, rows, cols)); } int pause_builder(BUILDER_ARGS) @@ -914,10 +1085,10 @@ int pause_builder(BUILDER_ARGS) int output; unsigned int secs; - if (argc < 1) { - strcpy(errbuf, "missing <seconds> for --pause\n"); - return (BSDDIALOG_ERROR); - } + 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); @@ -929,25 +1100,22 @@ int rangebox_builder(BUILDER_ARGS) { int output, min, max, value; - if (argc < 2) { - strcpy(errbuf, "usage --rangebox <text> <rows> <cols> " - "<min> <max> [<init>]\n"); - return (BSDDIALOG_ERROR); - } + 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 > 2) { + if (argc == 3) { value = (int)strtol(argv[2], NULL, 10); value = value < min ? min : value; value = value > max ? max : value; - } - else + } else value = min; output = bsddialog_rangebox(conf, text, rows, cols, min, max, &value); - dprintf(output_fd_opt, "%d", value); return (output); @@ -955,46 +1123,54 @@ int rangebox_builder(BUILDER_ARGS) int textbox_builder(BUILDER_ARGS) { - int output; - - output = bsddialog_textbox(conf, text, rows, cols); + if (argc > 0) + error_args("--textbox", argc, argv); - return (output); + return (bsddialog_textbox(conf, text, rows, cols)); } int yesno_builder(BUILDER_ARGS) { - int output; + if (argc > 0) + error_args("--yesno", argc, argv); - output = bsddialog_yesno(conf, text, rows, cols); - - return (output); + return (bsddialog_yesno(conf, text, rows, cols)); } -/* DATE and TIME */ -int datebox_builder(BUILDER_ARGS) +/* CALENDAR, DATE and TIME */ +static int date(BUILDER_ARGS, bool is_datebox) { - int output; + 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) { - yy = (u_int)strtoul(argv[0], NULL, 10); + 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); - dd = (u_int)strtoul(argv[2], NULL, 10); + yy = (u_int)strtoul(argv[2], NULL, 10); + if (yy < 1900) + yy = 1900; + /* max yy check is in lib */ } - output = bsddialog_datebox(conf, text, rows, cols, &yy, &mm, &dd); - if (output != BSDDIALOG_OK) - return (output); + 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); @@ -1005,12 +1181,36 @@ int datebox_builder(BUILDER_ARGS) 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", yy, mm, dd); + dprintf(output_fd_opt, "%u/%u/%u", dd, mm, yy); } else { - dprintf(output_fd_opt, "%u/%02u/%02u", yy, mm, dd); + dprintf(output_fd_opt, "%02u/%02u/%u", dd, mm, yy); } - return (output); + 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) @@ -1027,7 +1227,9 @@ int timebox_builder(BUILDER_ARGS) mm = localtm->tm_min; ss = localtm->tm_sec; - if (argc == 3) { + 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); @@ -1055,9 +1257,9 @@ int timebox_builder(BUILDER_ARGS) } /* MENU */ -static int -get_menu_items(char *errbuf, int argc, char **argv, bool setprefix, - bool setdepth, bool setname, bool setdesc, bool setstatus, bool sethelp, +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; @@ -1071,17 +1273,14 @@ get_menu_items(char *errbuf, int argc, char **argv, bool setprefix, sizeitem += setdesc ? 1 : 0; sizeitem += setstatus ? 1 : 0; sizeitem += sethelp ? 1 : 0; - if ((argc % sizeitem) != 0) { - strcpy(errbuf, "bad number of arguments for this menu\n"); - return (BSDDIALOG_ERROR); - } + 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) { - strcpy(errbuf, "cannot allocate memory menu items\n"); - return (BSDDIALOG_ERROR); - } + if (items == NULL) + exit_error("cannot allocate memory \"menu\" items", false); j = 0; for (i = 0; i < *nitems; i++) { @@ -1101,71 +1300,86 @@ get_menu_items(char *errbuf, int argc, char **argv, bool setprefix, if (strcmp((*items)[i].name, item_default_opt) == 0) *focusitem = i; } - - return (BSDDIALOG_OK); } static void print_menu_items(int output, int nitems, struct bsddialog_menuitem *items, - int focusitem) + int focusitem, bool ismenu) { - bool sep, toquote; + bool sep, sepfirst, seplast, toquote; int i; - char *sepstr, quotech; - const char *focusname; + char quotech; + const char *focusname, *sepstr; sep = false; quotech = item_singlequote_opt ? '\'' : '"'; - sepstr = item_output_sep_opt != NULL ? item_output_sep_opt : " "; - if (output != BSDDIALOG_OK && output != BSDDIALOG_ERROR && - focusitem >= 0) { - focusname = items[focusitem].name; + if (output == BSDDIALOG_ERROR || output == BSDDIALOG_CANCEL || + output == BSDDIALOG_ESC) + return; - if (output == BSDDIALOG_HELP) { - dprintf(output_fd_opt, "HELP "); + if (output == BSDDIALOG_HELP) { + dprintf(output_fd_opt, "HELP "); - if (item_bottomdesc_opt && item_tag_help_opt == false) + if (focusitem >= 0) { + focusname = items[focusitem].name; + if (item_bottomdesc_opt && + item_help_print_name_opt == false) focusname = items[focusitem].bottomdesc; - } - - toquote = item_always_quote_opt || - (item_output_sepnl_opt == false && - strchr(focusname, ' ') != NULL); - if (toquote) - dprintf(output_fd_opt, "%c", quotech); - dprintf(output_fd_opt, "%s", focusname); - if (toquote) - dprintf(output_fd_opt, "%c", quotech); + 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; } - if (output != BSDDIALOG_OK && - !(output == BSDDIALOG_HELP && list_items_on_opt)) - return; + 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 == true) { + if (sep || sepfirst) dprintf(output_fd_opt, "%s", sepstr); - if (item_output_sepnl_opt) - dprintf(output_fd_opt, "\n"); - } - sep = true; + sep = false; - toquote = item_always_quote_opt || - (item_output_sepnl_opt == false && - strchr(items[i].name, ' ') != NULL); - - if (toquote) - dprintf(output_fd_opt, "%c", quotech); - dprintf(output_fd_opt, "%s", items[i].name); + 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", quotech); + 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); } } @@ -1175,23 +1389,17 @@ int checklist_builder(BUILDER_ARGS) unsigned int menurows, nitems; struct bsddialog_menuitem *items; - if (argc < 1) { - strcpy(errbuf, "<menurows> not provided"); - return (BSDDIALOG_ERROR); - } - + if (argc < 1) + exit_error("--checklist missing <menurows>", true); menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt, - item_depth_opt, true, true, true, item_bottomdesc_opt, &nitems, - &items, &focusitem); - if (output != 0) - return (output); + 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); + print_menu_items(output, nitems, items, focusitem, false); free(items); @@ -1204,23 +1412,17 @@ int menu_builder(BUILDER_ARGS) unsigned int menurows, nitems; struct bsddialog_menuitem *items; - if (argc < 1) { - strcpy(errbuf, "<menurows> not provided"); - return (BSDDIALOG_ERROR); - } - + if (argc < 1) + exit_error("--menu missing <menurows>", true); menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt, - item_depth_opt, true, true, false, item_bottomdesc_opt, &nitems, - &items, &focusitem); - if (output != 0) - return (output); + 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); + print_menu_items(output, nitems, items, focusitem, true); free(items); @@ -1233,23 +1435,17 @@ int radiolist_builder(BUILDER_ARGS) unsigned int menurows, nitems; struct bsddialog_menuitem *items; - if (argc < 1) { - strcpy(errbuf, "<menurows> not provided"); - return (BSDDIALOG_ERROR); - } - + if (argc < 1) + exit_error("--radiolist missing <menurows>", true); menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt, - item_depth_opt, true, true, true, item_bottomdesc_opt, &nitems, - &items, &focusitem); - if (output != 0) - return (output); + 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); + print_menu_items(output, nitems, items, focusitem, false); free(items); @@ -1262,18 +1458,12 @@ int treeview_builder(BUILDER_ARGS) unsigned int menurows, nitems; struct bsddialog_menuitem *items; - if (argc < 1) { - strcpy(errbuf, "<menurows> not provided"); - return (BSDDIALOG_ERROR); - } - + if (argc < 1) + exit_error("--treeview missing <menurows>", true); menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_opt, - true, true, true, true, item_bottomdesc_opt, &nitems, &items, - &focusitem); - if (output != 0) - return (output); + 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; @@ -1281,7 +1471,7 @@ int treeview_builder(BUILDER_ARGS) output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems, items, &focusitem); - print_menu_items(output, nitems, items, focusitem); + print_menu_items(output, nitems, items, focusitem, false); free(items); @@ -1289,18 +1479,6 @@ int treeview_builder(BUILDER_ARGS) } /* FORM */ -static int -alloc_formitems(int nitems, struct bsddialog_formitem **items, char *errbuf) -{ - *items = calloc(nitems, sizeof(struct bsddialog_formitem)); - if (items == NULL) { - strcpy(errbuf, "cannot allocate memory for form items\n"); - return (BSDDIALOG_ERROR); - } - - return (BSDDIALOG_OK); -} - static void print_form_items(int output, int nitems, struct bsddialog_formitem *items) { @@ -1321,20 +1499,19 @@ int form_builder(BUILDER_ARGS) unsigned int i, j, flags, formheight, nitems, sizeitem; struct bsddialog_formitem *items; - sizeitem = item_bottomdesc_opt ? 9 : 8; - if (argc < 1 || (argc - 1) % sizeitem != 0) { - strcpy(errbuf, "bad number of arguments for this form\n"); - return (BSDDIALOG_ERROR); - } - + 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 (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK) - return (BSDDIALOG_ERROR); + 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++]; @@ -1369,6 +1546,9 @@ 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; @@ -1376,7 +1556,7 @@ int inputbox_builder(BUILDER_ARGS) item.yfield = 0; item.xfield = 0; item.fieldlen = 1; - item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048; + item.maxvaluelen = max_input_form_opt; item.flags = BSDDIALOG_FIELDNOCOLOR; item.flags |= BSDDIALOG_FIELDCURSOREND; item.flags |= BSDDIALOG_FIELDEXTEND; @@ -1394,20 +1574,19 @@ int mixedform_builder(BUILDER_ARGS) unsigned int i, j, formheight, nitems, sizeitem; struct bsddialog_formitem *items; - sizeitem = item_bottomdesc_opt ? 10 : 9; - if (argc < 1 || (argc-1) % sizeitem != 0) { - strcpy(errbuf, "bad number of arguments for this form\n"); - return (BSDDIALOG_ERROR); - } - + 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 (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK) - return (BSDDIALOG_ERROR); + 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++]; @@ -1435,6 +1614,9 @@ 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; @@ -1442,7 +1624,7 @@ int passwordbox_builder(BUILDER_ARGS) item.yfield = 0; item.xfield = 0; item.fieldlen = 1; - item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048; + item.maxvaluelen = max_input_form_opt; item.flags = BSDDIALOG_FIELDHIDDEN; item.flags |= BSDDIALOG_FIELDNOCOLOR; item.flags |= BSDDIALOG_FIELDCURSOREND; @@ -1461,21 +1643,20 @@ int passwordform_builder(BUILDER_ARGS) unsigned int i, j, flags, formheight, nitems, sizeitem; struct bsddialog_formitem *items; - sizeitem = item_bottomdesc_opt ? 9 : 8; - if (argc < 1 || (argc - 1) % sizeitem != 0) { - strcpy(errbuf, "bad number of arguments for this form\n"); - return (BSDDIALOG_ERROR); - } - + if (argc < 1) + exit_error("--passwordform missing <formheight>", true); formheight = (u_int)strtoul(argv[0], NULL, 10); - flags = BSDDIALOG_FIELDHIDDEN; 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 (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK) - return (BSDDIALOG_ERROR); + 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++]; diff --git a/examples_library/calendar.c b/examples_library/calendar.c new file mode 100644 index 000000000000..33e38c69a81b --- /dev/null +++ b/examples_library/calendar.c @@ -0,0 +1,55 @@ +/*- + * SPDX-License-Identifier: CC0-1.0 + * + * Written in 2022 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> +#include <string.h> +#include <time.h> + +int main() +{ + int output; + unsigned int yy, mm, dd; + struct bsddialog_conf conf; + time_t cal; + struct tm *localtm; + + time(&cal); + localtm = localtime(&cal); + yy = localtm->tm_year + 1900; + mm = localtm->tm_mon + 1; + dd = localtm->tm_mday; + + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + bsddialog_initconf(&conf); + conf.title = "calendar"; + output = bsddialog_calendar(&conf, "Example", 18, 40, &yy, &mm, &dd); + + bsddialog_end(); + + switch (output) { + case BSDDIALOG_OK: + printf("Date: %u/%u/%u", yy, mm, dd); + break; + case BSDDIALOG_CANCEL: + printf("Cancel"); + break; + case BSDDIALOG_ERROR: + printf("Error: %s", bsddialog_geterror()); + break; + } + printf("\n"); + + return (output); +}
\ No newline at end of file diff --git a/examples_library/compile b/examples_library/compile index 6f2c23b8ca75..4cb6d23bd6a6 100755 --- a/examples_library/compile +++ b/examples_library/compile @@ -10,7 +10,7 @@ libpath=../lib examples="menu checklist radiolist mixedlist theme infobox yesno msgbox \ - datebox form timebox rangebox pause" + datebox form timebox rangebox pause calendar" rm -f $examples diff --git a/examples_library/form.c b/examples_library/form.c index 56d8a8052a72..4780fb68d121 100644 --- a/examples_library/form.c +++ b/examples_library/form.c @@ -27,7 +27,7 @@ int main() {"Password:", 2, 0, "", 2, 10, 30, 50, NULL, H, "desc 3"} }; - /* Optional, unless for unicode/multicolum charachters */ + /* Optional, unless for unicode/multi-column characters */ setlocale(LC_ALL, ""); if (bsddialog_init() == BSDDIALOG_ERROR) { @@ -56,4 +56,4 @@ int main() } return (output); -}
\ No newline at end of file +} diff --git a/examples_utility/calendar.sh b/examples_utility/calendar.sh new file mode 100644 index 000000000000..a7ce4f1bb1d5 --- /dev/null +++ b/examples_utility/calendar.sh @@ -0,0 +1,34 @@ +#!/bin/sh +#- +# SPDX-License-Identifier: CC0-1.0 +# +# Written in 2022 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/>. + +: ${BSDDIALOG_ERROR=255} +: ${BSDDIALOG_OK=0} +: ${BSDDIALOG_CANCEL=1} +: ${BSDDIALOG_ESC=5} + +DATE=$(./bsddialog --title " calendar " --date-format "%x" \ + --calendar "Hello World!" 20 40 \ +3>&1 1>&2 2>&3 3>&-) + +case $? in + $BSDDIALOG_ERROR ) + exit 1 + ;; + $BSDDIALOG_ESC ) + echo "[ESC]" + ;; + $BSDDIALOG_CANCEL ) + echo "[Cancel]" + ;; + $BSDDIALOG_OK ) + echo "[OK] $DATE" + ;; +esac diff --git a/examples_utility/timebox.sh b/examples_utility/timebox.sh index 81d24d558dc9..233434b29195 100755 --- a/examples_utility/timebox.sh +++ b/examples_utility/timebox.sh @@ -14,8 +14,7 @@ : ${BSDDIALOG_CANCEL=1} : ${BSDDIALOG_ESC=5} -TIME=$(./bsddialog --title " timebox " \ - --timebox "Tab / Left / Right to move\nUp / Down to select" 10 40 \ +TIME=$(./bsddialog --title " timebox " --timebox "Hello World!" 8 25 \ 3>&1 1>&2 2>&3 3>&-) case $? in diff --git a/lib/GNUMakefile b/lib/GNUMakefile index 1d55d6edd60d..3c31c78fdf88 100644 --- a/lib/GNUMakefile +++ b/lib/GNUMakefile @@ -3,15 +3,15 @@ # # Written in 2021 by Alfonso Sabato Siciliano -VERSION = 0.3 +VERSION = 0.4 LIBRARY = bsddialog LIBRARY_SO = lib${LIBRARY:=.so} HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h -SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \ - messagebox.c textbox.c theme.c timebox.c +SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \ + lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c OBJECTS = $(SOURCES:.c=.o) -CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra -Wno-implicit-fallthrough \ - -Werror -fpic +CFLAGS = -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE -D_GNU_SOURCE -Wall -Wextra \ + -Wno-implicit-fallthrough -Werror -fpic LDFLAGS = -lncursesw -ltinfo LIBFLAG = -shared diff --git a/lib/Makefile b/lib/Makefile index 5c535c5483f1..0f536fb38743 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -3,13 +3,13 @@ # # Written in 2021 by Alfonso Sabato Siciliano -VERSION = 0.3 +VERSION = 0.4 LIBRARY = bsddialog LIBRARY_SO = lib${LIBRARY:=.so} LIBRARY_A = lib${LIBRARY:=.a} HEADERS = bsddialog.h bsddialog_theme.h bsddialog_progressview.h -SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \ - messagebox.c textbox.c theme.c timebox.c +SOURCES = barbox.c calendarbox.c formbox.c infobox.c libbsddialog.c \ + lib_util.c menubox.c messagebox.c textbox.c theme.c timebox.c OBJECTS = ${SOURCES:.c=.o} CFLAGS += -D_XOPEN_SOURCE_EXTENDED -fPIC -Wall -Wextra LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \ diff --git a/lib/barbox.c b/lib/barbox.c index b6bfe32fc0aa..71759839a709 100644 --- a/lib/barbox.c +++ b/lib/barbox.c @@ -327,7 +327,7 @@ do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols, wrefresh(bar); - /* getch(); port ncurses shows nothing */ + /* getch(); alternate mode (port devel/ncurses) shows nothing */ delwin(bar); end_dialog(conf, shadow, widget, textpad); diff --git a/lib/bsddialog.3 b/lib/bsddialog.3 index 12db1f039d59..9cc68a90ff62 100644 --- a/lib/bsddialog.3 +++ b/lib/bsddialog.3 @@ -22,11 +22,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 29, 2022 +.Dd September 23, 2022 .Dt BSDDIALOG 3 .Os .Sh NAME .Nm bsddialog_backtitle , +.Nm bsddialog_calendar , .Nm bsddialog_clearterminal , .Nm bsddialog_color , .Nm bsddialog_color_attrs , @@ -62,6 +63,16 @@ .Ft int .Fn bsddialog_backtitle "struct bsddialog_conf *conf" "const char *backtitle" .Ft int +.Fo bsddialog_calendar +.Fa "struct bsddialog_conf *conf" +.Fa "const char *text" +.Fa "int rows" +.Fa "int cols" +.Fa "unsigned int *yy" +.Fa "unsigned int *mm" +.Fa "unsigned int *dd" +.Fc +.Ft int .Fo bsddialog_checklist .Fa "struct bsddialog_conf *conf" .Fa "const char *text" @@ -75,7 +86,7 @@ .Ft int .Fn bsddialog_clearterminal "void" .Ft int -.Fo bsddialog_datebox" +.Fo bsddialog_datebox .Fa "struct bsddialog_conf *conf" .Fa "const char *text" .Fa "int rows" @@ -476,7 +487,8 @@ function. buttons always active, avoidind focus switch between buttons and input fields or input boxes in .Fn bsddialog_form , -.Fn bsddialog_datebox +.Fn bsddialog_datebox , +.Fn bsddialog_calendar and .Fn bsddialog_timebox . .It Fa conf.button.without_ok @@ -515,7 +527,10 @@ to true, and .Fa conf.x to -.Dv BSDDIALOG_CENTER . +.Dv BSDDIALOG_CENTER , +.Fa conf.text.cols_per_row +to +.Dv 10 . .Pp .Fn bsddialog_infobox builds a dialog without buttons and returns instantly. @@ -531,8 +546,10 @@ builds a dialog waiting until the timeout in .Fa seconds expires or a button is pressed. .Pp +.Fn bsddialog_calendar +and .Fn bsddialog_datebox -builds a dialog to select a date, +build a dialog to select a date, .Fa yy , .Fa mm , and @@ -606,14 +623,14 @@ builds a dialog with collections of checklists, radiolists and separators. A collection is a set defined like: .Pp .Bd -literal -offset indent -compact -enum bsddialog_grouptype { +enum bsddialog_menutype { BSDDIALOG_CHECKLIST, BSDDIALOG_RADIOLIST, BSDDIALOG_SEPARATOR, }; struct bsddialog_menugroup { - enum bsddialog_grouptype type; + enum bsddialog_menutype type; unsigned int nitems; struct bsddialog_menuitem *items; }; @@ -1013,7 +1030,7 @@ struct bsddialog_menuitem check[2] = { struct bsddialog_menuitem sep[1] = { { "3", true, 0, "Radiolist", "(desc)", "" } }; -struct bsddialog_menuitem radio[5] = { +struct bsddialog_menuitem radio[2] = { { "4", true, 0, "Name 1", "Desc 1", "Radio Bottom Desc 1" }, { "5", false, 0, "Name 2", "Desc 2", "Radio Bottom Desc 2" } }; diff --git a/lib/bsddialog.h b/lib/bsddialog.h index 6f13da3fa667..ce6aac6d4632 100644 --- a/lib/bsddialog.h +++ b/lib/bsddialog.h @@ -30,7 +30,7 @@ #include <stdbool.h> -#define LIBBSDDIALOG_VERSION "0.3" +#define LIBBSDDIALOG_VERSION "0.4" /* Exit status */ #define BSDDIALOG_ERROR -1 @@ -136,14 +136,14 @@ struct bsddialog_menuitem { const char *bottomdesc; }; -enum bsddialog_grouptype { +enum bsddialog_menutype { BSDDIALOG_CHECKLIST, BSDDIALOG_RADIOLIST, BSDDIALOG_SEPARATOR, }; struct bsddialog_menugroup { - enum bsddialog_grouptype type; + enum bsddialog_menutype type; unsigned int nitems; struct bsddialog_menuitem *items; }; @@ -174,6 +174,10 @@ const char *bsddialog_geterror(void); /* Dialogs */ int +bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd); + +int bsddialog_checklist(struct bsddialog_conf *conf, const char *text, int rows, int cols, unsigned int menurows, unsigned int nitems, struct bsddialog_menuitem *items, int *focusitem); diff --git a/lib/calendarbox.c b/lib/calendarbox.c new file mode 100644 index 000000000000..3b55b26a13b8 --- /dev/null +++ b/lib/calendarbox.c @@ -0,0 +1,520 @@ +/*- + * 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 <sys/param.h> + +#include <curses.h> +#include <stdlib.h> +#include <string.h> + +#include "bsddialog.h" +#include "bsddialog_theme.h" +#include "lib_util.h" + +#define MINHCAL 13 +#define MINWCAL 36 /* 34 calendar, 1 + 1 margins */ +#define MINYEAR 1900 +#define MAXYEAR 999999999 + +static int month_days(int yy, int mm) +{ + int days; + + if (mm == 2) + days = ISLEAP(yy) ? 29 : 28; + else if (mm == 4 || mm == 6 || mm == 9 || mm == 11) + days = 30; + else + days = 31; + + return (days); +} + +enum operation { + UP_DAY, + DOWN_DAY, + LEFT_DAY, + RIGHT_DAY, + UP_MONTH, + DOWN_MONTH, + UP_YEAR, + DOWN_YEAR +}; + +static void datectl(enum operation op, int *yy, int *mm, int *dd) +{ + int ndays; + + ndays = month_days(*yy, *mm); + + switch (op) { + case UP_DAY: + if (*dd > 7) + *dd -= 7; + else { + if (*mm == 1) { + *yy -= 1; + *mm = 12; + } else + *mm -= 1; + ndays = month_days(*yy, *mm); + *dd = ndays - abs(7 - *dd); + } + break; + case DOWN_DAY: + if (*dd + 7 < ndays) + *dd += 7; + else { + if (*mm == 12) { + *yy += 1; + *mm = 1; + } else + *mm += 1; + *dd = *dd + 7 - ndays; + } + break; + case LEFT_DAY: + if (*dd > 1) + *dd -= 1; + else { + if (*mm == 1) { + *yy -= 1; + *mm = 12; + } else + *mm -= 1; + *dd = month_days(*yy, *mm); + } + break; + case RIGHT_DAY: + if (*dd < ndays) + *dd += 1; + else { + if (*mm == 12) { + *yy += 1; + *mm = 1; + } else + *mm += 1; + *dd = 1; + } + break; + case UP_MONTH: + if (*mm == 1) { + *mm = 12; + *yy -= 1; + } else + *mm -= 1; + ndays = month_days(*yy, *mm); + if (*dd > ndays) + *dd = ndays; + break; + case DOWN_MONTH: + if (*mm == 12) { + *mm = 1; + *yy += 1; + } else + *mm += 1; + ndays = month_days(*yy, *mm); + if (*dd > ndays) + *dd = ndays; + break; + case UP_YEAR: + *yy -= 1; + ndays = month_days(*yy, *mm); + if (*dd > ndays) + *dd = ndays; + break; + case DOWN_YEAR: + *yy += 1; + ndays = month_days(*yy, *mm); + if (*dd > ndays) + *dd = ndays; + break; + } + + if (*yy < MINYEAR) { + *yy = MINYEAR; + *mm = 1; + *dd = 1; + } + if (*yy > MAXYEAR) { + *yy = MAXYEAR; + *mm = 12; + *dd = 31; + } +} + +static int week_day(int yy, int mm, int dd) +{ + int wd; + + dd += mm < 3 ? yy-- : yy - 2; + wd = 23*mm/9 + dd + 4 + yy/4 - yy/100 + yy/400; + wd %= 7; + + return (wd); +} + +static void +print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd, + bool active) +{ + int ndays, i, y, x, wd, h, w; + + getmaxyx(win, h, w); + wclear(win); + draw_borders(conf, win, h, w, RAISED); + if (active) { + wattron(win, t.dialog.arrowcolor); + mvwhline(win, 0, 15, conf->ascii_lines ? '^' : ACS_UARROW, 4); + mvwhline(win, h-1, 15, conf->ascii_lines ? 'v' : ACS_DARROW, 4); + mvwvline(win, 3, 0, conf->ascii_lines ? '<' : ACS_LARROW, 3); + mvwvline(win, 3, w-1, conf->ascii_lines ? '>' : ACS_RARROW, 3); + wattroff(win, t.dialog.arrowcolor); + } + + mvwaddstr(win, 1, 5, "Sun Mon Tue Wed Thu Fri Sat"); + ndays = month_days(yy, mm); + y = 2; + wd = week_day(yy, mm, 1); + for (i = 1; i <= ndays; i++) { + x = 5 + (4 * wd); /* x has to be 6 with week number */ + wmove(win, y, x); + mvwprintw(win, y, x, "%2d", i); + if (i == dd) { + wattron(win, t.menu.f_namecolor); + mvwprintw(win, y, x, "%2d", i); + wattroff(win, t.menu.f_namecolor); + } + wd++; + if (wd > 6) { + wd = 0; + y++; + } + } + + wrefresh(win); +} + +static void +drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt, + const void *value, bool focus) +{ + int h, w; + + getmaxyx(win, h, w); + draw_borders(conf, win, h, w, RAISED); + if (focus) { + wattron(win, t.dialog.arrowcolor); + mvwhline(win, 0, 7, conf->ascii_lines ? '^' : ACS_UARROW, 3); + mvwhline(win, 2, 7, conf->ascii_lines ? 'v' : ACS_DARROW, 3); + wattroff(win, t.dialog.arrowcolor); + } + + if (focus) + wattron(win, t.menu.f_namecolor); + if (strchr(fmt, 's') != NULL) + mvwprintw(win, 1, 1, fmt, (const char*)value); + else + mvwprintw(win, 1, 1, fmt, *((const int*)value)); + if (focus) + wattroff(win, t.menu.f_namecolor); + + wrefresh(win); +} + +static int +calendar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, + int *w, const char *text, struct buttons bs) +{ + int htext, wtext; + + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, &bs, MINHCAL, MINWCAL, + &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); + } + + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, MINWCAL, &bs); + + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, htext, MINHCAL, true); + + return (0); +} + +static int calendar_checksize(int rows, int cols, struct buttons bs) +{ + int mincols; + + mincols = MAX(MINWCAL, buttons_min_width(bs)); + mincols += VBORDERS; + + if (cols < mincols) + RETURN_ERROR("Few cols for this calendar (at least 38)"); + + if (rows < MINHCAL + 2 + 2) /* 2 buttons + 2 borders */ + RETURN_ERROR("Few rows for calendar (at least 17)"); + + return (0); +} + +int +bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd) +{ + bool loop, focusbuttons; + int retval, y, x, h, w, sel, ycal, xcal, year, month, day; + wint_t input; + WINDOW *widget, *textpad, *shadow, *yearwin, *monthwin, *daywin; + struct buttons bs; + const char *m[12] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" + }; + + if (yy == NULL || mm == NULL || dd == NULL) + RETURN_ERROR("yy / mm / dd cannot be NULL"); + + year = *yy > MAXYEAR ? MAXYEAR : *yy; + if (year < MINYEAR) + year = MINYEAR; + month = *mm > 12 ? 12 : *mm; + if (month == 0) + month = 1; + day = *dd == 0 ? 1 : *dd; + if(day > month_days(year, month)) + day = month_days(year, month); + + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); + + if (set_widget_size(conf, rows, cols, &h, &w) != 0) + return (BSDDIALOG_ERROR); + if (calendar_autosize(conf, rows, cols, &h, &w, text, bs) != 0) + return (BSDDIALOG_ERROR); + if (calendar_checksize(h, w, bs) != 0) + return (BSDDIALOG_ERROR); + if (set_widget_position(conf, &y, &x, h, w) != 0) + return (BSDDIALOG_ERROR); + + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); + + pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2); + doupdate(); + + ycal = y + h - 15; + xcal = x + w/2 - 17; + mvwaddstr(widget, h - 16, w/2 - 17, "Month"); + monthwin = new_boxed_window(conf, ycal, xcal, 3, 17, RAISED); + mvwaddstr(widget, h - 16, w/2, "Year"); + yearwin = new_boxed_window(conf, ycal, xcal + 17, 3, 17, RAISED); + daywin = new_boxed_window(conf, ycal + 3, xcal, 9, 34, RAISED); + + wrefresh(widget); + + sel = -1; + loop = focusbuttons = true; + while (loop) { + drawsquare(conf, monthwin, "%15s", m[month - 1], sel == 0); + drawsquare(conf, yearwin, "%15d", &year, sel == 1); + print_calendar(conf, daywin, year, month, day, sel == 2); + + if (get_wch(&input) == ERR) + continue; + switch(input) { + case KEY_ENTER: + case 10: /* Enter */ + if (focusbuttons || conf->button.always_active) { + retval = bs.value[bs.curr]; + loop = false; + } + break; + case 27: /* Esc */ + if (conf->key.enable_esc) { + retval = BSDDIALOG_ESC; + loop = false; + } + break; + case '\t': /* TAB */ + if (focusbuttons) { + bs.curr++; + if (bs.curr >= (int)bs.nbuttons) { + focusbuttons = false; + sel = 0; + bs.curr = conf->button.always_active ? + 0 : -1; + } + } else { + sel++; + if (sel > 2) { + focusbuttons = true; + sel = -1; + bs.curr = 0; + } + } + draw_buttons(widget, bs, true); + wrefresh(widget); + break; + case KEY_RIGHT: + if (focusbuttons) { + bs.curr++; + if (bs.curr >= (int)bs.nbuttons) { + focusbuttons = false; + sel = 0; + bs.curr = conf->button.always_active ? + 0 : -1; + } + } else if (sel == 2) { + datectl(RIGHT_DAY, &year, &month, &day); + } else { /* Month or Year*/ + sel++; + } + draw_buttons(widget, bs, true); + wrefresh(widget); + break; + case KEY_LEFT: + if (focusbuttons) { + bs.curr--; + if (bs.curr < 0) { + focusbuttons = false; + sel = 2; + bs.curr = conf->button.always_active ? + 0 : -1; + } + } else if (sel == 2) { + datectl(LEFT_DAY, &year, &month, &day); + } else if (sel == 1) { + sel = 0; + } else { /* sel = 0, Month */ + focusbuttons = true; + sel = -1; + bs.curr = 0; + } + draw_buttons(widget, bs, true); + wrefresh(widget); + break; + case KEY_UP: + if (focusbuttons) { + sel = 2; + focusbuttons = false; + bs.curr = conf->button.always_active ? 0 : -1; + draw_buttons(widget, bs, true); + wrefresh(widget); + } else if (sel == 0) { + datectl(UP_MONTH, &year, &month, &day); + } else if (sel == 1) { + datectl(UP_YEAR, &year, &month, &day); + } else { /* sel = 2 */ + datectl(UP_DAY, &year, &month, &day); + } + break; + case KEY_DOWN: + if (focusbuttons) { + break; + } else if (sel == 0) { + datectl(DOWN_MONTH, &year, &month, &day); + } else if (sel == 1) { + datectl(DOWN_YEAR, &year, &month, &day); + } else { /* sel = 2 */ + datectl(DOWN_DAY, &year, &month, &day); + } + break; + case KEY_HOME: + datectl(UP_MONTH, &year, &month, &day); + break; + case KEY_END: + datectl(DOWN_MONTH, &year, &month, &day); + break; + case KEY_PPAGE: + datectl(UP_YEAR, &year, &month, &day); + break; + case KEY_NPAGE: + datectl(DOWN_YEAR, &year, &month, &day); + break; + case KEY_F(1): + if (conf->key.f1_file == NULL && + conf->key.f1_message == NULL) + break; + if (f1help(conf) != 0) + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ + case KEY_RESIZE: + /* Important for decreasing screen */ + hide_widget(y, x, h, w, conf->shadow); + refresh(); + + if (set_widget_size(conf, rows, cols, &h, &w) != 0) + return (BSDDIALOG_ERROR); + if (calendar_autosize(conf, rows, cols, &h, &w, text, + bs) != 0) + return (BSDDIALOG_ERROR); + if (calendar_checksize(h, w, bs) != 0) + return (BSDDIALOG_ERROR); + if (set_widget_position(conf, &y, &x, h, w) != 0) + return (BSDDIALOG_ERROR); + + if (update_dialog(conf, shadow, widget, y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); + pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-17, x+w-2); + doupdate(); + + ycal = y + h - 15; + xcal = x + w/2 - 17; + mvwaddstr(widget, h - 16, w/2 - 17, "Month"); + mvwin(monthwin, ycal, xcal); + mvwaddstr(widget, h - 16, w/2, "Year"); + mvwin(yearwin, ycal, xcal + 17); + mvwin(daywin, ycal + 3, xcal); + wrefresh(widget); + + /* Important to avoid grey lines expanding screen */ + refresh(); + break; + default: + if (shortcut_buttons(input, &bs)) { + retval = bs.value[bs.curr]; + loop = false; + } + } + } + + if (retval == BSDDIALOG_OK) { + *yy = year; + *mm = month; + *dd = day; + } + + delwin(yearwin); + delwin(monthwin); + delwin(daywin); + end_dialog(conf, shadow, widget, textpad); + + return (retval); +}
\ No newline at end of file diff --git a/lib/formbox.c b/lib/formbox.c index cd29919417be..5b1d2ab61de2 100644 --- a/lib/formbox.c +++ b/lib/formbox.c @@ -424,34 +424,25 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, } else notext += *menurows; - /* cols autosize, rows autosize, rows fullscreen, menu particularity */ - if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) { - if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, - &htext, &wtext) != 0) - return (BSDDIALOG_ERROR); - } + if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, &htext, + &wtext) != 0) + return (BSDDIALOG_ERROR); if (cols == BSDDIALOG_AUTOSIZE) *w = widget_min_width(conf, wtext, linelen + 4, &bs); if (rows == BSDDIALOG_AUTOSIZE) { - if (*menurows == 0) { + if (*menurows == BSDDIALOG_AUTOSIZE) { menusize = widget_max_height(conf) - HBORDERS - 2 /*buttons*/ - htext; menusize = MIN(menusize, nitems + 2); *menurows = menusize - 2 < 0 ? 0 : menusize - 2; - } - else /* h autosize with fixed menurows */ + } else /* h autosize with fixed menurows */ menusize = *menurows + 2; *h = widget_min_height(conf, htext, menusize, true); - /* - * avoid menurows overflow and - * with rows=AUTOSIZE menurows!=0 becomes max-menurows - */ - *menurows = MIN(*h - 6 - htext, (int)*menurows); - } else { - if (*menurows == 0) { + } else { /* fixed rows */ + if (*menurows == BSDDIALOG_AUTOSIZE) { if (*h - 6 - htext <= 0) *menurows = 0; /* form_checksize() will check */ else @@ -459,6 +450,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, } } + /* avoid menurows overflow and menurows becomes at most menurows */ + if (*h - 6 - htext <= 0) + *menurows = 0; /* form_checksize() will check */ + else + *menurows = MIN(*h - 6 - htext, (int)*menurows); + return (0); } diff --git a/lib/lib_util.c b/lib/lib_util.c index fcdf4c3d8769..d8c0f1d21b42 100644 --- a/lib/lib_util.c +++ b/lib/lib_util.c @@ -921,11 +921,8 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w) *h = maxheight; else if (rows < BSDDIALOG_FULLSCREEN) RETURN_ERROR("Negative (less than -1) height"); - else if (rows > BSDDIALOG_AUTOSIZE) { - if ((*h = rows) > maxheight) - RETURN_ERROR("Height too big (> terminal height - " - "shadow)"); - } + else if (rows > BSDDIALOG_AUTOSIZE) /* fixed rows */ + *h = MIN(rows, maxheight); /* rows is at most maxheight */ /* rows == AUTOSIZE: each widget has to set its size */ if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR) @@ -935,11 +932,8 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w) *w = maxwidth; else if (cols < BSDDIALOG_FULLSCREEN) RETURN_ERROR("Negative (less than -1) width"); - else if (cols > BSDDIALOG_AUTOSIZE) { - if ((*w = cols) > maxwidth) - RETURN_ERROR("Width too big (> terminal width - " - "shadow)"); - } + else if (cols > BSDDIALOG_AUTOSIZE) /* fixed cols */ + *w = MIN(cols, maxwidth); /* cols is at most maxwidth */ /* cols == AUTOSIZE: each widget has to set its size */ return (0); diff --git a/lib/lib_util.h b/lib/lib_util.h index 238d3fda4675..17ea0e0d1368 100644 --- a/lib/lib_util.h +++ b/lib/lib_util.h @@ -43,6 +43,9 @@ extern bool hastermcolors; refresh(); \ } while (0) +/* date */ +#define ISLEAP(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) + /* unicode */ unsigned int strcols(const char *mbstring); int str_props(const char *mbstring, unsigned int *cols, bool *has_multi_col); diff --git a/lib/libbsddialog.c b/lib/libbsddialog.c index 1a8188b0e7d3..73c1f5c2dd57 100644 --- a/lib/libbsddialog.c +++ b/lib/libbsddialog.c @@ -99,7 +99,9 @@ int bsddialog_end(void) int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle) { - mvaddstr(0, 1, backtitle); + move(0, 1); + clrtoeol(); + addstr(backtitle); if (conf->no_lines != true) mvhline(1, 1, conf->ascii_lines ? '-' : ACS_HLINE, SCREENCOLS - 2); diff --git a/lib/menubox.c b/lib/menubox.c index 28b9c8a0923b..bd06a9e37df2 100644 --- a/lib/menubox.c +++ b/lib/menubox.c @@ -36,7 +36,6 @@ #include "bsddialog_theme.h" #include "lib_util.h" -#define DEPTH 2 #define MIN_HEIGHT VBORDERS + 6 /* 2 buttons 1 text 3 menu */ enum menumode { @@ -277,7 +276,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y, colorname = focus ? t.menu.f_namecolor : t.menu.namecolor; if (conf->menu.no_name == false) { wattron(pad, colorname); - mvwaddstr(pad, y, pos.xname + item->depth * DEPTH, item->name); + mvwaddstr(pad, y, pos.xname + item->depth, item->name); wattroff(pad, colorname); } @@ -290,8 +289,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y, if (conf->menu.no_desc == false) { wattron(pad, colordesc); if (conf->menu.no_name) - mvwaddstr(pad, y, pos.xname + item->depth * DEPTH, - item->desc); + mvwaddstr(pad, y, pos.xname + item->depth, item->desc); else mvwaddstr(pad, y, pos.xdesc, item->desc); wattroff(pad, colordesc); @@ -307,7 +305,7 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y, mbtowc(&shortcut, item->desc, MB_CUR_MAX); else mbtowc(&shortcut, item->name, MB_CUR_MAX); - mvwaddwch(pad, y, pos.xname + item->depth * DEPTH, shortcut); + mvwaddwch(pad, y, pos.xname + item->depth, shortcut); wattroff(pad, colorshortcut); } @@ -362,34 +360,25 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, } else notext += *menurows; - /* cols autosize, rows autosize, rows fullscreen, menu particularity */ - if (cols == BSDDIALOG_AUTOSIZE || rows <= BSDDIALOG_AUTOSIZE) { - if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, - &htext, &wtext) != 0) - return (BSDDIALOG_ERROR); - } + if (text_size(conf, rows, cols, text, &bs, notext, linelen + 4, &htext, + &wtext) != 0) + return (BSDDIALOG_ERROR); if (cols == BSDDIALOG_AUTOSIZE) *w = widget_min_width(conf, wtext, linelen + 4, &bs); if (rows == BSDDIALOG_AUTOSIZE) { - if (*menurows == 0) { + if (*menurows == BSDDIALOG_AUTOSIZE) { menusize = widget_max_height(conf) - HBORDERS - 2 /*buttons*/ - htext; menusize = MIN(menusize, nitems + 2); *menurows = menusize - 2 < 0 ? 0 : menusize - 2; - } - else /* h autosize with fixed menurows */ + } else /* h autosize with fixed menurows */ menusize = *menurows + 2; *h = widget_min_height(conf, htext, menusize, true); - /* - * avoid menurows overflow and - * with rows=AUTOSIZE menurows!=0 becomes max-menurows - */ - *menurows = MIN(*h - 6 - htext, (int)*menurows); - } else { - if (*menurows == 0) { + } else { /* fixed rows */ + if (*menurows == BSDDIALOG_AUTOSIZE) { if (*h - 6 - htext <= 0) *menurows = 0; /* menu_checksize() will check */ else @@ -397,6 +386,12 @@ menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, } } + /* avoid menurows overflow and menurows becomes at most menurows */ + if (*h - 6 - htext <= 0) + *menurows = 0; /* menu_checksize() will check */ + else + *menurows = MIN(*h - 6 - htext, (int)*menurows); + return (0); } @@ -475,7 +470,6 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols, } pos.maxname = conf->menu.no_name ? 0 : pos.maxname; pos.maxdesc = conf->menu.no_desc ? 0 : pos.maxdesc; - pos.maxdepth = DEPTH * pos.maxdepth; pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0); pos.xname = pos.xselector + pos.selectorlen + @@ -696,11 +690,15 @@ do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols, movefocus = next != abs; break; case ' ': /* Space */ - if (pritems[abs].type == MENUMODE) - break; - else if (pritems[abs].type == CHECKLISTMODE) + if (pritems[abs].type == MENUMODE) { + retval = bs.value[bs.curr]; + pritems[abs].on = true; + set_on_output(conf, retval, ngroups, groups, + pritems); + loop = false; + } else if (pritems[abs].type == CHECKLISTMODE) { pritems[abs].on = !pritems[abs].on; - else { /* RADIOLISTMODE */ + } else { /* RADIOLISTMODE */ for (i = abs - pritems[abs].index; i < totnitems && pritems[i].group == pritems[abs].group; diff --git a/lib/messagebox.c b/lib/messagebox.c index 06753be20c3d..7063ea9d273e 100644 --- a/lib/messagebox.c +++ b/lib/messagebox.c @@ -103,7 +103,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, struct buttons bs) { bool hastext, loop; - int y, x, h, w, retval, ytextpad, htextpad, unused; + int y, x, h, w, retval, ytextpad, htextpad, printrows, unused; WINDOW *widget, *textpad, *shadow; wint_t input; @@ -120,12 +120,13 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, true) != 0) return (BSDDIALOG_ERROR); + printrows = h - 4; ytextpad = 0; getmaxyx(textpad, htextpad, unused); unused++; /* fix unused error */ - textupdate(widget, textpad, htextpad, ytextpad, hastext); loop = true; while (loop) { + textupdate(widget, textpad, htextpad, ytextpad, hastext); doupdate(); if (get_wch(&input) == ERR) continue; @@ -160,6 +161,30 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, wnoutrefresh(widget); } break; + case KEY_UP: + if (ytextpad > 0) + ytextpad--; + break; + case KEY_DOWN: + if (ytextpad + printrows < htextpad) + ytextpad++; + break; + case KEY_HOME: + ytextpad = 0; + break; + case KEY_END: + ytextpad = htextpad - printrows; + ytextpad = ytextpad < 0 ? 0 : ytextpad; + break; + case KEY_PPAGE: + ytextpad -= printrows; + ytextpad = ytextpad < 0 ? 0 : ytextpad; + break; + case KEY_NPAGE: + ytextpad += printrows; + if (ytextpad + printrows > htextpad) + ytextpad = htextpad - printrows; + break; case KEY_F(1): if (conf->key.f1_file == NULL && conf->key.f1_message == NULL) @@ -186,6 +211,7 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, textpad, text, &bs, true) != 0) return (BSDDIALOG_ERROR); + printrows = h - 4; getmaxyx(textpad, htextpad, unused); ytextpad = 0; textupdate(widget, textpad, htextpad, ytextpad, hastext); @@ -193,18 +219,6 @@ do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, /* Important to fix grey lines expanding screen */ refresh(); break; - case KEY_UP: - if (ytextpad == 0) - break; - ytextpad--; - textupdate(widget, textpad, htextpad, ytextpad, hastext); - break; - case KEY_DOWN: - if (ytextpad + h - 4 >= htextpad) - break; - ytextpad++; - textupdate(widget, textpad, htextpad, ytextpad, hastext); - break; default: if (shortcut_buttons(input, &bs)) { retval = bs.value[bs.curr]; diff --git a/lib/theme.c b/lib/theme.c index 40310d58cda4..6e53eb356825 100644 --- a/lib/theme.c +++ b/lib/theme.c @@ -258,7 +258,6 @@ int bsddialog_set_theme(struct bsddialog_theme *theme) int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme) { - if (newtheme == BSDDIALOG_THEME_FLAT) { bsddialog_set_theme(&dialogtheme); t.dialog.lineraisecolor = t.dialog.linelowercolor; diff --git a/lib/timebox.c b/lib/timebox.c index 529563b49bca..53989bb97157 100644 --- a/lib/timebox.c +++ b/lib/timebox.c @@ -39,7 +39,7 @@ #define MINWTIME 14 /* 3 windows and their borders */ static void -drawquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt, +drawsquare(struct bsddialog_conf *conf, WINDOW *win, const char *fmt, const void *value, bool focus) { int h, l, w; @@ -167,7 +167,7 @@ bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows, loop = focusbuttons = true; while (loop) { for (i = 0; i < 3; i++) - drawquare(conf, c[i].win, "%02d", &c[i].value, + drawsquare(conf, c[i].win, "%02d", &c[i].value, sel == i); if (get_wch(&input) == ERR) @@ -341,8 +341,6 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, { "October", 31 }, { "November", 30 }, { "December", 31 } }; -#define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) - for (i = 0 ; i < 3; i++) { if (c[i].value > c[i].max) c[i].value = c[i].max; @@ -350,7 +348,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, c[i].value = 1; } c[2].max = m[c[1].value -1].days; - if (c[1].value == 2 && ISLEAF(c[0].value)) + if (c[1].value == 2 && ISLEAP(c[0].value)) c[2].max = 29; if (c[2].value > c[2].max) c[2].value = c[2].max; @@ -385,10 +383,10 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, sel = -1; loop = focusbuttons = true; while (loop) { - drawquare(conf, c[0].win, "%4d", &c[0].value, sel == 0); - drawquare(conf, c[1].win, "%9s", m[c[1].value-1].name, + drawsquare(conf, c[0].win, "%4d", &c[0].value, sel == 0); + drawsquare(conf, c[1].win, "%9s", m[c[1].value-1].name, sel == 1); - drawquare(conf, c[2].win, "%02d", &c[2].value, sel == 2); + drawsquare(conf, c[2].win, "%02d", &c[2].value, sel == 2); if (get_wch(&input) == ERR) continue; @@ -456,7 +454,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, /* if mount change */ c[2].max = m[c[1].value -1].days; /* if year change */ - if (c[1].value == 2 && ISLEAF(c[0].value)) + if (c[1].value == 2 && ISLEAP(c[0].value)) c[2].max = 29; /* set new day */ if (c[2].value > c[2].max) @@ -471,7 +469,7 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, /* if mount change */ c[2].max = m[c[1].value -1].days; /* if year change */ - if (c[1].value == 2 && ISLEAF(c[0].value)) + if (c[1].value == 2 && ISLEAP(c[0].value)) c[2].max = 29; /* set new day */ if (c[2].value > c[2].max) @@ -539,4 +537,4 @@ bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, end_dialog(conf, shadow, widget, textpad); return (retval); -} +}
\ No newline at end of file diff --git a/util_theme.c b/util_theme.c index e003e2c3d05f..caf62852e9f3 100644 --- a/util_theme.c +++ b/util_theme.c @@ -100,7 +100,7 @@ static struct property p[NPROPERTY] = { { "theme.button.f_shortcutcolor", COLOR, &t.button.f_shortcutcolor} }; -static char *color[8] = { +static const char *color[8] = { "black", "red", "green", @@ -111,7 +111,15 @@ static char *color[8] = { "white" }; -int savetheme(const char *file, char *errbuf, const char *version) +#define EXIT_FMTERROR(fmt, ...) do { \ + bsddialog_end(); \ + printf("Error: "); \ + printf(fmt, __VA_ARGS__); \ + printf(".\n"); \ + exit (255); \ +} while (0) + +void savetheme(const char *file, const char *version) { int i; unsigned int flags; @@ -119,20 +127,14 @@ int savetheme(const char *file, char *errbuf, const char *version) time_t clock; FILE *fp; - if (bsddialog_get_theme(&t) != BSDDIALOG_OK) { - sprintf(errbuf, "Cannot save theme: %s", bsddialog_geterror()); - return (BSDDIALOG_ERROR); - } + if (bsddialog_get_theme(&t) != BSDDIALOG_OK) + EXIT_FMTERROR("cannot save theme: %s", bsddialog_geterror()); - if(time(&clock) < 0) { - sprintf(errbuf, "Cannot save profile (getting current time)"); - return (BSDDIALOG_ERROR); - } + if(time(&clock) < 0) + EXIT_FMTERROR("%s", "cannot save profile getting current time"); - if ((fp = fopen(file, "w")) == NULL) { - sprintf(errbuf, "Cannot open %s to save profile", file); - return (BSDDIALOG_ERROR); - } + if ((fp = fopen(file, "w")) == NULL) + EXIT_FMTERROR("cannot open %s to save profile", file); fprintf(fp, "### bsddialog theme - %s", ctime(&clock)); fputs("# Refer to bsddialog(3) manual for theme.* properties\n", fp); @@ -167,11 +169,15 @@ int savetheme(const char *file, char *errbuf, const char *version) } fclose(fp); +} - return (BSDDIALOG_OK); +void setdeftheme(enum bsddialog_default_theme theme) +{ + if (bsddialog_set_default_theme(theme) != BSDDIALOG_OK) + EXIT_FMTERROR("%s", bsddialog_geterror()); } -int loadtheme(const char *file, char *errbuf) +void loadtheme(const char *file) { bool boolvalue; char charvalue, *value; @@ -181,21 +187,16 @@ int loadtheme(const char *file, char *errbuf) enum bsddialog_color bg, fg; FILE *fp; - if (bsddialog_get_theme(&t) != BSDDIALOG_OK) { - sprintf(errbuf, "Cannot get current theme: %s", + if (bsddialog_get_theme(&t) != BSDDIALOG_OK) + EXIT_FMTERROR("Cannot get current theme: %s", bsddialog_geterror()); - return (BSDDIALOG_ERROR); - } - if((fp = fopen(file, "r")) == NULL) { - sprintf(errbuf, "Cannot open theme \"%s\"", file); - return (BSDDIALOG_ERROR); - } + if((fp = fopen(file, "r")) == NULL) + EXIT_FMTERROR("Cannot open theme \"%s\"", file); -#define RETURN_ERROR(name, error) do { \ - sprintf(errbuf, "%s for \"%s\"", error, name); \ +#define EXIT_ERROR(name, error) do { \ fclose(fp); \ - return (BSDDIALOG_ERROR); \ + EXIT_FMTERROR("%s for \"%s\"", error, name); \ } while (0) while(fgets(line, BUFSIZ, fp) != NULL) { @@ -211,7 +212,7 @@ int loadtheme(const char *file, char *errbuf) if (i >= NPROPERTY) { if (strcmp(name, "version") == 0) continue; - RETURN_ERROR(name, "Unknown theme property name"); + EXIT_ERROR(name, "Unknown theme property name"); } switch (p[i].type) { case CHAR: @@ -219,17 +220,17 @@ int loadtheme(const char *file, char *errbuf) value[0] == '\0') value++; if (sscanf(value, "%c", &charvalue) != 1) - RETURN_ERROR(p[i].name, "Cannot get a char"); + EXIT_ERROR(p[i].name, "Cannot get a char"); *((int*)p[i].value) = charvalue; break; case INT: if (sscanf(value, "%d", &intvalue) != 1) - RETURN_ERROR(p[i].name, "Cannot get a int"); + EXIT_ERROR(p[i].name, "Cannot get a int"); *((int*)p[i].value) = intvalue; break; case UINT: if (sscanf(value, "%u", &uintvalue) != 1) - RETURN_ERROR(p[i].name, "Cannot get a uint"); + EXIT_ERROR(p[i].name, "Cannot get a uint"); *((unsigned int*)p[i].value) = uintvalue; break; case BOOL: @@ -239,19 +240,19 @@ int loadtheme(const char *file, char *errbuf) break; case COLOR: if (sscanf(value, "%s %s", c1, c2) != 2) - RETURN_ERROR(p[i].name, "Cannot get 2 colors"); + EXIT_ERROR(p[i].name, "Cannot get 2 colors"); /* Foreground */ for (j = 0; j < 8 ; j++) if ((strstr(c1, color[j])) != NULL) break; if ((fg = j) > 7) - RETURN_ERROR(p[i].name, "Bad foreground"); + EXIT_ERROR(p[i].name, "Bad foreground"); /* Background */ for (j = 0; j < 8 ; j++) if ((value = strstr(c2, color[j])) != NULL) break; if ((bg = j) > 7) - RETURN_ERROR(p[i].name, "Bad background"); + EXIT_ERROR(p[i].name, "Bad background"); /* Flags */ flags = 0; if (strstr(value, "bold") != NULL) @@ -268,11 +269,9 @@ int loadtheme(const char *file, char *errbuf) fclose(fp); bsddialog_set_theme(&t); - - return (BSDDIALOG_OK); } -int bikeshed(struct bsddialog_conf *conf, char *errbuf) +void bikeshed(struct bsddialog_conf *conf) { int margin, i; int colors[8] = {0, 0, 0, 0 ,0 ,0 , 0, 0}; @@ -284,7 +283,7 @@ int bikeshed(struct bsddialog_conf *conf, char *errbuf) /* theme */ if (bsddialog_get_theme(&t) != BSDDIALOG_OK) - return (BSDDIALOG_ERROR); + EXIT_FMTERROR("%s", bsddialog_geterror()); for (i = 0; i < 6; i++) { do { @@ -339,7 +338,7 @@ int bikeshed(struct bsddialog_conf *conf, char *errbuf) t.button.shortcutcolor = bsddialog_color(col[1], col[5], 0); if (bsddialog_set_theme(&t)) - return (BSDDIALOG_ERROR); + EXIT_FMTERROR("%s", bsddialog_geterror()); /* conf */ conf->button.always_active = (rand() % 2 == 0) ? true : false; @@ -351,6 +350,4 @@ int bikeshed(struct bsddialog_conf *conf, char *errbuf) memset(title + strlen(title), ' ', margin); conf->title = title; } - - return (BSDDIALOG_OK); } diff --git a/util_theme.h b/util_theme.h index fd9b32db1204..bf51447dfb2c 100644 --- a/util_theme.h +++ b/util_theme.h @@ -28,8 +28,9 @@ #ifndef _BSDDIALOG_UTILITY_THEME_H_ #define _BSDDIALOG_UTILITY_THEME_H_ -int savetheme(const char *file, char *errbuf, const char *version); -int loadtheme(const char *file, char *errbuf); -int bikeshed(struct bsddialog_conf *conf, char *errbuf); +void savetheme(const char *file, const char *version); +void loadtheme(const char *file); +void setdeftheme(enum bsddialog_default_theme theme); +void bikeshed(struct bsddialog_conf *conf); #endif |