diff options
author | Alfonso Siciliano <alfsiciliano@gmail.com> | 2022-01-28 08:14:55 +0000 |
---|---|---|
committer | Baptiste Daroussin <bapt@FreeBSD.org> | 2022-01-28 08:14:55 +0000 |
commit | 02db4a1234b3bd9cf153e567827fd387cf91bfb2 (patch) | |
tree | 6a8d148a11a4a9d58ba1adb078d72e491339652b | |
parent | 77a55d2c3b4dd48a9a608736a9ba7ebce700bae1 (diff) |
55 files changed, 4003 insertions, 3489 deletions
diff --git a/GNUMakefile b/GNUMakefile index 7480ae33ec21..69cec29d6a67 100644 --- a/GNUMakefile +++ b/GNUMakefile @@ -1,14 +1,14 @@ # PUBLIC DOMAIN - NO WARRANTY, see: -# <http://creativecommons.org/publicdomain/zero/1.0/> +# <http://creativecommons.org/publicdomain/zero/1.0/> # -# Written by Alfonso Sabato Siciliano +# Written in 2021 by Alfonso Sabato Siciliano OUTPUT= bsddialog SOURCES= bsddialog.c OBJECTS= $(SOURCES:.c=.o) LIBPATH= ./lib LIBBSDDIALOG= $(LIBPATH)/libbsddialog.so -CFLAGS= -g -Wall -I$(LIBPATH) +CFLAGS= -Wall -I$(LIBPATH) LDFLAGS= -Wl,-rpath=$(LIBPATH) -L$(LIBPATH) -lbsddialog RM = rm -f @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2021, Alfonso Sabato Siciliano +Copyright (c) 2021-2022, Alfonso Sabato Siciliano Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -1,7 +1,7 @@ -# Any copyright is dedicated to the Public Domain, see: +# PUBLIC DOMAIN - NO WARRANTY, see: # <http://creativecommons.org/publicdomain/zero/1.0/> # -# Written by Alfonso Sabato Siciliano +# Written in 2021 by Alfonso Sabato Siciliano OUTPUT= bsddialog SOURCES= bsddialog.c @@ -9,8 +9,19 @@ OBJECTS= ${SOURCES:.c=.o} LIBPATH= ${.CURDIR}/lib LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so -CFLAGS= -Wall -I${LIBPATH} -LDFLAGS= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog +CFLAGS+= -I${LIBPATH} -std=gnu99 -Wno-format-zero-length \ +-fstack-protector-strong -Wsystem-headers -Werror -Wall -Wno-format-y2k -W \ +-Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ +-Wno-uninitialized -Wno-pointer-sign -Wno-empty-body -Wno-string-plus-int \ +-Wno-unused-const-variable -Wno-tautological-compare -Wno-unused-value \ +-Wno-parentheses-equality -Wno-unused-function -Wno-enum-conversion \ +-Wno-unused-local-typedef -Wno-address-of-packed-member -Qunused-arguments +# `make -DDEBUG` +.if defined(DEBUG) +CFLAGS= -g -Wall -I${LIBPATH} +LIBDEBUG= -DDEBUG +.endif +LDFLAGS+= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog BINDIR= /usr/local/bin MAN= ${OUTPUT}.1 @@ -26,11 +37,7 @@ ${OUTPUT}: ${LIBBSDDIALOG} ${OBJECTS} ${CC} ${LDFLAGS} ${OBJECTS} -o ${.PREFIX} ${LIBBSDDIALOG}: -.if defined(PORTNCURSES) - make -C ${LIBPATH} -DPORTNCURSES -.else - make -C ${LIBPATH} -.endif + make -C ${LIBPATH} ${LIBDEBUG} .c.o: ${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET} diff --git a/README.md b/README.md index 31579f519ab6..17af3a0db8e5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,21 @@ -# BSDDialog +# BSDDialog 0.1 -**Work In Progress!** This project provides **bsddialog** and **libbsddialog**, an utility and a -library to build scripts and tools with *TUI Widgets*. +library to build scripts and tools with TUI dialogs and widgets. -Description: + +## Intro + +Briefly: <https://www.freebsd.org/status/report-2021-04-2021-06/#_bsddialog_tui_widgets> +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> @@ -23,35 +31,39 @@ FreeBSD: % ./bsddialog --msgbox "Hello World!" 8 20 ``` -If you are using XFCE install -[devel/ncurses](https://www.freshports.org/devel/ncurses/) - -``` -% sudo pkg install ncurses -% git clone https://gitlab.com/alfix/bsddialog.git -% cd bsddialog -% make -DPORTNCURSES -% ./bsddialog --msgbox "Hello World!" 8 20 -``` - Output:  -Examples utility: +## Utility + +**Dialogs:** + +--checklist, --datebox, --form, --gauge, --inputbox, --menu, --mixedform, +--mixedgauge, --msgbox, --passwordbox, --passwordform, --pause, --radiolist, +--rangebox, --textbox, --timebox, --treeview, --yesno. + +**Manual** + + - [bsddialog(1)](https://alfonsosiciliano.gitlab.io/posts/2022-01-26-manual-bsddialog.html) + + +**Examples**: + ``` -% ./bsddialog --title msgbox --msgbox "Hello World!" 5 30 -% ./bsddialog --theme default --title msgbox --msgbox "Hello World!" 5 30 -% ./bsddialog --begin-y 2 --title yesno --yesno "Hello World!" 5 30 -% ./bsddialog --ascii-lines --pause "Hello World!" 8 50 5 -% ./bsddialog --checklist "Space to select" 0 0 0 Name1 Desc1 off Name2 Desc2 on Name3 Desc3 off -% ./bsddialog --backtitle "TITLE" --title yesno --hline "bsddialog" --yesno "Hello World!" 5 25 -% ./bsddialog --extra-button --help-button --defaultno --yesno "Hello World!" 0 0 +% ./bsddialog --backtitle "TITLE" --title msgbox --msgbox "Hello World!" 5 30 +% ./bsddialog --theme blackwhite --title msgbox --msgbox "Hello World!" 5 30 +% ./bsddialog --begin-y 2 --default-no --title yesno --yesno "Hello World!" 5 30 +% ./bsddialog --ascii-lines --pause "Hello World!" 8 50 10 +% ./bsddialog --checklist "Space to select" 0 0 0 Name1 Desc1 off Name2 Desc2 on +% ./bsddialog --title yesno --hline "bsddialog" --yesno "Hello World!" 5 25 +% ./bsddialog --extra-button --help-button --yesno "Hello World!" 0 0 ``` -and + +and [Examples](https://gitlab.com/alfix/bsddialog/-/tree/main/examples_utility) +in the _Public Domain_ to build new projects: ``` -% sh ./examples_utility/buildlist.sh % sh ./examples_utility/checklist.sh % sh ./examples_utility/form.sh % sh ./examples_utility/gauge.sh @@ -68,12 +80,26 @@ and % sh ./examples_utility/yesno.sh ``` -Examples library: +## Library + +**API** + + - [bsddialog.h](https://gitlab.com/alfix/bsddialog/-/blob/main/lib/bsddialog.h) + - [bsddialog\_theme.h](https://gitlab.com/alfix/bsddialog/-/blob/main/lib/bsddialog_theme.h) + + +**Manual** + + - [bsddialog(3)](https://alfonsosiciliano.gitlab.io/posts/2022-01-15-manual-libbsddialog.html) + + +**Examples**: + +[Examples](https://gitlab.com/alfix/bsddialog/-/tree/main/examples_library) +in the _Public Domain_ to build new projects: ``` % cd examples_library % sh compile -% ./buildlist -% ./compile % ./datebox % ./form % ./infobox @@ -83,85 +109,8 @@ Examples library: % ./pause % ./radiolist % ./rangebox -% ./sade % ./theme % ./timebox -% ./treeview % ./yesno ``` - -Use Cases: - - - [portconfig](https://gitlab.com/alfix/portconfig) - - -## Features - -**Common Options:** - ---ascii-lines, --aspect *ratio* (for infobox, msgbox and yesno), ---backtitle *backtitle*, --begin-x *x* (--begin *y y*), -(--begin *y x*), --cancel-label *string*, -clear (test with multiple widgets), ---colors, --date-format *format*, --default-button *string*, --defaultno, ---default-item *string*, ---exit-label *string*, --extra-button, --extra-label *string*, ---hfile *filename* (for completed widgets), --help, --help-button, ---help-label *string*, --help-status, --help-tags, --hline *string*, --ignore, ---insecure, --item-help, --max-input *size*, --no-cancel, --nocancel, ---no-label *string*, --no-items, --no-lines, --no-ok, ---nook, --no-shadow, --no-tags, --ok-label *string*, --output-fd *fd*, ---output-separator *string*, --print-version, ---print-size (todo move lib -> utility), --quoted (quotes all != dialog), ---print-maxsize, --shadow, --single-quoted (add --quote-with *ch*?), ---separator *string* (alias --output-separator *string*), ---separate-output (rename --separate-output-withnl?), --sleep *secs*, --stderr, ---stdout, --theme *string* ("bsddialog", "dialog", "blackwhite"), ---time-format *format*, --title *title*, --version, --yes-label *string*. - -**Widgets:** - infobox (do not clear the screen), msgbox, - yesno (dialog renames "yes/no" -> "ok/cancel" with --extra-button --help-button). - checklist, radiolist, menu, mixedlist, treeview, textbox, mixedgauge, datebox, - timebox, gauge, rangebox, pause. - - - Without resize: - - form, inputbox, mixedform, passwordbox, passwordform. - - - Without autosize, resize, F1: - - buildlist - - - -## TODO - - -**Common Options:** - -| Option | Status | Note | -| ---------------------------- | ----------- | ------------------------------- | -| --cr-wrap | In progress | text | -| --no-collapse | In progress | text | -| --no-nl-expand | In progress | text | -| --trim | In progress | text | - - -To evaluate / Not planned in the short term / not in bsdinstall: - ---create-rc *file*, --iso-week, --no-mouse, --print-text-only *str h w*, ---print-text-size *str h w*, --reorder, -scrollbar, --separate-widget *string*, ---size-err, --timeout *secs*,--trace *filename*, --visit-items, ---week-start *day*, --keep-tite, --keep-window, --last-key, --no-kill, ---column-separator *string*, --input-fd *fd*, --tab-correct, --tab-len *n* - - -**Widgets:** - -To evaluate / Not planned in the short term: - -tailbox (textbox/fseek), tailboxbg, dselect, fselect, inputmenu, editbox, -calendar (use datebox), prgbox, programbox, progressbox. diff --git a/bsddialog.1 b/bsddialog.1 index bfee3229bd1f..c426c529e242 100644 --- a/bsddialog.1 +++ b/bsddialog.1 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2021 Alfonso Sabato Siciliano +.\" Copyright (c) 2021-2022 Alfonso Sabato Siciliano .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -22,45 +22,569 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 11, 2021 +.Dd January 26, 2022 .Dt BSDDIALOG 1 .Os .Sh NAME .Nm bsddialog -.Nd terminal dialogs and widgets +.Nd TUI dialogs .Sh SYNOPSIS -.Nm bsddialog -.Fl -help -.Nm bsddialog -.Fl -version -.Nm bsddialog -.Op Fl Ar -common-opts -.Fl Ar -widget -.Fl Artext -.Fl Arheight -.Fl Arwidth -.Op Fl Ar -widget-opts +.Nm +.Fl Fl help +.Nm +.Fl Fl version +.Nm +.Op Fl Fl common-opts +.Fl Fl dialog +.Ar text +.Ar rows +.Ar cols +.Op Ar dialog-opts .Sh DESCRIPTION The -.Nm BSDDialog -is an utility to write a script with a Text User Interface. It can build -dialogs and widgets: to show messages, to get input and to inform about a -computation status. -.\" .Sh ENVIRONMENT -.\" For sections 1, 6, 7, and 8 only. -.\" .Sh FILES -.\" .Sh EXIT STATUS -.\" For sections 1, 6, and 8 only. -.\" .Sh EXAMPLES -.\" .Sh DIAGNOSTICS -.\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. +.Nm bsddialog +utility builds Text User Interface dialogs and widgets: to display messages, +to get input and to inform about a computation status. +.Pp +The options +.Fl Fl help +and +.Fl Fl version +print the list of options and the version, respectively, then exit. +.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. +.Ar rows +and +.Ar cols +are the height and width, 0 for autosize and -1 for fullscreen. +The possible input got from the user interface is printed to standard error. +.Ss Common 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 ascii-lines +Ascii characters to draw lines. +.It Fl Fl backtitle Ar backtitle +Title on the top side of the screen. +.It Fl Fl begin-x Ar x +Dialog horizontal position, 0 is the left screen side, -1 center. +.It Fl Fl begin-y Ar y +Dialog vertical position, 0 is the top screen side, -1 center. +.It Fl Fl cancel-label Ar label +Label for the +.Dq Cancel +button. +.It Fl Fl clear +Hide the dialog at exit. +.It Fl Fl colors +Enable highlights for text, the following sequences are considered escapes: +.Bl -column -compact +.It Dq \eZ0 +black. +.It Dq \eZ1 +red. +.It Dq \eZ2 +green. +.It Dq \eZ3 +yellow. +.It Dq \eZ4 +blue. +.It Dq \eZ5 +magenta. +.It Dq \eZ6 +cyan. +.It Dq \eZ7 +white. +.It Dq \eZr +reverse foreground and background colors. +.It Dq \eZR +disable reverse. +.It Dq \eZb +bold. +.It Dq \eZB +disable bold. +.It Dq \eZu +underline. +.It Dq \eZU +disable underline. +.It Dq \eZn +restore to normal text. +.El +.It Fl Fl cr-wrap +Replace new line with a space in +.Ar text . +.It Fl Fl date-format Ar format +String accepted by +.Xr strftime 3 +to customize the output of +.Fl Fl datebox . +.It Fl Fl default-button Ar label +Focus on the button with +.Ar label +on startup. +.It Fl Fl default-item Ar name +Focus on the item with +.Ar name , +for Checklist, Menu, Radiolist and Treeview. +.It Fl Fl default-no +Focus on +.Dq Cancel +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-cancelvalue +Exits with the +.Dq Cancel +button value if the ESC key is pressed. +.It Fl Fl exit-label Ar label +Equivalent to +.Fl Fl ok-label . +.It Fl Fl extra-button +Add a button with +.Dq Extra +label. +.It Fl Fl extra-label Ar label +Set +.Ar label +for the +.Dq Extra +button. +.It Fl Fl generic-button1 Ar label +Add a button with +.Ar label . +.It Fl Fl generic-button2 Ar label +Add a button with +.Ar label . +.It Fl Fl help-button +Add a button with +.Dq Help +label. +.It Fl Fl help-label Ar label +Set +.Ar label +for +.Dq Help +button. +.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 +in a Textbox if F1 key is pressed, +.It Fl Fl hline Ar string +Dialog subtitle. +.It Fl Fl hmsg Ar string +Open a Msgbox with +.Ar string +if the F1 key is pressed. +.It Fl Fl ignore +Do not exit with unknown options. +.It Fl Fl insecure +Print +.Sq * +to hide passwords while typing, default space +.Sq " " . +.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 max-input Ar size +Maximum length of the input for +.Fl Fl input-box +ans +.Fl Fl passwordbox , +default 2048. +.It Fl Fl no-cancel +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 +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-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 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. +.It Fl Fl print-size +Print Dialog height and widget at exit. +.It Fl Fl print-version +Print version. +.It Fl Fl quoted +Quote items in output, default only when necessary. +.It Fl Fl separate-output +Separate selected items with a new line. +.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 +Use single quote for items in output. +.It Fl Fl sleep Ar secs +Wait +.Ar secs +seconds to close the dialog. +.It Fl Fl stderr +Print input from user interface to standand error, default. +.It Fl Fl stdout +Print input from user interface to standard output. +.It Fl Fl tab-len Ar spaces +Number of spaces to print a TAB in +.Ar text . +.It Fl Fl theme Ar theme +Set a graphical style: blackwhite, bsddialog, default or dialog. +.It Fl Fl time-format Ar format +String accepted by +.Xr strftime 3 +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 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. +An item has a +.Ar name , +.Ar desc +and a default +.Ar status +specified by +.Dq on +or +.Dq off . +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 +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 maxvaluelen Oc ... +Dialog to get a list of strings via forms. +A form has a +.Ar label +at the position +.Ar ylabel +and +.Ar xlabel , +a field to get the input at the position +.Ar yfield +and +.Ar xfield +with graphical length +.Ar fieldlen , +.Ar maxvaluelen +is the maximum input length. +The field can be customized, if +.Ar fieldlen +is 0 its length is the absolute value of +.Ar maxvaluelen , +if +.Ar maxvaluelen +is negative the field is read only, +.Ar init +is a default value. +.Ar formrows +is the graphical height of the list, has to be at least the number of forms. +.It Fl Fl gauge Ar text Ar rows Ar cols Op Ar percentage +Dialog with a bar to shows +.Ar percentage , +then it waits to read +.Dq XXX +from the standard input, then the first string replaces percentage and the +following strings replace +.Ar text +until the next +.Dq XXX , +the loop ends reading +.Dv EOF . +.It Fl Fl infobox Ar text Ar rows Ar cols +Dialog without buttons to display a message and to exit immediately. +.It Fl Fl inputbox Ar text Ar rows Ar cols Op Ar init +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. +An item has a +.Ar name +and a +.Ar desc . +The name of the selected item is printed to standard error. +.Ar menurows +is the graphical height of the list, 0 for autosize. +.It Fl Fl mixedform Ar text Ar rows Ar cols Ar formrows Oo Ar label Ar ylabel \ +Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar maxvaluelen Ar flag Oc ... +Dialog to get a list of strings via forms. +A form has a +.Ar label +at the position +.Ar ylabel +and +.Ar xlabel , +a field to get the input with graphical length +.Ar fieldlen +at the position +.Ar yfield +and +.Ar xfield , +.Ar maxvaluelen +is the maximum input length, +.Ar init +is a default value, +.Ar flag +can be 0 for normal field, 1 to hide the typed characters and 2 to set the +field read only. +.Ar formrows +is the graphical height of the list, has to be at least the number of forms. +.It Fl Fl mixedgauge Ar text Ar rows Ar cols Ar mainperc Oo Ar minilabel \ +Ar miniperc Oc ... +Dialog to show a main bar to represent +.Ar mainperc +from 0 to 100 and some mini bar with a +.Ar minilabel +string and a +.Ar miniperc +with value from 0 and 100 or negative to print a descriptive string: -1 +.Dq Succeeded , +-2 +.Dq Failed , +-3 +.Dq Passed , +-4 +.Dq Completed , +-5 +.Dq Checked , +-6 +.Dq Done , +-7 +.Dq Skipped , +-8 +.Dq \&In Progress , +-9 +a blank line, +-10 +.Dq N/A , +-11 +.Dq Pending . +.It Fl Fl msgbox Ar text Ar rows Ar cols +Dialog to diplay a message without the +.Dq Cancel +button. +.It Fl Fl passwordbox Ar text Ar rows Ar cols Op Ar init +Dialog to get a password, +.Ar init +is the default value. +.It Fl Fl passwordform Ar text Ar rows Ar cols Ar formrows Oo Ar label \ +Ar ylabel Ar xlabel Ar init Ar yfield Ar xfield Ar fieldlen Ar valuelen Oc ... +Dialog to get a list of passwords, equivalent to +.Fl Fl form +except typed characters are hidden. +.It Fl Fl pause Ar text Ar rows Ar cols Ar seconds +Dialog runs until the timeout in +.Ar seconds +expires or a button is pressed. +.It Fl Fl radiolist Ar text Ar rows Ar cols Ar menurows Oo Ar name Ar desc \ +Ar status Oc ... +Radiolist to select at most an item from a list via the SPACE key. +An item has a +.Ar name , +.Ar desc +and a default +.Ar status +specified by +.Dq on +or +.Dq off . +The name of the selected item is printed to standard error. +.Ar menurows +is the graphical height of the list, 0 for autosize. +.It Fl Fl rangebox Ar text Ar rows Ar cols Ar min Ar max Op Ar init +Dialog to select a value between +.Ar min +and +.Ar max , +.Ar init +is the default value, the keys UP, DOWN, HOME, END, PAGEUP and PAGEDOWN can +change it. +.It Fl Fl textbox Ar file Ar rows Ar cols +Opens and prints +.Ar file +the UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to navigate; +.Dq OK +button is renamed +.Dq EXIT . +.It Fl Fl timebox Ar text Ar rows Ar cols Op Ar hour Ar min Ar sec +Dialog to select a time. +.It Fl Fl treeview Ar text Ar rows Ar cols Ar menurows Oo Ar depth Ar name \ +Ar desc Ar status Oc ... +Equivalent to Radiolist with +.Fl Fl item-depth +and +.Fl Fl no-name . +.It Fl Fl yesno Ar text Ar rows Ar cols +.Dq Yes-No Question , +.Dq OK +and +.Dq Cancel +buttons are renamed +.Dq Yes +and +.Dq \&No . +.El +.Sh EXIT STATUS +The +.Nm +utility exits 255 on unsuccessful, otherwise depending on the button or key +pressed the following values can be returned: +.Bl -column -compact +.It 0 +.Dq OK , +.Dq Yes +or +.Dq Exit +button. +.It 1 +.Dq Cancel +or +.Dq \&No +button. +.It 2 +.Dq Help +button. +.It 3 +.Dq Extra +button. +.It 4 +Timeout. +.It 5 +ESC key. +.It 6 +Generic 1 button. +.It 7 +Generic 2 button. +.El +.Sh EXAMPLES +Backtitle, title and message: +.Dl bsddialog --backtitle MESSAGE --title Msgbox --msgbox Message 0 0 +.Pp +Yes-No Question and theme: +.Dl bsddialog --theme blackwhite --yesno Question 10 30 +.Pp +Checklist: +.Dl bsddialog --checklist Checklist 0 0 3 N1 \&D1 off N2 D2 on N3 D3 off +.Pp +Mixedgauge: +.Dl bsddialog --sleep 3 --mixedgauge Example 10 30 60 L1 "\(dq" -1" L2 30 +.Pp +Form: +.Dl bsddialog --form Form 0 0 2 L1: 1 1 X 1 5 20 25 L2: 2 1 X 2 5 20 25 +.Pp +Gauge script: +.Bd -literal -offset indent -compact +i=1 +for c in A B C D E F G H +do + sleep 1 + echo XXX + echo "$(expr $(expr $i "*" 100) "/" 8)" + echo "[$i/8] Char: $c" + echo XXX + if [ $i -eq 8 ] + then + sleep 1 + echo EOF + fi + i=`expr $i + 1` +done | bsddialog --title Gauge --gauge "Starting..." 10 70 +.Ed +.Pp +Mixedgauge script: +.Bd -literal -offset indent -compact +perc=0 +while [ $perc -le 100 ] +do + bsddialog --sleep 1 --title Mixedgauge \e + --mixedgauge "\enExample...\en" 0 0 $perc \e + "Hidden" " -9" \e + "Label 1" " -4" \e + "Label 2" " -4" \e + "Label 3" $perc + + perc=`expr $perc + 20` +done +.Ed .Sh SEE ALSO .Xr bsddialog 3 -.\" .Sh HISTORY -.\" .Sh AUTHORS -.Sh CAVEATS -autosize -compatibility text +.Sh HISTORY +The +.Nm bsddialog +utility first appeared in +.Fx 14.0 . +.Sh AUTHORS +.Nm bsddialog +was written by +.An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com . .Sh BUGS -buildlist -forms +The forms do not resize the dialog after a terminal change and does not provides +scrolling for items.
\ No newline at end of file diff --git a/bsddialog.c b/bsddialog.c index aa87dec2962b..6bd11fd458b8 100644 --- a/bsddialog.c +++ b/bsddialog.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,8 @@ #include <sys/ioctl.h> #include <getopt.h> +#include <locale.h> +#include <signal.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -37,12 +39,11 @@ #include <bsddialog.h> #include <bsddialog_theme.h> -#define BSDDIALOG_VERSION "0.0.1" +#define BSDDIALOG_VERSION "0.1" enum OPTS { /* Common options */ ASCII_LINES = '?' + 1, - ASPECT_RATIO, BACKTITLE, BEGIN_X, BEGIN_Y, @@ -51,19 +52,24 @@ enum OPTS { COLORS, CR_WRAP, DATE_FORMAT, - DEFAULTNO, DEFAULT_BUTTON, DEFAULT_ITEM, + DEFAULT_NO, + DISABLE_ESC, + ESC_CANCELVALUE, EXIT_LABEL, EXTRA_BUTTON, EXTRA_LABEL, + GENERIC_BUTTON1, + GENERIC_BUTTON2, HELP, HELP_BUTTON, HELP_LABEL, HELP_STATUS, HELP_TAGS, - HFILE, + HFILE, HLINE, + HMSG, IGNORE, INSECURE, ITEM_DEPTH, @@ -71,16 +77,13 @@ enum OPTS { ITEM_PREFIX, MAX_INPUT, NO_CANCEL, - NOCANCEL, NO_COLLAPSE, NO_ITEMS, - NO_LABEL, NO_LINES, NO_NL_EXPAND, NO_OK, - NOOK, - NO_TAGS, NO_SHADOW, + NO_TAGS, OK_LABEL, OUTPUT_FD, OUTPUT_SEPARATOR, @@ -89,20 +92,18 @@ enum OPTS { PRINT_VERSION, QUOTED, SEPARATE_OUTPUT, - SEPARATOR, SHADOW, SINGLE_QUOTED, SLEEP, STDERR, STDOUT, + TAB_LEN, THEME, TIME_FORMAT, TITLE, TRIM, VERSION, - YES_LABEL, - /* Widgets */ - BUILDLIST, + /* Dialogs */ CHECKLIST, DATEBOX, FORM, @@ -121,277 +122,245 @@ enum OPTS { TEXTBOX, TIMEBOX, TREEVIEW, - YESNO, + YESNO }; -/* libbsddialog does not support NULL string for now */ -static char *nostring = ""; /* Menus flags and options */ -static bool item_prefix_flag, item_bottomdesc_flag, item_output_sepnl_flag; -static bool item_singlequote_flag, list_items_on_flag, item_tag_help_flag; -static bool item_always_quote_flag, item_depth_flag; -static char *item_output_sep_flag; +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; /* Time and calendar options */ -static char *date_fmt_flag, *time_fmt_flag; +static char *date_fmt_opt, *time_fmt_opt; /* Forms */ -static int max_input_form_flag; +static int unsigned max_input_form_opt; /* General flags and options */ -static int output_fd_flag; - -void usage(void); -/* widgets */ -#define BUILDER_ARGS struct bsddialog_conf conf, char* text, int rows, \ - int cols, int argc, char **argv, char *errbuf -int buildlist_builder(BUILDER_ARGS); -int checklist_builder(BUILDER_ARGS); -int datebox_builder(BUILDER_ARGS); -int form_builder(BUILDER_ARGS); -int gauge_builder(BUILDER_ARGS); -int infobox_builder(BUILDER_ARGS); -int inputbox_builder(BUILDER_ARGS); -int menu_builder(BUILDER_ARGS); -int mixedform_builder(BUILDER_ARGS); -int mixedgauge_builder(BUILDER_ARGS); -int msgbox_builder(BUILDER_ARGS); -int passwordbox_builder(BUILDER_ARGS); -int passwordform_builder(BUILDER_ARGS); -int pause_builder(BUILDER_ARGS); -int radiolist_builder(BUILDER_ARGS); -int rangebox_builder(BUILDER_ARGS); -int textbox_builder(BUILDER_ARGS); -int timebox_builder(BUILDER_ARGS); -int treeview_builder(BUILDER_ARGS); -int yesno_builder(BUILDER_ARGS); +static int output_fd_opt; static void custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim, - char *text, char *buf) -{ - int i, j; - - 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'; - i++; - break; - case 't': - if (no_collapse) { - j++; - buf[j] = 't'; - } else - buf[j] = '\t'; - i++; - break; - } - break; - case '\n': - buf[j] = cr_wrap ? ' ' : '\n'; - break; - case '\t': - buf[j] = no_collapse ? '\t' : ' '; - break; - default: - buf[j] = text[i]; - } - i++; - j += (buf[j] == ' ' && trim && j > 0 && buf[j-1] == ' ') ? - 0 : 1; - } - buf[j] = '\0'; -} + char *text, char *buf); + +static void sigint_handler(int sig); -void usage(void) +/* Dialogs */ +#define BUILDER_ARGS struct bsddialog_conf conf, char* text, int rows, \ + int cols, int argc, char **argv, char *errbuf +static int checklist_builder(BUILDER_ARGS); +static int datebox_builder(BUILDER_ARGS); +static int form_builder(BUILDER_ARGS); +static int gauge_builder(BUILDER_ARGS); +static int infobox_builder(BUILDER_ARGS); +static int inputbox_builder(BUILDER_ARGS); +static int menu_builder(BUILDER_ARGS); +static int mixedform_builder(BUILDER_ARGS); +static int mixedgauge_builder(BUILDER_ARGS); +static int msgbox_builder(BUILDER_ARGS); +static int passwordbox_builder(BUILDER_ARGS); +static int passwordform_builder(BUILDER_ARGS); +static int pause_builder(BUILDER_ARGS); +static int radiolist_builder(BUILDER_ARGS); +static int rangebox_builder(BUILDER_ARGS); +static int textbox_builder(BUILDER_ARGS); +static int timebox_builder(BUILDER_ARGS); +static int treeview_builder(BUILDER_ARGS); +static int yesno_builder(BUILDER_ARGS); + +static void usage(void) { - - printf("usage: bsddialog --help\n" - " bsddialog --version\n" - " bsddialog [--<common-opts>] --<widget> <text> " - "<height> <width> [--<widget-opts>]\n"); + printf("usage: bsddialog --help\n"); + printf(" bsddialog --version\n"); + printf(" bsddialog [--<common-opts>] --<dialog> <text> <rows> " + "<cols> [--<dialog-opts>]\n"); printf("\n"); + printf("Common Options:\n"); - printf("--ascii-lines, --aspect <ratio>, --backtitle <backtitle>, " - "--begin-x <x>, --begin-y <y>, --cancel-label <string>, " - "--clear, --colors, --date-format <format>, " - "--default-button <label>, --defaultno, --default-item <name>," - "--exit-label <label>, --extra-button, --extra-label <label>," - "--hfile <filename>, --help-button, --help-label <label>, " - "--help-status, --help-tags, --hline string, --ignore, " - "--insecure, --item-depth, --item-help, --items-prefix, " - "--max-input <size>, --no-cancel, --nocancel, " - "--no-label <label>, --no-items, " - "--no-lines, --no-ok, --nook, --no-shadow, --no-tags, " - "--ok-label <label>, --output-fd <fd>, " - "--output-separator <sep>, --print-version, --print-size, " - "--quoted, --print-maxsize, --shadow, --single-quoted, " - "--separator <sep>, --separate-output, --sleep <secs>, " - "--stderr, --stdout, --theme <blackwhite|bsddialog|dialog>, " - "--time-format <format>, --title <title>, " - "--yes-label <string>.\n"); + printf("--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, --esc-cancelvalue, --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 <filename>, --hline <string>, --hmsg <string>, --ignore, " + "--insecure, --item-depth, --item-help, --items-prefix, " + "--max-input <size>, --no-cancel, --nocancel, --no-collapse, " + "--no-items, --no-label <label>, --no-lines, --no-nl-expand, " + "--no-ok, --nook, --no-shadow, --no-tags, --ok-label <label>, " + "--output-fd <fd>, --output-separator <sep>, --print-maxsize, " + "--print-size, --print-version, --quoted, --separate-output, " + "--separator <sep>, --shadow, --single-quoted, --sleep <secs>, " + "--stderr, --stdout, --tab-len <spaces>, " + "--theme <blackwhite|bsddialog|default|dialog>, " + "--time-format <format>, --title <title>, --trim, --version, " + "--yes-label <label>.\n"); printf("\n"); - printf("Widgets:\n"); - printf("--buildlist <text> <rows> <cols> <menurows> [<name> <desc> " - "<on|off> ...]\n" - "--checklist <text> <rows> <cols> <menurows> [<name> <desc> " - "<on|off> ...]\n" - "--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n" - "--form <text> <rows> <cols> <formrows> [<label> <ylabel> " - "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvalue> " - "...]\n" - "--gauge <text> <rows> <cols> [<perc\\n> [<text> ...] XXX " - "...] EOF\n" - "--infobox <text> <rows> <cols>\n" - "--inputbox <text> <rows> <cols> [init]\n" - "--menu <text> <rows> <cols> <menurows> [<name> <desc> ...]\n" - "--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> " - "<xlabe> <init> <yfield> <xfield> <fieldlen> <maxvalue> " - "<0|1|2> ...]\n" - "--mixedgauge <text> <rows> <cols> <mainperc> [<label> " - "<01234567|-perc> ...]\n" - "--msgbox <text> <rows> <cols>\n" - "--passwordbox <text> <rows> <cols> [init]\n" - "--passwordform <text> <rows> <cols> <formrows> [<label> " - "<ylabel> <xlabe> <init> <yfield> <xfield> <fieldlen> " - "<maxvalue> ...]\n" - "--pause <text> <rows> <cols> <secs>\n" - "--radiolist <text> <rows> <cols> <menurows> [<name> <desc> " - "<on|off> ...]\n" - "--rangebox <text> <rows> <cols> <min> <max> <default>\n" - "--textbox <file> <rows> <cols>\n" - "--timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n" - "--treeview <text> <rows> <cols> <menurows> [<depth> <name> " - "<desc> <on|off> ...]\n" - "--yesno <text> <rows> <cols>\n"); + + printf("Dialogs:\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> " + "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen>] " + "...\n"); + printf("--gauge <text> <rows> <cols> [<perc>]\n"); + printf("--infobox <text> <rows> <cols>\n"); + printf("--inputbox <text> <rows> <cols> [init]\n"); + printf("--menu <text> <rows> <cols> <menurows> [<name> <desc>] ...\n"); + printf("--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> " + "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvaluelen> " + "<0|1|2>] ...\n"); + printf("--mixedgauge <text> <rows> <cols> <mainperc> [<minilabel> " + "<miniperc>] ...\n"); + printf("--msgbox <text> <rows> <cols>\n"); + printf("--passwordbox <text> <rows> <cols> [init]\n"); + printf("--passwordform <text> <rows> <cols> <formrows> [<label> " + "<ylabel> <xlabel> <init> <yfield> <xfield> <fieldlen> " + "<maxvaluelen>] ...\n"); + printf("--pause <text> <rows> <cols> <secs>\n"); + printf("--radiolist <text> <rows> <cols> <menurows> [<name> <desc> " + "<on|off>] ...\n"); + printf("--rangebox <text> <rows> <cols> <min> <max> [<init>]\n"); + printf("--textbox <file> <rows> <cols>\n"); + printf("--timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n"); + printf("--treeview <text> <rows> <cols> <menurows> [<depth> <name> " + "<desc> <on|off>] ...\n"); + printf("--yesno <text> <rows> <cols>\n"); + printf("\n"); + + printf("See 'man 1 bsddialog' for more information.\n"); } int main(int argc, char *argv[argc]) { - char *text, *backtitle_flag, errorbuilder[1024]; + bool cr_wrap_opt, no_collapse_opt, no_nl_expand_opt, trim_opt; + bool esc_cancelvalue_opt, ignore_opt, print_maxsize_opt;; int input, rows, cols, output, getH, getW; - int (*widgetbuilder)(BUILDER_ARGS) = NULL; - bool ignore_flag, print_maxsize_flag; + int (*dialogbuilder)(BUILDER_ARGS) = NULL; + enum bsddialog_default_theme theme_opt; + char *text, *backtitle_opt, errorbuilder[1024]; struct winsize ws; struct bsddialog_conf conf; - enum bsddialog_default_theme theme_flag; - bool cr_wrap_flag, no_collapse_flag, no_nl_expand_flag, trim_flag; - bsddialog_initconf(&conf); + setlocale(LC_ALL, ""); - backtitle_flag = NULL; - theme_flag = -1; - output_fd_flag = STDERR_FILENO; - print_maxsize_flag = false; - ignore_flag = false; + bsddialog_initconf(&conf); + conf.key.enable_esc = true; + conf.menu.on_without_ok = true; + conf.form.value_without_ok = true; + + backtitle_opt = NULL; + theme_opt = BSDDIALOG_THEME_DEFAULT; + output_fd_opt = STDERR_FILENO; + print_maxsize_opt = false; + ignore_opt = false; errorbuilder[0] = '\0'; - cr_wrap_flag = no_collapse_flag = no_nl_expand_flag = trim_flag = false; + cr_wrap_opt = no_collapse_opt = no_nl_expand_opt = trim_opt = false; + esc_cancelvalue_opt = false; + + 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; + item_always_quote_opt = false; + item_output_sep_opt = NULL; + item_default_opt = NULL; - item_output_sepnl_flag = item_singlequote_flag = false; - item_prefix_flag = item_bottomdesc_flag = item_depth_flag = false; - list_items_on_flag = item_tag_help_flag = false; - item_always_quote_flag = false; - item_output_sep_flag = NULL; + date_fmt_opt = time_fmt_opt = NULL; - date_fmt_flag = time_fmt_flag = NULL; - - max_input_form_flag = 0; + max_input_form_opt = 0; /* options descriptor */ struct option longopts[] = { - /* common options */ - {"ascii-lines", no_argument, NULL, ASCII_LINES }, - {"aspect", required_argument, NULL, ASPECT_RATIO }, - {"backtitle", required_argument, NULL, BACKTITLE }, - {"begin-x", required_argument, NULL, BEGIN_X }, - {"begin-y", required_argument, NULL, BEGIN_Y }, - {"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, DEFAULTNO }, - {"default-button", required_argument, NULL, DEFAULT_BUTTON }, - {"default-item", required_argument, NULL, DEFAULT_ITEM }, - {"exit-label", required_argument, NULL, EXIT_LABEL }, - {"extra-button", no_argument, NULL, EXTRA_BUTTON }, - {"extra-label", required_argument, NULL, EXTRA_LABEL }, - {"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 }, - {"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 }, - {"max-input", required_argument, NULL, MAX_INPUT }, - {"no-cancel", no_argument, NULL, NO_CANCEL }, - {"nocancel", no_argument, NULL, NOCANCEL }, - {"no-collapse", no_argument, NULL, NO_COLLAPSE }, - {"no-items", no_argument, NULL, NO_ITEMS }, - {"no-label", required_argument, NULL, NO_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, NOOK }, - {"no-tags", no_argument, NULL, NO_TAGS }, - {"no-shadow", no_argument, NULL, NO_SHADOW }, - {"ok-label", required_argument, NULL, OK_LABEL }, - {"output-fd", required_argument, NULL, OUTPUT_FD }, - {"separator", required_argument, NULL, SEPARATOR }, - {"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 }, - {"separate-output", no_argument, NULL, SEPARATE_OUTPUT }, - {"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 }, - {"theme_flag", 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, YES_LABEL }, - /* Widgets */ - {"buildlist", no_argument, NULL, BUILDLIST }, - {"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 } + /* 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}, + {"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-cancelvalue", no_argument, NULL, ESC_CANCELVALUE}, + {"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}, + {"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}, + {"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}, + {"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) { @@ -400,30 +369,23 @@ int main(int argc, char *argv[argc]) case ASCII_LINES: conf.ascii_lines = true; break; - case ASPECT_RATIO: - conf.aspect_ratio = atoi(optarg); - if (conf.aspect_ratio < 1) { - printf("Error: aspect cannot be < 1"); - return (BSDDIALOG_ERROR); - } - break; case BACKTITLE: - backtitle_flag = optarg; + backtitle_opt = optarg; break; case BEGIN_X: - conf.x = atoi(optarg); + conf.x = (int)strtol(optarg, NULL, 10); if (conf.x < BSDDIALOG_CENTER) { - printf("Error: --begin-x %d, cannot be < %d", + printf("Error: --begin-x %d < %d", conf.x, BSDDIALOG_CENTER); - return (BSDDIALOG_ERROR); + return (255); } break; case BEGIN_Y: - conf.y = atoi(optarg); + conf.y = (int)strtol(optarg, NULL, 10); if (conf.y < BSDDIALOG_CENTER) { - printf("Error: --begin-y %d, cannot be < %d", + printf("Error: --begin-y %d < %d", conf.y, BSDDIALOG_CENTER); - return (BSDDIALOG_ERROR); + return (255); } break; case CANCEL_LABEL: @@ -433,25 +395,31 @@ int main(int argc, char *argv[argc]) conf.clear = true; break; case COLORS: - conf.text.colors = true; + conf.text.highlight = true; break; case CR_WRAP: - cr_wrap_flag = true; + cr_wrap_opt = true; break; case DATE_FORMAT: - date_fmt_flag = optarg; + date_fmt_opt = optarg; break; case DEFAULT_BUTTON: conf.button.default_label = optarg; break; case DEFAULT_ITEM: - conf.menu.default_item = optarg; + item_default_opt = optarg; break; - case DEFAULTNO: + case DEFAULT_NO: conf.button.default_cancel = true; break; + case DISABLE_ESC: + conf.key.enable_esc = false; + break; + case ESC_CANCELVALUE: + esc_cancelvalue_opt = true; + break; case EXIT_LABEL: - conf.button.exit_label = optarg; + conf.button.ok_label = optarg; break; case EXTRA_BUTTON: conf.button.with_extra = true; @@ -459,6 +427,12 @@ int main(int argc, char *argv[argc]) case EXTRA_LABEL: conf.button.extra_label = optarg; break; + case GENERIC_BUTTON1: + conf.button.generic1_label = optarg; + break; + case GENERIC_BUTTON2: + conf.button.generic2_label = optarg; + break; case HELP: usage(); return (BSDDIALOG_OK); @@ -469,10 +443,10 @@ int main(int argc, char *argv[argc]) conf.button.help_label = optarg; break; case HELP_STATUS: - list_items_on_flag = true; + list_items_on_opt = true; break; case HELP_TAGS: - item_tag_help_flag = true; + item_tag_help_opt = true; break; case HFILE: conf.f1_file = optarg; @@ -480,44 +454,42 @@ int main(int argc, char *argv[argc]) case HLINE: conf.bottomtitle = optarg; break; + case HMSG: + conf.f1_message = optarg; + break; case IGNORE: - ignore_flag = true; + ignore_opt = true; break; case INSECURE: conf.form.securech = '*'; break; case ITEM_DEPTH: - item_depth_flag = true; + item_depth_opt = true; break; case ITEM_HELP: - item_bottomdesc_flag = true; + item_bottomdesc_opt = true; break; case ITEM_PREFIX: - item_prefix_flag = true; + item_prefix_opt = true; break; case MAX_INPUT: - max_input_form_flag = atoi(optarg); + max_input_form_opt = (u_int)strtoul(optarg, NULL, 10); break; case NO_ITEMS: conf.menu.no_desc = true; break; - case NOCANCEL: case NO_CANCEL: conf.button.without_cancel = true; break; case NO_COLLAPSE: - no_collapse_flag = true; - break; - case NO_LABEL: - conf.button.cancel_label = optarg; + no_collapse_opt = true; break; case NO_LINES: conf.no_lines = true; break; case NO_NL_EXPAND: - no_nl_expand_flag = true; + no_nl_expand_opt = true; break; - case NOOK: case NO_OK: conf.button.without_ok = true; break; @@ -531,17 +503,16 @@ int main(int argc, char *argv[argc]) conf.button.ok_label = optarg; break; case OUTPUT_FD: - output_fd_flag = atoi(optarg); + output_fd_opt = (int)strtol(optarg, NULL, 10); break; - case SEPARATOR: case OUTPUT_SEPARATOR: - item_output_sep_flag = optarg; + item_output_sep_opt = optarg; break; case QUOTED: - item_always_quote_flag = true; + item_always_quote_opt = true; break; case PRINT_MAXSIZE: - print_maxsize_flag = true; + print_maxsize_opt = true; break; case PRINT_SIZE: conf.get_height = &getH;; @@ -551,127 +522,125 @@ int main(int argc, char *argv[argc]) printf("bsddialog version %s\n", BSDDIALOG_VERSION); break; case SEPARATE_OUTPUT: - item_output_sepnl_flag = true; + item_output_sepnl_opt = true; break; case SHADOW: conf.shadow = true; break; case SINGLE_QUOTED: - item_singlequote_flag = true; + item_singlequote_opt = true; break; case SLEEP: - conf.sleep = atoi(optarg); + conf.sleep = (u_int)strtoul(optarg, NULL, 10); break; case STDERR: - output_fd_flag = STDERR_FILENO; + output_fd_opt = STDERR_FILENO; break; case STDOUT: - output_fd_flag = STDOUT_FILENO; + output_fd_opt = STDOUT_FILENO; + break; + case TAB_LEN: + conf.text.tablen = (u_int)strtoul(optarg, NULL, 10); break; case THEME: - if (strcmp(optarg, "bsddialog") == 0) - theme_flag = BSDDIALOG_THEME_BSDDIALOG; - else if (strcmp(optarg, "blackwhite") == 0) - theme_flag = BSDDIALOG_THEME_BLACKWHITE; - else if (strcmp(optarg, "dialog") == 0) - theme_flag = BSDDIALOG_THEME_DIALOG; + if (strcasecmp(optarg, "bsddialog") == 0) + theme_opt = BSDDIALOG_THEME_BSDDIALOG; + else if (strcasecmp(optarg, "blackwhite") == 0) + theme_opt = BSDDIALOG_THEME_BLACKWHITE; + else if (strcasecmp(optarg, "default") == 0) + theme_opt = BSDDIALOG_THEME_DEFAULT; + else if (strcasecmp(optarg, "dialog") == 0) + theme_opt = BSDDIALOG_THEME_DIALOG; else { - printf("Unknown theme, possible values: "); - printf("blackwhite, bsddialog, dialog"); - return (BSDDIALOG_ERROR); + printf("Error: unknown theme\n"); + return (255); } break; case TIME_FORMAT: - time_fmt_flag = optarg; + time_fmt_opt = optarg; break; case TITLE: conf.title = optarg; break; case TRIM: - trim_flag = true; + trim_opt = true; break; case VERSION: - printf("bsddialog %s (libbsddialog %s).\n", + printf("bsddialog %s (libbsddialog %s)\n", BSDDIALOG_VERSION, LIBBSDDIALOG_VERSION); return (BSDDIALOG_OK); - case YES_LABEL: - conf.button.ok_label = optarg; - break; - /* Widgets */ - case BUILDLIST: - widgetbuilder = buildlist_builder; - break; + /* Dialogs */ case CHECKLIST: - widgetbuilder = checklist_builder; + dialogbuilder = checklist_builder; break; case DATEBOX: - widgetbuilder = datebox_builder; + dialogbuilder = datebox_builder; break; case FORM: - widgetbuilder = form_builder; + dialogbuilder = form_builder; break; case GAUGE: - widgetbuilder = gauge_builder; + dialogbuilder = gauge_builder; break; case INFOBOX: - widgetbuilder = infobox_builder; + dialogbuilder = infobox_builder; break; case INPUTBOX: - widgetbuilder = inputbox_builder; + dialogbuilder = inputbox_builder; break; case MENU: - widgetbuilder = menu_builder; + dialogbuilder = menu_builder; break; case MIXEDFORM: - widgetbuilder = mixedform_builder; + dialogbuilder = mixedform_builder; break; case MIXEDGAUGE: - widgetbuilder = mixedgauge_builder; + dialogbuilder = mixedgauge_builder; break; case MSGBOX: - widgetbuilder = msgbox_builder; + dialogbuilder = msgbox_builder; break; case PAUSE: - widgetbuilder = pause_builder; + dialogbuilder = pause_builder; break; case PASSWORDBOX: - widgetbuilder = passwordbox_builder; + dialogbuilder = passwordbox_builder; break; case PASSWORDFORM: - widgetbuilder = passwordform_builder; + dialogbuilder = passwordform_builder; break; case RADIOLIST: - widgetbuilder = radiolist_builder; + dialogbuilder = radiolist_builder; break; case RANGEBOX: - widgetbuilder = rangebox_builder; + dialogbuilder = rangebox_builder; break; case TEXTBOX: - widgetbuilder = textbox_builder; + dialogbuilder = textbox_builder; break; case TIMEBOX: - widgetbuilder = timebox_builder; + dialogbuilder = timebox_builder; break; case TREEVIEW: - widgetbuilder = treeview_builder; + dialogbuilder = treeview_builder; break; case YESNO: - widgetbuilder = yesno_builder; + dialogbuilder = yesno_builder; break; /* Error */ default: - if (ignore_flag == true) + if (ignore_opt == true) break; usage(); - return (BSDDIALOG_ERROR); + return (255); } } argc -= optind; argv += optind; - if (print_maxsize_flag) { + if (print_maxsize_opt) { ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); - dprintf(output_fd_flag, "MaxSize: %d, %d\n", + dprintf(output_fd_opt, "Screen size: (%d - %d)\n", ws.ws_row, ws.ws_col); if (argc == 0) return (BSDDIALOG_OK); @@ -679,38 +648,43 @@ int main(int argc, char *argv[argc]) if (argc < 3) { usage(); - return (BSDDIALOG_ERROR); + return (255); } - if (widgetbuilder == textbox_builder) + if (dialogbuilder == textbox_builder) text = argv[0]; else { - text = malloc(strlen(argv[0] + 1)); - custom_text(cr_wrap_flag, no_collapse_flag, no_nl_expand_flag, - trim_flag, argv[0], text); + 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 = atoi(argv[1]); - cols = atoi(argv[2]); + 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) { + if (bsddialog_init() != 0) { printf("Error: %s\n", bsddialog_geterror()); return (BSDDIALOG_ERROR); } - if (theme_flag >= 0) - bsddialog_set_default_theme(theme_flag); + signal(SIGINT, sigint_handler); + + if (theme_opt != BSDDIALOG_THEME_DEFAULT) + bsddialog_set_default_theme(theme_opt); - if (backtitle_flag != NULL) - bsddialog_backtitle(&conf, backtitle_flag); + if (backtitle_opt != NULL) + bsddialog_backtitle(&conf, backtitle_opt); output = BSDDIALOG_OK; - if (widgetbuilder != NULL) - output = widgetbuilder(conf, text, rows, cols, argc, argv, + if (dialogbuilder != NULL) + output = dialogbuilder(conf, text, rows, cols, argc, argv, errorbuilder); - if (widgetbuilder != textbox_builder) + if (dialogbuilder != textbox_builder) free(text); bsddialog_end(); @@ -721,30 +695,90 @@ int main(int argc, char *argv[argc]) printf("Error: %s\n", errorbuilder); else printf("Error: %s\n", bsddialog_geterror()); + return (255); } if (conf.get_height != NULL && conf.get_width != NULL) - dprintf(output_fd_flag, "Widget size: (%d - %d)\n", + dprintf(output_fd_opt, "Dialog size: (%d - %d)\n", *conf.get_height, *conf.get_width); + if (output == BSDDIALOG_ESC && esc_cancelvalue_opt) + output = BSDDIALOG_CANCEL; + return (output); } -/* Widgets */ +void sigint_handler(int sig) +{ + bsddialog_end(); + + exit(255); +} +void +custom_text(bool cr_wrap, bool no_collapse, bool no_nl_expand, bool trim, + char *text, char *buf) +{ + int i, j; + + 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'; + i++; + break; + case 't': + if (no_collapse) { + j++; + buf[j] = 't'; + } else + buf[j] = '\t'; + i++; + break; + } + break; + case '\n': + buf[j] = cr_wrap ? ' ' : '\n'; + break; + case '\t': + buf[j] = no_collapse ? '\t' : ' '; + break; + default: + buf[j] = text[i]; + } + i++; + j += (buf[j] == ' ' && trim && j > 0 && buf[j-1] == ' ') ? + 0 : 1; + } + buf[j] = '\0'; +} + +/* Dialogs */ int gauge_builder(BUILDER_ARGS) { - int output, perc; + int output; + unsigned int perc; if (argc > 0) { - perc = argc > 0 ? atoi (argv[0]) : 0; - perc = perc < 0 ? 0 : perc; + perc = argc > 0 ? (u_int)strtoul(argv[0], NULL, 10) : 0; perc = perc > 100 ? 100 : perc; } else perc = 0; - output = bsddialog_gauge(&conf, text, rows, cols, perc); + output = bsddialog_gauge(&conf, text, rows, cols, perc, STDIN_FILENO, + "XXX"); return (output); } @@ -760,16 +794,16 @@ int infobox_builder(BUILDER_ARGS) int mixedgauge_builder(BUILDER_ARGS) { - int i, output, mainperc, nminibars, *minipercs; - char **minilabels; + int output, *minipercs; + unsigned int i, mainperc, nminibars; + const char **minilabels; if (argc < 1 || (((argc-1) % 2) != 0) ) { strcpy(errbuf, "bad --mixedgauge arguments\n"); return (BSDDIALOG_ERROR); } - mainperc = atoi(argv[0]); - mainperc = mainperc < 0 ? 0 : mainperc; + mainperc = (u_int)strtoul(argv[0], NULL, 10); mainperc = mainperc > 100 ? 100 : mainperc; argc--; argv++; @@ -786,7 +820,7 @@ int mixedgauge_builder(BUILDER_ARGS) for (i = 0; i < nminibars; i++) { minilabels[i] = argv[i * 2]; - minipercs[i] = atoi(argv[i * 2 + 1]); + minipercs[i] = (int)strtol(argv[i * 2 + 1], NULL, 10); } output = bsddialog_mixedgauge(&conf, text, rows, cols, mainperc, @@ -806,15 +840,16 @@ int msgbox_builder(BUILDER_ARGS) int pause_builder(BUILDER_ARGS) { - int output, sec; + int output; + unsigned int secs; if (argc < 1) { - strcpy(errbuf, "not <seconds> argument for --pause\n"); + strcpy(errbuf, "missing <seconds> for --pause\n"); return (BSDDIALOG_ERROR); } - sec = atoi(argv[0]); - output = bsddialog_pause(&conf, text, rows, cols, sec); + secs = (u_int)strtoul(argv[0], NULL, 10); + output = bsddialog_pause(&conf, text, rows, cols, secs); return (output); } @@ -829,11 +864,11 @@ int rangebox_builder(BUILDER_ARGS) return (BSDDIALOG_ERROR); } - min = atoi(argv[0]); - max = atoi(argv[1]); - + min = (int)strtol(argv[0], NULL, 10); + max = (int)strtol(argv[1], NULL, 10); + if (argc > 2) { - value = atoi(argv[2]); + value = (int)strtol(argv[2], NULL, 10); value = value < min ? min : value; value = value > max ? max : value; } @@ -842,7 +877,7 @@ int rangebox_builder(BUILDER_ARGS) output = bsddialog_rangebox(&conf, text, rows, cols, min, max, &value); - dprintf(output_fd_flag, "%d", value); + dprintf(output_fd_opt, "%d", value); return (output); } @@ -880,28 +915,26 @@ int datebox_builder(BUILDER_ARGS) mm = localtm->tm_mon + 1; dd = localtm->tm_mday; - /* --calendar text h w [year month day] */ if (argc == 3) { - yy = atoi(argv[0]); - mm = atoi(argv[1]); - dd = atoi(argv[2]); + yy = (u_int)strtoul(argv[0], NULL, 10); + mm = (u_int)strtoul(argv[1], NULL, 10); + dd = (u_int)strtoul(argv[2], NULL, 10); } output = bsddialog_datebox(&conf, text, rows, cols, &yy, &mm, &dd); if (output != BSDDIALOG_OK) return (output); - if (date_fmt_flag == NULL) { - dprintf(output_fd_flag, "%u/%u/%u", yy, mm, dd); - } - else { + if (date_fmt_opt == NULL) { + dprintf(output_fd_opt, "%u/%u/%u", yy, mm, dd); + } else { time(&cal); localtm = localtime(&cal); localtm->tm_year = yy - 1900; localtm->tm_mon = mm; localtm->tm_mday = dd; - strftime(stringdate, 1024, date_fmt_flag, localtm); - dprintf(output_fd_flag, "%s", stringdate); + strftime(stringdate, 1024, date_fmt_opt, localtm); + dprintf(output_fd_opt, "%s", stringdate); } return (output); @@ -921,28 +954,26 @@ int timebox_builder(BUILDER_ARGS) mm = localtm->tm_min; ss = localtm->tm_sec; - /* --timebox text h w [hour minute second] */ if (argc == 3) { - hh = atoi(argv[0]); - mm = atoi(argv[1]); - ss = atoi(argv[2]); + hh = (u_int)strtoul(argv[0], NULL, 10); + mm = (u_int)strtoul(argv[1], NULL, 10); + ss = (u_int)strtoul(argv[2], NULL, 10); } output = bsddialog_timebox(&conf, text, rows, cols, &hh, &mm, &ss); if (output != BSDDIALOG_OK) return (output); - if (time_fmt_flag == NULL) { - dprintf(output_fd_flag, "%u:%u:%u", hh, mm, ss); - } - else { + if (time_fmt_opt == NULL) { + dprintf(output_fd_opt, "%u:%u:%u", hh, mm, ss); + } else { time(&clock); localtm = localtime(&clock); localtm->tm_hour = hh; localtm->tm_min = mm; localtm->tm_sec = ss; - strftime(stringtime, 1024, time_fmt_flag, localtm); - dprintf(output_fd_flag, "%s", stringtime); + strftime(stringtime, 1024, time_fmt_opt, localtm); + dprintf(output_fd_opt, "%s", stringtime); } return (output); @@ -952,35 +983,48 @@ int timebox_builder(BUILDER_ARGS) static int get_menu_items(char *errbuf, int argc, char **argv, bool setprefix, bool setdepth, bool setname, bool setdesc, bool setstatus, bool sethelp, - int *nitems, struct bsddialog_menuitem *items) + unsigned int *nitems, struct bsddialog_menuitem **items, int *focusitem) { - int i, j, sizeitem; + unsigned int i, j, sizeitem; + + *focusitem = -1; sizeitem = 0; - if (setprefix) sizeitem++; - if (setdepth) sizeitem++; - if (setname) sizeitem++; - if (setdesc) sizeitem++; - if (setstatus) sizeitem++; - if (sethelp) sizeitem++; + sizeitem += setprefix ? 1 : 0; + sizeitem += setdepth ? 1 : 0; + sizeitem += setname ? 1 : 0; + sizeitem += setdesc ? 1 : 0; + sizeitem += setstatus ? 1 : 0; + sizeitem += sethelp ? 1 : 0; if ((argc % sizeitem) != 0) { strcpy(errbuf, "bad number of arguments for this menu\n"); return (BSDDIALOG_ERROR); } - *nitems = argc / sizeitem; + + *items = calloc(*nitems, sizeof(struct bsddialog_menuitem)); + if (items == NULL) { + strcpy(errbuf, "cannot allocate memory menu items\n"); + return (BSDDIALOG_ERROR); + } + j = 0; - for (i=0; i<*nitems; i++) { - items[i].prefix = setprefix ? argv[j++] : nostring; - items[i].depth = setdepth ? atoi(argv[j++]) : 0; - items[i].name = setname ? argv[j++] : nostring; - items[i].desc = setdesc ? argv[j++] : nostring; + for (i = 0; i < *nitems; i++) { + (*items)[i].prefix = setprefix ? argv[j++] : ""; + (*items)[i].depth = setdepth ? + (u_int)strtoul(argv[j++], NULL, 0) : 0; + (*items)[i].name = setname ? argv[j++] : ""; + (*items)[i].desc = setdesc ? argv[j++] : ""; if (setstatus) - items[i].on = strcmp(argv[j++], "on") == 0 ? + (*items)[i].on = strcmp(argv[j++], "on") == 0 ? true : false; else - items[i].on = false; - items[i].bottomdesc = sethelp ? argv[j++] : nostring; + (*items)[i].on = false; + (*items)[i].bottomdesc = sethelp ? argv[j++] : ""; + + if (item_default_opt != NULL && *focusitem == -1) + if (strcmp((*items)[i].name, item_default_opt) == 0) + *focusitem = i; } return (BSDDIALOG_OK); @@ -990,37 +1034,36 @@ static void print_menu_items(struct bsddialog_conf *conf, int output, int nitems, struct bsddialog_menuitem *items, int focusitem) { - int i; bool sep, toquote; - char *sepstr, quotech, *helpvalue; + int i; + char *sepstr, quotech; + const char *helpvalue; sep = false; - quotech = item_singlequote_flag ? '\'' : '"'; - sepstr = item_output_sep_flag != NULL ? item_output_sep_flag : " "; + quotech = item_singlequote_opt ? '\'' : '"'; + sepstr = item_output_sep_opt != NULL ? item_output_sep_opt : " "; if (output == BSDDIALOG_HELP && focusitem >= 0) { - dprintf(output_fd_flag, "HELP "); - + dprintf(output_fd_opt, "HELP "); + helpvalue = items[focusitem].name; - if (item_bottomdesc_flag && item_tag_help_flag == false) + if (item_bottomdesc_opt && item_tag_help_opt == false) helpvalue = items[focusitem].bottomdesc; - toquote = item_always_quote_flag || + toquote = item_always_quote_opt || strchr(helpvalue, ' ') != NULL; if (toquote) - dprintf(output_fd_flag, "%c", quotech); - dprintf(output_fd_flag, "%s", helpvalue); + dprintf(output_fd_opt, "%c", quotech); + dprintf(output_fd_opt, "%s", helpvalue); if (toquote) - dprintf(output_fd_flag, "%c", quotech); - - if (list_items_on_flag == false) - return; - + dprintf(output_fd_opt, "%c", quotech); + sep = true; } - if (output != BSDDIALOG_OK && list_items_on_flag == false) + if (output != BSDDIALOG_OK && + !(output == BSDDIALOG_HELP && list_items_on_opt)) return; for (i = 0; i < nitems; i++) { @@ -1028,65 +1071,39 @@ print_menu_items(struct bsddialog_conf *conf, int output, int nitems, continue; if (sep == true) { - dprintf(output_fd_flag, "%s", sepstr); - if (item_output_sepnl_flag) - dprintf(output_fd_flag, "\n"); + dprintf(output_fd_opt, "%s", sepstr); + if (item_output_sepnl_opt) + dprintf(output_fd_opt, "\n"); } sep = true; - toquote = item_always_quote_flag || + toquote = item_always_quote_opt || strchr(items[i].name, ' ') != NULL; if (toquote) - dprintf(output_fd_flag, "%c", quotech); - dprintf(output_fd_flag, "%s", items[i].name); + dprintf(output_fd_opt, "%c", quotech); + dprintf(output_fd_opt, "%s", items[i].name); if (toquote) - dprintf(output_fd_flag, "%c", quotech); - } -} - -int buildlist_builder(BUILDER_ARGS) -{ - int output, menurows, nitems, focusitem; - struct bsddialog_menuitem items[1024]; - - if (argc < 1) { - strcpy(errbuf, "<menurows> not provided"); - return (BSDDIALOG_ERROR); + dprintf(output_fd_opt, "%c", quotech); } - - menurows = atoi(argv[0]); - - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false, - true, true, true, item_bottomdesc_flag, &nitems, items); - if (output != 0) - return (output); - - output = bsddialog_buildlist(&conf, text, rows, cols, menurows, nitems, - items, &focusitem); - if (output == BSDDIALOG_ERROR) - return (BSDDIALOG_ERROR); - - print_menu_items(&conf, output, nitems, items, focusitem); - - return (output); } int checklist_builder(BUILDER_ARGS) { - int output, menurows, nitems, focusitem; - struct bsddialog_menuitem items[1024]; + int output, focusitem; + unsigned int menurows, nitems; + struct bsddialog_menuitem *items; if (argc < 1) { strcpy(errbuf, "<menurows> not provided"); return (BSDDIALOG_ERROR); } - menurows = atoi(argv[0]); + menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, - item_depth_flag, true, true, true, item_bottomdesc_flag, &nitems, - items); + 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); @@ -1095,24 +1112,27 @@ int checklist_builder(BUILDER_ARGS) print_menu_items(&conf, output, nitems, items, focusitem); + free(items); + return (output); } int menu_builder(BUILDER_ARGS) { - int output, menurows, nitems, focusitem; - struct bsddialog_menuitem items[1024]; + int output, focusitem; + unsigned int menurows, nitems; + struct bsddialog_menuitem *items; if (argc < 1) { strcpy(errbuf, "<menurows> not provided"); return (BSDDIALOG_ERROR); } - menurows = atoi(argv[0]); + menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, - item_depth_flag, true, true, false, item_bottomdesc_flag, &nitems, - items); + 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); @@ -1121,24 +1141,27 @@ int menu_builder(BUILDER_ARGS) print_menu_items(&conf, output, nitems, items, focusitem); + free(items); + return (output); } int radiolist_builder(BUILDER_ARGS) { - int output, menurows, nitems, focusitem; - struct bsddialog_menuitem items[1024]; + int output, focusitem; + unsigned int menurows, nitems; + struct bsddialog_menuitem *items; if (argc < 1) { strcpy(errbuf, "<menurows> not provided"); return (BSDDIALOG_ERROR); } - menurows = atoi(argv[0]); + menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, - item_depth_flag, true, true, true, item_bottomdesc_flag, &nitems, - items); + 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); @@ -1147,23 +1170,26 @@ int radiolist_builder(BUILDER_ARGS) print_menu_items(&conf, output, nitems, items, focusitem); + free(items); + return (output); } int treeview_builder(BUILDER_ARGS) { - int output, menurows, nitems, focusitem; - struct bsddialog_menuitem items[1024]; + int output, focusitem; + unsigned int menurows, nitems; + struct bsddialog_menuitem *items; if (argc < 1) { strcpy(errbuf, "<menurows> not provided"); return (BSDDIALOG_ERROR); } - menurows = atoi(argv[0]); + menurows = (u_int)strtoul(argv[0], NULL, 10); - output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, true, - true, true, true, item_bottomdesc_flag, &nitems, items); + 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); @@ -1172,13 +1198,27 @@ int treeview_builder(BUILDER_ARGS) output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems, items, &focusitem); - + print_menu_items(&conf, output, nitems, items, focusitem); + free(items); + return (output); } /* 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(struct bsddialog_conf *conf, int output, int nitems, struct bsddialog_formitem *items) @@ -1188,52 +1228,58 @@ print_form_items(struct bsddialog_conf *conf, int output, int nitems, if (output == BSDDIALOG_ERROR) return; - for (i=0; i < nitems; i++) { - dprintf(output_fd_flag, "%s\n", items[i].value); + for (i = 0; i < nitems; i++) { + dprintf(output_fd_opt, "%s\n", items[i].value); free(items[i].value); } } int form_builder(BUILDER_ARGS) { - int i, output, formheight, nitems, fieldlen, valuelen; - struct bsddialog_formitem items[1024]; - unsigned int flags = 0; + int output, fieldlen, valuelen; + unsigned int i, j, flags, formheight, nitems, sizeitem; + struct bsddialog_formitem *items; - if (argc < 1 || (((argc-1) % 8) != 0) ) { + 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); } - formheight = atoi(argv[0]); + formheight = (u_int)strtoul(argv[0], NULL, 10); + flags = 0; argc--; argv++; - nitems = argc / 8; - for (i=0; i<nitems; i++) { - items[i].label = argv[8*i]; - items[i].ylabel = atoi(argv[8*i+1]); - items[i].xlabel = atoi(argv[8*i+2]); - items[i].init = argv[8*i+3]; - items[i].yfield = atoi(argv[8*i+4]); - items[i].xfield = atoi(argv[8*i+5]); - - fieldlen = atoi(argv[8*i+6]); + nitems = argc / sizeitem; + if (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK) + return (BSDDIALOG_ERROR); + j = 0; + for (i = 0; i < nitems; i++) { + items[i].label = argv[j++]; + items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10); + items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10); + items[i].init = argv[j++]; + items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10); + items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10); + + fieldlen = (int)strtol(argv[j++], NULL, 10); items[i].fieldlen = abs(fieldlen); - valuelen = atoi(argv[8*i+7]); + valuelen = (int)strtol(argv[j++], NULL, 10); items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen; flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0); items[i].flags = flags; - items[i].bottomdesc = nostring; + items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : ""; } output = bsddialog_form(&conf, text, rows, cols, formheight, nitems, items); print_form_items(&conf, output, nitems, items); + free(items); return (output); } @@ -1250,9 +1296,9 @@ int inputbox_builder(BUILDER_ARGS) item.yfield = 1; item.xfield = 1; item.fieldlen = cols > 4 ? cols-4 : 25; - item.maxvaluelen = max_input_form_flag > 0 ? max_input_form_flag : 2048; + item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048; item.flags = 0; - item.bottomdesc = nostring; + item.bottomdesc = ""; output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item); print_form_items(&conf, output, 1, &item); @@ -1262,36 +1308,42 @@ int inputbox_builder(BUILDER_ARGS) int mixedform_builder(BUILDER_ARGS) { - int i, output, formheight, nitems; - struct bsddialog_formitem items[1024]; + int output; + unsigned int i, j, formheight, nitems, sizeitem; + struct bsddialog_formitem *items; - if (argc < 1 || (((argc-1) % 9) != 0) ) { + 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); } - formheight = atoi(argv[0]); - + formheight = (u_int)strtoul(argv[0], NULL, 10); + argc--; argv++; - nitems = argc / 9; - for (i=0; i<nitems; i++) { - items[i].label = argv[9*i]; - items[i].ylabel = atoi(argv[9*i+1]); - items[i].xlabel = atoi(argv[9*i+2]); - items[i].init = argv[9*i+3]; - items[i].yfield = atoi(argv[9*i+4]); - items[i].xfield = atoi(argv[9*i+5]); - items[i].fieldlen = atoi(argv[9*i+6]); - items[i].maxvaluelen = atoi(argv[9*i+7]); - items[i].flags = atoi(argv[9*i+8]); - items[i].bottomdesc = nostring; + nitems = argc / sizeitem; + if (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK) + return (BSDDIALOG_ERROR); + j = 0; + for (i = 0; i < nitems; i++) { + items[i].label = argv[j++]; + items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10); + items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10); + items[i].init = argv[j++]; + items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10); + items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10); + items[i].fieldlen = (u_int)strtoul(argv[j++], NULL, 10); + items[i].maxvaluelen = (u_int)strtoul(argv[j++], NULL, 10); + items[i].flags = (u_int)strtoul(argv[j++], NULL, 10); + items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : ""; } output = bsddialog_form(&conf, text, rows, cols, formheight, nitems, items); print_form_items(&conf, output, nitems, items); + free(items); return (output); } @@ -1308,9 +1360,9 @@ int passwordbox_builder(BUILDER_ARGS) item.yfield = 1; item.xfield = 1; item.fieldlen = cols > 4 ? cols-4 : 25; - item.maxvaluelen = max_input_form_flag > 0 ? max_input_form_flag : 2048; + item.maxvaluelen = max_input_form_opt > 0 ? max_input_form_opt : 2048; item.flags = BSDDIALOG_FIELDHIDDEN; - item.bottomdesc = nostring; + item.bottomdesc = ""; output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item); print_form_items(&conf, output, 1, &item); @@ -1320,44 +1372,50 @@ int passwordbox_builder(BUILDER_ARGS) int passwordform_builder(BUILDER_ARGS) { - int i, output, formheight, nitems, fieldlen, valuelen; - struct bsddialog_formitem items[1024]; - unsigned int flags = BSDDIALOG_FIELDHIDDEN; + int output, fieldlen, valuelen; + unsigned int i, j, flags, formheight, nitems, sizeitem; + struct bsddialog_formitem *items; - if (argc < 1 || (((argc-1) % 8) != 0) ) { + 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); } - formheight = atoi(argv[0]); - + formheight = (u_int)strtoul(argv[0], NULL, 10); + flags = BSDDIALOG_FIELDHIDDEN; + argc--; argv++; - nitems = argc / 8; - for (i=0; i<nitems; i++) { - items[i].label = argv[8*i]; - items[i].ylabel = atoi(argv[8*i+1]); - items[i].xlabel = atoi(argv[8*i+2]); - items[i].init = argv[8*i+3]; - items[i].yfield = atoi(argv[8*i+4]); - items[i].xfield = atoi(argv[8*i+5]); - - fieldlen = atoi(argv[8*i+6]); + nitems = argc / sizeitem; + if (alloc_formitems(nitems, &items, errbuf) != BSDDIALOG_OK) + return (BSDDIALOG_ERROR); + j = 0; + for (i = 0; i < nitems; i++) { + items[i].label = argv[j++]; + items[i].ylabel = (u_int)strtoul(argv[j++], NULL, 10); + items[i].xlabel = (u_int)strtoul(argv[j++], NULL, 10); + items[i].init = argv[j++]; + items[i].yfield = (u_int)strtoul(argv[j++], NULL, 10); + items[i].xfield = (u_int)strtoul(argv[j++], NULL, 10); + + fieldlen = (int)strtol(argv[j++], NULL, 10); items[i].fieldlen = abs(fieldlen); - valuelen = atoi(argv[8*i+7]); + valuelen = (int)strtol(argv[j++], NULL, 10); items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen; flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0); items[i].flags = flags; - items[i].bottomdesc = nostring; + items[i].bottomdesc = item_bottomdesc_opt ? argv[j++] : ""; } - output = bsddialog_form(&conf, text, rows, cols, formheight, - nitems, items); + output = bsddialog_form(&conf, text, rows, cols, formheight, nitems, + items); print_form_items(&conf, output, nitems, items); + free(items); return (output); } diff --git a/examples_library/buildlist.c b/examples_library/buildlist.c deleted file mode 100644 index 37c1e342ace5..000000000000 --- a/examples_library/buildlist.c +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: CC0-1.0 - * - * Written in 2021 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 <stdio.h> -#include <string.h> - -#include <bsddialog.h> - -int main() -{ - int i, output; - struct bsddialog_conf conf; - struct bsddialog_menuitem items[5] = { - {"", false, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, - {"", true, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, - {"", false, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, - {"", true, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, - {"", false, 0, "Name 5", "Desc 5", "Bottom Desc 5"} - }; - - bsddialog_initconf(&conf); - conf.title = "radiolist"; - - if (bsddialog_init() < 0) - return -1; - - output = bsddialog_buildlist(&conf, "Example", 15, 30, 5, 5, items, NULL); - - bsddialog_end(); - - printf("Buildlist:\n"); - for (i=0; i<5; i++) - printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name); - - - return output; -} diff --git a/examples_library/checklist.c b/examples_library/checklist.c index d1c4a4db3597..7851383d0553 100644 --- a/examples_library/checklist.c +++ b/examples_library/checklist.c @@ -18,27 +18,38 @@ int main() int i, output; struct bsddialog_conf conf; struct bsddialog_menuitem items[5] = { - {"", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, - {"", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, - {"", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, - {"", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, - {"", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"} + {"i", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, + {"ii", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, + {"iii", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, + {"iv", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, + {"v", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"} }; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "checklist"; - - if (bsddialog_init() < 0) - return -1; - - output = bsddialog_checklist(&conf, "Example", 15, 30, 5, 5, items, NULL); + output = bsddialog_checklist(&conf, "Example", 15, 30, 5, 5, items, + NULL); bsddialog_end(); + if (output == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + if (output == BSDDIALOG_CANCEL) { + printf("Cancel\n"); + return (0); + } + printf("Checklist:\n"); - for (i=0; i<5; i++) + for (i = 0; i < 5; i++) printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name); - - - return output; -} + + return (output); +}
\ No newline at end of file diff --git a/examples_library/compile b/examples_library/compile index 4427568a7f0f..945d906cd43c 100755 --- a/examples_library/compile +++ b/examples_library/compile @@ -1,10 +1,19 @@ #!/bin/sh +#- +# SPDX-License-Identifier: CC0-1.0 +# +# Written in 2021 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/>. libpath=../lib -examples="buildlist menu treeview checklist radiolist mixedlist theme \ - infobox yesno msgbox datebox form timebox sade rangebox pause" +examples="menu checklist radiolist mixedlist theme infobox yesno msgbox \ + datebox form timebox rangebox pause" for e in $examples do - cc -g -Wall -I$libpath ${e}.c -o $e -L$libpath -lbsddialog -Wl,-rpath=$libpath + cc -g -Wall -Wextra -I$libpath ${e}.c -o $e -L$libpath -lbsddialog \ + -Wl,-rpath=$libpath done diff --git a/examples_library/datebox.c b/examples_library/datebox.c index 4839c3dbd895..d2af7bd7fae0 100644 --- a/examples_library/datebox.c +++ b/examples_library/datebox.c @@ -28,24 +28,22 @@ int main() 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 = "datebox"; conf.bottomtitle = "Press TAB and arrows"; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_datebox(&conf, "Example", 10, 50, &yy, &mm, &dd); - + bsddialog_end(); switch (output) { case BSDDIALOG_OK: printf("Date: %u/%u/%u", yy, mm, dd); break; - case BSDDIALOG_ESC: - printf("ESC\n"); - break; case BSDDIALOG_CANCEL: printf("Cancel"); break; @@ -55,5 +53,5 @@ int main() } printf("\n"); - return output; -} + return (output); +}
\ No newline at end of file diff --git a/examples_library/form.c b/examples_library/form.c index efb997f31d36..9bc7b0ccbe58 100644 --- a/examples_library/form.c +++ b/examples_library/form.c @@ -23,29 +23,37 @@ int main() int i, output; struct bsddialog_conf conf; struct bsddialog_formitem items[3] = { - {"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"}, - {"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"}, - {"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"} + {"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"}, + {"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"}, + {"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"} }; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "form"; conf.form.securech = '*'; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items); bsddialog_end(); - - if (output == BSDDIALOG_ERROR) + + if (output == BSDDIALOG_ERROR) { printf("Error: %s", bsddialog_geterror()); + return (1); + } + + if (output == BSDDIALOG_CANCEL) { + printf("Cancel\n"); + return (0); + } - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) { printf("%s \"%s\"\n", items[i].label, items[i].value); free(items[i].value); } - - return output; -} + + return (output); +}
\ No newline at end of file diff --git a/examples_library/infobox.c b/examples_library/infobox.c index 74f34bba91e1..c022fa755fc6 100644 --- a/examples_library/infobox.c +++ b/examples_library/infobox.c @@ -18,15 +18,22 @@ int main() int output; struct bsddialog_conf conf; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "infobox"; - - if (bsddialog_init() < 0) - return -1; - - output = bsddialog_infobox(&conf, "Example", 7, 20); + conf.sleep = 3; + output = bsddialog_infobox(&conf, "Example\n(3 seconds)", 7, 20); bsddialog_end(); - return output; -} + if (output == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + return (output); +}
\ No newline at end of file diff --git a/examples_library/menu.c b/examples_library/menu.c index 59999dabd1e5..6a2abe2aaadb 100644 --- a/examples_library/menu.c +++ b/examples_library/menu.c @@ -18,27 +18,37 @@ int main() int i, output; struct bsddialog_conf conf; struct bsddialog_menuitem items[5] = { - {"", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, - {"", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, - {"", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, - {"", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, - {"", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"} + {"I", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, + {"II", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, + {"III", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, + {"IV", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, + {"V", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"} }; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "menu"; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_menu(&conf, "Example", 15, 30, 5, 5, items, NULL); bsddialog_end(); + if (output == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + if (output == BSDDIALOG_CANCEL) { + printf("Cancel\n"); + return (0); + } + printf("Menu:\n"); - for (i=0; i<5; i++) + for (i = 0; i < 5; i++) printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name); - - - return output; -} + + return (output); +}
\ No newline at end of file diff --git a/examples_library/mixedlist.c b/examples_library/mixedlist.c index 2a4e9102164c..7f299218cb62 100644 --- a/examples_library/mixedlist.c +++ b/examples_library/mixedlist.c @@ -15,7 +15,8 @@ int main() { - int i, j, output; + int output; + unsigned int i, j; struct bsddialog_conf conf; struct bsddialog_menuitem item; struct bsddialog_menuitem check[5] = { @@ -41,30 +42,42 @@ int main() { BSDDIALOG_RADIOLIST, 5, radio } }; - bsddialog_initconf(&conf); - conf.title = "mixedmenu"; - - if (bsddialog_init() < 0) - return -1; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } - output = bsddialog_mixedlist(&conf, "dialog4ports", 20, 30, 11, 3, group, - NULL,NULL); + bsddialog_initconf(&conf); + conf.title = "mixedlist"; + output = bsddialog_mixedlist(&conf, "Example", 20, 30, 11, 3, group, + NULL, NULL); bsddialog_end(); + if (output == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + if (output == BSDDIALOG_CANCEL) { + printf("Cancel\n"); + return (0); + } + printf("Mixedlist:\n"); - for (i=0; i<3; i++) { - for (j=0; j<group[i].nitems; j++) { + for (i = 0; i < 3; i++) { + for (j = 0; j < group[i].nitems; j++) { item = group[i].items[j]; if (group[i].type == BSDDIALOG_SEPARATOR) printf("----- %s -----\n", item.name); else if (group[i].type == BSDDIALOG_RADIOLIST) - printf(" (%c) %s\n", item.on ? '*' : ' ', item.name); - else /* BSDDIALOG_PORTCHECKLIST */ - printf(" [%c] %s\n", item.on ? 'X' : ' ', item.name); + printf(" (%c) %s\n", + item.on ? '*' : ' ', item.name); + else /* BSDDIALOG_CHECKLIST */ + printf(" [%c] %s\n", + item.on ? 'X' : ' ', item.name); } } - - - return output; -} + + return (output); +}
\ No newline at end of file diff --git a/examples_library/msgbox.c b/examples_library/msgbox.c index 487266745c65..32696894aa85 100644 --- a/examples_library/msgbox.c +++ b/examples_library/msgbox.c @@ -15,28 +15,28 @@ int main() { - int input; + int output; struct bsddialog_conf conf; - /* Configuration */ - bsddialog_initconf(&conf); - conf.title = "msgbox"; - - /* Run BSDDialog */ if (bsddialog_init() == BSDDIALOG_ERROR) { printf("Error: %s\n", bsddialog_geterror()); - return -1; + return (1); } - input = bsddialog_msgbox(&conf, "Example", 7, 20); + + bsddialog_initconf(&conf); + conf.title = "msgbox"; + output = bsddialog_msgbox(&conf, "Example", 7, 20); + bsddialog_end(); - /* User Input */ - printf("User input: "); - switch (input) { - case BSDDIALOG_ERROR: printf("Error %s\n", bsddialog_geterror()); break; - case BSDDIALOG_OK: printf("OK\n"); break; - case BSDDIALOG_ESC: printf("ESC\n"); break; + switch (output) { + case BSDDIALOG_ERROR: + printf("Error %s\n", bsddialog_geterror()); + break; + case BSDDIALOG_OK: + printf("OK\n"); + break; } - return input; -} + return (output); +}
\ No newline at end of file diff --git a/examples_library/pause.c b/examples_library/pause.c index eb693325a18d..62c35afb0192 100644 --- a/examples_library/pause.c +++ b/examples_library/pause.c @@ -18,12 +18,13 @@ int main() int output; struct bsddialog_conf conf; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "pause"; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_pause(&conf, "Example", 8, 50, 10); bsddialog_end(); @@ -32,9 +33,6 @@ int main() case BSDDIALOG_OK: printf("OK\n"); break; - case BSDDIALOG_ESC: - printf("ESC\n"); - break; case BSDDIALOG_CANCEL: printf("Cancel\n"); break; @@ -46,5 +44,5 @@ int main() break; } - return output; -} + return (output); +}
\ No newline at end of file diff --git a/examples_library/radiolist.c b/examples_library/radiolist.c index d4c93c3d406f..79da63ad749f 100644 --- a/examples_library/radiolist.c +++ b/examples_library/radiolist.c @@ -18,27 +18,37 @@ int main() int i, output; struct bsddialog_conf conf; struct bsddialog_menuitem items[5] = { - {"", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, - {"", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, - {"", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, - {"", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, - {"", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"} + {"I", true, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, + {"II", false, 0, "Name 2", "Desc 2", "Bottom Desc 2"}, + {"III", true, 0, "Name 3", "Desc 3", "Bottom Desc 3"}, + {"IV", false, 0, "Name 4", "Desc 4", "Bottom Desc 4"}, + {"V", true, 0, "Name 5", "Desc 5", "Bottom Desc 5"} }; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "radiolist"; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_radiolist(&conf, "Example", 15, 30, 5, 5, items, NULL); bsddialog_end(); + if (output == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + if (output == BSDDIALOG_CANCEL) { + printf("Cancel\n"); + return (0); + } + printf("Radiolist:\n"); - for (i=0; i<5; i++) + for (i = 0; i < 5; i++) printf(" (%c) %s\n", items[i].on ? '*' : ' ', items[i].name); - - - return output; -} + + return (output); +}
\ No newline at end of file diff --git a/examples_library/rangebox.c b/examples_library/rangebox.c index 624bd4e438e8..06a62cc4b858 100644 --- a/examples_library/rangebox.c +++ b/examples_library/rangebox.c @@ -18,18 +18,24 @@ int main() int value, output; struct bsddialog_conf conf; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "rangebox"; - - if (bsddialog_init() < 0) - return -1; - value = 5; output = bsddialog_rangebox(&conf, "Example", 8, 50, 0, 10, &value); bsddialog_end(); - printf("Value: %d", value); + if (output == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + + printf("Value: %d\n", value); - return output; -} + return (output); +}
\ No newline at end of file diff --git a/examples_library/sade.c b/examples_library/sade.c deleted file mode 100644 index 1c1d74e5a501..000000000000 --- a/examples_library/sade.c +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * SPDX-License-Identifier: CC0-1.0 - * - * Written in 2021 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> - -/* Figure 15 - https://docs.freebsd.org/en/books/handbook/bsdinstall/ */ -int main() -{ - int i, output; - struct bsddialog_conf conf; - char *text = "Please review the disk setup. When complete, press the " - "Finish button"; - struct bsddialog_menuitem items[5] = { - {"", false, 0, "ada0", "16 GB GPT", ""}, - {"", false, 1, "ada0p1", "512 KB freebsd-boot", ""}, - {"", false, 1, "ada0p2", "15 GB freebsd-ufs", ""}, - {"", false, 1, "ada0p3", "819 MB freebsd-swap none", ""}, - {"", false, 0, "ada1", "16 GB", ""} - }; - - bsddialog_initconf(&conf); - - conf.title = "Partition Editor"; - conf.menu.shortcut_buttons = true; - conf.menu.align_left = true; - conf.button.ok_label = "Create"; - conf.button.with_extra = true; - conf.button.extra_label = "Delete"; - conf.button.cancel_label = "Cancel"; - conf.button.with_help = true; - conf.button.help_label = "Revert"; - conf.button.generic1_label = "Auto"; - conf.button.generic2_label = "Finish"; - conf.button.default_label = "Finish"; - - if (bsddialog_init() == BSDDIALOG_ERROR) - return (1); - output = bsddialog_menu(&conf, text, 20, 0, 10, 5, items, NULL); - bsddialog_end(); - - printf("Menu:\n"); - for (i=0; i<5; i++) - printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name); - - - return (output); -} diff --git a/examples_library/theme.c b/examples_library/theme.c index 305692d39cff..fb09aa1d1b24 100644 --- a/examples_library/theme.c +++ b/examples_library/theme.c @@ -16,47 +16,60 @@ int main() { - int output; + int output, focusitem; struct bsddialog_conf conf; enum bsddialog_default_theme theme; - struct bsddialog_menuitem items[4] = { - {"", false, 0, "Dialog", "Current dialog theme", "BSDDIALOG_THEME_DIALOG" }, - {"", false, 0, "BSDDialog", "Future default theme", "BSDDIALOG_THEME_DEFAULT"}, - {"", false, 0, "BlackWhite","Black and White theme", "BSDDIALOG_THEME_BLACKWHITE"}, - {"", false, 0, "Quit", "Exit", "Quit or Cancel to exit" } + struct bsddialog_menuitem items[5] = { + {"", false, 0, "Default", "dialog-like", + "BSDDIALOG_THEME_DEFAULT" }, + {"", false, 0, "Dialog", "dialog clone", + "BSDDIALOG_THEME_DIALOG" }, + {"", false, 0, "BSDDialog", "new theme", + "BSDDIALOG_THEME_BSDDIALOG" }, + {"", false, 0, "BlackWhite","black and white", + "BSDDIALOG_THEME_BLACKWHITE" }, + {"", false, 0, "Quit", "Exit", "Quit or Cancel to exit" } }; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); - conf.title = " Theme "; - - if (bsddialog_init() == BSDDIALOG_ERROR) - return BSDDIALOG_ERROR; - while (true) { - bsddialog_backtitle(&conf, "Theme Example"); + bsddialog_backtitle(&conf, "Theme Example"); - output = bsddialog_menu(&conf, "Choose theme", 15, 40, 4, 4, items, NULL); + conf.title = " Theme "; + focusitem = -1; + while (true) { + output = bsddialog_menu(&conf, "Choose theme", 15, 40, 5, 5, + items, &focusitem); - if (output != BSDDIALOG_OK || items[3].on) + if (output != BSDDIALOG_OK || items[4].on) break; if (items[0].on) { - theme = BSDDIALOG_THEME_DIALOG; - conf.menu.default_item = items[0].name; + theme = BSDDIALOG_THEME_DEFAULT; + focusitem = 0; } else if (items[1].on) { - theme = BSDDIALOG_THEME_BSDDIALOG; - conf.menu.default_item = items[1].name; + theme = BSDDIALOG_THEME_DIALOG; + focusitem = 1; } else if (items[2].on) { + theme = BSDDIALOG_THEME_BSDDIALOG; + focusitem = 2; + } + else if (items[3].on) { theme = BSDDIALOG_THEME_BLACKWHITE; - conf.menu.default_item = items[2].name; + focusitem = 3; } bsddialog_set_default_theme(theme); } - bsddialog_end(); + bsddialog_end(); - return output; -} + return (output); +}
\ No newline at end of file diff --git a/examples_library/timebox.c b/examples_library/timebox.c index 117d45dcdb7b..6e3721ea9188 100644 --- a/examples_library/timebox.c +++ b/examples_library/timebox.c @@ -28,24 +28,22 @@ int main() mm = localtm->tm_min; ss = localtm->tm_sec; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "timebox"; conf.bottomtitle = "Press TAB and arrows"; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_timebox(&conf, "Example", 10, 50, &hh, &mm, &ss); - + bsddialog_end(); switch (output) { case BSDDIALOG_OK: printf("Time: [%u:%u:%u]\n", hh, mm, ss); break; - case BSDDIALOG_ESC: - printf("ESC\n"); - break; case BSDDIALOG_CANCEL: printf("Cancel\n"); break; @@ -54,5 +52,5 @@ int main() break; } - return output; -} + return (output); +}
\ No newline at end of file diff --git a/examples_library/treeview.c b/examples_library/treeview.c deleted file mode 100644 index 7fa3d229adf9..000000000000 --- a/examples_library/treeview.c +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: CC0-1.0 - * - * Written in 2021 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 <stdio.h> -#include <string.h> - -#include <bsddialog.h> - -int main() -{ - int i, output; - struct bsddialog_conf conf; - struct bsddialog_menuitem items[5] = { - {"", false, 0, "Name 1", "Desc 1", "Bottom Desc 1"}, - {"", false, 1, "Name 2", "Desc 2", "Bottom Desc 2"}, - {"", false, 1, "Name 3", "Desc 3", "Bottom Desc 3"}, - {"", false, 2, "Name 4", "Desc 4", "Bottom Desc 4"}, - {"", false, 1, "Name 5", "Desc 5", "Bottom Desc 5"} - }; - - bsddialog_initconf(&conf); - conf.title = "radiolist"; - conf.menu.no_name = true; - conf.menu.align_left = true; - - if (bsddialog_init() < 0) - return -1; - - output = bsddialog_radiolist(&conf, "Example", 15, 30, 5, 5, items, NULL); - - bsddialog_end(); - - printf("Treeview:\n"); - for (i=0; i<5; i++) - printf(" (%c) %s\n", items[i].on ? '*' : ' ', items[i].name); - - - return output; -} diff --git a/examples_library/yesno.c b/examples_library/yesno.c index 783fcf57cbb6..5a9c95edc849 100644 --- a/examples_library/yesno.c +++ b/examples_library/yesno.c @@ -18,15 +18,28 @@ int main() int output; struct bsddialog_conf conf; + if (bsddialog_init() == BSDDIALOG_ERROR) { + printf("Error: %s\n", bsddialog_geterror()); + return (1); + } + bsddialog_initconf(&conf); conf.title = "yesno"; - - if (bsddialog_init() < 0) - return -1; - output = bsddialog_yesno(&conf, "Example", 7, 25); bsddialog_end(); - return output; -} + switch (output) { + case BSDDIALOG_ERROR: + printf("Error %s\n", bsddialog_geterror()); + break; + case BSDDIALOG_YES: + printf("YES\n"); + break; + case BSDDIALOG_NO: + printf("NO\n"); + break; + } + + return (output); +}
\ No newline at end of file diff --git a/examples_utility/buildlist.sh b/examples_utility/buildlist.sh deleted file mode 100755 index cefeea8f3c51..000000000000 --- a/examples_utility/buildlist.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -#- -# SPDX-License-Identifier: CC0-1.0 -# -# Written in 2021 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 --title buildlist --buildlist "Hello World!" 15 40 5 \ - "Tag 1" "DESC 1 xyz" off \ - "Tag 2" "DESC 2 xyz" off \ - "Tag 3" "DESC 3 xyz" on \ - "Tag 4" "DESC 4 xyz" off \ - "Tag 5" "DESC 5 xyz" off \ - 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/checklist.sh b/examples_utility/checklist.sh index 5f9a17cb64b1..94eb2043a3ab 100755 --- a/examples_utility/checklist.sh +++ b/examples_utility/checklist.sh @@ -6,9 +6,9 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title checklist --checklist "Hello World!" 15 30 5 \ +./bsddialog --title " checklist " --checklist "Hello World!" 15 30 5 \ "Tag 1" "DESC 1 xyz" on \ "Tag 2" "DESC 2 xyz" off \ "Tag 3" "DESC 3 xyz" on \ diff --git a/examples_utility/form.sh b/examples_utility/form.sh index 5d6b6ee1b606..ad1b5d275d0d 100755 --- a/examples_utility/form.sh +++ b/examples_utility/form.sh @@ -6,14 +6,14 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. ./bsddialog --title " form " --form "Hello World!" 12 40 5 \ - Label1: 1 1 Value1 1 9 18 25 \ - Label2: 2 1 Value2 2 9 18 25 \ - Label3: 3 1 Value3 3 9 18 25 \ - Label4: 4 1 Value4 4 9 18 25 \ - Label5: 5 1 Value5 5 9 18 25 \ + Label1: 1 1 Value1 1 9 18 25 \ + Label2: 2 1 Value2 2 9 18 25 \ + Label3: 3 1 Value3 3 9 18 25 \ + Label4: 4 1 Value4 4 9 18 25 \ + Label5: 5 1 Value5 5 9 18 25 \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/gauge.sh b/examples_utility/gauge.sh index 82d15655efe2..1665e04b4e8c 100755 --- a/examples_utility/gauge.sh +++ b/examples_utility/gauge.sh @@ -6,23 +6,23 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -input="A B C D E F G" -total=`echo $input | awk '{print split($0, a)}'` -curr=1 -for i in $input +characters="A B C D E F G" +total=`echo $characters | awk '{print split($0, a)}'` +i=1 +for c in $characters do sleep 1 - perc="$(expr $(expr $curr "*" 100 ) "/" $total )" - echo XXX - echo $perc - echo "[$curr/$total] Input: $i" - echo XXX - if [ $curr -eq $total ] - then - echo EOF - fi - curr=`expr $curr + 1` -done | ./bsddialog --title gauge --gauge "[0/$total] Starting..." 10 70 0 + echo XXX + echo "$(expr $(expr $i "*" 100) "/" $total)" + echo "[$i/$total] Char: $c" + echo XXX + if [ $i -eq $total ] + then + sleep 1 + echo EOF + fi + i=`expr $i + 1` +done | ./bsddialog --title " gauge " --gauge "[0/$total] Starting..." 10 70 diff --git a/examples_utility/infobox.sh b/examples_utility/infobox.sh index 468ecff826fd..75d14d10177a 100755 --- a/examples_utility/infobox.sh +++ b/examples_utility/infobox.sh @@ -6,7 +6,6 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. - -./bsddialog --sleep 3 --title infobox --infobox "Hello World!\n3 seconds" 6 20 +./bsddialog --sleep 3 --title " infobox " --infobox "Hello World!\n3 secs" 6 20 diff --git a/examples_utility/inputbox.sh b/examples_utility/inputbox.sh index 27073468a478..340500eaab1f 100755 --- a/examples_utility/inputbox.sh +++ b/examples_utility/inputbox.sh @@ -6,7 +6,7 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title " inputbox " --inputbox "Hello World!" 12 40 init \ +./bsddialog --title " inputbox " --inputbox "Hello World!" 12 40 default \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/menu.sh b/examples_utility/menu.sh index 66c9f54beb4c..fe56f4e079cf 100755 --- a/examples_utility/menu.sh +++ b/examples_utility/menu.sh @@ -6,12 +6,12 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title menu --menu "Hello World!" 15 30 5 \ - "Tag 1" "DESC 1 xyz" \ - "Tag 2" "DESC 2 xyz" \ - "Tag 3" "DESC 3 xyz" \ - "Tag 4" "DESC 4 xyz" \ - "Tag 5" "DESC 5 xyz" \ +./bsddialog --title " menu " --menu "Hello World!" 15 30 5 \ + "Tag 1" "DESC 1 xyz" \ + "Tag 2" "DESC 2 xyz" \ + "Tag 3" "DESC 3 xyz" \ + "Tag 4" "DESC 4 xyz" \ + "Tag 5" "DESC 5 xyz" \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/mixedform.sh b/examples_utility/mixedform.sh index 6677c20781ad..303c1a63dd98 100755 --- a/examples_utility/mixedform.sh +++ b/examples_utility/mixedform.sh @@ -6,10 +6,10 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. ./bsddialog --insecure --title " mixedform " --mixedform "Hello World!" 12 40 5 \ - Label: 1 1 Entry 1 11 18 25 0 \ - Label: 2 1 Read-Only 2 11 18 25 2 \ - Password: 3 1 Value2 3 11 18 25 1 \ + Label: 11 Entry 1 11 18 25 0 \ + Label: 21 Read-Only 2 11 18 25 2 \ + Password: 31 "" 3 11 18 25 1 \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/mixedgauge.sh b/examples_utility/mixedgauge.sh index bc0f91a1e506..735f8dc42922 100755 --- a/examples_utility/mixedgauge.sh +++ b/examples_utility/mixedgauge.sh @@ -6,29 +6,25 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. - -input="A B C D E F G H" -total=`echo $input | awk '{print split($0, a)}'` -curr=1 -for i in $input +perc=0 +while [ $perc -le 100 ] do - perc="$(expr $(expr $curr "*" 100 ) "/" $total )" - curr=`expr $curr + 1` - ./bsddialog --sleep 1 --title " mixedgauge " --mixedgauge "Example" 25 50 $perc \ - "Hidden!" 8 \ - "Label 1" 0 \ - "Label 2" 1 \ - "Label 3" 2 \ - "Label 4" 3 \ - "Label 5" 4 \ - "Label 6" 5 \ - "Label 7" 6 \ - "Label 8" 7 \ - "Label 9" 9 \ - "Label 10" 10 \ - "Label X" " -$perc" - #sleep 1 -done + ./bsddialog --sleep 1 --title " mixedgauge " \ + --mixedgauge "Example..." 20 45 $perc \ + "(Hidden)" " -9" \ + "Label 1" " -1" \ + "Label 2" " -2" \ + "Label 3" " -3" \ + "Label 4" " -4" \ + "Label 5" " -5" \ + "Label 6" " -6" \ + "Label 7" " -7" \ + "Label 8" " -8" \ + "Label 9" " -10" \ + "Label 10" " -11" \ + "Label X" $perc + perc=`expr $perc + 20` +done diff --git a/examples_utility/msgbox.sh b/examples_utility/msgbox.sh index 49cb626f4055..9e14ed6cbba4 100755 --- a/examples_utility/msgbox.sh +++ b/examples_utility/msgbox.sh @@ -6,6 +6,6 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title msgbox --msgbox "Hello World!" 6 20 +./bsddialog --title " msgbox " --msgbox "Hello World!" 6 20 diff --git a/examples_utility/passwordbox.sh b/examples_utility/passwordbox.sh index 5c6a91e0f057..673491f64140 100755 --- a/examples_utility/passwordbox.sh +++ b/examples_utility/passwordbox.sh @@ -6,7 +6,7 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. ./bsddialog --insecure --title " password " --passwordbox "Hello World!" 12 40 \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/passwordform.sh b/examples_utility/passwordform.sh index 5cfe0b0fa0a1..658f1635dffc 100755 --- a/examples_utility/passwordform.sh +++ b/examples_utility/passwordform.sh @@ -6,12 +6,12 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. ./bsddialog --insecure --title " passwordform " --passwordform "Example" 12 40 5 \ - Password1: 1 1 Value1 1 12 18 25 \ - Password2: 2 1 Value2 2 12 18 25 \ - Password3: 3 1 Value3 3 12 18 25 \ - Password4: 4 1 Value4 4 12 18 25 \ - Password5: 5 1 Value5 5 12 18 25 \ + Password1: 1 1 "" 1 12 18 25 \ + Password2: 2 1 "" 2 12 18 25 \ + Password3: 3 1 "" 3 12 18 25 \ + Password4: 4 1 "" 4 12 18 25 \ + Password5: 5 1 "" 5 12 18 25 \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/radiolist.sh b/examples_utility/radiolist.sh index c1c7724eb09d..2b4ce8d56809 100755 --- a/examples_utility/radiolist.sh +++ b/examples_utility/radiolist.sh @@ -6,12 +6,12 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title radiolist --radiolist "Hello World!" 15 30 5 \ - "Tag 1" "DESC 1 xyz" off \ - "Tag 2" "DESC 2 xyz" off \ - "Tag 3" "DESC 3 xyz" on \ - "Tag 4" "DESC 4 xyz" off \ - "Tag 5" "DESC 5 xyz" off \ +./bsddialog --title " radiolist " --radiolist "Hello World!" 15 30 5 \ + "Tag 1" "DESC 1 xyz" off \ + "Tag 2" "DESC 2 xyz" off \ + "Tag 3" "DESC 3 xyz" on \ + "Tag 4" "DESC 4 xyz" off \ + "Tag 5" "DESC 5 xyz" off \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/treeview.sh b/examples_utility/treeview.sh index 5286de673a1d..3566c6812714 100755 --- a/examples_utility/treeview.sh +++ b/examples_utility/treeview.sh @@ -6,12 +6,12 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title treeview --treeview "Hello World!" 15 40 5 \ - 0 "Tag 1" "DESC 1 xyz" off \ - 1 "Tag 2" "DESC 2 xyz" off \ - 2 "Tag 3" "DESC 3 xyz" on \ - 1 "Tag 4" "DESC 4 xyz" off \ - 1 "Tag 5" "DESC 5 xyz" off \ +./bsddialog --title " treeview " --treeview "Hello World!" 15 40 5 \ + 0 "Tag 1" "DESC 1 xyz" off \ + 1 "Tag 2" "DESC 2 xyz" off \ + 2 "Tag 3" "DESC 3 xyz" on \ + 1 "Tag 4" "DESC 4 xyz" off \ + 1 "Tag 5" "DESC 5 xyz" off \ 2>out.txt ; cat out.txt ; rm out.txt diff --git a/examples_utility/yesno.sh b/examples_utility/yesno.sh index 7d1d33530606..cfa082e8d24e 100755 --- a/examples_utility/yesno.sh +++ b/examples_utility/yesno.sh @@ -6,6 +6,6 @@ # 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/>. +# <http://creativecommons.org/publicdomain/zero/1.0/>. -./bsddialog --title yesno --yesno "Hello World!" 6 25 +./bsddialog --title " yesno " --yesno "Hello World!" 6 25 diff --git a/lib/GNUMakefile b/lib/GNUMakefile index 318b1218f9c0..842e03494b4c 100644 --- a/lib/GNUMakefile +++ b/lib/GNUMakefile @@ -1,17 +1,17 @@ # PUBLIC DOMAIN - NO WARRANTY, see: -# <http://creativecommons.org/publicdomain/zero/1.0/> +# <http://creativecommons.org/publicdomain/zero/1.0/> # # Written in 2021 by Alfonso Sabato Siciliano -VERSION = 0.0.2 +VERSION = 0.1 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 OBJECTS = $(SOURCES:.c=.o) -CFLAGS = -g -Wall -Werror -fpic -LDFLAGS = -lform -lncurses -ltinfo +CFLAGS = -Wall -Werror -fpic +LDFLAGS = -lformw -lncursesw -ltinfo LIBFLAG = -shared RM = rm -f diff --git a/lib/Makefile b/lib/Makefile index e8f3ab6aae02..d9f2ce8ed69b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,56 +1,55 @@ -# Any copyright is dedicated to the Public Domain, see: +# PUBLIC DOMAIN - NO WARRANTY, see: # <http://creativecommons.org/publicdomain/zero/1.0/> # # Written in 2021 by Alfonso Sabato Siciliano -VERSION = 0.0.2 +VERSION = 0.1 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 -OBJECTS= ${SOURCES:.c=.o} -CFLAGS = -I/usr/local/include -fPIC -Wall -Wextra -LDFLAGS = -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \ - -Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} +OBJECTS = ${SOURCES:.c=.o} +CFLAGS += -fPIC -Wall -Wextra +LDFLAGS += -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings \ + -Wl,--warn-shared-textrel -Wl,-soname,${LIBRARY_SO}.${VERSION} \ + -L/usr/lib -lformw -lncursesw -ltinfow .if defined(DEBUG) # `make -DDEBUG` -CFLAGS += -g +CFLAGS = -g -fPIC -Wall -Wextra .else CFLAGS += -O2 -pipe -std=gnu99 -Wno-format-zero-length \ -fstack-protector-strong -Qunused-arguments .endif -.if defined(PORTNCURSES) -# PORT ncurses `make -DPORTNCURSES` -CFLAGS += -DPORTNCURSES -I/usr/local/include -LDFLAGS += -L/usr/local/lib -lformw -lncursesw -ltinfow -.else -# BASE ncurses -LDFLAGS += -L/usr/lib -lformw -lncursesw -ltinfow -.endif - -INSTALL_PREFIX=/usr/local +LOCALBASE = /usr/local LN = ln -s -f RM = rm -f CP = cp GZIP = gzip -cn LDCONFIG = /sbin/ldconfig -m -MAN= ${OUTPUT}.3 -GZIP= gzip -cn -MANDIR= /usr/local/share/man/man3 -INSTALL= install -RM= rm -f +MAN = ${OUTPUT}.3 +GZIP = gzip -cn +MANDIR = ${LOCALBASE}/share/man/man3 +INSTALL = install +RM = rm -f + +all : man ${LIBRARY} -#all : man ${LIBRARY} -all : ${LIBRARY} +${LIBRARY}: ${LIBRARY_SO} ${LIBRARY_A} -${LIBRARY}: ${OBJECTS} +${LIBRARY_SO}.${VERSION}: ${OBJECTS} ${CC} ${LDFLAGS} ${.ALLSRC} -o ${LIBRARY_SO}.${VERSION} - # LN for devel + +${LIBRARY_SO}: ${LIBRARY_SO}.${VERSION} ${LN} ${LIBRARY_SO}.${VERSION} ${LIBRARY_SO} +${LIBRARY_A}: ${OBJECTS} + ${AR} cr ${.TARGET} ${OBJECTS} + ${RANLIB} ${.TARGET} + .c.o: ${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET} @@ -58,19 +57,20 @@ man: ${GZIP} ${LIBRARY}.3 > ${LIBRARY}.3.gz clean: - ${RM} ${LIBRARY_SO}* *.o *~ *.gz + ${RM} ${LIBRARY_SO}* *.o *~ *.gz ${LIBRARY_A} install: - ${CP} ${LIBRARY}.h ${INSTALL_PREFIX}/include - ${CP} ${LIBRARY_SO}.${VERSION} ${INSTALL_PREFIX}/lib/ - ${LN} ${INSTALL_PREFIX}/lib/${LIBRARY_SO}.${VERSION} ${INSTALL_PREFIX}/lib/${LIBRARY_SO} - ${LDCONFIG} ${INSTALL_PREFIX}/lib - ${CP} ${LIBRARY}.3.gz ${INSTALL_PREFIX}/man/man3/ + ${INSTALL} -m 644 ${HEADERS} ${LOCALBASE}/include + ${INSTALL} -m 644 -s ${LIBRARY_SO}.${VERSION} ${LOCALBASE}/lib/ + ${INSTALL} -l rs ${LOCALBASE}/lib/${LIBRARY_SO}.${VERSION} ${LOCALBASE}/lib/${LIBRARY_SO} + ${INSTALL} -m 644 ${LIBRARY_A} ${LOCALBASE}/lib + ${LDCONFIG} ${LOCALBASE}/lib + ${INSTALL} -m 644 ${LIBRARY}.3.gz ${MNADIR} unistall: - ${RM} ${INSTALL_PREFIX}/include/${LIBRARY}.h - ${RM} ${INSTALL_PREFIX}/lib/${LIBRARY_SO} - ${RM} ${INSTALL_PREFIX}/lib/${LIBRARY_SO}.${VERSION} - ${LDCONFIG} ${INSTALL_PREFIX}/lib - ${RM} ${INSTALL_PREFIX}/man/man3/${LIBRARY}.3.gz + ${RM} ${LOCALBASE}/include/${LIBRARY}*.h + ${RM} ${LOCALBASE}/lib/${LIBRARY_SO} + ${RM} ${LOCALBASE}/lib/${LIBRARY_SO}.${VERSION} + ${LDCONFIG} ${LOCALBASE}/lib + ${RM} ${MANDIR}/${LIBRARY}.3.gz diff --git a/lib/barbox.c b/lib/barbox.c index d67dfb953992..72000fad747c 100644 --- a/lib/barbox.c +++ b/lib/barbox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,26 +28,19 @@ #include <sys/param.h> #include <ctype.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include <stdlib.h> #include <string.h> #include <time.h> +#include <unistd.h> #include "bsddialog.h" #include "bsddialog_progressview.h" -#include "lib_util.h" #include "bsddialog_theme.h" +#include "lib_util.h" -#define BARMARGIN 3 -#define MINBARWIDTH 10 -#define MINWIDTH (VBORDERS + MINBARWIDTH + BARMARGIN * 2) -#define MINHEIGHT 7 /* without text */ - -/* "Bar": gauge - mixedgauge - rangebox - pause - progressview */ +#define BARPADDING 3 +#define MINBARWIDTH (15 + BARPADDING * 2) bool bsddialog_interruptprogview; bool bsddialog_abortprogview; @@ -56,11 +49,11 @@ int bsddialog_total_progview; extern struct bsddialog_theme t; static void -draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, +draw_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, int label) { - char labelstr[128]; int i, blue_x, color; + char labelstr[128]; blue_x = (int)((perc*(size))/100); @@ -77,7 +70,7 @@ draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, else sprintf(labelstr, "%3d%%", perc); wmove(win, y, x + size/2 - 2); - for (i=0; i < (int) strlen(labelstr); i++) { + for (i = 0; i < (int)strlen(labelstr); i++) { color = (blue_x + 1 <= size/2 - (int)strlen(labelstr)/2 + i ) ? t.bar.color : t.bar.f_color; wattron(win, color); @@ -88,49 +81,27 @@ draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, static int bar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, - char *text, struct buttons *bs) + const char *text, struct buttons *bs) { - int maxword, maxline, nlines, buttonswidth; - - if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) - return BSDDIALOG_ERROR; + int htext, wtext; - buttonswidth = 0; - if (bs != NULL) { /* gauge has not buttons */ - buttonswidth= bs->nbuttons * bs->sizebutton; - if (bs->nbuttons > 0) - buttonswidth += (bs->nbuttons-1) * t.button.space; + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, bs, 3, MINBARWIDTH, + &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += buttonswidth; - /* bar size */ - *w = MAX(*w, MINWIDTH); - /* text size*/ - *w = MAX((int)(maxline + VBORDERS + t.text.hmargin * 2), *w); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* avoid terminal overflow */ - *w = MIN(*w, widget_max_width(conf)); - } + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, MINBARWIDTH, bs); - if (rows == BSDDIALOG_AUTOSIZE) { - *h = MINHEIGHT; - if (maxword > 0) - *h += 1; - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); - } + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, htext, 3 /* bar */, bs != NULL); return (0); } static int -bar_checksize(char *text, int rows, int cols, struct buttons *bs) +bar_checksize(int rows, int cols, struct buttons *bs) { int minheight, minwidth; @@ -140,200 +111,213 @@ bar_checksize(char *text, int rows, int cols, struct buttons *bs) if (bs->nbuttons > 0) minwidth += (bs->nbuttons-1) * t.button.space; } - minwidth = MAX(minwidth + VBORDERS, MINBARWIDTH); + minwidth = MAX(minwidth, MINBARWIDTH); + minwidth += VBORDERS; - if (cols< minwidth) - RETURN_ERROR("Few cols for this widget"); + if (cols < minwidth) + RETURN_ERROR("Few cols to draw bar and/or buttons"); - minheight = MINHEIGHT + ((text != NULL && strlen(text) > 0) ? 1 : 0); + minheight = HBORDERS + 3; + if (bs != NULL) + minheight += 2; if (rows < minheight) - RETURN_ERROR("Few rows for this mixedgauge"); + RETURN_ERROR("Few rows to draw bar"); - return 0; + return (0); } int -bsddialog_gauge(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int perc) +bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int perc, int fd, const char *sep) { - WINDOW *widget, *textpad, *bar, *shadow; - char input[2048], ntext[2048], *pntext; - int y, x, h, w, htextpad; bool mainloop; + int y, x, h, w, fd2; + FILE *input; + WINDOW *widget, *textpad, *bar, *shadow; + char inputbuf[2048], ntext[2048], *pntext; if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (bar_autosize(conf, rows, cols, &h, &w, text, NULL) != 0) - return BSDDIALOG_ERROR; - if (bar_checksize(text, h, w, NULL) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (bar_checksize(h, w, NULL) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, false) != 0) - return BSDDIALOG_ERROR; + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, NULL, + false) != 0) + return (BSDDIALOG_ERROR); bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED); - mainloop = true; + mainloop = (fd < 0) ? false : true; + + if (mainloop) { + fd2 = dup(fd); + input = fdopen(fd2, "r"); + if (input == NULL) + RETURN_ERROR("Cannot build FILE* from fd"); + } else + input = NULL; + while (mainloop) { wrefresh(widget); - prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-4, - x+w-1-t.text.hmargin); - draw_perc_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/); + prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-4, + x+w-1-TEXTHMARGIN); + draw_borders(conf, bar, 3, w-6, RAISED); + draw_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/); wrefresh(bar); while (true) { - scanf("%s", input); - if (strcmp(input,"EOF") == 0) { + fscanf(input, "%s", inputbuf); + if (strcmp(inputbuf,"EOF") == 0) { mainloop = false; break; } - if (strcmp(input,"XXX") == 0) + if (strcmp(inputbuf, sep) == 0) break; } - scanf("%d", &perc); + if (mainloop == false) + break; + fscanf(input, "%d", &perc); perc = perc < 0 ? 0 : perc; perc = perc > 100 ? 100 : perc; - htextpad = 1; - wclear(textpad); pntext = &ntext[0]; ntext[0] = '\0'; while (true) { - scanf("%s", input); - if (strcmp(input,"EOF") == 0) { + fscanf(input, "%s", inputbuf); + if (strcmp(inputbuf,"EOF") == 0) { mainloop = false; break; } - if (strcmp(input,"XXX") == 0) + if (strcmp(inputbuf, sep) == 0) break; + strcpy(pntext, inputbuf); + pntext += strlen(inputbuf); pntext[0] = ' '; pntext++; - strcpy(pntext, input); - pntext += strlen(input); } - print_textpad(conf, textpad, &htextpad, w-2-t.text.hmargin*2, - ntext); + if (update_dialog(conf, shadow, widget, y, x, h, w, textpad, + ntext, NULL, false) != 0) + return (BSDDIALOG_ERROR); } + if (input != NULL) + fclose(input); delwin(bar); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return BSDDIALOG_OK; + return (BSDDIALOG_OK); } - /* Mixedgauge */ static int -mixedgauge(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int mainperc, unsigned int nminibars, char **minilabels, +do_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, int cols, + unsigned int mainperc, unsigned int nminibars, const char **minilabels, int *minipercs, bool color) { - WINDOW *widget, *textpad, *bar, *shadow; - int i, output, miniperc, y, x, h, w, max_minbarlen; - int maxword, maxline, nlines, htextpad, ypad; + int i, output, miniperc, y, x, h, w, ypad, max_minbarlen; + int htextpad, htext, wtext; int colorperc, red, green; + WINDOW *widget, *textpad, *bar, *shadow; char states[12][14] = { - " Succeeded ", /* 0 */ - " Failed ", /* 1 */ - " Passed ", /* 2 */ - " Completed ", /* 3 */ - " Checked ", /* 4 */ - " Done ", /* 5 */ - " Skipped ", /* 6 */ - " In Progress ", /* 7 */ - "(blank) ", /* 8 */ - " N/A ", /* 9 */ - " Pending ", /* 10 */ - " UNKNOWN ", /* 10+ */ + " Succeeded ", /* -1 */ + " Failed ", /* -2 */ + " Passed ", /* -3 */ + " Completed ", /* -4 */ + " Checked ", /* -5 */ + " Done ", /* -6 */ + " Skipped ", /* -7 */ + " In Progress ", /* -8 */ + "(blank) ", /* -9 */ + " N/A ", /* -10 */ + " Pending ", /* -11 */ + " UNKNOWN ", /* < -11, no API */ }; red = bsddialog_color(BSDDIALOG_WHITE,BSDDIALOG_RED, BSDDIALOG_BOLD); green = bsddialog_color(BSDDIALOG_WHITE,BSDDIALOG_GREEN,BSDDIALOG_BOLD); max_minbarlen = 0; - for (i=0; i < (int)nminibars; i++) + for (i = 0; i < (int)nminibars; i++) max_minbarlen = MAX(max_minbarlen, (int)strlen(minilabels[i])); max_minbarlen += 3 + 16 /* seps + [...] or mainbar */; if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); /* mixedgauge autosize */ - if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) - return BSDDIALOG_ERROR; - - if (cols == BSDDIALOG_AUTOSIZE) { - w = max_minbarlen + HBORDERS; - w = MAX(w, maxline + 4); - w = MAX(w, (int)conf->auto_minwidth); - w = MIN(w, widget_max_width(conf) - 1); - } - if (rows == BSDDIALOG_AUTOSIZE) { - h = 5; /* borders + mainbar */ - h += nminibars; - h += (strlen(text) > 0 ? 3 : 0); - h = MAX(h, (int)conf->auto_minheight); - h = MIN(h, widget_max_height(conf) -1); + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, NULL, nminibars + 3, + max_minbarlen, &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } + if (cols == BSDDIALOG_AUTOSIZE) + w = widget_min_width(conf, wtext, max_minbarlen, NULL); + if (rows == BSDDIALOG_AUTOSIZE) + h = widget_min_height(conf, htext, nminibars + 3, false); /* mixedgauge checksize */ if (w < max_minbarlen + 2) RETURN_ERROR("Few cols for this mixedgauge"); - if (h < 5 + (int)nminibars + (strlen(text) > 0 ? 1 : 0)) + if (h < 5 + (int)nminibars) RETURN_ERROR("Few rows for this mixedgauge"); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - output = new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, - RAISED, &textpad, &htextpad, text, false); + output = new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, + NULL, false); if (output == BSDDIALOG_ERROR) - return output; + return (output); /* mini bars */ - for (i=0; i < (int)nminibars; i++) { + for (i = 0; i < (int)nminibars; i++) { miniperc = minipercs[i]; - if (miniperc == 8) + if (miniperc == BSDDIALOG_MG_BLANK) continue; /* label */ - if (color && (miniperc == 7 || miniperc < 0)) + if (color && (miniperc >= 0)) wattron(widget, A_BOLD); mvwaddstr(widget, i+1, 2, minilabels[i]); wattroff(widget, A_BOLD); /* perc */ - if (miniperc > 10) + if (miniperc < -11) mvwaddstr(widget, i+1, w-2-15, states[11]); - else if (miniperc >= 0 && miniperc <= 10) { + else if (miniperc < 0) { mvwaddstr(widget, i+1, w-2-15, "[ ]"); - if (color && miniperc == 1) /* Failed */ + colorperc = -1; + if (color && miniperc == BSDDIALOG_MG_FAILED) colorperc = red; - if (color && miniperc == 5) /* Done */ + if (color && miniperc == BSDDIALOG_MG_DONE) colorperc = green; - if (color && (miniperc == 1 || miniperc == 5)) + if (colorperc != -1) wattron(widget, colorperc); + miniperc = abs(miniperc + 1); mvwaddstr(widget, i+1, 1+w-2-15, states[miniperc]); - if (color && (miniperc == 1 || miniperc == 5)) + if (colorperc != -1) wattroff(widget, colorperc); } - else { /* miniperc < 0 */ - miniperc = abs(miniperc); + else { /* miniperc >= 0 */ + if (miniperc > 100) + miniperc = 100; mvwaddstr(widget, i+1, w-2-15, "[ ]"); - draw_perc_bar(widget, i+1, 1+w-2-15, 13, miniperc, - false, -1 /*unused*/); + draw_bar(widget, i+1, 1+w-2-15, 13, miniperc, false, + -1 /*unused*/); } } wrefresh(widget); - ypad = y + h - 5 - htextpad; + getmaxyx(textpad, htextpad, i /* unused */); + ypad = y + h - 4 - htextpad; ypad = ypad < y+(int)nminibars ? y+nminibars : ypad; prefresh(textpad, 0, 0, ypad, x+2, y+h-4, x+w-2); - + /* main bar */ bar = new_boxed_window(conf, y+h -4, x+3, 3, w-6, RAISED); - - draw_perc_bar(bar, 1, 1, w-8, mainperc, false, -1 /*unused*/); + + draw_bar(bar, 1, 1, w-8, mainperc, false, -1 /*unused*/); wattron(bar, t.bar.color); mvwaddstr(bar, 0, 2, "Overall Progress"); @@ -344,48 +328,46 @@ mixedgauge(struct bsddialog_conf *conf, char* text, int rows, int cols, /* getch(); port ncurses shows nothing */ delwin(bar); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return BSDDIALOG_OK; + return (BSDDIALOG_OK); } int -bsddialog_mixedgauge(struct bsddialog_conf *conf, char* text, int rows, - int cols, unsigned int mainperc, unsigned int nminibars, char **minilabels, - int *minipercs) +bsddialog_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int mainperc, unsigned int nminibars, + const char **minilabels, int *minipercs) { int output; - output = mixedgauge(conf, text, rows, cols, mainperc, nminibars, + output = do_mixedgauge(conf, text, rows, cols, mainperc, nminibars, minilabels, minipercs, false); return (output); } int -bsddialog_progressview (struct bsddialog_conf *conf, char * text, int rows, +bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows, int cols, struct bsddialog_progviewconf *pvconf, unsigned int nminibar, struct bsddialog_fileminibar *minibar) { - int perc, output; - int *minipercs; - unsigned int i; - char **minilabels; - unsigned int mainperc, totaltodo; - time_t tstart, told, tnew, refresh; bool update; + int perc, output, *minipercs; + unsigned int i, mainperc, totaltodo; float readforsec; + const char **minilabels; + time_t tstart, told, tnew, refresh; if ((minilabels = calloc(nminibar, sizeof(char*))) == NULL) - RETURN_ERROR("Cannot allocate memory for minilabels\n"); + RETURN_ERROR("Cannot allocate memory for minilabels"); if ((minipercs = calloc(nminibar, sizeof(int))) == NULL) - RETURN_ERROR("Cannot allocate memory for minipercs\n"); + RETURN_ERROR("Cannot allocate memory for minipercs"); totaltodo = 0; - for(i=0; i<nminibar; i++) { - totaltodo += minibar[i].size; + for (i = 0; i < nminibar; i++) { + totaltodo += minibar[i].size; minilabels[i] = minibar[i].label; - minipercs[i] = 10; /*Pending*/ + minipercs[i] = minibar[i].status; } refresh = pvconf->refresh == 0 ? 0 : pvconf->refresh - 1; @@ -402,15 +384,15 @@ bsddialog_progressview (struct bsddialog_conf *conf, char * text, int rows, time(&tnew); if (update || tnew > told + refresh) { - output = mixedgauge(conf, text, rows, cols, mainperc, + output = do_mixedgauge(conf, text, rows, cols, mainperc, nminibar, minilabels, minipercs, true); if (output == BSDDIALOG_ERROR) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - move(LINES-1, 2); + move(SCREENLINES - 1, 2); clrtoeol(); - readforsec = ((tnew - tstart) == 0) ? - 0 : bsddialog_total_progview / (float)(tnew - tstart); + readforsec = ((tnew - tstart) == 0) ? 0 : + bsddialog_total_progview / (float)(tnew - tstart); printw(pvconf->fmtbottomstr, bsddialog_total_progview, readforsec); refresh(); @@ -421,22 +403,20 @@ bsddialog_progressview (struct bsddialog_conf *conf, char * text, int rows, if (i >= nminibar) break; - if (minibar[i].status == 1) /* Failed*/ + if (minibar[i].status == BSDDIALOG_MG_FAILED) break; perc = pvconf->callback(&minibar[i]); - if (minibar[i].status == 5) {/* ||prec >= 100) Done */ - minipercs[i] = 5; + if (minibar[i].status == BSDDIALOG_MG_DONE) { /*||perc >= 100)*/ + minipercs[i] = BSDDIALOG_MG_DONE; update = true; i++; - } else if (minibar[i].status == 1 || perc < 0) { /* Failed */ - minipercs[i] = 1; + } else if (minibar[i].status == BSDDIALOG_MG_FAILED || perc < 0) { + minipercs[i] = BSDDIALOG_MG_FAILED; update = true; - } else if (perc == 0) - minipercs[i] = 7; /* In progress */ - else /* perc > 0 */ - minipercs[i] = -(perc); + } else /* perc >= 0 */ + minipercs[i] = perc; } free(minilabels); @@ -445,14 +425,14 @@ bsddialog_progressview (struct bsddialog_conf *conf, char * text, int rows, } int -bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols, - int min, int max, int *value) +bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows, + int cols, int min, int max, int *value) { - WINDOW *widget, *textpad, *bar, *shadow; - int i, y, x, h, w, htextpad; bool loop, buttupdate, barupdate; + int y, x, h, w; int input, currvalue, output, sizebar, bigchange, positions; float perc; + WINDOW *widget, *textpad, *bar, *shadow; struct buttons bs; if (value == NULL) @@ -464,41 +444,41 @@ bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols, currvalue = *value; positions = max - min + 1; - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0) - return BSDDIALOG_ERROR; - if (bar_checksize(text, h, w, &bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (bar_checksize(h, w, &bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); - prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7, - x+w-1-t.text.hmargin); + doupdate(); - sizebar = w - HBORDERS - 2 - BARMARGIN * 2; + prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7, x+w-1-TEXTHMARGIN); + + sizebar = w - HBORDERS - 2 - BARPADDING * 2; bigchange = MAX(1, sizebar/10); - bar = new_boxed_window(conf, y + h - 6, x + 1 + BARMARGIN, 3, + bar = new_boxed_window(conf, y + h - 6, x + 1 + BARPADDING, 3, sizebar + 2, RAISED); loop = buttupdate = barupdate = true; - while(loop) { + while (loop) { if (buttupdate) { - draw_buttons(widget, h-2, w, bs, true); + draw_buttons(widget, bs, true); wrefresh(widget); buttupdate = false; } if (barupdate) { perc = ((float)(currvalue - min)*100) / (positions-1); - draw_perc_bar(bar, 1, 1, sizebar, perc, true, currvalue); + draw_bar(bar, 1, 1, sizebar, perc, true, currvalue); barupdate = false; wrefresh(bar); } @@ -512,8 +492,10 @@ bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols, loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case '\t': /* TAB */ bs.curr = (bs.curr + 1) % bs.nbuttons; @@ -567,125 +549,108 @@ bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols, if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; - /* No break! the terminal size can change */ + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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 (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0) - return BSDDIALOG_ERROR; - if (bar_checksize(text, h, w, &bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (bar_autosize(conf, rows, cols, &h, &w, text, + &bs) != 0) + return (BSDDIALOG_ERROR); + if (bar_checksize(h, w, &bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); + return (BSDDIALOG_ERROR); - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); + if (update_dialog(conf, shadow, widget,y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); + doupdate(); - sizebar = w - HBORDERS - 2 - BARMARGIN * 2; + sizebar = w - HBORDERS - 2 - BARPADDING * 2; bigchange = MAX(1, sizebar/10); wclear(bar); - mvwin(bar, y + h - 6, x + 1 + BARMARGIN); + mvwin(bar, y + h - 6, x + 1 + BARPADDING); wresize(bar, 3, sizebar + 2); + draw_borders(conf, bar, 3, sizebar+2, RAISED); - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7, - x+w-1-t.text.hmargin); - - draw_borders(conf, bar, 3, sizebar + 2, RAISED); + prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7, + x+w-1-TEXTHMARGIN); barupdate = true; - buttupdate = true; break; default: - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower((bs.label[i])[0])) { - output = bs.value[i]; - loop = false; + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; } } } delwin(bar); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; + return (output); } int -bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int sec) +bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int sec) { - WINDOW *widget, *textpad, *bar, *shadow; - int i, output, y, x, h, w, htextpad; bool loop, buttupdate, barupdate; - int input, tout, sizebar; + int output, y, x, h, w, input, tout, sizebar; float perc; + WINDOW *widget, *textpad, *bar, *shadow; struct buttons bs; - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0) - return BSDDIALOG_ERROR; - if (bar_checksize(text, h, w, &bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (bar_checksize(h, w, &bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7, - x+w-1-t.text.hmargin); + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); + + doupdate(); - sizebar = w - HBORDERS - 2 - BARMARGIN * 2; - bar = new_boxed_window(conf, y + h - 6, x + 1 + BARMARGIN, 3, + prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7, x+w-1-TEXTHMARGIN); + + sizebar = w - HBORDERS - 2 - BARPADDING * 2; + bar = new_boxed_window(conf, y + h - 6, x + 1 + BARPADDING, 3, sizebar + 2, RAISED); tout = sec; nodelay(stdscr, TRUE); timeout(1000); loop = buttupdate = barupdate = true; - while(loop) { + while (loop) { if (barupdate) { perc = (float)tout * 100 / sec; - draw_perc_bar(bar, 1, 1, sizebar, perc, true, tout); + draw_bar(bar, 1, 1, sizebar, perc, true, tout); barupdate = false; wrefresh(bar); } if (buttupdate) { - draw_buttons(widget, h-2, w, bs, true); + draw_buttons(widget, bs, true); wrefresh(widget); buttupdate = false; } input = getch(); - if(input < 0) { /* timeout */ + if (input < 0) { /* timeout */ tout--; if (tout < 0) { output = BSDDIALOG_TIMEOUT; @@ -703,8 +668,10 @@ bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols, loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case '\t': /* TAB */ bs.curr = (bs.curr + 1) % bs.nbuttons; @@ -726,60 +693,44 @@ bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols, if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; - /* No break! the terminal size can change */ + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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 (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0) - return BSDDIALOG_ERROR; - if (bar_checksize(text, h, w, &bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (bar_autosize(conf, rows, cols, &h, &w, text, + &bs) != 0) + return (BSDDIALOG_ERROR); + if (bar_checksize(h, w, &bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); + return (BSDDIALOG_ERROR); - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); + if (update_dialog(conf, shadow, widget,y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); + doupdate(); - sizebar = w - HBORDERS - 2 - BARMARGIN * 2; + sizebar = w - HBORDERS - 2 - BARPADDING * 2; wclear(bar); - mvwin(bar, y + h - 6, x + 1 + BARMARGIN); + mvwin(bar, y + h - 6, x + 1 + BARPADDING); wresize(bar, 3, sizebar + 2); + draw_borders(conf, bar, 3, sizebar+2, LOWERED); - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7, - x+w-1-t.text.hmargin); - - draw_borders(conf, bar, 3, sizebar + 2, RAISED); + prefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-7, + x+w-1-TEXTHMARGIN); barupdate = true; - buttupdate = true; break; default: - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower((bs.label[i])[0])) { - output = bs.value[i]; - loop = false; + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; } } } @@ -787,7 +738,7 @@ bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols, nodelay(stdscr, FALSE); delwin(bar); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; -} + return (output); +}
\ No newline at end of file diff --git a/lib/bsddialog.3 b/lib/bsddialog.3 index 0264c29e4470..4139970626b5 100644 --- a/lib/bsddialog.3 +++ b/lib/bsddialog.3 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2021 Alfonso Sabato Siciliano +.\" Copyright (c) 2021-2022 Alfonso Sabato Siciliano .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -22,21 +22,20 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 16, 2021 +.Dd January 23, 2022 .Dt BSDDIALOG 3 .Os .Sh NAME .Nm bsddialog_backtitle , .Nm bsddialog_clearterminal , .Nm bsddialog_color , -.Nm bsddialog_buildlist , .Nm bsddialog_checklist , .Nm bsddialog_datebox , .Nm bsddialog_end , .Nm bsddialog_form , .Nm bsddialog_gauge , .Nm bsddialog_geterror , -.Nm bsddialog_get_theme +.Nm bsddialog_get_theme , .Nm bsddialog_infobox , .Nm bsddialog_init , .Nm bsddialog_initconf , @@ -52,58 +51,21 @@ .Nm bsddialog_textbox , .Nm bsddialog_timebox , .Nm bsddialog_yesno -.Nd terminal dialogs and widgets +.Nd TUI dialogs .Sh LIBRARY .Lb libbsddialog .Sh SYNOPSIS .In bsddialog.h - -.Fd #define LIBBSDDIALOG_VERSION - -.Fd #define BSDDIALOG_ERROR -.Fd #define BSDDIALOG_OK -.Fd #define BSDDIALOG_YES -.Fd #define BSDDIALOG_CANCEL -.Fd #define BSDDIALOG_NO -.Fd #define BSDDIALOG_HELP -.Fd #define BSDDIALOG_EXTRA -.Fd #define BSDDIALOG_ITEM_HELP -.Fd #define BSDDIALOG_TIMEOUT -.Fd #define BSDDIALOG_ESC -.Fd #define BSDDIALOG_GENERIC1 -.Fd #define BSDDIALOG_GENERIC2 - -.Fd #define BSDDIALOG_FULLSCREEN -.Fd #define BSDDIALOG_AUTOSIZE -.Fd #define BSDDIALOG_CENTER - -.Fd struct bsddialog_conf -.Fd struct bsddialog_menuitem -.Fd enum bsddialog_grouptype -.Fd struct bsddialog_menugroup -.Fd struct bsddialog_formitem - -.Ft int -.Fn bsddialog_backtitle "struct bsddialog_conf *conf" "char *backtitle" .Ft int -.Fo bsddialog_buildlist -.Fa "struct bsddialog_conf *conf" -.Fa "char* text" -.Fa "int rows" -.Fa "int cols" -.Fa "unsigned int menurows" -.Fa "int nitems" -.Fa "struct bsddialog_menuitem *items" -.Fa "int *focusitem" -.Fc +.Fn bsddialog_backtitle "struct bsddialog_conf *conf" "const char *backtitle" .Ft int .Fo bsddialog_checklist .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int menurows" -.Fa "int nitems" +.Fa "unsigned int nitems" .Fa "struct bsddialog_menuitem *items" .Fa "int *focusitem" .Fc @@ -112,7 +74,7 @@ .Ft int .Fo bsddialog_datebox" .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int *yy" @@ -124,27 +86,29 @@ .Ft int .Fo bsddialog_form .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" -.Fa "unsigned int formheight" +.Fa "unsigned int formrows" .Fa "unsigned int nitems" .Fa "struct bsddialog_formitem *items" .Fc .Ft int .Fo bsddialog_gauge .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int perc" +.Fa "int fd" +.Fa "const char *sep" .Fc .Ft const char * .Fn bsddialog_geterror "void" .Ft int .Fo bsddialog_infobox .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fc @@ -155,18 +119,18 @@ .Ft int .Fo bsddialog_menu .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int menurows" -.Fa "int nitems" +.Fa "unsigned int nitems" .Fa "struct bsddialog_menuitem *items" .Fa "int *focusitem" .Fc .Ft int .Fo bsddialog_mixedgauge .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int mainperc" @@ -177,11 +141,11 @@ .Ft int .Fo bsddialog_mixedlist .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int menurows" -.Fa "int ngroups" +.Fa "unsigned int ngroups" .Fa "struct bsddialog_menugroup *groups" .Fa "int *focuslist" .Fa "int *focusitem" @@ -189,33 +153,33 @@ .Ft int .Fo bsddialog_msgbox .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fc .Ft int .Fo bsddialog_pause .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" -.Fa "unsigned int sec" +.Fa "unsigned int seconds" .Fc .Ft int .Fo bsddialog_radiolist .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int menurows" -.Fa "int nitems" +.Fa "unsigned int nitems" .Fa "struct bsddialog_menuitem *items" .Fa "int *focusitem" .Fc .Ft int .Fo bsddialog_rangebox .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "int min" @@ -225,14 +189,14 @@ .Ft int .Fo bsddialog_textbox .Fa "struct bsddialog_conf *conf" -.Fa "char* file" +.Fa "const char *file" .Fa "int rows" .Fa "int cols" .Fc .Ft int .Fo bsddialog_timebox .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fa "unsigned int *hh" @@ -242,25 +206,15 @@ .Ft int .Fo bsddialog_yesno .Fa "struct bsddialog_conf *conf" -.Fa "char* text" +.Fa "const char *text" .Fa "int rows" .Fa "int cols" .Fc - .In bsddialog_theme.h - -.Fd #define BSDDIALOG_BOLD -.Fd #define BSDDIALOG_REVERSE -.Fd #define BSDDIALOG_UNDERLINE - -.Fd enum bsddialog_color -.Fd enum bsddialog_default_theme -.Fd struct bsddialog_theme - .Ft int .Fo bsddialog_color -.Fa "enum bsddialog_color background" .Fa "enum bsddialog_color foreground" +.Fa "enum bsddialog_color background" .Fa "unsigned int flags" .Fc .Ft int @@ -271,40 +225,84 @@ .Fn bsddialog_set_theme "struct bsddialog_theme *theme" .Sh DESCRIPTION The -.Nm BSDDialog -library is an API to write a tools with a Text User Interface. It can build -dialogs and widgets: to show messages, to get input and to inform about a -computation status. +.Nm bsddialog +library provides an API to build Text User Interface dialogs and widgets: to +display messages, to get input and to inform about a computation status. +.Pp +.Fn bsddialog_init +initializes the library, the only functions that can be called before is +.Fn bsddialog_initconf +described later. +After the initialization the input and output should be handled via the library +API. +.Fn bsddialog_end +restores the screen like before +.Fn bsddialog_init , +then it is not possible to use the library functions. +.Pp +.Fn bsddialog_error +returns a string to describe the last error, it should be called after a +.Dv BSDDIALOG_ERROR +returned value. +.Fn bsddialog_clearterminal +clears the screen. +.Fn bsddialog_backtitle +prints +.Fa backtitle +on the top of the screen, it is possible to set +.Fa conf.ascii_lines +and +.Fa conf.no_lines ; +.Fa conf +is described later. +.Pp +Each +.Fa char* +argument has to be a well terminated string, can be empty +.Pq Dq +but not +.Dv NULL . +.Ss Dialogs +The dialogs have common arguments. +.Fa text +is a string printed inside the dialog. +.Fa rows +and +.Fa cols +are height and width, their value can be between 2 and the screen size, +.Dv BSDDIALOG_AUTOSIZE +or +.Dv BSDDIALOG_FULLSCREEN . +.Fa conf +is a struct to customize the dialog, it does not set global properties to the +library. .Pp .Bd -literal -offset indent -compact -/* size and position */ -#define BSDDIALOG_FULLSCREEN -1 -#define BSDDIALOG_AUTOSIZE 0 -#define BSDDIALOG_CENTER -1 - struct bsddialog_conf { bool ascii_lines; - unsigned int aspect_ratio; unsigned int auto_minheight; unsigned int auto_minwidth; - char *bottomtitle; + const char *bottomtitle; bool clear; - char *f1_file; - char *f1_message; - int *get_height; - int *get_width; + const char *f1_file; + const char *f1_message; + int *get_height; + int *get_width; bool no_lines; bool shadow; unsigned int sleep; - char *title; - int y; - int x; + const char *title; + int y; + int x; + struct { + bool enable_esc; + } key; struct { - bool colors; + bool highlight; + unsigned int tablen; } text; struct { bool align_left; - char *default_item; bool no_desc; bool no_name; bool shortcut_buttons; @@ -317,35 +315,238 @@ struct bsddialog_conf { } form; struct { bool without_ok; - char *ok_label; + const char *ok_label; bool with_extra; - char *extra_label; + const char *extra_label; bool without_cancel; - char *cancel_label; + const char *cancel_label; bool default_cancel; bool with_help; - char *help_label; - char *exit_label; - char *generic1_label; - char *generic2_label; - char *default_label; + const char *help_label; + const char *generic1_label; + const char *generic2_label; + const char *default_label; } button; }; .Ed .Pp - -.Ss Dialogs +.Bl -column -compact +.It Fa conf.ascii_lines +ascii characters to draw lines, default wide characters. +.It Fa conf.auto_minheight +minimum height if +.Fa rows +is +.Dv BSDDIALOG_AUTOSIZE . +.It Fa conf.auto_minwidth +minimum width if +.Fa cols +is +.Dv BSDDIALOG_AUTOSIZE . +.It Fa conf.bottomtitle +subtitle at the dialog bottom side. +.It Fa conf.clear +hide the dialog at exit. +.It Fa conf.f1_file +file to open if F1 is pressed. +.It Fa conf.f1_message +message to display if F1 is pressed. +.It Fa conf.get_height +if not +.Dv NULL +is set like the dialog height. +.It Fa conf.get_width +if not +.Dv NULL +is set like the dialog width. +.It Fa conf.no_lines +not draw lines. +.It Fa conf.shadow +draw shadow. +.It Fa conf.sleep +wait before to return, the value is in seconds. +.It Fa conf.title +title at the top dialog side. +.It Fa conf.y +vertical position, 0 is top screen size, can be +.Dv BSDDIALOG_CENTER . +.It Fa conf.x +horizontal position, 0 is left screen side, can be +.Dv BSDDIALOG_CENTER . +.El +.Pp +.Fa conf.key.enable_esc +enables +.Dv ESC +key to close the dialog. +.Pp +.Fa conf.text.highlight +enables highlights for +.Fa text , +properly the following sequences are considered escapes: +.Bl -column -compact +.It Dq \eZ0 +black. +.It Dq \eZ1 +red. +.It Dq \eZ2 +green. +.It Dq \eZ3 +yellow. +.It Dq \eZ4 +blue. +.It Dq \eZ5 +magenta. +.It Dq \eZ6 +cyan. +.It Dq \eZ7 +white. +.It Dq \eZr +reverse colors between foreground and background. +.It Dq \eZR +disable reverse. +.It Dq \eZb +bold. +.It Dq \eZB +disable bold. +.It Dq \eZu +underline. +.It Dq \eZU +disable underline. +.It Dq \eZn +disable each customization. +.El +.Fa conf.text.tablen +tab length. +.Pp +.Bl -column -compact +.It Fa conf.button.without_ok +disable OK button. +.It Fa conf.button.ok_label +set label for OK button. +.It Fa conf.button.with_extra +add Extra button. +.It Fa conf.button.extra_label +set a label for Extra button. +.It Fa conf.button.without_cancel +disable Cancel button. +.It Fa conf.button.cancel_label +sets a label for Cancel button. +.It Fa conf.button.default_cancel +on startup focus on the Cancel button. +.It Fa conf.button.with_help +add Help button. +.It Fa conf.button.help_label +set a label for Help button. +.It Fa conf.button.generic1_label +add a button with the specified label. +.It Fa conf.button.generic2_label +add a button with the specified label. +.It Fa conf.button.default_label +focus on the button with the specified label. +.El +.Pp +.Fn bsddialog_initconf +initializes +.Fa conf +disabling each property, except +.Fa conf.shadow +to true, +.Fa conf.y +and +.Fa conf.x +to +.Dv BSDDIALOG_CENTER . +.Pp +.Fn bsddialog_infobox +builds a dialog without buttons and returns instantly. +.Fn bsddialog_msgbox +builds a dialog with OK button. +.Fn bsddialog_yesno +provides a dialog for a +.Dq Yes-No Question , +the labels on buttons are Yes and No. +.Pp +.Fn bsddialog_pause +builds a dialog waiting until the timeout in +.Fa seconds +expires or a button is pressed. +.Pp +.Fn bsddialog_datebox +builds a dialog to select a date, +.Fa yy , +.Fa mm , +and +.Fa dd +are default values on startup, selected date at exit. +.Fn bsddialog_timebox +builds a dialog to choose a time, +.Fa hh , +.Fa mm , +and +.Fa ss +are default values on startup, selected time at exit. +.Pp +.Fn bsddialog_checklist , +.Fn bsddialog_menu +and +.Fn bsddialog_radiolist +build dialogs to select some item from a list via the SPACE key, an item is +defined like: .Pp .Bd -literal -offset indent -compact struct bsddialog_menuitem { - char *prefix; + const char *prefix; bool on; unsigned int depth; - char *name; - char *desc; - char *bottomdesc; + const char *name; + const char *desc; + const char *bottomdesc; }; - +.Ed +.Pp +.Fa prefix , +.Fa name +and +.Fa desc +are strings to describe the item and are printed on its row, +.Fa bottomdesc +is printed on the bottom side of the screen, +.Fa depth +is a margin between the +.Fa prefix +and +.Fa name +useful to implement a +.Dq treeview, +.Fa on +is set to +.Dv true +if the item is selected, +.Dv false +otherwise. +.Fa items +is an array of items of +.Fa nitem +elements, +.Fa menurows +specifies the graphical fixed height of the list, if +.Fa cols +is set to +.Dv BSDDIALOG_AUTOSIZE +.Fa menurows +specifies a maximum value. +Finally, if not +.Dv NULL , +.Fa focusitem +specifies the default item on startup and the last focused item at exit, could +be a negative value if no item is focused. +.Pp +.Fn bsddialog_mixedlist +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 { BSDDIALOG_CHECKLIST, BSDDIALOG_RADIOLIST, @@ -357,35 +558,185 @@ struct bsddialog_menugroup { unsigned int nitems; struct bsddialog_menuitem *items; }; - +.Ed +.Pp +.Fa groups +is an array of sets of +.Fa ngroups +elements. +.Fa menurows +is the graphical height size for the list. +If not +.Dv NULL , +.Fa focuslist +and +.Fa focusitem +specify the default item on startup and the last focused item at exit, could be +a negative value if no item is focused. +.Pp +.Fn bsddialog_checklist , +.Fn bsddialog_menu , +.Fn bsddialog_mixedlist +and +.Fn bsddialog_radiolist +can be costomizated by: +.Bl -column -compact +.It Fa conf.menu.align_left +aligns items to left, default center. +.It Fa conf.menu.no_desc +hide description. +.It Fa conf.menu.no_name +hide names. +.It Fa conf.menu.on_without_ok +set items +.Fa on +also if the OK button is not pressed. +.It Fa conf.menu.shortcut_buttons +enable shortcut keys on buttons, default on items. +.El +.Pp +.Fn bsddialog_form +builds a dialog to display a list of items to get strings in input, an item is +defined like: +.Pp +.Bd -literal -offset indent -compact struct bsddialog_formitem { - char *label; + const char *label; unsigned int ylabel; unsigned int xlabel; - char *init; + const char *init; unsigned int yfield; unsigned int xfield; unsigned int fieldlen; unsigned int maxvaluelen; - char *value; /* allocated memory */ -#define BSDDIALOG_FIELDHIDDEN 1U -#define BSDDIALOG_FIELDREADONLY 2U + char *value; + unsigned int flags; - char *bottomdesc; + const char *bottomdesc; }; .Ed .Pp - +.Fa label +describes the request, it is printed at the position +.Fa ylabel +and +.Fa xlabel . +The field for the input is at the position +.Fa yfield +and +.Fa xfield , +.Fa fieldlen +is its graphical width, while +.Fa maxvalelen +is the maximum length of the input string, +.Fa init +is the default value. +If the OK button is pressed +.Fa value +is the allocated memory with the current field string. +.Fa flags +is an OR value to set the +.Dv BSDDIALOG_FIELDHIDDEN +and +.Dv BSDDIALOG_FIELDREADONLY +flags for the field. +.Fa bottomdesc +is printed on the bottom side of the screen if the item is focused. +.Fa items +is an array of items of +.Fa nitems +elements, +.Fa formrows +specifies the graphical fixed height for the items list; +.Fa ylabel +and +.Fa yfield +have to be between 1 and +.Fa formrows . +.Pp +.Fn bsddialog_form +can be customized by: +.Bl -column -compact +.It Fa conf.form.securech +charachter to hide the input +with +.Dv BSDDIALOG_FIELDHIDDEN . +.It Fa conf.form.value_without_ok +allocate memory and set +.Fa value +also if the OK button is not pressed. +.El +.Pp +.Fn bsddialog_gauge +builds a dialog with a bar to shows +.Fa perc , +if the file descriptor +.Fa fd +is greater or equal to 0 the dialog waits to read +.Fa separator +from it, then the first string replaces +.Fa perc +and the following strings replace +.Fa text +until the next +.Fa separator , +the loop ends reading +.Dv EOF . +.Pp +.Fn bsddialog_mixedgauge +draws a main bar with the +.Fa mainperc +percentage and +.Fa nminibars +each one with a +.Fa minilabel +and a +.Fa miniperc +with a value between 0 and 100 or +.Dv BSDDIALOG_MG_SUCCEEDED , +.Dv BSDDIALOG_MG_FAILED , +.Dv BSDDIALOG_MG_PASSED , +.Dv BSDDIALOG_MG_COMPLETED , +.Dv BSDDIALOG_MG_CHECKED , +.Dv BSDDIALOG_MG_DONE , +.Dv BSDDIALOG_MG_SKIPPED , +.Dv BSDDIALOG_MG_INPROGRESS , +.Dv BSDDIALOG_MG_BLANK , +.Dv BSDDIALOG_MG_NA +or +.Dv BSDDIALOG_MG_PENDING +to print a descriptive string. +.Pp +.Fn bsddialog_rangebox +to select a value between +.Fa min +and +.Fa max . +.Fa value +is the default value on startup and the selected value at exit. +The current value is printed inside a bar, the keys UP, DOWN, HOME, END, PAGEUP +and PAGEDOWN can change it. +.Pp +.Fn bsddialog_textbox +opens and prints +.Fa file +in a dialog, the UP, DOWN, HOME, END, PAGEUP and PAGEDOWN keys are availble to +navigate the file. +OK button is renamed EXIT. .Ss Theme +The graphical properties are global to the library, they are represented by +.Fa struct bsddialog_theme +and can be customized at runtime via the +.In bsddialog_theme.h +API. .Pp .Bd -literal -offset indent -compact -/* f_ focus/active element */ struct bsddialog_theme { struct { int color; - } terminal; + } screen; struct { int color; unsigned int h; @@ -400,9 +751,6 @@ struct bsddialog_theme { int bottomtitlecolor; } dialog; struct { - unsigned int hmargin; - } text; - struct { int arrowcolor; int selectorcolor; int f_namecolor; @@ -435,84 +783,191 @@ struct bsddialog_theme { int f_shortcutcolor; } button; }; - -enum bsddialog_default_theme { - BSDDIALOG_THEME_BLACKWHITE, - BSDDIALOG_THEME_BSDDIALOG, - BSDDIALOG_THEME_DEFAULT, - BSDDIALOG_THEME_DIALOG, -}; - -enum bsddialog_color { - BSDDIALOG_BLACK = 0, - BSDDIALOG_RED, - BSDDIALOG_GREEN, - BSDDIALOG_YELLOW, - BSDDIALOG_BLUE, - BSDDIALOG_MAGENTA, - BSDDIALOG_CYAN, - BSDDIALOG_WHITE, -}; - -#define BSDDIALOG_BOLD 1U -#define BSDDIALOG_REVERSE 2U -#define BSDDIALOG_UNDERLINE 4U .Ed .Pp - +A member with the +.Dq f_ +prefix refers to an element with focus. +.Pp +.Fn bsddialog_get_theme +sets +.Fa theme +like the current theme. +.Pp +A color can be set by the value returned by +.Fn bsddialog_color , +Possible values for +.Fa background +and +.Fa foreground +are: +.Dv BSDDIALOG_BLACK , +.Dv BSDDIALOG_RED , +.Dv BSDDIALOG_GREEN , +.Dv BSDDIALOG_YELLOW , +.Dv BSDDIALOG_BLUE , +.Dv BSDDIALOG_MAGENTA , +.Dv BSDDIALOG_CYAN , +and +.Dv BSDDIALOG_WHITE , +.Fa flags +specifies OR-flags, possible values: +.Dv BSDDIALOG_BOLD , +.Dv BSDDIALOG_REVERSE +and +.Dv BSDDIALOG_UNDERLINE . +.Pp +.Fn bsddialog_set_theme +sets +.Fa theme +like current theme, the changes takes effect only for dialogs built after the +call. +.Pp +The library provides predefined themes: +.Dv BSDDIALOG_THEME_BLACKWHITE , +.Dv BSDDIALOG_THEME_BSDDIALOG , +.Dv BSDDIALOG_THEME_DEFAULT +and +.Dv BSDDIALOG_THEME_DIALOG , +they can be set via +.Fn bsddialog_set_default_theme . .Sh RETURN VALUES -The sysctlmif_oidbyname(), sysctlmif_oidextendedbyname(), - sysctlmif_name(), sysctlmif_desc(), sysctlmif_descbyname(), - sysctlmif_label(), sysctlmif_labelbyname(), sysctlmif_fmt(), - sysctlmif_fmtbyname(), sysctlmif_oidbyname0(), sysctlmif_oidbyname1(), - sysctlmif_oidbyname2(), sysctlmif_oidbyname3(), sysctlmif_oidbyname4(), - sysctlmif_oidbyname5(), sysctlmif_oidbyname6(), and - sysctlmif_oidbyname7() functions return the value 0 if successful; other- - wise the value -1 is returned and the global variable errno is set to in- - dicate the error. - - -functions return NULL upon error or a pointer to allo- - cated memory for success. - -.Sh EXAMPLES -Complete set of examples: -.Lk https://gitlab.com/alfix/bsddialog/-/blob/main/examples_library/ +The functions return the value +.Dv BSDDIALOG_ERROR +if unsuccessful; +otherwise, depending on the pressed button, the following values can be +returned: +.Dv BSDDIALOG_OK , +.Dv BSDDIALOG_CANCEL , +.Dv BSDDIALOG_HELP , +.Dv BSDDIALOG_EXTRA , +.Dv BSDDIALOG_GENERIC1 +or +.Dv BSDDIALOG_GENERIC2 . +.Dv BSDDIALOG_YES +and +.Dv BSDDIALOG_NO +are aliases for +.Dv BSDDIALOG_OK +and +.Dv BSDDIALOG_CANCEL , +respectively. .Pp -If installed: -.Dl /usr/local/share/examples/libbsddialog +The functions return +.Dv BSDDIALOG_ESC +if +.Fa conf.key.enable_esc +is enabled and the ESC key is pressed. .Pp -"Yes-No Question" Example: +.Fn bsddialog_pause +returns +.Dv BSDDIALOG_TIMEOUT +if the timeout expires. +.Sh EXAMPLES +.Dq Yes-No Question +Example: .Pp .Bd -literal -offset indent -compact int output; struct bsddialog_conf conf; -bsddialog_initconf(&conf); -conf.title = "yesno"; if (bsddialog_init() == BSDDIALOG_ERROR) return (1); +bsddialog_initconf(&conf); +conf.title = "yesno"; output = bsddialog_yesno(&conf, "Example", 7, 25); bsddialog_end(); switch (output) { case BSDDIALOG_YES: - printf("OK\\n"); + printf("Yes\\n"); break; case BSDDIALOG_NO printf("NO\\n"); break; -case BSDDIALOG_ESC; - printf("ESC\\n"); - break; case BSDDIALOG_ERROR: printf("Error: %s\\n", bsddialog_geterror()); } .Ed +.Pp +Theme Example: +.Pp +.Bd -literal -offset indent -compact +struct bsddialog_conf conf; +struct bsddialog_theme theme; + +if (bsddialog_init() == BSDDIALOG_ERROR) + +bsddialog_initconf(&conf); +bsddialog_msgbox(&conf, "Default theme", 7, 25); + +bsddialog_get_theme(&theme); +theme.screen.color = bsddialog_color(BSDDIALOG_RED, BSDDIALOG_GREEN, + BSDDIALOG_BOLD); +bsddialog_set_theme(&theme); +bsddialog_backtitle(&conf, "Red foreground and Green background"); +bsddialog_msgbox(&conf, "Change screen color", 7, 25); + +bsddialog_set_default_theme(BSDDIALOG_THEME_BLACKWHITE); +bsddialog_msgbox(&conf, "Black and White theme", 7, 25); + +bsddialog_end(); +.Ed +.Pp +Mixedlist Example: +.Pp +.Bd -literal -offset indent -compact +unsigned int i, j; +struct bsddialog_conf conf; +struct bsddialog_menuitem item; +struct bsddialog_menuitem check[2] = { + { "1", true, 0, "Name 1", "Desc 1", "Check Bottom Desc 1" }, + { "2", false, 0, "Name 2", "Desc 2", "Check Bottom Desc 2" } +}; +struct bsddialog_menuitem sep[1] = { + { "3", true, 0, "Radiolist", "(desc)", "" } +}; +struct bsddialog_menuitem radio[5] = { + { "4", true, 0, "Name 1", "Desc 1", "Radio Bottom Desc 1" }, + { "5", false, 0, "Name 2", "Desc 2", "Radio Bottom Desc 2" } +}; +struct bsddialog_menugroup group[3] = { + { BSDDIALOG_CHECKLIST, 2, check }, + { BSDDIALOG_SEPARATOR, 1, sep }, + { BSDDIALOG_RADIOLIST, 2, radio } +}; + +bsddialog_init(); +bsddialog_initconf(&conf); +bsddialog_mixedlist(&conf, "Example", 20, 30, 11, 3, group, NULL, + NULL); +bsddialog_end(); + +for (i = 0; i < 3; i++) { + for (j = 0; j < group[i].nitems; j++) { + item = group[i].items[j]; + switch (item.type) { + case BSDDIALOG_SEPARATOR: + printf("---- %s ----\\n", item.name); + break; + case BSDDIALOG_RADIOLIST: + printf(" (%c) %s\\n", + item.on ? '*' : ' ', item.name); + break; + case BSDDIALOG_CHECKLIST: + printf(" [%c] %s\\n", + item.on ? 'X' : ' ', item.name); + break; + } + } +} +.Ed .Sh SEE ALSO -.Xr bsddialog 1 +.Xr bsddialog 1 , +.Xr curses 3 , +.Xr ncurses 3 .Sh HISTORY The .Nm bsddialog @@ -522,9 +977,7 @@ library first appeared in .Nm bsddialog was written by .An Alfonso Sabato Siciliano Aq Mt alf.siciliano@gmail.com . -.Sh CAVEATS -See -.Xr bsddialog .Sh BUGS -See -.Xr bsddialog 1 +.Fn bsddialog_form +does not resize the dialog after a terminal resize and does not provide +scrolling for items.
\ No newline at end of file diff --git a/lib/bsddialog.h b/lib/bsddialog.h index 94342199439e..142713cc1ecf 100644 --- a/lib/bsddialog.h +++ b/lib/bsddialog.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,83 +30,100 @@ #include <stdbool.h> -#define LIBBSDDIALOG_VERSION "0.0.2" +#define LIBBSDDIALOG_VERSION "0.1" /* Exit status */ -#define BSDDIALOG_ERROR -1 -#define BSDDIALOG_OK 0 -#define BSDDIALOG_YES BSDDIALOG_OK -#define BSDDIALOG_CANCEL 1 -#define BSDDIALOG_NO BSDDIALOG_CANCEL -#define BSDDIALOG_HELP 2 -#define BSDDIALOG_EXTRA 3 -#define BSDDIALOG_TIMEOUT 4 -#define BSDDIALOG_ESC 5 -#define BSDDIALOG_GENERIC1 6 -#define BSDDIALOG_GENERIC2 7 +#define BSDDIALOG_ERROR -1 +#define BSDDIALOG_OK 0 +#define BSDDIALOG_YES BSDDIALOG_OK +#define BSDDIALOG_CANCEL 1 +#define BSDDIALOG_NO BSDDIALOG_CANCEL +#define BSDDIALOG_HELP 2 +#define BSDDIALOG_EXTRA 3 +#define BSDDIALOG_TIMEOUT 4 +#define BSDDIALOG_ESC 5 +#define BSDDIALOG_GENERIC1 6 +#define BSDDIALOG_GENERIC2 7 /* Size and position */ -#define BSDDIALOG_FULLSCREEN -1 -#define BSDDIALOG_AUTOSIZE 0 -#define BSDDIALOG_CENTER -1 +#define BSDDIALOG_FULLSCREEN -1 +#define BSDDIALOG_AUTOSIZE 0 +#define BSDDIALOG_CENTER -1 + +/* Mixedgauge */ +#define BSDDIALOG_MG_SUCCEEDED -1 +#define BSDDIALOG_MG_FAILED -2 +#define BSDDIALOG_MG_PASSED -3 +#define BSDDIALOG_MG_COMPLETED -4 +#define BSDDIALOG_MG_CHECKED -5 +#define BSDDIALOG_MG_DONE -6 +#define BSDDIALOG_MG_SKIPPED -7 +#define BSDDIALOG_MG_INPROGRESS -8 +#define BSDDIALOG_MG_BLANK -9 +#define BSDDIALOG_MG_NA -10 +#define BSDDIALOG_MG_PENDING -11 + +/* Form */ +#define BSDDIALOG_FIELDHIDDEN 1U +#define BSDDIALOG_FIELDREADONLY 2U struct bsddialog_conf { bool ascii_lines; - unsigned int aspect_ratio; unsigned int auto_minheight; unsigned int auto_minwidth; - char *bottomtitle; + const char *bottomtitle; bool clear; - char *f1_file; - char *f1_message; - int *get_height; - int *get_width; + const char *f1_file; + const char *f1_message; + int *get_height; + int *get_width; bool no_lines; bool shadow; unsigned int sleep; - char *title; - int y; - int x; + const char *title; + int y; + int x; struct { - bool colors; + bool enable_esc; + } key; + struct { + bool highlight; + unsigned int tablen; } text; struct { bool align_left; - char *default_item; bool no_desc; bool no_name; + bool on_without_ok; bool shortcut_buttons; } menu; struct { int securech; - bool value_withcancel; - bool value_withextra; - bool value_withhelp; + bool value_without_ok; } form; struct { bool without_ok; - char *ok_label; + const char *ok_label; bool with_extra; - char *extra_label; + const char *extra_label; bool without_cancel; - char *cancel_label; + const char *cancel_label; bool default_cancel; bool with_help; - char *help_label; - char *exit_label; - char *generic1_label; - char *generic2_label; - char *default_label; + const char *help_label; + const char *generic1_label; + const char *generic2_label; + const char *default_label; } button; }; struct bsddialog_menuitem { - char *prefix; + const char *prefix; bool on; unsigned int depth; - char *name; - char *desc; - char *bottomdesc; + const char *name; + const char *desc; + const char *bottomdesc; }; enum bsddialog_grouptype { @@ -122,96 +139,93 @@ struct bsddialog_menugroup { }; struct bsddialog_formitem { - char *label; + const char *label; unsigned int ylabel; unsigned int xlabel; - char *init; + const char *init; unsigned int yfield; unsigned int xfield; unsigned int fieldlen; unsigned int maxvaluelen; char *value; -#define BSDDIALOG_FIELDHIDDEN 1U -#define BSDDIALOG_FIELDREADONLY 2U unsigned int flags; - char *bottomdesc; + const char *bottomdesc; }; int bsddialog_init(void); int bsddialog_end(void); -int bsddialog_backtitle(struct bsddialog_conf *conf, char *backtitle); +int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle); int bsddialog_initconf(struct bsddialog_conf *conf); int bsddialog_clearterminal(void); const char *bsddialog_geterror(void); /* Dialogs */ int -bsddialog_buildlist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem); - -int -bsddialog_checklist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem); +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); int -bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int *yy, unsigned int *mm, unsigned int *dd); +bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd); int -bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int formheight, unsigned int nitems, +bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int formheight, unsigned int nitems, struct bsddialog_formitem *items); int -bsddialog_gauge(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int perc); +bsddialog_gauge(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int perc, int fd, const char *sep); int -bsddialog_infobox(struct bsddialog_conf *conf, char* text, int rows, int cols); +bsddialog_infobox(struct bsddialog_conf *conf, const char *text, int rows, + int cols); int -bsddialog_menu(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem); +bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int menurows, unsigned int nitems, + struct bsddialog_menuitem *items, int *focusitem); int -bsddialog_mixedgauge(struct bsddialog_conf *conf, char* text, int rows, - int cols, unsigned int mainperc, unsigned int nminibars, char **minilabels, - int *minipercs); +bsddialog_mixedgauge(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int mainperc, unsigned int nminibars, + const char **minilabels, int *minipercs); int -bsddialog_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int ngroups, struct bsddialog_menugroup *groups, - int *focuslist, int *focusitem); +bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int menurows, unsigned int ngroups, + struct bsddialog_menugroup *groups, int *focuslist, int *focusitem); int -bsddialog_msgbox(struct bsddialog_conf *conf, char* text, int rows, int cols); +bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows, + int cols); int -bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int sec); +bsddialog_pause(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int seconds); int -bsddialog_radiolist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem); +bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int menurows, unsigned int nitems, + struct bsddialog_menuitem *items, int *focusitem); int -bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols, - int min, int max, int *value); +bsddialog_rangebox(struct bsddialog_conf *conf, const char *text, int rows, + int cols, int min, int max, int *value); int -bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols); +bsddialog_textbox(struct bsddialog_conf *conf, const char *file, int rows, + int cols); int -bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int *hh, unsigned int *mm, unsigned int *ss); +bsddialog_timebox(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss); int -bsddialog_yesno(struct bsddialog_conf *conf, char* text, int rows, int cols); +bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows, + int cols); #endif diff --git a/lib/bsddialog_progressview.h b/lib/bsddialog_progressview.h index 453d46a242e6..0cd9368a1040 100644 --- a/lib/bsddialog_progressview.h +++ b/lib/bsddialog_progressview.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,27 +28,33 @@ #ifndef _LIBBSDDIALOG_PROGRESSVIEW_H_ #define _LIBBSDDIALOG_PROGRESSVIEW_H_ +/* + * Undocumented API, DO NOT USE! + * Please consider this file private: it is used by bsdinstall/distextract, + * could be deleted or changed in the future. + */ + extern bool bsddialog_interruptprogview; extern bool bsddialog_abortprogview; extern int bsddialog_total_progview; struct bsddialog_fileminibar { - char *path; - char *label; - int status; /* mixedgauge: 1 failed - 5 done - 7 in progress*/ + const char *path; + const char *label; + int status; /* next if BSDDIALOG_MG_DONE or BSDDIALOG_MG_FAILED */ long long size; long long read; }; struct bsddialog_progviewconf { - char *fmtbottomstr; + const char *fmtbottomstr; unsigned int refresh; /* in seconds */ int (*callback)(struct bsddialog_fileminibar *minibar); }; int -bsddialog_progressview (struct bsddialog_conf *conf, char * text, int rows, +bsddialog_progressview (struct bsddialog_conf *conf, const char *text, int rows, int cols, struct bsddialog_progviewconf *pvconf, unsigned int nminibar, struct bsddialog_fileminibar *minibar); -#endif +#endif
\ No newline at end of file diff --git a/lib/bsddialog_theme.h b/lib/bsddialog_theme.h index 853eb5f9d864..65ba5f5e94e8 100644 --- a/lib/bsddialog_theme.h +++ b/lib/bsddialog_theme.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,11 +28,15 @@ #ifndef _LIBBSDDIALOG_THEME_H_ #define _LIBBSDDIALOG_THEME_H_ -/* f_ focus/active element */ +/* color flags */ +#define BSDDIALOG_BOLD 1U +#define BSDDIALOG_REVERSE 2U +#define BSDDIALOG_UNDERLINE 4U + struct bsddialog_theme { struct { int color; - } terminal; + } screen; struct { int color; unsigned int h; @@ -47,9 +51,6 @@ struct bsddialog_theme { int bottomtitlecolor; } dialog; struct { - unsigned int hmargin; - } text; - struct { int arrowcolor; int selectorcolor; int f_namecolor; @@ -87,7 +88,7 @@ enum bsddialog_default_theme { BSDDIALOG_THEME_BLACKWHITE, BSDDIALOG_THEME_BSDDIALOG, BSDDIALOG_THEME_DEFAULT, - BSDDIALOG_THEME_DIALOG, + BSDDIALOG_THEME_DIALOG }; enum bsddialog_color { @@ -98,13 +99,9 @@ enum bsddialog_color { BSDDIALOG_BLUE, BSDDIALOG_MAGENTA, BSDDIALOG_CYAN, - BSDDIALOG_WHITE, + BSDDIALOG_WHITE }; -#define BSDDIALOG_BOLD 1U -#define BSDDIALOG_REVERSE 2U -#define BSDDIALOG_UNDERLINE 4U - int bsddialog_color(enum bsddialog_color foreground, enum bsddialog_color background, unsigned int flags); @@ -112,4 +109,4 @@ int bsddialog_get_theme(struct bsddialog_theme *theme); int bsddialog_set_default_theme(enum bsddialog_default_theme theme); int bsddialog_set_theme(struct bsddialog_theme *theme); -#endif +#endif
\ No newline at end of file diff --git a/lib/formbox.c b/lib/formbox.c index 3a5d8a49e359..ade1660c2645 100644 --- a/lib/formbox.c +++ b/lib/formbox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,35 +28,29 @@ #include <sys/param.h> #include <ctype.h> -#ifdef PORTNCURSES -#include <ncurses/form.h> -#else #include <form.h> -#endif #include <stdlib.h> #include <string.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" +#include "lib_util.h" -#define REDRAWFORM 14021986 /* magic number */ +#define REDRAWFORM 19860214 /* magic number */ #define ISFIELDHIDDEN(item) (item.flags & BSDDIALOG_FIELDHIDDEN) #define ISFIELDREADONLY(item) (item.flags & BSDDIALOG_FIELDREADONLY) -/* "Form": inputbox - passwordbox - form - passwordform - mixedform */ - extern struct bsddialog_theme t; -/* util struct for private buffer and view options */ +/* field_userptr for private buffer and view options */ struct myfield { - int buflen; + int buflen; char *buf; - int pos; - int maxpos; + int pos; + int maxpos; bool secure; - int securech; - char *bottomdesc; + int securech; + const char *bottomdesc; }; #define GETMYFIELD(field) ((struct myfield*)field_userptr(field)) #define GETMYFIELD2(form) ((struct myfield*)field_userptr(current_field(form))) @@ -95,8 +89,7 @@ static void shiftleft(struct myfield *mf) static void print_bottomdesc(struct myfield *mf) { - - move(LINES-1, 2); + move(SCREENLINES - 1, 2); clrtoeol(); if (mf->bottomdesc != NULL) { addstr(mf->bottomdesc); @@ -105,26 +98,18 @@ static void print_bottomdesc(struct myfield *mf) } int -return_values(struct bsddialog_conf *conf, struct buttons bs, int nitems, +return_values(struct bsddialog_conf *conf, int output, int nitems, struct bsddialog_formitem *items, FORM *form, FIELD **cfield) { - int i, output; + int i; struct myfield *mf; - output = bs.value[bs.curr]; - if (output == BSDDIALOG_HELP && conf->form.value_withhelp == false) - return output; - if (output == BSDDIALOG_EXTRA && conf->form.value_withextra == false) - return output; - if (output == BSDDIALOG_CANCEL && conf->form.value_withcancel == false) - return output; - if (output == BSDDIALOG_GENERIC1 || output == BSDDIALOG_GENERIC2) - return output; - - /* BSDDIALOG_OK */ + if (output != BSDDIALOG_OK && conf->form.value_without_ok == false) + return (output); + form_driver(form, REQ_NEXT_FIELD); form_driver(form, REQ_PREV_FIELD); - for (i=0; i<nitems; i++) { + for (i = 0; i < nitems; i++) { mf = GETMYFIELD(cfield[i]); items[i].value = strdup(mf->buf); if (items[i].value == NULL) @@ -135,11 +120,11 @@ return_values(struct bsddialog_conf *conf, struct buttons bs, int nitems, } static int -form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, - struct buttons bs, WINDOW *formwin, FORM *form, FIELD **cfield, int nitems, +form_handler(struct bsddialog_conf *conf, WINDOW *widget, struct buttons bs, + WINDOW *formwin, FORM *form, FIELD **cfield, int nitems, struct bsddialog_formitem *items) { - bool loop, buttupdate, informwin = true; + bool loop, buttupdate, informwin; int i, input, output; struct myfield *mf; @@ -149,11 +134,15 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, form_driver(form, REQ_END_LINE); mf->pos = MIN(mf->buflen, mf->maxpos); curs_set(2); + informwin = true; + bs.curr = -1; - loop = buttupdate = true; - while(loop) { + buttupdate = true; + + loop = true; + while (loop) { if (buttupdate) { - draw_buttons(widget, y, cols, bs, !informwin); + draw_buttons(widget, bs, !informwin); wrefresh(widget); buttupdate = false; } @@ -164,12 +153,16 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, case 10: /* Enter */ if (informwin) break; + output = return_values(conf, bs.value[bs.curr], nitems, + items, form, cfield); loop = false; - output = return_values(conf, bs, nitems, items, form, cfield); break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = return_values(conf, BSDDIALOG_ESC, + nitems, items, form, cfield); + loop = false; + } break; case '\t': /* TAB */ if (informwin) { @@ -178,7 +171,7 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, curs_set(0); } else { bs.curr++; - informwin = bs.curr >= (int) bs.nbuttons ? + informwin = bs.curr >= (int)bs.nbuttons ? true : false; if (informwin) { curs_set(2); @@ -248,7 +241,7 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, form_driver(form, REQ_DEL_PREV); form_driver(form, REQ_BEG_LINE); mf->pos = mf->pos - 1; - for (i=0; i<mf->pos; i++) + for (i = 0; i < mf->pos; i++) form_driver(form, REQ_NEXT_CHAR); shiftleft(mf); break; @@ -262,16 +255,13 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); /* No Break */ case KEY_RESIZE: output = REDRAWFORM; loop = false; break; default: - /* - * user input, add unicode chars to "public" buffer - */ if (informwin) { mf = GETMYFIELD2(form); if (mf->secure) @@ -281,14 +271,11 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, insertch(mf, input); } else { - for (i = 0; i < (int) bs.nbuttons; i++) { - if (tolower(input) == - tolower((bs.label[i])[0])) { - bs.curr = i; - output = return_values(conf, bs, - nitems, items, form, cfield); - loop = false; - } + if (shortcut_buttons(input, &bs)) { + output = return_values(conf, + bs.value[bs.curr], nitems, items, + form, cfield); + loop = false; } } break; @@ -297,62 +284,47 @@ form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols, curs_set(0); - return output; + return (output); } -static void +static int form_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, - char *text, int linelen, unsigned int *formheight, int nitems, + const char *text, int linelen, unsigned int *formheight, int nitems, struct buttons bs) { - int textrow, menusize; + int htext, wtext, menusize; - textrow = text != NULL && strlen(text) > 0 ? 1 : 0; - - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += bs.nbuttons * bs.sizebutton; - *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* line size */ - *w = MAX(*w, linelen + 3); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* - * avoid terminal overflow, - * -1 fix false negative with big menu over the terminal and - * autosize, for example "portconfig /usr/ports/www/apache24/". - */ - *w = MIN(*w, widget_max_width(conf)-1); + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, &bs, *formheight + 2, + linelen + 2, &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } - if (rows == BSDDIALOG_AUTOSIZE) { - *h = HBORDERS + 2 /* buttons */ + textrow; + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, linelen + 2, &bs); + if (rows == BSDDIALOG_AUTOSIZE) { if (*formheight == 0) { - *h += nitems + 2; - *h = MIN(*h, widget_max_height(conf)); - menusize = MIN(nitems + 2, *h - (HBORDERS + 2 + textrow)); - menusize -=2; - *formheight = menusize < 0 ? 0 : menusize; + menusize = widget_max_height(conf) - HBORDERS - + 2 /*buttons*/ - htext; + menusize = MIN(menusize, nitems + 2); + *formheight = menusize - 2 < 0 ? 0 : menusize - 2; } - else /* h autosize with a fixed formheight */ - *h = *h + *formheight + 2; + else /* h autosize with fixed formheight */ + menusize = *formheight + 2; - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); - } - else { + *h = widget_min_height(conf, htext, menusize, true); + } else { if (*formheight == 0) - *formheight = MIN(rows-6-textrow, nitems); + *formheight = MIN(rows-6-htext, nitems); } + + return (0); } static int -form_checksize(int rows, int cols, char *text, int formheight, int nitems, - struct buttons bs) +form_checksize(int rows, int cols, const char *text, int formheight, int nitems, + unsigned int linelen, struct buttons bs) { int mincols, textrow, formrows; @@ -360,40 +332,39 @@ form_checksize(int rows, int cols, char *text, int formheight, int nitems, /* buttons */ mincols += bs.nbuttons * bs.sizebutton; mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* line, comment to permet some cols hidden */ - /* mincols = MAX(mincols, linelen); */ + mincols = MAX(mincols, (int)linelen + 4); if (cols < mincols) - RETURN_ERROR("Few cols, width < size buttons or "\ - "labels + forms"); + RETURN_ERROR("Few cols, width < size buttons or " + "forms (label + field)"); textrow = text != NULL && strlen(text) > 0 ? 1 : 0; if (nitems > 0 && formheight == 0) - RETURN_ERROR("fields > 0 but formheight == 0, probably "\ + RETURN_ERROR("fields > 0 but formheight == 0, probably " "terminal too small"); formrows = nitems > 0 ? 3 : 0; if (rows < 2 + 2 + formrows + textrow) RETURN_ERROR("Few lines for this menus"); - return 0; + return (0); } int -bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int formheight, unsigned int nitems, +bsddialog_form(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int formheight, unsigned int nitems, struct bsddialog_formitem *items) { WINDOW *widget, *formwin, *textpad, *shadow; - int i, output, color, y, x, h, w, htextpad; + int i, output, color, y, x, h, w; FIELD **cfield; FORM *form; struct buttons bs; struct myfield *myfields; unsigned long maxline; - /* disable form scrolling like dialog */ + /* disable form scrolling */ if (formheight < nitems) formheight = nitems; @@ -409,7 +380,7 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, maxline = 0; myfields = malloc(nitems * sizeof(struct myfield)); cfield = calloc(nitems + 1, sizeof(FIELD*)); - for (i=0; i < (int)nitems; i++) { + for (i = 0; i < (int)nitems; i++) { cfield[i] = new_field(1, items[i].fieldlen, items[i].yfield-1, items[i].xfield-1, 0, 0); field_opts_off(cfield[i], O_STATIC); @@ -417,7 +388,7 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, set_field_buffer(cfield[i], 0, items[i].init); myfields[i].buf = malloc(items[i].maxvaluelen + 1); - memset(myfields[i].buf, 0, items[i].maxvaluelen + 1); // end with '\0' for strdup + memset(myfields[i].buf, 0, items[i].maxvaluelen + 1); strncpy(myfields[i].buf, items[i].init, items[i].maxvaluelen); myfields[i].buflen = strlen(myfields[i].buf); @@ -430,16 +401,15 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, field_opts_off(cfield[i], O_AUTOSKIP); field_opts_off(cfield[i], O_BLANK); - /* field_opts_off(field[i], O_BS_OVERLOAD); */ if (ISFIELDHIDDEN(items[i])) { - /* field_opts_off(field[i], O_PUBLIC); old hidden */ myfields[i].secure = true; myfields[i].securech = ' '; if (conf->form.securech != '\0') myfields[i].securech = conf->form.securech; } - else myfields[i].secure = false; + else + myfields[i].secure = false; if (ISFIELDREADONLY(items[i])) { field_opts_off(cfield[i], O_EDIT); @@ -452,7 +422,7 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, set_field_back(cfield[i], color); maxline = MAX(maxline, items[i].xlabel + strlen(items[i].label)); - maxline = MAX(maxline, items[i].xfield + items[i].fieldlen); + maxline = MAX(maxline, items[i].xfield + items[i].fieldlen - 1); } cfield[i] = NULL; @@ -462,26 +432,26 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, set_field_fore(cfield[0], t.dialog.color); set_field_back(cfield[0], t.dialog.color); } - - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); + + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - form_autosize(conf, rows, cols, &h, &w, text, maxline, &formheight, - nitems, bs); - if (form_checksize(h, w, text, formheight, nitems, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (form_autosize(conf, rows, cols, &h, &w, text, maxline, &formheight, + nitems, bs) != 0) + return (BSDDIALOG_ERROR); + if (form_checksize(h, w, text, formheight, nitems, maxline, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); + + prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, + y + h - formheight, x + 1 + w - TEXTHMARGIN); - prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, - y + h - formheight, x + 1 + w - t.text.hmargin); - formwin = new_boxed_window(conf, y + h - 3 - formheight -2, x +1, formheight+2, w-2, LOWERED); @@ -491,32 +461,35 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, set_form_sub(form, derwin(formwin, nitems, w-4, 1, 1)); post_form(form); - for (i=0; i < (int)nitems; i++) - mvwaddstr(formwin, items[i].ylabel, items[i].xlabel, items[i].label); + for (i = 0; i < (int)nitems; i++) + mvwaddstr(formwin, items[i].ylabel, items[i].xlabel, + items[i].label); wrefresh(formwin); do { - output = form_handler(conf, widget, h-2, w, bs, formwin, form, - cfield, nitems, items); - - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - draw_buttons(widget, h-2, w, bs, true); + output = form_handler(conf, widget, bs, formwin, form, cfield, + nitems, items); + + if (update_dialog(conf, shadow, widget, y, x, h, w, textpad, + text, &bs, true) != 0) + return (BSDDIALOG_ERROR); + + doupdate(); wrefresh(widget); - prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, - y + h - formheight, x + 1 + w - t.text.hmargin); + prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, + y + h - formheight, x + 1 + w - TEXTHMARGIN); draw_borders(conf, formwin, formheight+2, w-2, LOWERED); - /* wrefresh(formwin); */ + wrefresh(formwin); + + refresh(); } while (output == REDRAWFORM); unpost_form(form); free_form(form); - for (i=0; i < (int)nitems; i++) { + for (i = 0; i < (int)nitems; i++) { free_field(cfield[i]); free(myfields[i].buf); } @@ -524,7 +497,7 @@ bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols, free(myfields); delwin(formwin); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; -} + return (output); +}
\ No newline at end of file diff --git a/lib/infobox.c b/lib/infobox.c index 7752d7eec190..4ded942fb300 100644 --- a/lib/infobox.c +++ b/lib/infobox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,92 +27,73 @@ #include <sys/param.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" - -/* "Info": infobox */ - -#define MIN_HEIGHT 3 +#include "lib_util.h" extern struct bsddialog_theme t; static int -infobox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, - char *text) +infobox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, + int *w, const char *text) { - int maxword, maxline, nlines; - - if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) - return BSDDIALOG_ERROR; - - if (cols == BSDDIALOG_AUTOSIZE) { - /* text size */ - *w = maxline + VBORDERS + t.text.hmargin * 2; - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* avoid terminal overflow */ - *w = MIN(*w, widget_max_width(conf)); - } + int htext, wtext; - if (rows == BSDDIALOG_AUTOSIZE) { - *h = MIN_HEIGHT - 1; - if (maxword > 0) - *h += MIN(nlines, (int)(*w / GET_ASPECT_RATIO(conf))); - *h = MAX(*h, MIN_HEIGHT); - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, NULL, 0, SCREENCOLS/2, + &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } - return 0; + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, 0, NULL); + + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, htext, 0, false); + + return (0); } static int infobox_checksize(int rows, int cols) { + if (cols < HBORDERS) + RETURN_ERROR("Few cols, infobox needs at least width 2"); - if (cols < HBORDERS + 1 + (int) t.text.hmargin * 2) - RETURN_ERROR("Few cols, infobox needs at least width 3 + text "\ - "margins"); - - if (rows < 3) - RETURN_ERROR("Infobox needs at least height 3"); + if (rows < VBORDERS) + RETURN_ERROR("Infobox needs at least height 2"); - return 0; + return (0); } +/* API */ int -bsddialog_infobox(struct bsddialog_conf *conf, char* text, int rows, int cols) +bsddialog_infobox(struct bsddialog_conf *conf, const char *text, int rows, + int cols) { + int y, x, h, w; WINDOW *shadow, *widget, *textpad; - int y, x, h, w, htextpad; if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (infobox_autosize(conf, rows, cols, &h, &w, text) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (infobox_checksize(h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, false) != 0) - return BSDDIALOG_ERROR; + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, + NULL, false) != 0) + return (BSDDIALOG_ERROR); - pnoutrefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-2, x+w-t.text.hmargin); + pnoutrefresh(textpad, 0, 0, y+1, x+1+TEXTHMARGIN, y+h-2, + x+w-TEXTHMARGIN); doupdate(); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); return (BSDDIALOG_OK); -} - +}
\ No newline at end of file diff --git a/lib/lib_util.c b/lib/lib_util.c index 81c2b7642aac..f7e6a2ae15ab 100644 --- a/lib/lib_util.c +++ b/lib/lib_util.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,46 +27,42 @@ #include <sys/param.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <ctype.h> +#include <curses.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" +#include "lib_util.h" extern struct bsddialog_theme t; -/* Error buffer */ +#define TABLEN 4 /* Default tab len */ +#define ERRBUFLEN 1024 /* Error buffer */ -#define ERRBUFLEN 1024 +/* Error */ static char errorbuffer[ERRBUFLEN]; const char *get_error_string(void) { - return errorbuffer; + return (errorbuffer); } void set_error_string(char *str) { - strncpy(errorbuffer, str, ERRBUFLEN-1); } -/* cleaner */ +/* Clear */ int hide_widget(int y, int x, int h, int w, bool withshadow) { WINDOW *clear; - /* no check: y, x, h and w are checked by the builders */ if ((clear = newwin(h, w, y + t.shadow.h, x + t.shadow.w)) == NULL) RETURN_ERROR("Cannot hide the widget"); - wbkgd(clear, t.terminal.color); + wbkgd(clear, t.screen.color); if (withshadow) wrefresh(clear); @@ -76,7 +72,7 @@ int hide_widget(int y, int x, int h, int w, bool withshadow) delwin(clear); - return 0; + return (0); } /* F1 help */ @@ -85,15 +81,14 @@ int f1help(struct bsddialog_conf *conf) int output; struct bsddialog_conf hconf; - //memcpy(&hconf, conf, sizeof(struct bsddialog_conf)); bsddialog_initconf(&hconf); - hconf.title = "HELP"; + hconf.title = "HELP"; hconf.button.ok_label = "EXIT"; - hconf.clear = true; - hconf.ascii_lines = conf->ascii_lines; - hconf.no_lines = conf->no_lines; - hconf.shadow = conf->shadow; - hconf.text.colors = conf->text.colors; + hconf.clear = true; + hconf.ascii_lines = conf->ascii_lines; + hconf.no_lines = conf->no_lines; + hconf.shadow = conf->shadow; + hconf.text.highlight = conf->text.highlight; output = BSDDIALOG_OK; if (conf->f1_message != NULL) @@ -106,9 +101,9 @@ int f1help(struct bsddialog_conf *conf) } /* Buttons */ -void -draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected, - bool shortkey) +static void +draw_button(WINDOW *window, int y, int x, int size, const char *text, + bool selected, bool shortcut) { int i, color_arrows, color_shortkey, color_button; @@ -126,7 +121,7 @@ draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected, mvwaddch(window, y, x, t.button.leftch); wattroff(window, color_arrows); wattron(window, color_button); - for(i = 1; i < size - 1; i++) + for (i = 1; i < size - 1; i++) waddch(window, ' '); wattroff(window, color_button); wattron(window, color_arrows); @@ -138,7 +133,7 @@ draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected, mvwaddstr(window, y, x, text); wattroff(window, color_button); - if (shortkey) { + if (shortcut) { wattron(window, color_shortkey); mvwaddch(window, y, x, text[0]); wattroff(window, color_shortkey); @@ -146,56 +141,62 @@ draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected, } void -draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey) +draw_buttons(WINDOW *window, struct buttons bs, bool shortcut) { - int i, x, start_x; + int i, x, startx, y, rows, cols; + + getmaxyx(window, rows, cols); + y = rows - 2; - start_x = bs.sizebutton * bs.nbuttons + (bs.nbuttons - 1) * t.button.space; - start_x = cols/2 - start_x/2; + startx = bs.sizebutton * bs.nbuttons + (bs.nbuttons-1) * t.button.space; + startx = cols/2 - startx/2; for (i = 0; i < (int) bs.nbuttons; i++) { x = i * (bs.sizebutton + t.button.space); - draw_button(window, y, start_x + x, bs.sizebutton, bs.label[i], - i == bs.curr, shortkey); + draw_button(window, y, startx + x, bs.sizebutton, bs.label[i], + i == bs.curr, shortcut); } } void get_buttons(struct bsddialog_conf *conf, struct buttons *bs, char *yesoklabel, - char *extralabel, char *nocancellabel, char *helplabel) + char *nocancellabel) { int i; -#define SIZEBUTTON 8 -#define DEFAULT_BUTTON_LABEL LABEL_ok_label +#define SIZEBUTTON 8 +#define DEFAULT_BUTTON_LABEL BUTTON_OK_LABEL #define DEFAULT_BUTTON_VALUE BSDDIALOG_OK - bs->nbuttons = 0; bs->curr = 0; bs->sizebutton = 0; if (yesoklabel != NULL && conf->button.without_ok == false) { - bs->label[0] = yesoklabel; + bs->label[0] = conf->button.ok_label != NULL ? + conf->button.ok_label : yesoklabel; bs->value[0] = BSDDIALOG_OK; bs->nbuttons += 1; } - if (extralabel != NULL && conf->button.with_extra) { - bs->label[bs->nbuttons] = extralabel; + if (conf->button.with_extra) { + bs->label[bs->nbuttons] = conf->button.extra_label != NULL ? + conf->button.extra_label : "Extra"; bs->value[bs->nbuttons] = BSDDIALOG_EXTRA; bs->nbuttons += 1; } if (nocancellabel != NULL && conf->button.without_cancel == false) { - bs->label[bs->nbuttons] = nocancellabel; + bs->label[bs->nbuttons] = conf->button.cancel_label ? + conf->button.cancel_label : nocancellabel; bs->value[bs->nbuttons] = BSDDIALOG_CANCEL; if (conf->button.default_cancel) bs->curr = bs->nbuttons; bs->nbuttons += 1; } - if (helplabel != NULL && conf->button.with_help) { - bs->label[bs->nbuttons] = helplabel; + if (conf->button.with_help) { + bs->label[bs->nbuttons] = conf->button.help_label != NULL ? + conf->button.help_label : "Help"; bs->value[bs->nbuttons] = BSDDIALOG_HELP; bs->nbuttons += 1; } @@ -219,44 +220,61 @@ get_buttons(struct bsddialog_conf *conf, struct buttons *bs, char *yesoklabel, } if (conf->button.default_label != NULL) { - for (i=0; i<(int)bs->nbuttons; i++) { - if (strcmp(conf->button.default_label, bs->label[i]) == 0) + for (i = 0; i < (int)bs->nbuttons; i++) { + if (strcmp(conf->button.default_label, + bs->label[i]) == 0) bs->curr = i; } } bs->sizebutton = MAX(SIZEBUTTON - 2, strlen(bs->label[0])); - for (i=1; i < (int) bs->nbuttons; i++) + for (i = 1; i < (int)bs->nbuttons; i++) bs->sizebutton = MAX(bs->sizebutton, strlen(bs->label[i])); bs->sizebutton += 2; } -/* Text */ -static bool is_ncurses_attr(char *text) +bool shortcut_buttons(int key, struct buttons *bs) { + bool match; + unsigned int i; + + match = false; + for (i = 0; i < bs->nbuttons; i++) { + if (tolower(key) == tolower(bs->label[i][0])) { + bs->curr = i; + match = true; + break; + } + } + return (match); +} + +/* Text */ +static bool is_text_attr(const char *text) +{ if (strnlen(text, 3) < 3) - return false; + return (false); if (text[0] != '\\' || text[1] != 'Z') - return false; + return (false); return (strchr("nbBrRuU01234567", text[2]) == NULL ? false : true); } -static bool check_set_ncurses_attr(WINDOW *win, char *text) +static bool check_set_text_attr(WINDOW *win, char *text) { - - if (is_ncurses_attr(text) == false) - return false; + if (is_text_attr(text) == false) + return (false); if ((text[2] - '0') >= 0 && (text[2] - '0') < 8) { - wattron(win, bsddialog_color( text[2] - '0', COLOR_WHITE, 0)); - return true; + wattron(win, bsddialog_color(text[2] - '0', COLOR_WHITE, 0)); + return (true); } switch (text[2]) { case 'n': + wattron(win, t.dialog.color); wattrset(win, A_NORMAL); break; case 'b': @@ -279,22 +297,20 @@ static bool check_set_ncurses_attr(WINDOW *win, char *text) break; } - return true; + return (true); } static void -print_str(WINDOW *win, int *rows, int *y, int *x, int cols, char *str, bool color) +print_string(WINDOW *win, int *rows, int cols, int *y, int *x, char *str, + bool color) { int i, j, len, reallen; - if(strlen(str) == 0) - return; - len = reallen = strlen(str); if (color) { i=0; while (i < len) { - if (is_ncurses_attr(str+i)) + if (is_text_attr(str+i)) reallen -= 3; i++; } @@ -312,7 +328,7 @@ print_str(WINDOW *win, int *rows, int *y, int *x, int cols, char *str, bool colo } j = *x; while (j < cols && i < len) { - if (color && check_set_ncurses_attr(win, str+i)) { + if (color && check_set_text_attr(win, str+i)) { i += 3; } else { mvwaddch(win, *y, j, str[i]); @@ -325,77 +341,28 @@ print_str(WINDOW *win, int *rows, int *y, int *x, int cols, char *str, bool colo } } -int -get_text_properties(struct bsddialog_conf *conf, char *text, int *maxword, - int *maxline, int *nlines) -{ - int i, buflen, wordlen, linelen; - - - buflen = strlen(text) + 1; - *maxword = 0; - wordlen = 0; - for (i=0; i < buflen; i++) { - if (text[i] == '\t' || text[i] == '\n' || text[i] == ' ' || text[i] == '\0') - if (wordlen != 0) { - *maxword = MAX(*maxword, wordlen); - wordlen = 0; - continue; - } - if (conf->text.colors && is_ncurses_attr(text + i)) - i += 3; - else - wordlen++; - } - - *maxline = linelen = 0; - *nlines = 1; - for (i=0; i < buflen; i++) { - switch (text[i]) { - case '\n': - *nlines = *nlines + 1; - case '\0': - *maxline = MAX(*maxline, linelen); - linelen = 0; - break; - default: - if (conf->text.colors && is_ncurses_attr(text + i)) - i += 3; - else - linelen++; - } - } - if (*nlines == 1 && *maxline == 0) - *nlines = 0; - - //free(buf); - - return 0; -} - -int -print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols, - char *text) +static int +print_textpad(struct bsddialog_conf *conf, WINDOW *pad, const char *text) { - char *string; - int i, j, x, y; bool loop; + int i, j, z, rows, cols, x, y, tablen; + char *string; if ((string = malloc(strlen(text) + 1)) == NULL) RETURN_ERROR("Cannot build (analyze) text"); + getmaxyx(pad, rows, cols); + tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen; + i = j = x = y = 0; loop = true; while (loop) { string[j] = text[i]; - if (string[j] == '\0' || string[j] == '\n' || - string[j] == '\t' || string[j] == ' ') { - if (j != 0) { - string[j] = '\0'; - print_str(pad, rows, &y, &x, cols, string, - conf->text.colors); - } + if (strchr("\n\t ", string[j]) != NULL || string[j] == '\0') { + string[j] = '\0'; + print_string(pad, &rows, cols, &y, &x, string, + conf->text.highlight); } switch (text[i]) { @@ -403,17 +370,17 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols, loop = false; break; case '\n': - j = -1; x = 0; y++; + j = -1; break; case '\t': - for (j=0; j<4 /*tablen*/; j++) { - x++; + for (z = 0; z < tablen; z++) { if (x >= cols) { x = 0; y++; } + x++; } j = -1; break; @@ -426,9 +393,9 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols, j = -1; } - if (y >= *rows) { /* check for whitespaces */ - *rows = y + 1; - wresize(pad, *rows, cols); + if (y >= rows) { + rows = y + 1; + wresize(pad, rows, cols); } j++; @@ -437,44 +404,279 @@ print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols, free(string); - return 0; + return (0); } -/* autosize */ +/* Autosize */ +static int +text_autosize(struct bsddialog_conf *conf, const char *text, int maxrows, + int mincols, bool increasecols, int *h, int *w) +{ + int i, j, z, x, y; + int tablen, wordlen, maxwordlen, nword, maxwords, line, maxwidth; + int *words; +#define NL -1 +#define WS -2 + + maxwords = 1024; + if ((words = calloc(maxwords, sizeof(int))) == NULL) + RETURN_ERROR("Cannot alloc memory for text autosize"); + + tablen = (conf->text.tablen == 0) ? TABLEN : (int)conf->text.tablen; + maxwidth = widget_max_width(conf) - HBORDERS - TEXTHMARGINS; + + nword = 0; + wordlen = 0; + maxwordlen = 0; + i=0; + while (true) { + if (conf->text.highlight && is_text_attr(text + i)) { + i += 3; + continue; + } + + if (nword + tablen >= maxwords) { + maxwords += 1024; + if (realloc(words, maxwords * sizeof(int)) == NULL) + RETURN_ERROR("Cannot realloc memory for text " + "autosize"); + } + + if (text[i] == '\0') { + words[nword] = wordlen; + maxwordlen = MAX(wordlen, maxwordlen); + break; + } + + if (strchr("\t\n ", text[i]) != NULL) { + maxwordlen = MAX(wordlen, maxwordlen); + + if (wordlen != 0) { + words[nword] = wordlen; + nword++; + wordlen = 0; + } + + if (text[i] == '\t') { + for (j = 0; j < tablen; j++) + words[nword + j] = 1; + nword += tablen; + } else { + words[nword] = text[i] == '\n' ? NL : WS; + nword++; + } + } + else + wordlen++; + + i++; + } + + if (increasecols) { + mincols = MAX(mincols, maxwordlen); + mincols = MAX(mincols, + (int)conf->auto_minwidth - HBORDERS - TEXTHMARGINS); + mincols = MIN(mincols, maxwidth); + } + + while (true) { + x = 0; + y = 1; + line=0; + for (i = 0; i <= nword; i++) { + if (words[i] == NL) { + y++; + x = 0; + } + else if (words[i] == WS) { + x++; + if (x >= mincols) { + x = 0; + y++; + } + } + else { + if (words[i] + x <= mincols) + x += words[i]; + else { + for (z = words[i]; z > 0; ) { + y++; + x = MIN(mincols, z); + z -= x; + } + } + } + line = MAX(line, x); + } + + if (increasecols == false) + break; + if (y <= maxrows || mincols >= maxwidth) + break; + mincols++; + } + + *h = (nword == 0 && words[0] == 0) ? 0 : y; + *w = MIN(mincols, line); /* wtext can be less than mincols */ + + free(words); + + return (0); +} + +int +text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text, + struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext) +{ + int wbuttons, maxhtext; + bool changewtext; + + wbuttons = 0; + if (bs != NULL) { + wbuttons = bs->nbuttons * bs->sizebutton; + if (bs->nbuttons > 0) + wbuttons += (bs->nbuttons-1) * t.button.space; + } + + if (cols == BSDDIALOG_AUTOSIZE) { + startwtext = MAX(startwtext, wbuttons - TEXTHMARGINS); + changewtext = true; + } else if (cols == BSDDIALOG_FULLSCREEN) { + startwtext = widget_max_width(conf) - VBORDERS - TEXTHMARGINS; + changewtext = false; + } else { /* fixed */ + startwtext = cols - VBORDERS - TEXTHMARGINS; + changewtext = false; + } + + if (rows == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_FULLSCREEN) { + maxhtext = widget_max_height(conf) - VBORDERS - rowsnotext; + if (bs != NULL) + maxhtext -= 2; + } else { /* fixed */ + maxhtext = rows - VBORDERS - rowsnotext; + if (bs != NULL) + maxhtext -= 2; + } + + if (startwtext <= 0 && changewtext) + startwtext = 1; + if (maxhtext <= 0 || startwtext <= 0) { + *htext = *wtext = 0; + return (0); + } + + if (text_autosize(conf, text, maxhtext, startwtext, changewtext, + htext, wtext) != 0) + return (BSDDIALOG_ERROR); + + return (0); +} -/* - * max y, that is from 0 to LINES - 1 - t.shadowrows, - * could not be max height but avoids problems with checksize - */ int widget_max_height(struct bsddialog_conf *conf) { int maxheight; - if ((maxheight = conf->shadow ? LINES - 1 - t.shadow.h : LINES - 1) <= 0) - RETURN_ERROR("Terminal too small, LINES - shadow <= 0"); + maxheight = conf->shadow ? SCREENLINES - t.shadow.h : SCREENLINES; + if (maxheight <= 0) + RETURN_ERROR("Terminal too small, screen lines - shadow <= 0"); - if (conf->y > 0) - if ((maxheight -= conf->y) <=0) - RETURN_ERROR("Terminal too small, LINES - shadow - y <= 0"); + if (conf->y > 0) { + maxheight -= conf->y; + if (maxheight <= 0) + RETURN_ERROR("Terminal too small, screen lines - " + "shadow - y <= 0"); + } - return maxheight; + return (maxheight); } -/* - * max x, that is from 0 to COLS - 1 - t.shadowcols, - * * could not be max height but avoids problems with checksize - */ int widget_max_width(struct bsddialog_conf *conf) { int maxwidth; - if ((maxwidth = conf->shadow ? COLS - 1 - t.shadow.w : COLS - 1) <= 0) - RETURN_ERROR("Terminal too small, COLS - shadow <= 0"); - if (conf->x > 0) - if ((maxwidth -= conf->x) <=0) - RETURN_ERROR("Terminal too small, COLS - shadow - x <= 0"); + maxwidth = conf->shadow ? SCREENCOLS - t.shadow.w : SCREENCOLS; + if (maxwidth <= 0) + RETURN_ERROR("Terminal too small, screen cols - shadow <= 0"); + + if (conf->x > 0) { + maxwidth -= conf->x; + if (maxwidth <= 0) + RETURN_ERROR("Terminal too small, screen cols - shadow " + "- x <= 0"); + } + + return (maxwidth); +} + +int +widget_min_height(struct bsddialog_conf *conf, int htext, int minwidget, + bool withbuttons) +{ + int min; + + min = 0; + + /* buttons */ + if (withbuttons) + min += 2; /* buttons and border */ + + /* text */ + min += htext; + + /* specific widget min height */ + min += minwidget; + + /* dialog borders */ + min += HBORDERS; + /* conf.auto_minheight */ + min = MAX(min, (int)conf->auto_minheight); + /* avoid terminal overflow */ + min = MIN(min, widget_max_height(conf)); + + return (min); +} + +int +widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget, + struct buttons *bs) + +{ + int min, delimtitle; + + min = 0; + + /* buttons */ + if (bs != NULL) { + min += bs->nbuttons * bs->sizebutton; + min += bs->nbuttons > 0 ? (bs->nbuttons-1) * t.button.space : 0; + } + + /* text */ + if (wtext > 0) + min = MAX(min, wtext + TEXTHMARGINS); + + /* specific widget min width */ + min = MAX(min, minwidget); + + /* title */ + if (conf->title != NULL) { + delimtitle = t.dialog.delimtitle ? 2 : 0; + min = MAX(min, (int)strlen(conf->title) + 2 + delimtitle); + } + + /* bottom title */ + if (conf->bottomtitle != NULL) + min = MAX(min, (int)strlen(conf->bottomtitle) + 4); + + /* dialog borders */ + min += VBORDERS; + /* conf.auto_minwidth */ + min = MAX(min, (int)conf->auto_minwidth); + /* avoid terminal overflow */ + min = MIN(min, widget_max_width(conf)); - return maxwidth; + return (min); } int @@ -483,7 +685,7 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w) int maxheight, maxwidth; if ((maxheight = widget_max_height(conf)) == BSDDIALOG_ERROR) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (rows == BSDDIALOG_FULLSCREEN) *h = maxheight; @@ -491,13 +693,13 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w) RETURN_ERROR("Negative (less than -1) height"); else if (rows > BSDDIALOG_AUTOSIZE) { if ((*h = rows) > maxheight) - RETURN_ERROR("Height too big (> terminal height - "\ - "shadow"); + RETURN_ERROR("Height too big (> terminal height - " + "shadow)"); } /* rows == AUTOSIZE: each widget has to set its size */ if ((maxwidth = widget_max_width(conf)) == BSDDIALOG_ERROR) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (cols == BSDDIALOG_FULLSCREEN) *w = maxwidth; @@ -505,45 +707,45 @@ set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w) RETURN_ERROR("Negative (less than -1) width"); else if (cols > BSDDIALOG_AUTOSIZE) { if ((*w = cols) > maxwidth) - RETURN_ERROR("Width too big (> terminal width - shadow)"); + RETURN_ERROR("Width too big (> terminal width - " + "shadow)"); } /* cols == AUTOSIZE: each widget has to set its size */ - return 0; + return (0); } int set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w) { - if (conf->y == BSDDIALOG_CENTER) - *y = LINES/2 - h/2; + *y = SCREENLINES/2 - (h + t.shadow.h)/2; else if (conf->y < BSDDIALOG_CENTER) RETURN_ERROR("Negative begin y (less than -1)"); - else if (conf->y >= LINES) + else if (conf->y >= SCREENLINES) RETURN_ERROR("Begin Y under the terminal"); else *y = conf->y; - if ((*y + h + (conf->shadow ? (int) t.shadow.h : 0)) > LINES) - RETURN_ERROR("The lower of the box under the terminal "\ + if ((*y + h + (conf->shadow ? (int) t.shadow.h : 0)) > SCREENLINES) + RETURN_ERROR("The lower of the box under the terminal " "(begin Y + height (+ shadow) > terminal lines)"); if (conf->x == BSDDIALOG_CENTER) - *x = COLS/2 - w/2; + *x = SCREENCOLS/2 - (w + t.shadow.w)/2; else if (conf->x < BSDDIALOG_CENTER) RETURN_ERROR("Negative begin x (less than -1)"); - else if (conf->x >= COLS) + else if (conf->x >= SCREENCOLS) RETURN_ERROR("Begin X over the right of the terminal"); else *x = conf->x; - if ((*x + w + (conf->shadow ? (int) t.shadow.w : 0)) > COLS) - RETURN_ERROR("The right of the box over the terminal "\ + if ((*x + w + (conf->shadow ? (int) t.shadow.w : 0)) > SCREENCOLS) + RETURN_ERROR("The right of the box over the terminal " "(begin X + width (+ shadow) > terminal cols)"); - return 0; + return (0); } /* Widgets builders */ @@ -552,39 +754,40 @@ draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols, enum elevation elev) { int leftcolor, rightcolor; - int ls, rs, ts, bs, tl, tr, bl, br; - int ltee, rtee; - - ls = rs = ACS_VLINE; - ts = bs = ACS_HLINE; - tl = ACS_ULCORNER; - tr = ACS_URCORNER; - bl = ACS_LLCORNER; - br = ACS_LRCORNER; - ltee = ACS_LTEE; - rtee = ACS_RTEE; - - if (conf->no_lines == false) { - if (conf->ascii_lines) { - ls = rs = '|'; - ts = bs = '-'; - tl = tr = bl = br = ltee = rtee = '+'; - } - leftcolor = elev == RAISED ? - t.dialog.lineraisecolor : t.dialog.linelowercolor; - rightcolor = elev == RAISED ? - t.dialog.linelowercolor : t.dialog.lineraisecolor; - wattron(win, leftcolor); - wborder(win, ls, rs, ts, bs, tl, tr, bl, br); - wattroff(win, leftcolor); - - wattron(win, rightcolor); - mvwaddch(win, 0, cols-1, tr); - mvwvline(win, 1, cols-1, rs, rows-2); - mvwaddch(win, rows-1, cols-1, br); - mvwhline(win, rows-1, 1, bs, cols-2); - wattroff(win, rightcolor); + int ls, rs, ts, bs, tl, tr, bl, br, ltee, rtee; + + if (conf->no_lines) + return; + + if (conf->ascii_lines) { + ls = rs = '|'; + ts = bs = '-'; + tl = tr = bl = br = ltee = rtee = '+'; + } else { + ls = rs = ACS_VLINE; + ts = bs = ACS_HLINE; + tl = ACS_ULCORNER; + tr = ACS_URCORNER; + bl = ACS_LLCORNER; + br = ACS_LRCORNER; + ltee = ACS_LTEE; + rtee = ACS_RTEE; } + + leftcolor = elev == RAISED ? + t.dialog.lineraisecolor : t.dialog.linelowercolor; + rightcolor = elev == RAISED ? + t.dialog.linelowercolor : t.dialog.lineraisecolor; + wattron(win, leftcolor); + wborder(win, ls, rs, ts, bs, tl, tr, bl, br); + wattroff(win, leftcolor); + + wattron(win, rightcolor); + mvwaddch(win, 0, cols-1, tr); + mvwvline(win, 1, cols-1, rs, rows-2); + mvwaddch(win, rows-1, cols-1, br); + mvwhline(win, rows-1, 1, bs, cols-2); + wattroff(win, rightcolor); } WINDOW * @@ -595,119 +798,113 @@ new_boxed_window(struct bsddialog_conf *conf, int y, int x, int rows, int cols, if ((win = newwin(rows, cols, y, x)) == NULL) { set_error_string("Cannot build boxed window"); - return NULL; + return (NULL); } wbkgd(win, t.dialog.color); draw_borders(conf, win, rows, cols, elev); - return win; + return (win); } -/* - * `enum elevation elev` could be useless because it should be always RAISED, - * to check at the end. - */ static int -draw_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *shadow, - WINDOW *widget, int h, int w, enum elevation elev, - WINDOW *textpad, int *htextpad, char *text, bool buttons) +draw_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, + WINDOW *textpad, const char *text, struct buttons *bs, bool shortcutbuttons) { - int ts, ltee, rtee; - int colordelimtitle; + int h, w, ts, ltee, rtee; ts = conf->ascii_lines ? '-' : ACS_HLINE; ltee = conf->ascii_lines ? '+' : ACS_LTEE; rtee = conf->ascii_lines ? '+' : ACS_RTEE; - colordelimtitle = elev == RAISED ? - t.dialog.lineraisecolor : t.dialog.linelowercolor; + + getmaxyx(widget, h, w); if (shadow != NULL) wnoutrefresh(shadow); - // move / resize now or the caller? - draw_borders(conf, widget, h, w, elev); + draw_borders(conf, widget, h, w, RAISED); if (conf->title != NULL) { if (t.dialog.delimtitle && conf->no_lines == false) { - wattron(widget, colordelimtitle); - mvwaddch(widget, 0, w/2 - strlen(conf->title)/2 - 1, rtee); - wattroff(widget, colordelimtitle); + wattron(widget, t.dialog.lineraisecolor); + mvwaddch(widget, 0, w/2-strlen(conf->title)/2-1, rtee); + wattroff(widget, t.dialog.lineraisecolor); } wattron(widget, t.dialog.titlecolor); mvwaddstr(widget, 0, w/2 - strlen(conf->title)/2, conf->title); wattroff(widget, t.dialog.titlecolor); if (t.dialog.delimtitle && conf->no_lines == false) { - wattron(widget, colordelimtitle); + wattron(widget, t.dialog.lineraisecolor); waddch(widget, ltee); - wattroff(widget, colordelimtitle); + wattroff(widget, t.dialog.lineraisecolor); } } + if (bs != NULL) { + if (conf->no_lines == false) { + wattron(widget, t.dialog.lineraisecolor); + mvwaddch(widget, h-3, 0, ltee); + mvwhline(widget, h-3, 1, ts, w-2); + wattroff(widget, t.dialog.lineraisecolor); + + wattron(widget, t.dialog.linelowercolor); + mvwaddch(widget, h-3, w-1, rtee); + wattroff(widget, t.dialog.linelowercolor); + } + draw_buttons(widget, *bs, shortcutbuttons); + } + if (conf->bottomtitle != NULL) { wattron(widget, t.dialog.bottomtitlecolor); wmove(widget, h - 1, w/2 - strlen(conf->bottomtitle)/2 - 1); - waddch(widget, '['); + waddch(widget, ' '); waddstr(widget, conf->bottomtitle); - waddch(widget, ']'); + waddch(widget, ' '); wattroff(widget, t.dialog.bottomtitlecolor); } - //if (textpad == NULL && text != NULL) /* no pad, text null for textbox */ - // print_text(conf, widget, 1, 2, w-3, text); - - if (buttons && conf->no_lines == false) { - wattron(widget, t.dialog.lineraisecolor); - mvwaddch(widget, h-3, 0, ltee); - mvwhline(widget, h-3, 1, ts, w-2); - wattroff(widget, t.dialog.lineraisecolor); - - wattron(widget, t.dialog.linelowercolor); - mvwaddch(widget, h-3, w-1, rtee); - wattroff(widget, t.dialog.linelowercolor); - } - wnoutrefresh(widget); - if (textpad == NULL) - return 0; /* widget_init() ends */ + if (textpad != NULL && text != NULL) /* textbox */ + if (print_textpad(conf, textpad, text) !=0) + return (BSDDIALOG_ERROR); - if (text != NULL) /* programbox etc */ - if (print_textpad(conf, textpad, htextpad, - w - HBORDERS - t.text.hmargin * 2, text) !=0) - return BSDDIALOG_ERROR; - - return 0; + return (0); } -/* - * `enum elevation elev` could be useless because it should be always RAISED, - * to check at the end. - */ int -update_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *shadow, - WINDOW *widget, int h, int w, enum elevation elev, - WINDOW *textpad, int *htextpad, char *text, bool buttons) +update_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, + int y, int x, int h, int w, WINDOW *textpad, const char *text, + struct buttons *bs, bool shortcutbuttons) { int error; - /* nothing for now */ + if (shadow != NULL) { + wclear(shadow); + mvwin(shadow, y + t.shadow.h, x + t.shadow.w); + wresize(shadow, h, w); + } + + wclear(widget); + mvwin(widget, y, x); + wresize(widget, h, w); + + if (textpad != NULL) { + wclear(textpad); + wresize(textpad, 1, w - HBORDERS - TEXTHMARGINS); + } - error = draw_widget_withtextpad(conf, shadow, widget, h, w, - elev, textpad, htextpad, text, buttons); + error = draw_dialog(conf, shadow, widget, textpad, text, bs, + shortcutbuttons); - return error; + return (error); } -/* - * `enum elevation elev` could be useless because it should be always RAISED, - * to check at the end. - */ int -new_widget_withtextpad(struct bsddialog_conf *conf, WINDOW **shadow, - WINDOW **widget, int y, int x, int h, int w, enum elevation elev, - WINDOW **textpad, int *htextpad, char *text, bool buttons) +new_dialog(struct bsddialog_conf *conf, WINDOW **shadow, WINDOW **widget, int y, + int x, int h, int w, WINDOW **textpad, const char *text, struct buttons *bs, + bool shortcutbuttons) { int error; @@ -718,23 +915,16 @@ new_widget_withtextpad(struct bsddialog_conf *conf, WINDOW **shadow, wbkgd(*shadow, t.shadow.color); } - if ((*widget = new_boxed_window(conf, y, x, h, w, elev)) == NULL) { + if ((*widget = new_boxed_window(conf, y, x, h, w, RAISED)) == NULL) { if (conf->shadow) delwin(*shadow); - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); } - if (textpad == NULL) { /* widget_init() */ - error = draw_widget_withtextpad(conf, *shadow, *widget, h, w, - elev, NULL, NULL, text, buttons); - return error; - } - - if (text != NULL) { /* programbox etc */ - *htextpad = 1; - *textpad = newpad(*htextpad, w - HBORDERS - t.text.hmargin * 2); + if (textpad != NULL && text != NULL) { /* textbox */ + *textpad = newpad(1, w - HBORDERS - TEXTHMARGINS); if (*textpad == NULL) { - delwin(*textpad); + delwin(*widget); if (conf->shadow) delwin(*shadow); RETURN_ERROR("Cannot build the pad window for text"); @@ -742,19 +932,20 @@ new_widget_withtextpad(struct bsddialog_conf *conf, WINDOW **shadow, wbkgd(*textpad, t.dialog.color); } - error = draw_widget_withtextpad(conf, *shadow, *widget, h, w, elev, - *textpad, htextpad, text, buttons); + error = draw_dialog(conf, *shadow, *widget, + textpad == NULL ? NULL : *textpad, text, bs, shortcutbuttons); - return error; + return (error); } void -end_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *window, int h, int w, - WINDOW *textpad, WINDOW *shadow) +end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, + WINDOW *textpad) { - int y, x; + int y, x, h, w; - getbegyx(window, y, x); /* for clear, add y & x to args? */ + getbegyx(widget, y, x); + getmaxyx(widget, h, w); if (conf->sleep > 0) sleep(conf->sleep); @@ -762,7 +953,7 @@ end_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *window, int h, int w if (textpad != NULL) delwin(textpad); - delwin(window); + delwin(widget); if (conf->shadow) delwin(shadow); @@ -774,4 +965,4 @@ end_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *window, int h, int w *conf->get_height = h; if (conf->get_width != NULL) *conf->get_width = w; -} +}
\ No newline at end of file diff --git a/lib/lib_util.h b/lib/lib_util.h index e9791b1894a7..a3ed2508cd49 100644 --- a/lib/lib_util.h +++ b/lib/lib_util.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,21 +28,10 @@ #ifndef _LIBBSDDIALOG_UTIL_H_ #define _LIBBSDDIALOG_UTIL_H_ -/* - * Utils to implement widgets - Internal library API - Dafult values - */ - -#define HBORDER 1 -#define HBORDERS (HBORDER + HBORDER) -#define VBORDER 1 -#define VBORDERS (VBORDER + VBORDER) -#define PADDING(p) (p) - -/* ncurses has not a Ctrl key macro */ -#define KEY_CTRL(x) ((x) & 0x1f) - -/* Set default aspect ratio to 9 */ -#define GET_ASPECT_RATIO(conf) (conf->aspect_ratio > 0 ? conf->aspect_ratio : 9) +#define HBORDERS 2 +#define VBORDERS 2 +#define TEXTHMARGIN 1 +#define TEXTHMARGINS (TEXTHMARGIN + TEXTHMARGIN) /* debug */ #define BSDDIALOG_DEBUG(y,x,fmt, ...) do { \ @@ -56,36 +45,29 @@ void set_error_string(char *string); #define RETURN_ERROR(str) do { \ set_error_string(str); \ - return BSDDIALOG_ERROR; \ + return (BSDDIALOG_ERROR); \ } while (0) -/* Buttons */ -#define LABEL_cancel_label "Cancel" -#define LABEL_exit_label "EXIT" -#define LABEL_extra_label "Extra" -#define LABEL_help_label "Help" -#define LABEL_ok_label "OK" -#define BUTTONLABEL(l) (conf->button.l != NULL ? conf->button.l : LABEL_ ##l) - -#define MAXBUTTONS 6 /* yes|ok + extra + no|cancel + help + 2 generics */ +/* buttons */ struct buttons { unsigned int nbuttons; - char *label[MAXBUTTONS]; +#define MAXBUTTONS 6 /* ok + extra + cancel + help + 2 generics */ + const char *label[MAXBUTTONS]; int value[MAXBUTTONS]; int curr; unsigned int sizebutton; /* including left and right delimiters */ }; +#define BUTTON_OK_LABEL "OK" +#define BUTTON_CANCEL_LABEL "Cancel" void get_buttons(struct bsddialog_conf *conf, struct buttons *bs, char *yesoklabel, - char *extralabel, char *nocancellabel, char *helplabel); + char *nocancellabel); void -draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected, - bool shortkey); +draw_buttons(WINDOW *window, struct buttons bs, bool shortcut); -void -draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey); +bool shortcut_buttons(int key, struct buttons *bs); /* help window with F1 key */ int f1help(struct bsddialog_conf *conf); @@ -94,24 +76,32 @@ int f1help(struct bsddialog_conf *conf); int hide_widget(int y, int x, int h, int w, bool withshadow); /* (auto) size and (auto) position */ +#define SCREENLINES (getmaxy(stdscr)) +#define SCREENCOLS (getmaxx(stdscr)) + int -get_text_properties(struct bsddialog_conf *conf, char *text, int *maxword, - int *maxline, int *nlines); +text_size(struct bsddialog_conf *conf, int rows, int cols, const char *text, + struct buttons *bs, int rowsnotext, int startwtext, int *htext, int *wtext); int widget_max_height(struct bsddialog_conf *conf); int widget_max_width(struct bsddialog_conf *conf); int -set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w); +widget_min_height(struct bsddialog_conf *conf, int htext, int minwidget, + bool withbuttons); int -set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w); +widget_min_width(struct bsddialog_conf *conf, int wtext, int minwidget, + struct buttons *bs); + +int +set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, + int *w); -/* widget builders */ int -print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols, - char *text); +set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w); +/* widget builders */ enum elevation { RAISED, LOWERED }; void @@ -123,17 +113,17 @@ new_boxed_window(struct bsddialog_conf *conf, int y, int x, int rows, int cols, enum elevation elev); int -new_widget_withtextpad(struct bsddialog_conf *conf, WINDOW **shadow, - WINDOW **widget, int y, int x, int h, int w, enum elevation elev, - WINDOW **textpad, int *htextpad, char *text, bool buttons); +new_dialog(struct bsddialog_conf *conf, WINDOW **shadow, WINDOW **widget, int y, + int x, int h, int w, WINDOW **textpad, const char *text, struct buttons *bs, + bool shortcutbuttons); int -update_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *shadow, - WINDOW *widget, int h, int w, enum elevation elev, WINDOW *textpad, - int *htextpad, char *text, bool buttons); +update_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, + int y, int x, int h, int w, WINDOW *textpad, const char *text, + struct buttons *bs, bool shortcutbuttons); void -end_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *window, int h, int w, - WINDOW *textpad, WINDOW *shadow); +end_dialog(struct bsddialog_conf *conf, WINDOW *shadow, WINDOW *widget, + WINDOW *textpad); -#endif +#endif
\ No newline at end of file diff --git a/lib/libbsddialog.c b/lib/libbsddialog.c index aea3b152adfd..65134eabe5f3 100644 --- a/lib/libbsddialog.c +++ b/lib/libbsddialog.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,43 +25,26 @@ * SUCH DAMAGE. */ -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" - -/* - * This file implements public functions not related to a specific dialog. - * lib_utils.h/c: private functions to implement the library. - * theme.h/c: public API related to themes. - * Dialogs implementation: - * infobox.c infobox - * messgebox.c msgbox - yesno - * menubox.c buildlist - checklist - menu - mixedlist - radiolist - * formbox.c inputbox - passwordbox - form - passwordform - mixedform - * barbox.c gauge - mixedgauge - rangebox - pause - progressview - * textbox.c textbox - * timebox.c timebox - calendar - */ +#include "lib_util.h" extern struct bsddialog_theme t; int bsddialog_init(void) { int i, j, c, error; + enum bsddialog_default_theme theme; set_error_string(""); - if(initscr() == NULL) - RETURN_ERROR("Cannot init ncurses (initscr)"); + if (initscr() == NULL) + RETURN_ERROR("Cannot init curses (initscr)"); error = OK; error += keypad(stdscr, TRUE); @@ -69,24 +52,25 @@ int bsddialog_init(void) error += cbreak(); error += noecho(); curs_set(0); - if(error != OK) { + if (error != OK) { bsddialog_end(); - RETURN_ERROR("Cannot init ncurses (keypad and cursor)"); + RETURN_ERROR("Cannot init curses (keypad and cursor)"); } c = 1; error += start_color(); - for (i=0; i<8; i++) - for(j=0; j<8; j++) { + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) { error += init_pair(c, i, j); c++; } - if(error != OK) { - bsddialog_end(); - RETURN_ERROR("Cannot init ncurses (colors)"); - } - if (bsddialog_set_default_theme(BSDDIALOG_THEME_DEFAULT) != 0) { + if (error == OK) + theme = BSDDIALOG_THEME_DEFAULT; + else + theme = BSDDIALOG_THEME_BLACKWHITE; + + if (bsddialog_set_default_theme(theme) != 0) { bsddialog_end(); return (BSDDIALOG_ERROR); } @@ -97,16 +81,17 @@ int bsddialog_init(void) int bsddialog_end(void) { if (endwin() != OK) - RETURN_ERROR("Cannot end ncurses (endwin)"); + RETURN_ERROR("Cannot end curses (endwin)"); return (BSDDIALOG_OK); } -int bsddialog_backtitle(struct bsddialog_conf *conf, char *backtitle) +int bsddialog_backtitle(struct bsddialog_conf *conf, const char *backtitle) { mvaddstr(0, 1, backtitle); if (conf->no_lines != true) - mvhline(1, 1, conf->ascii_lines ? '-' : ACS_HLINE, COLS-2); + mvhline(1, 1, conf->ascii_lines ? '-' : ACS_HLINE, + SCREENCOLS - 2); refresh(); @@ -140,4 +125,4 @@ int bsddialog_clearterminal(void) refresh(); return (BSDDIALOG_OK); -} +}
\ No newline at end of file diff --git a/lib/menubox.c b/lib/menubox.c index c9fb182422ea..0d8e3b14521c 100644 --- a/lib/menubox.c +++ b/lib/menubox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,19 +28,13 @@ #include <sys/param.h> #include <ctype.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> +#include <stdlib.h> #include <string.h> - #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" - -/* "Menu": checklist - menu - mixedlist - radiolist - buildlist */ +#include "lib_util.h" #define DEPTHSPACE 4 #define MIN_HEIGHT VBORDERS + 6 /* 2 buttons 1 text 3 menu */ @@ -48,7 +42,6 @@ extern struct bsddialog_theme t; enum menumode { - BUILDLISTMODE, CHECKLISTMODE, MENUMODE, MIXEDLISTMODE, @@ -69,267 +62,152 @@ struct lineposition { unsigned int line; }; -static int checkradiolist(int nitems, struct bsddialog_menuitem *items) -{ - int i, error; - - error = 0; - for (i=0; i<nitems; i++) { - if (error > 0) - items[i].on = false; - - if (items[i].on == true) - error++; - } - - return (error == 0 ? 0 : -1); -} - -static int checkmenu(int nitems, struct bsddialog_menuitem *items) // useful? -{ - int i, error; - - error = 0; - for (i=0; i<nitems; i++) { - if (items[i].on == true) - error++; - - items[i].on = false; - } - - return (error == 0 ? 0 : -1); -} +struct privateitem { + bool on; + int group; + int index; + enum menumode type; + struct bsddialog_menuitem *item; +}; static void -getfirst(int ngroups, struct bsddialog_menugroup *groups, int *abs, int *group, - int *rel) +set_on_output(struct bsddialog_conf *conf, int output, int ngroups, + struct bsddialog_menugroup *groups, struct privateitem *pritems) { - int i, a; + int i, j, abs; + + if (output != BSDDIALOG_OK && !conf->menu.on_without_ok) + return; - *abs = *rel = *group = -1; - a = 0; - for (i=0; i<ngroups; i++) { + for(i = abs = 0; i < ngroups; i++) { if (groups[i].type == BSDDIALOG_SEPARATOR) { - a += groups[i].nitems; + abs += groups[i].nitems; continue; } - if (groups[i].nitems != 0) { - *group = i; - *abs = a; - *rel = 0; - break; + + for(j = 0; j < (int)groups[i].nitems; j++) { + groups[i].items[j].on = pritems[abs].on; + abs++; } } } -static void -getfirst_with_default(struct bsddialog_conf *conf, int ngroups, - struct bsddialog_menugroup *groups, int *abs, int *group, int *rel) +static int getprev(struct privateitem *pritems, int abs) { - int i, j, a; - struct bsddialog_menuitem *item; - - getfirst(ngroups, groups, abs, group, rel); - if (*abs < 0) - return; - - a = *abs; + int i; - for (i=*group; i<ngroups; i++) { - if (groups[i].type == BSDDIALOG_SEPARATOR) { - a += groups[i].nitems; + for (i = abs - 1; i >= 0; i--) { + if (pritems[i].type == SEPARATORMODE) continue; - } - for (j = 0; j < (int) groups[i].nitems; j++) { - item = &groups[i].items[j]; - if (conf->menu.default_item != NULL && item->name != NULL) { - if (strcmp(item->name, conf->menu.default_item) == 0) { - *abs = a; - *group = i; - *rel = j; - return; - } - } - a++; - } + return (i); } + + return (abs); } -static void -getlast(int totnitems, int ngroups, struct bsddialog_menugroup *groups, - int *abs, int *group, int *rel) +static int getnext(int npritems, struct privateitem *pritems, int abs) { - int i, a; + int i; - a = totnitems - 1; - for (i = ngroups-1; i>=0; i--) { - if (groups[i].type == BSDDIALOG_SEPARATOR) { - a -= groups[i].nitems; + for (i = abs + 1; i < npritems; i++) { + if (pritems[i].type == SEPARATORMODE) continue; - } - if (groups[i].nitems != 0) { - *group = i; - *abs = a; - *rel = groups[i].nitems - 1; - break; - } + return (i); } + + return (abs); } -static void -getnext(int ngroups, struct bsddialog_menugroup *groups, int *abs, int *group, - int *rel) +static int +getfirst_with_default(int npritems, struct privateitem *pritems, int ngroups, + struct bsddialog_menugroup *groups, int *focusgroup, int *focusitem) { - int i, a; - - if (*abs < 0 || *group < 0 || *rel < 0) - return; - - if (*rel + 1 < (int) groups[*group].nitems) { - *rel = *rel + 1; - *abs = *abs + 1; - return; + int i, abs; + + if ((abs = getnext(npritems, pritems, -1)) < 0) + return (abs); + + if (focusgroup == NULL || focusitem == NULL) + return (abs); + if (*focusgroup < 0 || *focusgroup >= ngroups) + return (abs); + if (groups[*focusgroup].type == BSDDIALOG_SEPARATOR) + return (abs); + if (*focusitem < 0 || *focusitem >= (int)groups[*focusgroup].nitems) + return (abs); + + for (i = abs; i < npritems; i++) { + if (pritems[i].group == *focusgroup && + pritems[i].index == *focusitem) + return (i); } - if (*group + 1 > ngroups) - return; - - a = *abs; - for (i = *group + 1; i < ngroups; i++) { - if (groups[i].type == BSDDIALOG_SEPARATOR) { - a += groups[i].nitems; - continue; - } - if (groups[i].nitems != 0) { - *group = i; - *abs = a + 1; - *rel = 0; - break; - } - } + return (abs); } -static void -getfastnext(int menurows, int ngroups, struct bsddialog_menugroup *groups, - int *abs, int *group, int *rel) +static int +getfastnext(int menurows, int npritems, struct privateitem *pritems, int abs) { int a, start, i; - start = *abs; + start = abs; i = menurows; do { - a = *abs; - getnext(ngroups, groups, abs, group, rel); + a = abs; + abs = getnext(npritems, pritems, abs); i--; - } while (*abs != a && *abs < start + menurows && i > 0); -} - -static void -getprev(struct bsddialog_menugroup *groups, int *abs, int *group, int *rel) -{ - int i, a; - - if (*abs < 0 || *group < 0 || *rel < 0) - return; - - if (*rel > 0) { - *rel = *rel - 1; - *abs = *abs - 1; - return; - } - - if (*group - 1 < 0) - return; + } while (abs != a && abs < start + menurows && i > 0); - a = *abs; - for (i = *group - 1; i >= 0; i--) { - if (groups[i].type == BSDDIALOG_SEPARATOR) { - a -= (int) groups[i].nitems; - continue; - } - if (groups[i].nitems != 0) { - *group = i; - *abs = a - 1; - *rel = (int) groups[i].nitems - 1; - break; - } - } + return (abs); } -static void -getfastprev(int menurows, struct bsddialog_menugroup *groups, int *abs, - int *group, int *rel) +static int +getfastprev(int menurows, struct privateitem *pritems, int abs) { int a, start, i; - start = *abs; + start = abs; i = menurows; do { - a = *abs; - getprev(groups, abs, group, rel); + a = abs; + abs = getprev(pritems, abs); i--; - } while (*abs != a && *abs > start - menurows && i > 0); + } while (abs != a && abs > start - menurows && i > 0); + + return (abs); } -static bool -getnextshortcut(struct bsddialog_conf *conf, enum menumode mode, int ngroups, - struct bsddialog_menugroup *groups, int *abs, int *group, int *rel, - int key) +static int +getnextshortcut(struct bsddialog_conf *conf, int npritems, + struct privateitem *pritems, int abs, int key) { - int i, j, a, ch, ng, nr, na; - bool mainloop; - - if (*abs < 0 || ngroups < 0 || *rel < 0 || mode == BUILDLISTMODE) - return false; + int i, ch, next; - na = a = -1; - mainloop = true; - for (i = 0; i < ngroups && mainloop; i++) { - if (groups[i].type == BSDDIALOG_SEPARATOR) { - a += groups[i].nitems; + next = -1; + for (i = 0; i < npritems; i++) { + if (pritems[i].type == SEPARATORMODE) continue; - } - for (j = 0; j < (int)groups[i].nitems; j++) { - a++; - if (a == *abs) - continue; - if (conf->menu.no_name) - ch = groups[i].items[j].desc[0]; - else - ch = groups[i].items[j].name[0]; - - if (ch == key) { - if (a < *abs && na == -1) { - na = a; - ng = i; - nr = j; - } - if (a > *abs) { - na = a; - ng = i; - nr = j; - mainloop = false; - break; - } - } - } - } + if (conf->menu.no_name) + ch = pritems[i].item->desc[0]; + else + ch = pritems[i].item->name[0]; + + if (ch == key) { + if (i > abs) + return (i); - if (na != -1) { - *abs = na; - *group = ng; - *rel = nr; - return (true); + if (i < abs && next == -1) + next = i; + } } - return (false); + return (next != -1 ? next : abs); } static enum menumode getmode(enum menumode mode, struct bsddialog_menugroup group) { - if (mode == MIXEDLISTMODE) { if (group.type == BSDDIALOG_SEPARATOR) mode = SEPARATORMODE; @@ -339,16 +217,25 @@ getmode(enum menumode mode, struct bsddialog_menugroup group) mode = CHECKLISTMODE; } - return mode; + return (mode); } static void drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y, - struct bsddialog_menuitem item, enum menumode mode, struct lineposition pos, - bool curr) + struct lineposition pos, struct privateitem *pritem, bool focus) { int colordesc, colorname, colorshortcut, linech; - char *shortcut; + unsigned int depth; + enum menumode mode; + const char *prefix, *name, *desc, *bottomdesc, *shortcut; + + prefix = pritem->item->prefix; + name = pritem->item->name; + depth = pritem->item->depth; + desc = pritem->item->desc; + bottomdesc = pritem->item->bottomdesc; + + mode = pritem->type; if (mode == SEPARATORMODE) { if (conf->no_lines == false) { @@ -357,140 +244,132 @@ drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y, mvwhline(pad, y, 0, linech, pos.line); wattroff(pad, t.menu.desccolor); } - wmove(pad, y, pos.line/2 - (strlen(item.name)+strlen(item.desc))/2); + wmove(pad, y, + pos.line/2 - (strlen(name) + strlen(desc)) / 2 ); wattron(pad, t.menu.namesepcolor); - waddstr(pad, item.name); + waddstr(pad, name); wattroff(pad, t.menu.namesepcolor); - if (strlen(item.name) > 0 && strlen(item.desc) > 0) + if (strlen(name) > 0 && strlen(desc) > 0) waddch(pad, ' '); wattron(pad, t.menu.descsepcolor); - waddstr(pad, item.desc); + waddstr(pad, desc); wattroff(pad, t.menu.descsepcolor); return; } /* prefix */ - if (item.prefix != NULL && item.prefix[0] != '\0') - mvwaddstr(pad, y, 0, item.prefix); + if (prefix != NULL && prefix[0] != '\0') + mvwaddstr(pad, y, 0, prefix); /* selector */ wmove(pad, y, pos.xselector); wattron(pad, t.menu.selectorcolor); if (mode == CHECKLISTMODE) - wprintw(pad, "[%c]", item.on ? 'X' : ' '); + wprintw(pad, "[%c]", pritem->on ? 'X' : ' '); if (mode == RADIOLISTMODE) - wprintw(pad, "(%c)", item.on ? '*' : ' '); + wprintw(pad, "(%c)", pritem->on ? '*' : ' '); wattroff(pad, t.menu.selectorcolor); /* name */ - colorname = curr ? t.menu.f_namecolor : t.menu.namecolor; - if (mode != BUILDLISTMODE && conf->menu.no_name == false) { + 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 * DEPTHSPACE, item.name); + mvwaddstr(pad, y, pos.xname + depth * DEPTHSPACE, name); wattroff(pad, colorname); } /* description */ - if (mode == BUILDLISTMODE) { - if (curr == false) - colordesc = item.on ? t.menu.namecolor : t.menu.desccolor; - else - colordesc = t.menu.f_namecolor; - } - else { - if (conf->menu.no_name) - colordesc = curr ? t.menu.f_namecolor : t.menu.namecolor; - else - colordesc = curr ? t.menu.f_desccolor : t.menu.desccolor; - } - if (mode == BUILDLISTMODE || conf->menu.no_desc == false) { + if (conf->menu.no_name) + colordesc = focus ? t.menu.f_namecolor : t.menu.namecolor; + else + colordesc = focus ? t.menu.f_desccolor : t.menu.desccolor; + + if (conf->menu.no_desc == false) { wattron(pad, colordesc); if (conf->menu.no_name) - mvwaddstr(pad, y, pos.xname + item.depth * DEPTHSPACE, item.desc); + mvwaddstr(pad, y, pos.xname + depth * DEPTHSPACE, desc); else - mvwaddstr(pad, y, pos.xdesc, item.desc); + mvwaddstr(pad, y, pos.xdesc, desc); wattroff(pad, colordesc); } /* shortcut */ - if (mode != BUILDLISTMODE && conf->menu.shortcut_buttons == false) { - colorshortcut = curr ? t.menu.f_shortcutcolor : t.menu.shortcutcolor; + if (conf->menu.shortcut_buttons == false) { + colorshortcut = focus ? + t.menu.f_shortcutcolor : t.menu.shortcutcolor; wattron(pad, colorshortcut); if (conf->menu.no_name) - shortcut = item.desc; + shortcut = desc; else - shortcut = item.name; - wmove(pad, y, pos.xname + item.depth * DEPTHSPACE); + shortcut = name; + wmove(pad, y, pos.xname + depth * DEPTHSPACE); if (shortcut != NULL && shortcut[0] != '\0') waddch(pad, shortcut[0]); wattroff(pad, colorshortcut); -} + } /* bottom description */ - move(LINES-1, 2); + move(SCREENLINES - 1, 2); clrtoeol(); - if (item.bottomdesc != NULL) { - addstr(item.bottomdesc); + if (bottomdesc != NULL && focus) { + addstr(bottomdesc); refresh(); } } -static void +static int menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, - char *text, int linelen, unsigned int *menurows, int nitems, + const char *text, int linelen, unsigned int *menurows, int nitems, struct buttons bs) { - int textrow, menusize; - - textrow = text != NULL && strlen(text) > 0 ? 1 : 0; - - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += bs.nbuttons * bs.sizebutton; - *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* line size */ - *w = MAX(*w, linelen + 6); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* - * avoid terminal overflow, - * -1 fix false negative with big menu over the terminal and - * autosize, for example "portconfig /usr/ports/www/apache24/". - */ - *w = MIN(*w, widget_max_width(conf)-1); + int htext, wtext, menusize, notext; + + notext = 2; + if (*menurows == BSDDIALOG_AUTOSIZE) { + /* algo 1): grows vertically */ + /* notext = 1; */ + /* algo 2): grows horizontally, better with little terminals */ + notext += nitems; + notext = MIN(notext, widget_max_height(conf) - HBORDERS - 3); + } else + notext += *menurows; + + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, &bs, notext, linelen + 6, + &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } - if (rows == BSDDIALOG_AUTOSIZE) { - *h = HBORDERS + 2 /* buttons */ + textrow; + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, linelen + 6, &bs); + if (rows == BSDDIALOG_AUTOSIZE) { if (*menurows == 0) { - *h += nitems + 2; - *h = MIN(*h, widget_max_height(conf)); - menusize = MIN(nitems + 2, *h - (HBORDERS + 2 + textrow)); - menusize -=2; - *menurows = menusize < 0 ? 0 : menusize; + 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 a fixed menurows */ - *h = *h + *menurows + 2; - - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); - /* avoid menurows overflow */ - /* manual: with rows=autosize menurows!=0 is maxmenurows */ - *menurows = MIN(*h - 6 - textrow, (int)*menurows); - } - else { + 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) - *menurows = MIN(rows-6-textrow, nitems); + *menurows = MIN(rows-6-htext, nitems); } + + return (0); } static int -menu_checksize(int rows, int cols, char *text, int menurows, int nitems, +menu_checksize(int rows, int cols, const char *text, int menurows, int nitems, struct buttons bs) { int mincols, textrow, menusize; @@ -499,24 +378,27 @@ menu_checksize(int rows, int cols, char *text, int menurows, int nitems, /* buttons */ mincols += bs.nbuttons * bs.sizebutton; mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* line, comment to permet some cols hidden */ + /* + * linelen check, comment to allow some hidden col otherwise portconfig + * could not show big menus like www/apache24 + */ /* mincols = MAX(mincols, linelen); */ if (cols < mincols) - RETURN_ERROR("Few cols, width < size buttons or "\ - "name+descripion of the items"); + RETURN_ERROR("Few cols, width < size buttons or " + "name + descripion of the items"); textrow = text != NULL && strlen(text) > 0 ? 1 : 0; if (nitems > 0 && menurows == 0) - RETURN_ERROR("items > 0 but menurows == 0, probably terminal "\ + RETURN_ERROR("items > 0 but menurows == 0, probably terminal " "too small"); menusize = nitems > 0 ? 3 : 0; if (rows < 2 + 2 + menusize + textrow) RETURN_ERROR("Few lines for this menus"); - return 0; + return (0); } /* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */ @@ -524,7 +406,6 @@ static void update_menuwin(struct bsddialog_conf *conf, WINDOW *menuwin, int h, int w, int totnitems, unsigned int menurows, int ymenupad) { - draw_borders(conf, menuwin, h, w, LOWERED); if (totnitems > (int) menurows) { @@ -544,36 +425,30 @@ update_menuwin(struct bsddialog_conf *conf, WINDOW *menuwin, int h, int w, } static int -do_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, enum menumode mode, int ngroups, +do_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, int cols, + unsigned int menurows, enum menumode mode, unsigned int ngroups, struct bsddialog_menugroup *groups, int *focuslist, int *focusitem) { + bool loop, onetrue, movefocus, automenurows, shortcut_butts; + int i, j, y, x, h, w, output, input; + int ymenupad, ys, ye, xs, xe, abs, next, totnitems; WINDOW *shadow, *widget, *textpad, *menuwin, *menupad; - int i, j, y, x, h, w, htextpad, output, input; - int ymenupad, ys, ye, xs, xe, abs, g, rel, totnitems; - bool loop, automenurows, shortcut_buttons; struct buttons bs; - struct bsddialog_menuitem *item; - enum menumode currmode; struct lineposition pos = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + struct bsddialog_menuitem *item; + struct privateitem *pritems; - shortcut_buttons = conf->menu.shortcut_buttons; + shortcut_butts = conf->menu.shortcut_buttons; automenurows = menurows == BSDDIALOG_AUTOSIZE ? true : false; totnitems = 0; - for (i=0; i < ngroups; i++) { - currmode = getmode(mode, groups[i]); - if (currmode == RADIOLISTMODE) - checkradiolist(groups[i].nitems, groups[i].items); - - if (currmode == MENUMODE) - checkmenu(groups[i].nitems, groups[i].items); - - if (currmode == RADIOLISTMODE || currmode == CHECKLISTMODE) + for (i = 0; i < (int)ngroups; i++) { + if (getmode(mode, groups[i]) == RADIOLISTMODE || + getmode(mode, groups[i]) == CHECKLISTMODE) pos.selectorlen = 3; - for (j=0; j < (int) groups[i].nitems; j++) { + for (j = 0; j < (int)groups[i].nitems; j++) { totnitems++; item = &groups[i].items[j]; @@ -583,7 +458,7 @@ do_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, continue; } - pos.maxprefix = MAX(pos.maxprefix, strlen(item->prefix)); + pos.maxprefix = MAX(pos.maxprefix,strlen(item->prefix)); pos.maxdepth = MAX(pos.maxdepth, item->depth); pos.maxname = MAX(pos.maxname, strlen(item->name)); pos.maxdesc = MAX(pos.maxdesc, strlen(item->desc)); @@ -594,30 +469,33 @@ do_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, pos.maxdepth *= DEPTHSPACE; pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0); - pos.xname = pos.xselector + pos.selectorlen + (pos.selectorlen > 0 ? 1 : 0); + pos.xname = pos.xselector + pos.selectorlen + + (pos.selectorlen > 0 ? 1 : 0); pos.xdesc = pos.maxdepth + pos.xname + pos.maxname; pos.xdesc += (pos.maxname != 0 ? 1 : 0); pos.line = MAX(pos.maxsepstr + 3, pos.xdesc + pos.maxdesc); - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - menu_autosize(conf, rows, cols, &h, &w, text, pos.line, &menurows, - totnitems, bs); + return (BSDDIALOG_ERROR); + if (menu_autosize(conf, rows, cols, &h, &w, text, pos.line, &menurows, + totnitems, bs) != 0) + return (BSDDIALOG_ERROR); if (menu_checksize(h, w, text, menurows, totnitems, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + shortcut_butts) != 0) + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; + doupdate(); - prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, - y + h - menurows, x + 1 + w - t.text.hmargin); + prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, + y + h - menurows, x + 1 + w - TEXTHMARGIN); menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2, menurows+2, w-4, LOWERED); @@ -625,138 +503,143 @@ do_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, menupad = newpad(totnitems, pos.line); wbkgd(menupad, t.dialog.color); - ymenupad = 0; - for (i=0; i<ngroups; i++) { - currmode = getmode(mode, groups[i]); - for (j=0; j < (int) groups[i].nitems; j++) { + if ((pritems = calloc(totnitems, sizeof (struct privateitem))) == NULL) + RETURN_ERROR("Cannot allocate memory for internal menu items"); + + abs = 0; + for (i = 0; i < (int)ngroups; i++) { + onetrue = false; + for (j = 0; j < (int)groups[i].nitems; j++) { item = &groups[i].items[j]; - drawitem(conf, menupad, ymenupad, *item, currmode, pos, - false); - ymenupad++; + + if (getmode(mode, groups[i]) == MENUMODE) { + pritems[abs].on = false; + } else if (getmode(mode, groups[i]) == RADIOLISTMODE) { + pritems[abs].on = onetrue ? false : item->on; + if (pritems[abs].on) + onetrue = true; + } else { + pritems[abs].on = item->on; + } + pritems[abs].group = i; + pritems[abs].index = j; + pritems[abs].type = getmode(mode, groups[i]); + pritems[abs].item = item; + + drawitem(conf, menupad, abs, pos, &pritems[abs], false); + abs++; } } - getfirst_with_default(conf, ngroups, groups, &abs, &g, &rel); - currmode = getmode(mode, groups[g]); - item = &groups[g].items[rel]; - drawitem(conf, menupad, abs, *item, currmode, pos, true); + abs = getfirst_with_default(totnitems, pritems, ngroups, groups, + focuslist, focusitem); + if (abs >= 0) + drawitem(conf, menupad, abs, pos, &pritems[abs], true); ys = y + h - 5 - menurows + 1; ye = y + h - 5 ; if (conf->menu.align_left || (int)pos.line > w - 6) { xs = x + 3; xe = xs + w - 7; - } - else { /* center */ + } else { /* center */ xs = x + 3 + (w-6)/2 - pos.line/2; xe = xs + w - 5; } - ymenupad = 0; /* now ymenupad is pminrow for prefresh() */ + ymenupad = 0; if ((int)(ymenupad + menurows) - 1 < abs) ymenupad = abs - menurows + 1; - update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, menurows, ymenupad); + update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, menurows, + ymenupad); wrefresh(menuwin); prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); - - draw_buttons(widget, h-2, w, bs, shortcut_buttons); - wrefresh(widget); + movefocus = false; loop = true; - while(loop) { + while (loop) { input = getch(); switch(input) { case KEY_ENTER: case 10: /* Enter */ output = bs.value[bs.curr]; - if (currmode == MENUMODE) - item->on = true; + if (abs >= 0 && pritems[abs].type == MENUMODE) + pritems[abs].on = true; + set_on_output(conf, output, ngroups, groups, pritems); loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + if (abs >= 0 && pritems[abs].type == MENUMODE) + pritems[abs].on = true; + set_on_output(conf, output, ngroups, groups, + pritems); + loop = false; + } break; case '\t': /* TAB */ bs.curr = (bs.curr + 1) % bs.nbuttons; - draw_buttons(widget, h-2, w, bs, shortcut_buttons); + draw_buttons(widget, bs, shortcut_butts); wrefresh(widget); break; case KEY_LEFT: if (bs.curr > 0) { bs.curr--; - draw_buttons(widget, h-2, w, bs, shortcut_buttons); + draw_buttons(widget, bs, shortcut_butts); wrefresh(widget); } break; case KEY_RIGHT: if (bs.curr < (int) bs.nbuttons - 1) { bs.curr++; - draw_buttons(widget, h-2, w, bs, shortcut_buttons); + draw_buttons(widget, bs, shortcut_butts); wrefresh(widget); } break; - case KEY_CTRL('E'): /* add conf->menu.extrahelpkey ? */ case KEY_F(1): if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; - /* No break! the terminal size can change */ + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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; + return (BSDDIALOG_ERROR); menurows = automenurows ? 0 : menurows; - menu_autosize(conf, rows, cols, &h, &w, text, pos.line, - &menurows, totnitems, bs); - if (menu_checksize(h, w, text, menurows, totnitems, bs) != 0) - return BSDDIALOG_ERROR; + if (menu_autosize(conf, rows, cols, &h, &w, text, + pos.line, &menurows, totnitems, bs) != 0) + return (BSDDIALOG_ERROR); + if (menu_checksize(h, w, text, menurows, totnitems, + bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); - - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); + return (BSDDIALOG_ERROR); - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); + if (update_dialog(conf, shadow, widget, y, x, h, w, + textpad, text, &bs, shortcut_butts) != 0) + return (BSDDIALOG_ERROR); - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - draw_buttons(widget, h-2, w, bs, shortcut_buttons); - wrefresh(widget); + doupdate(); - prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, - y + h - menurows, x + 1 + w - t.text.hmargin); + prefresh(textpad, 0, 0, y + 1, x + 1 + TEXTHMARGIN, + y + h - menurows, x + 1 + w - TEXTHMARGIN); wclear(menuwin); mvwin(menuwin, y + h - 5 - menurows, x + 2); wresize(menuwin,menurows+2, w-4); - update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, - menurows, ymenupad); + update_menuwin(conf, menuwin, menurows+2, w-4, + totnitems, menurows, ymenupad); wrefresh(menuwin); - + ys = y + h - 5 - menurows + 1; ye = y + h - 5 ; if (conf->menu.align_left || (int)pos.line > w - 6) { xs = x + 3; xe = xs + w - 7; - } - else { /* center */ + } else { /* center */ xs = x + 3 + (w-6)/2 - pos.line/2; xe = xs + w - 5; } @@ -774,385 +657,153 @@ do_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, continue; switch(input) { case KEY_HOME: + next = getnext(totnitems, pritems, -1); + movefocus = next != abs; + break; case KEY_UP: + next = getprev(pritems, abs); + movefocus = next != abs; + break; case KEY_PPAGE: - if (abs == 0) /* useless, just to save cpu refresh */ - break; - drawitem(conf, menupad, abs, *item, currmode, pos, false); - if (input == KEY_HOME) - getfirst(ngroups, groups, &abs, &g, &rel); - else if (input == KEY_UP) - getprev(groups, &abs, &g, &rel); - else /* input == KEY_PPAGE*/ - getfastprev(menurows, groups, &abs, &g, &rel); - item = &groups[g].items[rel]; - currmode= getmode(mode, groups[g]); - drawitem(conf, menupad, abs, *item, currmode, pos, true); - if (ymenupad > abs && ymenupad > 0) - ymenupad = abs; - update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, - menurows, ymenupad); - wrefresh(menuwin); - prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); + next = getfastprev(menurows, pritems, abs); + movefocus = next != abs; break; case KEY_END: + next = getprev(pritems, totnitems); + movefocus = next != abs; + break; case KEY_DOWN: + next = getnext(totnitems, pritems, abs); + movefocus = next != abs; + break; case KEY_NPAGE: - if (abs == totnitems -1) - break; /* useless, just to save cpu refresh */ - drawitem(conf, menupad, abs, *item, currmode, pos, false); - if (input == KEY_END) - getlast(totnitems, ngroups, groups, &abs, &g, &rel); - else if (input == KEY_DOWN) - getnext(ngroups, groups, &abs, &g, &rel); - else /* input == KEY_NPAGE*/ - getfastnext(menurows, ngroups, groups, &abs, &g, &rel); - item = &groups[g].items[rel]; - currmode= getmode(mode, groups[g]); - drawitem(conf, menupad, abs, *item, currmode, pos, true); - if ((int)(ymenupad + menurows) <= abs) - ymenupad = abs - menurows + 1; - update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, - menurows, ymenupad); - wrefresh(menuwin); - prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); + next = getfastnext(menurows, totnitems, pritems, abs); + movefocus = next != abs; break; case ' ': /* Space */ - if (currmode == MENUMODE) + if (pritems[abs].type == MENUMODE) break; - else if (currmode == CHECKLISTMODE) - item->on = !item->on; + else if (pritems[abs].type == CHECKLISTMODE) + pritems[abs].on = !pritems[abs].on; else { /* RADIOLISTMODE */ - for (i=0; i < (int) groups[g].nitems; i++) - if (groups[g].items[i].on == true && i != rel) { - groups[g].items[i].on = false; - drawitem(conf, menupad, - abs - rel + i, groups[g].items[i], - currmode, pos, false); + for (i = abs - pritems[abs].index; + i < totnitems && + pritems[i].group == pritems[abs].group; + i++) { + if (i != abs && pritems[i].on) { + pritems[i].on = false; + drawitem(conf, menupad, i, pos, + &pritems[i], false); } - item->on = !item->on; + } + pritems[abs].on = !pritems[abs].on; } - drawitem(conf, menupad, abs, *item, currmode, pos, true); + drawitem(conf, menupad, abs, pos, &pritems[abs], true); prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); + break; default: - if (shortcut_buttons) { - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower((bs.label[i])[0])) { - output = bs.value[i]; - if (currmode == MENUMODE) - item->on = true; - loop = false; - } + if (shortcut_butts) { + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + if (pritems[abs].type == MENUMODE) + pritems[abs].on = true; + set_on_output(conf, output, ngroups, + groups, pritems); + loop = false; + } break; } - drawitem(conf, menupad, abs, *item, currmode, pos, false); - getnextshortcut(conf, currmode, ngroups, groups, &abs, - &g, &rel, input); - item = &groups[g].items[rel]; - currmode = getmode(mode, groups[g]); - drawitem(conf, menupad, abs, *item, currmode, pos, true); + /* shourtcut items */ + next = getnextshortcut(conf, totnitems, pritems, abs, + input); + movefocus = next != abs; + } + + if (movefocus) { + drawitem(conf, menupad, abs, pos, &pritems[abs], false); + abs = next; + drawitem(conf, menupad, abs, pos, &pritems[abs], true); if (ymenupad > abs && ymenupad > 0) ymenupad = abs; if ((int)(ymenupad + menurows) <= abs) ymenupad = abs - menurows + 1; - update_menuwin(conf, menuwin, menurows+2, w-4, totnitems, - menurows, ymenupad); + update_menuwin(conf, menuwin, menurows+2, w-4, + totnitems, menurows, ymenupad); wrefresh(menuwin); prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); + movefocus = false; } } if (focuslist != NULL) - *focuslist = g; + *focuslist = abs < 0 ? -1 : pritems[abs].group; if (focusitem !=NULL) - *focusitem = rel; + *focusitem = abs < 0 ? -1 : pritems[abs].index; delwin(menupad); delwin(menuwin); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); + free(pritems); - return output; + return (output); } -/* - * API - */ - -int bsddialog_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int ngroups, struct bsddialog_menugroup *groups, - int *focuslist, int *focusitem) +/* API */ +int +bsddialog_mixedlist(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int menurows, unsigned int ngroups, + struct bsddialog_menugroup *groups, int *focuslist, int *focusitem) { int output; output = do_mixedlist(conf, text, rows, cols, menurows, MIXEDLISTMODE, ngroups, groups, focuslist, focusitem); - return output; + return (output); } int -bsddialog_checklist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem) +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) { - int output; + int output, focuslist = 0; struct bsddialog_menugroup group = { BSDDIALOG_CHECKLIST /* unused */, nitems, items}; output = do_mixedlist(conf, text, rows, cols, menurows, CHECKLISTMODE, - 1, &group, NULL, focusitem); + 1, &group, &focuslist, focusitem); - return output; + return (output); } int -bsddialog_menu(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem) +bsddialog_menu(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int menurows, unsigned int nitems, + struct bsddialog_menuitem *items, int *focusitem) { - int output; + int output, focuslist = 0; struct bsddialog_menugroup group = { BSDDIALOG_CHECKLIST /* unused */, nitems, items}; output = do_mixedlist(conf, text, rows, cols, menurows, MENUMODE, 1, - &group, NULL, focusitem); + &group, &focuslist, focusitem); - return output; + return (output); } int -bsddialog_radiolist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem) +bsddialog_radiolist(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int menurows, unsigned int nitems, + struct bsddialog_menuitem *items, int *focusitem) { - int output; + int output, focuslist = 0; struct bsddialog_menugroup group = { BSDDIALOG_RADIOLIST /* unused */, nitems, items}; output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE, - 1, &group, NULL, focusitem); - - return output; -} - -/* todo */ -static int buildlist_autosize(int rows, int cols) -{ - - if (cols == BSDDIALOG_AUTOSIZE) - RETURN_ERROR("Unimplemented cols autosize for buildlist"); - - if (rows == BSDDIALOG_AUTOSIZE) - RETURN_ERROR("Unimplemented rows autosize for buildlist"); - - return 0; -} - -/* to improve */ -static int -buildlist_checksize(int rows, int cols, char *text, int menurows, int nitems, - struct buttons bs) -{ - int mincols, textrow, menusize; - - mincols = VBORDERS; - /* buttons */ - mincols += bs.nbuttons * bs.sizebutton; - mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* line, comment to permet some cols hidden */ - /* mincols = MAX(mincols, linelen); */ + 1, &group, &focuslist, focusitem); - if (cols < mincols) - RETURN_ERROR("Few cols, width < size buttons or "\ - "name+descripion of the items"); - - textrow = text != NULL && strlen(text) > 0 ? 1 : 0; - - if (nitems > 0 && menurows == 0) - RETURN_ERROR("items > 0 but menurows == 0, probably terminal "\ - "too small"); - - menusize = nitems > 0 ? 3 : 0; - if (rows < 2 + 2 + menusize + textrow) - RETURN_ERROR("Few lines for this menus"); - - return 0; -} - -int -bsddialog_buildlist(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int menurows, int nitems, struct bsddialog_menuitem *items, - int *focusitem) -{ - WINDOW *widget, *textpad, *leftwin, *leftpad, *rightwin, *rightpad, *shadow; - int output, i, x, y, h, w, htextpad, input; - bool loop, buttupdate, padsupdate, startleft; - int nlefts, nrights, leftwinx, rightwinx, winsy, padscols, curr; - enum side {LEFT, RIGHT} currV; - int currH; - struct buttons bs; - struct lineposition pos = {0,0,0,0,0,0,0,0,0,0}; - - startleft = false; - for (i=0; i<nitems; i++) { - pos.line = MAX(pos.line, strlen(items[i].desc)); - if (items[i].on == false) - startleft = true; - } - - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); - - if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - if (buildlist_autosize(rows, cols) != 0) - return BSDDIALOG_ERROR; - if (buildlist_checksize(h, w, text, menurows, nitems, bs) != 0) - return BSDDIALOG_ERROR; - if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin, - y + h - menurows, x + 1 + w - t.text.hmargin); - - winsy = y + h - 5 - menurows; - leftwinx = x+2; - leftwin = new_boxed_window(conf, winsy, leftwinx, menurows+2, (w-5)/2, - LOWERED); - rightwinx = x + w - 2 -(w-5)/2; - rightwin = new_boxed_window(conf, winsy, rightwinx, menurows+2, - (w-5)/2, LOWERED); - - wrefresh(leftwin); - wrefresh(rightwin); - - padscols = (w-5)/2 - 2; - leftpad = newpad(nitems, pos.line); - rightpad = newpad(nitems, pos.line); - wbkgd(leftpad, t.dialog.color); - wbkgd(rightpad, t.dialog.color); - - currH = 0; - currV = startleft ? LEFT : RIGHT; - loop = buttupdate = padsupdate = true; - while(loop) { - if (buttupdate) { - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); - buttupdate = false; - } - - if (padsupdate) { - werase(leftpad); - werase(rightpad); - curr = -1; - nlefts = nrights = 0; - for (i=0; i<nitems; i++) { - if (items[i].on == false) { - if (currV == LEFT && currH == nlefts) - curr = i; - drawitem(conf, leftpad, nlefts, items[i], - BUILDLISTMODE, pos, curr == i); - nlefts++; - } else { - if (currV == RIGHT && currH == nrights) - curr = i; - drawitem(conf, rightpad, nrights, items[i], - BUILDLISTMODE, pos, curr == i); - nrights++; - } - } - prefresh(leftpad, 0, 0, winsy+1, leftwinx+1, - winsy+1+menurows, leftwinx + 1 + padscols); - prefresh(rightpad, 0, 0, winsy+1, rightwinx+1, - winsy+1+menurows, rightwinx + 1 + padscols); - padsupdate = false; - } - - input = getch(); - switch(input) { - case KEY_ENTER: - case 10: /* Enter */ - output = bs.value[bs.curr]; - loop = false; - break; - case 27: /* Esc */ - output = BSDDIALOG_ERROR; - loop = false; - break; - case '\t': /* TAB */ - bs.curr = (bs.curr + 1) % bs.nbuttons; - buttupdate = true; - break; - } - - if (nitems <= 0) - continue; - - switch(input) { - case KEY_LEFT: - if (currV == RIGHT && nrights > 0) { - currV = LEFT; - currH = 0; - padsupdate = true; - } - break; - case KEY_RIGHT: - if (currV == LEFT && nrights > 0) { - currV = RIGHT; - currH = 0; - padsupdate = true; - } - break; - case KEY_UP: - currH = (currH > 0) ? currH - 1 : 0; - padsupdate = true; - break; - case KEY_DOWN: - if (currV == LEFT) - currH = (currH < nlefts-1) ? currH +1 : currH; - else - currH = (currH < nrights-1)? currH +1 : currH; - padsupdate = true; - break; - case ' ': /* Space */ - items[curr].on = ! items[curr].on; - if (currV == LEFT) { - if (nlefts > 1) - currH = currH > 0 ? currH-1 : 0; - else { - currH = 0; - currV = RIGHT; - } - } else { - if (nrights > 1) - currH = currH > 0 ? currH-1 : 0; - else { - currH = 0; - currV = LEFT; - } - } - padsupdate = true; - break; - default: - - break; - } - } - - if(focusitem != NULL) - *focusitem = curr; - - delwin(leftpad); - delwin(leftwin); - delwin(rightpad); - delwin(rightwin); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); - - return output; -} + return (output); +}
\ No newline at end of file diff --git a/lib/messagebox.c b/lib/messagebox.c index 6fe775cfcbc9..edea7c41c18d 100644 --- a/lib/messagebox.c +++ b/lib/messagebox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,60 +27,34 @@ #include <sys/param.h> -#include <ctype.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include <string.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" - -#define AUTO_WIDTH (COLS / 3U) -/* at least 1 line text for its pad building in widget_withtextpad_init() */ -#define MIN_HEIGHT (HBORDERS + 2 /*buttons*/ + 1 /*text*/) +#include "lib_util.h" extern struct bsddialog_theme t; static int message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, - int *w, char *text, struct buttons bs) + int *w, const char *text, struct buttons bs) { - int maxword, maxline, nlines, line; - - if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) - return BSDDIALOG_ERROR; - - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += bs.nbuttons * bs.sizebutton; - *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* text size */ - line = MIN(maxline + VBORDERS + t.text.hmargin * 2, AUTO_WIDTH); - line = MAX(line, (int) (maxword + VBORDERS + t.text.hmargin * 2)); - *w = MAX(*w, line); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* avoid terminal overflow */ - *w = MIN(*w, widget_max_width(conf)); - } + int htext, wtext; - if (rows == BSDDIALOG_AUTOSIZE) { - *h = MIN_HEIGHT - 1; - if (maxword > 0) - *h += MAX(nlines, (int)(*w / GET_ASPECT_RATIO(conf))); - *h = MAX(*h, MIN_HEIGHT); - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, &bs, 0, SCREENCOLS/2, + &htext, &wtext) != 0) + return (BSDDIALOG_ERROR); } - return 0; + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, wtext, 0, &bs); + + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, htext, 0, true); + + return (0); } static int message_checksize(int rows, int cols, struct buttons bs) @@ -92,182 +66,167 @@ static int message_checksize(int rows, int cols, struct buttons bs) mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; if (cols < mincols) - RETURN_ERROR("Few cols, Msgbox and Yesno need at least width "\ + RETURN_ERROR("Few cols, Msgbox and Yesno need at least width " "for borders, buttons and spaces between buttons"); - if (rows < MIN_HEIGHT) - RETURN_ERROR("Msgbox and Yesno need at least height 5"); + if (rows < HBORDERS + 2 /*buttons*/) + RETURN_ERROR("Msgbox and Yesno need at least height 4"); - return 0; + return (0); } static void -buttonsupdate(WINDOW *widget, int h, int w, struct buttons bs) +textupdate(WINDOW *widget, WINDOW *textpad, int htextpad, int ytextpad) { - draw_buttons(widget, h-2, w, bs, true); - wnoutrefresh(widget); -} + int y, x, h, w; + + getbegyx(widget, y, x); + getmaxyx(widget, h, w); -static void -textupdate(WINDOW *widget, int y, int x, int h, int w, WINDOW *textpad, - int htextpad, int textrow) -{ if (htextpad > h - 4) { mvwprintw(widget, h-3, w-6, "%3d%%", - 100 * (textrow+h-4)/ htextpad); + 100 * (ytextpad+h-4)/ htextpad); wnoutrefresh(widget); } - pnoutrefresh(textpad, textrow, 0, y+1, x+2, y+h-4, x+w-2); + pnoutrefresh(textpad, ytextpad, 0, y+1, x+2, y+h-4, x+w-2); } static int -do_dialog(struct bsddialog_conf *conf, char *text, int rows, int cols, +do_message(struct bsddialog_conf *conf, const char *text, int rows, int cols, struct buttons bs) { - WINDOW *widget, *textpad, *shadow; bool loop; - int i, y, x, h, w, input, output, htextpad, textrow; + int y, x, h, w, input, output, ytextpad, htextpad, unused; + WINDOW *widget, *textpad, *shadow; if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (message_checksize(h, w, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); - textrow = 0; + ytextpad = 0; + getmaxyx(textpad, htextpad, unused); + unused++; /* fix unused error */ + textupdate(widget, textpad, htextpad, ytextpad); loop = true; - buttonsupdate(widget, h, w, bs); - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); - while(loop) { + while (loop) { doupdate(); input = getch(); switch (input) { + case KEY_ENTER: case 10: /* Enter */ output = bs.value[bs.curr]; loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case '\t': /* TAB */ bs.curr = (bs.curr + 1) % bs.nbuttons; - buttonsupdate(widget, h, w, bs); + draw_buttons(widget, bs, true); + wnoutrefresh(widget); + break; + case KEY_LEFT: + if (bs.curr > 0) { + bs.curr--; + draw_buttons(widget, bs, true); + wnoutrefresh(widget); + } + break; + case KEY_RIGHT: + if (bs.curr < (int)bs.nbuttons - 1) { + bs.curr++; + draw_buttons(widget, bs, true); + wnoutrefresh(widget); + } break; case KEY_F(1): if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; - /* No break! the terminal size can change */ + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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 (message_autosize(conf, rows, cols, &h, &w, text, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (message_autosize(conf, rows, cols, &h, &w, text, + bs) != 0) + return (BSDDIALOG_ERROR); if (message_checksize(h, w, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); + if (update_dialog(conf, shadow, widget, y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); - - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); - - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - buttonsupdate(widget, h, w, bs); - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); + getmaxyx(textpad, htextpad, unused); + textupdate(widget, textpad, htextpad, ytextpad); /* Important to fix grey lines expanding screen */ refresh(); break; case KEY_UP: - if (textrow == 0) + if (ytextpad == 0) break; - textrow--; - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); + ytextpad--; + textupdate(widget, textpad, htextpad, ytextpad); break; case KEY_DOWN: - if (textrow + h - 4 >= htextpad) + if (ytextpad + h - 4 >= htextpad) break; - textrow++; - textupdate(widget, y, x, h, w, textpad, htextpad, textrow); - break; - case KEY_LEFT: - if (bs.curr > 0) { - bs.curr--; - buttonsupdate(widget, h, w, bs); - } - break; - case KEY_RIGHT: - if (bs.curr < (int) bs.nbuttons - 1) { - bs.curr++; - buttonsupdate(widget, h, w, bs); - } + ytextpad++; + textupdate(widget, textpad, htextpad, ytextpad); break; default: - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower(bs.label[i][0])) { - output = bs.value[i]; - loop = false; + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; } } } - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; + return (output); } /* API */ int -bsddialog_msgbox(struct bsddialog_conf *conf, char* text, int rows, int cols) +bsddialog_msgbox(struct bsddialog_conf *conf, const char *text, int rows, + int cols) { struct buttons bs; - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - NULL, BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, NULL); - return (do_dialog(conf, text, rows, cols, bs)); + return (do_message(conf, text, rows, cols, bs)); } int -bsddialog_yesno(struct bsddialog_conf *conf, char* text, int rows, int cols) +bsddialog_yesno(struct bsddialog_conf *conf, const char *text, int rows, + int cols) { struct buttons bs; - get_buttons(conf, &bs, - conf->button.ok_label == NULL ? "Yes" : conf->button.ok_label, - BUTTONLABEL(extra_label), - conf->button.cancel_label == NULL ? "No" : conf->button.cancel_label, - BUTTONLABEL(help_label)); + get_buttons(conf, &bs, "Yes", "No"); - return (do_dialog(conf, text, rows, cols, bs)); -} + return (do_message(conf, text, rows, cols, bs)); +}
\ No newline at end of file diff --git a/lib/textbox.c b/lib/textbox.c index 6dae6c81343b..9e242b9fb5ab 100644 --- a/lib/textbox.c +++ b/lib/textbox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,57 +25,34 @@ * SUCH DAMAGE. */ - #include <sys/param.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include <string.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" - -/* "Text": textbox */ - -#define BUTTON_TEXTBOX "EXIT" +#include "lib_util.h" extern struct bsddialog_theme t; static void -textbox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w, - int hpad, int wpad) +textbox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, + int *w, int hpad, int wpad, struct buttons bs) { + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, 0, wpad, &bs); - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += strlen(BUTTON_TEXTBOX) + 2 /* text delims*/; - /* text size */ - *w = MAX(*w, wpad + VBORDERS); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* avoid terminal overflow */ - *w = MIN(*w, widget_max_width(conf)-1); /* again -1, fix util.c */ - } - - if (rows == BSDDIALOG_AUTOSIZE) { - *h = hpad + 4; /* HBORDERS + button border */ - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf)); - } + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, 0, hpad, true); } -static int textbox_checksize(int rows, int cols, int hpad) +static int +textbox_checksize(int rows, int cols, int hpad, struct buttons bs) { int mincols; - mincols = VBORDERS + strlen(BUTTON_TEXTBOX) + 2 /* text delims */; + mincols = VBORDERS + bs.sizebutton; if (cols < mincols) RETURN_ERROR("Few cols for the textbox"); @@ -83,18 +60,21 @@ static int textbox_checksize(int rows, int cols, int hpad) if (rows < 4 /* HBORDERS + button*/ + (hpad > 0 ? 1 : 0)) RETURN_ERROR("Few rows for the textbox"); - return 0; + return (0); } +/* API */ int -bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) +bsddialog_textbox(struct bsddialog_conf *conf, const char* file, int rows, + int cols) { - WINDOW *widget, *pad, *shadow; - int i, input, y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows; - char buf[BUFSIZ], *exitbutt; - FILE *fp; bool loop; - int output; + int i, output, input; + int y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows; + char buf[BUFSIZ]; + FILE *fp; + struct buttons bs; + WINDOW *shadow, *widget, *pad; if ((fp = fopen(file, "r")) == NULL) RETURN_ERROR("Cannot open file"); @@ -104,7 +84,7 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) pad = newpad(hpad, wpad); wbkgd(pad, t.dialog.color); i = 0; - while(fgets(buf, BUFSIZ, fp) != NULL) { + while (fgets(buf, BUFSIZ, fp) != NULL) { if ((int) strlen(buf) > wpad) { wpad = strlen(buf); wresize(pad, hpad, wpad); @@ -118,23 +98,25 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) } fclose(fp); + bs.nbuttons = 1; + bs.label[0] = "EXIT"; + if (conf->button.ok_label != NULL) + bs.label[0] = conf->button.ok_label; + bs.value[0] = BSDDIALOG_OK; + bs.curr = 0; + bs.sizebutton = strlen(bs.label[0]) + 2; + if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad); - if (textbox_checksize(h, w, hpad) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, bs); + if (textbox_checksize(h, w, hpad, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - NULL, NULL, NULL, true) != 0) - return BSDDIALOG_ERROR; - - exitbutt = conf->button.exit_label == NULL ? BUTTON_TEXTBOX : conf->button.exit_label; - draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2, strlen(exitbutt)+2, - exitbutt, true, false); + return (BSDDIALOG_ERROR); - wrefresh(widget); + if (new_dialog(conf, &shadow, &widget, y, x, h, w, NULL, NULL, &bs, + true) != 0) + return (BSDDIALOG_ERROR); ys = y + 1; xs = x + 1; @@ -143,8 +125,10 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) ypad = xpad = 0; printrows = h-4; loop = true; - while(loop) { - prefresh(pad, ypad, xpad, ys, xs, ye, xe); + while (loop) { + wnoutrefresh(widget); + pnoutrefresh(pad, ypad, xpad, ys, xs, ye, xe); + doupdate(); input = getch(); switch(input) { case KEY_ENTER: @@ -153,8 +137,10 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case KEY_HOME: ypad = 0; @@ -169,7 +155,8 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) break; case KEY_NPAGE: ypad += printrows; - ypad = ypad + printrows > hpad ? hpad - printrows : ypad; + if (ypad + printrows > hpad) + ypad = hpad - printrows; break; case '0': xpad = 0; @@ -193,32 +180,21 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) if (conf->f1_file == NULL && conf->f1_message == NULL) break; if (f1help(conf) != 0) - return BSDDIALOG_ERROR; - /* No break! the terminal size can change */ + return (BSDDIALOG_ERROR); + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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; - textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad); - if (textbox_checksize(h, w, hpad) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad, + bs); + if (textbox_checksize(h, w, hpad, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); - - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); + return (BSDDIALOG_ERROR); ys = y + 1; xs = x + 1; @@ -227,22 +203,22 @@ bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols) ypad = xpad = 0; printrows = h - 4; - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, NULL, NULL, NULL, true) != 0) - return BSDDIALOG_ERROR; - - draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2, - strlen(exitbutt)+2, exitbutt, true, false); - - wrefresh(widget); /* for button */ + if (update_dialog(conf, shadow, widget, y, x, h, w, + NULL, NULL, &bs, true) != 0) + return (BSDDIALOG_ERROR); /* Important to fix grey lines expanding screen */ refresh(); break; + default: + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; + } } } - end_widget_withtextpad(conf, widget, h, w, pad, shadow); + end_dialog(conf, shadow, widget, pad); - return output; -} + return (output); +}
\ No newline at end of file diff --git a/lib/theme.c b/lib/theme.c index 0948501e52ff..48eed6a8e598 100644 --- a/lib/theme.c +++ b/lib/theme.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,15 +25,11 @@ * SUCH DAMAGE. */ -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" +#include "lib_util.h" #define GET_COLOR(bg, fg) (COLOR_PAIR(bg * 8 + fg +1)) @@ -42,7 +38,7 @@ struct bsddialog_theme t; static struct bsddialog_theme bsddialogtheme = { #define bgwidget COLOR_WHITE #define bgcurr COLOR_YELLOW - .terminal.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN), + .screen.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN), .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), .shadow.h = 1, @@ -55,8 +51,6 @@ static struct bsddialog_theme bsddialogtheme = { .dialog.color = GET_COLOR(COLOR_BLACK, bgwidget), .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, bgwidget), - .text.hmargin = 1, - .menu.arrowcolor = GET_COLOR(COLOR_YELLOW, bgwidget), .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget) | A_BOLD, .menu.f_desccolor = GET_COLOR(COLOR_WHITE, bgcurr), @@ -89,7 +83,7 @@ static struct bsddialog_theme bsddialogtheme = { static struct bsddialog_theme blackwhite = { #define fg COLOR_WHITE #define bk COLOR_BLACK - .terminal.color = GET_COLOR(fg, bk), + .screen.color = GET_COLOR(fg, bk), .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), .shadow.h = 1, @@ -102,8 +96,6 @@ static struct bsddialog_theme blackwhite = { .dialog.color = GET_COLOR(fg, bk), .dialog.bottomtitlecolor = GET_COLOR(fg, bk), - .text.hmargin = 1, - .menu.arrowcolor = GET_COLOR(fg, bk), .menu.selectorcolor = GET_COLOR(fg, bk), .menu.f_desccolor = GET_COLOR(fg, bk) | A_REVERSE, @@ -134,7 +126,7 @@ static struct bsddialog_theme blackwhite = { }; static struct bsddialog_theme dialogtheme = { - .terminal.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD, + .screen.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD, .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK), .shadow.h = 1, @@ -147,18 +139,16 @@ static struct bsddialog_theme dialogtheme = { .dialog.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE), .dialog.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD, - .text.hmargin = 1, - .menu.arrowcolor = GET_COLOR(COLOR_GREEN, COLOR_WHITE), - .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget) | A_BOLD, - .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, - .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD, - .menu.f_namecolor = GET_COLOR(COLOR_YELLOW, COLOR_BLUE) | A_BOLD, - .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD, + .menu.selectorcolor = GET_COLOR(COLOR_BLACK, bgwidget), + .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE), + .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE), + .menu.f_namecolor = GET_COLOR(COLOR_YELLOW, COLOR_BLUE), + .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE), .menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), .menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), - .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE) | A_BOLD, - .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE) | A_BOLD, + .menu.f_shortcutcolor = GET_COLOR(COLOR_RED, COLOR_BLUE), + .menu.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE), .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD, .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD, @@ -181,11 +171,12 @@ static struct bsddialog_theme dialogtheme = { static void set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src) { + dst->screen.color = src->screen.color; + dst->shadow.color = src->shadow.color; dst->shadow.h = src->shadow.h; dst->shadow.w = src->shadow.w; - dst->terminal.color = src->terminal.color; dst->dialog.delimtitle = src->dialog.delimtitle; dst->dialog.titlecolor = src->dialog.titlecolor; dst->dialog.lineraisecolor = src->dialog.lineraisecolor; @@ -193,8 +184,6 @@ set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src) dst->dialog.color = src->dialog.color; dst->dialog.bottomtitlecolor = src->dialog.bottomtitlecolor; - dst->text.hmargin = src->text.hmargin; - dst->menu.arrowcolor = src->menu.arrowcolor; dst->menu.selectorcolor = src->menu.selectorcolor; dst->menu.f_desccolor = src->menu.f_desccolor; @@ -223,7 +212,7 @@ set_theme(struct bsddialog_theme *dst, struct bsddialog_theme *src) dst->button.f_shortcutcolor = src->button.f_shortcutcolor; dst->button.shortcutcolor = src->button.shortcutcolor; - bkgd(dst->terminal.color); + bkgd(dst->screen.color); refresh(); } @@ -258,6 +247,9 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme) if (newtheme == BSDDIALOG_THEME_DEFAULT) { bsddialog_set_theme(&dialogtheme); t.dialog.lineraisecolor = t.dialog.linelowercolor; + t.dialog.delimtitle = true; + t.button.leftch = '['; + t.button.rightch = ']'; } else if (newtheme == BSDDIALOG_THEME_BSDDIALOG) bsddialog_set_theme(&bsddialogtheme); @@ -285,4 +277,4 @@ bsddialog_color(enum bsddialog_color foreground, cursesflags |= A_UNDERLINE; return (GET_COLOR(foreground, background) | cursesflags); -} +}
\ No newline at end of file diff --git a/lib/timebox.c b/lib/timebox.c index 04e058448149..db1d4377d007 100644 --- a/lib/timebox.c +++ b/lib/timebox.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 Alfonso Sabato Siciliano + * Copyright (c) 2021-2022 Alfonso Sabato Siciliano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,66 +28,41 @@ #include <sys/param.h> #include <ctype.h> -#ifdef PORTNCURSES -#include <ncurses/ncurses.h> -#else -#include <ncurses.h> -#endif +#include <curses.h> #include <string.h> #include "bsddialog.h" -#include "lib_util.h" #include "bsddialog_theme.h" +#include "lib_util.h" -#define MINWDATE 25 /* 23 wins + 2 VBORDERS */ -#define MINWTIME 16 /*14 wins + 2 VBORDERS */ -#define MINHEIGHT 8 /* 2 for text */ - -/* "Time": timebox - datebox */ +#define MINWDATE 23 /* 3 windows and their borders */ +#define MINWTIME 14 /* 3 windows and their borders */ extern struct bsddialog_theme t; static int datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, - int *w, int minw, char *text, struct buttons bs) + int *w, int minw, const char *text, struct buttons bs) { - int maxword, maxline, nlines, line; - - if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) - return BSDDIALOG_ERROR; - - if (cols == BSDDIALOG_AUTOSIZE) { - *w = VBORDERS; - /* buttons size */ - *w += bs.nbuttons * bs.sizebutton; - *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; - /* text size */ - line = maxline + VBORDERS + t.text.hmargin * 2; - line = MAX(line, (int) (maxword + VBORDERS + t.text.hmargin * 2)); - *w = MAX(*w, line); - /* date windows */ - *w = MAX(*w, minw); - /* conf.auto_minwidth */ - *w = MAX(*w, (int)conf->auto_minwidth); - /* avoid terminal overflow */ - *w = MIN(*w, widget_max_width(conf) -1); - } + int htext, wtext; - if (rows == BSDDIALOG_AUTOSIZE) { - *h = MINHEIGHT; - if (maxword > 0) - *h += MAX(nlines, (int)(*w / GET_ASPECT_RATIO(conf))); - /* conf.auto_minheight */ - *h = MAX(*h, (int)conf->auto_minheight); - /* avoid terminal overflow */ - *h = MIN(*h, widget_max_height(conf) -1); + if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) { + if (text_size(conf, rows, cols, text, &bs, 3, minw, &htext, + &wtext) != 0) + return (BSDDIALOG_ERROR); } - return 0; + if (cols == BSDDIALOG_AUTOSIZE) + *w = widget_min_width(conf, htext,minw, &bs); + + if (rows == BSDDIALOG_AUTOSIZE) + *h = widget_min_height(conf, htext, 3 /* windows */, true); + + return (0); } static int -datetime_checksize(int rows, int cols, char *text, int minw, struct buttons bs) +datetime_checksize(int rows, int cols, int minw, struct buttons bs) { int mincols; @@ -99,19 +74,20 @@ datetime_checksize(int rows, int cols, char *text, int minw, struct buttons bs) if (cols < mincols) RETURN_ERROR("Few cols for this timebox/datebox"); - if (rows < MINHEIGHT + (strlen(text) > 0 ? 1 : 0)) - RETURN_ERROR("Few rows for this timebox/datebox"); + if (rows < 7) /* 2 button + 2 borders + 3 windows */ + RETURN_ERROR("Few rows for this timebox/datebox, at least 7"); - return 0; + return (0); } -int bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int *hh, unsigned int *mm, unsigned int *ss) +int +bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows, + int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss) { + bool loop; + int i, input, output, y, x, h, w, sel; WINDOW *widget, *textpad, *shadow; - int i, input, output, y, x, h, w, sel, htextpad; struct buttons bs; - bool loop; struct myclockstruct { unsigned int max; unsigned int value; @@ -132,41 +108,38 @@ int bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int col c[i].value = c[i].max; } - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, bs) != 0) - return BSDDIALOG_ERROR; - if (datetime_checksize(h, w, text, MINWTIME, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, + bs) != 0) + return (BSDDIALOG_ERROR); + if (datetime_checksize(h, w, MINWTIME, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - draw_buttons(widget, h-2, w, bs, true); + return (BSDDIALOG_ERROR); - wrefresh(widget); + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); - prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); + pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); + doupdate(); - c[0].win = new_boxed_window(conf, y + h - 6, x + w/2 - 7, 3, 4, LOWERED); + c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 7, 3, 4, LOWERED); mvwaddch(widget, h - 5, w/2 - 3, ':'); - c[1].win = new_boxed_window(conf, y + h - 6, x + w/2 - 2, 3, 4, LOWERED); + c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 2, 3, 4, LOWERED); mvwaddch(widget, h - 5, w/2 + 2, ':'); - c[2].win = new_boxed_window(conf, y + h - 6, x + w/2 + 3, 3, 4, LOWERED); + c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 3, 3, 4, LOWERED); wrefresh(widget); sel = 0; curs_set(2); loop = true; - while(loop) { - for (i=0; i<3; i++) { + while (loop) { + for (i = 0; i < 3; i++) { mvwprintw(c[i].win, 1, 1, "%2d", c[i].value); wrefresh(c[i].win); } @@ -186,79 +159,61 @@ int bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int col loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case '\t': /* TAB */ - sel = (sel + 1) % 3; + bs.curr = (bs.curr + 1) % bs.nbuttons; + draw_buttons(widget, bs, true); + wrefresh(widget); break; case KEY_LEFT: - if (bs.curr > 0) { - bs.curr--; - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); - } + sel = sel == 0 ? 2 : (sel - 1); break; case KEY_RIGHT: - if (bs.curr < (int) bs.nbuttons - 1) { - bs.curr++; - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); - } + sel = (sel + 1) % 3; break; case KEY_UP: - c[sel].value = c[sel].value < c[sel].max ? c[sel].value + 1 : 0; + c[sel].value = c[sel].value < c[sel].max ? + c[sel].value + 1 : 0; break; case KEY_DOWN: - c[sel].value = c[sel].value > 0 ? c[sel].value - 1 : c[sel].max; + c[sel].value = c[sel].value > 0 ? + c[sel].value - 1 : c[sel].max; break; case KEY_F(1): if (conf->f1_file == NULL && conf->f1_message == NULL) break; curs_set(0); if (f1help(conf) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); curs_set(2); - /* No break! the terminal size can change */ + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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 (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, bs) != 0) - return BSDDIALOG_ERROR; - if (datetime_checksize(h, w, text, MINWTIME, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (datetime_autosize(conf, rows, cols, &h, &w, + MINWTIME, text, bs) != 0) + return (BSDDIALOG_ERROR); + if (datetime_checksize(h, w, MINWTIME, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); + return (BSDDIALOG_ERROR); - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); + if (update_dialog(conf, shadow, widget, y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); + doupdate(); - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - mvwaddch(widget, h - 5, w/2 - 3, ':'); mvwaddch(widget, h - 5, w/2 + 2, ':'); - - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); @@ -282,31 +237,30 @@ int bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int col refresh(); break; default: - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower((bs.label[i])[0])) { - output = bs.value[i]; - loop = false; + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; } } } curs_set(0); - for (i=0; i<3; i++) + for (i = 0; i < 3; i++) delwin(c[i].win); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; + return (output); } int -bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, - unsigned int *yy, unsigned int *mm, unsigned int *dd) +bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows, + int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd) { + bool loop; + int i, input, output, y, x, h, w, sel; WINDOW *widget, *textpad, *shadow; - int i, input, output, y, x, h, w, sel, htextpad; struct buttons bs; - bool loop; struct calendar { int max; int value; @@ -348,44 +302,41 @@ bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, if (c[2].value > c[2].max) c[2].value = c[2].max; - get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), - BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); + get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL); if (set_widget_size(conf, rows, cols, &h, &w) != 0) - return BSDDIALOG_ERROR; - if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, bs) != 0) - return BSDDIALOG_ERROR; - if (datetime_checksize(h, w, text, MINWDATE, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, + bs) != 0) + return (BSDDIALOG_ERROR); + if (datetime_checksize(h, w, MINWDATE, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; - - if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, - &textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - - draw_buttons(widget, h-2, w, bs, true); + return (BSDDIALOG_ERROR); - wrefresh(widget); + if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs, + true) != 0) + return (BSDDIALOG_ERROR); - prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); + pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); + doupdate(); - c[0].win = new_boxed_window(conf, y + h - 6, x + w/2 - 11, 3, 6, LOWERED); + c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 11, 3, 6, LOWERED); mvwaddch(widget, h - 5, w/2 - 5, '/'); - c[1].win = new_boxed_window(conf, y + h - 6, x + w/2 - 4, 3, 11, LOWERED); + c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 4, 3, 11, LOWERED); mvwaddch(widget, h - 5, w/2 + 7, '/'); - c[2].win = new_boxed_window(conf, y + h - 6, x + w/2 + 8, 3, 4, LOWERED); - + c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 8, 3, 4, LOWERED); + wrefresh(widget); sel = 2; curs_set(2); loop = true; - while(loop) { + while (loop) { mvwprintw(c[0].win, 1, 1, "%4d", c[0].value); mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name); mvwprintw(c[2].win, 1, 1, "%2d", c[2].value); - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) { wrefresh(c[i].win); } wmove(c[sel].win, 1, c[sel].x); @@ -404,28 +355,25 @@ bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, loop = false; break; case 27: /* Esc */ - output = BSDDIALOG_ESC; - loop = false; + if (conf->key.enable_esc) { + output = BSDDIALOG_ESC; + loop = false; + } break; case '\t': /* TAB */ - sel = (sel + 1) % 3; + bs.curr = (bs.curr + 1) % bs.nbuttons; + draw_buttons(widget, bs, true); + wrefresh(widget); break; case KEY_LEFT: - if (bs.curr > 0) { - bs.curr--; - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); - } + sel = sel == 0 ? 2 : (sel - 1); break; case KEY_RIGHT: - if (bs.curr < (int) bs.nbuttons - 1) { - bs.curr++; - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); - } + sel = (sel + 1) % 3; break; case KEY_UP: - c[sel].value = c[sel].value > 1 ? c[sel].value - 1 : c[sel].max ; + c[sel].value = c[sel].value > 1 ? + c[sel].value - 1 : c[sel].max ; /* if mount change */ c[2].max = m[c[1].value -1].days; /* if year change */ @@ -436,7 +384,8 @@ bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, c[2].value = c[2].max; break; case KEY_DOWN: - c[sel].value = c[sel].value < c[sel].max ? c[sel].value + 1 : 1; + c[sel].value = c[sel].value < c[sel].max ? + c[sel].value + 1 : 1; /* if mount change */ c[2].max = m[c[1].value -1].days; /* if year change */ @@ -451,48 +400,31 @@ bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, break; curs_set(0); if (f1help(conf) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); curs_set(2); - /* No break! the terminal size can change */ + /* No break, screen size can change */ case KEY_RESIZE: - hide_widget(y, x, h, w,conf->shadow); - - /* - * Unnecessary, but, when the columns decrease the - * following "refresh" seem not work - */ + /* 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 (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, bs) != 0) - return BSDDIALOG_ERROR; - if (datetime_checksize(h, w, text, MINWDATE, bs) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); + if (datetime_autosize(conf, rows, cols, &h, &w, + MINWDATE, text, bs) != 0) + return (BSDDIALOG_ERROR); + if (datetime_checksize(h, w, MINWDATE, bs) != 0) + return (BSDDIALOG_ERROR); if (set_widget_position(conf, &y, &x, h, w) != 0) - return BSDDIALOG_ERROR; + return (BSDDIALOG_ERROR); - wclear(shadow); - mvwin(shadow, y + t.shadow.h, x + t.shadow.w); - wresize(shadow, h, w); + if (update_dialog(conf, shadow, widget, y, x, h, w, + textpad, text, &bs, true) != 0) + return (BSDDIALOG_ERROR); + doupdate(); - wclear(widget); - mvwin(widget, y, x); - wresize(widget, h, w); - - htextpad = 1; - wclear(textpad); - wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); - - if(update_widget_withtextpad(conf, shadow, widget, h, w, - RAISED, textpad, &htextpad, text, true) != 0) - return BSDDIALOG_ERROR; - mvwaddch(widget, h - 5, w/2 - 5, '/'); mvwaddch(widget, h - 5, w/2 + 7, '/'); - - draw_buttons(widget, h-2, w, bs, true); - wrefresh(widget); prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); @@ -516,19 +448,18 @@ bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, refresh(); break; default: - for (i = 0; i < (int) bs.nbuttons; i++) - if (tolower(input) == tolower((bs.label[i])[0])) { - output = bs.value[i]; - loop = false; + if (shortcut_buttons(input, &bs)) { + output = bs.value[bs.curr]; + loop = false; } } } curs_set(0); - for (i=0; i<3; i++) + for (i = 0; i < 3; i++) delwin(c[i].win); - end_widget_withtextpad(conf, widget, h, w, textpad, shadow); + end_dialog(conf, shadow, widget, textpad); - return output; -} + return (output); +}
\ No newline at end of file |